fork download
  1. /*
  2.  * SimpleJS
  3.  * https://g...content-available-to-author-only...b.com/TylerOBrien/SimpleJS
  4.  *
  5.  * Copyright (c) 2012 Tyler O'Brien
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining
  8.  * a copy of this software and associated documentation files (the
  9.  * "Software"), to deal in the Software without restriction, including
  10.  * without limitation the rights to use, copy, modify, merge, publish,
  11.  * distribute, sublicense, and/or sell copies of the Software, and to
  12.  * permit persons to whom the Software is furnished to do so, subject to
  13.  * the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be
  16.  * included in all copies or substantial portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  * */
  26.  
  27. /*
  28.  * SimpleJS
  29.  * */
  30. var Simple = window.$s = {};
  31. (function(__Simple){
  32. "use strict";
  33.  
  34. /*
  35. * AJAX fallback for IE6.
  36. * Might not work for IE5 and earlier.
  37. * */
  38. if (typeof window.XMLHttpRequest === "undefined") {
  39. window.XMLHttpRequest = function(){
  40. return new ActiveXObject("Microsoft.XMLHTTP");
  41. };
  42. window.XMLHttpRequest.prototype.isActiveX = true;
  43. } else {
  44. window.XMLHttpRequest.prototype.isActiveX = false;
  45. }
  46.  
  47. /*
  48. * Internal AJAX operations.
  49. * */
  50. var AJAXInternal = {
  51. /*
  52. * class Request
  53. * Basic wrapper of an XMLHttpRequest object.
  54. * Is only ever used in the Simple.AJAX function.
  55. * */
  56. Request: function(args){
  57. this.async = __Simple.Exists(args["async"], true);
  58. this.charset = __Simple.Exists(args["charset"], "utf-8");
  59. this.contentType = __Simple.Exists(args["contentType"], "application/x-www-form-urlencoded");
  60. this.data = __Simple.Exists(args["data"], {});
  61. this.http = new XMLHttpRequest();
  62. this.method = __Simple.Exists(args["method"], "GET");
  63. this.onError = args["onError"];
  64. this.onConnect = args["onConnect"];
  65. this.onNotFound = args["onNotFound"];
  66. this.onProcess = args["onProcess"];
  67. this.onRecvRequest = args["onRecvRequest"];
  68. this.onSuccess = args["onSuccess"];
  69. this.queryString = __Simple.EncodeQueryString(this.data);
  70. this.timeBegin = 0;
  71. this.timeDifference = 0;
  72. this.timeEnd = 0;
  73. this.url = __Simple.Exists(args["url"], "/");
  74. this.urlToOpen = (this.method === "POST") ? this.url : (this.url + "?" + this.queryString);
  75. },
  76.  
  77. /*
  78. * Send() returns Nothing
  79. * Input: AJAXInternal.Request, Object
  80. * A "safe" version of XMLHttpRequest.send().
  81. * Is compatible with both ActiveX-based AJAX and otherwise.
  82. * */
  83. Send: function(ajaxRequest, args){
  84. if (typeof args === CacheInternal.undefined || args === null) {
  85. if (ajaxRequest.isActiveX) {
  86. ajaxRequest.send();
  87. } else {
  88. ajaxRequest.send(null);
  89. }
  90. } else if ("method" in args && "queryString" in args && args.method === "post") {
  91. ajaxRequest.send(args.queryString);
  92. } else {
  93. Send(ajaxRequest, null);
  94. }
  95. }
  96. };
  97.  
  98. /*
  99. * Used to map class names (e.g "[object String]") to their object names (e.g. "string").
  100. * Is used by the Simple.Type() function.
  101. * */
  102. var ClassTypesInternal = {
  103. /* Populated by function at bottom using Simple.Each(). */
  104. };
  105.  
  106. /*
  107. * Cache of commonly used values.
  108. * The following are commonly used values that are cached so that new string
  109. * objects don't need to be constantly created.
  110. * */
  111. var CacheInternal = {
  112. array: "array",
  113. cookieGetRegex: "=([^;]+);?", /* Passed as an argument to RegExp's constructor. */
  114. contentType: "Content-type",
  115. emptyString: "",
  116. forwardSlash: "/",
  117. func: "function",
  118. length: "length",
  119. nullstr: "null", /* Must use "nullstr" as name. Using "null" does not work in IE6-8. */
  120. number: "number",
  121. object: "object",
  122. on: "on",
  123. semicolon: ";",
  124. string: "string",
  125. timeout: "timeout",
  126. uint32max: 4294967296,
  127. undefined: "undefined"
  128. };
  129.  
  130. /*
  131. * Used for treating certain objects has shortcuts.
  132. * Generally only used when the object is going to be iterated.
  133. * */
  134. var GetInternalShortcut = function(object){
  135. switch (object){
  136. case __Simple.Cookie: return __Simple.Cookie.GetAll();
  137. case __Simple.GET: return __GET;
  138. default: return object;
  139. }
  140. };
  141.  
  142. /*
  143. * Internal DOM operations.
  144. * */
  145. var DOMInternal = {
  146. busy: false,
  147. callbacks: [], /* Array of Function */
  148. ready: false,
  149.  
  150. /*
  151. * ManageEventListener() returns Nothing
  152. * Input: Boolean, Mixed, String, Function, Boolean
  153. * This function adds or removes an event listener, depending on the
  154. * value of the first parameter.
  155. * Is called by DOMInternal.ProcessEventListener().
  156. * */
  157. ManageEventListener: function(isAddingEvent, element, event, callback, useCapture){
  158. if (typeof element !== CacheInternal.undefined && element !== null) {
  159. if (typeof element.addEventListener !== CacheInternal.undefined) {
  160. if (typeof useCapture === CacheInternal.undefined) {
  161. useCapture = false;
  162. }
  163. if (isAddingEvent) element.addEventListener(event, callback, useCapture);
  164. else element.removeEventListener(event, callback, useCapture);
  165. } else {
  166. if (isAddingEvent) element.attachEvent(CacheInternal.on+event, callback);
  167. else element.detachEvent(CacheInternal.on+event, callback);
  168. }
  169. }
  170. },
  171.  
  172. /*
  173. * ProcessEventListener() returns Nothing
  174. * Input: Boolean, Mixed, String, Function, Boolean
  175. * Processes any bases elements/events.
  176. * */
  177. ProcessEventListener: function(isAddingEvent, element, event, callback, useCapture){
  178. if (__Simple.IsString(element)) {
  179. element = __Simple.DOMElement(element);
  180. }
  181. if (__Simple.IsDOMElementArray(element) || __Simple.IsArray(element)) {
  182. __Simple.Each(element, function(elementItr){
  183. DOMInternal.ProcessEventListener(isAddingEvent, elementItr.value, event, callback, useCapture);
  184. });
  185. } else {
  186. if (__Simple.IsArray(event)) {
  187. __Simple.Each(event, function(eventItr){
  188. DOMInternal.ManageEventListener(isAddingEvent, element, eventItr.value, callback, useCapture);
  189. });
  190. } else {
  191. DOMInternal.ManageEventListener(isAddingEvent, element, event, callback, useCapture);
  192. }
  193. }
  194. },
  195.  
  196. /*
  197. * OnDOMContentLoaded() returns Nothing
  198. * Input: Nothing
  199. * Called by one of two possible event listeners.
  200. * As function name suggests, is called when the DOM has finished loading.
  201. * */
  202. OnDOMContentLoaded: function(){
  203. if (typeof document.addEventListener !== CacheInternal.undefined) {
  204. document.removeEventListener("DOMContentLoaded", DOMInternal.OnDOMContentLoaded, false);
  205. DOMInternal.OnReady();
  206. } else if (typeof document.attachEvent !== CacheInternal.undefined && document.readyState === "complete" && document.body !== null) {
  207. document.detachEvent("onreadystatechange", DOMInternal.OnDOMContentLoaded);
  208. DOMInternal.OnReady();
  209. }
  210. },
  211.  
  212. /*
  213. * OnReady() returns Nothing
  214. * Input: Nothing
  215. * Called when the DOM is ready.
  216. * Is usually called by DOMInternal.OnDOMContentLoaded.
  217. * */
  218. OnReady: function(){
  219. if (this.busy === false && this.ready === false) {
  220. this.busy = true;
  221. Simple.Each(this.callbacks, function(itr){
  222. itr.value();
  223. });
  224. this.ready = true;
  225. this.busy = false;
  226. }
  227. }
  228. };
  229.  
  230. /*
  231. * Internal regular expressions.
  232. * */
  233. var RegexInternal = {
  234. cookie: /[ ]?([^=]+)=([^;]+)[; ]?/g,
  235. floatingPoint: /[0-9]+([.][0-9]+)?/g,
  236. notNumber: /[^0-9.\-+]+/g, /* Used to match anything NOT a number. That is 0-9 and decimal points. */
  237. number: /([0-9]{1,3}([,][0-9]{3})?)+([.][0-9]+)?/g, /* Used to match any number. Includes commas because some string-numbers use them. */
  238. queryString: /[?&]?([^&=]+)=?([^&]+)?/g,
  239. sprintfVariable: /%[b|d|f|h|H|o|s|u|x|X]/g
  240. };
  241.  
  242. /*
  243. * Internal Sprintf operations.
  244. * Should probably cache these string values.
  245. * */
  246. var SprintfInternal = {
  247. Process: function(type, value){
  248. switch (type){
  249. case "%b": return __Simple.ToInt(value).toString(2);
  250. case "%d": return __Simple.ToInt(value).toString();
  251. case "%f": return parseFloat(value).toString();
  252. case "%h": return __Simple.ToInt(value).toString(16);
  253. case "%H": return __Simple.ToInt(value).toString(16).toUpperCase();
  254. case "%o": return __Simple.ToInt(value).toString(8);
  255. case "%u": return __Simple.ToUnsignedInt(value).toString();
  256. case "%x": return "0x" + __Simple.ToInt(value).toString(16);
  257. case "%X": return "0x" + __Simple.ToInt(value).toString(16).toUpperCase();
  258. default: return value;
  259. }
  260. }
  261. };
  262.  
  263. /*
  264. * class Iterator
  265. * Used for storing iteration informating by the Simple.Each function.
  266. * Is only used internally, so there's no point in making it public-facing.
  267. * */
  268. var Iterator = function(container){
  269. this.container = container;
  270. this.i = null;
  271. this.value = null;
  272. };
  273.  
  274. /*
  275. * AddEvent() returns Nothing
  276. * Input: String|DOMElement, String, Function
  277. * */
  278. __Simple.AddEvent = function(element, event, callback, useCapture){
  279. DOMInternal.ProcessEventListener(true, element, event, callback, useCapture);
  280. };
  281.  
  282. /*
  283. * ArraysEqual() returns Boolean
  284. * Input: Array, Array
  285. * */
  286. __Simple.ArraysEqual = function(first, second){
  287. var result = false;
  288. if (__Simple.IsArray([first,second],true) && first.length === second.length) {
  289. __Simple.Each(first, function(itr){
  290. return result = __Simple.Equals(itr.value, second[itr.i]);
  291. });
  292. }
  293. return result;
  294. };
  295.  
  296. /*
  297. * AJAX() returns nothing
  298. * Input: Object
  299. * */
  300. __Simple.AJAX = function(args){
  301. var ajaxRequest = new AJAXInternal.Request(args);
  302.  
  303. ajaxRequest.http.open(ajaxRequest.method, ajaxRequest.urlToOpen, ajaxRequest.async);
  304. ajaxRequest.http.setRequestHeader(CacheInternal.contentType, ajaxRequest.contentType+"; charset="+ajaxRequest.charset);
  305. ajaxRequest.http.onreadystatechange = function(){
  306. switch (ajaxRequest.http.readyState) {
  307. case 1: /* CONNECT */
  308. ajaxRequest.timeBegin = new Date().getTime();
  309. __Simple.Call(ajaxRequest.onConnect);
  310. break;
  311. case 2: /* REQUEST RECEIVED */
  312. __Simple.Call(ajaxRequest.onRecvRequest);
  313. break;
  314. case 3: /* PROCESSING */
  315. __Simple.Call(ajaxRequest.onProcess);
  316. break;
  317. case 4: /* COMPLETE */
  318. if (typeof ajaxRequest.timeout !== CacheInternal.undefined) {
  319. clearTimeout(ajaxRequest.timeout);
  320. }
  321.  
  322. ajaxRequest.timeEnd = new Date().getTime();
  323. ajaxRequest.timeDifference = (ajaxRequest.timeEnd - ajaxRequest.timeBegin);
  324.  
  325. switch (ajaxRequest.http.status) {
  326. case 200: __Simple.Call(ajaxRequest.onSuccess, ajaxRequest.http.responseText, ajaxRequest.timeDifference);
  327. break;
  328. case 404: __Simple.Call(ajaxRequest.onNotFound, ajaxRequest.http.responseText, ajaxRequest.timeDifference);
  329. default: __Simple.Call(ajaxRequest.onError, [ajaxRequest.http.responseText,ajaxRequest.http.status], ajaxRequest.timeDifference);
  330. break;
  331. }
  332. break;
  333. }
  334. };
  335.  
  336. /*
  337. * Add a new timeout if one is given.
  338. * The time is assumed to be milliseconds.
  339. * */
  340. if (typeof args[CacheInternal.timeout] === CacheInternal.number) {
  341. ajaxRequest.timeout = setTimeout(function(){
  342. ajaxRequest.http.abort();
  343. __Simple.Call(ajaxRequest.onTimeout);
  344. }, args[CacheInternal.timeout]);
  345. }
  346.  
  347. /* Send twice because the request object will also contain the GET/POST
  348. * variables being sent through HTTP (that's what the second parameter is for). */
  349. AJAXInternal.Send(ajaxRequest, ajaxRequest);
  350. };
  351.  
  352. /*
  353. * Call() returns Mixed
  354. * Input: Mixed, Mixed, Mixed
  355. * */
  356. __Simple.Call = function(callback, first, second){
  357. if (__Simple.Type(callback) === CacheInternal.func) {
  358. if (typeof second !== CacheInternal.undefined) return callback(first, second);
  359. else if (typeof first !== CacheInternal.undefined) return callback(first);
  360. else return callback();
  361. }
  362. };
  363.  
  364. /*
  365. * Functions for getting and setting cookies.
  366. * */
  367. __Simple.Cookie = {
  368. /*
  369. * Exists() returns Boolean
  370. * Input: Array|String
  371. * */
  372. Exists: function(name){
  373. return __Simple.HasProperty(__Simple.Cookie.GetAll(), name);
  374. },
  375.  
  376. /*
  377. * Get() returns String
  378. * Input: Array|String
  379. * */
  380. Get: function(name){
  381. if (__Simple.IsString(name)) {
  382. var result = new RegExp(name+CacheInternal.cookieGetRegex, "g").exec(document.cookie);
  383. if (result !== null) {
  384. return result[1];
  385. }
  386. }
  387. },
  388.  
  389. /*
  390. * GetAll() returns Object
  391. * Input: Nothing
  392. * */
  393. GetAll: function(){
  394. var currentCookie = document.cookie;
  395. var buffer = RegexInternal.cookie.exec(currentCookie);
  396. var result = {};
  397.  
  398. while (buffer !== null) {
  399. result[buffer[1]] = buffer[2];
  400. buffer = RegexInternal.cookie.exec(currentCookie);
  401. }
  402.  
  403. return result;
  404. },
  405.  
  406. /*
  407. * Set() returns Nothing
  408. * Input: String, String, Object[, String]
  409. * */
  410. Set: function(name, value, milliseconds, path){
  411. var date = new Date;
  412. var expiration = new Date(milliseconds);
  413.  
  414. date.setTime(date.getTime() + expiration.getTime());
  415.  
  416. path = __Simple.Exists(path, CacheInternal.forwardSlash);
  417. document.cookie = name+"="+value+"; expires="+date.toUTCString()+"; path="+path;
  418. }
  419. };
  420.  
  421. /*
  422. * DOMElement() returns Mixed
  423. * Input: String, Mixed
  424. * */
  425. __Simple.DOMElement = function(elementString, context){
  426. /* Ensure context is defined. */
  427. if (typeof context === CacheInternal.undefined) {
  428. context = document;
  429. } else if (__Simple.IsString(context)) {
  430. context = __Simple.DOMElement(context);
  431. }
  432.  
  433. var result;
  434.  
  435. /* Second condition is necessary for IE6-8. */
  436. if (__Simple.IsDOMElement(context) || context === document) {
  437. switch (elementString.charAt(0)) {
  438. case "#": result = context.getElementById(elementString.substring(1)); break;
  439. case ".": result = context.getElementsByClassName(elementString.substring(1)); break;
  440. case ":": result = context.getElementsByName(elementString.substring(1)); break;
  441. default: result = context.getElementsByTagName(elementString); break;
  442. }
  443.  
  444. /* The getElements functions return arrays. Replace any empty ones with NULL values. */
  445. if (result !== null && __Simple.HasProperty(result, CacheInternal.length) && result.length === 0) {
  446. result = null;
  447. }
  448. }
  449.  
  450. return result;
  451. };
  452.  
  453. /*
  454. * DOMReady() returns nothing
  455. * Input: Function
  456. * Calls the passed function when the DOM is ready.
  457. * */
  458. __Simple.DOMReady = function(callback){
  459. if (__Simple.Type(callback) === CacheInternal.func) {
  460. if (DOMInternal.ready === false && DOMInternal.busy === false) {
  461. DOMInternal.callbacks.push(callback);
  462. } else {
  463. callback();
  464. }
  465. }
  466. };
  467.  
  468. /*
  469. * DecodeQueryString() returns Object
  470. * Input: String
  471. * Converts a passed query string in this format:
  472. * id=42&name=John%20Doe&type=user
  473. * Into an object containing the defined variables.
  474. *
  475. * Any variables not given a value, like so:
  476. * foo&bar&baz
  477. * Will be NULL valued in the object.
  478. * */
  479. __Simple.DecodeQueryString = function(queryString){
  480. var buffer = RegexInternal.queryString.exec(queryString);
  481. var result = {};
  482.  
  483. while (buffer !== null) {
  484. result[decodeURIComponent(buffer[1])] = (__Simple.Exists(buffer[2], null, true)) ? decodeURIComponent(buffer[2]) : CacheInternal.emptyString;
  485. buffer = RegexInternal.queryString.exec(queryString);
  486. }
  487.  
  488. return result;
  489. };
  490.  
  491. /*
  492. * Simple.Each() returns nothing
  493. * Input: Mixed, Function
  494. * */
  495. __Simple.Each = function(haystack, callback){
  496. if (typeof haystack !== CacheInternal.undefined) {
  497. haystack = GetInternalShortcut(haystack);
  498.  
  499. /* Iterator will hold a reference to haystack. */
  500. var iterator = new Iterator(haystack);
  501.  
  502. /* DOMObjectArrays aren't considered arrays for some reason.
  503.   So also check for a length property. Need to look into this and improve it. */
  504. if (__Simple.IsArray(haystack) || __Simple.HasProperty(haystack, CacheInternal.length)) {
  505. iterator.i = 0;
  506. var end = haystack.length;
  507. for (; iterator.i < end; iterator.i++) {
  508. iterator.value = haystack[iterator.i];
  509. if (callback.call(iterator.value, iterator) === false) {
  510. break;
  511. }
  512. }
  513. } else {
  514. for (iterator.i in haystack) {
  515. iterator.value = haystack[iterator.i];
  516. if (callback.call(iterator.value, iterator) === false) {
  517. break;
  518. }
  519. }
  520. }
  521. }
  522. };
  523.  
  524. /*
  525. * EncodeQueryString() returns String
  526. * Input: Object
  527. * Encodes a passed Object into a query string.
  528. * For example, this:
  529. * {name:"John Doe", id:42}
  530. * Would become:
  531. * name=John%20Doe&id=42
  532. * */
  533. __Simple.EncodeQueryString = function(object){
  534. var result = "";
  535.  
  536. for (var index in object) {
  537. result += (encodeURIComponent(index) + "=" + encodeURIComponent(object[index]) + "&");
  538. }
  539.  
  540. if (result.length > 0) { /* Trim off the extra ampersand. */
  541. result = result.substring(0, result.length-1);
  542. }
  543.  
  544. return result;
  545. };
  546.  
  547. /*
  548. * Equals() returns Boolean
  549. * Input: Mixed, Mixed
  550. */
  551. __Simple.Equals = function(first, second){
  552. first = GetInternalShortcut(first);
  553. second = GetInternalShortcut(second);
  554.  
  555. var result = false;
  556.  
  557. if (__Simple.IsArray([first,second],true)) {
  558. result = __Simple.ArraysEqual(first, second);
  559. } else if (__Simple.IsObject([first,second],true)) {
  560. var firstArr = __Simple.ObjectToArray(first);
  561. var secondArr = __Simple.ObjectToArray(second);
  562. result = __Simple.Equals(firstArr[0], secondArr[0]) && __Simple.Equals(firstArr[1], secondArr[1]);
  563. } else {
  564. result = (first === second);
  565. }
  566.  
  567. return result;
  568. };
  569.  
  570. /*
  571. * Exists() returns Mixed
  572. * Input: Mixed, Mixed, Boolean
  573. * Used for determining if "object" is defined.
  574. * If defined "object" will be returned, otherwise "override" is returned.
  575. * If "doReturnBoolean" is true then false/true is returned in place of object/override.
  576. * */
  577. __Simple.Exists = function(object, override, doReturnBoolean){
  578. var useBool = (typeof doReturnBoolean !== CacheInternal.undefined && doReturnBoolean);
  579.  
  580. if (typeof object !== CacheInternal.undefined) {
  581. if (useBool) return true;
  582. else return object;
  583. } else {
  584. if (useBool) return false;
  585. else return override;
  586. }
  587. };
  588.  
  589. /*
  590. * GET
  591. * Contains functions for accessing GET variables.
  592. * */
  593. __Simple.GET = {
  594. /*
  595. * Exists() returns Boolean
  596. * Input: Array|String
  597. * Returns true if the passed GET variable has been defined.
  598. * Does not require a value to have been assigned.
  599. * */
  600. Exists: function(name){
  601. return __Simple.HasProperty(__GET, name);
  602. },
  603.  
  604. /*
  605. * Get() returns Array|String|undefined
  606. * Input: Object|String
  607. * Returns the value of the passed GET variable.
  608. * If the GET variable has no value assigned this will return NULL.
  609. * If the GET variable does not exist this will return undefined.
  610. * */
  611. Get: function(name){
  612. if (__Simple.IsArray(name)) {
  613. var result = {};
  614. __Simple.Each(name, function(itr){
  615. result[itr.value] = __Simple.GET.Get(itr.value);
  616. });
  617. return result;
  618. } else {
  619. return __Simple.GET.Exists(name) ? __GET[name] : undefined;
  620. }
  621. },
  622.  
  623. /*
  624. * GetAll() returns Object
  625. * Input: Nothing
  626. * */
  627. GetAll: function(){
  628. var result = {};
  629. __Simple.Each(__GET, function(itr){
  630. result[itr.i] = itr.value;
  631. });
  632. return result;
  633. }
  634. };
  635.  
  636. /*
  637. * GenerateArray() returns Array
  638. * Input: Integer, Mixed, Boolean
  639. * */
  640. __Simple.GenerateArray = function(num, value, isCallback){
  641. var result = [];
  642. for (var i = 0; i < num; i++) {
  643. result.push(isCallback ? value(result, i) : value);
  644. }
  645. return result;
  646. };
  647.  
  648. /*
  649. * HasProperty() returns Boolean
  650. * Input: Mixed, Array|String
  651. * */
  652. __Simple.HasProperty = function(object, property){
  653. object = GetInternalShortcut(object);
  654.  
  655. if (__Simple.IsArray(property)) {
  656. var result = false;
  657. __Simple.Each(property, function(itr){
  658. return result = __Simple.HasProperty(object, itr.value);
  659. });
  660. return result;
  661. } else {
  662. return typeof object[property] !== CacheInternal.undefined;
  663. }
  664. };
  665.  
  666. /*
  667. * HasValue() returns Boolean
  668. * Input: Mixed, Mixed
  669. * */
  670. __Simple.HasValue = function(object, value){
  671. object = GetInternalShortcut(object);
  672.  
  673. var result = false;
  674. __Simple.Each(object, function(itr){
  675. return !(result = __Simple.Equals(value, itr.value));
  676. });
  677. return result;
  678. };
  679.  
  680. /*
  681. * IsEmptyArray() returns Boolean
  682. * Input: Array, Boolean
  683. * */
  684. __Simple.IsArray = function(source, doIterateSource){
  685. if (typeof doIterateSource !== CacheInternal.undefined && doIterateSource) {
  686. var result = false;
  687. __Simple.Each(source, function(itr){
  688. return result = __Simple.IsArray(itr.value);
  689. });
  690. return result;
  691. } else {
  692. return (__Simple.Type(source) === CacheInternal.array);
  693. }
  694. };
  695.  
  696. /*
  697. * IsObject() returns Boolean
  698. * Input: Array|Object, Boolean
  699. * */
  700. __Simple.IsObject = function(source, doIterateSource){
  701. if (typeof doIterateSource !== CacheInternal.undefined && doIterateSource) {
  702. var result = false;
  703. __Simple.Each(source, function(itr){
  704. return result = __Simple.IsObject(itr.value);
  705. });
  706. return result;
  707. } else {
  708. return (__Simple.Type(source) === CacheInternal.object);
  709. }
  710. };
  711.  
  712. /*
  713. * IsEmptyArray() returns Boolean
  714. * Input: Array
  715. * */
  716. __Simple.IsEmptyArray = function(object){
  717. return __Simple.IsArray(object) && object.length === 0;
  718. };
  719.  
  720. /*
  721. * IsEmptyObject() returns Boolean
  722. * Input: Mixed
  723. * Borrowed from jQuery.
  724. * */
  725. __Simple.IsEmptyObject = function(object){
  726. for (var index in GetInternalShortcut(object)) {
  727. return false;
  728. }
  729. return true;
  730. };
  731.  
  732. /*
  733. * IsDOMElementArray() returns Boolean
  734. * Input: Mixed
  735. * */
  736. __Simple.IsDOMElementArray = function(arr){
  737. return typeof arr !== CacheInternal.undefined && arr !== null && __Simple.IsDOMElement(arr[0]) && __Simple.HasProperty(arr, "item");
  738. };
  739.  
  740. /*
  741. * IsDOMElement() returns Boolean
  742. * Input: Mixed
  743. * */
  744. __Simple.IsDOMElement = function(object){
  745. return typeof object !== CacheInternal.undefined && object !== null && __Simple.HasProperty(object, "ELEMENT_NODE");
  746. };
  747.  
  748. /*
  749. * IsNumeric() returns Boolean
  750. * Input: Mixed
  751. * */
  752. __Simple.IsNumeric = function(object){
  753. return !isNaN(parseFloat(object)) && isFinite(object);
  754. };
  755.  
  756. /*
  757. * IsString() returns Boolean
  758. * Input: Mixed
  759. * */
  760. __Simple.IsString = function(object){
  761. return __Simple.Type(object) === CacheInternal.string;
  762. };
  763.  
  764. /*
  765. * RemoveEvent() returns Nothing
  766. * Input: String|DOMElement, String, Function
  767. * */
  768. __Simple.RemoveEvent = function(element, event, callback, useCapture){
  769. DOMInternal.ProcessEventListener(false, element, event, callback, useCapture);
  770. };
  771.  
  772. /*
  773. * ToInt() returns Integer
  774. * Input: Mixed, Integer
  775. * */
  776. __Simple.ToInt = function(source, base){
  777. if (__Simple.Type(source) !== CacheInternal.number) {
  778. var result = source.match(RegexInternal.number);
  779. if (result !== null && result.length === 1) {
  780. return parseInt(source.replace(RegexInternal.notNumber, CacheInternal.emptyString), __Simple.Exists(base, 10));
  781. } else {
  782. return NaN;
  783. }
  784. } else {
  785. return parseInt(source, __Simple.Exists(base, 10));
  786. }
  787. };
  788.  
  789. /*
  790. * ToUnsignedInt() returns Integer
  791. * Input: Mixed
  792. * */
  793. __Simple.ToUnsignedInt = function(source, base){
  794. if (source = __Simple.ToInt(source, base)) {
  795. return (source > 0) ? source : (CacheInternal.uint32max - Math.abs(source));
  796. } else {
  797. return source;
  798. }
  799. };
  800.  
  801. /*
  802. * Simple.Type() returns String
  803. * Input: Mixed
  804. * Returns the type of the passed object.
  805. * Borrowed from jQuery.
  806. * */
  807. __Simple.Type = function(object){
  808. return object === null ? CacheInternal.nullstr : (ClassTypesInteral[Object.prototype.toString.call(object)] || CacheInternal.object);
  809. };
  810.  
  811. /*
  812. * ObjectToArray() returns Array
  813. * Input: Object
  814. * */
  815. __Simple.ObjectToArray = function(object){
  816. object = GetInternalShortcut(object);
  817. var result = [[],[]];
  818.  
  819. __Simple.Each(object, function(itr){
  820. result[0].push(itr.i);
  821. result[1].push(itr.value);
  822. });
  823.  
  824. return result;
  825. };
  826.  
  827. /*
  828. * Round() returns Float|Integer
  829. * Input: Float|Integer, Integer
  830. * */
  831. __Simple.Round = function(num, decimalPlaces){
  832. decimalPlaces = Math.pow(10, __Simple.Exists(decimalPlaces, 0));
  833. return Math.round(num*decimalPlaces) / decimalPlaces;
  834. };
  835.  
  836. /*
  837. * Sprintf() returns String
  838. * Input: String[, Array|String ...]
  839. * */
  840. __Simple.Sprintf = function(source){
  841. if (arguments.length > 1) {
  842. /* The values may be in the arguments array,
  843. * or may be an array passed as the second argument.
  844. * */
  845. var indexOffset = 1;
  846. var values = arguments;
  847. if (__Simple.IsArray(arguments[1])) {
  848. indexOffset = 0;
  849. values = arguments[1];
  850. }
  851.  
  852. var variables = source.match(RegexInternal.sprintfVariable);
  853. var end = (variables) ? variables.length : 0;
  854.  
  855. /* Replace each sprintf variable with the appropriate values. */
  856. for (var i = 0; i < end; i++) {
  857. source = source.replace(
  858. variables[i],
  859. SprintfInternal.Process(variables[i], values[i+indexOffset].toString())
  860. );
  861. }
  862. }
  863.  
  864. return source;
  865. };
  866.  
  867. /*
  868. * Populate the class types.
  869. * Borrowed from jQuery.
  870. * */
  871. __Simple.Each("Array Boolean Date Function Number Object RegExp String".split(" "), function(itr){
  872. ClassTypesInteral["[object " + itr.value + "]"] = itr.value.toLowerCase();
  873. });
  874.  
  875. /*
  876. * Decode the browser's query string, if it exists.
  877. * */
  878. var __GET = __Simple.DecodeQueryString(document.location.search);
  879.  
  880. /*
  881. * Older browsers (e.g. Internet Explorer 6) may have different methods for DOM loading.
  882. * Based on jQuery.
  883. * */
  884. if (typeof document.addEventListener !== CacheInternal.undefined) {
  885. document.addEventListener("DOMContentLoaded", DOMInternal.OnDOMContentLoaded, false);
  886. window.addEventListener("load", DOMInternal.OnReady, false);
  887. } else if (typeof document.attachEvent !== CacheInternal.undefined) {
  888. document.attachEvent("onreadystatechange", DOMInternal.OnDOMContentLoaded);
  889. window.attachEvent("onload", DOMInternal.OnReady, false);
  890. } else {
  891. window.onload = DOMInternal.OnReady;
  892. }
  893. }(Simple));
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty