SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Wizard
    Join Date
    Oct 2005
    Location
    London
    Posts
    1,678
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Stylable select fields using javascript

    Hi,

    I had a design come through that featured custom select inputs and as well all know they're not stylable...so I thought i'd have a go at making this work using javascript...i hope it's of interest to someone. Heres a text page to look at:

    http://play.boudaki.com/stylableselects/

    Code JavaScript:
     
    /**
    * stylableSelects v1
     * stylableSelects is (c) 2009 James Filtness and is released under the MIT *License:
     * [url]http://www.opensource.org/licenses/mit-license.php[/url]
    **/
     
    var stylableSelect = {
     
        selectedText : '',
     
        init : function(imagePath,imageHeight) {
            var im = new Image();
            im.src =  "" + imagePath + "";
            var bo = document.getElementsByTagName('body')[0];
            bo.appendChild(im);
            var wi = this.getStyle(im,'width');
            var he = this.getStyle(im,'height');
            im.style.display ='none';     
            var browser = navigator.userAgent;
            if(browser.indexOf('MSIE 6.0') == -1 && browser.indexOf('Apple') == -1) {
                var selects = document.getElementsByTagName('select');
                for(var m=0; m < selects.length; ++m) {
                    if((" " + selects[m].className + " ").toLowerCase().indexOf(" stylable ") != -1) { 
                        selects[m].className += " "+ "styled";
                        selects[m].onchange = this.selectOnchange;
    			        selects[m].id = 'select'+m;
    			        selects[m].style.opacity = '0';
    			        selects[m].style.position = 'relative';
    			        selects[m].style.zIndex = '2';
    			        selects[m].style.width = wi;
    			        selects[m].style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
    			        var width =  selects[m].offsetWidth;
    			        this.findSelectedOption(selects[m]);
    			        var ptag = document.createElement('p');
    			        ptag.style.margin = '0px';
    			        ptag.id = 'paragraph'+m;
    			        ptag.className = 'selector';
    			        this.texty = document.createTextNode(this.selectedText);
                        ptag.appendChild(this.texty);
                        var div = document.createElement('div');
                        div.style.position = 'absolute';
                        div.style.height = he; 
                        div.style.width = wi;
                        div.style.top = this.findPos(selects[m],'Top');
                        div.style.left = this.findPos(selects[m],'Left');
                        div.style.padding = '0px';
                        div.style.backgroundImage = "url('" + imagePath + "')";
                        div.style.display = 'block';
                        div.style.width = width + 'px';
                        div.appendChild(ptag);
                        var bod = document.getElementsByTagName('body')[0];
                        bod.appendChild(div);
                    } 
                }
            }
        },
     
    	selectOnchange : function() {
    	    stylableSelect.current = this;
            var t = stylableSelect.findSelectedOption(this);
            var curP = document.getElementById('paragraph'+ this.id.replace('select', ''));
    	    stylableSelect.replaceText(curP, t);
    	},
     
    	findSelectedOption : function(curr) {
    	    var options = curr.childNodes;
    	    for(var i=0; i< options.length; ++i) {
    	        if(options[i].nodeType == '1') {
    			    if(options[i].selected == true) {
    			        this.selectedText = options[i].text;
    			        return(this.selectedText);
    			    }
    		    }
            }
    	},
     
    	getStyle : function(ele,style) {
            var styleValue = 0;
            if(ele.style[style]) {
                styleValue = ele.style[style];
            } else {
                if(ele.currentStyle) {
                    styleValue = ele.currentStyle[style];
                } else if (window.getComputedStyle) {
                    styleValue = document.defaultView.getComputedStyle(ele,null).getPropertyValue(style);
                }
     
            }
            return styleValue;
        },
     
        replaceText : function(el, text) {
            if (el != null) {
                for (var i = 0; i < el.childNodes.length; i++) {
                    var childNode = el.childNodes[i];
                    el.removeChild(childNode);
                }
                var newNode = document.createTextNode(text);
                el.appendChild(newNode);
            }
        },
     
       findPos : function(obj,axis) {
           var axisLower = axis.toLowerCase();
           var st = 'cur' + axisLower;
           st = 0;
           if(obj.offsetParent) {
               while(1) {
                   st += obj['offset'+axis];
                   if(!obj.offsetParent) {
                       break;
                   }
                   obj = obj.offsetParent;
               }
           }
           else if(obj.x) {
               st += obj.x;
           }
           return st;
       }
    };

    To use all you need to do is include the js above in an external file called stylableSelects.js, include this in the head, make a call to the init function onload (or at the bottom of the page) and feed it the path to the image you want to use as the select. Your selects must also have a class of stylable otherwise the script will ignore them. like so:

    Code HTML4Strict:
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=utf-8">
            <title></title>
            <script type="text/javascript" src="stylableSelects.js"> </script> 
            <style type="text/css">
            * {margin: 0; padding: 0;}
            select {padding: 4px;}
            .selector {padding: 4px 0 0 5px;}
            </style>
     
        </head>
        <body>
            <select class="stylable">
                <option value="">Fender</option>
                <option value="">Gibson</option>
                <option value="">Ribenbacher</option>
                <option value="">Martin</option>
                <option value="">Taylor</option>
                <option value="">Ibanez</option>
            </select>
     
            <select class="stylable">
                <option value="">Fender</option>
                <option value="">Gibson</option>
                <option value="">Ribenbacher</option>
                <option value="">Martin</option>
                <option value="">Taylor</option>
                <option value="">Ibanez</option>
            </select>
       </body>
       <script type="text/javascript">
           stylableSelect.init('image.gif');
       </script>
    </html>

    Use firebug to find out whats happening...you may have noticed that i've added some css at the top to push and pull things in and out of line. Again, use firebug to find out what classes you need to target to make adjustments....it shouldn't be much.

    This script works for FF, ie7+, opera, etc. However, due to it's method it will never work in ie6 (you cannot set opacity on windowed content in ie6 - which is what i'm doing to the select) and it will currently not work in Safari...so these users just get the normal select dropdown. Look at it as progressive enhancement. I am looking at a fix for safari and will release another version when I do.

    Here's a link to the select image I have been using during testing:



    Please let me know what you think. Any problems, improvements, bugs criticisms...please post here...and please feel free to use!
    Last edited by elduderino; May 1, 2009 at 06:40.

  2. #2
    We're from teh basements.
    Join Date
    Apr 2007
    Posts
    1,205
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I didn't see a working styled SELECT at that link. I ended up with a lot more open tabs in Firefox than I care for though.

  3. #3
    SitePoint Wizard
    Join Date
    Oct 2005
    Location
    London
    Posts
    1,678
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I did say it was a link to an image and not a real example...and lots of tabs, erh?! Think that might just be a problem on your end buddy.

    Fixed my server so here's a link:

    http://play.boudaki.com/stylableselects/
    Last edited by elduderino; May 1, 2009 at 07:52.

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    the menus are functional, but not properly styled in opera

  5. #5
    We're from teh basements.
    Join Date
    Apr 2007
    Posts
    1,205
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by elduderino View Post
    I did say it was a link to an image and not a real example...and lots of tabs, erh?! Think that might just be a problem on your end buddy.

    Fixed my server so here's a link:

    http://play.boudaki.com/stylableselects/
    I saw the image.

    Firefox doesn't arbitrarily open a new tab for every link clicked. There would have to be a target attribute in every anchor tag for that to occur.

  6. #6
    Follow Me On Twitter: @djg gold trophysilver trophybronze trophy Dan Grossman's Avatar
    Join Date
    Aug 2000
    Location
    Philadephia, PA
    Posts
    20,578
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    The selects aren't styled at all in Chrome either (which probably means the same for Safari).

  7. #7
    SitePoint Wizard
    Join Date
    Oct 2005
    Location
    London
    Posts
    1,678
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by World Wide Weird View Post
    Firefox doesn't arbitrarily open a new tab for every link clicked. There would have to be a target attribute in every anchor tag for that to occur.
    I'm not sure what you're referring to. There are no anchor tags on created by the script...it's just the select. Why would you want to open links in a new window having made a selection from a select inout anyway?!

    As for the script not performing in Chrome (which I personally don't support) and safari.....this is a work in progress....i'll look in to fixes for these browsers.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •