mirror of
https://github.com/brachiel/Androtafl.git
synced 2026-03-16 22:50:23 +00:00
* Using jqMobi as a javascript framework * Using jqMobi-Ui as ui framework * Implemented basic minimax AI * Implemented minimalistic player pairing server for node.js
1895 lines
No EOL
71 KiB
JavaScript
1895 lines
No EOL
71 KiB
JavaScript
/**
|
|
* jqMobi is a query selector class for HTML5 mobile apps on a WebkitBrowser.
|
|
* Since most mobile devices (Android, iOS, webOS) use a WebKit browser, you only need to target one browser.
|
|
* We are able to increase the speed greatly by removing support for legacy desktop browsers and taking advantage of browser features, like native JSON parsing and querySelectorAll
|
|
|
|
|
|
* MIT License
|
|
* @author AppMobi
|
|
* @api private
|
|
*/
|
|
if (!window.jq || typeof (jq) !== "function") {
|
|
/**
|
|
* This is our master jq object that everything is built upon.
|
|
* $ is a pointer to this object
|
|
* @title jqMobi
|
|
* @api private
|
|
*/
|
|
var jq = (function(window) {
|
|
"use strict";
|
|
var undefined, document = window.document,
|
|
emptyArray = [],
|
|
slice = emptyArray.slice,
|
|
classCache = [],
|
|
eventHandlers = [],
|
|
_eventID = 1,
|
|
jsonPHandlers = [],
|
|
_jsonPID = 1,
|
|
fragementRE=/^\s*<(\w+)[^>]*>/,
|
|
_attrCache={};
|
|
|
|
|
|
/**
|
|
* Internal function to test if a class name fits in a regular expression
|
|
* @param {String} name to search against
|
|
* @return {Boolean}
|
|
* @api private
|
|
*/
|
|
function classRE(name) {
|
|
return name in classCache ? classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'));
|
|
}
|
|
|
|
/**
|
|
* Internal function that returns a array of unique elements
|
|
* @param {Array} array to compare against
|
|
* @return {Array} array of unique elements
|
|
* @api private
|
|
*/
|
|
function unique(arr) {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (arr.indexOf(arr[i]) != i) {
|
|
arr.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
/**
|
|
* Given a set of nodes, it returns them as an array. Used to find
|
|
* siblings of an element
|
|
* @param {Nodelist} Node list to search
|
|
* @param {Object} [element] to find siblings off of
|
|
* @return {Array} array of sibblings
|
|
* @api private
|
|
*/
|
|
function siblings(nodes, element) {
|
|
var elems = [];
|
|
if (nodes == undefined)
|
|
return elems;
|
|
|
|
for (; nodes; nodes = nodes.nextSibling) {
|
|
if (nodes.nodeType == 1 && nodes !== element) {
|
|
elems.push(nodes);
|
|
}
|
|
}
|
|
return elems;
|
|
}
|
|
|
|
/**
|
|
* This is the internal jqMobi object that gets extended and added on to it
|
|
* This is also the start of our query selector engine
|
|
* @param {String|Element|Object|Array} selector
|
|
* @param {String|Element|Object} [context]
|
|
*/
|
|
var $jqm = function(toSelect, what) {
|
|
this.length = 0;
|
|
if (!toSelect) {
|
|
return this;
|
|
} else if (toSelect instanceof $jqm && what == undefined) {
|
|
return toSelect;
|
|
} else if ($.isFunction(toSelect)) {
|
|
return $(document).ready(toSelect);
|
|
} else if ($.isArray(toSelect) && toSelect.length != undefined) { //Passing in an array or object
|
|
for (var i = 0; i < toSelect.length; i++)
|
|
this[this.length++] = toSelect[i];
|
|
return this;
|
|
} else if ($.isObject(toSelect) && $.isObject(what)) { //var tmp=$("span"); $("p").find(tmp);
|
|
if (toSelect.length == undefined) {
|
|
if (toSelect.parentNode == what)
|
|
this[this.length++] = toSelect;
|
|
} else {
|
|
for (var i = 0; i < toSelect.length; i++)
|
|
if (toSelect[i].parentNode == what)
|
|
this[this.length++] = toSelect[i];
|
|
}
|
|
return this;
|
|
} else if ($.isObject(toSelect) && what == undefined) { //Single object
|
|
this[this.length++] = toSelect;
|
|
return this;
|
|
} else if (what !== undefined) {
|
|
if (what instanceof $jqm) {
|
|
return what.find(toSelect);
|
|
}
|
|
|
|
} else {
|
|
what = document;
|
|
}
|
|
|
|
var dom = this.selector(toSelect, what);
|
|
if (!dom) {
|
|
return this;
|
|
}
|
|
//reverse the query selector all storage
|
|
else if ($.isArray(dom)) {
|
|
for (var j = 0; j < dom.length; j++) {
|
|
this[this.length++] = dom[j];
|
|
}
|
|
} else {
|
|
this[this.length++] = dom;
|
|
return this;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* This calls the $jqm function
|
|
* @param {String|Element|Object|Array} selector
|
|
* @param {String|Element|Object} [context]
|
|
*/
|
|
var $ = function(selector, what) {
|
|
return new $jqm(selector, what);
|
|
};
|
|
|
|
/**
|
|
* this is the query selector library for elements
|
|
* @param {String} selector
|
|
* @param {String|Element|Object} [context]
|
|
* @api private
|
|
*/
|
|
|
|
function _selector(selector, what) {
|
|
var dom;
|
|
try {
|
|
selector=selector.trim();
|
|
if (selector[0] === "#" && selector.indexOf(" ") === -1 && selector.indexOf(">") === -1) {
|
|
if (what == document)
|
|
dom = what.getElementById(selector.replace("#", ""));
|
|
else
|
|
dom = [].slice.call(what.querySelectorAll(selector));
|
|
} else if (selector[0] === "<" && selector[selector.length - 1] === ">") //html
|
|
{
|
|
var tmp = document.createElement("div");
|
|
tmp.innerHTML = selector.trim();
|
|
dom = [].slice.call(tmp.childNodes);
|
|
} else {
|
|
dom = [].slice.call(what.querySelectorAll(selector));
|
|
}
|
|
} catch (e) {
|
|
}
|
|
return dom;
|
|
}
|
|
|
|
/**
|
|
* Map takes in elements and executes a callback function on each and returns a collection
|
|
```
|
|
$.map([1,2],function(ind){return ind+1});
|
|
```
|
|
|
|
* @param {Array|Object} elements
|
|
* @param {Function} callback
|
|
* @return {Object} jqMobi object with elements in it
|
|
* @title $.map(elements,callback)
|
|
*/
|
|
$.map = function(elements, callback) {
|
|
var value, values = [],
|
|
i, key;
|
|
if ($.isArray(elements))
|
|
for (i = 0; i < elements.length; i++) {
|
|
value = callback(elements[i], i);
|
|
if (value !== undefined)
|
|
values.push(value);
|
|
}
|
|
else if ($.isObject(elements))
|
|
for (key in elements) {
|
|
if (!elements.hasOwnProperty(key))
|
|
continue;
|
|
value = callback(elements[key], key);
|
|
if (value !== undefined)
|
|
values.push(value);
|
|
}
|
|
return $([values]);
|
|
};
|
|
|
|
/**
|
|
* Iterates through elements and executes a callback. Returns if false
|
|
```
|
|
$.each([1,2],function(ind){console.log(ind);});
|
|
```
|
|
|
|
* @param {Array|Object} elements
|
|
* @param {Function} callback
|
|
* @return {Array} elements
|
|
* @title $.each(elements,callback)
|
|
*/
|
|
$.each = function(elements, callback) {
|
|
var i, key;
|
|
if ($.isArray(elements))
|
|
for (i = 0; i < elements.length; i++) {
|
|
if (callback(i, elements[i]) === false)
|
|
return elements;
|
|
}
|
|
else if ($.isObject(elements))
|
|
for (key in elements) {
|
|
if (!elements.hasOwnProperty(key))
|
|
continue;
|
|
if (callback(key, elements[key]) === false)
|
|
return elements;
|
|
}
|
|
return elements;
|
|
};
|
|
|
|
/**
|
|
* Extends an object with additional arguments
|
|
```
|
|
$.extend({foo:'bar'});
|
|
$.extend(element,{foo:'bar'});
|
|
```
|
|
|
|
* @param {Object} [target] element
|
|
* @param any number of additional arguments
|
|
* @return {Object} [target]
|
|
* @title $.extend(target,{params})
|
|
*/
|
|
$.extend = function(target) {
|
|
if (target == undefined)
|
|
target = this;
|
|
if (arguments.length === 1) {
|
|
for (var key in target)
|
|
this[key] = target[key];
|
|
return this;
|
|
} else {
|
|
slice.call(arguments, 1).forEach(function(source) {
|
|
for (var key in source)
|
|
target[key] = source[key];
|
|
});
|
|
}
|
|
return target;
|
|
};
|
|
|
|
/**
|
|
* Checks to see if the parameter is an array
|
|
```
|
|
var arr=[];
|
|
$.isArray(arr);
|
|
```
|
|
|
|
* @param {Object} element
|
|
* @return {Boolean}
|
|
* @example $.isArray([1]);
|
|
* @title $.isArray(param)
|
|
*/
|
|
$.isArray = function(obj) {
|
|
return obj instanceof Array && obj['push'] != undefined; //ios 3.1.3 doesn't have Array.isArray
|
|
};
|
|
|
|
/**
|
|
* Checks to see if the parameter is a function
|
|
```
|
|
var func=function(){};
|
|
$.isFunction(func);
|
|
```
|
|
|
|
* @param {Object} element
|
|
* @return {Boolean}
|
|
* @title $.isFunction(param)
|
|
*/
|
|
$.isFunction = function(obj) {
|
|
return typeof obj === "function";
|
|
};
|
|
/**
|
|
* Checks to see if the parameter is a object
|
|
```
|
|
var foo={bar:'bar'};
|
|
$.isObject(foo);
|
|
```
|
|
|
|
* @param {Object} element
|
|
* @return {Boolean}
|
|
* @title $.isObject(param)
|
|
*/
|
|
$.isObject = function(obj) {
|
|
return typeof obj === "object";
|
|
}
|
|
|
|
|
|
/**
|
|
* Prototype for jqm object. Also extens $.fn
|
|
*/
|
|
$.fn = $jqm.prototype = {
|
|
constructor: $jqm,
|
|
forEach: emptyArray.forEach,
|
|
reduce: emptyArray.reduce,
|
|
push: emptyArray.push,
|
|
indexOf: emptyArray.indexOf,
|
|
concat: emptyArray.concat,
|
|
selector: _selector,
|
|
oldElement: undefined,
|
|
slice: emptyArray.slice,
|
|
/**
|
|
* This is a utility function for .end()
|
|
* @param {Object} params
|
|
* @return {Object} a jqMobi with params.oldElement set to this
|
|
* @api private
|
|
*/
|
|
setupOld: function(params) {
|
|
if (params == undefined)
|
|
return $();
|
|
params.oldElement = this;
|
|
return params;
|
|
|
|
},
|
|
/**
|
|
* This is a wrapper to $.map on the selected elements
|
|
```
|
|
$().map(function(){this.value+=ind});
|
|
```
|
|
|
|
* @param {Function} callback
|
|
* @return {Object} a jqMobi object
|
|
* @title $().map(function)
|
|
*/
|
|
map: function(fn) {
|
|
return $.map(this, function(el, i) {
|
|
return fn.call(el, i, el);
|
|
});
|
|
},
|
|
/**
|
|
* Iterates through all elements and applys a callback function
|
|
```
|
|
$().each(function(){console.log(this.value)});
|
|
```
|
|
|
|
* @param {Function} callback
|
|
* @return {Object} a jqMobi object
|
|
* @title $().each(function)
|
|
*/
|
|
each: function(callback) {
|
|
this.forEach(function(el, idx) {
|
|
callback.call(el, idx, el);
|
|
});
|
|
return this;
|
|
},
|
|
/**
|
|
* This is executed when DOMContentLoaded happens, or after if you've registered for it.
|
|
```
|
|
$(document).ready(function(){console.log('I'm ready');});
|
|
```
|
|
|
|
* @param {Function} callback
|
|
* @return {Object} a jqMobi object
|
|
* @title $().ready(function)
|
|
*/
|
|
|
|
ready: function(callback) {
|
|
if (document.readyState === "complete" || document.readyState === "loaded")
|
|
callback();
|
|
document.addEventListener("DOMContentLoaded", callback, false);
|
|
return this;
|
|
},
|
|
/**
|
|
* Searches through the collection and reduces them to elements that match the selector
|
|
```
|
|
$("#foo").find('.bar');
|
|
$("#foo").find($('.bar'));
|
|
$("#foo").find($('.bar').get());
|
|
```
|
|
|
|
* @param {String|Object|Array} selector
|
|
* @return {Object} a jqMobi object filtered
|
|
* @title $().find(selector)
|
|
|
|
*/
|
|
find: function(sel) {
|
|
if (this.length === 0)
|
|
return undefined;
|
|
var elems = [];
|
|
var tmpElems;
|
|
for (var i = 0; i < this.length; i++) {
|
|
tmpElems = ($(sel, this[i]));
|
|
|
|
for (var j = 0; j < tmpElems.length; j++) {
|
|
elems.push(tmpElems[j]);
|
|
}
|
|
}
|
|
return $(unique(elems));
|
|
},
|
|
/**
|
|
* Gets or sets the innerHTML for the collection.
|
|
* If used as a get, the first elements innerHTML is returned
|
|
```
|
|
$("#foo").html(); //gets the first elements html
|
|
$("#foo").html('new html');//sets the html
|
|
```
|
|
|
|
* @param {String} html to set
|
|
* @return {Object} a jqMobi object
|
|
* @title $().html([html])
|
|
*/
|
|
html: function(html) {
|
|
if (this.length === 0)
|
|
return undefined;
|
|
if (html === undefined)
|
|
return this[0].innerHTML;
|
|
for (var i = 0; i < this.length; i++) {
|
|
this[i].innerHTML = html;
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Gets or sets the innerText for the collection.
|
|
* If used as a get, the first elements innerText is returned
|
|
```
|
|
$("#foo").text(); //gets the first elements text;
|
|
$("#foo").text('new text'); //sets the text
|
|
```
|
|
|
|
* @param {String} text to set
|
|
* @return {Object} a jqMobi object
|
|
* @title $().text([text])
|
|
*/
|
|
text: function(text) {
|
|
if (this.length === 0)
|
|
return undefined;
|
|
if (text === undefined)
|
|
return this[0].textContent;
|
|
for (var i = 0; i < this.length; i++) {
|
|
this[i].textContent = text;
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Gets or sets a css property for the collection
|
|
* If used as a get, the first elements css property is returned
|
|
```
|
|
$().css("background"); // Gets the first elements background
|
|
$().css("background","red") //Sets the elements background to red
|
|
```
|
|
|
|
* @param {String} attribute to get
|
|
* @param {String} value to set as
|
|
* @return {Object} a jqMobi object
|
|
* @title $().css(attribute,[value])
|
|
*/
|
|
css: function(attribute, value, obj) {
|
|
var toAct = obj != undefined ? obj : this[0];
|
|
if (this.length === 0)
|
|
return undefined;
|
|
if (value == undefined && typeof (attribute) === "string") {
|
|
var styles = window.getComputedStyle(toAct);
|
|
return toAct.style[attribute] ? toAct.style[attribute]: window.getComputedStyle(toAct)[attribute] ;
|
|
}
|
|
for (var i = 0; i < this.length; i++) {
|
|
if ($.isObject(attribute)) {
|
|
for (var j in attribute) {
|
|
this[i].style[j] = attribute[j];
|
|
}
|
|
} else {
|
|
this[i].style[attribute] = value;
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Sets the innerHTML of all elements to an empty string
|
|
```
|
|
$().empty();
|
|
```
|
|
|
|
* @return {Object} a jqMobi object
|
|
* @title $().empty()
|
|
*/
|
|
empty: function() {
|
|
for (var i = 0; i < this.length; i++) {
|
|
this[i].innerHTML = '';
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Sets the elements display property to "none".
|
|
* This will also store the old property into an attribute for hide
|
|
```
|
|
$().hide();
|
|
```
|
|
|
|
* @return {Object} a jqMobi object
|
|
* @title $().hide()
|
|
*/
|
|
hide: function() {
|
|
if (this.length === 0)
|
|
return this;
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (this.css("display", null, this[i]) != "none") {
|
|
this[i].setAttribute("jqmOldStyle", this.css("display", null, this[i]));
|
|
this[i].style.display = "none";
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Shows all the elements by setting the css display property
|
|
* We look to see if we were retaining an old style (like table-cell) and restore that, otherwise we set it to block
|
|
```
|
|
$().show();
|
|
```
|
|
|
|
* @return {Object} a jqMobi object
|
|
* @title $().show()
|
|
*/
|
|
show: function() {
|
|
if (this.length === 0)
|
|
return this;
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (this.css("display", null, this[i]) == "none") {
|
|
this[i].style.display = this[i].getAttribute("jqmOldStyle") ? this[i].getAttribute("jqmOldStyle") : 'block';
|
|
this[i].removeAttribute("jqmOldStyle");
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Toggle the visibility of a div
|
|
```
|
|
$().toggle();
|
|
$().toggle(true); //force showing
|
|
```
|
|
|
|
* @param {Boolean} [show] -force the hiding or showing of the element
|
|
* @return {Object} a jqMobi object
|
|
* @title $().toggle([show])
|
|
*/
|
|
toggle: function(show) {
|
|
var show2 = show === true ? true : false;
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (window.getComputedStyle(this[i])['display'] !== "none" || (show !== undefined && show2 === false)) {
|
|
this[i].setAttribute("jqmOldStyle", this[i].style.display)
|
|
this[i].style.display = "none";
|
|
} else {
|
|
this[i].style.display = this[i].getAttribute("jqmOldStyle") != undefined ? this[i].getAttribute("jqmOldStyle") : 'block';
|
|
this[i].removeAttribute("jqmOldStyle");
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Gets or sets an elements value
|
|
* If used as a getter, we return the first elements value. If nothing is in the collection, we return undefined
|
|
```
|
|
$().value; //Gets the first elements value;
|
|
$().value="bar"; //Sets all elements value to bar
|
|
```
|
|
|
|
* @param {String} [value] to set
|
|
* @return {String|Object} A string as a getter, jqMobi object as a setter
|
|
* @title $().val([value])
|
|
*/
|
|
val: function(value) {
|
|
if (this.length === 0)
|
|
return undefined;
|
|
if (value == undefined)
|
|
return this[0].value;
|
|
for (var i = 0; i < this.length; i++) {
|
|
this[i].value = value;
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Gets or sets an attribute on an element
|
|
* If used as a getter, we return the first elements value. If nothing is in the collection, we return undefined
|
|
```
|
|
$().attr("foo"); //Gets the first elements 'foo' attribute
|
|
$().attr("foo","bar");//Sets the elements 'foo' attribute to 'bar'
|
|
$().attr("foo",{bar:'bar'}) //Adds the object to an internal cache
|
|
```
|
|
|
|
* @param {String|Object} attribute to act upon. If it's an object (hashmap), it will set the attributes based off the kvp.
|
|
* @param {String|Array|Object|function} [value] to set
|
|
* @return {String|Object|Array|Function} If used as a getter, return the attribute value. If a setter, return a jqMobi object
|
|
* @title $().attr(attribute,[value])
|
|
*/
|
|
attr: function(attr, value) {
|
|
if (this.length === 0)
|
|
return undefined;
|
|
if (value === undefined && !$.isObject(attr)) {
|
|
|
|
var val = (this[0].jqmCacheId&&_attrCache[this[0].jqmCacheId][attr])?(this[0].jqmCacheId&&_attrCache[this[0].jqmCacheId][attr]):this[0].getAttribute(attr);
|
|
return val;
|
|
}
|
|
for (var i = 0; i < this.length; i++) {
|
|
if ($.isObject(attr)) {
|
|
for (var key in attr) {
|
|
$(this[i]).attr(key,attr[key]);
|
|
}
|
|
}
|
|
else if($.isArray(value)||$.isObject(value)||$.isFunction(value))
|
|
{
|
|
|
|
if(!this[i].jqmCacheId)
|
|
this[i].jqmCacheId=$.uuid();
|
|
|
|
if(!_attrCache[this[i].jqmCacheId])
|
|
_attrCache[this[i].jqmCacheId]={}
|
|
_attrCache[this[i].jqmCacheId][attr]=value;
|
|
}
|
|
else if (value == null && value !== undefined)
|
|
{
|
|
this[i].removeAttribute(attr);
|
|
if(this[i].jqmCacheId&&_attrCache[this[i].jqmCacheId][attr])
|
|
delete _attrCache[this[i].jqmCacheId][attr];
|
|
}
|
|
else{
|
|
this[i].setAttribute(attr, value);
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Removes an attribute on the elements
|
|
```
|
|
$().removeAttr("foo");
|
|
```
|
|
|
|
* @param {String} attributes that can be space delimited
|
|
* @return {Object} jqMobi object
|
|
* @title $().removeAttr(attribute)
|
|
*/
|
|
removeAttr: function(attr) {
|
|
var that = this;
|
|
for (var i = 0; i < this.length; i++) {
|
|
attr.split(/\s+/g).forEach(function(param) {
|
|
that[i].removeAttribute(param);
|
|
if(that[i].jqmCacheId&&_attrCache[that[i].jqmCacheId][attr])
|
|
delete _attrCache[that[i].jqmCacheId][attr];
|
|
});
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Removes elements based off a selector
|
|
```
|
|
$().remove(".foo");//Remove off a string selector
|
|
var element=$("#foo").get();
|
|
$().remove(element); //Remove by an element
|
|
$().remove($(".foo")); //Remove by a collection
|
|
```
|
|
|
|
* @param {String|Object|Array} selector to filter against
|
|
* @return {Object} jqMobi object
|
|
* @title $().remove(selector)
|
|
*/
|
|
remove: function(selector) {
|
|
var elems = $(this).filter(selector);
|
|
if (elems == undefined)
|
|
return this;
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].parentNode.removeChild(elems[i]);
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Adds a css class to elements.
|
|
```
|
|
$().addClass("selected");
|
|
```
|
|
|
|
* @param {String} classes that are space delimited
|
|
* @return {Object} jqMobi object
|
|
* @title $().addClass(name)
|
|
*/
|
|
addClass: function(name) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
var cls = this[i].className;
|
|
var classList = [];
|
|
var that = this;
|
|
name.split(/\s+/g).forEach(function(cname) {
|
|
if (!that.hasClass(cname, that[i]))
|
|
classList.push(cname);
|
|
});
|
|
|
|
this[i].className += (cls ? " " : "") + classList.join(" ");
|
|
this[i].className = this[i].className.trim();
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Removes a css class from elements.
|
|
```
|
|
$().removeClass("foo"); //single class
|
|
$().removeClass("foo selected");//remove multiple classess
|
|
```
|
|
|
|
* @param {String} classes that are space delimited
|
|
* @return {Object} jqMobi object
|
|
* @title $().removeClass(name)
|
|
*/
|
|
removeClass: function(name) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (name == undefined) {
|
|
this[i].className = '';
|
|
return this;
|
|
}
|
|
var classList = this[i].className;
|
|
name.split(/\s+/g).forEach(function(cname) {
|
|
classList = classList.replace(classRE(cname), " ");
|
|
});
|
|
if (classList.length > 0)
|
|
this[i].className = classList.trim();
|
|
else
|
|
this[i].className = "";
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Checks to see if an element has a class.
|
|
```
|
|
$().hasClass('foo');
|
|
$().hasClass('foo',element);
|
|
```
|
|
|
|
* @param {String} class name to check against
|
|
* @param {Object} [element] to check against
|
|
* @return {Boolean}
|
|
* @title $().hasClass(name,[element])
|
|
*/
|
|
hasClass: function(name, element) {
|
|
if (this.length === 0)
|
|
return false;
|
|
if (!element)
|
|
element = this[0];
|
|
return classRE(name).test(element.className);
|
|
},
|
|
/**
|
|
* Appends to the elements
|
|
* We boil everything down to a jqMobi object and then loop through that.
|
|
* If it's HTML, we create a dom element so we do not break event bindings.
|
|
* if it's a script tag, we evaluate it.
|
|
```
|
|
$().append("<div></div>"); //Creates the object from the string and appends it
|
|
$().append($("#foo")); //Append an object;
|
|
```
|
|
|
|
* @param {String|Object} Element/string to add
|
|
* @param {Boolean} [insert] insert or append
|
|
* @return {Object} jqMobi object
|
|
* @title $().append(element,[insert])
|
|
*/
|
|
append: function(element, insert) {
|
|
if (element && element.length != undefined && element.length === 0)
|
|
return this;
|
|
if ($.isArray(element) || $.isObject(element))
|
|
element = $(element);
|
|
var i;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
if (element.length && typeof element != "string") {
|
|
element = $(element);
|
|
for (var j = 0; j < element.length; j++)
|
|
insert != undefined ? this[i].insertBefore(element[j], this[i].firstChild) : this[i].appendChild(element[j]);
|
|
} else {
|
|
var obj =fragementRE.test(element)?$(element):undefined;
|
|
if (obj == undefined || obj.length == 0) {
|
|
obj = document.createTextNode(element);
|
|
}
|
|
if (obj.nodeName != undefined && obj.nodeName.toLowerCase() == "script" && (!obj.type || obj.type.toLowerCase() === 'text/javascript')) {
|
|
window.eval(obj.innerHTML);
|
|
} else if(obj instanceof $jqm) {
|
|
for(var k=0;k<obj.length;k++)
|
|
{
|
|
insert != undefined ? this[i].insertBefore(obj[k], this[i].firstChild) : this[i].appendChild(obj[k]);
|
|
}
|
|
}
|
|
else {
|
|
insert != undefined ? this[i].insertBefore(obj, this[i].firstChild) : this[i].appendChild(obj);
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Prepends to the elements
|
|
* This simply calls append and sets insert to true
|
|
```
|
|
$().prepend("<div></div>");//Creates the object from the string and appends it
|
|
$().prepend($("#foo")); //Prepends an object
|
|
```
|
|
|
|
* @param {String|Object} Element/string to add
|
|
* @return {Object} jqMobi object
|
|
* @title $().prepend(element)
|
|
*/
|
|
prepend: function(element) {
|
|
return this.append(element, 1);
|
|
},
|
|
/**
|
|
* Inserts collection before the target (adjacent)
|
|
```
|
|
$().insertBefore(jq("#target"));
|
|
```
|
|
|
|
* @param {String|Object} Target
|
|
* @title $().insertBefore(target);
|
|
*/
|
|
insertBefore: function(target, after) {
|
|
if (this.length == 0)
|
|
return this;
|
|
target = $(target).get(0);
|
|
if (!target || target.length == 0)
|
|
return this;
|
|
for (var i = 0; i < this.length; i++)
|
|
{
|
|
after ? target.parentNode.insertBefore(this[i], target.nextSibling) : target.parentNode.insertBefore(this[i], target);
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* Inserts collection after the target (adjacent)
|
|
```
|
|
$().insertAfter(jq("#target"));
|
|
```
|
|
* @param {String|Object} target
|
|
* @title $().insertAfter(target);
|
|
*/
|
|
insertAfter: function(target) {
|
|
this.insertBefore(target, true);
|
|
},
|
|
/**
|
|
* Returns the raw DOM element.
|
|
```
|
|
$().get(); //returns the first element
|
|
$().get(2);// returns the third element
|
|
```
|
|
|
|
* @param {Int} [index]
|
|
* @return {Object} raw DOM element
|
|
* @title $().get([index])
|
|
*/
|
|
get: function(index) {
|
|
index = index == undefined ? 0 : index;
|
|
if (index < 0)
|
|
index += this.length;
|
|
return (this[index]) ? this[index] : undefined;
|
|
},
|
|
/**
|
|
* Returns the offset of the element, including traversing up the tree
|
|
```
|
|
$().offset();
|
|
```
|
|
|
|
* @return {Object} with left, top, width and height properties
|
|
* @title $().offset()
|
|
*/
|
|
offset: function() {
|
|
if (this.length === 0)
|
|
return undefined;
|
|
var obj = this[0].getBoundingClientRect();
|
|
return {
|
|
left: obj.left + window.pageXOffset,
|
|
top: obj.top + window.pageYOffset,
|
|
width: parseInt(this[0].style.width),
|
|
height: parseInt(this[0].style.height)
|
|
};
|
|
},
|
|
/**
|
|
* Returns the parent nodes of the elements based off the selector
|
|
```
|
|
$("#foo").parent('.bar');
|
|
$("#foo").parent($('.bar'));
|
|
$("#foo").parent($('.bar').get());
|
|
```
|
|
|
|
* @param {String|Array|Object} [selector]
|
|
* @return {Object} jqMobi object with unique parents
|
|
* @title $().parent(selector)
|
|
*/
|
|
parent: function(selector) {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
var elems = [];
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (this[i].parentNode)
|
|
elems.push(this[i].parentNode);
|
|
}
|
|
return this.setupOld($(unique(elems)).filter(selector));
|
|
},
|
|
/**
|
|
* Returns the child nodes of the elements based off the selector
|
|
```
|
|
$("#foo").children('.bar'); //Selector
|
|
$("#foo").children($('.bar')); //Objects
|
|
$("#foo").children($('.bar').get()); //Single element
|
|
```
|
|
|
|
* @param {String|Array|Object} [selector]
|
|
* @return {Object} jqMobi object with unique children
|
|
* @title $().children(selector)
|
|
*/
|
|
children: function(selector) {
|
|
|
|
if (this.length == 0)
|
|
return undefined;
|
|
var elems = [];
|
|
for (var i = 0; i < this.length; i++) {
|
|
elems = elems.concat(siblings(this[i].firstChild));
|
|
}
|
|
return this.setupOld($((elems)).filter(selector));
|
|
|
|
},
|
|
/**
|
|
* Returns the siblings of the element based off the selector
|
|
```
|
|
$("#foo").siblings('.bar'); //Selector
|
|
$("#foo").siblings($('.bar')); //Objects
|
|
$("#foo").siblings($('.bar').get()); //Single element
|
|
```
|
|
|
|
* @param {String|Array|Object} [selector]
|
|
* @return {Object} jqMobi object with unique siblings
|
|
* @title $().siblings(selector)
|
|
*/
|
|
siblings: function(selector) {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
var elems = [];
|
|
for (var i = 0; i < this.length; i++) {
|
|
if (this[i].parentNode)
|
|
elems = elems.concat(siblings(this[i].parentNode.firstChild, this[i]));
|
|
}
|
|
return this.setupOld($(elems).filter(selector));
|
|
},
|
|
/**
|
|
* Returns the closest element based off the selector and optional context
|
|
```
|
|
$("#foo").closest('.bar'); //Selector
|
|
$("#foo").closest($('.bar')); //Objects
|
|
$("#foo").closest($('.bar').get()); //Single element
|
|
```
|
|
|
|
* @param {String|Array|Object} selector
|
|
* @param {Object} [context]
|
|
* @return {Object} Returns a jqMobi object with the closest element based off the selector
|
|
* @title $().closest(selector,[context]);
|
|
*/
|
|
closest: function(selector, context) {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
var elems = [],
|
|
cur = this[0];
|
|
|
|
var start = $(selector, context);
|
|
if (start.length == 0)
|
|
return $();
|
|
while (cur && start.indexOf(cur) == -1) {
|
|
cur = cur !== context && cur !== document && cur.parentNode;
|
|
}
|
|
return $(cur);
|
|
|
|
},
|
|
/**
|
|
* Filters elements based off the selector
|
|
```
|
|
$("#foo").filter('.bar'); //Selector
|
|
$("#foo").filter($('.bar')); //Objects
|
|
$("#foo").filter($('.bar').get()); //Single element
|
|
```
|
|
|
|
* @param {String|Array|Object} selector
|
|
* @return {Object} Returns a jqMobi object after the filter was run
|
|
* @title $().filter(selector);
|
|
*/
|
|
filter: function(selector) {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
|
|
if (selector == undefined)
|
|
return this;
|
|
var elems = [];
|
|
for (var i = 0; i < this.length; i++) {
|
|
var val = this[i];
|
|
if (val.parentNode && $(selector, val.parentNode).indexOf(val) >= 0)
|
|
elems.push(val);
|
|
}
|
|
return this.setupOld($(unique(elems)));
|
|
},
|
|
/**
|
|
* Basically the reverse of filter. Return all elements that do NOT match the selector
|
|
```
|
|
$("#foo").not('.bar'); //Selector
|
|
$("#foo").not($('.bar')); //Objects
|
|
$("#foo").not($('.bar').get()); //Single element
|
|
```
|
|
|
|
* @param {String|Array|Object} selector
|
|
* @return {Object} Returns a jqMobi object after the filter was run
|
|
* @title $().not(selector);
|
|
*/
|
|
not: function(selector) {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
var elems = [];
|
|
for (var i = 0; i < this.length; i++) {
|
|
var val = this[i];
|
|
if (val.parentNode && $(selector, val.parentNode).indexOf(val) == -1)
|
|
elems.push(val);
|
|
}
|
|
return this.setupOld($(unique(elems)));
|
|
},
|
|
/**
|
|
* Gets or set data-* attribute parameters on elements
|
|
* When used as a getter, it's only the first element
|
|
```
|
|
$().data("foo"); //Gets the data-foo attribute for the first element
|
|
$().data("foo","bar"); //Sets the data-foo attribute for all elements
|
|
$().data("foo",{bar:'bar'});//object as the data
|
|
```
|
|
|
|
* @param {String} key
|
|
* @param {String|Array|Object} value
|
|
* @return {String|Object} returns the value or jqMobi object
|
|
* @title $().data(key,[value]);
|
|
*/
|
|
data: function(key, value) {
|
|
return this.attr('data-' + key, value);
|
|
},
|
|
/**
|
|
* Rolls back the jqMobi elements when filters were applied
|
|
* This can be used after .not(), .filter(), .children(), .parent()
|
|
```
|
|
$().filter(".panel").end(); //This will return the collection BEFORE filter is applied
|
|
```
|
|
|
|
* @return {Object} returns the previous jqMobi object before filter was applied
|
|
* @title $().end();
|
|
*/
|
|
end: function() {
|
|
return this.oldElement != undefined ? this.oldElement : $();
|
|
},
|
|
/**
|
|
* Clones the nodes in the collection.
|
|
```
|
|
$().clone();// Deep clone of all elements
|
|
$().clone(false); //Shallow clone
|
|
```
|
|
|
|
* @param {Boolean} [deep] - do a deep copy or not
|
|
* @return {Object} jqMobi object of cloned nodes
|
|
* @title $().clone();
|
|
*/
|
|
clone: function(deep) {
|
|
deep = deep === false ? false : true;
|
|
if (this.length == 0)
|
|
return undefined;
|
|
var elems = [];
|
|
for (var i = 0; i < this.length; i++) {
|
|
elems.push(this[i].cloneNode(deep));
|
|
}
|
|
|
|
return $(elems);
|
|
},
|
|
/**
|
|
* Returns the number of elements in the collection
|
|
```
|
|
$().size();
|
|
```
|
|
|
|
* @return {Int}
|
|
* @title $().size();
|
|
*/
|
|
size: function() {
|
|
return this.length;
|
|
},
|
|
/**
|
|
* Serailizes a form into a query string
|
|
```
|
|
$().serialize(grouping);
|
|
```
|
|
* @param {String} [grouping] - optional grouping to the fields -e.g users[name]
|
|
* @return {String}
|
|
* @title $().serialize(grouping)
|
|
*/
|
|
serialize: function(grouping) {
|
|
if (this.length == 0)
|
|
return "";
|
|
var params = {};
|
|
for (var i = 0; i < this.length; i++)
|
|
{
|
|
this.slice.call(this[i].elements).forEach(function(elem) {
|
|
var type = elem.getAttribute("type");
|
|
if (elem.nodeName.toLowerCase() != "fieldset" && !elem.disabled && type != "submit"
|
|
&& type != "reset" && type != "button" && ((type != "radio" && type != "checkbox") || elem.checked))
|
|
params[elem.getAttribute("name")] = elem.value;
|
|
});
|
|
}
|
|
return $.param(params,grouping);
|
|
}
|
|
};
|
|
|
|
|
|
/* AJAX functions */
|
|
|
|
function empty() {
|
|
}
|
|
var ajaxSettings = {
|
|
type: 'GET',
|
|
beforeSend: empty,
|
|
success: empty,
|
|
error: empty,
|
|
complete: empty,
|
|
context: undefined,
|
|
timeout: 0,
|
|
crossDomain:false
|
|
};
|
|
/**
|
|
* Execute a jsonP call, allowing cross domain scripting
|
|
* options.url - URL to call
|
|
* options.success - Success function to call
|
|
* options.error - Error function to call
|
|
```
|
|
$.jsonP({url:'mysite.php?callback=?&foo=bar',success:function(){},error:function(){}});
|
|
```
|
|
|
|
* @param {Object} options
|
|
* @title $.jsonP(options)
|
|
*/
|
|
$.jsonP = function(options) {
|
|
var callbackName = 'jsonp_callback' + (++_jsonPID);
|
|
var abortTimeout = "",
|
|
context;
|
|
var script = document.createElement("script");
|
|
var abort = function() {
|
|
$(script).remove();
|
|
if (window[callbackName])
|
|
window[callbackName] = empty;
|
|
};
|
|
window[callbackName] = function(data) {
|
|
clearTimeout(abortTimeout);
|
|
$(script).remove();
|
|
delete window[callbackName];
|
|
options.success.call(context, data);
|
|
};
|
|
script.src = options.url.replace(/=\?/, '=' + callbackName);
|
|
if(options.error)
|
|
{
|
|
script.onerror=function(){
|
|
clearTimeout(abortTimeout);
|
|
options.error.call(context, "", 'error');
|
|
}
|
|
}
|
|
$('head').append(script);
|
|
if (options.timeout > 0)
|
|
abortTimeout = setTimeout(function() {
|
|
options.error.call(context, "", 'timeout');
|
|
}, options.timeout);
|
|
return {};
|
|
};
|
|
|
|
/**
|
|
* Execute an Ajax call with the given options
|
|
* options.type - Type of request
|
|
* options.beforeSend - function to execute before sending the request
|
|
* options.success - success callback
|
|
* options.error - error callback
|
|
* options.complete - complete callback - callled with a success or error
|
|
* options.timeout - timeout to wait for the request
|
|
* options.url - URL to make request against
|
|
* options.contentType - HTTP Request Content Type
|
|
* options.headers - Object of headers to set
|
|
* options.dataType - Data type of request
|
|
* options.data - data to pass into request. $.param is called on objects
|
|
```
|
|
var opts={
|
|
type:"GET",
|
|
success:function(data){},
|
|
url:"mypage.php",
|
|
data:{bar:'bar'},
|
|
}
|
|
$.ajax(opts);
|
|
```
|
|
|
|
* @param {Object} options
|
|
* @title $.ajax(options)
|
|
*/
|
|
$.ajax = function(opts) {
|
|
var xhr;
|
|
try {
|
|
xhr = new window.XMLHttpRequest();
|
|
var settings = opts || {};
|
|
for (var key in ajaxSettings) {
|
|
if (!settings[key])
|
|
settings[key] = ajaxSettings[key];
|
|
}
|
|
|
|
if (!settings.url)
|
|
settings.url = window.location;
|
|
if (!settings.contentType)
|
|
settings.contentType = "application/x-www-form-urlencoded";
|
|
if (!settings.headers)
|
|
settings.headers = {};
|
|
|
|
if (!settings.dataType)
|
|
settings.dataType = "text/html";
|
|
else {
|
|
switch (settings.dataType) {
|
|
case "script":
|
|
settings.dataType = 'text/javascript, application/javascript';
|
|
break;
|
|
case "json":
|
|
settings.dataType = 'application/json';
|
|
break;
|
|
case "xml":
|
|
settings.dataType = 'application/xml, text/xml';
|
|
break;
|
|
case "html":
|
|
settings.dataType = 'text/html';
|
|
break;
|
|
case "text":
|
|
settings.dataType = 'text/plain';
|
|
break;
|
|
default:
|
|
settings.dataType = "text/html";
|
|
break;
|
|
case "jsonp":
|
|
return $.jsonP(opts);
|
|
break;
|
|
}
|
|
}
|
|
if ($.isObject(settings.data))
|
|
settings.data = $.param(settings.data);
|
|
if (settings.type.toLowerCase() === "get" && settings.data) {
|
|
if (settings.url.indexOf("?") === -1)
|
|
settings.url += "?" + settings.data;
|
|
else
|
|
settings.url += "&" + settings.data;
|
|
}
|
|
|
|
if (/=\?/.test(settings.url)) {
|
|
return $.jsonP(settings);
|
|
}
|
|
|
|
if (!settings.crossDomain) settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) &&
|
|
RegExp.$2 != window.location.host;
|
|
|
|
if(!settings.crossDomain)
|
|
settings.headers = $.extend({'X-Requested-With': 'XMLHttpRequest'}, settings.headers);
|
|
var abortTimeout;
|
|
var context = settings.context;
|
|
var protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol;
|
|
xhr.onreadystatechange = function() {
|
|
var mime = settings.dataType;
|
|
if (xhr.readyState === 4) {
|
|
clearTimeout(abortTimeout);
|
|
var result, error = false;
|
|
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0&&protocol=='file:') {
|
|
if (mime === 'application/json' && !(/^\s*$/.test(xhr.responseText))) {
|
|
try {
|
|
result = JSON.parse(xhr.responseText);
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
} else
|
|
result = xhr.responseText;
|
|
//If we're looking at a local file, we assume that no response sent back means there was an error
|
|
if(xhr.status===0&&result.length===0)
|
|
error=true;
|
|
if (error)
|
|
settings.error.call(context, xhr, 'parsererror', error);
|
|
else {
|
|
settings.success.call(context, result, 'success', xhr);
|
|
}
|
|
} else {
|
|
error = true;
|
|
settings.error.call(context, xhr, 'error');
|
|
}
|
|
settings.complete.call(context, xhr, error ? 'error' : 'success');
|
|
}
|
|
};
|
|
xhr.open(settings.type, settings.url, true);
|
|
|
|
if (settings.contentType)
|
|
settings.headers['Content-Type'] = settings.contentType;
|
|
for (var name in settings.headers)
|
|
xhr.setRequestHeader(name, settings.headers[name]);
|
|
if (settings.beforeSend.call(context, xhr, settings) === false) {
|
|
xhr.abort();
|
|
return false;
|
|
}
|
|
|
|
if (settings.timeout > 0)
|
|
abortTimeout = setTimeout(function() {
|
|
xhr.onreadystatechange = empty;
|
|
xhr.abort();
|
|
settings.error.call(context, xhr, 'timeout');
|
|
}, settings.timeout);
|
|
xhr.send(settings.data);
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
return xhr;
|
|
};
|
|
|
|
|
|
/**
|
|
* Shorthand call to an Ajax GET request
|
|
```
|
|
$.get("mypage.php?foo=bar",function(data){});
|
|
```
|
|
|
|
* @param {String} url to hit
|
|
* @param {Function} success
|
|
* @title $.get(url,success)
|
|
*/
|
|
$.get = function(url, success) {
|
|
return this.ajax({
|
|
url: url,
|
|
success: success
|
|
});
|
|
};
|
|
/**
|
|
* Shorthand call to an Ajax POST request
|
|
```
|
|
$.post("mypage.php",{bar:'bar'},function(data){});
|
|
```
|
|
|
|
* @param {String} url to hit
|
|
* @param {Object} [data] to pass in
|
|
* @param {Function} success
|
|
* @param {String} [dataType]
|
|
* @title $.post(url,[data],success,[dataType])
|
|
*/
|
|
$.post = function(url, data, success, dataType) {
|
|
if (typeof (data) === "function") {
|
|
success = data;
|
|
data = {};
|
|
}
|
|
if (dataType === undefined)
|
|
dataType = "html";
|
|
return this.ajax({
|
|
url: url,
|
|
type: "POST",
|
|
data: data,
|
|
dataType: dataType,
|
|
success: success
|
|
});
|
|
};
|
|
/**
|
|
* Shorthand call to an Ajax request that expects a JSON response
|
|
```
|
|
$.getJSON("mypage.php",{bar:'bar'},function(data){});
|
|
```
|
|
|
|
* @param {String} url to hit
|
|
* @param {Object} [data]
|
|
* @param {Function} [success]
|
|
* @title $.getJSON(url,data,success)
|
|
*/
|
|
$.getJSON = function(url, data, success) {
|
|
if (typeof (data) === "function") {
|
|
success = data;
|
|
data = {};
|
|
}
|
|
return this.ajax({
|
|
url: url,
|
|
data: data,
|
|
success: success,
|
|
dataType: "json"
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Converts an object into a key/value par with an optional prefix. Used for converting objects to a query string
|
|
```
|
|
var obj={
|
|
foo:'foo',
|
|
bar:'bar'
|
|
}
|
|
var kvp=$.param(obj,'data');
|
|
```
|
|
|
|
* @param {Object} object
|
|
* @param {String} [prefix]
|
|
* @return {String} Key/value pair representation
|
|
* @title $.param(object,[prefix];
|
|
*/
|
|
$.param = function(obj, prefix) {
|
|
var str = [];
|
|
if (obj instanceof $jqm) {
|
|
obj.each(function() {
|
|
var k = prefix ? prefix + "[]" : this.id,
|
|
v = this.value;
|
|
str.push((k) + "=" + encodeURIComponent(v));
|
|
});
|
|
} else {
|
|
for (var p in obj) {
|
|
var k = prefix ? prefix + "[" + p + "]" : p,
|
|
v = obj[p];
|
|
str.push($.isObject(v) ? $.param(v, k) : (k) + "=" + encodeURIComponent(v));
|
|
}
|
|
}
|
|
return str.join("&");
|
|
};
|
|
/**
|
|
* Used for backwards compatibility. Uses native JSON.parse function
|
|
```
|
|
var obj=$.parseJSON("{\"bar\":\"bar\"}");
|
|
```
|
|
|
|
* @params {String} string
|
|
* @return {Object}
|
|
* @title $.parseJSON(string)
|
|
*/
|
|
$.parseJSON = function(string) {
|
|
return JSON.parse(string);
|
|
};
|
|
/**
|
|
* Helper function to convert XML into the DOM node representation
|
|
```
|
|
var xmlDoc=$.parseXML("<xml><foo>bar</foo></xml>");
|
|
```
|
|
|
|
* @param {String} string
|
|
* @return {Object} DOM nodes
|
|
* @title $.parseXML(string)
|
|
*/
|
|
$.parseXML = function(string) {
|
|
return (new DOMParser).parseFromString(string, "text/xml");
|
|
};
|
|
/**
|
|
* Helper function to parse the user agent. Sets the following
|
|
* .os.webkit
|
|
* .os.android
|
|
* .os.ipad
|
|
* .os.iphone
|
|
* .os.webos
|
|
* .os.touchpad
|
|
* .os.blackberry
|
|
* .os.opera
|
|
* .os.fennec
|
|
* @api private
|
|
*/
|
|
function detectUA($, userAgent) {
|
|
$.os = {};
|
|
$.os.webkit = userAgent.match(/WebKit\/([\d.]+)/) ? true : false;
|
|
$.os.android = userAgent.match(/(Android)\s+([\d.]+)/) || userAgent.match(/Silk-Accelerated/) ? true : false;
|
|
$.os.ipad = userAgent.match(/(iPad).*OS\s([\d_]+)/) ? true : false;
|
|
$.os.iphone = !$.os.ipad && userAgent.match(/(iPhone\sOS)\s([\d_]+)/) ? true : false;
|
|
$.os.webos = userAgent.match(/(webOS|hpwOS)[\s\/]([\d.]+)/) ? true : false;
|
|
$.os.touchpad = $.os.webos && userAgent.match(/TouchPad/) ? true : false;
|
|
$.os.ios = $.os.ipad || $.os.iphone;
|
|
$.os.blackberry = userAgent.match(/BlackBerry/) || userAgent.match(/PlayBook/) ? true : false;
|
|
$.os.opera = userAgent.match(/Opera Mobi/) ? true : false;
|
|
$.os.fennec = userAgent.match(/fennec/i) ? true : false;
|
|
$.os.desktop = !($.os.ios || $.os.android || $.os.blackberry || $.os.opera || $.os.fennec);
|
|
}
|
|
detectUA($, navigator.userAgent);
|
|
$.__detectUA = detectUA; //needed for unit tests
|
|
if (typeof String.prototype.trim !== 'function') {
|
|
|
|
/**
|
|
* Helper function for iOS 3.1.3
|
|
*/
|
|
String.prototype.trim = function() {
|
|
this.replace(/(\r\n|\n|\r)/gm, "").replace(/^\s+|\s+$/, '');
|
|
return this
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Utility function to create a psuedo GUID
|
|
```
|
|
var id= $.uuid();
|
|
```
|
|
* @title $.uuid
|
|
*/
|
|
$.uuid = function () {
|
|
var S4 = function () {
|
|
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
|
}
|
|
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
|
};
|
|
/**
|
|
Zepto.js events
|
|
@api private
|
|
*/
|
|
|
|
//The following is modified from Zepto.js / events.js
|
|
//We've removed depricated jQuery events like .live and allow anonymous functions to be removed
|
|
var $$ = $.qsa,
|
|
handlers = {},
|
|
_jqmid = 1,
|
|
specialEvents = {};
|
|
/**
|
|
* Gets or sets the expando property on a javascript element
|
|
* Also increments the internal counter for elements;
|
|
* @param {Object} element
|
|
* @return {Int} jqmid
|
|
* @api private
|
|
*/
|
|
function jqmid(element) {
|
|
return element._jqmid || (element._jqmid = _jqmid++);
|
|
}
|
|
/**
|
|
* Searches through a local array that keeps track of event handlers for proxying.
|
|
* Since we listen for multiple events, we match up the event, function and selector.
|
|
* This is used to find, execute, remove proxied event functions
|
|
* @param {Object} element
|
|
* @param {String} [event]
|
|
* @param {Function} [function]
|
|
* @param {String|Object|Array} [selector]
|
|
* @return {Function|null} handler function or false if not found
|
|
* @api private
|
|
*/
|
|
function findHandlers(element, event, fn, selector) {
|
|
event = parse(event);
|
|
if (event.ns)
|
|
var matcher = matcherFor(event.ns);
|
|
return (handlers[jqmid(element)] || []).filter(function(handler) {
|
|
return handler && (!event.e || handler.e == event.e) && (!event.ns || matcher.test(handler.ns)) && (!fn || handler.fn == fn || (typeof handler.fn === 'function' && typeof fn === 'function' && "" + handler.fn === "" + fn)) && (!selector || handler.sel == selector);
|
|
});
|
|
}
|
|
/**
|
|
* Splits an event name by "." to look for namespaces (e.g touch.click)
|
|
* @param {String} event
|
|
* @return {Object} an object with the event name and namespace
|
|
* @api private
|
|
*/
|
|
function parse(event) {
|
|
var parts = ('' + event).split('.');
|
|
return {
|
|
e: parts[0],
|
|
ns: parts.slice(1).sort().join(' ')
|
|
};
|
|
}
|
|
/**
|
|
* Regular expression checker for event namespace checking
|
|
* @param {String} namespace
|
|
* @return {Regex} regular expression
|
|
* @api private
|
|
*/
|
|
function matcherFor(ns) {
|
|
return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)');
|
|
}
|
|
|
|
/**
|
|
* Utility function that will loop through events that can be a hash or space delimited and executes the function
|
|
* @param {String|Object} events
|
|
* @param {Function} fn
|
|
* @param {Iterator} [iterator]
|
|
* @api private
|
|
*/
|
|
function eachEvent(events, fn, iterator) {
|
|
if ($.isObject(events))
|
|
$.each(events, iterator);
|
|
else
|
|
events.split(/\s/).forEach(function(type) {
|
|
iterator(type, fn)
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper function for adding an event and creating the proxy handler function.
|
|
* All event handlers call this to wire event listeners up. We create proxy handlers so they can be removed then.
|
|
* This is needed for delegate/on
|
|
* @param {Object} element
|
|
* @param {String|Object} events
|
|
* @param {Function} function that will be executed when event triggers
|
|
* @param {String|Array|Object} [selector]
|
|
* @param {Boolean} [getDelegate]
|
|
* @api private
|
|
*/
|
|
function add(element, events, fn, selector, getDelegate) {
|
|
var id = jqmid(element),
|
|
set = (handlers[id] || (handlers[id] = []));
|
|
|
|
eachEvent(events, fn, function(event, fn) {
|
|
var delegate = getDelegate && getDelegate(fn, event),
|
|
callback = delegate || fn;
|
|
var proxyfn = function(event) {
|
|
var result = callback.apply(element, [event].concat(event.data));
|
|
if (result === false)
|
|
event.preventDefault();
|
|
return result;
|
|
};
|
|
var handler = $.extend(parse(event), {
|
|
fn: fn,
|
|
proxy: proxyfn,
|
|
sel: selector,
|
|
del: delegate,
|
|
i: set.length
|
|
});
|
|
set.push(handler);
|
|
element.addEventListener(handler.e, proxyfn, false);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper function to remove event listeners. We look through each event and then the proxy handler array to see if it exists
|
|
* If found, we remove the listener and the entry from the proxy array. If no function is specified, we remove all listeners that match
|
|
* @param {Object} element
|
|
* @param {String|Object} events
|
|
* @param {Function} [fn]
|
|
* @param {String|Array|Object} [selector]
|
|
* @api private
|
|
*/
|
|
function remove(element, events, fn, selector) {
|
|
|
|
var id = jqmid(element);
|
|
eachEvent(events || '', fn, function(event, fn) {
|
|
findHandlers(element, event, fn, selector).forEach(function(handler) {
|
|
delete handlers[id][handler.i];
|
|
element.removeEventListener(handler.e, handler.proxy, false);
|
|
});
|
|
});
|
|
}
|
|
|
|
$.event = {
|
|
add: add,
|
|
remove: remove
|
|
}
|
|
|
|
/**
|
|
* Binds an event to each element in the collection and executes the callback
|
|
```
|
|
$().bind('click',function(){console.log('I clicked '+this.id);});
|
|
```
|
|
|
|
* @param {String|Object} event
|
|
* @param {Function} callback
|
|
* @return {Object} jqMobi object
|
|
* @title $().bind(event,callback)
|
|
*/
|
|
$.fn.bind = function(event, callback) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
add(this[i], event, callback);
|
|
}
|
|
return this;
|
|
};
|
|
/**
|
|
* Unbinds an event to each element in the collection. If a callback is passed in, we remove just that one, otherwise we remove all callbacks for those events
|
|
```
|
|
$().unbind('click'); //Unbinds all click events
|
|
$().unbind('click',myFunc); //Unbinds myFunc
|
|
```
|
|
|
|
* @param {String|Object} event
|
|
* @param {Function} [callback]
|
|
* @return {Object} jqMobi object
|
|
* @title $().unbind(event,[callback]);
|
|
*/
|
|
$.fn.unbind = function(event, callback) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
remove(this[i], event, callback);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Binds an event to each element in the collection that will only execute once. When it executes, we remove the event listener then right away so it no longer happens
|
|
```
|
|
$().one('click',function(){console.log('I was clicked once');});
|
|
```
|
|
|
|
* @param {String|Object} event
|
|
* @param {Function} [callback]
|
|
* @return jqMobi object
|
|
* @title $().one(event,callback);
|
|
*/
|
|
$.fn.one = function(event, callback) {
|
|
return this.each(function(i, element) {
|
|
add(this, event, callback, null, function(fn, type) {
|
|
return function() {
|
|
var result = fn.apply(element, arguments);
|
|
remove(element, type, fn);
|
|
return result;
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* internal variables
|
|
* @api private
|
|
*/
|
|
|
|
var returnTrue = function() {
|
|
return true
|
|
},
|
|
returnFalse = function() {
|
|
return false
|
|
},
|
|
eventMethods = {
|
|
preventDefault: 'isDefaultPrevented',
|
|
stopImmediatePropagation: 'isImmediatePropagationStopped',
|
|
stopPropagation: 'isPropagationStopped'
|
|
};
|
|
/**
|
|
* Creates a proxy function for event handlers
|
|
* @param {String} event
|
|
* @return {Function} proxy
|
|
* @api private
|
|
*/
|
|
function createProxy(event) {
|
|
var proxy = $.extend({
|
|
originalEvent: event
|
|
}, event);
|
|
$.each(eventMethods, function(name, predicate) {
|
|
proxy[name] = function() {
|
|
this[predicate] = returnTrue;
|
|
return event[name].apply(event, arguments);
|
|
};
|
|
proxy[predicate] = returnFalse;
|
|
})
|
|
return proxy;
|
|
}
|
|
|
|
/**
|
|
* Delegate an event based off the selector. The event will be registered at the parent level, but executes on the selector.
|
|
```
|
|
$("#div").delegate("p",'click',callback);
|
|
```
|
|
|
|
* @param {String|Array|Object} selector
|
|
* @param {String|Object} event
|
|
* @param {Function} callback
|
|
* @return {Object} jqMobi object
|
|
* @title $().delegate(selector,event,callback)
|
|
*/
|
|
$.fn.delegate = function(selector, event, callback) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
var element = this[i];
|
|
add(element, event, callback, selector, function(fn) {
|
|
return function(e) {
|
|
var evt, match = $(e.target).closest(selector, element).get(0);
|
|
if (match) {
|
|
evt = $.extend(createProxy(e), {
|
|
currentTarget: match,
|
|
liveFired: element
|
|
});
|
|
return fn.apply(match, [evt].concat([].slice.call(arguments, 1)));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Unbinds events that were registered through delegate. It acts upon the selector and event. If a callback is specified, it will remove that one, otherwise it removes all of them.
|
|
```
|
|
$("#div").undelegate("p",'click',callback);//Undelegates callback for the click event
|
|
$("#div").undelegate("p",'click');//Undelegates all click events
|
|
```
|
|
|
|
* @param {String|Array|Object} selector
|
|
* @param {String|Object} event
|
|
* @param {Function} callback
|
|
* @return {Object} jqMobi object
|
|
* @title $().undelegate(selector,event,[callback]);
|
|
*/
|
|
$.fn.undelegate = function(selector, event, callback) {
|
|
for (var i = 0; i < this.length; i++) {
|
|
remove(this[i], event, callback, selector);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Similar to delegate, but the function parameter order is easier to understand.
|
|
* If selector is undefined or a function, we just call .bind, otherwise we use .delegate
|
|
```
|
|
$("#div").on("click","p",callback);
|
|
```
|
|
|
|
* @param {String|Array|Object} selector
|
|
* @param {String|Object} event
|
|
* @param {Function} callback
|
|
* @return {Object} jqMobi object
|
|
* @title $().on(event,selector,callback);
|
|
*/
|
|
$.fn.on = function(event, selector, callback) {
|
|
return selector === undefined || $.isFunction(selector) ? this.bind(event, selector) : this.delegate(selector, event, callback);
|
|
};
|
|
/**
|
|
* Removes event listeners for .on()
|
|
* If selector is undefined or a function, we call unbind, otherwise it's undelegate
|
|
```
|
|
$().off("click","p",callback); //Remove callback function for click events
|
|
$().off("click","p") //Remove all click events
|
|
```
|
|
|
|
* @param {String|Object} event
|
|
* @param {String|Array|Object} selector
|
|
* @param {Sunction} callback
|
|
* @return {Object} jqMobi object
|
|
* @title $().off(event,selector,[callback])
|
|
*/
|
|
$.fn.off = function(event, selector, callback) {
|
|
return selector === undefined || $.isFunction(selector) ? this.unbind(event, selector) : this.undelegate(selector, event, callback);
|
|
};
|
|
|
|
/**
|
|
This triggers an event to be dispatched. Usefull for emulating events, etc.
|
|
```
|
|
$().trigger("click",{foo:'bar'});//Trigger the click event and pass in data
|
|
```
|
|
|
|
* @param {String|Object} event
|
|
* @param {Object} [data]
|
|
* @return {Object} jqMobi object
|
|
* @title $().trigger(event,data);
|
|
*/
|
|
$.fn.trigger = function(event, data) {
|
|
if (typeof event == 'string')
|
|
event = $.Event(event);
|
|
event.data = data;
|
|
for (var i = 0; i < this.length; i++) {
|
|
this[i].dispatchEvent(event)
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Creates a custom event to be used internally.
|
|
* @param {String} type
|
|
* @param {Object} [properties]
|
|
* @return {event} a custom event that can then be dispatched
|
|
* @title $.Event(type,props);
|
|
*/
|
|
|
|
$.Event = function(type, props) {
|
|
var event = document.createEvent(specialEvents[type] || 'Events'),
|
|
bubbles = true;
|
|
if (props)
|
|
for (var name in props)
|
|
(name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name]);
|
|
event.initEvent(type, bubbles, true, null, null, null, null, null, null, null, null, null, null, null, null);
|
|
return event;
|
|
};
|
|
|
|
/**
|
|
* Creates a proxy function so you can change the 'this' context in the function
|
|
```
|
|
var newObj={foo:bar}
|
|
$("#main").bind("click",$.proxy(function(evt){console.log(this)},newObj);
|
|
```
|
|
|
|
* @param {Function} Callback
|
|
* @param {Object} Context
|
|
* @title $.proxy(callback,context);
|
|
*/
|
|
|
|
$.proxy=function(fnc,ctx){
|
|
var tmp=function(evt){
|
|
|
|
return fnc.call(ctx,evt);
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
/**
|
|
* End of APIS
|
|
* @api private
|
|
*/
|
|
|
|
//End zepto/events.js
|
|
return $;
|
|
|
|
})(window);
|
|
'$' in window || (window.$ = jq);
|
|
//Helper function used in jq.mobi.plugins.
|
|
if (!window.numOnly) {
|
|
window.numOnly = function numOnly(val) {
|
|
if (isNaN(parseFloat(val)))
|
|
val = val.replace(/[^0-9.-]/, "");
|
|
return parseFloat(val);
|
|
}
|
|
}
|
|
} |