1 2/** 3 * Copyright 2010 Tim Down. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18/** 19 * jshashtable 20 * 21 * jshashtable is a JavaScript implementation of a hash table. It creates a single constructor function called Hashtable 22 * in the global scope. 23 * 24 * Author: Tim Down <[email protected]> 25 * Version: 2.1 26 * Build date: 21 March 2010 27 * Website: http://www.timdown.co.uk/jshashtable 28 */ 29 30var Hashtable = (function() { 31 var FUNCTION = "function"; 32 33 var arrayRemoveAt = (typeof Array.prototype.splice == FUNCTION) ? 34 function(arr, idx) { 35 arr.splice(idx, 1); 36 } : 37 38 function(arr, idx) { 39 var itemsAfterDeleted, i, len; 40 if (idx === arr.length - 1) { 41 arr.length = idx; 42 } else { 43 itemsAfterDeleted = arr.slice(idx + 1); 44 arr.length = idx; 45 for (i = 0, len = itemsAfterDeleted.length; i < len; ++i) { 46 arr[idx + i] = itemsAfterDeleted[i]; 47 } 48 } 49 }; 50 51 function hashObject(obj) { 52 var hashCode; 53 if (typeof obj == "string") { 54 return obj; 55 } else if (typeof obj.hashCode == FUNCTION) { 56 // Check the hashCode method really has returned a string 57 hashCode = obj.hashCode(); 58 return (typeof hashCode == "string") ? hashCode : hashObject(hashCode); 59 } else if (typeof obj.toString == FUNCTION) { 60 return obj.toString(); 61 } else { 62 try { 63 return String(obj); 64 } catch (ex) { 65 // For host objects (such as ActiveObjects in IE) that have no toString() method and throw an error when 66 // passed to String() 67 return Object.prototype.toString.call(obj); 68 } 69 } 70 } 71 72 function equals_fixedValueHasEquals(fixedValue, variableValue) { 73 return fixedValue.equals(variableValue); 74 } 75 76 function equals_fixedValueNoEquals(fixedValue, variableValue) { 77 return (typeof variableValue.equals == FUNCTION) ? 78 variableValue.equals(fixedValue) : (fixedValue === variableValue); 79 } 80 81 function createKeyValCheck(kvStr) { 82 return function(kv) { 83 if (kv === null) { 84 throw new Error("null is not a valid " + kvStr); 85 } else if (typeof kv == "undefined") { 86 throw new Error(kvStr + " must not be undefined"); 87 } 88 }; 89 } 90 91 var checkKey = createKeyValCheck("key"), checkValue = createKeyValCheck("value"); 92 93 /*----------------------------------------------------------------------------------------------------------------*/ 94 95 function Bucket(hash, firstKey, firstValue, equalityFunction) { 96 this[0] = hash; 97 this.entries = []; 98 this.addEntry(firstKey, firstValue); 99 100 if (equalityFunction !== null) { 101 this.getEqualityFunction = function() { 102 return equalityFunction; 103 }; 104 } 105 } 106 107 var EXISTENCE = 0, ENTRY = 1, ENTRY_INDEX_AND_VALUE = 2; 108 109 function createBucketSearcher(mode) { 110 return function(key) { 111 var i = this.entries.length, entry, equals = this.getEqualityFunction(key); 112 while (i--) { 113 entry = this.entries[i]; 114 if ( equals(key, entry[0]) ) { 115 switch (mode) { 116 case EXISTENCE: 117 return true; 118 case ENTRY: 119 return entry; 120 case ENTRY_INDEX_AND_VALUE: 121 return [ i, entry[1] ]; 122 } 123 } 124 } 125 return false; 126 }; 127 } 128 129 function createBucketLister(entryProperty) { 130 return function(aggregatedArr) { 131 var startIndex = aggregatedArr.length; 132 for (var i = 0, len = this.entries.length; i < len; ++i) { 133 aggregatedArr[startIndex + i] = this.entries[i][entryProperty]; 134 } 135 }; 136 } 137 138 Bucket.prototype = { 139 getEqualityFunction: function(searchValue) { 140 return (typeof searchValue.equals == FUNCTION) ? equals_fixedValueHasEquals : equals_fixedValueNoEquals; 141 }, 142 143 getEntryForKey: createBucketSearcher(ENTRY), 144 145 getEntryAndIndexForKey: createBucketSearcher(ENTRY_INDEX_AND_VALUE), 146 147 removeEntryForKey: function(key) { 148 var result = this.getEntryAndIndexForKey(key); 149 if (result) { 150 arrayRemoveAt(this.entries, result[0]); 151 return result[1]; 152 } 153 return null; 154 }, 155 156 addEntry: function(key, value) { 157 this.entries[this.entries.length] = [key, value]; 158 }, 159 160 keys: createBucketLister(0), 161 162 values: createBucketLister(1), 163 164 getEntries: function(entries) { 165 var startIndex = entries.length; 166 for (var i = 0, len = this.entries.length; i < len; ++i) { 167 // Clone the entry stored in the bucket before adding to array
168 entries[startIndex + i] = this.entries[i].slice(0); 169 } 170 }, 171 172 containsKey: createBucketSearcher(EXISTENCE), 173 174 containsValue: function(value) { 175 var i = this.entries.length; 176 while (i--) { 177 if ( value === this.entries[i][1] ) { 178 return true; 179 } 180 } 181 return false; 182 } 183 }; 184 185 /*----------------------------------------------------------------------------------------------------------------*/ 186 187 // Supporting functions for searching hashtable buckets 188 189 function searchBuckets(buckets, hash) { 190 var i = buckets.length, bucket; 191 while (i--) { 192 bucket = buckets[i]; 193 if (hash === bucket[0]) { 194 return i; 195 } 196 } 197 return null; 198 } 199 200 function getBucketForHash(bucketsByHash, hash) { 201 var bucket = bucketsByHash[hash]; 202 203 // Check that this is a genuine bucket and not something inherited from the bucketsByHash's prototype 204 return ( bucket && (bucket instanceof Bucket) ) ? bucket : null; 205 } 206 207 /*----------------------------------------------------------------------------------------------------------------*/ 208 209 function Hashtable(hashingFunctionParam, equalityFunctionParam) { 210 var that = this; 211 var buckets = []; 212 var bucketsByHash = {}; 213 214 var hashingFunction = (typeof hashingFunctionParam == FUNCTION) ? hashingFunctionParam : hashObject; 215 var equalityFunction = (typeof equalityFunctionParam == FUNCTION) ? equalityFunctionParam : null; 216 217 this.put = function(key, value) { 218 checkKey(key); 219 checkValue(value); 220 var hash = hashingFunction(key), bucket, bucketEntry, oldValue = null; 221 222 // Check if a bucket exists for the bucket key 223 bucket = getBucketForHash(bucketsByHash, hash); 224 if (bucket) { 225 // Check this bucket to see if it already contains this key 226 bucketEntry = bucket.getEntryForKey(key); 227 if (bucketEntry) { 228 // This bucket entry is the current mapping of key to value, so replace old value and we're done. 229 oldValue = bucketEntry[1]; 230 bucketEntry[1] = value; 231 } else { 232 // The bucket does not contain an entry for this key, so add one 233 bucket.addEntry(key, value); 234 } 235 } else { 236 // No bucket exists for the key, so create one and put our key/value mapping in 237 bucket = new Bucket(hash, key, value, equalityFunction); 238 buckets[buckets.length] = bucket; 239 bucketsByHash[hash] = bucket; 240 } 241 return oldValue; 242 }; 243 244 this.get = function(key) { 245 checkKey(key); 246 247 var hash = hashingFunction(key); 248 249 // Check if a bucket exists for the bucket key 250 var bucket = getBucketForHash(bucketsByHash, hash); 251 if (bucket) { 252 // Check this bucket to see if it contains this key 253 var bucketEntry = bucket.getEntryForKey(key); 254 if (bucketEntry) { 255 // This bucket entry is the current mapping of key to value, so return the value. 256 return bucketEntry[1]; 257 } 258 } 259 return null; 260 }; 261 262 this.containsKey = function(key) { 263 checkKey(key); 264 var bucketKey = hashingFunction(key); 265 266 // Check if a bucket exists for the bucket key 267 var bucket = getBucketForHash(bucketsByHash, bucketKey); 268 269 return bucket ? bucket.containsKey(key) : false; 270 }; 271 272 this.containsValue = function(value) { 273 checkValue(value); 274 var i = buckets.length; 275 while (i--) { 276 if (buckets[i].containsValue(value)) { 277 return true; 278 } 279 } 280 return false; 281 }; 282 283 this.clear = function() { 284 buckets.length = 0; 285 bucketsByHash = {}; 286 }; 287 288 this.isEmpty = function() { 289 return !buckets.length; 290 }; 291 292 var createBucketAggregator = function(bucketFuncName) { 293 return function() { 294 var aggregated = [], i = buckets.length; 295 while (i--) { 296 buckets[i][bucketFuncName](aggregated); 297 } 298 return aggregated; 299 }; 300 }; 301 302 this.keys = createBucketAggregator("keys"); 303 this.values = createBucketAggregator("values"); 304 this.entries = createBucketAggregator("getEntries"); 305 306 this.remove = function(key) { 307 checkKey(key); 308 309 var hash = hashingFunction(key), bucketIndex, oldValue = null; 310 311 // Check if a bucket exists for the bucket key 312 var bucket = getBucketForHash(bucketsByHash, hash); 313 314 if (bucket) { 315 // Remove entry from this bucket for this key 316 oldValue = bucket.removeEntryForKey(key); 317 if (oldValue !== null) { 318 // Entry was removed, so check if bucket is empty 319 if (!bucket.entries.length) { 320 // Bucket is empty, so remove it from the bucket collections 321 bucketIndex = searchBuckets(buckets, hash); 322 arrayRemoveAt(buckets, bucketIndex); 323 delete bucketsByHash[hash]; 324 } 325 } 326 } 327 return oldValue; 328 }; 329 330 this.size = function() { 331 var total = 0, i = buckets.length; 332 while (i--) { 333 total += buckets[i].entries.length; 334 } 335 return total; 336 }; 337 338 this.each = function(callback) { 339 var entries = that.entries(), i = entries.length, entry; 340 while (i--) { 341 entry = entries[i]; 342 callback(entry[0], entry[1]); 343 } 344 }; 345 346 this.putAll = function(hashtable, conflictCallback) { 347 var entries = hashtable.entries(); 348 var entry, key, value, thisValue, i = entries.length; 349 var hasConflictCallback = (typeof conflictCallback == FUNCTION); 350 while (i--) { 351 entry = entries[i]; 352 key = entry[0]; 353 value = entry[1]; 354 355 // Check for a conflict. The default behaviour is to overwrite the value for an existing key 356 if ( hasConflictCallback && (thisValue = that.get(key)) ) { 357 value = conflictCallback(key, thisValue, value); 358 } 359 that.put(key, value); 360 } 361 }; 362 363 this.clone = function() { 364 var clone = new Hashtable(hashingFunctionParam, equalityFunctionParam); 365 clone.putAll(that); 366 return clone; 367 }; 368 } 369 370 return Hashtable; 371})(); 372 373/** 374 * jquery.numberformatter - Formatting/Parsing Numbers in jQuery 375 * 376 * Written by 377 * Michael Abernethy ([email protected]), 378 * Andrew Parry ([email protected]) 379 * 380 * Dual licensed under the MIT (MIT-LICENSE.txt) 381 * and GPL (GPL-LICENSE.txt) licenses. 382 * 383 * @author Michael Abernethy, Andrew Parry 384 * @version 1.2.3-SNAPSHOT ($Id$) 385 * 386 * Dependencies 387 * 388 * jQuery (http://jquery.com) 389 * jshashtable (http://www.timdown.co.uk/jshashtable) 390 * 391 * Notes & Thanks 392 * 393 * many thanks to advweb.nanasi.jp for his bug fixes 394 * jsHashtable is now used also, so thanks to the author for that excellent little class. 395 * 396 * This plugin can be used to format numbers as text and parse text as Numbers 397 * Because we live in an international world, we cannot assume that everyone 398 * uses "," to divide thousands, and "." as a decimal point. 399 * 400 * As of 1.2 the way this plugin works has changed slightly, parsing text to a number 401 * has 1 set of functions, formatting a number to text has it's own. Before things 402 * were a little confusing, so I wanted to separate the 2 out more. 403 * 404 * 405 * jQuery extension functions: 406 * 407 * formatNumber(options, writeBack, giveReturnValue) - Reads the value from the subject, parses to 408 * a Javascript Number object, then formats back to text using the passed options and write back to 409 * the subject. 410 * 411 * parseNumber(options) - Parses the value in the subject to a Number object using the passed options 412 * to decipher the actual number from the text, then writes the value as text back to the subject. 413 * 414 * 415 * Generic functions: 416 * 417 * formatNumber(numberString, options) - Takes a plain number as a string (e.g. '1002.0123') and returns 418 * a string of the given format options. 419 * 420 * parseNumber(numberString, options) - Takes a number as text that is formatted the same as the given 421 * options then and returns it as a plain Number object. 422 * 423 * To achieve the old way of combining parsing and formatting to keep say a input field always formatted 424 * to a given format after it has lost focus you'd simply use a combination of the functions. 425 * 426 * e.g. 427 * $("#salary").blur(function(){ 428 * $(this).parseNumber({format:"#,###.00", locale:"us"}); 429 * $(this).formatNumber({format:"#,###.00", locale:"us"}); 430 * }); 431 * 432 * The syntax for the formatting is: 433 * 0 = Digit 434 * # = Digit, zero shows as absent 435 * . = Decimal separator 436 * - = Negative sign 437 * , = Grouping Separator 438 * % = Percent (multiplies the number by 100) 439 * 440 * For example, a format of "#,###.00" and text of 4500.20 will 441 * display as "4.500,20" with a locale of "de", and "4,500.20" with a locale of "us" 442 * 443 * 444 * As of now, the only acceptable locales are 445 * Arab Emirates -> "ae" 446 * Australia -> "au" 447 * Austria -> "at" 448 * Brazil -> "br" 449 * Canada -> "ca" 450 * China -> "cn" 451 * Czech -> "cz" 452 * Denmark -> "dk" 453 * Egypt -> "eg" 454 * Finland -> "fi" 455 * France -> "fr" 456 * Germany -> "de" 457 * Greece -> "gr" 458 * Great Britain -> "gb" 459 * Hong Kong -> "hk" 460 * India -> "in" 461 * Israel -> "il" 462 * Japan -> "jp" 463 * Russia -> "ru" 464 * South Korea -> "kr" 465 * Spain -> "es" 466 * Sweden -> "se" 467 * Switzerland -> "ch" 468 * Taiwan -> "tw" 469 * Thailand -> "th" 470 * United States -> "us" 471 * Vietnam -> "vn" 472 **/ 473 474(function(jQuery) { 475 476 var nfLocales = new Hashtable(); 477 478 var nfLocalesLikeUS = [ 'ae','au','ca','cn','eg','gb','hk','il','in','jp','sk','th','tw','us' ]; 479 var nfLocalesLikeDE = [ 'at','br','de','dk','es','gr','it','nl','pt','tr','vn' ]; 480 var nfLocalesLikeFR = [ 'cz','fi','fr','ru','se','pl' ]; 481 var nfLocalesLikeCH = [ 'ch' ]; 482 483 var nfLocaleFormatting = [ [".", ","], [",", "."], [",", " "], [".", "'"] ]; 484 var nfAllLocales = [ nfLocalesLikeUS, nfLocalesLikeDE, nfLocalesLikeFR, nfLocalesLikeCH ] 485 486 function FormatData(dec, group, neg) { 487 this.dec = dec; 488 this.group = group; 489 this.neg = neg; 490 }; 491
492 function init() { 493 // write the arrays into the hashtable 494 for (var localeGroupIdx = 0; localeGroupIdx < nfAllLocales.length; localeGroupIdx++) { 495 localeGroup = nfAllLocales[localeGroupIdx]; 496 for (var i = 0; i < localeGroup.length; i++) { 497 nfLocales.put(localeGroup[i], localeGroupIdx); 498 } 499 } 500 }; 501 502 function formatCodes(locale, isFullLocale) { 503 if (nfLocales.size() == 0) 504 init(); 505 506 // default values 507 var dec = "."; 508 var group = ","; 509 var neg = "-"; 510 511 if (isFullLocale == false) { 512 // Extract and convert to lower-case any language code from a real 'locale' formatted string, if not use as-is 513 // (To prevent locale format like : "fr_FR", "en_US", "de_DE", "fr_FR", "en-US", "de-DE") 514 if (locale.indexOf('_') != -1) 515 locale = locale.split('_')[1].toLowerCase(); 516 else if (locale.indexOf('-') != -1) 517 locale = locale.split('-')[1].toLowerCase(); 518 } 519 520 // hashtable lookup to match locale with codes 521 var codesIndex = nfLocales.get(locale); 522 if (codesIndex) { 523 var codes = nfLocaleFormatting[codesIndex]; 524 if (codes) { 525 dec = codes[0]; 526 group = codes[1]; 527 } 528 } 529 return new FormatData(dec, group, neg); 530 }; 531 532 533 /* Formatting Methods */ 534 535 536 /** 537 * Formats anything containing a number in standard js number notation. 538 * 539 * @param {Object} options The formatting options to use 540 * @param {Boolean} writeBack (true) If the output value should be written back to the subject 541 * @param {Boolean} giveReturnValue (true) If the function should return the output string 542 */ 543 jQuery.fn.formatNumber = function(options, writeBack, giveReturnValue) { 544 545 return this.each(function() { 546 // enforce defaults 547 if (writeBack == null) 548 writeBack = true; 549 if (giveReturnValue == null) 550 giveReturnValue = true; 551 552 // get text 553 var text; 554 if (jQuery(this).is(":input")) 555 text = new String(jQuery(this).val()); 556 else 557 text = new String(jQuery(this).text()); 558 559 // format 560 var returnString = jQuery.formatNumber(text, options); 561 562 // set formatted string back, only if a success 563// if (returnString) { 564 if (writeBack) { 565 if (jQuery(this).is(":input")) 566 jQuery(this).val(returnString); 567 else 568 jQuery(this).text(returnString); 569 } 570 if (giveReturnValue) 571 return returnString; 572// } 573// return ''; 574 }); 575 }; 576 577 /** 578 * First parses a string and reformats it with the given options. 579 * 580 * @param {Object} numberString 581 * @param {Object} options 582 */ 583 jQuery.formatNumber = function(numberString, options){ 584 var options = jQuery.extend({}, jQuery.fn.formatNumber.defaults, options); 585 var formatData = formatCodes(options.locale.toLowerCase(), options.isFullLocale); 586 587 var dec = formatData.dec; 588 var group = formatData.group; 589 var neg = formatData.neg; 590 591 var validFormat = "0#-,."; 592 593 // strip all the invalid characters at the beginning and the end 594 // of the format, and we'll stick them back on at the end 595 // make a special case for the negative sign "-" though, so 596 // we can have formats like -$23.32 597 var prefix = ""; 598 var negativeInFront = false; 599 for (var i = 0; i < options.format.length; i++) { 600 if (validFormat.indexOf(options.format.charAt(i)) == -1) 601 prefix = prefix + options.format.charAt(i); 602 else 603 if (i == 0 && options.format.charAt(i) == '-') { 604 negativeInFront = true; 605 continue; 606 } 607 else 608 break; 609 } 610 var suffix = ""; 611 for (var i = options.format.length - 1; i >= 0; i--) { 612 if (validFormat.indexOf(options.format.charAt(i)) == -1) 613 suffix = options.format.charAt(i) + suffix; 614 else 615 break; 616 } 617 618 options.format = options.format.substring(prefix.length); 619 options.format = options.format.substring(0, options.format.length - suffix.length); 620 621 // now we need to convert it into a number 622 //while (numberString.indexOf(group) > -1) 623 // numberString = numberString.replace(group, ''); 624 //var number = new Number(numberString.replace(dec, ".").replace(neg, "-")); 625 var number = new Number(numberString); 626 627 return jQuery._formatNumber(number, options, suffix, prefix, negativeInFront); 628 }; 629 630 /** 631 * Formats a Number object into a string, using the given formatting options 632 * 633 * @param {Object} numberString 634 * @param {Object} options 635 */ 636 jQuery._formatNumber = function(number, options, suffix, prefix, negativeInFront) { 637 var options = jQuery.extend({}, jQuery.fn.formatNumber.defaults, options); 638 var formatData = formatCodes(options.locale.toLowerCase(), options.isFullLocale); 639 640 var dec = formatData.dec; 641 var group = formatData.group; 642 var neg = formatData.neg; 643 644 var forcedToZero = false;
645 if (isNaN(number)) { 646 if (options.nanForceZero == true) { 647 number = 0; 648 forcedToZero = true; 649 } else 650 return null; 651 } 652 653 // special case for percentages 654 if (suffix == "%") 655 number = number * 100; 656 657 var returnString = ""; 658 if (options.format.indexOf(".") > -1) { 659 var decimalPortion = dec; 660 var decimalFormat = options.format.substring(options.format.lastIndexOf(".") + 1); 661 662 // round or truncate number as needed 663 if (options.round == true) 664 number = new Number(number.toFixed(decimalFormat.length)); 665 else { 666 var numStr = number.toString(); 667 numStr = numStr.substring(0, numStr.lastIndexOf('.') + decimalFormat.length + 1); 668 number = new Number(numStr); 669 } 670 671 var decimalValue = number % 1; 672 var decimalString = new String(decimalValue.toFixed(decimalFormat.length)); 673 decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1); 674 675 for (var i = 0; i < decimalFormat.length; i++) { 676 if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') { 677 decimalPortion += decimalString.charAt(i); 678 continue; 679 } else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') { 680 var notParsed = decimalString.substring(i); 681 if (notParsed.match('[1-9]')) { 682 decimalPortion += decimalString.charAt(i); 683 continue; 684 } else 685 break; 686 } else if (decimalFormat.charAt(i) == "0") 687 decimalPortion += decimalString.charAt(i); 688 } 689 returnString += decimalPortion 690 } else 691 number = Math.round(number); 692 693 var ones = Math.floor(number); 694 if (number < 0) 695 ones = Math.ceil(number); 696 697 var onesFormat = ""; 698 if (options.format.indexOf(".") == -1) 699 onesFormat = options.format; 700 else 701 onesFormat = options.format.substring(0, options.format.indexOf(".")); 702 703 var onePortion = ""; 704 if (!(ones == 0 && onesFormat.substr(onesFormat.length - 1) == '#') || forcedToZero) { 705 // find how many digits are in the group 706 var oneText = new String(Math.abs(ones)); 707 var groupLength = 9999; 708 if (onesFormat.lastIndexOf(",") != -1) 709 groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1; 710 var groupCount = 0; 711 for (var i = oneText.length - 1; i > -1; i--) { 712 onePortion = oneText.charAt(i) + onePortion; 713 groupCount++; 714 if (groupCount == groupLength && i != 0) { 715 onePortion = group + onePortion; 716 groupCount = 0; 717 } 718 } 719 720 // account for any pre-data padding 721 if (onesFormat.length > onePortion.length) { 722 var padStart = onesFormat.indexOf('0'); 723 if (padStart != -1) { 724 var padLen = onesFormat.length - padStart; 725 726 // pad to left with 0's or group char 727 var pos = onesFormat.length - onePortion.length - 1; 728 while (onePortion.length < padLen) { 729 var padChar = onesFormat.charAt(pos); 730 // replace with real group char if needed 731 if (padChar == ',') 732 padChar = group; 733 onePortion = padChar + onePortion; 734 pos--; 735 } 736 } 737 } 738 } 739 740 if (!onePortion && onesFormat.indexOf('0', onesFormat.length - 1) !== -1) 741 onePortion = '0'; 742 743 returnString = onePortion + returnString; 744 745 // handle special case where negative is in front of the invalid characters 746 if (number < 0 && negativeInFront && prefix.length > 0) 747 prefix = neg + prefix; 748 else if (number < 0) 749 returnString = neg + returnString; 750 751 if (!options.decimalSeparatorAlwaysShown) { 752 if (returnString.lastIndexOf(dec) == returnString.length - 1) { 753 returnString = returnString.substring(0, returnString.length - 1); 754 } 755 } 756 returnString = prefix + returnString + suffix; 757 return returnString; 758 }; 759 760 761 /* Parsing Methods */ 762 763 764 /** 765 * Parses a number of given format from the element and returns a Number object. 766 * @param {Object} options 767 */ 768 jQuery.fn.parseNumber = function(options, writeBack, giveReturnValue) { 769 // enforce defaults 770 if (writeBack == null) 771 writeBack = true; 772 if (giveReturnValue == null) 773 giveReturnValue = true; 774 775 // get text 776 var text; 777 if (jQuery(this).is(":input")) 778 text = new String(jQuery(this).val()); 779 else 780 text = new String(jQuery(this).text()); 781 782 // parse text 783 var number = jQuery.parseNumber(text, options); 784 785 if (number) { 786 if (writeBack) { 787 if (jQuery(this).is(":input")) 788 jQuery(this).val(number.toString()); 789 else 790 jQuery(this).text(number.toString()); 791 } 792 if (giveReturnValue) 793 return number; 794 } 795 }; 796 797 /** 798 * Parses a string of given format into a Number object. 799 * 800 * @param {Object} string 801 * @param {Object} options 802 */ 803 jQuery.parseNumber = function(numberString, options) { 804 var options = jQuery.extend({}, jQuery.fn.parseNumber.defaults, options); 805 var formatData = formatCodes(options.locale.toLowerCase(), options.isFullLocale); 806 807 var dec = formatData.dec; 808 var group = formatData.group; 809 var neg = formatData.neg; 810
811 var valid = "1234567890.-"; 812 813 // now we need to convert it into a number 814 while (numberString.indexOf(group)>-1) 815 numberString = numberString.replace(group,''); 816 numberString = numberString.replace(dec,".").replace(neg,"-"); 817 var validText = ""; 818 var hasPercent = false; 819 if (numberString.charAt(numberString.length - 1) == "%" || options.isPercentage == true) 820 hasPercent = true; 821 for (var i=0; i<numberString.length; i++) { 822 if (valid.indexOf(numberString.charAt(i))>-1) 823 validText = validText + numberString.charAt(i); 824 } 825 var number = new Number(validText); 826 if (hasPercent) { 827 number = number / 100; 828 var decimalPos = validText.indexOf('.'); 829 if (decimalPos != -1) { 830 var decimalPoints = validText.length - decimalPos - 1; 831 number = number.toFixed(decimalPoints + 2); 832 } else { 833 number = number.toFixed(validText.length - 1); 834 } 835 } 836 837 return number; 838 }; 839 840 jQuery.fn.parseNumber.defaults = { 841 locale: "us", 842 decimalSeparatorAlwaysShown: false, 843 isPercentage: false, 844 isFullLocale: false 845 }; 846 847 jQuery.fn.formatNumber.defaults = { 848 format: "#,###.00", 849 locale: "us", 850 decimalSeparatorAlwaysShown: false, 851 nanForceZero: true, 852 round: true, 853 isFullLocale: false 854 }; 855 856 Number.prototype.toFixed = function(precision) { 857 return jQuery._roundNumber(this, precision); 858 }; 859 860 jQuery._roundNumber = function(number, decimalPlaces) { 861 var power = Math.pow(10, decimalPlaces || 0); 862 var value = String(Math.round(number * power) / power); 863 864 // ensure the decimal places are there 865 if (decimalPlaces > 0) { 866 var dp = value.indexOf("."); 867 if (dp == -1) { 868 value += '.'; 869 dp = 0; 870 } else { 871 dp = value.length - (dp + 1); 872 } 873 874 while (dp < decimalPlaces) { 875 value += '0'; 876 dp++; 877 } 878 } 879 return value; 880 }; 881 882 })(jQuery); 883 884 // Simple JavaScript Templating 885// John Resig - http://ejohn.org/ - MIT Licensed 886(function(){ 887 var cache = {}; 888 889 this.tmpl = function tmpl(str, data){ 890 // Figure out if we're getting a template, or if we need to 891 // load the template - and be sure to cache the result. 892 var fn = !/\W/.test(str) ? 893 cache[str] = cache[str] || 894 tmpl(document.getElementById(str).innerHTML) : 895 896 // Generate a reusable function that will serve as a template 897 // generator (and which will be cached). 898 new Function("obj", 899 "var p=[],print=function(){p.push.apply(p,arguments);};" + 900 901 // Introduce the data as local variables using with(){} 902 "with(obj){p.push('" + 903 904 // Convert the template into pure JavaScript 905 str 906 .replace(/[\r\t\n]/g, " ") 907 .split("<%").join("\t") 908 .replace(/((^|%>)[^\t]*)'/g, "$1\r") 909 .replace(/\t=(.*?)%>/g, "',$1,'") 910 .split("\t").join("');") 911 .split("%>").join("p.push('") 912 .split("\r").join("\\'") 913 + "');}return p.join('');"); 914 915 // Provide some basic currying to the user 916 return data ? fn( data ) : fn; 917 }; 918})(); 919 920/** 921 * jquery.dependClass - Attach class based on first class in list of current element 922 * 923 * Written by 924 * Egor Khmelev ([email protected]) 925 * 926 * Licensed under the MIT (MIT-LICENSE.txt). 927 * 928 * @author Egor Khmelev 929 * @version 0.1.0-BETA ($Id$) 930 * 931 **/ 932 933(function($) { 934 $.baseClass = function(obj){ 935 obj = $(obj); 936 return obj.get(0).className.match(/([^ ]+)/)[1]; 937 }; 938 939 $.fn.addDependClass = function(className, delimiter){ 940 var options = { 941 delimiter: delimiter ? delimiter : '-' 942 } 943 return this.each(function(){ 944 var baseClass = $.baseClass(this); 945 if(baseClass) 946 $(this).addClass(baseClass + options.delimiter + className); 947 }); 948 }; 949 950 $.fn.removeDependClass = function(className, delimiter){ 951 var options = { 952 delimiter: delimiter ? delimiter : '-' 953 } 954 return this.each(function(){ 955 var baseClass = $.baseClass(this); 956 if(baseClass) 957 $(this).removeClass(baseClass + options.delimiter + className); 958 }); 959 }; 960 961 $.fn.toggleDependClass = function(className, delimiter){ 962 var options = { 963 delimiter: delimiter ? delimiter : '-' 964 } 965 return this.each(function(){ 966 var baseClass = $.baseClass(this); 967 if(baseClass) 968 if($(this).is("." + baseClass + options.delimiter + className)) 969 $(this).removeClass(baseClass + options.delimiter + className); 970 else 971 $(this).addClass(baseClass + options.delimiter + className); 972 }); 973 }; 974 975})(jQuery); 976 977/** 978 * draggable - Class allows to make any element draggable 979 * 980 * Written by 981 * Egor Khmelev ([email protected]) 982 * 983 * Licensed under the MIT (MIT-LICENSE.txt). 984 * 985 * @author Egor Khmelev 986 * @version 0.1.0-BETA ($Id$) 987 * 988 **/ 989 990(function( $ ){ 991 992 function Draggable(){ 993 this._init.apply( this, arguments ); 994 }; 995 996 Draggable.prototype.oninit = function(){ 997 998 }; 999 1000 Draggable.prototype.events = function(){ 1001 1002 }; 1003 1004 Draggable.prototype.onmousedown = function(){ 1005 this.ptr.css({ position: "absolute" }); 1006 }; 1007 1008 Draggable.prototype.onmousemove = function( evt, x, y ){ 1009 this.ptr.css({ left: x, top: y }); 1010 }; 1011 1012 Draggable.prototype.onmouseup = function(){ 1013 1014 }; 1015 1016 Draggable.prototype.isDefault = { 1017 drag: false,
1018 clicked: false, 1019 toclick: true, 1020 mouseup: false 1021 }; 1022 1023 Draggable.prototype._init = function(){ 1024 if( arguments.length > 0 ){ 1025 this.ptr = $(arguments[0]); 1026 this.outer = $(".draggable-outer"); 1027 1028 this.is = {}; 1029 $.extend( this.is, this.isDefault ); 1030 1031 var _offset = this.ptr.offset(); 1032 this.d = { 1033 left: _offset.left, 1034 top: _offset.top, 1035 width: this.ptr.width(), 1036 height: this.ptr.height() 1037 }; 1038 1039 this.oninit.apply( this, arguments ); 1040 1041 this._events(); 1042 } 1043 }; 1044 1045 Draggable.prototype._getPageCoords = function( event ){ 1046 if( event.targetTouches && event.targetTouches[0] ){ 1047 return { x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY }; 1048 } else 1049 return { x: event.pageX, y: event.pageY }; 1050 }; 1051 1052 Draggable.prototype._bindEvent = function( ptr, eventType, handler ){ 1053 var self = this; 1054 1055 if( this.supportTouches_ ) 1056 ptr.get(0).addEventListener( this.events_[ eventType ], handler, false ); 1057 1058 else 1059 ptr.bind( this.events_[ eventType ], handler ); 1060 }; 1061 1062 Draggable.prototype._events = function(){ 1063 var self = this; 1064 1065 this.supportTouches_ = 'ontouchend' in document; 1066 this.events_ = { 1067 "click": this.supportTouches_ ? "touchstart" : "click", 1068 "down": this.supportTouches_ ? "touchstart" : "mousedown", 1069 "move": this.supportTouches_ ? "touchmove" : "mousemove", 1070 "up" : this.supportTouches_ ? "touchend" : "mouseup" 1071 }; 1072 1073 this._bindEvent( $( document ), "move", function( event ){ 1074 if( self.is.drag ){ 1075 event.stopPropagation(); 1076 event.preventDefault(); 1077 self._mousemove( event ); 1078 } 1079 }); 1080 this._bindEvent( $( document ), "down", function( event ){ 1081 if( self.is.drag ){ 1082 event.stopPropagation(); 1083 event.preventDefault(); 1084 } 1085 }); 1086 this._bindEvent( $( document ), "up", function( event ){ 1087 self._mouseup( event ); 1088 }); 1089 1090 this._bindEvent( this.ptr, "down", function( event ){ 1091 self._mousedown( event ); 1092 return false; 1093 }); 1094 this._bindEvent( this.ptr, "up", function( event ){ 1095 self._mouseup( event ); 1096 }); 1097 1098 this.ptr.find("a") 1099 .click(function(){ 1100 self.is.clicked = true; 1101 1102 if( !self.is.toclick ){ 1103 self.is.toclick = true; 1104 return false; 1105 } 1106 }) 1107 .mousedown(function( event ){ 1108 self._mousedown( event ); 1109 return false; 1110 }); 1111 1112 this.events(); 1113 }; 1114 1115 Draggable.prototype._mousedown = function( evt ){ 1116 this.is.drag = true; 1117 this.is.clicked = false; 1118 this.is.mouseup = false; 1119 1120 var _offset = this.ptr.offset(); 1121 var coords = this._getPageCoords( evt ); 1122 this.cx = coords.x - _offset.left; 1123 this.cy = coords.y - _offset.top; 1124 1125 $.extend(this.d, { 1126 left: _offset.left, 1127 top: _offset.top, 1128 width: this.ptr.width(), 1129 height: this.ptr.height() 1130 }); 1131 1132 if( this.outer && this.outer.get(0) ){ 1133 this.outer.css({ height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden" }); 1134 } 1135 1136 this.onmousedown( evt ); 1137 }; 1138 1139 Draggable.prototype._mousemove = function( evt ){ 1140 this.is.toclick = false; 1141 var coords = this._getPageCoords( evt ); 1142 this.onmousemove( evt, coords.x - this.cx, coords.y - this.cy ); 1143 }; 1144 1145 Draggable.prototype._mouseup = function( evt ){ 1146 var oThis = this; 1147 1148 if( this.is.drag ){ 1149 this.is.drag = false; 1150 1151 if( this.outer && this.outer.get(0) ){ 1152 1153 if( $.browser.mozilla ){ 1154 this.outer.css({ overflow: "hidden" }); 1155 } else { 1156 this.outer.css({ overflow: "visible" }); 1157 } 1158 1159 if( $.browser.msie && $.browser.version == '6.0' ){ 1160 this.outer.css({ height: "100%" }); 1161 } else { 1162 this.outer.css({ height: "auto" }); 1163 } 1164 } 1165 1166 this.onmouseup( evt ); 1167 } 1168 }; 1169 1170 window.Draggable = Draggable; 1171 1172})( jQuery ); 1173 1174 1175/** 1176 * jquery.slider - Slider ui control in jQuery 1177 * 1178 * Written by 1179 * Egor Khmelev ([email protected]) 1180 * 1181 * Licensed under the MIT (MIT-LICENSE.txt). 1182 * 1183 * @author Egor Khmelev 1184 * @version 1.1.0-RELEASE ($Id$) 1185 * 1186 * Dependencies 1187 * 1188 * jQuery (http://jquery.com) 1189 * jquery.numberformatter (http://code.google.com/p/jquery-numberformatter/) 1190 * tmpl (http://ejohn.org/blog/javascript-micro-templating/) 1191 * jquery.dependClass 1192 * draggable 1193 * 1194 **/ 1195 1196(function( $ ) { 1197 1198 function isArray( value ){ 1199 if( typeof value == "undefined" ) return false;
1200 1201 if (value instanceof Array || (!(value instanceof Object) && 1202 (Object.prototype.toString.call((value)) == '[object Array]') || 1203 typeof value.length == 'number' && 1204 typeof value.splice != 'undefined' && 1205 typeof value.propertyIsEnumerable != 'undefined' && 1206 !value.propertyIsEnumerable('splice') 1207 )) { 1208 return true; 1209 } 1210 1211 return false; 1212 } 1213 1214 $.slider = function( node, settings ){ 1215 var jNode = $(node); 1216 if( !jNode.data( "jslider" ) ) 1217 jNode.data( "jslider", new jSlider( node, settings ) ); 1218 1219 return jNode.data( "jslider" ); 1220 }; 1221 1222 $.fn.slider = function( action, opt_value ){ 1223 var returnValue, args = arguments; 1224 1225 function isDef( val ){ 1226 return val !== undefined; 1227 }; 1228 1229 function isDefAndNotNull( val ){ 1230 return val != null; 1231 }; 1232 1233 this.each(function(){ 1234 var self = $.slider( this, action ); 1235 1236 // do actions 1237 if( typeof action == "string" ){ 1238 switch( action ){ 1239 case "value": 1240 if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){ 1241 var pointers = self.getPointers(); 1242 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 1243 pointers[0].set( args[ 1 ] ); 1244 pointers[0].setIndexOver(); 1245 } 1246 1247 if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){ 1248 pointers[1].set( args[ 2 ] ); 1249 pointers[1].setIndexOver(); 1250 } 1251 } 1252 1253 else if( isDef( args[ 1 ] ) ){ 1254 var pointers = self.getPointers(); 1255 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 1256 pointers[0].set( args[ 1 ] ); 1257 pointers[0].setIndexOver(); 1258 } 1259 } 1260 1261 else 1262 returnValue = self.getValue(); 1263 1264 break; 1265 1266 case "prc": 1267 if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){ 1268 var pointers = self.getPointers(); 1269 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 1270 pointers[0]._set( args[ 1 ] ); 1271 pointers[0].setIndexOver(); 1272 } 1273 1274 if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){ 1275 pointers[1]._set( args[ 2 ] ); 1276 pointers[1].setIndexOver(); 1277 } 1278 } 1279 1280 else if( isDef( args[ 1 ] ) ){ 1281 var pointers = self.getPointers(); 1282 if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){ 1283 pointers[0]._set( args[ 1 ] ); 1284 pointers[0].setIndexOver(); 1285 } 1286 } 1287 1288 else 1289 returnValue = self.getPrcValue(); 1290 1291 break; 1292 1293 case "calculatedValue": 1294 var value = self.getValue().split(";"); 1295 returnValue = ""; 1296 for (var i=0; i < value.length; i++) { 1297 returnValue += (i > 0 ? ";" : "") + self.nice( value[i] ); 1298 }; 1299 1300 break; 1301 1302 case "skin": 1303 self.setSkin( args[1] ); 1304 1305 break; 1306 }; 1307 1308 } 1309 1310 // return actual object 1311 else if( !action && !opt_value ){ 1312 if( !isArray( returnValue ) ) 1313 returnValue = []; 1314 1315 returnValue.push( self ); 1316 } 1317 }); 1318 1319 // flatten array just with one slider 1320 if( isArray( returnValue ) && returnValue.length == 1 ) 1321 returnValue = returnValue[ 0 ]; 1322 1323 return returnValue || this; 1324 }; 1325 1326 var OPTIONS = { 1327 1328 settings: { 1329 from: 1, 1330 to: 10, 1331 step: 1, 1332 smooth: true, 1333 limits: true, 1334 round: 0, 1335 format: { format: "#,##0.##" }, 1336 value: "5;7", 1337 dimension: "" 1338 }, 1339 1340 className: "jslider", 1341 selector: ".jslider-", 1342 1343 template: tmpl( 1344 '<span class="<%=className%>">' + 1345 '<table><tr><td>' + 1346 '<div class="<%=className%>-bg">' + 1347 '<i class="l"></i><i class="f"></i><i class="r"></i>' + 1348 '<i class="v"></i>' + 1349 '</div>' + 1350 1351 '<div class="<%=className%>-pointer"></div>' + 1352 '<div class="<%=className%>-pointer <%=className%>-pointer-to"></div>' + 1353 1354 '<div class="<%=className%>-label"><%=settings.dimension%><span><%=settings.from%></span></div>' + 1355 '<div class="<%=className%>-label <%=className%>-label-to"><%=settings.dimension%><span><%=settings.to%></span></div>' + 1356 1357 '<div class="<%=className%>-value"><%=settings.dimension%><span></span></div>' + 1358 '<div class="<%=className%>-value <%=className%>-value-to"><%=settings.dimension%><span></span></div>' + 1359 1360 '<div class="<%=className%>-scale"><%=scale%></div>'+ 1361 1362 '</td></tr></table>' + 1363 '</span>' 1364 ) 1365 1366 }; 1367 1368 function jSlider(){ 1369 return this.init.apply( this, arguments ); 1370 }; 1371 1372 jSlider.prototype.init = function( node, settings ){ 1373 this.settings = $.extend(true, {}, OPTIONS.settings, settings ? settings : {}); 1374 1375 // obj.sliderHandler = this; 1376 this.inputNode = $( node ).hide(); 1377 1378 this.settings.interval = this.settings.to-this.settings.from; 1379 this.settings.value = this.inputNode.attr("value"); 1380 1381 if( this.settings.calculate && $.isFunction( this.settings.calculate ) ) 1382 this.nice = this.settings.calculate; 1383 1384 if( this.settings.onstatechange && $.isFunction( this.settings.onstatechange ) ) 1385 this.onstatechange = this.settings.onstatechange; 1386 1387 this.is = { 1388 init: false 1389 }; 1390 this.o = {}; 1391 1392 this.create(); 1393 }; 1394 1395 jSlider.prototype.onstatechange = function(){ 1396 1397 }; 1398 1399 jSlider.prototype.create = function(){ 1400 var $this = this; 1401 1402 this.domNode = $( OPTIONS.template({ 1403 className: OPTIONS.className, 1404 settings: { 1405 from: this.nice( this.settings.from ), 1406 to: this.nice( this.settings.to ), 1407 dimension: this.settings.dimension 1408 }, 1409 scale: this.generateScale() 1410 }) ); 1411 1412 this.inputNode.after( this.domNode ); 1413 this.drawScale(); 1414 1415 // set skin class 1416 if( this.settings.skin && this.settings.skin.length > 0 ) 1417 this.setSkin( this.settings.skin ); 1418 1419 this.sizes = { 1420 domWidth: this.domNode.width(), 1421 domOffset: this.domNode.offset() 1422 }; 1423 1424 // find some objects 1425 $.extend(this.o, { 1426 pointers: {}, 1427 labels: { 1428 0: { 1429 o: this.domNode.find(OPTIONS.selector + "value").not(OPTIONS.selector + "value-to") 1430 }, 1431 1: { 1432 o: this.domNode.find(OPTIONS.selector + "value").filter(OPTIONS.selector + "value-to") 1433 } 1434 }, 1435 limits: { 1436 0: this.domNode.find(OPTIONS.selector + "label").not(OPTIONS.selector + "label-to"), 1437 1: this.domNode.find(OPTIONS.selector + "label").filter(OPTIONS.selector + "label-to") 1438 } 1439 }); 1440 1441 $.extend(this.o.labels[0], { 1442 value: this.o.labels[0].o.find("span") 1443 }); 1444 1445 $.extend(this.o.labels[1], { 1446 value: this.o.labels[1].o.find("span") 1447 }); 1448 1449 1450 if( !$this.settings.value.split(";")[1] ){ 1451 this.settings.single = true; 1452 this.domNode.addDependClass("single"); 1453 } 1454 1455 if( !$this.settings.limits ) 1456 this.domNode.addDependClass("limitless"); 1457 1458 this.domNode.find(OPTIONS.selector + "pointer").each(function( i ){ 1459 var value = $this.settings.value.split(";")[i]; 1460 if( value ){ 1461 $this.o.pointers[i] = new jSliderPointer( this, i, $this ); 1462 1463 var prev = $this.settings.value.split(";")[i-1];
1464 if( prev && new Number(value) < new Number(prev) ) value = prev; 1465 1466 value = value < $this.settings.from ? $this.settings.from : value; 1467 value = value > $this.settings.to ? $this.settings.to : value; 1468 1469 $this.o.pointers[i].set( value, true ); 1470 } 1471 }); 1472 1473 this.o.value = this.domNode.find(".v"); 1474 this.is.init = true; 1475 1476 $.each(this.o.pointers, function(i){ 1477 $this.redraw(this); 1478 }); 1479 1480 (function(self){ 1481 $(window).resize(function(){ 1482 self.onresize(); 1483 }); 1484 })(this); 1485 1486 }; 1487 1488 jSlider.prototype.setSkin = function( skin ){ 1489 if( this.skin_ ) 1490 this.domNode.removeDependClass( this.skin_, "_" ); 1491 1492 this.domNode.addDependClass( this.skin_ = skin, "_" ); 1493 }; 1494 1495 jSlider.prototype.setPointersIndex = function( i ){ 1496 $.each(this.getPointers(), function(i){ 1497 this.index( i ); 1498 }); 1499 }; 1500 1501 jSlider.prototype.getPointers = function(){ 1502 return this.o.pointers; 1503 }; 1504 1505 jSlider.prototype.generateScale = function(){ 1506 if( this.settings.scale && this.settings.scale.length > 0 ){ 1507 var str = ""; 1508 var s = this.settings.scale; 1509 var prc = Math.round((100/(s.length-1))*10)/10; 1510 for( var i=0; i < s.length; i++ ){ 1511 str += '<span style="left: ' + i*prc + '%">' + ( s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '' ) + '</span>'; 1512 }; 1513 return str; 1514 } else return ""; 1515 1516 return ""; 1517 }; 1518 1519 jSlider.prototype.drawScale = function(){ 1520 this.domNode.find(OPTIONS.selector + "scale span ins").each(function(){ 1521 $(this).css({ marginLeft: -$(this).outerWidth()/2 }); 1522 }); 1523 }; 1524 1525 jSlider.prototype.onresize = function(){ 1526 var self = this; 1527 this.sizes = { 1528 domWidth: this.domNode.width(), 1529 domOffset: this.domNode.offset() 1530 }; 1531 1532 $.each(this.o.pointers, function(i){ 1533 self.redraw(this); 1534 }); 1535 }; 1536 1537 jSlider.prototype.update = function(){ 1538 this.onresize(); 1539 this.drawScale(); 1540 }; 1541 1542 jSlider.prototype.limits = function( x, pointer ){ 1543 // smooth 1544 if( !this.settings.smooth ){ 1545 var step = this.settings.step*100 / ( this.settings.interval ); 1546 x = Math.round( x/step ) * step; 1547 } 1548 1549 var another = this.o.pointers[1-pointer.uid]; 1550 if( another && pointer.uid && x < another.value.prc ) x = another.value.prc; 1551 if( another && !pointer.uid && x > another.value.prc ) x = another.value.prc; 1552 1553 // base limit 1554 if( x < 0 ) x = 0; 1555 if( x > 100 ) x = 100; 1556 1557 return Math.round( x*10 ) / 10; 1558 }; 1559 1560 jSlider.prototype.redraw = function( pointer ){ 1561 if( !this.is.init ) return false; 1562 1563 this.setValue(); 1564 1565 // redraw range line 1566 if( this.o.pointers[0] && this.o.pointers[1] ) 1567 this.o.value.css({ left: this.o.pointers[0].value.prc + "%", width: ( this.o.pointers[1].value.prc - this.o.pointers[0].value.prc ) + "%" }); 1568 1569 this.o.labels[pointer.uid].value.html( 1570 this.nice( 1571 pointer.value.origin 1572 ) 1573 ); 1574 1575 // redraw position of labels 1576 this.redrawLabels( pointer ); 1577 1578 }; 1579 1580 jSlider.prototype.redrawLabels = function( pointer ){ 1581 1582 function setPosition( label, sizes, prc ){ 1583 sizes.margin = -sizes.label/2; 1584 1585 // left limit 1586 label_left = sizes.border + sizes.margin; 1587 if( label_left < 0 ) 1588 sizes.margin -= label_left; 1589 1590 // right limit 1591 if( sizes.border+sizes.label / 2 > self.sizes.domWidth ){ 1592 sizes.margin = 0; 1593 sizes.right = true; 1594 } else 1595 sizes.right = false; 1596 1597 label.o.css({ left: prc + "%", marginLeft: sizes.margin, right: "auto" }); 1598 if( sizes.right ) label.o.css({ left: "auto", right: 0 }); 1599 return sizes; 1600 } 1601 1602 var self = this; 1603 var label = this.o.labels[pointer.uid]; 1604 var prc = pointer.value.prc; 1605 1606 var sizes = { 1607 label: label.o.outerWidth(), 1608 right: false, 1609 border: ( prc * this.sizes.domWidth ) / 100 1610 }; 1611 1612 if( !this.settings.single ){ 1613 // glue if near; 1614 var another = this.o.pointers[1-pointer.uid]; 1615 var another_label = this.o.labels[another.uid]; 1616 1617 switch( pointer.uid ){ 1618 case 0: 1619 if( sizes.border+sizes.label / 2 > another_label.o.offset().left-this.sizes.domOffset.left ){ 1620 another_label.o.css({ visibility: "hidden" }); 1621 another_label.value.html( this.nice( another.value.origin ) ); 1622 1623 label.o.css({ visibility: "visible" }); 1624 1625 prc = ( another.value.prc - prc ) / 2 + prc; 1626 if( another.value.prc != pointer.value.prc ){ 1627 //label.value.html( this.nice(pointer.value.origin) + " – " + this.nice(another.value.origin) ); 1628 label.value.html( this.nice(pointer.value.origin) ); 1629 sizes.label = label.o.outerWidth(); 1630 sizes.border = ( prc * this.sizes.domWidth ) / 100; 1631 } 1632 } else { 1633 another_label.o.css({ visibility: "visible" }); 1634 } 1635 break; 1636 1637 case 1: 1638 if( sizes.border - sizes.label / 2 < another_label.o.offset().left - this.sizes.domOffset.left + another_label.o.outerWidth() ){ 1639 another_label.o.css({ visibility: "hidden" }); 1640 another_label.value.html( this.nice(another.value.origin) ); 1641 1642 label.o.css({ visibility: "visible" }); 1643 //modified by george 1644 //prc = ( prc - another.value.prc ) / 2 + another.value.prc; 1645 if( another.value.prc != pointer.value.prc ){ 1646 //label.value.html( this.nice(another.value.origin) + " – " + this.nice(pointer.value.origin) ); 1647 label.value.html( this.nice(pointer.value.origin) ); 1648 sizes.label = label.o.outerWidth(); 1649 sizes.border = ( prc * this.sizes.domWidth ) / 100; 1650 } 1651 } else { 1652 another_label.o.css({ visibility: "visible" }); 1653 } 1654 break; 1655 } 1656 } 1657 1658 sizes = setPosition( label, sizes, prc ); 1659 1660 /* draw second label */ 1661 if( another_label ){ 1662 var sizes = { 1663 label: another_label.o.outerWidth(), 1664 right: false, 1665 border: ( another.value.prc * this.sizes.domWidth ) / 100 1666 }; 1667 sizes = setPosition( another_label, sizes, another.value.prc ); 1668 } 1669 1670 this.redrawLimits(); 1671 }; 1672 1673 jSlider.prototype.redrawLimits = function(){ 1674 if( this.settings.limits ){ 1675 1676 var limits = [ true, true ]; 1677 1678 for( key in this.o.pointers ){ 1679 1680 if( !this.settings.single || key == 0 ){ 1681 1682 var pointer = this.o.pointers[key]; 1683 var label = this.o.labels[pointer.uid]; 1684 var label_left = label.o.offset().left - this.sizes.domOffset.left; 1685 1686 var limit = this.o.limits[0]; 1687 if( label_left < limit.outerWidth() ) 1688 limits[0] = false;
1689 1690 var limit = this.o.limits[1]; 1691 if( label_left + label.o.outerWidth() > this.sizes.domWidth - limit.outerWidth() ) 1692 limits[1] = false; 1693 } 1694 1695 }; 1696 1697 for( var i=0; i < limits.length; i++ ){ 1698 if( limits[i] ) 1699 this.o.limits[i].fadeIn("fast"); 1700 else 1701 this.o.limits[i].fadeOut("fast"); 1702 }; 1703 1704 } 1705 }; 1706 1707 jSlider.prototype.setValue = function(){ 1708 var value = this.getValue(); 1709 this.inputNode.attr( "value", value ); 1710 this.onstatechange.call( this, value ); 1711 }; 1712 1713 jSlider.prototype.getValue = function(){ 1714 if(!this.is.init) return false; 1715 var $this = this; 1716 1717 var value = ""; 1718 $.each( this.o.pointers, function(i){ 1719 if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + $this.prcToValue( this.value.prc ); 1720 }); 1721 return value; 1722 }; 1723 1724 jSlider.prototype.getPrcValue = function(){ 1725 if(!this.is.init) return false; 1726 var $this = this; 1727 1728 var value = ""; 1729 $.each( this.o.pointers, function(i){ 1730 if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + this.value.prc; 1731 }); 1732 return value; 1733 }; 1734 1735 jSlider.prototype.prcToValue = function( prc ){ 1736 1737 if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){ 1738 var h = this.settings.heterogeneity; 1739 1740 var _start = 0; 1741 var _from = this.settings.from; 1742 1743 for( var i=0; i <= h.length; i++ ){ 1744 if( h[i] ) var v = h[i].split("/"); 1745 else var v = [100, this.settings.to]; 1746 1747 v[0] = new Number(v[0]); 1748 v[1] = new Number(v[1]); 1749 1750 if( prc >= _start && prc <= v[0] ) { 1751 var value = _from + ( (prc-_start) * (v[1]-_from) ) / (v[0]-_start); 1752 } 1753 1754 _start = v[0]; 1755 _from = v[1]; 1756 }; 1757 1758 } else { 1759 var value = this.settings.from + ( prc * this.settings.interval ) / 100; 1760 } 1761 1762 return this.round( value ); 1763 }; 1764 1765 jSlider.prototype.valueToPrc = function( value, pointer ){ 1766 if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){ 1767 var h = this.settings.heterogeneity; 1768 1769 var _start = 0; 1770 var _from = this.settings.from; 1771 1772 for (var i=0; i <= h.length; i++) { 1773 if(h[i]) var v = h[i].split("/"); 1774 else var v = [100, this.settings.to]; 1775 v[0] = new Number(v[0]); v[1] = new Number(v[1]); 1776 1777 if(value >= _from && value <= v[1]){ 1778 var prc = pointer.limits(_start + (value-_from)*(v[0]-_start)/(v[1]-_from)); 1779 } 1780 1781 _start = v[0]; _from = v[1]; 1782 }; 1783 1784 } else { 1785 var prc = pointer.limits((value-this.settings.from)*100/this.settings.interval); 1786 } 1787 1788 return prc; 1789 }; 1790 1791 jSlider.prototype.round = function( value ){ 1792 value = Math.round( value / this.settings.step ) * this.settings.step; 1793 if( this.settings.round ) value = Math.round( value * Math.pow(10, this.settings.round) ) / Math.pow(10, this.settings.round); 1794 else value = Math.round( value ); 1795 return value; 1796 }; 1797 1798 jSlider.prototype.nice = function( value ){ 1799 value = value.toString().replace(/,/gi, ".").replace(/ /gi, "");; 1800 1801 if( $.formatNumber ){ 1802 return $.formatNumber( new Number(value), this.settings.format || {} ).replace( /-/gi, "−" ); 1803 } 1804 1805 else { 1806 return new Number(value); 1807 } 1808 }; 1809 1810 1811 function jSliderPointer(){ 1812 Draggable.apply( this, arguments ); 1813 } 1814 jSliderPointer.prototype = new Draggable(); 1815 1816 jSliderPointer.prototype.oninit = function( ptr, id, _constructor ){ 1817 this.uid = id; 1818 this.parent = _constructor; 1819 this.value = {}; 1820 this.settings = this.parent.settings; 1821 }; 1822 1823 jSliderPointer.prototype.onmousedown = function(evt){ 1824 this._parent = { 1825 offset: this.parent.domNode.offset(), 1826 width: this.parent.domNode.width() 1827 }; 1828 this.ptr.addDependClass("hover"); 1829 this.setIndexOver(); 1830 }; 1831 1832 jSliderPointer.prototype.onmousemove = function( evt, x ){ 1833 var coords = this._getPageCoords( evt ); 1834 this._set( this.calc( coords.x ) ); 1835 }; 1836 1837 jSliderPointer.prototype.onmouseup = function( evt ){ 1838 if( this.parent.settings.callback && $.isFunction(this.parent.settings.callback) ) 1839 this.parent.settings.callback.call( this.parent, this.parent.getValue() ); 1840 1841 this.ptr.removeDependClass("hover"); 1842 }; 1843 1844 jSliderPointer.prototype.setIndexOver = function(){ 1845 this.parent.setPointersIndex( 1 ); 1846 this.index( 2 ); 1847 }; 1848 1849 jSliderPointer.prototype.index = function( i ){ 1850 this.ptr.css({ zIndex: i }); 1851 }; 1852 1853 jSliderPointer.prototype.limits = function( x ){ 1854 return this.parent.limits( x, this ); 1855 }; 1856 1857 jSliderPointer.prototype.calc = function(coords){ 1858 var x = this.limits(((coords-this._parent.offset.left)*100)/this._parent.width); 1859 return x; 1860 }; 1861 1862 jSliderPointer.prototype.set = function( value, opt_origin ){ 1863 this.value.origin = this.parent.round(value); 1864 this._set( this.parent.valueToPrc( value, this ), opt_origin ); 1865 }; 1866 1867 jSliderPointer.prototype._set = function( prc, opt_origin ){ 1868 if( !opt_origin ) 1869 this.value.origin = this.parent.prcToValue(prc); 1870 1871 this.value.prc = prc; 1872 this.ptr.css({ left: prc + "%" }); 1873 this.parent.redraw(this); 1874 }; 1875 1876})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.