/*! Copyright (c) 2012 Guo Kai, http://jsql.us/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* --------------- jSQL --------------- a SQL like database using javascript website: http://jsql.us licence: MIT Licence version: 0.7.1-dev description: using jSQL to process the data easily. */ (function() { var slice = Array.prototype.slice, toString = Object.prototype.toString, hasOwnProperty = Object.prototype.hasOwnProperty; var nativeForEach = Array.prototype.forEach, nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeIndexOf = Array.prototype.indexOf, nativeLastIndexOf = Array.prototype.lastIndexOf; var utils = {}; var jSQL_KEY_NAME = 'jSQL_Key'; var jSQL, _jSQL, _jsql, _DB = {}, _DBIndexMap = {}, _protected = {}, _events = {}; var interpolation = function(str) { var args = [].slice.call(arguments, 1); return str.replace(/%s/igm, function() { return args.shift() || ''; }); }; var logcat = { error: function(error) { error = interpolation.apply(this, arguments); if(typeof(console) !== 'undefined') { if(console.warn) { console.warn(error); return; } if(console.log) { console.log(error); return; } } throw(error); }, info: function(info) { info = interpolation.apply(this, arguments); if(typeof(console) !== 'undefined') { if(console.info) { console.info(info); return; } if(console.log) { console.log(info); return; } } } }; if(typeof(this.jSQL) !== 'undefined') { _jSQL = this.jSQL; } if(typeof(this.jsql) !== 'undefined') { _jsql = this.jsql; } jSQL = function() { this.init.apply(this, arguments); }; jSQL.prototype = { version: '0.7.1-dev', init: function() { this._jSQL = _jSQL; this._jsql = _jsql; this._DB = _DB; this._currentDB = null; this._buffer = null; this._currentDBName = null; this._DBIndexMap = _DBIndexMap; this._protected = _protected; this._indexList = null; this._events = _events; this.utils = utils; }, create: function(dbname, db /*, scope */) { var indexList; var that = this; if(this._DB.hasOwnProperty(dbname)) { logcat.error('DB Already Exist.'); } if(utils.isArray(db)) { indexList = utils.listSlice(arguments, '2:'); utils.appendKey(db, indexList); _DBIndexMap[dbname] = utils.arrayToObject(db); this._indexList = indexList || null; //remember indexList for insert/save } if(utils.isPlainObject(db)) { _DBIndexMap[dbname] = utils.clone(db); db = utils.objectToArray(db); } if(typeof(db) === 'string' && db.match(/^http(s)?:\/\//igm)) { var scope = arguments[2] || '*'; var proxyCallback = function(data) { db = typeof(scope) === 'function' ? scope.call(this, data) : scope === '*' ? data : utils.deep(data, scope); that._DB[dbname] = utils.clone(db); that._events[dbname] = that._events[dbname] || new that.Events(); that.trigger(dbname, 'create'); that.trigger(dbname, 'io:success'); that.trigger(dbname, 'io:complete'); }; var proxyFallback = function() { that._events[dbname] = that._events[dbname] || new that.Events(); that.trigger(dbname, 'io:error'); }; if(db.match('callback=')) { this.io.jsonp(db, {}, proxyCallback, proxyFallback); } else { this.io.ajax(db, {}, proxyCallback, proxyFallback); } this._events[dbname] = this._events[dbname] || new this.Events(); this.trigger(dbname, 'io:start'); return this; } this._DB[dbname] = utils.clone(db); this._events[dbname] = this._events[dbname] || new this.Events(); this.trigger(dbname, 'create'); return this; }, use: function(dbname) { if(!this._DB.hasOwnProperty(dbname)) { throw('Database Not Exist.'); } this._currentDB = this._DB[dbname]; this._currentDBName = dbname; this.rebase(); return this; }, drop: function(dbname) { if(this._DB.hasOwnProperty(dbname)) { delete this._DB[dbname]; this.trigger(dbname, 'drop'); } return this; }, dbs: function() { return utils.keys(this._DB); }, db: function() { return this._currentDBName; }, select: function(key) { if(!this._currentDB) { throw('Please Select Database First.'); } this._protected['field'] = [].slice.call(utils.isArray(key) ? key : arguments); if(key === '*') { return this; } return this; }, count: function() { var result; result = this._buffer.length; return result; }, total: function(scope) { var rs = 0, _tmp; for(var _key in this._currentDB) { if(this._currentDB.hasOwnProperty(_key)) { _tmp = scope === '*' ? this._currentDB[_key] : typeof(scope) === 'function' ? scope.call(this, this._currentDB[_key], _key) === true ? true : undefined : utils.deep(this._currentDB[_key], scope); if(typeof(_tmp) !== 'undefined') { rs++; } } } return rs; }, orderby: function(field, callback, order) { var _array = this._buffer; var _this = this; if(typeof(callback) !== 'function') { callback = [order, order = callback][0]; } _array.sort(function(a, b) { a = utils.deep(a, field); b = utils.deep(b, field); if(callback) { a = callback(a); b = callback(b); } return order && order.toLowerCase() === 'asc' ? a - b : b - a; }); this._buffer = _array; this._protected['sort'] = true; return this; }, where: function(fn) { var _tmp = [], _swap; this._buffer = this._buffer || this._currentDB; fn = utils.parseFn(fn); for(var i in this._buffer) { if(this._buffer.hasOwnProperty(i)) { if(typeof(fn) === 'function') { _swap = fn.call(this, utils.clone(this._buffer[i]), i); } if(utils.isArray(fn)) { _swap = false; for(var f in fn) { if(fn.hasOwnProperty(f)) { if(fn[f].call(this, utils.clone(this._buffer[i]), i)) { _swap = true; } } } } if(_swap) { _tmp.push(this._buffer[i]); } } } this._buffer = _tmp; return this; }, iterate: function(fn) { this._buffer = this._buffer || this._currentDB; for(var i in this._buffer) { if(this._buffer.hasOwnProperty(i)) { fn.call(this, this._buffer[i]); } } return this; }, findAll: function() { var result; result = utils.clone(utils.arrayToObject(this._select())); return result; }, find: function(key) { var result; var _tmp = this._DBIndexMap[this._currentDBName]; if(!key) { for(var i in _tmp) { if(_tmp.hasOwnProperty(i)) { if(key) { break; } if(this._buffer.hasOwnProperty(i)) { key = i; } } } } result = utils.clone(_tmp[key]); return result; }, listAll: function() { var result; result = utils.clone(this._select()); return result; }, update: function(fn) { var _swap = this.utils.arrayToObject(this._currentDB); var _tmp; this._buffer = this._buffer || this._currentDB; if(!this._currentDB) { throw('Please Select Database First.'); } for(var i in this._buffer) { if(this._buffer.hasOwnProperty(i)) { _tmp = fn.call(this, utils.clone(this._buffer[i])); if(_tmp) { _swap[this._buffer[i][jSQL_KEY_NAME]] = _tmp; } } } this._currentDB = this.utils.objectToArray(_swap); this._DB[this._currentDBName] = this.utils.objectToArray(_swap); this.trigger(this._currentDBName, 'update'); return this; }, insert: function(item, key /*, fromIndex */) { var item = utils.clone(item); var fromIndex = arguments[2]; item[jSQL_KEY_NAME] = item.key || key; fromIndex ? this._currentDB.splice(fromIndex, 0, item) : this._currentDB.push(item); this.trigger(this._currentDBName, 'update'); return this; }, append: function(database, data) { if(arguments.length > 1) { this.use(database); } else { data = arguments[0]; } data = utils.clone(data); if(utils.isArray(data)) { utils.appendKey(data, this._indexList); this._currentDB = this._currentDB.concat(data); } if(utils.isPlainObject(data)) { this._currentDB = this._currentDB.concat(utils.objectToArray(data)); } this._DB[this._currentDBName] = this.utils.objectToArray(this._currentDB); this.trigger(this._currentDBName, 'update'); return this; }, remove: function() { var that = this; var _swap = this.utils.arrayToObject(this._currentDB); this._buffer = this._buffer || this._currentDB; for(var i in this._buffer) { if(this._buffer.hasOwnProperty(i)) { delete _swap[this._buffer[i][jSQL_KEY_NAME]]; } } this._currentDB = this.utils.objectToArray(_swap); this._DB[this._currentDBName] = this.utils.objectToArray(_swap); return this; }, limit: function(start, end) { var _tmp = this._buffer; var limit; if(!end) { start = [0, end = start][0]; } limit = start + ':' + (start + end); this._buffer = utils.listSlice(_tmp, limit); return this; }, keys: function() { return utils.keys(this.findAll()); }, first: function(fn) { if(fn) { return this.where(fn).first(); } return utils.listSlice(this._select(), ':1'); }, last: function(fn) { if(fn) { return this.where(fn).last(); } return utils.listSlice(this._select(), '-1:'); }, distinct: function(field) { return utils.distinct(this.listAll()); }, rebase: function() { this._protected = {}; this.select('*'); this._resetBuffer(); this._updateIndexMap(); return this; }, noConflict: function() { if(window.jSQL === jSQL) { window.jSQL = this._jSQL; } if(window.jsql === jsql) { window.jsql = this._jsql; } return this; }, io: new function() { var that = this; this.ajax = function(uri, data, success, error) { var args = [].slice.call(arguments); if(args.length < 4) { args.splice(1, 0, {}); } uri = args[0], data = args[1], success = args[2], error = args[3]; data._t = utils.uuid(); this.reqwest({ url: uri, type: 'json', method: 'get', data: data, success: success, error: error }); }, this.jsonp = function(uri, data, success, error) { var args = [].slice.call(arguments); if(args.length < 4) { args.splice(1, 0, {}); } uri = args[0], data = args[1], success = args[2], error = args[3]; if(!uri.match('callback=')) { if(uri.match(/\?/igm)) { if(uri.lastIndexOf('&') === uri.length - 1) { uri += 'callback=?&_t=' + utils.uuid(); } else { uri += '&callback=?&_t=' + utils.uuid(); } } else { uri += '?callback=?&_t=' + utils.uuid(); } } this.reqwest({ url: uri, type: 'jsonp', data: data, success: success, error: error }); } }, on: function(database, event, callback) { this._events[database] = this._events[database] || new this.Events(); return this._events[database].on(event, callback); }, off: function(database, event, callback) { return this._events[database].off(event, callback); }, trigger: function(database, event) { var args = [].slice.call(arguments, 1); if(!this._events.hasOwnProperty(database)) { return false; } logcat.info('%s: trigger - %s', database, event); return this._events[database].trigger.apply(this._events[database], args); }, alias: function(name) { window[name] = this; return this; }, _select: function(field) { var tmp, result = []; field = field || this._protected['field']; if(this._protected['sort'] === true) { this.trigger(this._currentDBName, 'sort'); } if(field === '*' || (field.join && field.join('') === '*')) { return this._buffer; } if(typeof(field) === 'string') { field = field.split(','); } utils.each(this._buffer, function(o, i, r) { tmp = {}; tmp[jSQL_KEY_NAME] = utils.deep(o, jSQL_KEY_NAME); if(field.length === 1) { result.push(utils.deep(o, field[0])); return; } utils.each(field, function(_o, _i, _r) { if(o.hasOwnProperty(_o)) { tmp[_o.split('.').pop()] = utils.deep(o, _o); } }); result.push(tmp); }); return result; }, _updateIndexMap: function() { _DBIndexMap[this._currentDBName] = utils.arrayToObject(this._currentDB); }, _resetBuffer: function() { this._buffer = this._currentDB; //reset the _buffer } }; utils = { deep: function(data, scope) { var _tmp = data, scope = scope.split('.'); for(var i = 0; i < scope.length; i++) { _tmp = _tmp[scope[i]]; } return _tmp; }, isArray: nativeIsArray || function(obj) { return toString.call(obj) === '[object Array]'; }, isObject: function(obj) { return obj === Object(obj); }, isPlainObject: function(obj) { return this.isObject(obj) && obj.constructor === Object; }, clone: function (obj) { if(obj == null || typeof(obj) != 'object') { return obj; } var temp = new obj.constructor(); for(var key in obj) { temp[key] = arguments.callee(obj[key]); } return temp; }, objectToArray: function(object) { var array = [], object = this.clone(object); for(var i in object) { if(object.hasOwnProperty(i)) { object[i][jSQL_KEY_NAME] = i; array.push(object[i]); } } return array; }, arrayToObject: function(array, key) { var object = {}; for(var i = 0; i < array.length; i++) { object[array[i][key || jSQL_KEY_NAME]] = this.clone(array[i]); delete object[array[i][key || jSQL_KEY_NAME]][key || jSQL_KEY_NAME]; }; return object; }, each: function(list, fn) { if(nativeForEach) { list.forEach(fn); return; } for(var i = 0; i < list.length; i++) { fn(list[i], i, list); } }, keygen: function(object, indexList) { var that = this; var baseRef = [].slice.call(arguments, 1); var key = ''; if(that.isArray(indexList)) { baseRef = indexList; } that.each(baseRef, function(o, i, r) { key += utils.deep(object, o); }); return key; }, listSlice: function(list, range) { var start, end; list = [].slice.call(list); range = range.split(':'); start = range[0] || 0; end = range.length > 1 ? range[1] || list.length : list.length; return [].slice.call(list, start, end); }, appendKey: function(list, indexList) { var that = this; that.each(list, function(o, i, r) { o[jSQL_KEY_NAME] = that.keygen(o, indexList) || i; }); }, keys: nativeKeys || (function() { var hasDontEnumBug = true, dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ], dontEnumsLength = dontEnums.length; for (var key in {'toString': null}) { hasDontEnumBug = false; } return function keys(object) { if ((typeof object != 'object' && typeof object != 'function') || object === null) { throw new TypeError('Object.keys called on a non-object'); } var keys = []; for (var name in object) { if (object.hasOwnProperty(name)) { keys.push(name); } } if (hasDontEnumBug) { for (var i = 0, ii = dontEnumsLength; i < ii; i++) { var dontEnum = dontEnums[i]; if (object.hasOwnProperty(dontEnum)) { keys.push(dontEnum); } } } return keys; }; })(), parseFn: function(fn) { if(typeof(fn) === 'string') { fn = fn || true; fn = new Function('data', 'with(data) { return ' + fn + '; }'); } return fn; }, indexOf: function(list, sought /*, fromIndex */ ) { if(nativeIndexOf) { return nativeIndexOf.apply(list, this.listSlice(arguments, '1:')); } var self = list, length = self.length >>> 0; if (!length) { return -1; } var i = 0; if (arguments.length > 2) { i = arguments[2]; } // handle negative indices i = i >= 0 ? i : Math.max(0, length + i); for (; i < length; i++) { if (i in self && self[i] === sought) { return i; } } return -1; }, lastIndexOf: function lastIndexOf(list, sought /*, fromIndex */) { if(nativeLastIndexOf) { return nativeLastIndexOf.apply(list, this.listSlice(arguments, '1:')); } var self = list, length = self.length >>> 0; if (!length) { return -1; } var i = length - 1; if (arguments.length > 1) { i = Math.min(i, toInteger(arguments[1])); } // handle negative indices i = i >= 0 ? i : length - Math.abs(i); for (; i >= 0; i--) { if (i in self && sought === self[i]) { return i; } } return -1; }, uuid: function() { return new Date().getTime() + '_' + parseInt(Math.random() * 1000); }, distinct: function(arr) { var tmp = []; for(var i = 0; i < arr.length; i++) { if(tmp.indexOf(arr[i]) === -1) { tmp.push(arr[i]); } } return tmp; } }; jSQL = new jSQL(); typeof(module) !== 'undefined' && module.exports ? module.exports = jSQL : this.jsql = this.jSQL = jSQL; })(); /*! * Reqwest! A general purpose XHR connection manager * (c) Dustin Diaz 2013 * https://github.com/ded/reqwest * license MIT */ !function (name, context, definition) { if (typeof module != 'undefined' && module.exports) module.exports = definition() else if (typeof define == 'function' && define.amd) define(definition) else context[name] = definition() }('reqwest', jsql.io, function () { var win = window , doc = document , twoHundo = /^20\d$/ , byTag = 'getElementsByTagName' , readyState = 'readyState' , contentType = 'Content-Type' , requestedWith = 'X-Requested-With' , head = doc[byTag]('head')[0] , uniqid = 0 , callbackPrefix = 'reqwest_' + (+new Date()) , lastValue // data stored by the most recent JSONP callback , xmlHttpRequest = 'XMLHttpRequest' , noop = function () {} , isArray = typeof Array.isArray == 'function' ? Array.isArray : function (a) { return a instanceof Array } , defaultHeaders = { contentType: 'application/x-www-form-urlencoded' , requestedWith: xmlHttpRequest , accept: { '*': 'text/javascript, text/html, application/xml, text/xml, */*' , xml: 'application/xml, text/xml' , html: 'text/html' , text: 'text/plain' , json: 'application/json, text/javascript' , js: 'application/javascript, text/javascript' } } , xhr = win[xmlHttpRequest] ? function () { return new XMLHttpRequest() } : function () { return new ActiveXObject('Microsoft.XMLHTTP') } , globalSetupOptions = { dataFilter: function (data) { return data } } function handleReadyState(r, success, error) { return function () { // use _aborted to mitigate against IE err c00c023f // (can't read props on aborted request objects) if (r._aborted) return error(r.request) if (r.request && r.request[readyState] == 4) { r.request.onreadystatechange = noop if (twoHundo.test(r.request.status)) success(r.request) else error(r.request) } } } function setHeaders(http, o) { var headers = o.headers || {} , h headers.Accept = headers.Accept || defaultHeaders.accept[o.type] || defaultHeaders.accept['*'] // breaks cross-origin requests with legacy browsers if (!o.crossOrigin && !headers[requestedWith]) headers[requestedWith] = defaultHeaders.requestedWith if (!headers[contentType]) headers[contentType] = o.contentType || defaultHeaders.contentType for (h in headers) headers.hasOwnProperty(h) && http.setRequestHeader(h, headers[h]) } function setCredentials(http, o) { if (typeof o.withCredentials !== 'undefined' && typeof http.withCredentials !== 'undefined') { http.withCredentials = !!o.withCredentials } } function generalCallback(data) { lastValue = data } function urlappend (url, s) { return url + (/\?/.test(url) ? '&' : '?') + s } function handleJsonp(o, fn, err, url) { var reqId = uniqid++ , cbkey = o.jsonpCallback || 'callback' // the 'callback' key , cbval = o.jsonpCallbackName || reqwest.getcallbackPrefix(reqId) // , cbval = o.jsonpCallbackName || ('reqwest_' + reqId) // the 'callback' value , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)') , match = url.match(cbreg) , script = doc.createElement('script') , loaded = 0 , isIE10 = navigator.userAgent.indexOf('MSIE 10.0') !== -1 if (match) { if (match[3] === '?') { url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name } else { cbval = match[3] // provided callback func name } } else { url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em } win[cbval] = generalCallback script.type = 'text/javascript' script.src = url script.async = true if (typeof script.onreadystatechange !== 'undefined' && !isIE10) { // need this for IE due to out-of-order onreadystatechange(), binding script // execution to an event listener gives us control over when the script // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html // // if this hack is used in IE10 jsonp callback are never called script.event = 'onclick' script.htmlFor = script.id = '_reqwest_' + reqId } script.onload = script.onreadystatechange = function () { if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) { return false } script.onload = script.onreadystatechange = null script.onclick && script.onclick() // Call the user callback with the last value stored and clean up values and scripts. o.success && o.success(lastValue) lastValue = undefined head.removeChild(script) loaded = 1 } // Add the script to the DOM head head.appendChild(script) // Enable JSONP timeout return { abort: function () { script.onload = script.onreadystatechange = null o.error && o.error({}, 'Request is aborted: timeout', {}) lastValue = undefined head.removeChild(script) loaded = 1 } } } function getRequest(fn, err) { var o = this.o , method = (o.method || 'GET').toUpperCase() , url = typeof o === 'string' ? o : o.url // convert non-string objects to query-string form unless o.processData is false , data = (o.processData !== false && o.data && typeof o.data !== 'string') ? reqwest.toQueryString(o.data) : (o.data || null) , http // if we're working on a GET request and we have data then we should append // query string to end of URL and not post data if ((o.type == 'jsonp' || method == 'GET') && data) { url = urlappend(url, data) data = null } if (o.type == 'jsonp') return handleJsonp(o, fn, err, url) http = xhr() http.open(method, url, true) setHeaders(http, o) setCredentials(http, o) http.onreadystatechange = handleReadyState(this, fn, err) o.before && o.before(http) http.send(data) return http } function Reqwest(o, fn) { this.o = o this.fn = fn init.apply(this, arguments) } function setType(url) { var m = url.match(/\.(json|jsonp|html|xml)(\?|$)/) return m ? m[1] : 'js' } function init(o, fn) { this.url = typeof o == 'string' ? o : o.url this.timeout = null // whether request has been fulfilled for purpose // of tracking the Promises this._fulfilled = false // success handlers this._fulfillmentHandlers = [] // error handlers this._errorHandlers = [] // complete (both success and fail) handlers this._completeHandlers = [] this._erred = false this._responseArgs = {} var self = this , type = o.type || setType(this.url) fn = fn || function () {} if (o.timeout) { this.timeout = setTimeout(function () { self.abort() }, o.timeout) } if (o.success) { this._fulfillmentHandlers.push(function () { o.success.apply(o, arguments) }) } if (o.error) { this._errorHandlers.push(function () { o.error.apply(o, arguments) }) } if (o.complete) { this._completeHandlers.push(function () { o.complete.apply(o, arguments) }) } function complete (resp) { o.timeout && clearTimeout(self.timeout) self.timeout = null while (self._completeHandlers.length > 0) { self._completeHandlers.shift()(resp) } } function success (resp) { // use global data filter on response text var filteredResponse = globalSetupOptions.dataFilter(resp.responseText, type) , r = resp.responseText = filteredResponse if (r) { switch (type) { case 'json': try { resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')') } catch (err) { return error(resp, 'Could not parse JSON in response', err) } break case 'js': resp = eval(r) break case 'html': resp = r break case 'xml': resp = resp.responseXML && resp.responseXML.parseError // IE trololo && resp.responseXML.parseError.errorCode && resp.responseXML.parseError.reason ? null : resp.responseXML break } } self._responseArgs.resp = resp self._fulfilled = true fn(resp) while (self._fulfillmentHandlers.length > 0) { self._fulfillmentHandlers.shift()(resp) } complete(resp) } function error(resp, msg, t) { self._responseArgs.resp = resp self._responseArgs.msg = msg self._responseArgs.t = t self._erred = true while (self._errorHandlers.length > 0) { self._errorHandlers.shift()(resp, msg, t) } complete(resp) } this.request = getRequest.call(this, success, error) } Reqwest.prototype = { abort: function () { this._aborted = true this.request.abort() } , retry: function () { init.call(this, this.o, this.fn) } /** * Small deviation from the Promises A CommonJs specification * http://wiki.commonjs.org/wiki/Promises/A */ /** * `then` will execute upon successful requests */ , then: function (success, fail) { if (this._fulfilled) { success(this._responseArgs.resp) } else if (this._erred) { fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t) } else { this._fulfillmentHandlers.push(success) this._errorHandlers.push(fail) } return this } /** * `always` will execute whether the request succeeds or fails */ , always: function (fn) { if (this._fulfilled || this._erred) { fn(this._responseArgs.resp) } else { this._completeHandlers.push(fn) } return this } /** * `fail` will execute when the request fails */ , fail: function (fn) { if (this._erred) { fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t) } else { this._errorHandlers.push(fn) } return this } } function reqwest(o, fn) { return new Reqwest(o, fn) } // normalize newline variants according to spec -> CRLF function normalize(s) { return s ? s.replace(/\r?\n/g, '\r\n') : '' } function serial(el, cb) { var n = el.name , t = el.tagName.toLowerCase() , optCb = function (o) { // IE gives value="" even where there is no value attribute // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273 if (o && !o.disabled) cb(n, normalize(o.attributes.value && o.attributes.value.specified ? o.value : o.text)) } , ch, ra, val, i // don't serialize elements that are disabled or without a name if (el.disabled || !n) return switch (t) { case 'input': if (!/reset|button|image|file/i.test(el.type)) { ch = /checkbox/i.test(el.type) ra = /radio/i.test(el.type) val = el.value // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here ;(!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val)) } break case 'textarea': cb(n, normalize(el.value)) break case 'select': if (el.type.toLowerCase() === 'select-one') { optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null) } else { for (i = 0; el.length && i < el.length; i++) { el.options[i].selected && optCb(el.options[i]) } } break } } // collect up all form elements found from the passed argument elements all // the way down to child elements; pass a '