Matt's 411

A Web Developer's Blog · Javascript, CSS, HTML and more

  • Internet Explorer localStorage polyfill using userData

    Saturday, December 15, 2012·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    I have written a localStorage polyfill for Internet Explorer 7 and older using IE's non-standard userData behavior. Below is the code required. It's also available on Github as a gist.

    Please note that there are some major differences between userData and localStorage. For example, localStorage persistence is by same-origin policy where as userData persistence is by same-origin plus directory. One workaround to this difference is to use a hidden iFrame with a consistent URL path to load and save persisted data for the parent page.

    (function(window, document) {
      "use strict";
      var userData, attr, attributes;
      
      if (!window.localStorage && (userData = document.body) && userData.addBehavior) {
        if (userData.addBehavior("#default#userdata")) {
          userData.load((attr = "localStorage"));
          attributes = userData.XMLDocument.documentElement.attributes;
          
          window.localStorage = {
            "length" : attributes.length, 
            "key" : function(idx) { return (idx >= this.length) ? null : attributes[idx].name; }, 
            "getItem" : function(key) { return userData.getAttribute(key); }, 
            "setItem" : function(key, value) {
              userData.setAttribute(key, value);
              userData.save(attr);
              this.length += ((userData.getAttribute(key) === null) ? 1 : 0);
            }, 
            "removeItem" : function(key) {
              if (userData.getAttribute(key) !== null) {
                userData.removeAttribute(key);
                userData.save(attr);
                this.length = Math.max(0, this.length - 1);
              }
            }, 
            "clear" : function() {
              while (this.length) { userData.removeAttribute(attributes[--this.length].name); }
              userData.save(attr);
            }
          };
        }
      }
    })(this, this.document);
    
  • Autocomplete with <datalist>

    Sunday, December 9, 2012·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    Introduced in HTML5 is a new element called <datalist>. This new element enables web developers to add autocompletion features to <input> text fields without having to use any Javascript. When a <datalist> element is attached to an <input> field via the "list" attribute, users typing into the text field will see prepopulated choices appear beneath the field. They can either choose one of those prepopulated choices, or type in their own. One of the best examples of this user experience today is Google Search's search field.

    Autocomplete

    Recently I've been working on a polyfill for the <datalist> element in browsers that have yet to adopt it. One of the challenges of course has been getting everything to work in IE, such as finding a workaround to IE9's poor oninput event handling. Fortunately after a couple of long nights I've gotten to what I feel is a high quality polyfill. Please feel free to check out the demo below and code / documentation on Github.

    = View Autocomplete Demo =

    Some features:

    • Cross browser compatible (Chrome, Firefox, Safari, Opera, Internet Explorer 7+)
    • Framework independent - Works with jQuery, Mootools, etc.
    • Works with HTML5's <datalist> element
    • Add and remove autocomplete suggestions on the fly
    • Accepts an array or XML as input or retrieves from DOM
    • Supports dynamic choice populating via Ajax
    • Touch friendly
    • Open source
  • Internet Explorer 9 oninput event

    Friday, December 7, 2012·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    Internet Explorer 9 is the first version of IE to support the oninput event. While it's good to see Microsoft finally adding the needed event handler, it's unfortunately quite buggy in its implementation. In this post I'll describe one of the bugs and a potential fix for it. For the other known bug, just remember to always use addEventListener when attaching an oninput event to a DOM element.

    The major bug that IE9's oninput event has is that it does not fire when characters are deleted from a text field. It only fires when characters are added. If you press the backspace key, delete key, use the cut command or the delete command from the context menu, the oninput event should fire but does not. In working on a cross browser autocomplete implementation, I found that one excellent model to look at was Google Search's autocomplete feature. It successfully tracks any input changes in IE9 including the delete command from the context menu, the trickiest one to fix.

    Internet Explorer 9

    Using a combination of IE9's oninput, onfocus, onblur and onselectionchange events, you can successfully emulate a full oninput implementation. Note, I have not tested event capturing/bubbling with this solution, nor have I fully tested this solution with a textarea element.

    A simple example: 

      <input id="myInput" type="text">
      
      <script>
        // Get the input and remember its last value:
        var myInput = document.getElementById("myInput"), 
            lastValue = myInput.value;
        
        // An oninput function to call:
        var onInput = function() {
          if (lastValue !== myInput.value) { // selectionchange fires more often than needed
            lastValue = myInput.value;
            console.log("New value: " + lastValue);
          }
        };
        
        // Called by focus/blur events:
        var onFocusChange = function(event) {
          if (event.type === "focus") {
          	document.addEventListener("selectionchange", onInput, false);
          } else {
            document.removeEventListener("selectionchange", onInput, false);
          }
        };
        
        // Add events to listen for input in IE9:
        myInput.addEventListener("input", onInput, false);
        myInput.addEventListener("focus", onFocusChange, false);
        myInput.addEventListener("blur", onFocusChange, false);
      </script>
    

    For implementing oninput in Internet Explorer 7 and 8, use the onpropertychange event.

  • Grid Updated

    Sunday, November 25, 2012·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    I've updated MooGrid with some performance tweaks and documentation. Additionally the dependence on Mootools is gone. This will hopefully clear the path for anyone using jQuery or plain old Javascript.

    = View Grid Demo =

    Grid Demo Screenshot

    For those who are new to this blog, first, welcome! Second, I'll describe what Grid is. Grid is an open source project I've been working on for some time now. It's an HTML-based table component with fixed headers, fixed footers, fixed left columns, row selection, sorting and more. It works across all major browsers and is (now) Javascript framework independent, so it will work on your website if you use jQuery, Mootools, or something else entirely. Grid's full list of features are:

    • Cross browser compatible (Chrome, Firefox, Safari, Opera, Internet Explorer 7+)
    • Framework independent - Works with jQuery, Mootools, etc.
    • Fixed header, footer, columns
    • Column resizing
    • Column sorting
    • Grid resizing
    • Row selection (singular and multi-select)
    • Accepts JSON or XML as input or retrieves from DOM
    • Tablet friendly
    • Open source

    Please see the Github project page for documentation and implementation details.

    If any issues are found please use Github instead of emailing me directly. I will try to fix bugs as soon as I can. Thanks and hope you like Grid!

  • Canvas Pie and Ring Charts with Tooltips

    Saturday, November 16, 2012·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    Here are some demos of a Canvas-based pie chart and Canvas-based ring chart. Both charts support mouse-over tooltips and can be updated with new values after initial rendering. When updated, under certain conditions, an animation will play of the charts updating themselves. To see this in action, click on the demo links below.

    Features:

    • Cross browser compatible (Internet Explorer 7+, FireFox, Chrome, Safari, Opera)
    • Framework independent - Works with jQuery, Mootools, etc.
    • Pie charts with animations and tooltips
    • 2-level Ring charts with animations and tooltips
    • Open source: GitHub project page

    Canvas Pie and Ring Charts

    = View Pie Chart Demo == View Ring Chart Demo =

  • Receive an SMS via Twilio When Your Website Goes Down

    Saturday, November 16, 2012·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    You can use Twilio as a lightweight solution to alerting yourself whenever one of your websites goes down or is unresponsive.

    While there are better solutions with automatic problem solving logic, here is a simple example of a Python method that sends an SMS alert to a website administrator's phone whenever the target website returns a non-200 server response. This method uses the Python Requests library as well as Twilio's Python API. It gets called by a Cron job every 5 minutes.

    def checkSiteStatus():
        """ Checks matts411.com's server response code and sends an SMS alert if not 200 """
        res = requests.get("http://www.matts411.com")
        if res.status_code != 200:
            # Send SMS alert to admin phone:
            twilio_account_sid = settings.TWILIO["account_sid"]
            url = "https://api.twilio.com/2010-04-01/Accounts/%s/SMS/Messages.json" % twilio_account_sid
            auth = requests.auth.HTTPBasicAuth(twilio_account_sid, settings.TWILIO["auth_token"])
            
            requests.post(url, auth=auth, data={
                "From" : settings.TWILIO["from"], 
                "To" : settings.TWILIO["to"], 
                "Body" : "Alert! Matts411.com server response code: %i" % res.status_code
            })
    
  • Comments with Disqus.com

    Wednesday, January 12, 2011·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    Comments have been added to every blog post using Disqus.com. It was very easy to add their plugin however the performance impact is not great so we'll see how it goes.

  • Disabling Spellcheck in Textarea Elements

    Saturday, December 4, 2010·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    To disable spell checking on HTML elements in newer browsers (eg. Firefox 3.6) set the attribute spellcheck="false" in the element's opening tag. Note: Some browsers (eg. Safari 5) will not show the red underline for mispelled words until you focus your cursor on a word and then remove it.

    For more detailed information refer to the W3C Specification.

  • Setting the name attribute in IE's DOM

    Thursday, May 28, 2009·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    An old problem with IE is that you can't set the name attribute on form elements in the DOM directly. Fortunately there is a workaround to this issue using IE's mergeAttributes method. By creating a temporary named element acceptable by IE's createElement method, you can merge the name attribute into the element you desire, allowing you to name or rename an element. An example demo follows.

    var setName = function(el, newName) {
      el = (typeof el === "string") ? document.getElementById(el) : el;
      el.name = newName;
      if (/*@cc_on!@*/0) { // Internet Explorer test (needs to be modified for IE8)
        el.mergeAttributes(document.createElement("<INPUT name='" + newName + "'/>"), false);
      }
    };
    

    In Mootools 1.2.1:

    var setName = function(elementId, newName) {
      var el = (!!elementId) ? $(elementId) : null;
      if (!elementId || !newName || !el) return;
      
      el.set({ "name" : newName });
      if (Browser.Engine.trident4 || Browser.Engine.trident5) {
        el.mergeAttributes(document.createElement("<INPUT name='" + newName + "'/>"), false);
      }
    };
    
  • Recent Activity

    Wednesday, April 22, 2009·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    It's been a while since I've last posted anything so I thought I would mention a couple websites I've been working on recently. Both are puzzle sites - one in Flex: www.ideabo.com (pronounced eye-d-ah-bow) and one in HTML/CSS/JS: www.razzlepuzzles.com.

    I'll probably be posting some new things I've learned shortly. Stay tuned.

  • Tips for Web Developers

    Sunday, November 30, 2008·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    The following is a list of tips and bits of knowledge I've gathered over the past year or so and thought worth sharing:

    • The key to any successful website is how well it solves a need.

      Going against big players is tough and competitive. One approach is finding (or creating) a niche need and from there growing the site until it's better able to move into the more competitive markets - that is if it's even worthwhile to do so.

    • The amount of text on your site (and more importantly keywords), may help your site get off the ground.

      This tip deals with search engine optimization, and how making your site seo friendly can help with search engine rankings. In my experience, having pages with specific keywords and/or lots of relevant text can improve traffic to your site. This is an especially useful practice if your site is new or has little marketing as it's a way to help your site list well in search engine rankings without having to accumulate numerous inbound links which normally takes a while to do.

    • Try developing your site in Firefox with the Firebug extension, and the YSlow and Hammerhead Firebug extensions.

      Although Firebug has many features, one that I find myself using the most is the Net feature. This feature gives you visual representations of how your site's javascript, html, css and image files (etc, etc) are downloaded by the browser. When coupled with Yahoo's YSlow Firebug extension and Steve Souders' Hammerhead extension, optimizing your site's page load times becomes easier, and it helps in all browsers beyond just Firefox.

    • Minimize DOM styling on page load.

      This tip applies especially to Internet Explorer. If you are setting a lot of styling (via javascript) on various DOM nodes during page load, the page will render significantly slower in many cases than if you forgo or keep the styling to a minimum. Applying display, width, or height properties on DIV's with lots of inner HTML can take upwards of 5-10 seconds (in IE at least) depending on the amount of HTML code. Worse still, the browser (again in IE at least) will wait until that styling is finished before showing the contents of the page!

    • onmousedown is ~100ms faster than onclick.

      Something to keep in mind. Use only where appropriate (not for links!).

    • Need a repeating background image and another one just for the top of the page? Set the background on both the HTML and BODY tags.

      You can set a background on both the HTML and BODY tags in CSS. One technique is to set a repeating (fixed) background image on the HTML tag and a second, top of the page only background (transparent) image on the BODY tag. I would recommend setting the background-attachment attribute on the HTML tag to fixed so that you don't get the jitter effect in some browsers when scrolling (if the background-repeat property is set to repeat).

    • Develop a useful window.onerror function if you have a lot of javascript in your site.

      If your site has a lot of javascript and numerous pages, it would probably be a good idea to have a useful onerror function to help debug during development and even while in production. The window onerror function provides three arguments: the error message, the url, and the line number. Using these three pieces of information, coupled with other useful bits of data such as the browser user agent string, the os type, perhaps the resolution, and others, you can create an onerror function that could make an ajax call to write to a log file with this useful information that you can later look at.

    • Javascript: The Good Parts.

      This is an excellent read by Douglas Crockford, creator of JSON and currently employed by Yahoo. It's short, about 120 pages, and is a nice overview of "the good parts" of javascript. It's the book I point to these days whenever someone asks me where to start learning javascript.

    • Good feeds to follow:

      A List Apart, Ajaxian, DZone, DZone: JS, TechCrunch, WebGuild. While there are numerous web development blogs out there, I find these to be consistently interesting and useful. A great way to stay up to date in this fast paced world.

    • Technologies worth checking out:

      Django and Flex. Flex I'm still taking a look at however Django I've been working with for a few months now and think it's great. It's a Python based MVC framework that has been gaining traction as of late (Google apps and the Russian search engine Yandex use it). It's rather easy to pick up, even if you don't know any Python (as was my case). Coming from a Rails background, I found it was quite easy to port some of my sites (such as this one) over.

    • Other useful things:

      For editing/development in Windows: E Text Editor (Textmate for Windows.) For tracking/analytics: Woopra. For sitemap generation: XML-Sitemaps.com.

    Just as a final note, something I haven't looked into much but will be shortly, is internationalization. There are tools out there that translate web content quickly and easily (and these days more accurately). Might be worth looking into yourself if you get a lot of foreign visitors.

  • Delaying Javascript Event Execution

    Monday, October 13, 2008·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    If you're looking to execute javascript code whenever someone finishes (or stops temporary) scrolling, moving the mouse, or resizing the page, you may find the following code segment useful.

    var onFooEndFunc = function() {
      var throttleTimer;
      return function(event) {
        throttleTimer = (!!throttleTimer) ? window.clearTimeout(throttleTimer) : null;
        throttleTimer = window.setTimeout(function() {
          
          // Your code here
          
        }, 50);
      };
    }();
    

    As an example, let's say you have an element with ID "foobar" and you want to perform some action on scroll, but only when the user stops scrolling. You can do this by creating the function above and assigning it to the element's onscroll event handler:

    document.getElementById("foobar").onscroll = onFooEndFunc;
    
  • Auto Selecting HTML Text with Javascript

    Wednesday, October 8, 2008·Share
    • Facebook
    • ·
    • Google Plus
    • ·
    • LinkedIn
    • ·
    • StumbleUpon
    • ·
    • Twitter
    ·Comments

    Here is a function that when called on a particular HTML element will auto-select all of its inner text. The function works on elements such as INPUT (text), TEXTAREA, DIV, SPAN, TD, and PRE. It is also cross browser compatible.

    var autoSelect = function(event) {
      var event = event || window.event, 
          elem = event.target || event.srcElement, 
          tag = (elem.tagName || "").toLowerCase(), 
          sel, range;
      
      if (tag === "textarea" || tag === "input") {
        try {
          elem.select();
        } catch(e) {
          // May be disabled or not selectable
        }
      } else if (window.getSelection) { // Not IE
        sel = window.getSelection();
        range = document.createRange();
        range.selectNodeContents(elem);
        sel.removeAllRanges();
        sel.addRange(range);
      } else if (document.selection) { // IE
        document.selection.empty();
        range = document.body.createTextRange();
        range.moveToElementText(elem);
        range.select();
      }
    };
    

    To attach this function to an element, you could write:

    document.getElementById("foobar").onclick = autoSelect;
    

Latest Posts

  • Internet Explorer localStorage polyfill using userData
  • Autocomplete with <datalist>
  • Internet Explorer 9 oninput event
  • Grid Updated
  • Canvas Pie and Ring Charts with Tooltips
  • Receive an SMS via Twilio When Your Website Goes Down
  • Comments with Disqus.com
  • Disabling Spellcheck in Textarea Elements
  • Setting the name attribute in IE's DOM
  • Recent Activity
  • Tips for Web Developers
  • Delaying Javascript Event Execution
  • Auto Selecting HTML Text with Javascript