diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..fa10dee --- /dev/null +++ b/.jshintrc @@ -0,0 +1,57 @@ +{ + "passfail": false, + "maxerr": 20, + "browser": true, + "node": false, + "predef": [], + "debug": false, + "devel": false, + "strict": false, + "globalstrict": false, + "asi": true, + "laxbreak": true, + "bitwise": false, + "boss": true, + "curly": true, + "eqeqeq": false, + "eqnull": false, + "evil": false, + "expr": true, + "forin": false, + "immed": true, + "latedef": false, + "loopfunc": false, + "noarg": false, + "regexp": false, + "regexdash": false, + "scripturl": false, + "shadow": false, + "supernew": false, + "undef": true, + "validthis": false, + "smarttabs": true, + "proto": false, + "onecase": false, + "nonstandard": false, + "multistr": false, + "laxcomma": false, + "lastsemic": false, + "iterator": false, + "funcscope": false, + "esnext": false, + "newcap": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "sub": false, + "trailing": false, + "indent": 2, + "white": false, + "quotmark": false, + "maxparams": 5, + "maxdepth": 4, + "maxstatements": 25, + "maxcomplexity": 6 +} diff --git a/jymin.js b/jymin.js index 005d4c5..6313bdc 100644 --- a/jymin.js +++ b/jymin.js @@ -1,9 +1,9 @@ /** - * _ _ ___ ____ ____ - * | |_ _ _ __ ___ (_)_ __ __ __/ _ \ |___ \ |___ \ - * _ | | | | | '_ ` _ \| | '_ \ \ \ / / | | | __) | __) | - * | |_| | |_| | | | | | | | | | | \ V /| |_| | / __/ _ / __/ - * \___/ \__, |_| |_| |_|_|_| |_| \_/ \___(_)_____(_)_____| + * _ _ ___ ____ _____ + * | |_ _ _ __ ___ (_)_ __ __ __/ _ \ |___ \ |___ / + * _ | | | | | '_ ` _ \| | '_ \ \ \ / / | | | __) | |_ \ + * | |_| | |_| | | | | | | | | | | \ V /| |_| | / __/ _ ___) | + * \___/ \__, |_| |_| |_|_|_| |_| \_/ \___(_)_____(_)____/ * |___/ * * http://lighter.io/jymin @@ -13,7 +13,6 @@ * * Source files: * https://github.com/zerious/jymin/blob/master/scripts/ajax.js - * https://github.com/zerious/jymin/blob/master/scripts/animation.js * https://github.com/zerious/jymin/blob/master/scripts/collections.js * https://github.com/zerious/jymin/blob/master/scripts/cookies.js * https://github.com/zerious/jymin/blob/master/scripts/dates.js @@ -30,7 +29,7 @@ */ -this.jymin = {version: '0.2.2'}; +this.jymin = {version: '0.2.3'}; /** * Empty handler. @@ -60,9 +59,11 @@ var getResponse = function ( var request; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - request = new ActiveXObject('Microsoft.XMLHTTP'); - } else { + } + else if (window.ActiveXObject) { + request = new ActiveXObject('Microsoft.XMLHTTP'); // jshint ignore:line + } + else { return false; } if (request) { @@ -79,15 +80,15 @@ var getResponse = function ( var object; if (status) { try { - // Trick Uglify into thinking there's no eval. - var e = window.eval; - e('eval.J=' + response); - object = e.J; + // Trick UglifyJS into thinking there's no eval. + var evil = window.eval; // jshint ignore:line + evil('eval.J=' + response); + object = evil.J; } catch (e) { - //+env:dev - error('Could not parse JSON: "' + response + '"'); - //-env:dev + //+env:debug,dev + error('Jymin: Could not parse JSON: "' + response + '"'); + //-env:debug,dev object = {_ERROR: '_BAD_JSON', _TEXT: response}; } } @@ -137,63 +138,6 @@ var getJson = function ( ) { return getResponse(url, body, onSuccess, onFailure, true); }; -var DEFAULT_ANIMATION_FRAME_COUNT = 40; -var DEFAULT_ANIMATION_FRAME_DELAY = 20; - -/** - * Perform an animation. - */ -var animate = function ( - element, // string|DOMElement: Element or ID of element to animate. - styleTransitions, // object: cssText values to animate through. - onFinish, // function|: Callback to execute when animation is complete. - frameCount, // integer|: Number of frames to animate through. (Default: 40) - frameDelay, // integer|: Number of milliseconds between frames. (Default: 20ms) - frameIndex // integer|: Index of the frame to start on. (Default: 0) -) { - if (element = getElement(element)) { - // Only allow one animation on an element at a time. - stopAnimation(element); - frameIndex = frameIndex || 0; - frameCount = frameCount || DEFAULT_ANIMATION_FRAME_COUNT; - frameDelay = frameDelay || DEFAULT_ANIMATION_FRAME_DELAY; - var scale = Math.atan(1.5) * 2; - var fraction = Math.atan(frameIndex / frameCount * 3 - 1.5) / scale + 0.5; - var styles = {}; - forIn(styleTransitions, function(transition, key) { - var start = transition[0]; - var end = transition[1]; - var value; - if (isNaN(start)) { - value = frameIndex ? end : start; - } - else { - value = (1 - fraction) * start + fraction * end; - } - styles[key] = value; - }); - extendStyle(element, styles); - if (frameIndex < frameCount) { - element.animation = setTimeout(function() { - animate(element, styleTransitions, onFinish, frameCount, frameDelay, frameIndex + 1); - }); - } - else if (onFinish) { - onFinish(element); - } - } -}; - -/** - * Stop an animation on a given DOM element. - */ -var stopAnimation = function ( - element // string|DOMElement: Element or ID of element to cancel the animation on. -) { - if (element = getElement(element)) { - clearTimeout(element.animation); - } -}; /** * Iterate over an array, and call a function on each item. */ @@ -201,14 +145,14 @@ var forEach = function ( array, // Array*: The array to iterate over. callback // Function*: The function to call on each item. `callback(item, index, array)` ) { - if (array) { - for (var index = 0, length = getLength(array); index < length; index++) { - var result = callback(array[index], index, array); - if (result === false) { - break; - } - } + if (array) { + for (var index = 0, length = getLength(array); index < length; index++) { + var result = callback(array[index], index, array); + if (result === false) { + break; + } } + } }; /** @@ -218,14 +162,14 @@ var forIn = function ( object, // Object*: The object to iterate over. callback // Function*: The function to call on each pair. `callback(value, key, object)` ) { - if (object) { - for (var key in object) { - var result = callback(object[key], key, object); - if (result === false) { - break; - } - } + if (object) { + for (var key in object) { + var result = callback(object[key], key, object); + if (result === false) { + break; + } } + } }; /** @@ -316,12 +260,12 @@ var merge = function ( array, // Array: The array to merge into. items // mixed+: The items to merge into the array. ) { + // TODO: Use splice instead of pushes to get better performance? + var addToFirstArray = function (item) { + array.push(item); + }; for (var i = 1, l = arguments.length; i < l; i++) { - items = arguments[i]; - // TODO: Use splice instead of push to get better performance? - forEach(items, function (item) { - array.push(item); - }); + forEach(arguments[i], addToFirstArray); } }; @@ -338,7 +282,7 @@ var pad = function ( if (isArray(array)) { var startingLength = getLength(array); if (startingLength < length) { - paddingValue = isDefined(paddingValue) ? paddingValue : ''; + paddingValue = isUndefined(paddingValue) ? '' : paddingValue; for (var index = startingLength; index < length; index++) { array.push(paddingValue); countAdded++; @@ -352,15 +296,14 @@ var pad = function ( * @return object: Cookie names and values. */ var getAllCookies = function () { - var str = document.cookie; - var decode = decodeURIComponent; var obj = {}; - var pairs = str.split(/ *; */); - var pair; - if ('' == pairs[0]) return obj; - for (var i = 0; i < pairs.length; ++i) { - pair = pairs[i].split('='); - obj[decode(pair[0])] = decode(pair[1]); + var documentCookie = trim(document.cookie); + if (documentCookie) { + var cookies = documentCookie.split(/\s*;\s*/); + forEach(cookies, function (cookie) { + var pair = cookie.split(/\s*=\s*/); + obj[unescape(pair[0])] = unescape(pair[1]); + }); } return obj; }; @@ -384,19 +327,18 @@ var setCookie = function ( options // object|: Name/value pairs for options including "maxage", "expires", "path", "domain" and "secure". ) { options = options || {}; - var encode = encodeURIComponent; - var str = encode(name) + '=' + encode(value); - if (null == value) { + var str = escape(name) + '=' + unescape(value); + if (null === value) { options.maxage = -1; } if (options.maxage) { - options.expires = new Date(+new Date + options.maxage); + options.expires = new Date(+new Date() + options.maxage); } - if (options.path) str += ';path=' + options.path; - if (options.domain) str += ';domain=' + options.domain; - if (options.expires) str += ';expires=' + options.expires.toUTCString(); - if (options.secure) str += ';secure'; - document.cookie = str; + document.cookie = str + + (options.path ? ';path=' + options.path : '') + + (options.domain ? ';domain=' + options.domain : '') + + (options.expires ? ';expires=' + options.expires.toUTCString() : '') + + (options.secure ? ';secure' : ''); }; /** @@ -464,8 +406,9 @@ var getElementsByTagAndClass = function ( var tagName = (tagAndClass[0] || '*').toUpperCase(); var className = tagAndClass[1]; var anyTag = (tagName == '*'); + var elements; if (className) { - var elements = []; + elements = []; if (parentElement.getElementsByClassName) { forEach(parentElement.getElementsByClassName(className), function(element) { if (anyTag || (element.tagName == tagName)) { @@ -503,8 +446,8 @@ var getParent = function ( }; /** -* Create a DOM element. -*/ + * Create a DOM element. + */ var createElement = function ( tagIdentifier ) { @@ -519,7 +462,7 @@ var createElement = function ( var tagName = tagAndId[0] || 'div'; var id = tagAndId[1]; var attributes = tagAndAttributes[1]; - var cachedElement = addElement[tagName] || (addElement[tagName] = document.createElement(tagName)); + var cachedElement = createElement[tagName] || (createElement[tagName] = document.createElement(tagName)); var element = cachedElement.cloneNode(true); if (id) { element.id = id; @@ -605,13 +548,13 @@ var getChildren = function ( var getIndex = function ( element ) { - if (element = getElement(element)) { - var index = 0; - while (element = element.previousSibling) { - ++index; - } - return index; + element = getElement(element); + var index = -1; + while (element) { + ++index; + element = element.previousSibling; } + return index; }; /** @@ -635,6 +578,31 @@ var insertElement = function ( } }; +/** + * Insert a DOM element after another. + */ +var insertBefore = function ( + element, + childElement +) { + element = getElement(element); + var parentElement = getParent(element); + addElement(parentElement, childElement, element); +}; + +/** + * Insert a DOM element after another. + */ +var insertAfter = function ( + element, + childElement +) { + element = getElement(element); + var parentElement = getParent(element); + var beforeElement = getNextSibling(element); + addElement(parentElement, childElement, beforeElement); +}; + /** * Remove a DOM element from its parent. */ @@ -642,7 +610,8 @@ var removeElement = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Remove the element from its parent, provided that its parent still exists. var parentElement = getParent(element); if (parentElement) { @@ -667,7 +636,8 @@ var getHtml = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.innerHTML; } }; @@ -680,7 +650,8 @@ var setHtml = function ( html ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Set the element's innerHTML. element.innerHTML = html; } @@ -693,7 +664,8 @@ var getText = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.innerText; } }; @@ -706,7 +678,8 @@ var setText = function ( text ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Set the element's innerText. element.innerHTML = text; } @@ -719,7 +692,8 @@ var getClass = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.className; } }; @@ -732,7 +706,8 @@ var setClass = function ( className ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Set the element's innerText. element.className = className; } @@ -745,7 +720,8 @@ var getFirstChild = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.firstChild; } }; @@ -757,7 +733,8 @@ var getPreviousSibling = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.previousSibling; } }; @@ -769,7 +746,8 @@ var getNextSibling = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.nextSibling; } }; @@ -792,7 +770,8 @@ var addClass = function ( element, className ) { - if (element = getElement(element)) { + element = getElement(element); + if (element) { element.className += ' ' + className; } }; @@ -804,7 +783,8 @@ var removeClass = function ( element, className ) { - if (element = getElement(element)) { + element = getElement(element); + if (element) { var tokens = getClass(element).split(/\s/); var ok = []; forEach(tokens, function (token) { @@ -865,16 +845,17 @@ var insertScript = function ( }; /** - * Run a callback on each element matching a given selector. + * Finds elements matching a selector, and return or run a callback on them. */ var all = function ( parentElement, selector, callback ) { + // TODO: Better argument collapsing. if (!selector || isFunction(selector)) { callback = selector; - selector = parentElement + selector = parentElement; parentElement = document; } var elements; @@ -910,6 +891,17 @@ var all = function ( } return elements; }; + +/** + * Finds elements matching a selector, and return or run a callback on them. + */ +var one = function ( + parentElement, + selector, + callback +) { + return all(parentElement, selector, callback)[0]; +}; /** * Bind a handler to listen for a particular event on an element. */ @@ -930,7 +922,8 @@ var bind = function ( } // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Invoke the event handler with the event information and the target element. var callback = function(event) { @@ -944,7 +937,7 @@ var bind = function ( } var relatedTarget = event.relatedTarget || event.toElement; if (eventName == 'mouseout') { - while (relatedTarget = getParent(relatedTarget)) { + while (relatedTarget = getParent(relatedTarget)) { // jshint ignore:line if (relatedTarget == target) { return; } @@ -1069,7 +1062,8 @@ var on = function ( } } // Bubble up to find a tagAndClass match because we didn't find one this time. - if (target = getParent(target)) { + target = getParent(target); + if (target) { onHandler(element, event, target, customData); } }; @@ -1223,8 +1217,8 @@ var getValue = function ( else if (type == 's') { value = options[input.selectedIndex].value; } + return value; } - return value; }; /** @@ -1387,7 +1381,7 @@ var onReady = window.onReady = function ( // The first item in the queue causes onReady to be triggered. if (!getLength(queue)) { setTimeout(function () { - onReady() + onReady(); }, 1); } @@ -1428,7 +1422,7 @@ var startsWith = function ( string, substring ) { - return ensureString(string).indexOf(substring) == 0; + return ensureString(string).indexOf(substring) == 0; // jshint ignore:line }; /** @@ -1535,6 +1529,20 @@ var upper = function ( return ensureString(object).toUpperCase(); }; +/** + * Return an escaped value for URLs. + */ +var escape = function (value) { + return encodeURIComponent(value); +}; + +/** + * Return an unescaped value from an escaped URL. + */ +var unescape = function (value) { + return decodeURIComponent(value); +}; + /** * Returns a query string generated by serializing an object and joined using a delimiter (defaults to '&') */ diff --git a/jymin.min.js b/jymin.min.js index 07c9515..f95372f 100644 --- a/jymin.min.js +++ b/jymin.min.js @@ -1 +1 @@ -!function(n,t,r,i){this.jymin={version:"0.2.2"};var o=function(n,t){if(n)for(var r=0,i=e(n);i>r;r++){var o=t(n[r],r,n);if(o===!1)break}},u=function(n,t,r){var i=n[t];return i||(i=n[t]=r),i},e=function(n){return v(n)||s(n)?n.length:0},f=function(n,t){return h(n)&&n.push(t),t},c=n.onReady=function(n){var t=u(c,"_QUEUE",[]);n?(e(t)||setTimeout(function(){c()},1),f(t,n)):o(t,function(n){n()})},a=function(n,t){return typeof n==t},s=function(n){return a(n,"string")},v=function(n,t){return n instanceof(t||Object)},h=function(n){return v(n,Array)}}(window,document,location,Math); \ No newline at end of file +!function(n,t,r){this.jymin={version:"0.2.3"};var i=function(n,t){if(n)for(var r=0,i=u(n);i>r;r++){var o=t(n[r],r,n);if(o===!1)break}},o=function(n,t,r){var i=n[t];return i||(i=n[t]=r),i},u=function(n){return s(n)||a(n)?n.length:0},e=function(n,t){return v(n)&&n.push(t),t},f=n.onReady=function(n){var t=o(f,"_QUEUE",[]);n?(u(t)||setTimeout(function(){f()},1),e(t,n)):i(t,function(n){n()})},c=function(n,t){return typeof n==t},a=function(n){return c(n,"string")},s=function(n,t){return n instanceof(t||Object)},v=function(n){return s(n,Array)}}(window,document,location,Math); \ No newline at end of file diff --git a/package.json b/package.json index f43463a..5473a9d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "zepto", "alternative" ], - "version": "0.2.2", + "version": "0.2.3", "main": "chug/chug.js", "homepage": "http://lighter.io/jymin", "repository": "http://github.com/zerious/jymin.git", @@ -49,9 +49,9 @@ "zeriousify": "0.1.5", "assert-plus": "0.1.5", "mocha": "1.20.1", - "istanbul": "0.2.10", + "istanbul": "0.2.11", "coveralls": "2.10.0", - "chug": "0.1.26", - "figlet": "1.0.8" + "chug": "0.1.27", + "figlet": "1.0.9" } } diff --git a/scripts/ajax.js b/scripts/ajax.js index 10b2d0a..0e2b64f 100755 --- a/scripts/ajax.js +++ b/scripts/ajax.js @@ -26,9 +26,11 @@ var getResponse = function ( var request; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - request = new ActiveXObject('Microsoft.XMLHTTP'); - } else { + } + else if (window.ActiveXObject) { + request = new ActiveXObject('Microsoft.XMLHTTP'); // jshint ignore:line + } + else { return false; } if (request) { @@ -45,15 +47,15 @@ var getResponse = function ( var object; if (status) { try { - // Trick Uglify into thinking there's no eval. - var e = window.eval; - e('eval.J=' + response); - object = e.J; + // Trick UglifyJS into thinking there's no eval. + var evil = window.eval; // jshint ignore:line + evil('eval.J=' + response); + object = evil.J; } catch (e) { - //+env:dev - error('Could not parse JSON: "' + response + '"'); - //-env:dev + //+env:debug,dev + error('Jymin: Could not parse JSON: "' + response + '"'); + //-env:debug,dev object = {_ERROR: '_BAD_JSON', _TEXT: response}; } } diff --git a/scripts/animation.js b/scripts/animation.js deleted file mode 100755 index 1a24509..0000000 --- a/scripts/animation.js +++ /dev/null @@ -1,57 +0,0 @@ -var DEFAULT_ANIMATION_FRAME_COUNT = 40; -var DEFAULT_ANIMATION_FRAME_DELAY = 20; - -/** - * Perform an animation. - */ -var animate = function ( - element, // string|DOMElement: Element or ID of element to animate. - styleTransitions, // object: cssText values to animate through. - onFinish, // function|: Callback to execute when animation is complete. - frameCount, // integer|: Number of frames to animate through. (Default: 40) - frameDelay, // integer|: Number of milliseconds between frames. (Default: 20ms) - frameIndex // integer|: Index of the frame to start on. (Default: 0) -) { - if (element = getElement(element)) { - // Only allow one animation on an element at a time. - stopAnimation(element); - frameIndex = frameIndex || 0; - frameCount = frameCount || DEFAULT_ANIMATION_FRAME_COUNT; - frameDelay = frameDelay || DEFAULT_ANIMATION_FRAME_DELAY; - var scale = Math.atan(1.5) * 2; - var fraction = Math.atan(frameIndex / frameCount * 3 - 1.5) / scale + 0.5; - var styles = {}; - forIn(styleTransitions, function(transition, key) { - var start = transition[0]; - var end = transition[1]; - var value; - if (isNaN(start)) { - value = frameIndex ? end : start; - } - else { - value = (1 - fraction) * start + fraction * end; - } - styles[key] = value; - }); - extendStyle(element, styles); - if (frameIndex < frameCount) { - element.animation = setTimeout(function() { - animate(element, styleTransitions, onFinish, frameCount, frameDelay, frameIndex + 1); - }); - } - else if (onFinish) { - onFinish(element); - } - } -}; - -/** - * Stop an animation on a given DOM element. - */ -var stopAnimation = function ( - element // string|DOMElement: Element or ID of element to cancel the animation on. -) { - if (element = getElement(element)) { - clearTimeout(element.animation); - } -}; diff --git a/scripts/collections.js b/scripts/collections.js index 1faf6d1..f461045 100755 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -5,14 +5,14 @@ var forEach = function ( array, // Array*: The array to iterate over. callback // Function*: The function to call on each item. `callback(item, index, array)` ) { - if (array) { - for (var index = 0, length = getLength(array); index < length; index++) { - var result = callback(array[index], index, array); - if (result === false) { - break; - } - } + if (array) { + for (var index = 0, length = getLength(array); index < length; index++) { + var result = callback(array[index], index, array); + if (result === false) { + break; + } } + } }; /** @@ -22,14 +22,14 @@ var forIn = function ( object, // Object*: The object to iterate over. callback // Function*: The function to call on each pair. `callback(value, key, object)` ) { - if (object) { - for (var key in object) { - var result = callback(object[key], key, object); - if (result === false) { - break; - } - } + if (object) { + for (var key in object) { + var result = callback(object[key], key, object); + if (result === false) { + break; + } } + } }; /** @@ -120,12 +120,12 @@ var merge = function ( array, // Array: The array to merge into. items // mixed+: The items to merge into the array. ) { + // TODO: Use splice instead of pushes to get better performance? + var addToFirstArray = function (item) { + array.push(item); + }; for (var i = 1, l = arguments.length; i < l; i++) { - items = arguments[i]; - // TODO: Use splice instead of push to get better performance? - forEach(items, function (item) { - array.push(item); - }); + forEach(arguments[i], addToFirstArray); } }; @@ -142,7 +142,7 @@ var pad = function ( if (isArray(array)) { var startingLength = getLength(array); if (startingLength < length) { - paddingValue = isDefined(paddingValue) ? paddingValue : ''; + paddingValue = isUndefined(paddingValue) ? '' : paddingValue; for (var index = startingLength; index < length; index++) { array.push(paddingValue); countAdded++; diff --git a/scripts/cookies.js b/scripts/cookies.js index 8ecf862..c1daa83 100755 --- a/scripts/cookies.js +++ b/scripts/cookies.js @@ -3,15 +3,14 @@ * @return object: Cookie names and values. */ var getAllCookies = function () { - var str = document.cookie; - var decode = decodeURIComponent; var obj = {}; - var pairs = str.split(/ *; */); - var pair; - if ('' == pairs[0]) return obj; - for (var i = 0; i < pairs.length; ++i) { - pair = pairs[i].split('='); - obj[decode(pair[0])] = decode(pair[1]); + var documentCookie = trim(document.cookie); + if (documentCookie) { + var cookies = documentCookie.split(/\s*;\s*/); + forEach(cookies, function (cookie) { + var pair = cookie.split(/\s*=\s*/); + obj[unescape(pair[0])] = unescape(pair[1]); + }); } return obj; }; @@ -35,19 +34,18 @@ var setCookie = function ( options // object|: Name/value pairs for options including "maxage", "expires", "path", "domain" and "secure". ) { options = options || {}; - var encode = encodeURIComponent; - var str = encode(name) + '=' + encode(value); - if (null == value) { + var str = escape(name) + '=' + unescape(value); + if (null === value) { options.maxage = -1; } if (options.maxage) { - options.expires = new Date(+new Date + options.maxage); + options.expires = new Date(+new Date() + options.maxage); } - if (options.path) str += ';path=' + options.path; - if (options.domain) str += ';domain=' + options.domain; - if (options.expires) str += ';expires=' + options.expires.toUTCString(); - if (options.secure) str += ';secure'; - document.cookie = str; + document.cookie = str + + (options.path ? ';path=' + options.path : '') + + (options.domain ? ';domain=' + options.domain : '') + + (options.expires ? ';expires=' + options.expires.toUTCString() : '') + + (options.secure ? ';secure' : ''); }; /** diff --git a/scripts/dom.js b/scripts/dom.js index 84a8151..1fa7c39 100755 --- a/scripts/dom.js +++ b/scripts/dom.js @@ -44,8 +44,9 @@ var getElementsByTagAndClass = function ( var tagName = (tagAndClass[0] || '*').toUpperCase(); var className = tagAndClass[1]; var anyTag = (tagName == '*'); + var elements; if (className) { - var elements = []; + elements = []; if (parentElement.getElementsByClassName) { forEach(parentElement.getElementsByClassName(className), function(element) { if (anyTag || (element.tagName == tagName)) { @@ -83,8 +84,8 @@ var getParent = function ( }; /** -* Create a DOM element. -*/ + * Create a DOM element. + */ var createElement = function ( tagIdentifier ) { @@ -99,7 +100,7 @@ var createElement = function ( var tagName = tagAndId[0] || 'div'; var id = tagAndId[1]; var attributes = tagAndAttributes[1]; - var cachedElement = addElement[tagName] || (addElement[tagName] = document.createElement(tagName)); + var cachedElement = createElement[tagName] || (createElement[tagName] = document.createElement(tagName)); var element = cachedElement.cloneNode(true); if (id) { element.id = id; @@ -185,13 +186,13 @@ var getChildren = function ( var getIndex = function ( element ) { - if (element = getElement(element)) { - var index = 0; - while (element = element.previousSibling) { - ++index; - } - return index; + element = getElement(element); + var index = -1; + while (element) { + ++index; + element = element.previousSibling; } + return index; }; /** @@ -215,6 +216,31 @@ var insertElement = function ( } }; +/** + * Insert a DOM element after another. + */ +var insertBefore = function ( + element, + childElement +) { + element = getElement(element); + var parentElement = getParent(element); + addElement(parentElement, childElement, element); +}; + +/** + * Insert a DOM element after another. + */ +var insertAfter = function ( + element, + childElement +) { + element = getElement(element); + var parentElement = getParent(element); + var beforeElement = getNextSibling(element); + addElement(parentElement, childElement, beforeElement); +}; + /** * Remove a DOM element from its parent. */ @@ -222,7 +248,8 @@ var removeElement = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Remove the element from its parent, provided that its parent still exists. var parentElement = getParent(element); if (parentElement) { @@ -247,7 +274,8 @@ var getHtml = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.innerHTML; } }; @@ -260,7 +288,8 @@ var setHtml = function ( html ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Set the element's innerHTML. element.innerHTML = html; } @@ -273,7 +302,8 @@ var getText = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.innerText; } }; @@ -286,7 +316,8 @@ var setText = function ( text ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Set the element's innerText. element.innerHTML = text; } @@ -299,7 +330,8 @@ var getClass = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.className; } }; @@ -312,7 +344,8 @@ var setClass = function ( className ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Set the element's innerText. element.className = className; } @@ -325,7 +358,8 @@ var getFirstChild = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.firstChild; } }; @@ -337,7 +371,8 @@ var getPreviousSibling = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.previousSibling; } }; @@ -349,7 +384,8 @@ var getNextSibling = function ( element ) { // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { return element.nextSibling; } }; @@ -372,7 +408,8 @@ var addClass = function ( element, className ) { - if (element = getElement(element)) { + element = getElement(element); + if (element) { element.className += ' ' + className; } }; @@ -384,7 +421,8 @@ var removeClass = function ( element, className ) { - if (element = getElement(element)) { + element = getElement(element); + if (element) { var tokens = getClass(element).split(/\s/); var ok = []; forEach(tokens, function (token) { @@ -445,16 +483,17 @@ var insertScript = function ( }; /** - * Run a callback on each element matching a given selector. + * Finds elements matching a selector, and return or run a callback on them. */ var all = function ( parentElement, selector, callback ) { + // TODO: Better argument collapsing. if (!selector || isFunction(selector)) { callback = selector; - selector = parentElement + selector = parentElement; parentElement = document; } var elements; @@ -490,3 +529,14 @@ var all = function ( } return elements; }; + +/** + * Finds elements matching a selector, and return or run a callback on them. + */ +var one = function ( + parentElement, + selector, + callback +) { + return all(parentElement, selector, callback)[0]; +}; diff --git a/scripts/events.js b/scripts/events.js index 7945406..dd379b8 100755 --- a/scripts/events.js +++ b/scripts/events.js @@ -18,7 +18,8 @@ var bind = function ( } // Ensure that we have an element, not just an ID. - if (element = getElement(element)) { + element = getElement(element); + if (element) { // Invoke the event handler with the event information and the target element. var callback = function(event) { @@ -32,7 +33,7 @@ var bind = function ( } var relatedTarget = event.relatedTarget || event.toElement; if (eventName == 'mouseout') { - while (relatedTarget = getParent(relatedTarget)) { + while (relatedTarget = getParent(relatedTarget)) { // jshint ignore:line if (relatedTarget == target) { return; } @@ -157,7 +158,8 @@ var on = function ( } } // Bubble up to find a tagAndClass match because we didn't find one this time. - if (target = getParent(target)) { + target = getParent(target); + if (target) { onHandler(element, event, target, customData); } }; diff --git a/scripts/forms.js b/scripts/forms.js index e286d3f..d51177c 100755 --- a/scripts/forms.js +++ b/scripts/forms.js @@ -24,8 +24,8 @@ var getValue = function ( else if (type == 's') { value = options[input.selectedIndex].value; } + return value; } - return value; }; /** diff --git a/scripts/ready.js b/scripts/ready.js index 1532d99..031a552 100644 --- a/scripts/ready.js +++ b/scripts/ready.js @@ -13,7 +13,7 @@ var onReady = window.onReady = function ( // The first item in the queue causes onReady to be triggered. if (!getLength(queue)) { setTimeout(function () { - onReady() + onReady(); }, 1); } diff --git a/scripts/strings.js b/scripts/strings.js index f29a140..c5dacbc 100755 --- a/scripts/strings.js +++ b/scripts/strings.js @@ -24,7 +24,7 @@ var startsWith = function ( string, substring ) { - return ensureString(string).indexOf(substring) == 0; + return ensureString(string).indexOf(substring) == 0; // jshint ignore:line }; /** @@ -131,6 +131,20 @@ var upper = function ( return ensureString(object).toUpperCase(); }; +/** + * Return an escaped value for URLs. + */ +var escape = function (value) { + return encodeURIComponent(value); +}; + +/** + * Return an unescaped value from an escaped URL. + */ +var unescape = function (value) { + return decodeURIComponent(value); +}; + /** * Returns a query string generated by serializing an object and joined using a delimiter (defaults to '&') */