A JavaScript library used by JoeSimmons
สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @require https://update.greasyfork.org/scripts/22443/142782/JoeSimmons%27%20Library.js
- // ==UserScript==
- // @name JoeSimmons' Library
- // @namespace http://userscripts-mirror.org/users/23652
- // @description A JavaScript library used by JoeSimmons
- // @include *
- // @copyright JoeSimmons
- // @author JoeSimmons
- // @version 1.3.0
- // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
- // @grant GM_addStyle
- // ==/UserScript==
- /**
- WIKI ==> https://github.com/joesimmons/jsl/wiki/
- SOURCE ==> https://raw.githubusercontent.com/joesimmons/jsl/master/versions/jsl-1.3.0.js
- **/
- (function (window, undefined) {
- 'use strict'; // use strict mode in ECMAScript-5
- var version = '1.3.0'; // this will be used for JSL.prototype.version
- var intervals = []; // for the setInterval/clearInterval methods
- // regular expressions
- var rSelector = /^\*|^\.[a-z][\w\d-]*|^#[^ ]+|^[a-z]+|^\[a-z]+/i; // matches a CSS selector
- var rXpath = /^\.?\/{1,2}[a-zA-Z\*]+/; // matches an XPath query
- var rHTML = /<[^>]+>/; // matches a string of HTML
- var rHyphenated = /-([a-zA-Z])/g; // matches alphabetic, hyphenated strings
- var rElementObject = /^\[object HTML([a-zA-Z]+)?Element\]$/; // matches the toString value of an element
- var rWindowObject = /^\[object Window\]$/; // matches the toString value of a window object
- var rValidVarname = /^[a-zA-Z$_][a-zA-Z0-9$_]*$/; // matches a valid variable name
- // compatibility methods for browsers that don't support ECMAScript-5 completely
- var compat = {
- 'arr_indexOf' : function (searchElement, fromIndex) {
- var index = parseInt(fromIndex || 0, 10), len = this.length;
- index = index < 0 ? len + index : index; // handle negative fromIndex
- index = !(index > 0) ? 0 : index; // handle out of range and/or NaN fromIndex
- while (index < len && index >= 0) {
- if (this[index] === searchElement) {
- return index;
- }
- index += 1;
- }
- return -1;
- },
- /*
- 'filter' : function (fn, oThis) {
- var index, value, len = this.length, ret = [];
- for (index = 0; index < len; index += 1) {
- value = this[index];
- if ( fn.call(oThis, value, index, this) ) {
- ret.push(value);
- }
- }
- return ret;
- },
- */
- 'forEach' : function (fn, oThis) {
- var index, len;
- for (index = 0, len = this.length; index < len; index += 1) {
- fn.call(oThis, this[index], index, this);
- }
- },
- 'map' : function (fn, oThis) {
- var index, newArr = [], len;
- for (index = 0, len = this.length; index < len; index += 1) {
- newArr[index] = fn.call(oThis, this[index], index, this);
- }
- return newArr;
- },
- 'reduce' : function (fn, initialValue) {
- var index, len, value, isValueSet = false;
- if (arguments.length > 1) {
- value = initialValue;
- isValueSet = true;
- }
- for (index = 0, len = this.length; index < len; index += 1) {
- if (isValueSet) {
- value = fn(value, this[index], index, this);
- } else {
- value = this[index];
- isValueSet = true;
- }
- }
- return value;
- }
- };
- // gets a method from an object's prototype. returns undefined if not found
- var getMethod = function (obj, method) {
- if (typeof XPCNativeWrapper === 'function' && typeof XPCNativeWrapper.unwrap === 'function') {
- obj = XPCNativeWrapper.unwrap(obj);
- } else if (obj.wrappedJSObject) {
- obj = obj.wrappedJSObject;
- }
- if (obj.prototype && typeof obj.prototype[method] === 'function') {
- return obj.prototype[method];
- }
- };
- // original methods for some common uses
- var core = {
- // array
- 'arr_indexOf' : getMethod(Array, 'indexOf') || compat.arr_indexOf,
- 'concat' : getMethod(Array, 'concat'),
- 'filter' : getMethod(Array, 'filter') || compat.filter,
- 'forEach' : getMethod(Array, 'forEach') || compat.forEach,
- 'map' : getMethod(Array, 'map') || compat.map,
- 'reduce' : getMethod(Array, 'reduce') || compat.reduce,
- 'slice' : getMethod(Array, 'slice'),
- // object
- 'hasOwnProperty' : getMethod(Object, 'hasOwnProperty'),
- 'toString' : getMethod(Object, 'toString'),
- };
- var JSL = function JSL(selector, context) {
- return new JSL.fn.init(selector, context);
- };
- // a simple class for dealing with event listener handlers
- var handlers = {
- stack : [],
- add : function (thisElement, type, fn) {
- this.stack.push({
- element : thisElement,
- type : type,
- fn : fn
- });
- },
- get : function (thisElement, type) {
- var events = [];
- type = typeof type === 'string' ? type : '*';
- JSL.each(this.stack, function (thisEventObj) {
- if (thisElement === thisEventObj.element) {
- if (type === '*' || thisEventObj.type === type) {
- events.push(thisEventObj);
- }
- }
- });
- return events;
- },
- remove : function (thisElement, type) {
- var handlerIndices = [], that = this;
- // find all the indices of what we need to remove
- JSL.each(handlers.get(thisElement, type), function (thisEventObj, index, array) {
- handlerIndices.push(
- core.arr_indexOf.call(that.stack, thisEventObj)
- );
- });
- // remove all the indices here, using a separate array of indices
- // we can't do this as we loop over the (stack) array itself, because
- // we would be removing values as they are being iterated through
- JSL.each(handlerIndices, function (thisIndex) {
- that.stack.splice(thisIndex, 1);
- });
- }
- };
- // Node.prototype.matchesSelector compat for vendor prefixes
- function matchesSelector(element, selector) {
- if (element && typeof selector === 'string') {
- if (typeof element.mozMatchesSelector === 'function') {
- // Mozilla
- return element.mozMatchesSelector(selector);
- } else if (typeof element.webkitMatchesSelector === 'function') {
- // Webkit
- return element.webkitMatchesSelector(selector);
- } else if (typeof element.oMatchesSelector === 'function') {
- // Opera
- return element.oMatchesSelector(selector);
- } else if (typeof element.msMatchesSelector === 'function') {
- // IE
- return element.msMatchesSelector(selector);
- }
- }
- return false;
- }
- // calls 'this' with the first parameter as the first argument
- function call(a) {
- return this(a);
- }
- function toCamelCase(string) {
- return string.replace(rHyphenated, function (fullMatch, firstGroup) {
- return firstGroup.toUpperCase();
- });
- }
- // walkTheDom by Douglas Crockford
- function walkTheDom(node, func) {
- func(node);
- node = node.firstChild;
- while (node) {
- walkTheDom(node, func);
- node = node.nextSibling;
- }
- }
- // can pluck a key out of an object
- function pluck(obj) {
- var subs = this.split('.'),
- ret = obj, i;
- for (i = 0; i < subs.length; i += 1) {
- ret = ret[ subs[i] ];
- if (ret == null) {
- return '';
- }
- }
- return ret;
- }
- function sum(curValue, nextValue) {
- return curValue + nextValue;
- }
- function sumInt(curValue, nextValue) {
- return parseInt(curValue, 10) + parseInt(nextValue, 10);
- }
- // internal function for throwing errors, so the user gets
- // some sort of hint as to why their operation failed
- function error(errorString) {
- if (typeof console !== 'undefined' && typeof console.error === 'function') {
- console.error(errorString);
- }
- return null; // always return null
- }
- // will copy an element and return a new copy with the same event listeners
- function cloneElement(thisElement) {
- var newElement = thisElement.cloneNode(true);
- // clone event listeners of element
- JSL.each(handlers.get(thisElement), function (thisEventObj) {
- JSL.addEvent(newElement, thisEventObj.type, thisEventObj.fn);
- });
- return newElement;
- }
- function getEachElements(array, selector, key, type) {
- var newElementsArray = [],
- isValidSelector = typeof selector === 'string' && selector.trim() !== '';
- JSL.each(array, function (currentElement) {
- while ( currentElement = currentElement[key] ) { // note: intentional assignment
- if (type > 0 ? currentElement.nodeType === type : true) {
- if ( isValidSelector === false || JSL(currentElement).filter(selector).exists ) {
- newElementsArray.push(currentElement);
- return;
- }
- }
- }
- });
- return newElementsArray;
- }
- // this will take
- function doElementOperationOnEach(args, op) {
- var newElementsArray = [], newElement,
- passedElements = JSL.create.apply(JSL, args);
- if (this.exists) {
- if (JSL.typeOf(passedElements) === 'array') {
- this.each(function (thisElement) {
- JSL.each(passedElements, function (passedElement) {
- // clone the element
- var newElement = cloneElement(passedElement);
- // add the new elements to an array
- newElementsArray.push(newElement);
- // perform the passed operation on the element
- op(thisElement, newElement);
- });
- });
- } else {
- this.each(function (thisElement) {
- // clone the element
- var newElement = cloneElement(passedElements);
- // add the new elements to an array
- newElementsArray.push(newElement);
- // perform the passed operation on the element
- op(thisElement, newElement);
- });
- }
- }
- return newElementsArray;
- }
- // define JSL's prototype, aka JSL.fn
- JSL.fn = JSL.prototype = {
- isJSL : true,
- constructor : JSL,
- length : 0,
- version : version,
- // similar to jQuery. JSL is just the init constructor
- init : function (selector, context) {
- var selectorStringValue = core.toString.call(selector),
- that = this,
- elems = [];
- switch (typeof selector) {
- case 'string': { // -- STRING --
- if ( selector.match(rXpath) ) {
- // handle an XPath expression
- elems = JSL.xpath({expression : selector, type : 7, context : context});
- } else if ( selector.match(rHTML) ) {
- // reserved for html code creation
- // not sure if I want to implement it
- } else if ( selector.match(rSelector) ) {
- if (JSL.typeOf(context) === 'array') {
- // handle an array being passed as the context
- return that.find.call(context, selector);
- } else if (typeof context === 'string') {
- // handle a selector being passsed as the context
- context = JSL(context);
- if (context.exists) {
- return JSL(selector, context[0]);
- }
- } else if (context != null && context.isJSL === true && context.exists) {
- // handle a JSL object being passsed as the context
- return JSL( selector, context[0] );
- } else {
- // handle a regular element being passed as the context
- context = context != null && context.querySelectorAll ? context : document;
- elems = context.querySelectorAll(selector);
- }
- }
- break;
- }
- // ---------------------------------------------------
- case 'object': { // -- OBJECT --
- if (selector != null) {
- if (selector.isJSL === true) {
- // handle a JSL object
- return selector;
- } else if ( core.hasOwnProperty.call(selector, 'length') ) {
- // handle an array-like object
- elems = selector;
- } else if ( selectorStringValue.match(rElementObject) || selectorStringValue.match(rWindowObject) ) {
- // handle a single element
- elems = [selector];
- }
- }
- break;
- }
- // ---------------------------------------------------
- default: { // -- UNKNOWN --
- if ( selectorStringValue.match(rElementObject) || selectorStringValue.match(rWindowObject) ) {
- // handle elements that are typeof === 'function'
- // e.g., object, applet, embed
- elems = [selector];
- }
- }
- }
- // define the length property of our object wrapper
- that.length = elems.length;
- // bind the elements to array-like key:value pairs in our wrapper
- // e.g., this[0] ==> element
- JSL.each(elems, function (value, index) {
- that[index] = value;
- });
- return that;
- },
- // --- STARTING LINE FOR THE JSL WRAPPER METHODS
- add : function (selector, context) {
- var newElements = JSL(selector, context).raw(),
- allElements = core.concat.call(this.raw(), newElements);
- return JSL(allElements);
- },
- addEvent : function (type, fn) {
- return this.each(function (thisElement) {
- JSL.addEvent(thisElement, type, fn);
- });
- },
- after : function () {
- var newElementsArray = doElementOperationOnEach.call(this, JSL.toArray(arguments), function (baseElement, newElement) {
- var parent = baseElement.parentNode,
- next = baseElement.nextSibling;
- if (parent) {
- if (next) {
- // add the newElement after the current element
- parent.insertBefore(newElement, next);
- } else {
- // nextSibling didn't exist. just append to its parent
- parent.appendChild(newElement);
- }
- }
- });
- return JSL(newElementsArray);
- },
- append : function () {
- var newElementsArray = doElementOperationOnEach.call(this, JSL.toArray(arguments), function (baseElement, newElement) {
- baseElement.appendChild(newElement);
- });
- return JSL(newElementsArray);
- },
- attribute : function (name, value) {
- var ret = '', valueIsValid = value != null;
- if ( typeof name === 'string' && this.exists ) {
- this.each(function (elem) {
- if (valueIsValid) {
- elem.setAttribute(name, value);
- } else {
- ret += elem.getAttribute(name) || '';
- }
- });
- }
- return valueIsValid ? this : ret;
- },
- before : function () {
- var newElementsArray = doElementOperationOnEach.call(this, JSL.toArray(arguments), function (baseElement, newElement) {
- var parent = baseElement.parentNode;
- // add the newElement before the current element
- if (parent) {
- parent.insertBefore(newElement, baseElement);
- }
- });
- return JSL(newElementsArray);
- },
- center : function () {
- return this.each(function (thisElement) {
- thisElement = JSL(thisElement);
- thisElement.css('position', 'fixed');
- thisElement.css('top', Math.floor( (window.innerHeight - thisElement.height) / 2 ) + 'px');
- thisElement.css('left', Math.floor( (window.innerWidth - thisElement.width) / 2 ) + 'px');
- });
- },
- clone : function () {
- var clonedElements = core.map.call(this, cloneElement); // variable for clarity
- return JSL(clonedElements);
- },
- css : function (name, value) {
- if (typeof name === 'string') {
- // convert the hyphenated string to camel-case
- name = toCamelCase(name);
- if (typeof value === 'string') {
- return this.each(function (thisElement) {
- if (name in thisElement.style) {
- thisElement.style[name] = value;
- }
- });
- }
- return core.map.call(this, pluck, 'style.' + name).join('');
- } else {
- return error('.css() was not passed a string for the first argument.');
- }
- },
- each : function (fn, oThis) {
- if (this.exists) {
- JSL.each(this, fn, oThis);
- }
- return this;
- },
- get exists() {
- return this.length > 0 && this[0] != null;
- },
- filter : function (selector) {
- var newElementsArray = [];
- if (typeof selector === 'string') {
- this.each(function (thisElement) {
- if ( matchesSelector(thisElement, selector) ) {
- newElementsArray.push(thisElement);
- }
- });
- }
- // returns an empty JSL object if no elements are matched
- return JSL(newElementsArray);
- },
- find : function (selector) {
- var arrayOfMatchesArrays = core.map.call(this, function (thisElement) {
- var matches = thisElement.querySelectorAll(selector);
- return JSL.toArray(matches);
- });
- var singleArrayOfMatches = arrayOfMatchesArrays.length > 0 ?
- core.reduce.call(arrayOfMatchesArrays, function (a, b) {
- return core.concat.call(a, b);
- }) : [];
- return JSL(singleArrayOfMatches);
- },
- first : function () {
- return this.get(0);
- },
- get : function (index) {
- index = index === 'first' ? 0 : index === 'last' ? -1 : parseInt(index, 10);
- if ( !isNaN(index) ) {
- return JSL( index < 0 ? this[this.length + index] : this[index] );
- }
- return JSL.toArray(this);
- },
- get height() {
- var arrayOfElemHeights = core.map.call(this, pluck, 'offsetHeight');
- return core.reduce.call(arrayOfElemHeights, sum);
- },
- has : function (selector) {
- var newElementsArray = [];
- if ( typeof selector === 'string' && selector.match(rSelector) ) {
- this.each(function (thisElement) {
- if ( JSL(selector, thisElement).exists ) {
- newElementsArray.push(thisElement);
- }
- });
- }
- return JSL(newElementsArray);
- },
- hide : function () {
- return this.css('display', 'none');
- },
- /*
- get inView(passedContainer) {
- var isInView = false;
- this.each(function (thisElement) {
- var container = passedContainer || thisElement.parentNode;
- var visible = !!( (container.scrollTop + container.offsetHeight) >= thisElement.offsetTop &&
- (container.scrollTop - thisElement.offsetHeight) <= thisElement.offsetTop );
- if (visible) {
- isInView = true;
- return 'stop';
- }
- });
- return isInView;
- },
- */
- is : function (selector) {
- for (var i = 0; i < this.length; i += 1) {
- if ( matchesSelector(this[i], selector) ) {
- return true;
- }
- }
- return false;
- },
- isnt : function (selector) {
- return !this.is(selector);
- },
- last : function (selector) {
- return this.get(-1);
- },
- next : function (selector) {
- return JSL( getEachElements(this, selector, 'nextSibling', 1) );
- },
- not : function (selector) {
- var newElementsArray = [];
- if ( typeof selector === 'string' && selector.match(rSelector) ) {
- this.each(function (thisElement) {
- if ( JSL(thisElement).isnt(selector) ) {
- newElementsArray.push(thisElement);
- }
- });
- }
- return JSL(newElementsArray);
- },
- parent : function (selector) {
- return JSL( getEachElements(this, selector, 'parentNode', 1) );
- },
- prepend : function () {
- var newElementsArray = doElementOperationOnEach.call(this, JSL.toArray(arguments), function (baseElement, newElement) {
- var firstChild = baseElement.firstChild;
- if (firstChild) {
- baseElement.insertBefore(newElement, firstChild);
- }
- });
- return JSL(newElementsArray);
- },
- prev : function (selector) {
- return JSL( getEachElements(this, selector, 'previousSibling', 1) );
- },
- prop : function (name, value) {
- var valueIsValid = value != null, ret;
- if (typeof name === 'string' && this.exists) {
- this.each(function (thisElement) {
- if (valueIsValid) {
- thisElement[name] = value;
- } else {
- if (typeof ret === 'undefined') {
- ret = thisElement[name];
- } else {
- ret += thisElement[name];
- }
- }
- });
- }
- return valueIsValid ? this : ret;
- },
- raw : function () {
- return core.slice.call(this, 0);
- },
- remove : function () {
- return this.each(function (element) {
- var parent = element.parentNode;
- if (element && parent) {
- parent.removeChild(element);
- }
- });
- },
- removeAttribute : function (attributeName) {
- if (typeof attributeName === 'string') {
- return this.each(function (thisElement) {
- thisElement.removeAttribute(attributeName);
- });
- } else {
- return error('.removeAttribute() was not passed a string.');
- }
- },
- removeEvent : function (type) {
- if (typeof type === 'string') {
- return this.each(function (thisElement) {
- JSL.removeEvent(thisElement, type);
- });
- } else {
- return error('.removeEvent() was not passed a string.');
- }
- },
- replace : function () {
- var newElementsArray = doElementOperationOnEach.call(this, JSL.toArray(arguments), function (baseElement, newElement) {
- var parent = baseElement.parentNode;
- if (parent) {
- parent.replaceChild(newElement, baseElement);
- }
- });
- return JSL(newElementsArray);
- },
- show : function (value) {
- value = typeof value === 'string' ? value : 'inline';
- return this.css('display', value);
- },
- text : function (passedText, append) {
- // handle setting text
- if (typeof passedText === 'string') {
- if (append !== true) {
- this.each(function (thisElement) {
- JSL('.//text()', thisElement).each(function (textNode) {
- textNode.data = '';
- });
- });
- }
- this.append('text', passedText);
- return this;
- }
- // handle getting text
- return core.reduce.call(this, function (curValue, nextElement) {
- return curValue + nextElement.textContent;
- }, '');
- },
- toggle : function () {
- return this.each(function (thisElement) {
- thisElement = JSL(thisElement);
- if (thisElement.visible) {
- thisElement.hide();
- } else {
- thisElement.show();
- }
- });
- },
- value : function (passedValue) {
- var elem = this[0],
- tagName = elem && elem.tagName || '',
- selectedOptions = [],
- rInputTypeBlacklist = /button|checkbox|file|image|radio|reset|submit/,
- passedValueType = JSL.typeOf(passedValue);
- if (passedValue == null) {
- // no arguments were passed, return a value
- if (tagName === 'SELECT') {
- if ( elem.hasAttribute('multiple') ) {
- JSL.each(elem.options, function (thisOption) {
- if (thisOption.selected) {
- selectedOptions.push(thisOption.value);
- }
- });
- return selectedOptions;
- } else {
- return elem.options[elem.selectedIndex].value;
- }
- } else if ( tagName === 'INPUT' && !elem.type.match(rInputTypeBlacklist) ) {
- return elem.value;
- }
- if (tagName === 'TEXTAREA') {
- return elem.value;
- }
- } else {
- // an argument was passed, set the value on each element
- return this.each(function (thisElement) {
- var tagName = thisElement.tagName;
- if (tagName === 'SELECT') {
- if (thisElement.hasAttribute('multiple') && passedValueType === 'array') {
- JSL.each(thisElement.options, function (thisOption) {
- JSL.each(passedValue, function (thisPassedValue) {
- if (thisOption.value == thisPassedValue) {
- thisOption.selected = true;
- return 'stop';
- } else {
- thisOption.selected = false;
- }
- });
- });
- } else {
- JSL.each(thisElement.options, function (thisOption) {
- thisOption.selected = thisOption.value == passedValue;
- });
- }
- } else if (tagName === 'INPUT') {
- if ( !thisElement.type.match(rInputTypeBlacklist) ) {
- thisElement.value = passedValue;
- } else if (thisElement.type === 'checkbox' || thisElement.type === 'radio') {
- if (passedValueType === 'array') {
- JSL.each(passedValue, function (thisPassedValue) {
- if (thisElement.value == thisPassedValue) {
- thisElement.checked = true;
- return 'stop';
- } else {
- thisElement.checked = false;
- }
- });
- } else if (thisElement.value == passedValue) {
- thisElement.checked = true;
- }
- }
- } else if (tagName === 'TEXTAREA') {
- thisElement.value = passedValue;
- }
- });
- }
- return null;
- },
- get visible() {
- return Math.max(this.width, this.height) > 0;
- },
- get width() {
- var arrayOfElemHeights = core.map.call(this, pluck, 'offsetWidth');
- return core.reduce.call(arrayOfElemHeights, sum);
- },
- };
- // give the init function the JSL prototype for later instantiation
- JSL.fn.init.prototype = JSL.fn;
- // extend method. can extend any object it's run upon
- JSL.fn.extend = JSL.extend = function (obj) {
- var name, copy;
- for (name in obj) {
- copy = obj[name];
- if ( !core.hasOwnProperty.call(this, name) && typeof copy !== 'undefined' ) {
- this[name] = copy;
- }
- }
- };
- // --- STARTLING LINE FOR THE DIRECT JSL METHODS
- JSL.extend({
- addEvent : function addEvent(thisElement, type, fn) {
- if (thisElement != null && typeof type === 'string' && typeof fn === 'function') {
- if (typeof thisElement.addEventListener === 'function') {
- thisElement.addEventListener(type, fn, false);
- } else if (typeof thisElement.attachEvent === 'function') {
- type = 'on' + type;
- thisElement.attachEvent(type, fn);
- } else {
- return;
- }
- handlers.add(thisElement, type, fn);
- }
- },
- addScript : function addScript(contents, id, node) {
- var newElement = document.createElement('script');
- newElement.id = id || ( 'jsl-script-' + JSL.random(999) );
- newElement.innerHTML = contents;
- node = node || document.head || document.querySelector('html > head');
- node.appendChild(newElement);
- return {
- remove : function () {
- node.removeChild(newElement);
- }
- };
- },
- addStyle : function addStyle(css, id, node) {
- id = id || ( 'jsl-style-' + JSL.random(999) );
- node = node || document.head || document.querySelector('html > head');
- if (node) {
- node.appendChild(
- JSL.create('style', {id : id, type : 'text/css'}, [ JSL.create('text', css) ] )
- );
- }
- },
- alias : function alias(newAlias) {
- if (typeof newAlias === 'string' && newAlias.match(rValidVarname) && typeof window[newAlias] === 'undefined') {
- window[newAlias] = JSL;
- }
- },
- clearInterval : function clearInterval(index) {
- if (typeof index === 'number' && index < intervals.length) {
- window.clearTimeout( intervals[index] );
- intervals[index] = null;
- }
- },
- create : function create(elementName, descObj, kidsArray) {
- var argsLength = arguments.length,
- typeValue, prop, val, HTMLholder, ret, i;
- if (argsLength === 2 && elementName === 'text' && typeof descObj === 'string') {
- // handle text node creation
- return document.createTextNode(descObj);
- } else if ( argsLength === 1 && typeof elementName === 'string' && elementName.match(rHTML) ) {
- // handle HTML strings
- // take the HTML string and put it inside a div
- HTMLholder = document.createElement('div');
- HTMLholder.innerHTML = elementName;
- // add each childNode to an array to return
- ret = [];
- ret.push.apply(ret, HTMLholder.childNodes);
- return ret.length > 0 ? (ret.length === 1 ? ret[0] : ret) : null;
- } else if (argsLength > 1 && typeof elementName === 'string' && typeof descObj === 'object') {
- // handle the normal element name and descriptor object
- ret = document.createElement(elementName + '');
- for (prop in descObj) {
- if ( core.hasOwnProperty.call(descObj, prop) ) {
- val = descObj[prop];
- if (prop.indexOf('on') === 0 && typeof val === 'function') {
- JSL.addEvent(ret, prop.substring(2), val);
- } else if ( prop !== 'style' && prop !== 'class' && prop in ret && typeof ret[prop] !== 'undefined' ) {
- ret[prop] = val;
- } else {
- ret.setAttribute(prop, val);
- }
- }
- }
- if (JSL.typeOf(kidsArray) === 'array') {
- JSL.each(kidsArray, function (kid) {
- var val, item, i;
- if (typeof kid === 'string') {
- val = JSL.create(kid)
- if (JSL.typeOf(val) === 'array') {
- for (i = 0; i < val.length; i += 1) {
- ret.appendChild( val[i] );
- }
- } else if (JSL.typeOf(kid) === 'element') {
- ret.appendChild(kid);
- }
- } else if (JSL.typeOf(kid) === 'element') {
- ret.appendChild(kid);
- }
- });
- }
- return ret;
- } else if (argsLength === 1 && JSL.typeOf(elementName) === 'element') {
- // handle an element
- return elementName;
- }
- },
- each : function each(passedArray, fn, oThis) {
- var isOthisUndefined = typeof oThis !== 'undefined',
- index, len, otherThis, value;
- for (index = 0; index < passedArray.length; index += 1) {
- value = passedArray[index];
- otherThis = isOthisUndefined ? oThis : value;
- if (fn.call(otherThis, value, index, passedArray) === 'stop') {
- break;
- }
- }
- },
- loop : function loop(maxIterations, fn) {
- var args = JSL.toArray(arguments), i;
- if (typeof maxIterations === 'number' && maxIterations > 0 && typeof fn === 'function') {
- args = args.slice(2);
- for (i = 0; i < maxIterations; i += 1) {
- fn.apply(null, args);
- }
- }
- },
- random : function random(maxInteger, minInteger) {
- var rand = -1;
- while (rand < 0 || rand > maxInteger || rand < minInteger) {
- rand = Math.floor( Math.random() * maxInteger ) + Math.round( Math.random() );
- }
- return rand;
- },
- removeEvent : function removeEvent(thisElement, type) {
- JSL.each(handlers.get(thisElement, type), function (thisEventObj) {
- if (typeof thisElement.removeEventListener === 'function') {
- thisEventObj.element.removeEventListener(thisEventObj.type, thisEventObj.fn, false);
- } else if (typeof thisElement.detachEvent === 'function') {
- type = 'on' + type;
- thisEventObj.element.detachEvent(thisEventObj.type, thisEventObj.fn);
- }
- handlers.remove(thisElement, type);
- });
- },
- runAt : function runAt(state, func, oThis) {
- var args = JSL.toArray(arguments), intv,
- // compose a list of the 4 states, to use .indexOf() upon later
- states = ['uninitialized', 'loading', 'interactive', 'complete'],
- // in-case they pass [start/end] instead of [loading/complete]
- state = state.replace('start', 'loading').replace('end', 'complete');
- // this will run their function with the specified arguments, if any,
- // and a custom 'this' value, if specified
- function runFunc() {
- func.apply( oThis, args.slice(3) );
- }
- // this will run on each state change if the specified state is
- // not achieved yet. it will run their function when it is achieved
- function checkState() {
- if (document.readyState === state) {
- runFunc();
- JSL.clearInterval(intv);
- }
- }
- if ( core.arr_indexOf.call(states, state) <= core.arr_indexOf.call(states, document.readyState) ) {
- // we are at, or have missed, our desired state
- // run the specified function
- runFunc();
- } else {
- intv = JSL.setInterval(checkState, 200);
- }
- },
- setInterval : function setInterval(func, delay) {
- var index = intervals.length,
- delay_orig = delay,
- count = 1, startTime;
- function doRe(func, delay) {
- return window.setTimeout(function () {
- // drift accomodation
- var difference = ( new Date().getTime() ) - startTime,
- correctTime = delay_orig * count,
- drift = difference - correctTime;
- // execute the function before setting a new timeout
- func.call(null);
- // fix for when a timeout takes longer than double the original delay time to execute
- if (drift > delay_orig) {
- drift = delay_orig;
- }
- // save the reference of the new timeout in our 'intervals' stack
- if (intervals[index] !== null) {
- intervals[index] = doRe(func, delay_orig - drift);
- }
- count += 1;
- }, delay);
- }
- startTime = new Date().getTime();
- intervals[index] = doRe(func, delay_orig);
- return index;
- },
- toArray : function toArray(arr) {
- var newArr = [], // new array to store the values into
- len = arr.length || arr.snapshotLength,
- item, i;
- if (typeof len === 'number' && len > 0) {
- if (typeof arr.snapshotItem === 'function') {
- for (i = 0; ( item = arr.snapshotItem(i) ); i += 1) {
- newArr.push(item);
- }
- } else {
- // if the specified 'list' is array-like, use slice on it
- // to convert it to an array
- newArr = core.slice.call(arr, 0);
- }
- }
- return newArr;
- },
- toString : function toString(item) {
- var key, value, values = [];
- function stringifyValue(val) {
- var typeOfVal = JSL.typeOf(val),
- toStringValue = core.toString.call(val);
- if (typeOfVal === 'null' || typeOfVal === 'undefined') {
- val = typeOfVal;
- } else if (typeof val === 'string') {
- if (val.length > 15) { // truncate strings longer than 15 characters
- val = '"' + val.substring(0, 12) + '"...';
- } else {
- val = '"' + val + '"';
- }
- } else if (typeOfVal === 'function') {
- val = val.toString().substring(0, 20);
- } else if (typeOfVal !== 'number' && typeOfVal !== 'boolean') {
- val = toStringValue;
- }
- return val;
- }
- switch( JSL.typeOf(item) ) {
- case 'object': {
- for (key in item) {
- if ( item.hasOwnProperty(key) ) {
- value = stringifyValue( item[key] );
- values.push( '"' + key + '" : ' + value );
- }
- }
- return '{\n ' + values.join(',\n ') + '\n}';
- }
- // --------------------------------------
- case 'array': {
- item = core.map.call(item, function (thisValue) {
- return stringifyValue(thisValue);
- });
- return '[\n ' + item.join(',\n ') + '\n]';
- }
- // --------------------------------------
- case 'string': {
- return '"' + item + '"';
- }
- // --------------------------------------
- case 'number': {
- item = parseInt(item, 10);
- if ( isNaN(item) ) { // no ternary operator, for clarity
- return 'NaN';
- } else {
- return item.toString();
- }
- }
- // --------------------------------------
- case 'regexp': {
- if (item.toString().length <= 20) {
- item.toString();
- } else {
- return '[object RegExp]';
- }
- }
- // --------------------------------------
- case 'function': case 'boolean': {
- return item.toString();
- }
- // --------------------------------------
- case 'null': {
- return 'null';
- }
- // --------------------------------------
- case 'undefined': {
- return 'undefined';
- }
- // --------------------------------------
- default: {
- return core.toString.call(item);
- }
- }
- },
- // typeOf by Douglas Crockford. modified by JoeSimmons
- typeOf : function typeOf(value) {
- var s = typeof value,
- ostr = core.toString.call(value);
- if (s === 'object' || s === 'function') {
- if (value) {
- if (ostr === '[object Array]') {
- s = 'array';
- } else if ( ostr === '[object Text]' || ostr.match(rElementObject) ) {
- s = 'element';
- } else if (ostr === '[object HTMLCollection]') {
- s = 'collection';
- } else if (ostr === '[object NodeList]') {
- s = 'nodelist';
- } else if (ostr === '[object Arguments]') {
- s = 'arguments';
- } else if (ostr === '[object RegExp]') {
- s = 'regexp';
- }
- } else {
- s = 'null';
- }
- }
- return s;
- },
- waitFor : function waitFor(info) {
- var verifier = function () { return true; },
- done = info ? info.done : null,
- i, selector, context, waitForInterval;
- if (info == null || typeof done !== 'function') { return; }
- switch ( JSL.typeOf(info.selector) ) {
- case 'string': case 'element': case 'array': {
- selector = info.selector;
- break;
- }
- default: {
- return error('Invalid selector passed to JSL.waitFor()');
- }
- }
- switch ( JSL.typeOf(info.context) ) {
- case 'string': case 'element': case 'array': {
- context = info.context;
- }
- }
- if (typeof info.verifier === 'function' && info.verifier.toString().indexOf('return ') !== -1) {
- verifier = info.verifier;
- }
- function clear() {
- JSL.clearInterval(waitForInterval);
- }
- function check() {
- var elem = JSL(selector, context);
- if (elem.exists && verifier(elem) === true) {
- done(elem);
- return clear();
- }
- if (i >= 150) { // check for 30 seconds max
- return clear();
- }
- i += 1;
- }
- waitForInterval = JSL.setInterval(check, 200);
- },
- xpath : function xpath(obj) {
- var type = obj.type || 7,
- types = {
- '1' : 'numberValue',
- '2' : 'stringValue',
- '3' : 'booleanValue',
- '8' : 'singleNodeValue',
- '9' : 'singleNodeValue'
- },
- expression = obj.expression,
- context = obj.context || document,
- doc = document, xp;
- if (typeof context.evaluate === 'function') {
- doc = context;
- } else if (typeof context.ownerDocument.evaluate === 'function') {
- doc = context.ownerDocument;
- }
- xp = doc.evaluate(expression, context, null, type, null);
- if (!expression) {
- error('An expression must be supplied for JSL.xpath()');
- return null;
- }
- if ( types[type] ) {
- return xp[ types[ type ] ];
- } else {
- return JSL.toArray(xp);
- }
- }
- });
- // assign JSL to the window object
- window.JSL = window._J = JSL;
- // just for testing purposes
- //unsafeWindow.JSL = unsafeWindow._J = JSL;
- }(window));
- /*
- // JSL test button
- // use it to test code on user click (non-automatic)
- (function () {
- var mo = new MutationObserver(function (mutations) {
- mutations.forEach(function (mutation) {
- var target = mutation.target;
- if (mutation.attributeName === 'value' && target.value !== 'Run JSL test') {
- target.value = 'Run JSL test';
- }
- });
- });
- JSL(document.body).append(
- 'input',
- {
- id : 'jsl_user_test',
- type : 'button',
- value : 'Run JSL test',
- style : 'display: block; position: fixed; top: 4px; right: 4px; z-index: 999999; padding: 2px 14px; font-size: 11pt; font-family: Arial, Verdana;',
- onclick : function () {
- // ---- ENTER ONCLICK CODE HERE ----
- window.setTimeout(function () {
- JSL(document.body).append('<div id="waitForTest">I\'m a JSL.waitFor() test DIV!</div>');
- }, 1500);
- JSL.waitFor({
- selector : '#waitForTest',
- done : function (elem) {
- alert('#waitForTest is loaded!');
- }
- });
- // ---------------------------------
- }
- }
- );
- mo.observe( JSL('#jsl_user_test')[0], { attributes : true } );
- }());
- */