1 /** 2 * @namespace JekFk Framework 3 * @author Vincenzo De Vivo http://www.vincenzodevivo.com 4 */ 5 var Jek = { 6 7 /** 8 * JekFk framework info 9 * 10 * @namespace 11 */ 12 info : { 13 /** 14 * The current name of framework 15 * 16 * @type String 17 */ 18 name : 'JekFk', 19 /** 20 * The current version of framework 21 * 22 * @type String 23 */ 24 version : '0.6' 25 }, 26 /** 27 * Framework statistics 28 * 29 * @type JekStats 30 */ 31 fkStats : new JekStats(), 32 /** 33 * Generates a unique ID 34 * 35 * @param {String}idType[optional] 36 * 37 * <b><i>default</i></b> value: "jek" 38 * @returns {String} A unique ID 39 */ 40 id : function(idType) { 41 idType = this.defParam(idType, 'jek'); 42 return idType + this.fkStats.increase(idType); 43 }, 44 /** 45 * If param is undefined then returns default parameter else returns param 46 * 47 * @param {Object}param 48 * @param {Object}defaultParam 49 * @returns {Object} 50 */ 51 defParam : function(param, defaultParam) { 52 if (this.isUndef(param)) { 53 return defaultParam; 54 } else { 55 return param; 56 } 57 }, 58 /** 59 * Returns true if <b>o</b> is of type Boolean, false otherwise. 60 * 61 * @param {any}o 62 * @returns {Boolean} 63 */ 64 isBoolean : function(o) { 65 return typeof o === 'boolean'; 66 }, 67 /** 68 * Returns true if <b>o</b> is null, false otherwise. 69 * 70 * @param {any}o 71 * @returns {Boolean} 72 */ 73 isNull : function(o) { 74 return o === null; 75 }, 76 /** 77 * Returns true if <b>o</b> is of type String, false otherwise. 78 * 79 * @param {any}o 80 * @returns {Boolean} 81 */ 82 isString : function(o) { 83 return this.toObjName(o) == '[object String]'; 84 }, 85 /** 86 * Returns true if <b>o</b> is of type Number, false otherwise. 87 * 88 * @param {any}o 89 * @returns {Boolean} 90 */ 91 isNumber : function(o) { 92 return this.toObjName(o) == '[object Number]'; 93 }, 94 /** 95 * Returns true if <b>o</b> is of type Array, false otherwise. 96 * 97 * @param {any}o 98 * @returns {Boolean} 99 */ 100 isArray : function(o) { 101 return this.toObjName(o) == '[object Array]'; 102 }, 103 /** 104 * Returns true if <b>o</b> is of type Function, false otherwise. 105 * 106 * @param {any}o 107 * @returns {Boolean} 108 */ 109 isFn : function(o) { 110 return typeof o === 'function'; 111 }, 112 /** 113 * Returns true if <b>o</b> is of type undefined, false otherwise. 114 * 115 * @param {any}o 116 * @returns {Boolean} 117 */ 118 isUndef : function(o) { 119 return typeof o === 'undefined'; 120 }, 121 /** 122 * Returns true if <b>o</b> is of type Object, false otherwise. 123 * 124 * @param {any}o 125 * @returns {Boolean} 126 */ 127 isObject : function(o) { 128 return !!o && this.toObjName(o) === '[object Object]'; 129 }, 130 /** 131 * Return true if email is correct, false � otherwise 132 * 133 * @param {String}email 134 * @returns {Boolean} 135 */ 136 isEmail : function(email) { 137 var eReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; 138 return eReg.test(email); 139 }, 140 /** 141 * Returns object toString: '[object Object]' | '[object String]' | '[object 142 * Array]' | '[object Number]' | ... 143 * 144 * @param {any}o 145 * @returns {String} 146 */ 147 toObjName : function(o) { 148 return Object.prototype.toString.call(o); 149 }, 150 /** 151 * Round a number 152 * 153 * @param {Number}value 154 * @param {Number}decimalPositions 155 * @returns {Number} 156 */ 157 roundTo : function(value, decimalPositions) { 158 var i = value * Math.pow(10, decimalPositions); 159 i = Math.round(i); 160 return i / Math.pow(10, decimalPositions); 161 }, 162 /** 163 * Generates a Globally Unique IDentifier (GUID) 164 * 165 * @returns {String} 166 */ 167 guid : function() { 168 function r() { 169 var now = new Date(); 170 var seed = now.getSeconds(); 171 return ((1 + Math.random(seed)) * parseInt('10000', 16)).toString( 172 16).substring(1, 5); 173 } 174 return (r() + r() + '-' + r() + '-' + r() + '-' + r() + '-' + r() + r() + r()) 175 .toUpperCase(); 176 }, 177 /** 178 * Escapes a string according to the JSON specification. 179 * 180 * @param {String}str 181 * @returns {String} 182 */ 183 escapeString : function(str) { 184 var s = ""; 185 var ch; 186 var len = str.length; 187 for ( var i = 0; i < len; i++) { 188 ch = str.charAt(i); 189 switch (ch) { 190 case '"': 191 s += "\\\""; 192 break; 193 case '\\': 194 s += "\\\\"; 195 break; 196 case '\b': 197 s += "\\b"; 198 break; 199 case '\f': 200 s += "\\f"; 201 break; 202 case '\n': 203 s += "\\n"; 204 break; 205 case '\r': 206 s += "\\r"; 207 break; 208 case '\t': 209 s += "\\t"; 210 break; 211 default: 212 if (ch < ' ') { 213 var hexCode = ch.charCodeAt(0).toString(16); 214 var zeroPad = hexCode.length == 2 ? "00" : "000"; 215 s += "\\u" + zeroPad + hexCode; 216 } else { 217 s += ch; 218 } 219 } 220 } 221 return s; 222 }, 223 /** 224 * Decodes a JSON string to an Object. 225 * 226 * @param {String}json 227 * @returns {Object} 228 */ 229 fromJSON : function(json) { 230 return (new Function("return " + json))(); 231 }, 232 /** 233 * Returns a string containing the JSON representation of 'obj' value. 234 * 235 * @param {Object}obj 236 * @returns {String} 237 */ 238 toJSON : function(obj) { 239 var json = new String(); 240 var value; 241 var separator = ","; 242 var n = 0; 243 var obj_isFlat = false; 244 var obj_isArr = false; 245 var obj_isObj = false; 246 247 if (this.isUndef(obj) || this.isBoolean(obj) || this.isNull(obj) 248 || this.isNumber(obj)) { 249 obj_isFlat = true; 250 json += String(obj); 251 } else if (this.isString(obj)) { 252 obj_isFlat = true; 253 obj = this.escapeString(obj); 254 json += '"' + obj + '"'; 255 } else if (obj_isArr = this.isArray(obj)) { 256 json = "["; 257 } else if (obj_isObj = this.isObject(obj)) { 258 json = "{"; 259 } 260 if (!obj_isFlat) { 261 for ( var key in obj) { 262 value = obj[key]; 263 key = '"' + key + '"'; 264 if (n > 0 && !this.isFn(value)) { 265 json += separator; 266 } 267 if (this.isArray(value)) { 268 if (!obj_isArr) { 269 json += key + ":"; 270 } 271 json += this.toJSON(value); 272 n++; 273 } else if (obj_isArr) { 274 json += this.toJSON(value); 275 n++; 276 } else if (!this.isFn(value)) { 277 json += key + ":" + this.toJSON(value); 278 n++; 279 } 280 281 } 282 if (obj_isArr) { 283 json += "]"; 284 } else if (obj_isObj) { 285 json += "}"; 286 } 287 } 288 return json; 289 }, 290 /** 291 * Trim leading whitespace characters from the String. 292 * 293 * @param {String}str 294 * @returns {String} 295 */ 296 trimLeft : function(str) { 297 return str.replace(/^\s+/, ''); 298 }, 299 /** 300 * Trim trailing whitespace characters from the String. 301 * 302 * @param {String}str 303 * @returns {String} 304 */ 305 trimRight : function(str) { 306 return str.replace(/\s+$/, ''); 307 }, 308 /** 309 * Trim marginal whitespace characters from the String. 310 * 311 * @param {String}str 312 * @returns {String} 313 */ 314 trim : function(str) { 315 return str.replace(/^\s+|\s+$/g, ''); 316 }, 317 /** 318 * Read in a sequence of words from string input and capitalize each one 319 * (make first letter uppercase; make rest lowercase). 320 * 321 * @param {String}str 322 * @returns {String} 323 */ 324 capitalize : function(str) { 325 function upp_0() { 326 return arguments[0].toUpperCase(); 327 } 328 return str.toLowerCase().replace(/\b[a-z]/g, upp_0); 329 }, 330 /** 331 * Repeats the specified string 'n' times to form a new String. 332 * 333 * @param {String}str 334 * String to repeat 335 * @param {Number}n 336 * How many times to repeat the string 337 * @returns {String} 338 */ 339 repeat : function(str, n) { 340 var sb = new JekString(); 341 for ( var j = 0; j < n; j++) { 342 sb.append(str); 343 } 344 return sb.toString(); 345 }, 346 347 /** 348 * Split string into word array 349 * 350 * @param {String}string 351 * @returns {Array} 352 */ 353 words : function(string) { 354 string = string.replace(/^\W+|\W+$/g, ''); 355 var arr = string.split(/\W+/); 356 return arr; 357 }, 358 /** 359 * Switch a string between two alternating values 360 * 361 * @param {String}str 362 * @param {String}val1 363 * @param {String}val2 364 * @returns {String} 365 */ 366 toggle : function(str, val1, val2) { 367 return str == val1 ? val2 : val1; 368 }, 369 /** 370 * Encodes URL 371 * 372 * @param {String}str 373 * @returns {String} 374 */ 375 urlEncode : function(str) { 376 return escape(Jek.conversion.utf8Encode(str)); 377 }, 378 /** 379 * Decodes URL 380 * 381 * @param {String}str 382 * @returns {String} 383 */ 384 urlDecode : function(str) { 385 return Jek.conversion.utf8Decode(unescape(str)); 386 }, 387 388 /** 389 * padLeft 390 * 391 * @param str 392 * @param char 393 * @param num 394 */ 395 padLeft : function(str, ch, num) { 396 var re = new RegExp(".{" + num + "}$"); 397 if (!ch) ch = " "; 398 var pad = Jek.repeat(ch, num); 399 return re.exec(pad + str)[0]; 400 }, 401 /** 402 * padRight 403 * 404 * @param str 405 * @param char 406 * @param num 407 */ 408 padRight : function (str, ch, num){ 409 var re = new RegExp("^.{" + num + "}"); 410 if (!ch) ch = " "; 411 var pad = Jek.repeat(ch, num); 412 return re.exec(str + pad)[0]; 413 }, 414 415 /** 416 * padRight 417 * 418 * @param str 419 * @param char 420 * @param num 421 */ 422 removeVowels : function (str){ 423 var vowels = /[aeiou]/gi; 424 return str.replace(vowels,''); 425 }, 426 427 /** 428 * Create new package 429 * 430 * @param {String}pk 431 * @param {any}newObj[optional] 432 * @returns {Object} 433 */ 434 newPackage : function(pk, newObj) { 435 var obj = window; 436 var elArr = pk.split('.'); 437 var el; 438 var len = elArr.length; 439 for ( var i = 0; i < len; i++) { 440 el = elArr[i]; 441 if (typeof newObj != 'undefined' && i + 1 == len) { 442 obj[el] = newObj; 443 } else if (!obj[el]) { 444 obj[el] = {}; 445 } 446 obj = obj[el]; 447 } 448 return obj; 449 }, 450 /** 451 * Try all functions in input 452 * 453 * @param {Function}args... 454 * @returns {any} 455 */ 456 tryFns : function() { 457 var ret; 458 for ( var i = 0, len = arguments.length; i < len; i++) { 459 var fn = arguments[i]; 460 try { 461 ret = fn(); 462 return ret; 463 } catch (e) { 464 } 465 } 466 return ret; 467 }, 468 /** 469 * @namespace 470 */ 471 array : { 472 /** 473 * Returns the minimum element of the given array, according to the 474 * natural ordering of its elements. 475 * 476 * @param {Array}array 477 * @returns {Number,String} 478 */ 479 min : function(array) { 480 var mi = array[0]; 481 for ( var i = 1; i < array.length; i++) { 482 var n = array[i]; 483 if (n < mi) { 484 mi = n; 485 } 486 } 487 return mi; 488 }, 489 /** 490 * Returns the maximum element of the given array, according to the 491 * natural ordering of its elements. 492 * 493 * @param {Array}array 494 * @returns {Number,String} 495 */ 496 max : function(array) { 497 var mx = array[0]; 498 for ( var i = 1; i < array.length; i++) { 499 var n = array[i]; 500 if (n > mx) { 501 mx = n; 502 } 503 } 504 return mx; 505 }, 506 /** 507 * Returns the position of the first occurrence of the argument within 508 * the array(==). If the argument doesn't exist in the array, returns 509 * -1. 510 * 511 * @param {Array}array 512 * @param {any}value 513 * @returns {Number} 514 */ 515 indexOf : function(array, value) { 516 for ( var i = 0; i < array.length; i++) { 517 if (value == array[i]) { 518 return i; 519 } 520 } 521 return -1; 522 }, 523 /** 524 * <b>IndexOf Exactly</b><br> 525 * Returns the position of the first occurrence of the argument within 526 * the array(===). If the argument doesn't exist in the array, returns 527 * -1. 528 * 529 * @param {Array}array 530 * @param {any}value 531 * @returns {Number} 532 */ 533 indexOfEx : function(array, value) { 534 for ( var i = 0; i < array.length; i++) { 535 if (value === array[i]) { 536 return i; 537 } 538 } 539 return -1; 540 }, 541 /** 542 * Returns true if this array contains the specified element(==). 543 * 544 * @param {Array}array 545 * @param {any}value 546 * @returns {Boolean} 547 */ 548 contains : function(array, value) { 549 return this.indexOf(array, value) != -1; 550 }, 551 /** 552 * <b>Contains Exactly</b><br> 553 * Returns true if this array contains the specified element(===). 554 * 555 * @param {Array}array 556 * @param {any}value 557 * @returns {Boolean} 558 */ 559 containsEx : function(array, value) { 560 return this.indexOfEx(array, value) != -1; 561 }, 562 /** 563 * Removes the element at the specified position in the array 564 * 565 * @param {Array}array 566 * @param {Number}index 567 * @returns {Object} 568 */ 569 remove : function(array, index) { 570 var value = array[index]; 571 array.splice(index, 1); 572 return value; 573 }, 574 /** 575 * Return a new array with no duplicates 576 * 577 * @param {Array}array 578 * @returns {Array} 579 */ 580 unique : function(array) { 581 var arr = []; 582 var l = array.length; 583 for ( var i = 0; i < l; i++) { 584 for ( var j = i + 1; j < l; j++) { 585 if (array[i] === array[j]) 586 j = ++i; 587 } 588 arr.push(array[i]); 589 } 590 return arr; 591 } 592 }, 593 /** 594 * @namespace 595 */ 596 conversion : { 597 /** 598 * argsToArray 599 * 600 * @param {Object}args 601 * @returns {Array} 602 */ 603 argsToArray : function(args) { 604 var arr = new Array(); 605 for ( var i = 0; i < args.length; i++) { 606 arr.push(args[i]); 607 } 608 return arr; 609 }, 610 /** 611 * decToHex 612 * 613 * @param {Number}number 614 * @returns {String} 615 */ 616 decToHex : function(number) { 617 if (number < 0) { 618 number = 0xFFFFFFFF + number + 1; 619 } 620 return number.toString(16).toUpperCase(); 621 } 622 }, 623 /** 624 * @namespace 625 */ 626 algorithm : {}, 627 /** 628 * @namespace 629 */ 630 stats : { 631 /** 632 * Returns the arithmetic mean of the entries in the input array 633 * 634 * @param {Array}array 635 * @returns {Number} 636 */ 637 mean : function(array) { 638 if (array.length > 0) { 639 return this.sum(array) / array.length; 640 } 641 return 0; 642 }, 643 /** 644 * Returns the sum of the entries in the input array 645 * 646 * @param {Array}array 647 * @returns {Number} 648 */ 649 sum : function(array) { 650 var sum = 0; 651 for ( var i = 0; i < array.length; i++) { 652 sum += array[i]; 653 } 654 return sum; 655 }, 656 /** 657 * Returns the minimum element of the given array, according to the 658 * natural ordering of its elements. 659 * 660 * @param {Array}array 661 * @returns {Number} 662 */ 663 min : function(array) { 664 return Jek.array.min(array); 665 }, 666 /** 667 * Returns the maximum element of the given array, according to the 668 * natural ordering of its elements. 669 * 670 * @param {Array}array 671 * @returns {Number} 672 */ 673 max : function(array) { 674 return Jek.array.max(array); 675 }, 676 /** 677 * Convert values in an array to percentage 678 * 679 * @param {Array}array 680 * @param {String}suffix[optional] 681 * @param {Number}decimalPositions[optional] 682 * <b><i>default</i></b> value = 0 683 * @returns {Array} 684 */ 685 percentage : function(array, suffix, decimalPositions) { 686 var hasSuffix = Jek.isString(suffix) && suffix.length > 0; 687 if (!Jek.isNumber(decimalPositions)) { 688 decimalPositions = 0; 689 } 690 var sum = this.sum(array); 691 var ratio = 100 / sum; 692 var resArray = new Array(); 693 var resItem; 694 for ( var i = 0; i < array.length; i++) { 695 resItem = Jek.roundTo(array[i] * ratio, decimalPositions); 696 697 if (hasSuffix) { 698 resItem += suffix; 699 } 700 resArray.push(resItem); 701 } 702 return resArray; 703 } 704 } 705 }; 706 /** 707 * Encodes the string data to UTF-8 708 * 709 * @param {String}string 710 * @returns {String} 711 */ 712 Jek.conversion.utf8Encode = function(string) { 713 string = string.replace(/\r\n/g, "\n"); 714 var utftext = ""; 715 for ( var n = 0; n < string.length; n++) { 716 var c = string.charCodeAt(n); 717 if (c < 128) { 718 utftext += String.fromCharCode(c); 719 } else if ((c > 127) && (c < 2048)) { 720 utftext += String.fromCharCode((c >> 6) | 192); 721 utftext += String.fromCharCode((c & 63) | 128); 722 } else { 723 utftext += String.fromCharCode((c >> 12) | 224); 724 utftext += String.fromCharCode(((c >> 6) & 63) | 128); 725 utftext += String.fromCharCode((c & 63) | 128); 726 } 727 } 728 return utftext; 729 }; 730 /** 731 * Decodes data, assumed to be UTF-8 encoded, to ISO-8859-1 732 * 733 * @param {String}utftext 734 * @returns {String} 735 */ 736 Jek.conversion.utf8Decode = function(utftext) { 737 var string = ""; 738 var i = 0; 739 var c = c1 = c2 = 0; 740 741 while (i < utftext.length) { 742 c = utftext.charCodeAt(i); 743 if (c < 128) { 744 string += String.fromCharCode(c); 745 i++; 746 } else if ((c > 191) && (c < 224)) { 747 c2 = utftext.charCodeAt(i + 1); 748 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 749 i += 2; 750 } else { 751 c2 = utftext.charCodeAt(i + 1); 752 c3 = utftext.charCodeAt(i + 2); 753 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) 754 | (c3 & 63)); 755 i += 3; 756 } 757 } 758 return string; 759 }; 760 Jek.conversion.base64KeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 761 /** 762 * Jek.conversion.base64Encode 763 * 764 * @param {String}string 765 * @returns {String} 766 */ 767 Jek.conversion.base64Encode = function(str) { 768 var res = ''; 769 var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 770 var i = 0; 771 var keyStr = Jek.conversion.base64KeyStr; 772 773 str = Jek.conversion.utf8Encode(str); 774 775 while (i < str.length) { 776 777 chr1 = str.charCodeAt(i++); 778 chr2 = str.charCodeAt(i++); 779 chr3 = str.charCodeAt(i++); 780 781 enc1 = chr1 >> 2; 782 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 783 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 784 enc4 = chr3 & 63; 785 786 if (isNaN(chr2)) { 787 enc3 = enc4 = 64; 788 } else if (isNaN(chr3)) { 789 enc4 = 64; 790 } 791 792 res = res + 793 keyStr.charAt(enc1) + keyStr.charAt(enc2) + 794 keyStr.charAt(enc3) + keyStr.charAt(enc4); 795 796 } 797 return res; 798 }; 799 /** 800 * Jek.conversion.base64Decode 801 * 802 * @param {String}string 803 * @returns {String} 804 */ 805 Jek.conversion.base64Decode = function(str) { 806 var res = ''; 807 var chr1, chr2, chr3; 808 var enc1, enc2, enc3, enc4; 809 var i = 0; 810 var keyStr = Jek.conversion.base64KeyStr; 811 812 str = str.replace(/[^A-Za-z0-9\+\/\=]/g, ''); 813 814 while (i < str.length) { 815 816 enc1 = keyStr.indexOf(str.charAt(i++)); 817 enc2 = keyStr.indexOf(str.charAt(i++)); 818 enc3 = keyStr.indexOf(str.charAt(i++)); 819 enc4 = keyStr.indexOf(str.charAt(i++)); 820 821 chr1 = (enc1 << 2) | (enc2 >> 4); 822 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 823 chr3 = ((enc3 & 3) << 6) | enc4; 824 825 res = res + String.fromCharCode(chr1); 826 827 if (enc3 != 64) { 828 res = res + String.fromCharCode(chr2); 829 } 830 if (enc4 != 64) { 831 res = res + String.fromCharCode(chr3); 832 } 833 } 834 return Jek.conversion.utf8Decode(res); 835 }; 836 /** 837 * Jek.algorithm.crc32 838 * 839 * @param {String}string 840 * @returns {String} 841 */ 842 Jek.algorithm.crc32 = function(string) { 843 string = Jek.conversion.utf8Encode(string); 844 var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D"; 845 var crc = 0; 846 var x = 0; 847 var y = 0; 848 crc = crc ^ (-1); 849 for ( var i = 0, iTop = string.length; i < iTop; i++) { 850 y = (crc ^ string.charCodeAt(i)) & 0xFF; 851 x = "0x" + table.substr(y * 9, 8); 852 crc = (crc >>> 8) ^ x; 853 } 854 return Jek.conversion.decToHex(crc ^ (-1)); 855 }; 856 /** 857 * The Levenshtein distance is a metric for measuring the amount of difference 858 * between two strings, is the minimum number of edits needed to transform one 859 * string into the other, with the allowable edit operations being insertion, 860 * deletion, or substitution of a single character. 861 * 862 * @param {String}string1 863 * @param {String}string2 864 * @returns {Number} 865 */ 866 Jek.algorithm.levenshteinDistance = function(string1, string2) { 867 var d = new Array(), n, m, i, j, s_i, t_j, cost; 868 // Step I 869 n = string1.length; 870 m = string2.length; 871 if (n == 0) { 872 return m; 873 } 874 if (m == 0) { 875 return n; 876 } 877 for (w = 0; w <= n + 1; w++) { 878 var arr = new Array(); 879 for (ww = 0; ww <= m + 1; ww++) { 880 arr.push({}); 881 } 882 d.push(arr); 883 } 884 // Step II 885 for (i = 0; i <= n; i++) { 886 d[i][0] = i; 887 } 888 for (j = 0; j <= m; j++) { 889 d[0][j] = j; 890 } 891 // Step III 892 for (i = 1; i <= n; i++) { 893 s_i = string1.charAt(i - 1); 894 // Step IV 895 for (j = 1; j <= m; j++) { 896 t_j = string2.charAt(j - 1); 897 // Step V 898 if (s_i == t_j) { 899 cost = 0; 900 } else { 901 cost = 1; 902 } 903 // Step VI 904 d[i][j] = Jek.array.min([ d[i - 1][j] + 1, d[i][j - 1] + 1, 905 d[i - 1][j - 1] + cost ]); 906 } 907 } 908 // Step VII 909 return d[n][m]; 910 }; 911 /** 912 * @param {String}str1 913 * @param {String}str2 914 * @param {Number}decimalPositions[optional] 915 * <b><i>default</i></b> value = 0 916 * @returns {Number} 917 */ 918 Jek.algorithm.stringDistancePerc = function(str1, str2, decimalPositions) { 919 if (!Jek.isNumber(decimalPositions)) { 920 decimalPositions = 0; 921 } 922 var l1 = str1.length; 923 var l2 = str2.length; 924 var ratio = l1 >= l2 ? 100 / l1 : 100 / l2; 925 926 return Jek.roundTo(Jek.algorithm.levenshteinDistance(str1, str2) * ratio, 927 decimalPositions); 928 }; 929 /** 930 * Check if a string contains a sequence of characters or numbers 931 * 932 * @example <b>Example:</b> 12345, abcdef, 876543210, 123bcde, 12344321, etc. 933 * @param {String}str 934 * @returns {Number} 935 */ 936 Jek.algorithm.charSequenceCheck = function(str) { 937 var res = new Array(); 938 var i; 939 var l = str.length; 940 for (i = 0; i < l - 1; i++) { 941 res.push(str.charCodeAt(i + 1) - str.charCodeAt(i)); 942 } 943 res = Jek.array.unique(res); 944 if (res.length == 0) { 945 return 0; 946 } else if (res.length == 1) { 947 if (res[0] == -1 || res[0] == 0 || res[0] == 1) { 948 return 1; 949 } else { 950 return 0; 951 } 952 } else if (res.length == l-1) { 953 return 0; 954 } else { 955 return res.length; 956 } 957 }; 958 /** 959 * Generate a password from string (like Name + Surname) based on a passed seed 960 * 961 * @param {String}str 962 * @param {String}seed 963 * @param {Number}pswLen 964 * @returns {String} 965 */ 966 Jek.algorithm.generatePassword = function(str, seed, pswLen) { 967 var inp = Jek.algorithm.crc32(str + seed); 968 var noVowels = Jek.removeVowels(str).toLowerCase(); 969 var prefix = ''; 970 var sufix = ''; 971 972 if (noVowels.length>0){ 973 sufix = noVowels.charAt(0); 974 sufix+=sufix.toUpperCase(); 975 976 prefix = noVowels.charAt(0); 977 978 var words = Jek.words(noVowels); 979 if (words.length>1){ 980 prefix += words[1].charAt(0); 981 }else if(noVowels.length>1) { 982 prefix += noVowels.charAt(1); 983 } 984 } 985 986 var res = ''; 987 for (n=0; n < pswLen; n++){ 988 var out = 0; 989 for (i in inp){ 990 out ^= inp.charCodeAt(i)*n; 991 } 992 res +=out; 993 } 994 var num = ''; 995 var prefixSufixLen=prefix.length+sufix.length; 996 997 if (pswLen-prefixSufixLen>0){ 998 num = Jek.padLeft(res,'0', pswLen-prefixSufixLen); 999 } 1000 return prefix + num + sufix; 1001 }; 1002 /** 1003 * Calculate the dv1 hash of a string. 1004 * 1005 * @param {String}str 1006 * @param {Number}len 1007 * @returns {String} 1008 */ 1009 Jek.algorithm.dv1= function(str, len) { 1010 var seed = 'dv1'; 1011 var out=len+str.length+1; 1012 var crc = Jek.algorithm.crc32(seed+str+out); 1013 var res = crc; 1014 while (res.length < len) { 1015 out /= 1.00003; 1016 res += Jek.algorithm.crc32(''+(crc.charCodeAt(crc.length-1)+out)); 1017 } 1018 return res.substring(0, len); 1019 }; 1020 /** 1021 * Encrypt string 1022 * 1023 * @param {String}str 1024 * @param {String}psw 1025 * @returns {String} 1026 */ 1027 Jek.algorithm.jsEncrypt = function(str, psw) { 1028 var bigPsw= Jek.algorithm.dv1(psw, str.length); 1029 var res = ''; 1030 for (i in str){ 1031 res+= String.fromCharCode(str.charCodeAt(i) ^ bigPsw.charCodeAt(i)); 1032 } 1033 return Jek.conversion.base64Encode(res); 1034 }; 1035 /** 1036 * Decrypt string 1037 * 1038 * @param {String}str 1039 * @param {String}psw 1040 * @returns {String} 1041 */ 1042 Jek.algorithm.jsDecrypt = function(str, psw) { 1043 str = Jek.conversion.base64Decode(str); 1044 var bigPsw= Jek.algorithm.dv1(psw, str.length); 1045 var res = ''; 1046 for (i in str){ 1047 res+= String.fromCharCode(str.charCodeAt(i) ^ bigPsw.charCodeAt(i)); 1048 } 1049 return res; 1050 }; 1051 /** 1052 * Faster javascript StringBuilder implementation 1053 * 1054 * @class 1055 * @param {String}string[optional] 1056 * <b><i>default</i></b> value = "" 1057 * @returns {JekString} 1058 */ 1059 function JekString(string) { 1060 var _length = 0; 1061 1062 /** 1063 * All strings 1064 */ 1065 var _strings = new Array(Jek.defParam(string, '')); 1066 1067 /** 1068 * Returns the length (character count). 1069 * 1070 * @returns {Number} 1071 */ 1072 this.length = function() { 1073 return _length; 1074 }; 1075 /** 1076 * Appends the specified string to this character sequence. 1077 * 1078 * @param {String}string 1079 * @returns {JekString} 1080 */ 1081 this.append = function(string) { 1082 if (string) { 1083 _strings.push(string); 1084 _length += string.length; 1085 } 1086 return this; 1087 }; 1088 /** 1089 * Allows you to define a tokenized string and pass an arbitrary number of 1090 * arguments to replace the tokens, and append to this character sequence. 1091 * 1092 * @param {String}string 1093 * @param {String}args... 1094 * @returns {JekString} 1095 * @example JekString.appendFormat('Lorem {0} dolor {1} amet','ipsum','sit') -> 1096 * <i>"Lorem ipsum dolor sit amet"</i> 1097 */ 1098 this.appendFormat = function() { 1099 if (arguments.length > 0) { 1100 var str = arguments[0]; 1101 for ( var i = 1; i < arguments.length; ++i) { 1102 str = str.replace("{" + (i - 1) + "}", arguments[i]); 1103 } 1104 _strings.push(str); 1105 _length += str.length; 1106 } 1107 return this; 1108 }; 1109 /** 1110 * Removes all character sequence. 1111 * 1112 * @returns {JekString} 1113 */ 1114 this.clear = function() { 1115 _strings = new Array(''); 1116 _length = 0; 1117 return this; 1118 }; 1119 /** 1120 * Returns a string representing the data in this sequence. 1121 * 1122 * @returns {String} 1123 */ 1124 this.toString = function() { 1125 return _strings.join(''); 1126 }; 1127 }; 1128 /** 1129 * JekArray 1130 * 1131 * @class 1132 * @param {Array}array[optional] 1133 * <b><i>default</i></b> value = new Array() 1134 * @returns {JekArray} 1135 */ 1136 function JekArray(arrey) { 1137 /** 1138 * All items 1139 * 1140 * @type Array 1141 */ 1142 this.items = arrey || new Array(); 1143 /** 1144 * Returns the number of elements in this array 1145 * 1146 * @returns {Number} 1147 */ 1148 this.size = function() { 1149 return this.items.length; 1150 }; 1151 /** 1152 * Returns true if this array contains the specified element(==). 1153 * 1154 * @param {any}value 1155 * @returns {Boolean} 1156 */ 1157 this.contains = function(value) { 1158 return Jek.array.contains(this.items, value); 1159 }; 1160 /** 1161 * <b>Contains Exactly</b><br> 1162 * Returns true if this array contains the specified element(===). 1163 * 1164 * @param {any}value 1165 * @returns {Boolean} 1166 */ 1167 this.containsEx = function(value) { 1168 return Jek.array.containsEx(this.items, value); 1169 }; 1170 /** 1171 * Returns the position of the first occurrence of the argument within the 1172 * array(==). If the argument doesn't exist in the array, returns -1. 1173 * 1174 * @param {any}value 1175 * @returns {Number} 1176 */ 1177 this.indexOf = function(value) { 1178 return Jek.array.indexOf(this.items, value); 1179 }; 1180 /** 1181 * <b>IndexOf Exactly</b><br> 1182 * Returns the position of the first occurrence of the argument within the 1183 * array(===). If the argument doesn't exist in the array, returns -1. 1184 * 1185 * @param {any}value 1186 * @returns {Number} 1187 */ 1188 this.indexOfEx = function(value) { 1189 return Jek.array.indexOfEx(this.items, value); 1190 }; 1191 /** 1192 * Appends the specified element to the end of this array. 1193 * 1194 * @param {any}value 1195 * @returns {Array} 1196 */ 1197 this.add = function(value) { 1198 this.items.push(value); 1199 return this.items; 1200 }; 1201 /** 1202 * Replaces the element at the specified position in this array with the 1203 * specified element. 1204 * 1205 * @param {Number}index 1206 * @param {any}value 1207 * @returns {Boolean} 1208 */ 1209 this.set = function(index, value) { 1210 if (index >= 0 && index < this.items.length) { 1211 this.items[index] = value; 1212 return true; 1213 } else { 1214 return false; 1215 } 1216 }; 1217 /** 1218 * Removes the element at the specified position in the array 1219 * 1220 * @param {Number}index 1221 * @returns {any} 1222 */ 1223 this.remove = function(index) { 1224 return Jek.array.remove(this.items, index); 1225 }; 1226 /** 1227 * Returns the element at the specified position in this array. 1228 * 1229 * @param {Number}index 1230 * @returns {any} 1231 */ 1232 this.get = function(index) { 1233 return this.items[index]; 1234 }; 1235 /** 1236 * Returns the last element. 1237 * 1238 * @returns {any} 1239 */ 1240 this.getLast = function() { 1241 if (this.items.length > 0) { 1242 return this.items[this.items.length - 1]; 1243 } 1244 return undefined; 1245 }; 1246 /** 1247 * Returns the minimum element of this array, according to the natural 1248 * ordering of its elements. 1249 * 1250 * @returns {Number,String} 1251 */ 1252 this.min = function() { 1253 return Jek.array.min(this.items); 1254 }; 1255 /** 1256 * Returns the maximum element of this array, according to the natural 1257 * ordering of its elements. 1258 * 1259 * @returns {Number,String} 1260 */ 1261 this.max = function() { 1262 return Jek.array.max(this.items); 1263 }; 1264 /** 1265 * 1266 * @returns {Array} 1267 */ 1268 this.unique = function() { 1269 return Jek.array.unique(this.items); 1270 }; 1271 /** 1272 * Iterates on array calling the supplied function. 1273 * 1274 * @param {Function}fn 1275 * @param {Object}scope[optional] 1276 * <b><i>default</i></b> value = entry 1277 * @returns {any} 1278 * @example JekArray.each(function(key, value) {<br> 1279 * ...<br> 1280 * }); 1281 * @example JekArray.each(function(key, value) {<br> 1282 * ...<br> }, scope); 1283 */ 1284 this.each = function(fn, scope) { 1285 for ( var i = 0; i < this.items.length; i++) { 1286 if (fn.call(scope || this.items[i], this.items[i], i, this.items) === false) { 1287 return i; 1288 } 1289 } 1290 }; 1291 }; 1292 /** 1293 * JekKeyValue 1294 * 1295 * @class 1296 * @param {any}key 1297 * @param {any}value 1298 * @returns {JekKeyValue} 1299 */ 1300 function JekKeyValue(key, value) { 1301 /** 1302 * key 1303 * 1304 * @type any 1305 */ 1306 this.key = key; 1307 /** 1308 * value 1309 * 1310 * @type any 1311 */ 1312 this.value = value; 1313 }; 1314 /** 1315 * JekMap 1316 * 1317 * @class 1318 * @returns {JekMap} 1319 */ 1320 function JekMap() { 1321 /** 1322 * @type Array 1323 */ 1324 this.items = new Array(); 1325 /** 1326 * size 1327 * 1328 * @returns {Number} size 1329 */ 1330 this.size = function() { 1331 var sz = 0; 1332 for ( var key in this.items) { 1333 sz++; 1334 } 1335 return sz; 1336 }; 1337 /** 1338 * set 1339 * 1340 * @param {any}key 1341 * @param {any}value 1342 * @returns {any} value 1343 */ 1344 this.set = function(key, value) { 1345 this.items[key] = value; 1346 return value; 1347 }; 1348 /** 1349 * get 1350 * 1351 * @param {any}key 1352 * @returns {any} value 1353 */ 1354 this.get = function(key) { 1355 return this.items[key]; 1356 }; 1357 /** 1358 * remove 1359 * 1360 * @param {any}key 1361 * @returns {any} value 1362 */ 1363 this.remove = function(key) { 1364 var value = this.items[key]; 1365 delete this.items[key]; 1366 return value; 1367 }; 1368 /** 1369 * clear 1370 * 1371 * @returns {Boolean} 1372 */ 1373 this.clear = function() { 1374 for ( var key in this.items) { 1375 this.remove(key); 1376 } 1377 return true; 1378 }; 1379 /** 1380 * containsKey 1381 * 1382 * @param {any}key 1383 * @returns {Boolean} 1384 */ 1385 this.containsKey = function(key) { 1386 return (typeof this.items[key] != 'undefined'); 1387 }; 1388 /** 1389 * containsValue 1390 * 1391 * @param {any}value 1392 * @returns {Boolean} 1393 */ 1394 this.containsValue = function(value) { 1395 for ( var key in this.items) { 1396 if (this.items[key] === value) { 1397 return true; 1398 } 1399 } 1400 return false; 1401 }; 1402 /** 1403 * entrySet 1404 * 1405 * @returns {Array} 1406 */ 1407 this.entrySet = function() { 1408 var res = new Array(); 1409 for ( var key in this.items) { 1410 res.push(this.items[key]); 1411 } 1412 return res; 1413 }; 1414 /** 1415 * keySet 1416 * 1417 * @returns {Array} 1418 */ 1419 this.keySet = function() { 1420 var res = new Array(); 1421 for ( var key in this.items) { 1422 res.push(key); 1423 } 1424 return res; 1425 }; 1426 /** 1427 * values 1428 * 1429 * @returns {[JekKeyValue]} Array of JekKeyValue 1430 */ 1431 this.values = function() { 1432 var res = new Array(); 1433 for ( var key in this.items) { 1434 res.push(new JekKeyValue(key, this.items[key])); 1435 } 1436 return res; 1437 }; 1438 /** 1439 * Iterates on elements calling the supplied function. 1440 * 1441 * @param {Function}fn 1442 * @param {Object}scope[optional] 1443 * <b><i>default</i></b> value = {JekKeyValue}entry 1444 * @returns {any} 1445 * @example JekMap.each(function(key, value) {<br> 1446 * ...<br> 1447 * }); 1448 * @example JekMap.each(function(key, value) {<br> 1449 * ...<br>}, scope); 1450 */ 1451 this.each = function(fn, scope) { 1452 var entry; 1453 for ( var key in this.items) { 1454 entry = new JekKeyValue(key, this.items[key]); 1455 if (fn.call(scope || entry, entry.key, entry.value) === false) { 1456 return entry; 1457 } 1458 } 1459 }; 1460 }; 1461 /** 1462 * JekStats 1463 * 1464 * @class 1465 */ 1466 function JekStats() { 1467 /** 1468 * @type JekMap 1469 */ 1470 this.stats = new JekMap(); 1471 /** 1472 * @param {String}statId 1473 * @param {Number}value[optional] 1474 * <b><i>default</i></b> value = 1 1475 * @returns {Number}value 1476 */ 1477 this.increase = function(statId, value) { 1478 value = Jek.defParam(value, 1); 1479 var oldValue; 1480 if (this.stats.containsKey(statId)) { 1481 oldValue = this.stats.get(statId); 1482 return this.stats.set(statId, oldValue + value); 1483 } else { 1484 return this.stats.set(statId, value); 1485 } 1486 }; 1487 /** 1488 * @param {String}statId 1489 * @param {Number}value[optional] 1490 * <b><i>default</i></b> value = 1 1491 * @returns {Number}value 1492 */ 1493 this.decrease = function(statId, value) { 1494 value = Jek.defParam(value, 1); 1495 var oldValue; 1496 if (this.stats.containsKey(statId)) { 1497 oldValue = this.stats.get(statId); 1498 return this.stats.set(statId, oldValue - value); 1499 } else { 1500 return this.stats.set(statId, 0 - value); 1501 } 1502 }; 1503 /** 1504 * @param {String}statId 1505 * @returns {Number}value 1506 */ 1507 this.get = function(statId) { 1508 return this.stats.get(statId); 1509 }; 1510 } 1511 /** 1512 * JekLinkEntry 1513 * 1514 * @class 1515 * @param {any}value 1516 * @param {JekLinkEntry,null}prev 1517 * @param {JekLinkEntry,null}next 1518 * @returns {JekLinkEntry} 1519 * @see JekLinkedList 1520 */ 1521 function JekLinkEntry(value, prev, next) { 1522 this.value = value; 1523 this.prev = prev; 1524 this.next = next; 1525 }; 1526 1527 /** 1528 * JekLinkedList 1529 * 1530 * @class 1531 * @returns {JekLinkedList} 1532 */ 1533 function JekLinkedList() { 1534 var _first = null; 1535 var _last = null; 1536 /** 1537 * add 1538 * 1539 * @param {any}value 1540 */ 1541 this.add = function(value) { 1542 var entry = null; 1543 if (!_first) { 1544 _first = new JekLinkEntry(value, null, null); 1545 _last = _first; 1546 } else { 1547 entry = new JekLinkEntry(value, _last, null); 1548 _last.next = entry; 1549 _last = entry; 1550 } 1551 }; 1552 /** 1553 * addFirst 1554 * 1555 * @param {any}value 1556 * @returns {Boolean} 1557 */ 1558 this.addFirst = function(value) { 1559 return this.insert(0, value); 1560 }; 1561 /** 1562 * addAll 1563 * 1564 * @param {Array}values 1565 * @returns {Boolean} 1566 */ 1567 this.addAll = function(values) { 1568 var res = false; 1569 for ( var index in values) { 1570 this.add(values[index]); 1571 res = true; 1572 } 1573 return res; 1574 }; 1575 /** 1576 * first 1577 * 1578 * @returns {any} 1579 */ 1580 this.first = function() { 1581 if (_first) { 1582 return _first.value; 1583 } 1584 }; 1585 /** 1586 * last 1587 * 1588 * @returns {any} 1589 */ 1590 this.last = function() { 1591 if (_last) { 1592 return _last.value; 1593 } 1594 }; 1595 /** 1596 * get 1597 * 1598 * @param {Number}index 1599 * @returns {any} 1600 */ 1601 this.get = function(index) { 1602 var entry = this._getEntry(index); 1603 if (entry) { 1604 return entry.value; 1605 } else { 1606 return undefined; 1607 } 1608 }; 1609 /** 1610 * _getEntry 1611 * 1612 * @param {Number}index 1613 * @returns {JekLinkEntry} 1614 */ 1615 this._getEntry = function(index) { 1616 var i = 0; 1617 if (_first) { 1618 var entry = _first; 1619 while (entry) { 1620 if (i == index) { 1621 return entry; 1622 } 1623 entry = entry.next; 1624 i++; 1625 } 1626 } 1627 return undefined; 1628 }; 1629 /** 1630 * set 1631 * 1632 * @param {Number}index 1633 * @param {any}value 1634 * @returns {Boolean} 1635 */ 1636 this.set = function(index, value) { 1637 var entry = this._getEntry(index); 1638 if (entry) { 1639 entry.value = value; 1640 return true; 1641 } else { 1642 return false; 1643 } 1644 }; 1645 /** 1646 * insert 1647 * 1648 * @param {Number}index 1649 * @param {any}value 1650 * @returns {Boolean} 1651 */ 1652 this.insert = function(index, value) { 1653 var entry = this._getEntry(index); 1654 var newEntry; 1655 if (entry) { 1656 if (entry == _first) { 1657 newEntry = new JekLinkEntry(value, null, entry); 1658 entry.prev = newEntry; 1659 _first = newEntry; 1660 } 1661 // else if (entry == _last) { 1662 // newEntry = new JekLinkEntry(value, entry, null); 1663 // entry.next = newEntry; 1664 // _last = newEntry; 1665 // } 1666 else { 1667 newEntry = new JekLinkEntry(value, entry.prev, entry); 1668 entry.prev.next = newEntry; 1669 entry.prev = newEntry; 1670 } 1671 } else { 1672 this.add(value); 1673 } 1674 return true; 1675 }; 1676 /** 1677 * size 1678 * 1679 * @returns {Number} 1680 */ 1681 this.size = function() { 1682 var sz = 0; 1683 if (_first) { 1684 var entry = _first; 1685 while (entry) { 1686 entry = entry.next; 1687 sz++; 1688 } 1689 } 1690 return sz; 1691 }; 1692 /** 1693 * toArray 1694 * 1695 * @returns {Array} 1696 */ 1697 this.toArray = function() { 1698 var arr = new Array(); 1699 if (_first) { 1700 var entry = _first; 1701 while (entry) { 1702 arr.push(entry.value); 1703 entry = entry.next; 1704 } 1705 } 1706 return arr; 1707 }; 1708 /** 1709 * toJekLinkEntryArray 1710 * 1711 * @returns {[JekLinkEntry]} Array of JekLinkEntry 1712 */ 1713 this.toJekLinkEntryArray = function() { 1714 var arr = new Array(); 1715 if (_first) { 1716 var entry = _first; 1717 while (entry) { 1718 arr.push(entry); 1719 entry = entry.next; 1720 } 1721 } 1722 return arr; 1723 }; 1724 /** 1725 * contains 1726 * 1727 * @param {any}value 1728 * @returns {Boolean} 1729 */ 1730 this.contains = function(value) { 1731 return (this.indexOf(value) != -1); 1732 }; 1733 /** 1734 * indexOf 1735 * 1736 * @param {any}value 1737 * @returns {Number} 1738 */ 1739 this.indexOf = function(value) { 1740 var res = 0; 1741 if (_first) { 1742 var entry = _first; 1743 while (entry) { 1744 if (entry.value === value) { 1745 return res; 1746 } 1747 entry = entry.next; 1748 res++; 1749 } 1750 } 1751 return -1; 1752 }; 1753 /** 1754 * remove 1755 * 1756 * @param {any}value 1757 * @returns {Boolean} 1758 */ 1759 this.remove = function(value) { 1760 if (_first) { 1761 var entry = _first; 1762 while (entry) { 1763 if (entry.value === value) { 1764 if (entry == _first) { 1765 _first = entry.next; 1766 if (_first) { 1767 _first.prev = null; 1768 } else { 1769 _last = null; 1770 } 1771 1772 } else if (entry == _last) { 1773 _last = entry.prev; 1774 _last.next = null; 1775 } else { 1776 entry.prev.next = entry.next; 1777 entry.next.prev = entry.prev; 1778 } 1779 delete entry; 1780 return true; 1781 } 1782 entry = entry.next; 1783 } 1784 } 1785 return false; 1786 }; 1787 /** 1788 * removeLast 1789 * 1790 * @returns {Boolean} 1791 */ 1792 this.removeLast = function() { 1793 if (_last) { 1794 _last = _last.prev; 1795 _last.next = null; 1796 return true; 1797 } 1798 return false; 1799 }; 1800 /** 1801 * removeFirst 1802 * 1803 * @returns {Boolean} 1804 */ 1805 this.removeFirst = function() { 1806 if (_first) { 1807 _first = _first.next; 1808 if (_first) { 1809 _first.prev = null; 1810 } else { 1811 _last = null; 1812 } 1813 return true; 1814 } 1815 return false; 1816 }; 1817 /** 1818 * clear 1819 */ 1820 this.clear = function() { 1821 _first = null; 1822 _last = null; 1823 }; 1824 /** 1825 * each 1826 * 1827 * @param {Function}fn 1828 * @param {Object}scope[optional] 1829 * <b><i>default</i></b> value = {JekLinkEntry}entry 1830 * @returns {any} 1831 * @example JekLinkedList.each(function(key, value) {<br> 1832 * ...<br> 1833 * }); 1834 * @example JekLinkedList.each(function(key, value) {<br> 1835 * ...<br>}, scope); 1836 */ 1837 this.each = function(fn, scope) { 1838 var i = 0; 1839 if (_first) { 1840 var entry = _first; 1841 while (entry) { 1842 if (fn.call(scope || entry, entry.value, i) === false) { 1843 return entry; 1844 } 1845 ; 1846 entry = entry.next; 1847 i++; 1848 } 1849 } 1850 }; 1851 };