// artisan.js - Copyright (c) 2011 Daniel Knell
!function(context) {
    "use strict";
    var _artisan = context.artisan,
        artisan = context.artisan = {};

    // http://javascript.crockford.com/prototypal.html
    Object.create = Object.create || function (proto) {
        function F() {}
        F.prototype = proto;
        return new F();
    };

    artisan.extend = function() {
        var args = arguments,
            obj = args[0],
            length = args.length,
            key,
            i = 1,
            arg;

        if (1 === length) {
            return artisan.extend(artisan, obj);
        }

        for (; i < length; ++i) {
            arg = args[i];
            for (key in arg) {
                if (arg.hasOwnProperty(key)) {
                    obj[key] = arg[key];
                }
            }
        }

        return obj;
    };

    artisan.extend({
        version: "0.0.1",
        bind: function(fn, obj) {
            var args = [].slice.call(arguments, 2);

            return function() {
                return fn.apply(obj, args.concat(arguments));
            };
        },
        create: function(proto, props) {
            var obj = Object.create(proto);

            return (props === undefined) ? obj : artisan.extend(obj, props);
        },
        filter: function(obj, fn, context) {
            var length = obj.length,
                result = [],
                i = 0;
                
            fn = fn || function(obj) { return !!obj; }

            if (length | 0 === length) {
                for (; i < length; ++i) {
                    if (fn.call(context, obj[i], i, obj)) {
                        result.push(obj[i]);
                    }
                }
            }
            
            return result;
        },
        forEach: function(obj, fn, context) {
            var length = obj.length,
                key = 0;

            if (length | 0 === length) {
                for (; key < length; ++key) {
                    fn.call(context, obj[key], key, obj);
                }
            }
            else {
                for (key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        fn.call(context, obj[key], key, obj);
                    }
                }
            }
            return obj;
        },
        map: function(obj, fn, context) {
            var length = obj.length,
                result = [],
                i = 0;

            if (length | 0 === length) {
                for (; i < length; ++i) {
                    result.push(fn.call(context, obj[i], i, obj));
                }
            }
            
            return result;
        },
        noConflict: function() {
            context.artisan = _artisan;
            return artisan;
        },
        trim: function(string) {
            return (typeof string.trim === "function") ? 
                        string.trim() : string.replace(/(^\s*|\s*$)/g, '');
        },
        wrap: function(fn, wrapper) {
            return function() {
                return wrapper.apply(this, [artisan.bind(fn, this)].concat(arguments));
            };
        }
    });
}(this);
// artisan.js - Copyright (c) 2011 Daniel Knell
!function(artisan, navigator, parseFloat) {
    "use strict";
    var INDEX_OF = "indexOf",
        userAgent = navigator.userAgent.toLowerCase(),
        vendor = (navigator.vendor || "").toLowerCase(),
        browser = artisan.browser = {
            chrome:  userAgent[INDEX_OF]("chrome")  != -1,
            firefox: userAgent[INDEX_OF]("firefox") != -1,
            msie:    userAgent[INDEX_OF]("msie")    != -1,
            opera:   !!window.opera,
            safari:  vendor[INDEX_OF]("apple")  != -1,
            webkit:  userAgent[INDEX_OF]("webkit")  != -1,
            version: null,
            mobile:  /palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|webos|amoi|novarra|cdm|alcatel|pocket|iphone|mobileexplorer|mobile/.test(userAgent)
        };

    browser.gecko = browser.firefox;

    if (browser.chrome) {
        browser.version = parseFloat(userAgent.match(/chrome\/(\d+(\.\d+)?)/i)[1]);
    }

    if (browser.msie) {
        browser.version = parseFloat(userAgent.match(/msie (\d+(\.\d+)?);/i)[1]);
    }

    if (browser.safari || browser.opera) {
        browser.version = parseFloat(userAgent.match(/version\/(\d+(\.\d+)?)/i)[1]);
    }

    if (browser.firefox) {
        browser.version = parseFloat(userAgent.match(/firefox\/(\d+(\.\d+)?)/i)[1]);
    }
}(artisan, navigator, parseFloat);
// artisan.js - Copyright (c) 2011 Daniel Knell
!function(artisan, document, window, undefined) {
    "use strict";
    var documentElement = document.documentElement,
        BOOLEAN_ATTRIBUTES = /^(async|autofocus|autoplay|checked|controls|default|defer|disabled|formnovalidate|hidden|ismap|loop|multiple|novalidate|open|pubdate|readonly|required|reversed|scoped|seamless|selected)$/i,
        TEXT_CONTENT = "textContent" in documentElement ? "textContent" : "innerText",
        EVENTS = "__events__",
        slice = [].slice,
        gid = 0,
        storage = {};

    function toElements(html) {
        var parent = document.createElement("div"),
            result = [],
            el;
        
        if (html && html.nodeName && html.nodeType == 1) {
            return [html.cloneNode(true)];
        }
        
        parent.innerHTML = html;
        
        el = parent.firstChild;
        
        do {
            if (el && el.nodeName && el.nodeType == 1) {
                result.push(el);
            }
        }
        while(el = el.nextSibling);
        
        return result;
    }

    function getElementsByClassName(el, className) {
        if (el.getElementsByClassName) {
            return el.getElementsByClassName(className);
        }
        else if (el.getElementsByTagName) {
            var elements = el.all ? el.all : el.getElementsByTagName("*"),
                regexp = new RegExp('(^|\\s)' + className + '(\\s|$)'),
                index = elements.length,
                result = [];
            
            while (index--) {
                if (regexp.test(elements[index].className)) {
                    result.unshift(elements[index]);
                }
            }
            
            return result;
        }
    }

    function getStorage(element) {
        var id = 0;

        if (element !== window) {
            id = element.__artisan__ = element.__artisan__ || ++gid;
        }

        storage[id] = storage[id] || {};

        return storage[id];
    }

    function subscribe(element, type, fn) {
        var storage = getStorage(element),
            listeners = storage[EVENTS] = storage[EVENTS] || {},
            listener;

        listeners = listeners[type] = listeners[type] || [];

        for (listener in listeners) {
            if (listener.fn === fn) {
                return;
            }
        }

        listener = function(event) {
            fn.call(element, event);
        };

        listener.fn = fn;

        listeners.push(listener);

        if (element.addEventListener) {
            element.addEventListener(type, listener, false);
        }
        else {
            element.attachEvent("on" + type, listener);
        }
    }

    function unsubscribe(element, type, fn) {
        var storage = getStorage(element),
            listeners = storage[EVENTS] = storage[EVENTS] || {},
            index;

        if (!type) {
            for (index in listeners) {
                unsubscribe(element, index);
            }
            return;
        }

        listeners = listeners[type] = listeners[type] || [];

        index = listeners.length;

        while(index--) {
            if (!fn) {
                unsubscribe(element, type, listeners[index].fn);
            }
            else if (listeners[index].fn === fn) {
                if (element.removeEventListener) {
                    element.removeEventListener(type, listeners[index], false);
                }
                else {
                    element.removeEventListener("on" + type, listeners[index]);
                }
            }
            else {
                listeners.splice(index, 1);
            }
        }
    }

    artisan.extend({
        proto: {},
        _query: function(selector, context) {
            var matches,
                results;
            
            if (typeof context === 'string') {
                context = artisan._query(context, document)[0];
            }
            else {
                context = context || document;
            }

            if (!context || !selector) {
                return [];
            }
            
            if (matches = selector.match(/^#([\w+]+)$/)) {
                results = context.getElementById(matches[1]);
                return results ? [results] : [];
            }
            
            if (matches = selector.match(/^([\w+]+)$/)) {
                return context.getElementsByTagName(matches[1]);
            }
            
            if (matches = selector.match(/^\.([\w+]+)$/)) {
                return getElementsByClassName(context, matches[1]);
            }

            return [];
        },
        get: function(elements, context) {
            var results = Object.create(artisan.proto),
                index;

            if (typeof elements == 'string') {
                elements = artisan._query(elements, context);
            }

            if (!elements.length) {
                elements = [elements];
            }

            index = results.length = elements.length;

            while (index--) {
                results[index] = elements[index];
            }

            return results;
        }
    });

    artisan.extend(artisan.proto, {
        addClass: function (className) {
            var regexp = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
            return this.forEach(function (el) {
                if (!regexp.test(el.className)) {
                    el.className = artisan.trim(el.className + ' ' + className);
                }
            }, this);
        },
        after: function(html) {
            return this.forEach(function (el) {
                artisan.forEach(toElements(html), function(newEl) {
                    el.parentNode.insertBefore(newEl, el.nextSibling);
                });
            }, this);
        },
        append: function(html) {
            return this.forEach(function (el) {
                artisan.forEach(toElements(html), function(newEl) {
                    el.appendChild(newEl);
                });
            }, this);
        },
        attr: function(key, value) {
            var el = this[0],
                k;

            if (typeof key === "object") {
                for (k in key) {
                    this.set(k, key[k]);
                }
                return this;
            }
            
            if (value === undefined) {
                if (BOOLEAN_ATTRIBUTES.test(key)) {
                    return el.hasAttribute(key);
                }
                else {
                    return el.getAttribute(key);
                }
            }

            return this.forEach(function(el) {
                if (BOOLEAN_ATTRIBUTES.test(key)) {
                    value = value ? key : null;
                }
                
                if (value === null) {
                    el.removeAttribute(key);
                }
                else {
                    el.setAttribute(key, value);
                }
            });
        },
        before: function(html) {
            return this.forEach(function (el) {
                artisan.forEach(toElements(html), function(newEl) {
                    el.parentNode.insertBefore(newEl, el);
                });
            }, this);
        },
        css: function(style, value) {
            var el = this[0],
                styles,
                key;
            
            if (typeof style === "object") {
                for (key in style) {
                    this.css(key, style[key]);
                }
                return this;
            }

            if (style === "float") {
                style = "styleFloat" in documentElement.style ? "styleFloat" : "cssFloat";
            }
    
            style = style.replace(/-+(.)?/g, function(match, chr) {
                return chr ? chr.toUpperCase() : '';
            });
            
            if (value === undefined) {
                value = el.style[key];

                if (!value && window.getComputedStyle) {
                    styles = window.getComputedStyle(el, null);
                    value = styles ? styles[key] : null;
                }

                if (!value && el.currentStyle) {
                    value = el.currentStyle[key];
                }

                return value === 'auto' ? null : value;
            }
            
            return this.forEach(function(el) {
                el.style[style] = value;
            }, this);
        },
        data: function(key, value) {
            var storage = getStorage(this[0]);
            
            if (key === undefined) {
                return storage;
            }
            else if (value === undefined) {
                return storage[key] || null;
            }
            else {
                return this.forEach(function(el) {
                    storage[key] = value;
                });
            }
        },
        empty: function() {
            return this.forEach(function (el) {
                el.innerHTML = "";
            }, this);
        },
        filter: function(fn, context) {
            return artisan.get(artisan.filter(this, fn, context));
        },
        first: function() {
            return artisan.get(this[0]);
        },
        forEach: function(fn, context) {
            return artisan.forEach(this, fn, context);
        },
        hasClass: function (className) {
            var regexp = new RegExp("(^|\\s+)" + className + "(\\s+|$)"),
                el = this[0];
            
            return regexp.test(el.className);
        },
        hide: function (elements) {
            return this.css("display", "none");
        },
        html: function(value) {
            if (value === undefined) {
                return this[0].innerHTML;
            }
            
            return this.forEach(function(el) {
                el.innerHTML = value;
            });
        },
        last: function() {
            return artisan.get(this[this.length - 1]);
        },
        map: function(fn, context) {
            return artisan.get(artisan.map(this, fn, context));
        },
        next: function() {
            return this.map(function (el) {
                do {
                    el = el.nextSibling;
                }
                while(el && el.nodeType !== 1);
                
                return el;
            }, this).filter();
        },
        prepend: function(html) {
            return this.forEach(function (el) {
                artisan.forEach(toElements(html), function(newEl) {
                    el.insertBefore(newEl, el.firstChild);
                });
            }, this);
        },
        previous: function() {
            return this.map(function (el) {
                do {
                    el = el.previousSibling;
                }
                while(el && el.nodeType !== 1);

                return el;
            }, this).filter();
        },    
        remove: function () {
            return this.forEach(function (el) {
                el.parentNode.removeChild(el);
            }, this);
        },
        removeClass: function (className) {
            var regexp = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
            return this.forEach(function (el) {
                el.className = artisan.trim(el.className.replace(regexp, ' '));
            }, this);
        },
        show: function () {
            return this.css("display", "");
        },
        subscribe: function(type, fn) {
            var key;
            
            if (typeof type === "object") {
                for (key in type) {
                    this.subscribe(key, type[key]);
                }
                return this;
            }
            
            return this.forEach(function(el) {
                subscribe(el, type, fn);
            }, this);
        },
        text: function(value) {
            if (value === undefined) {
                return this[0][TEXT_CONTENT];
            }
            
            return this.forEach(function(el) {
                el[TEXT_CONTENT] = value;
            });
        },
        toggleClass: function (className) {
            var regexp = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
            return this.forEach(function (el) {
                if (!regexp.test(el.className)) {
                    el.className = artisan.trim(el.className + ' ' + className);
                } else {
                    el.className = artisan.trim(el.className.replace(regexp, ' '));
                }
            }, this);
        },
        unsubscribe: function(type, fn) {
            return this.forEach(function(el) {
                unsubscribe(el, type,  fn);
            }, this);
        },
        val: function (value) {
            var el = this[0];
            if (value === undefined) {
                return el.value
            }
            return this.forEach(function(el) {
                el.value = value;
            });
        }
    });
}(artisan, document, window);
!function(artisan) {
    var foot = artisan.get("#foot"),
        timer;
    
    if (artisan.browser.mobile) {
        artisan.get("head").append("<style>.foot { display: none; } .icon { background-position-y: -100px;}</style>");
        return;
    }
    
    artisan.get(".icon").subscribe({
        mouseover: function(e) {
            var node = artisan.get(this);
            clearTimeout(timer);
            foot.html("<p>" + node.html() + "</p>")
                .css("background-color", node.attr("data-color"));
        },
        mouseout: function(e) {
            timer = setTimeout(function() {
                foot.html("<p></p>")
                    .css("background-color", "#CCCCCC");
            }, 100);
        }
    });
}(artisan);
