Showing the changes to Source/Libraries/GSF.Web/Shared/Scripts (4 of 36 files). Show all
Unified · Split
| @@ -0,0 +1,31768 @@ | ||
| 1 | +/** | |
| 2 | + * @license AngularJS v1.5.8 | |
| 3 | + * (c) 2010-2016 Google, Inc. http://angularjs.org | |
| 4 | + * License: MIT | |
| 5 | + */ | |
| 6 | +(function(window) {'use strict'; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * @description | |
| 10 | + * | |
| 11 | + * This object provides a utility for producing rich Error messages within | |
| 12 | + * Angular. It can be called as follows: | |
| 13 | + * | |
| 14 | + * var exampleMinErr = minErr('example'); | |
| 15 | + * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); | |
| 16 | + * | |
| 17 | + * The above creates an instance of minErr in the example namespace. The | |
| 18 | + * resulting error will have a namespaced error code of example.one. The | |
| 19 | + * resulting error will replace {0} with the value of foo, and {1} with the | |
| 20 | + * value of bar. The object is not restricted in the number of arguments it can | |
| 21 | + * take. | |
| 22 | + * | |
| 23 | + * If fewer arguments are specified than necessary for interpolation, the extra | |
| 24 | + * interpolation markers will be preserved in the final string. | |
| 25 | + * | |
| 26 | + * Since data will be parsed statically during a build step, some restrictions | |
| 27 | + * are applied with respect to how minErr instances are created and called. | |
| 28 | + * Instances should have names of the form namespaceMinErr for a minErr created | |
| 29 | + * using minErr('namespace') . Error codes, namespaces and template strings | |
| 30 | + * should all be static strings, not variables or general expressions. | |
| 31 | + * | |
| 32 | + * @param {string} module The namespace to use for the new minErr instance. | |
| 33 | + * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning | |
| 34 | + * error from returned function, for cases when a particular type of error is useful. | |
| 35 | + * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance | |
| 36 | + */ | |
| 37 | + | |
| 38 | +function minErr(module, ErrorConstructor) { | |
| 39 | + ErrorConstructor = ErrorConstructor || Error; | |
| 40 | + return function() { | |
| 41 | + var SKIP_INDEXES = 2; | |
| 42 | + | |
| 43 | + var templateArgs = arguments, | |
| 44 | + code = templateArgs[0], | |
| 45 | + message = '[' + (module ? module + ':' : '') + code + '] ', | |
| 46 | + template = templateArgs[1], | |
| 47 | + paramPrefix, i; | |
| 48 | + | |
| 49 | + message += template.replace(/\{\d+\}/g, function(match) { | |
| 50 | + var index = +match.slice(1, -1), | |
| 51 | + shiftedIndex = index + SKIP_INDEXES; | |
| 52 | + | |
| 53 | + if (shiftedIndex < templateArgs.length) { | |
| 54 | + return toDebugString(templateArgs[shiftedIndex]); | |
| 55 | + } | |
| 56 | + | |
| 57 | + return match; | |
| 58 | + }); | |
| 59 | + | |
| 60 | + message += '\nhttp://errors.angularjs.org/1.5.8/' + | |
| 61 | + (module ? module + '/' : '') + code; | |
| 62 | + | |
| 63 | + for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { | |
| 64 | + message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' + | |
| 65 | + encodeURIComponent(toDebugString(templateArgs[i])); | |
| 66 | + } | |
| 67 | + | |
| 68 | + return new ErrorConstructor(message); | |
| 69 | + }; | |
| 70 | +} | |
| 71 | + | |
| 72 | +/* We need to tell jshint what variables are being exported */ | |
| 73 | +/* global angular: true, | |
| 74 | + msie: true, | |
| 75 | + jqLite: true, | |
| 76 | + jQuery: true, | |
| 77 | + slice: true, | |
| 78 | + splice: true, | |
| 79 | + push: true, | |
| 80 | + toString: true, | |
| 81 | + ngMinErr: true, | |
| 82 | + angularModule: true, | |
| 83 | + uid: true, | |
| 84 | + REGEX_STRING_REGEXP: true, | |
| 85 | + VALIDITY_STATE_PROPERTY: true, | |
| 86 | + | |
| 87 | + lowercase: true, | |
| 88 | + uppercase: true, | |
| 89 | + manualLowercase: true, | |
| 90 | + manualUppercase: true, | |
| 91 | + nodeName_: true, | |
| 92 | + isArrayLike: true, | |
| 93 | + forEach: true, | |
| 94 | + forEachSorted: true, | |
| 95 | + reverseParams: true, | |
| 96 | + nextUid: true, | |
| 97 | + setHashKey: true, | |
| 98 | + extend: true, | |
| 99 | + toInt: true, | |
| 100 | + inherit: true, | |
| 101 | + merge: true, | |
| 102 | + noop: true, | |
| 103 | + identity: true, | |
| 104 | + valueFn: true, | |
| 105 | + isUndefined: true, | |
| 106 | + isDefined: true, | |
| 107 | + isObject: true, | |
| 108 | + isBlankObject: true, | |
| 109 | + isString: true, | |
| 110 | + isNumber: true, | |
| 111 | + isDate: true, | |
| 112 | + isArray: true, | |
| 113 | + isFunction: true, | |
| 114 | + isRegExp: true, | |
| 115 | + isWindow: true, | |
| 116 | + isScope: true, | |
| 117 | + isFile: true, | |
| 118 | + isFormData: true, | |
| 119 | + isBlob: true, | |
| 120 | + isBoolean: true, | |
| 121 | + isPromiseLike: true, | |
| 122 | + trim: true, | |
| 123 | + escapeForRegexp: true, | |
| 124 | + isElement: true, | |
| 125 | + makeMap: true, | |
| 126 | + includes: true, | |
| 127 | + arrayRemove: true, | |
| 128 | + copy: true, | |
| 129 | + equals: true, | |
| 130 | + csp: true, | |
| 131 | + jq: true, | |
| 132 | + concat: true, | |
| 133 | + sliceArgs: true, | |
| 134 | + bind: true, | |
| 135 | + toJsonReplacer: true, | |
| 136 | + toJson: true, | |
| 137 | + fromJson: true, | |
| 138 | + convertTimezoneToLocal: true, | |
| 139 | + timezoneToOffset: true, | |
| 140 | + startingTag: true, | |
| 141 | + tryDecodeURIComponent: true, | |
| 142 | + parseKeyValue: true, | |
| 143 | + toKeyValue: true, | |
| 144 | + encodeUriSegment: true, | |
| 145 | + encodeUriQuery: true, | |
| 146 | + angularInit: true, | |
| 147 | + bootstrap: true, | |
| 148 | + getTestability: true, | |
| 149 | + snake_case: true, | |
| 150 | + bindJQuery: true, | |
| 151 | + assertArg: true, | |
| 152 | + assertArgFn: true, | |
| 153 | + assertNotHasOwnProperty: true, | |
| 154 | + getter: true, | |
| 155 | + getBlockNodes: true, | |
| 156 | + hasOwnProperty: true, | |
| 157 | + createMap: true, | |
| 158 | + | |
| 159 | + NODE_TYPE_ELEMENT: true, | |
| 160 | + NODE_TYPE_ATTRIBUTE: true, | |
| 161 | + NODE_TYPE_TEXT: true, | |
| 162 | + NODE_TYPE_COMMENT: true, | |
| 163 | + NODE_TYPE_DOCUMENT: true, | |
| 164 | + NODE_TYPE_DOCUMENT_FRAGMENT: true, | |
| 165 | +*/ | |
| 166 | + | |
| 167 | +//////////////////////////////////// | |
| 168 | + | |
| 169 | +/** | |
| 170 | + * @ngdoc module | |
| 171 | + * @name ng | |
| 172 | + * @module ng | |
| 173 | + * @installation | |
| 174 | + * @description | |
| 175 | + * | |
| 176 | + * # ng (core module) | |
| 177 | + * The ng module is loaded by default when an AngularJS application is started. The module itself | |
| 178 | + * contains the essential components for an AngularJS application to function. The table below | |
| 179 | + * lists a high level breakdown of each of the services/factories, filters, directives and testing | |
| 180 | + * components available within this core module. | |
| 181 | + * | |
| 182 | + * <div doc-module-components="ng"></div> | |
| 183 | + */ | |
| 184 | + | |
| 185 | +var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; | |
| 186 | + | |
| 187 | +// The name of a form control's ValidityState property. | |
| 188 | +// This is used so that it's possible for internal tests to create mock ValidityStates. | |
| 189 | +var VALIDITY_STATE_PROPERTY = 'validity'; | |
| 190 | + | |
| 191 | +var hasOwnProperty = Object.prototype.hasOwnProperty; | |
| 192 | + | |
| 193 | +var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; | |
| 194 | +var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; | |
| 195 | + | |
| 196 | + | |
| 197 | +var manualLowercase = function(s) { | |
| 198 | + /* jshint bitwise: false */ | |
| 199 | + return isString(s) | |
| 200 | + ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) | |
| 201 | + : s; | |
| 202 | +}; | |
| 203 | +var manualUppercase = function(s) { | |
| 204 | + /* jshint bitwise: false */ | |
| 205 | + return isString(s) | |
| 206 | + ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) | |
| 207 | + : s; | |
| 208 | +}; | |
| 209 | + | |
| 210 | + | |
| 211 | +// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish | |
| 212 | +// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods | |
| 213 | +// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387 | |
| 214 | +if ('i' !== 'I'.toLowerCase()) { | |
| 215 | + lowercase = manualLowercase; | |
| 216 | + uppercase = manualUppercase; | |
| 217 | +} | |
| 218 | + | |
| 219 | + | |
| 220 | +var | |
| 221 | + msie, // holds major version number for IE, or NaN if UA is not IE. | |
| 222 | + jqLite, // delay binding since jQuery could be loaded after us. | |
| 223 | + jQuery, // delay binding | |
| 224 | + slice = [].slice, | |
| 225 | + splice = [].splice, | |
| 226 | + push = [].push, | |
| 227 | + toString = Object.prototype.toString, | |
| 228 | + getPrototypeOf = Object.getPrototypeOf, | |
| 229 | + ngMinErr = minErr('ng'), | |
| 230 | + | |
| 231 | + /** @name angular */ | |
| 232 | + angular = window.angular || (window.angular = {}), | |
| 233 | + angularModule, | |
| 234 | + uid = 0; | |
| 235 | + | |
| 236 | +/** | |
| 237 | + * documentMode is an IE-only property | |
| 238 | + * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx | |
| 239 | + */ | |
| 240 | +msie = window.document.documentMode; | |
| 241 | + | |
| 242 | + | |
| 243 | +/** | |
| 244 | + * @private | |
| 245 | + * @param {*} obj | |
| 246 | + * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, | |
| 247 | + * String ...) | |
| 248 | + */ | |
| 249 | +function isArrayLike(obj) { | |
| 250 | + | |
| 251 | + // `null`, `undefined` and `window` are not array-like | |
| 252 | + if (obj == null || isWindow(obj)) return false; | |
| 253 | + | |
| 254 | + // arrays, strings and jQuery/jqLite objects are array like | |
| 255 | + // * jqLite is either the jQuery or jqLite constructor function | |
| 256 | + // * we have to check the existence of jqLite first as this method is called | |
| 257 | + // via the forEach method when constructing the jqLite object in the first place | |
| 258 | + if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true; | |
| 259 | + | |
| 260 | + // Support: iOS 8.2 (not reproducible in simulator) | |
| 261 | + // "length" in obj used to prevent JIT error (gh-11508) | |
| 262 | + var length = "length" in Object(obj) && obj.length; | |
| 263 | + | |
| 264 | + // NodeList objects (with `item` method) and | |
| 265 | + // other objects with suitable length characteristics are array-like | |
| 266 | + return isNumber(length) && | |
| 267 | + (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function'); | |
| 268 | + | |
| 269 | +} | |
| 270 | + | |
| 271 | +/** | |
| 272 | + * @ngdoc function | |
| 273 | + * @name angular.forEach | |
| 274 | + * @module ng | |
| 275 | + * @kind function | |
| 276 | + * | |
| 277 | + * @description | |
| 278 | + * Invokes the `iterator` function once for each item in `obj` collection, which can be either an | |
| 279 | + * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value` | |
| 280 | + * is the value of an object property or an array element, `key` is the object property key or | |
| 281 | + * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional. | |
| 282 | + * | |
| 283 | + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters | |
| 284 | + * using the `hasOwnProperty` method. | |
| 285 | + * | |
| 286 | + * Unlike ES262's | |
| 287 | + * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), | |
| 288 | + * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just | |
| 289 | + * return the value provided. | |
| 290 | + * | |
| 291 | + ```js | |
| 292 | + var values = {name: 'misko', gender: 'male'}; | |
| 293 | + var log = []; | |
| 294 | + angular.forEach(values, function(value, key) { | |
| 295 | + this.push(key + ': ' + value); | |
| 296 | + }, log); | |
| 297 | + expect(log).toEqual(['name: misko', 'gender: male']); | |
| 298 | + ``` | |
| 299 | + * | |
| 300 | + * @param {Object|Array} obj Object to iterate over. | |
| 301 | + * @param {Function} iterator Iterator function. | |
| 302 | + * @param {Object=} context Object to become context (`this`) for the iterator function. | |
| 303 | + * @returns {Object|Array} Reference to `obj`. | |
| 304 | + */ | |
| 305 | + | |
| 306 | +function forEach(obj, iterator, context) { | |
| 307 | + var key, length; | |
| 308 | + if (obj) { | |
| 309 | + if (isFunction(obj)) { | |
| 310 | + for (key in obj) { | |
| 311 | + // Need to check if hasOwnProperty exists, | |
| 312 | + // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function | |
| 313 | + if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { | |
| 314 | + iterator.call(context, obj[key], key, obj); | |
| 315 | + } | |
| 316 | + } | |
| 317 | + } else if (isArray(obj) || isArrayLike(obj)) { | |
| 318 | + var isPrimitive = typeof obj !== 'object'; | |
| 319 | + for (key = 0, length = obj.length; key < length; key++) { | |
| 320 | + if (isPrimitive || key in obj) { | |
| 321 | + iterator.call(context, obj[key], key, obj); | |
| 322 | + } | |
| 323 | + } | |
| 324 | + } else if (obj.forEach && obj.forEach !== forEach) { | |
| 325 | + obj.forEach(iterator, context, obj); | |
| 326 | + } else if (isBlankObject(obj)) { | |
| 327 | + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty | |
| 328 | + for (key in obj) { | |
| 329 | + iterator.call(context, obj[key], key, obj); | |
| 330 | + } | |
| 331 | + } else if (typeof obj.hasOwnProperty === 'function') { | |
| 332 | + // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed | |
| 333 | + for (key in obj) { | |
| 334 | + if (obj.hasOwnProperty(key)) { | |
| 335 | + iterator.call(context, obj[key], key, obj); | |
| 336 | + } | |
| 337 | + } | |
| 338 | + } else { | |
| 339 | + // Slow path for objects which do not have a method `hasOwnProperty` | |
| 340 | + for (key in obj) { | |
| 341 | + if (hasOwnProperty.call(obj, key)) { | |
| 342 | + iterator.call(context, obj[key], key, obj); | |
| 343 | + } | |
| 344 | + } | |
| 345 | + } | |
| 346 | + } | |
| 347 | + return obj; | |
| 348 | +} | |
| 349 | + | |
| 350 | +function forEachSorted(obj, iterator, context) { | |
| 351 | + var keys = Object.keys(obj).sort(); | |
| 352 | + for (var i = 0; i < keys.length; i++) { | |
| 353 | + iterator.call(context, obj[keys[i]], keys[i]); | |
| 354 | + } | |
| 355 | + return keys; | |
| 356 | +} | |
| 357 | + | |
| 358 | + | |
| 359 | +/** | |
| 360 | + * when using forEach the params are value, key, but it is often useful to have key, value. | |
| 361 | + * @param {function(string, *)} iteratorFn | |
| 362 | + * @returns {function(*, string)} | |
| 363 | + */ | |
| 364 | +function reverseParams(iteratorFn) { | |
| 365 | + return function(value, key) {iteratorFn(key, value);}; | |
| 366 | +} | |
| 367 | + | |
| 368 | +/** | |
| 369 | + * A consistent way of creating unique IDs in angular. | |
| 370 | + * | |
| 371 | + * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before | |
| 372 | + * we hit number precision issues in JavaScript. | |
| 373 | + * | |
| 374 | + * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M | |
| 375 | + * | |
| 376 | + * @returns {number} an unique alpha-numeric string | |
| 377 | + */ | |
| 378 | +function nextUid() { | |
| 379 | + return ++uid; | |
| 380 | +} | |
| 381 | + | |
| 382 | + | |
| 383 | +/** | |
| 384 | + * Set or clear the hashkey for an object. | |
| 385 | + * @param obj object | |
| 386 | + * @param h the hashkey (!truthy to delete the hashkey) | |
| 387 | + */ | |
| 388 | +function setHashKey(obj, h) { | |
| 389 | + if (h) { | |
| 390 | + obj.$$hashKey = h; | |
| 391 | + } else { | |
| 392 | + delete obj.$$hashKey; | |
| 393 | + } | |
| 394 | +} | |
| 395 | + | |
| 396 | + | |
| 397 | +function baseExtend(dst, objs, deep) { | |
| 398 | + var h = dst.$$hashKey; | |
| 399 | + | |
| 400 | + for (var i = 0, ii = objs.length; i < ii; ++i) { | |
| 401 | + var obj = objs[i]; | |
| 402 | + if (!isObject(obj) && !isFunction(obj)) continue; | |
| 403 | + var keys = Object.keys(obj); | |
| 404 | + for (var j = 0, jj = keys.length; j < jj; j++) { | |
| 405 | + var key = keys[j]; | |
| 406 | + var src = obj[key]; | |
| 407 | + | |
| 408 | + if (deep && isObject(src)) { | |
| 409 | + if (isDate(src)) { | |
| 410 | + dst[key] = new Date(src.valueOf()); | |
| 411 | + } else if (isRegExp(src)) { | |
| 412 | + dst[key] = new RegExp(src); | |
| 413 | + } else if (src.nodeName) { | |
| 414 | + dst[key] = src.cloneNode(true); | |
| 415 | + } else if (isElement(src)) { | |
| 416 | + dst[key] = src.clone(); | |
| 417 | + } else { | |
| 418 | + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; | |
| 419 | + baseExtend(dst[key], [src], true); | |
| 420 | + } | |
| 421 | + } else { | |
| 422 | + dst[key] = src; | |
| 423 | + } | |
| 424 | + } | |
| 425 | + } | |
| 426 | + | |
| 427 | + setHashKey(dst, h); | |
| 428 | + return dst; | |
| 429 | +} | |
| 430 | + | |
| 431 | +/** | |
| 432 | + * @ngdoc function | |
| 433 | + * @name angular.extend | |
| 434 | + * @module ng | |
| 435 | + * @kind function | |
| 436 | + * | |
| 437 | + * @description | |
| 438 | + * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) | |
| 439 | + * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so | |
| 440 | + * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. | |
| 441 | + * | |
| 442 | + * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use | |
| 443 | + * {@link angular.merge} for this. | |
| 444 | + * | |
| 445 | + * @param {Object} dst Destination object. | |
| 446 | + * @param {...Object} src Source object(s). | |
| 447 | + * @returns {Object} Reference to `dst`. | |
| 448 | + */ | |
| 449 | +function extend(dst) { | |
| 450 | + return baseExtend(dst, slice.call(arguments, 1), false); | |
| 451 | +} | |
| 452 | + | |
| 453 | + | |
| 454 | +/** | |
| 455 | +* @ngdoc function | |
| 456 | +* @name angular.merge | |
| 457 | +* @module ng | |
| 458 | +* @kind function | |
| 459 | +* | |
| 460 | +* @description | |
| 461 | +* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s) | |
| 462 | +* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so | |
| 463 | +* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`. | |
| 464 | +* | |
| 465 | +* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source | |
| 466 | +* objects, performing a deep copy. | |
| 467 | +* | |
| 468 | +* @param {Object} dst Destination object. | |
| 469 | +* @param {...Object} src Source object(s). | |
| 470 | +* @returns {Object} Reference to `dst`. | |
| 471 | +*/ | |
| 472 | +function merge(dst) { | |
| 473 | + return baseExtend(dst, slice.call(arguments, 1), true); | |
| 474 | +} | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | +function toInt(str) { | |
| 479 | + return parseInt(str, 10); | |
| 480 | +} | |
| 481 | + | |
| 482 | + | |
| 483 | +function inherit(parent, extra) { | |
| 484 | + return extend(Object.create(parent), extra); | |
| 485 | +} | |
| 486 | + | |
| 487 | +/** | |
| 488 | + * @ngdoc function | |
| 489 | + * @name angular.noop | |
| 490 | + * @module ng | |
| 491 | + * @kind function | |
| 492 | + * | |
| 493 | + * @description | |
| 494 | + * A function that performs no operations. This function can be useful when writing code in the | |
| 495 | + * functional style. | |
| 496 | + ```js | |
| 497 | + function foo(callback) { | |
| 498 | + var result = calculateResult(); | |
| 499 | + (callback || angular.noop)(result); | |
| 500 | + } | |
| 501 | + ``` | |
| 502 | + */ | |
| 503 | +function noop() {} | |
| 504 | +noop.$inject = []; | |
| 505 | + | |
| 506 | + | |
| 507 | +/** | |
| 508 | + * @ngdoc function | |
| 509 | + * @name angular.identity | |
| 510 | + * @module ng | |
| 511 | + * @kind function | |
| 512 | + * | |
| 513 | + * @description | |
| 514 | + * A function that returns its first argument. This function is useful when writing code in the | |
| 515 | + * functional style. | |
| 516 | + * | |
| 517 | + ```js | |
| 518 | + function transformer(transformationFn, value) { | |
| 519 | + return (transformationFn || angular.identity)(value); | |
| 520 | + }; | |
| 521 | + | |
| 522 | + // E.g. | |
| 523 | + function getResult(fn, input) { | |
| 524 | + return (fn || angular.identity)(input); | |
| 525 | + }; | |
| 526 | + | |
| 527 | + getResult(function(n) { return n * 2; }, 21); // returns 42 | |
| 528 | + getResult(null, 21); // returns 21 | |
| 529 | + getResult(undefined, 21); // returns 21 | |
| 530 | + ``` | |
| 531 | + * | |
| 532 | + * @param {*} value to be returned. | |
| 533 | + * @returns {*} the value passed in. | |
| 534 | + */ | |
| 535 | +function identity($) {return $;} | |
| 536 | +identity.$inject = []; | |
| 537 | + | |
| 538 | + | |
| 539 | +function valueFn(value) {return function valueRef() {return value;};} | |
| 540 | + | |
| 541 | +function hasCustomToString(obj) { | |
| 542 | + return isFunction(obj.toString) && obj.toString !== toString; | |
| 543 | +} | |
| 544 | + | |
| 545 | + | |
| 546 | +/** | |
| 547 | + * @ngdoc function | |
| 548 | + * @name angular.isUndefined | |
| 549 | + * @module ng | |
| 550 | + * @kind function | |
| 551 | + * | |
| 552 | + * @description | |
| 553 | + * Determines if a reference is undefined. | |
| 554 | + * | |
| 555 | + * @param {*} value Reference to check. | |
| 556 | + * @returns {boolean} True if `value` is undefined. | |
| 557 | + */ | |
| 558 | +function isUndefined(value) {return typeof value === 'undefined';} | |
| 559 | + | |
| 560 | + | |
| 561 | +/** | |
| 562 | + * @ngdoc function | |
| 563 | + * @name angular.isDefined | |
| 564 | + * @module ng | |
| 565 | + * @kind function | |
| 566 | + * | |
| 567 | + * @description | |
| 568 | + * Determines if a reference is defined. | |
| 569 | + * | |
| 570 | + * @param {*} value Reference to check. | |
| 571 | + * @returns {boolean} True if `value` is defined. | |
| 572 | + */ | |
| 573 | +function isDefined(value) {return typeof value !== 'undefined';} | |
| 574 | + | |
| 575 | + | |
| 576 | +/** | |
| 577 | + * @ngdoc function | |
| 578 | + * @name angular.isObject | |
| 579 | + * @module ng | |
| 580 | + * @kind function | |
| 581 | + * | |
| 582 | + * @description | |
| 583 | + * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not | |
| 584 | + * considered to be objects. Note that JavaScript arrays are objects. | |
| 585 | + * | |
| 586 | + * @param {*} value Reference to check. | |
| 587 | + * @returns {boolean} True if `value` is an `Object` but not `null`. | |
| 588 | + */ | |
| 589 | +function isObject(value) { | |
| 590 | + // http://jsperf.com/isobject4 | |
| 591 | + return value !== null && typeof value === 'object'; | |
| 592 | +} | |
| 593 | + | |
| 594 | + | |
| 595 | +/** | |
| 596 | + * Determine if a value is an object with a null prototype | |
| 597 | + * | |
| 598 | + * @returns {boolean} True if `value` is an `Object` with a null prototype | |
| 599 | + */ | |
| 600 | +function isBlankObject(value) { | |
| 601 | + return value !== null && typeof value === 'object' && !getPrototypeOf(value); | |
| 602 | +} | |
| 603 | + | |
| 604 | + | |
| 605 | +/** | |
| 606 | + * @ngdoc function | |
| 607 | + * @name angular.isString | |
| 608 | + * @module ng | |
| 609 | + * @kind function | |
| 610 | + * | |
| 611 | + * @description | |
| 612 | + * Determines if a reference is a `String`. | |
| 613 | + * | |
| 614 | + * @param {*} value Reference to check. | |
| 615 | + * @returns {boolean} True if `value` is a `String`. | |
| 616 | + */ | |
| 617 | +function isString(value) {return typeof value === 'string';} | |
| 618 | + | |
| 619 | + | |
| 620 | +/** | |
| 621 | + * @ngdoc function | |
| 622 | + * @name angular.isNumber | |
| 623 | + * @module ng | |
| 624 | + * @kind function | |
| 625 | + * | |
| 626 | + * @description | |
| 627 | + * Determines if a reference is a `Number`. | |
| 628 | + * | |
| 629 | + * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. | |
| 630 | + * | |
| 631 | + * If you wish to exclude these then you can use the native | |
| 632 | + * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) | |
| 633 | + * method. | |
| 634 | + * | |
| 635 | + * @param {*} value Reference to check. | |
| 636 | + * @returns {boolean} True if `value` is a `Number`. | |
| 637 | + */ | |
| 638 | +function isNumber(value) {return typeof value === 'number';} | |
| 639 | + | |
| 640 | + | |
| 641 | +/** | |
| 642 | + * @ngdoc function | |
| 643 | + * @name angular.isDate | |
| 644 | + * @module ng | |
| 645 | + * @kind function | |
| 646 | + * | |
| 647 | + * @description | |
| 648 | + * Determines if a value is a date. | |
| 649 | + * | |
| 650 | + * @param {*} value Reference to check. | |
| 651 | + * @returns {boolean} True if `value` is a `Date`. | |
| 652 | + */ | |
| 653 | +function isDate(value) { | |
| 654 | + return toString.call(value) === '[object Date]'; | |
| 655 | +} | |
| 656 | + | |
| 657 | + | |
| 658 | +/** | |
| 659 | + * @ngdoc function | |
| 660 | + * @name angular.isArray | |
| 661 | + * @module ng | |
| 662 | + * @kind function | |
| 663 | + * | |
| 664 | + * @description | |
| 665 | + * Determines if a reference is an `Array`. | |
| 666 | + * | |
| 667 | + * @param {*} value Reference to check. | |
| 668 | + * @returns {boolean} True if `value` is an `Array`. | |
| 669 | + */ | |
| 670 | +var isArray = Array.isArray; | |
| 671 | + | |
| 672 | +/** | |
| 673 | + * @ngdoc function | |
| 674 | + * @name angular.isFunction | |
| 675 | + * @module ng | |
| 676 | + * @kind function | |
| 677 | + * | |
| 678 | + * @description | |
| 679 | + * Determines if a reference is a `Function`. | |
| 680 | + * | |
| 681 | + * @param {*} value Reference to check. | |
| 682 | + * @returns {boolean} True if `value` is a `Function`. | |
| 683 | + */ | |
| 684 | +function isFunction(value) {return typeof value === 'function';} | |
| 685 | + | |
| 686 | + | |
| 687 | +/** | |
| 688 | + * Determines if a value is a regular expression object. | |
| 689 | + * | |
| 690 | + * @private | |
| 691 | + * @param {*} value Reference to check. | |
| 692 | + * @returns {boolean} True if `value` is a `RegExp`. | |
| 693 | + */ | |
| 694 | +function isRegExp(value) { | |
| 695 | + return toString.call(value) === '[object RegExp]'; | |
| 696 | +} | |
| 697 | + | |
| 698 | + | |
| 699 | +/** | |
| 700 | + * Checks if `obj` is a window object. | |
| 701 | + * | |
| 702 | + * @private | |
| 703 | + * @param {*} obj Object to check | |
| 704 | + * @returns {boolean} True if `obj` is a window obj. | |
| 705 | + */ | |
| 706 | +function isWindow(obj) { | |
| 707 | + return obj && obj.window === obj; | |
| 708 | +} | |
| 709 | + | |
| 710 | + | |
| 711 | +function isScope(obj) { | |
| 712 | + return obj && obj.$evalAsync && obj.$watch; | |
| 713 | +} | |
| 714 | + | |
| 715 | + | |
| 716 | +function isFile(obj) { | |
| 717 | + return toString.call(obj) === '[object File]'; | |
| 718 | +} | |
| 719 | + | |
| 720 | + | |
| 721 | +function isFormData(obj) { | |
| 722 | + return toString.call(obj) === '[object FormData]'; | |
| 723 | +} | |
| 724 | + | |
| 725 | + | |
| 726 | +function isBlob(obj) { | |
| 727 | + return toString.call(obj) === '[object Blob]'; | |
| 728 | +} | |
| 729 | + | |
| 730 | + | |
| 731 | +function isBoolean(value) { | |
| 732 | + return typeof value === 'boolean'; | |
| 733 | +} | |
| 734 | + | |
| 735 | + | |
| 736 | +function isPromiseLike(obj) { | |
| 737 | + return obj && isFunction(obj.then); | |
| 738 | +} | |
| 739 | + | |
| 740 | + | |
| 741 | +var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/; | |
| 742 | +function isTypedArray(value) { | |
| 743 | + return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value)); | |
| 744 | +} | |
| 745 | + | |
| 746 | +function isArrayBuffer(obj) { | |
| 747 | + return toString.call(obj) === '[object ArrayBuffer]'; | |
| 748 | +} | |
| 749 | + | |
| 750 | + | |
| 751 | +var trim = function(value) { | |
| 752 | + return isString(value) ? value.trim() : value; | |
| 753 | +}; | |
| 754 | + | |
| 755 | +// Copied from: | |
| 756 | +// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021 | |
| 757 | +// Prereq: s is a string. | |
| 758 | +var escapeForRegexp = function(s) { | |
| 759 | + return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1'). | |
| 760 | + replace(/\x08/g, '\\x08'); | |
| 761 | +}; | |
| 762 | + | |
| 763 | + | |
| 764 | +/** | |
| 765 | + * @ngdoc function | |
| 766 | + * @name angular.isElement | |
| 767 | + * @module ng | |
| 768 | + * @kind function | |
| 769 | + * | |
| 770 | + * @description | |
| 771 | + * Determines if a reference is a DOM element (or wrapped jQuery element). | |
| 772 | + * | |
| 773 | + * @param {*} value Reference to check. | |
| 774 | + * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element). | |
| 775 | + */ | |
| 776 | +function isElement(node) { | |
| 777 | + return !!(node && | |
| 778 | + (node.nodeName // We are a direct element. | |
| 779 | + || (node.prop && node.attr && node.find))); // We have an on and find method part of jQuery API. | |
| 780 | +} | |
| 781 | + | |
| 782 | +/** | |
| 783 | + * @param str 'key1,key2,...' | |
| 784 | + * @returns {object} in the form of {key1:true, key2:true, ...} | |
| 785 | + */ | |
| 786 | +function makeMap(str) { | |
| 787 | + var obj = {}, items = str.split(','), i; | |
| 788 | + for (i = 0; i < items.length; i++) { | |
| 789 | + obj[items[i]] = true; | |
| 790 | + } | |
| 791 | + return obj; | |
| 792 | +} | |
| 793 | + | |
| 794 | + | |
| 795 | +function nodeName_(element) { | |
| 796 | + return lowercase(element.nodeName || (element[0] && element[0].nodeName)); | |
| 797 | +} | |
| 798 | + | |
| 799 | +function includes(array, obj) { | |
| 800 | + return Array.prototype.indexOf.call(array, obj) != -1; | |
| 801 | +} | |
| 802 | + | |
| 803 | +function arrayRemove(array, value) { | |
| 804 | + var index = array.indexOf(value); | |
| 805 | + if (index >= 0) { | |
| 806 | + array.splice(index, 1); | |
| 807 | + } | |
| 808 | + return index; | |
| 809 | +} | |
| 810 | + | |
| 811 | +/** | |
| 812 | + * @ngdoc function | |
| 813 | + * @name angular.copy | |
| 814 | + * @module ng | |
| 815 | + * @kind function | |
| 816 | + * | |
| 817 | + * @description | |
| 818 | + * Creates a deep copy of `source`, which should be an object or an array. | |
| 819 | + * | |
| 820 | + * * If no destination is supplied, a copy of the object or array is created. | |
| 821 | + * * If a destination is provided, all of its elements (for arrays) or properties (for objects) | |
| 822 | + * are deleted and then all elements/properties from the source are copied to it. | |
| 823 | + * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. | |
| 824 | + * * If `source` is identical to `destination` an exception will be thrown. | |
| 825 | + * | |
| 826 | + * <br /> | |
| 827 | + * <div class="alert alert-warning"> | |
| 828 | + * Only enumerable properties are taken into account. Non-enumerable properties (both on `source` | |
| 829 | + * and on `destination`) will be ignored. | |
| 830 | + * </div> | |
| 831 | + * | |
| 832 | + * @param {*} source The source that will be used to make a copy. | |
| 833 | + * Can be any type, including primitives, `null`, and `undefined`. | |
| 834 | + * @param {(Object|Array)=} destination Destination into which the source is copied. If | |
| 835 | + * provided, must be of the same type as `source`. | |
| 836 | + * @returns {*} The copy or updated `destination`, if `destination` was specified. | |
| 837 | + * | |
| 838 | + * @example | |
| 839 | + <example module="copyExample"> | |
| 840 | + <file name="index.html"> | |
| 841 | + <div ng-controller="ExampleController"> | |
| 842 | + <form novalidate class="simple-form"> | |
| 843 | + <label>Name: <input type="text" ng-model="user.name" /></label><br /> | |
| 844 | + <label>Age: <input type="number" ng-model="user.age" /></label><br /> | |
| 845 | + Gender: <label><input type="radio" ng-model="user.gender" value="male" />male</label> | |
| 846 | + <label><input type="radio" ng-model="user.gender" value="female" />female</label><br /> | |
| 847 | + <button ng-click="reset()">RESET</button> | |
| 848 | + <button ng-click="update(user)">SAVE</button> | |
| 849 | + </form> | |
| 850 | + <pre>form = {{user | json}}</pre> | |
| 851 | + <pre>master = {{master | json}}</pre> | |
| 852 | + </div> | |
| 853 | + </file> | |
| 854 | + <file name="script.js"> | |
| 855 | + // Module: copyExample | |
| 856 | + angular. | |
| 857 | + module('copyExample', []). | |
| 858 | + controller('ExampleController', ['$scope', function($scope) { | |
| 859 | + $scope.master = {}; | |
| 860 | + | |
| 861 | + $scope.reset = function() { | |
| 862 | + // Example with 1 argument | |
| 863 | + $scope.user = angular.copy($scope.master); | |
| 864 | + }; | |
| 865 | + | |
| 866 | + $scope.update = function(user) { | |
| 867 | + // Example with 2 arguments | |
| 868 | + angular.copy(user, $scope.master); | |
| 869 | + }; | |
| 870 | + | |
| 871 | + $scope.reset(); | |
| 872 | + }]); | |
| 873 | + </file> | |
| 874 | + </example> | |
| 875 | + */ | |
| 876 | +function copy(source, destination) { | |
| 877 | + var stackSource = []; | |
| 878 | + var stackDest = []; | |
| 879 | + | |
| 880 | + if (destination) { | |
| 881 | + if (isTypedArray(destination) || isArrayBuffer(destination)) { | |
| 882 | + throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated."); | |
| 883 | + } | |
| 884 | + if (source === destination) { | |
| 885 | + throw ngMinErr('cpi', "Can't copy! Source and destination are identical."); | |
| 886 | + } | |
| 887 | + | |
| 888 | + // Empty the destination object | |
| 889 | + if (isArray(destination)) { | |
| 890 | + destination.length = 0; | |
| 891 | + } else { | |
| 892 | + forEach(destination, function(value, key) { | |
| 893 | + if (key !== '$$hashKey') { | |
| 894 | + delete destination[key]; | |
| 895 | + } | |
| 896 | + }); | |
| 897 | + } | |
| 898 | + | |
| 899 | + stackSource.push(source); | |
| 900 | + stackDest.push(destination); | |
| 901 | + return copyRecurse(source, destination); | |
| 902 | + } | |
| 903 | + | |
| 904 | + return copyElement(source); | |
| 905 | + | |
| 906 | + function copyRecurse(source, destination) { | |
| 907 | + var h = destination.$$hashKey; | |
| 908 | + var key; | |
| 909 | + if (isArray(source)) { | |
| 910 | + for (var i = 0, ii = source.length; i < ii; i++) { | |
| 911 | + destination.push(copyElement(source[i])); | |
| 912 | + } | |
| 913 | + } else if (isBlankObject(source)) { | |
| 914 | + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty | |
| 915 | + for (key in source) { | |
| 916 | + destination[key] = copyElement(source[key]); | |
| 917 | + } | |
| 918 | + } else if (source && typeof source.hasOwnProperty === 'function') { | |
| 919 | + // Slow path, which must rely on hasOwnProperty | |
| 920 | + for (key in source) { | |
| 921 | + if (source.hasOwnProperty(key)) { | |
| 922 | + destination[key] = copyElement(source[key]); | |
| 923 | + } | |
| 924 | + } | |
| 925 | + } else { | |
| 926 | + // Slowest path --- hasOwnProperty can't be called as a method | |
| 927 | + for (key in source) { | |
| 928 | + if (hasOwnProperty.call(source, key)) { | |
| 929 | + destination[key] = copyElement(source[key]); | |
| 930 | + } | |
| 931 | + } | |
| 932 | + } | |
| 933 | + setHashKey(destination, h); | |
| 934 | + return destination; | |
| 935 | + } | |
| 936 | + | |
| 937 | + function copyElement(source) { | |
| 938 | + // Simple values | |
| 939 | + if (!isObject(source)) { | |
| 940 | + return source; | |
| 941 | + } | |
| 942 | + | |
| 943 | + // Already copied values | |
| 944 | + var index = stackSource.indexOf(source); | |
| 945 | + if (index !== -1) { | |
| 946 | + return stackDest[index]; | |
| 947 | + } | |
| 948 | + | |
| 949 | + if (isWindow(source) || isScope(source)) { | |
| 950 | + throw ngMinErr('cpws', | |
| 951 | + "Can't copy! Making copies of Window or Scope instances is not supported."); | |
| 952 | + } | |
| 953 | + | |
| 954 | + var needsRecurse = false; | |
| 955 | + var destination = copyType(source); | |
| 956 | + | |
| 957 | + if (destination === undefined) { | |
| 958 | + destination = isArray(source) ? [] : Object.create(getPrototypeOf(source)); | |
| 959 | + needsRecurse = true; | |
| 960 | + } | |
| 961 | + | |
| 962 | + stackSource.push(source); | |
| 963 | + stackDest.push(destination); | |
| 964 | + | |
| 965 | + return needsRecurse | |
| 966 | + ? copyRecurse(source, destination) | |
| 967 | + : destination; | |
| 968 | + } | |
| 969 | + | |
| 970 | + function copyType(source) { | |
| 971 | + switch (toString.call(source)) { | |
| 972 | + case '[object Int8Array]': | |
| 973 | + case '[object Int16Array]': | |
| 974 | + case '[object Int32Array]': | |
| 975 | + case '[object Float32Array]': | |
| 976 | + case '[object Float64Array]': | |
| 977 | + case '[object Uint8Array]': | |
| 978 | + case '[object Uint8ClampedArray]': | |
| 979 | + case '[object Uint16Array]': | |
| 980 | + case '[object Uint32Array]': | |
| 981 | + return new source.constructor(copyElement(source.buffer), source.byteOffset, source.length); | |
| 982 | + | |
| 983 | + case '[object ArrayBuffer]': | |
| 984 | + //Support: IE10 | |
| 985 | + if (!source.slice) { | |
| 986 | + var copied = new ArrayBuffer(source.byteLength); | |
| 987 | + new Uint8Array(copied).set(new Uint8Array(source)); | |
| 988 | + return copied; | |
| 989 | + } | |
| 990 | + return source.slice(0); | |
| 991 | + | |
| 992 | + case '[object Boolean]': | |
| 993 | + case '[object Number]': | |
| 994 | + case '[object String]': | |
| 995 | + case '[object Date]': | |
| 996 | + return new source.constructor(source.valueOf()); | |
| 997 | + | |
| 998 | + case '[object RegExp]': | |
| 999 | + var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); | |
| 1000 | + re.lastIndex = source.lastIndex; | |
| 1001 | + return re; | |
| 1002 | + | |
| 1003 | + case '[object Blob]': | |
| 1004 | + return new source.constructor([source], {type: source.type}); | |
| 1005 | + } | |
| 1006 | + | |
| 1007 | + if (isFunction(source.cloneNode)) { | |
| 1008 | + return source.cloneNode(true); | |
| 1009 | + } | |
| 1010 | + } | |
| 1011 | +} | |
| 1012 | + | |
| 1013 | + | |
| 1014 | +/** | |
| 1015 | + * @ngdoc function | |
| 1016 | + * @name angular.equals | |
| 1017 | + * @module ng | |
| 1018 | + * @kind function | |
| 1019 | + * | |
| 1020 | + * @description | |
| 1021 | + * Determines if two objects or two values are equivalent. Supports value types, regular | |
| 1022 | + * expressions, arrays and objects. | |
| 1023 | + * | |
| 1024 | + * Two objects or values are considered equivalent if at least one of the following is true: | |
| 1025 | + * | |
| 1026 | + * * Both objects or values pass `===` comparison. | |
| 1027 | + * * Both objects or values are of the same type and all of their properties are equal by | |
| 1028 | + * comparing them with `angular.equals`. | |
| 1029 | + * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) | |
| 1030 | + * * Both values represent the same regular expression (In JavaScript, | |
| 1031 | + * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual | |
| 1032 | + * representation matches). | |
| 1033 | + * | |
| 1034 | + * During a property comparison, properties of `function` type and properties with names | |
| 1035 | + * that begin with `$` are ignored. | |
| 1036 | + * | |
| 1037 | + * Scope and DOMWindow objects are being compared only by identify (`===`). | |
| 1038 | + * | |
| 1039 | + * @param {*} o1 Object or value to compare. | |
| 1040 | + * @param {*} o2 Object or value to compare. | |
| 1041 | + * @returns {boolean} True if arguments are equal. | |
| 1042 | + * | |
| 1043 | + * @example | |
| 1044 | + <example module="equalsExample" name="equalsExample"> | |
| 1045 | + <file name="index.html"> | |
| 1046 | + <div ng-controller="ExampleController"> | |
| 1047 | + <form novalidate> | |
| 1048 | + <h3>User 1</h3> | |
| 1049 | + Name: <input type="text" ng-model="user1.name"> | |
| 1050 | + Age: <input type="number" ng-model="user1.age"> | |
| 1051 | + | |
| 1052 | + <h3>User 2</h3> | |
| 1053 | + Name: <input type="text" ng-model="user2.name"> | |
| 1054 | + Age: <input type="number" ng-model="user2.age"> | |
| 1055 | + | |
| 1056 | + <div> | |
| 1057 | + <br/> | |
| 1058 | + <input type="button" value="Compare" ng-click="compare()"> | |
| 1059 | + </div> | |
| 1060 | + User 1: <pre>{{user1 | json}}</pre> | |
| 1061 | + User 2: <pre>{{user2 | json}}</pre> | |
| 1062 | + Equal: <pre>{{result}}</pre> | |
| 1063 | + </form> | |
| 1064 | + </div> | |
| 1065 | + </file> | |
| 1066 | + <file name="script.js"> | |
| 1067 | + angular.module('equalsExample', []).controller('ExampleController', ['$scope', function($scope) { | |
| 1068 | + $scope.user1 = {}; | |
| 1069 | + $scope.user2 = {}; | |
| 1070 | + $scope.result; | |
| 1071 | + $scope.compare = function() { | |
| 1072 | + $scope.result = angular.equals($scope.user1, $scope.user2); | |
| 1073 | + }; | |
| 1074 | + }]); | |
| 1075 | + </file> | |
| 1076 | + </example> | |
| 1077 | + */ | |
| 1078 | +function equals(o1, o2) { | |
| 1079 | + if (o1 === o2) return true; | |
| 1080 | + if (o1 === null || o2 === null) return false; | |
| 1081 | + if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN | |
| 1082 | + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; | |
| 1083 | + if (t1 == t2 && t1 == 'object') { | |
| 1084 | + if (isArray(o1)) { | |
| 1085 | + if (!isArray(o2)) return false; | |
| 1086 | + if ((length = o1.length) == o2.length) { | |
| 1087 | + for (key = 0; key < length; key++) { | |
| 1088 | + if (!equals(o1[key], o2[key])) return false; | |
| 1089 | + } | |
| 1090 | + return true; | |
| 1091 | + } | |
| 1092 | + } else if (isDate(o1)) { | |
| 1093 | + if (!isDate(o2)) return false; | |
| 1094 | + return equals(o1.getTime(), o2.getTime()); | |
| 1095 | + } else if (isRegExp(o1)) { | |
| 1096 | + if (!isRegExp(o2)) return false; | |
| 1097 | + return o1.toString() == o2.toString(); | |
| 1098 | + } else { | |
| 1099 | + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || | |
| 1100 | + isArray(o2) || isDate(o2) || isRegExp(o2)) return false; | |
| 1101 | + keySet = createMap(); | |
| 1102 | + for (key in o1) { | |
| 1103 | + if (key.charAt(0) === '$' || isFunction(o1[key])) continue; | |
| 1104 | + if (!equals(o1[key], o2[key])) return false; | |
| 1105 | + keySet[key] = true; | |
| 1106 | + } | |
| 1107 | + for (key in o2) { | |
| 1108 | + if (!(key in keySet) && | |
| 1109 | + key.charAt(0) !== '$' && | |
| 1110 | + isDefined(o2[key]) && | |
| 1111 | + !isFunction(o2[key])) return false; | |
| 1112 | + } | |
| 1113 | + return true; | |
| 1114 | + } | |
| 1115 | + } | |
| 1116 | + return false; | |
| 1117 | +} | |
| 1118 | + | |
| 1119 | +var csp = function() { | |
| 1120 | + if (!isDefined(csp.rules)) { | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + var ngCspElement = (window.document.querySelector('[ng-csp]') || | |
| 1124 | + window.document.querySelector('[data-ng-csp]')); | |
| 1125 | + | |
| 1126 | + if (ngCspElement) { | |
| 1127 | + var ngCspAttribute = ngCspElement.getAttribute('ng-csp') || | |
| 1128 | + ngCspElement.getAttribute('data-ng-csp'); | |
| 1129 | + csp.rules = { | |
| 1130 | + noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1), | |
| 1131 | + noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1) | |
| 1132 | + }; | |
| 1133 | + } else { | |
| 1134 | + csp.rules = { | |
| 1135 | + noUnsafeEval: noUnsafeEval(), | |
| 1136 | + noInlineStyle: false | |
| 1137 | + }; | |
| 1138 | + } | |
| 1139 | + } | |
| 1140 | + | |
| 1141 | + return csp.rules; | |
| 1142 | + | |
| 1143 | + function noUnsafeEval() { | |
| 1144 | + try { | |
| 1145 | + /* jshint -W031, -W054 */ | |
| 1146 | + new Function(''); | |
| 1147 | + /* jshint +W031, +W054 */ | |
| 1148 | + return false; | |
| 1149 | + } catch (e) { | |
| 1150 | + return true; | |
| 1151 | + } | |
| 1152 | + } | |
| 1153 | +}; | |
| 1154 | + | |
| 1155 | +/** | |
| 1156 | + * @ngdoc directive | |
| 1157 | + * @module ng | |
| 1158 | + * @name ngJq | |
| 1159 | + * | |
| 1160 | + * @element ANY | |
| 1161 | + * @param {string=} ngJq the name of the library available under `window` | |
| 1162 | + * to be used for angular.element | |
| 1163 | + * @description | |
| 1164 | + * Use this directive to force the angular.element library. This should be | |
| 1165 | + * used to force either jqLite by leaving ng-jq blank or setting the name of | |
| 1166 | + * the jquery variable under window (eg. jQuery). | |
| 1167 | + * | |
| 1168 | + * Since angular looks for this directive when it is loaded (doesn't wait for the | |
| 1169 | + * DOMContentLoaded event), it must be placed on an element that comes before the script | |
| 1170 | + * which loads angular. Also, only the first instance of `ng-jq` will be used and all | |
| 1171 | + * others ignored. | |
| 1172 | + * | |
| 1173 | + * @example | |
| 1174 | + * This example shows how to force jqLite using the `ngJq` directive to the `html` tag. | |
| 1175 | + ```html | |
| 1176 | + <!doctype html> | |
| 1177 | + <html ng-app ng-jq> | |
| 1178 | + ... | |
| 1179 | + ... | |
| 1180 | + </html> | |
| 1181 | + ``` | |
| 1182 | + * @example | |
| 1183 | + * This example shows how to use a jQuery based library of a different name. | |
| 1184 | + * The library name must be available at the top most 'window'. | |
| 1185 | + ```html | |
| 1186 | + <!doctype html> | |
| 1187 | + <html ng-app ng-jq="jQueryLib"> | |
| 1188 | + ... | |
| 1189 | + ... | |
| 1190 | + </html> | |
| 1191 | + ``` | |
| 1192 | + */ | |
| 1193 | +var jq = function() { | |
| 1194 | + if (isDefined(jq.name_)) return jq.name_; | |
| 1195 | + var el; | |
| 1196 | + var i, ii = ngAttrPrefixes.length, prefix, name; | |
| 1197 | + for (i = 0; i < ii; ++i) { | |
| 1198 | + prefix = ngAttrPrefixes[i]; | |
| 1199 | + if (el = window.document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { | |
| 1200 | + name = el.getAttribute(prefix + 'jq'); | |
| 1201 | + break; | |
| 1202 | + } | |
| 1203 | + } | |
| 1204 | + | |
| 1205 | + return (jq.name_ = name); | |
| 1206 | +}; | |
| 1207 | + | |
| 1208 | +function concat(array1, array2, index) { | |
| 1209 | + return array1.concat(slice.call(array2, index)); | |
| 1210 | +} | |
| 1211 | + | |
| 1212 | +function sliceArgs(args, startIndex) { | |
| 1213 | + return slice.call(args, startIndex || 0); | |
| 1214 | +} | |
| 1215 | + | |
| 1216 | + | |
| 1217 | +/* jshint -W101 */ | |
| 1218 | +/** | |
| 1219 | + * @ngdoc function | |
| 1220 | + * @name angular.bind | |
| 1221 | + * @module ng | |
| 1222 | + * @kind function | |
| 1223 | + * | |
| 1224 | + * @description | |
| 1225 | + * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for | |
| 1226 | + * `fn`). You can supply optional `args` that are prebound to the function. This feature is also | |
| 1227 | + * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as | |
| 1228 | + * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). | |
| 1229 | + * | |
| 1230 | + * @param {Object} self Context which `fn` should be evaluated in. | |
| 1231 | + * @param {function()} fn Function to be bound. | |
| 1232 | + * @param {...*} args Optional arguments to be prebound to the `fn` function call. | |
| 1233 | + * @returns {function()} Function that wraps the `fn` with all the specified bindings. | |
| 1234 | + */ | |
| 1235 | +/* jshint +W101 */ | |
| 1236 | +function bind(self, fn) { | |
| 1237 | + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; | |
| 1238 | + if (isFunction(fn) && !(fn instanceof RegExp)) { | |
| 1239 | + return curryArgs.length | |
| 1240 | + ? function() { | |
| 1241 | + return arguments.length | |
| 1242 | + ? fn.apply(self, concat(curryArgs, arguments, 0)) | |
| 1243 | + : fn.apply(self, curryArgs); | |
| 1244 | + } | |
| 1245 | + : function() { | |
| 1246 | + return arguments.length | |
| 1247 | + ? fn.apply(self, arguments) | |
| 1248 | + : fn.call(self); | |
| 1249 | + }; | |
| 1250 | + } else { | |
| 1251 | + // In IE, native methods are not functions so they cannot be bound (note: they don't need to be). | |
| 1252 | + return fn; | |
| 1253 | + } | |
| 1254 | +} | |
| 1255 | + | |
| 1256 | + | |
| 1257 | +function toJsonReplacer(key, value) { | |
| 1258 | + var val = value; | |
| 1259 | + | |
| 1260 | + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { | |
| 1261 | + val = undefined; | |
| 1262 | + } else if (isWindow(value)) { | |
| 1263 | + val = '$WINDOW'; | |
| 1264 | + } else if (value && window.document === value) { | |
| 1265 | + val = '$DOCUMENT'; | |
| 1266 | + } else if (isScope(value)) { | |
| 1267 | + val = '$SCOPE'; | |
| 1268 | + } | |
| 1269 | + | |
| 1270 | + return val; | |
| 1271 | +} | |
| 1272 | + | |
| 1273 | + | |
| 1274 | +/** | |
| 1275 | + * @ngdoc function | |
| 1276 | + * @name angular.toJson | |
| 1277 | + * @module ng | |
| 1278 | + * @kind function | |
| 1279 | + * | |
| 1280 | + * @description | |
| 1281 | + * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be | |
| 1282 | + * stripped since angular uses this notation internally. | |
| 1283 | + * | |
| 1284 | + * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. | |
| 1285 | + * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. | |
| 1286 | + * If set to an integer, the JSON output will contain that many spaces per indentation. | |
| 1287 | + * @returns {string|undefined} JSON-ified string representing `obj`. | |
| 1288 | + * @knownIssue | |
| 1289 | + * | |
| 1290 | + * The Safari browser throws a `RangeError` instead of returning `null` when it tries to stringify a `Date` | |
| 1291 | + * object with an invalid date value. The only reliable way to prevent this is to monkeypatch the | |
| 1292 | + * `Date.prototype.toJSON` method as follows: | |
| 1293 | + * | |
| 1294 | + * ``` | |
| 1295 | + * var _DatetoJSON = Date.prototype.toJSON; | |
| 1296 | + * Date.prototype.toJSON = function() { | |
| 1297 | + * try { | |
| 1298 | + * return _DatetoJSON.call(this); | |
| 1299 | + * } catch(e) { | |
| 1300 | + * if (e instanceof RangeError) { | |
| 1301 | + * return null; | |
| 1302 | + * } | |
| 1303 | + * throw e; | |
| 1304 | + * } | |
| 1305 | + * }; | |
| 1306 | + * ``` | |
| 1307 | + * | |
| 1308 | + * See https://github.com/angular/angular.js/pull/14221 for more information. | |
| 1309 | + */ | |
| 1310 | +function toJson(obj, pretty) { | |
| 1311 | + if (isUndefined(obj)) return undefined; | |
| 1312 | + if (!isNumber(pretty)) { | |
| 1313 | + pretty = pretty ? 2 : null; | |
| 1314 | + } | |
| 1315 | + return JSON.stringify(obj, toJsonReplacer, pretty); | |
| 1316 | +} | |
| 1317 | + | |
| 1318 | + | |
| 1319 | +/** | |
| 1320 | + * @ngdoc function | |
| 1321 | + * @name angular.fromJson | |
| 1322 | + * @module ng | |
| 1323 | + * @kind function | |
| 1324 | + * | |
| 1325 | + * @description | |
| 1326 | + * Deserializes a JSON string. | |
| 1327 | + * | |
| 1328 | + * @param {string} json JSON string to deserialize. | |
| 1329 | + * @returns {Object|Array|string|number} Deserialized JSON string. | |
| 1330 | + */ | |
| 1331 | +function fromJson(json) { | |
| 1332 | + return isString(json) | |
| 1333 | + ? JSON.parse(json) | |
| 1334 | + : json; | |
| 1335 | +} | |
| 1336 | + | |
| 1337 | + | |
| 1338 | +var ALL_COLONS = /:/g; | |
| 1339 | +function timezoneToOffset(timezone, fallback) { | |
| 1340 | + // IE/Edge do not "understand" colon (`:`) in timezone | |
| 1341 | + timezone = timezone.replace(ALL_COLONS, ''); | |
| 1342 | + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; | |
| 1343 | + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; | |
| 1344 | +} | |
| 1345 | + | |
| 1346 | + | |
| 1347 | +function addDateMinutes(date, minutes) { | |
| 1348 | + date = new Date(date.getTime()); | |
| 1349 | + date.setMinutes(date.getMinutes() + minutes); | |
| 1350 | + return date; | |
| 1351 | +} | |
| 1352 | + | |
| 1353 | + | |
| 1354 | +function convertTimezoneToLocal(date, timezone, reverse) { | |
| 1355 | + reverse = reverse ? -1 : 1; | |
| 1356 | + var dateTimezoneOffset = date.getTimezoneOffset(); | |
| 1357 | + var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); | |
| 1358 | + return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset)); | |
| 1359 | +} | |
| 1360 | + | |
| 1361 | + | |
| 1362 | +/** | |
| 1363 | + * @returns {string} Returns the string representation of the element. | |
| 1364 | + */ | |
| 1365 | +function startingTag(element) { | |
| 1366 | + element = jqLite(element).clone(); | |
| 1367 | + try { | |
| 1368 | + // turns out IE does not let you set .html() on elements which | |
| 1369 | + // are not allowed to have children. So we just ignore it. | |
| 1370 | + element.empty(); | |
| 1371 | + } catch (e) {} | |
| 1372 | + var elemHtml = jqLite('<div>').append(element).html(); | |
| 1373 | + try { | |
| 1374 | + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : | |
| 1375 | + elemHtml. | |
| 1376 | + match(/^(<[^>]+>)/)[1]. | |
| 1377 | + replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);}); | |
| 1378 | + } catch (e) { | |
| 1379 | + return lowercase(elemHtml); | |
| 1380 | + } | |
| 1381 | + | |
| 1382 | +} | |
| 1383 | + | |
| 1384 | + | |
| 1385 | +///////////////////////////////////////////////// | |
| 1386 | + | |
| 1387 | +/** | |
| 1388 | + * Tries to decode the URI component without throwing an exception. | |
| 1389 | + * | |
| 1390 | + * @private | |
| 1391 | + * @param str value potential URI component to check. | |
| 1392 | + * @returns {boolean} True if `value` can be decoded | |
| 1393 | + * with the decodeURIComponent function. | |
| 1394 | + */ | |
| 1395 | +function tryDecodeURIComponent(value) { | |
| 1396 | + try { | |
| 1397 | + return decodeURIComponent(value); | |
| 1398 | + } catch (e) { | |
| 1399 | + // Ignore any invalid uri component. | |
| 1400 | + } | |
| 1401 | +} | |
| 1402 | + | |
| 1403 | + | |
| 1404 | +/** | |
| 1405 | + * Parses an escaped url query string into key-value pairs. | |
| 1406 | + * @returns {Object.<string,boolean|Array>} | |
| 1407 | + */ | |
| 1408 | +function parseKeyValue(/**string*/keyValue) { | |
| 1409 | + var obj = {}; | |
| 1410 | + forEach((keyValue || "").split('&'), function(keyValue) { | |
| 1411 | + var splitPoint, key, val; | |
| 1412 | + if (keyValue) { | |
| 1413 | + key = keyValue = keyValue.replace(/\+/g,'%20'); | |
| 1414 | + splitPoint = keyValue.indexOf('='); | |
| 1415 | + if (splitPoint !== -1) { | |
| 1416 | + key = keyValue.substring(0, splitPoint); | |
| 1417 | + val = keyValue.substring(splitPoint + 1); | |
| 1418 | + } | |
| 1419 | + key = tryDecodeURIComponent(key); | |
| 1420 | + if (isDefined(key)) { | |
| 1421 | + val = isDefined(val) ? tryDecodeURIComponent(val) : true; | |
| 1422 | + if (!hasOwnProperty.call(obj, key)) { | |
| 1423 | + obj[key] = val; | |
| 1424 | + } else if (isArray(obj[key])) { | |
| 1425 | + obj[key].push(val); | |
| 1426 | + } else { | |
| 1427 | + obj[key] = [obj[key],val]; | |
| 1428 | + } | |
| 1429 | + } | |
| 1430 | + } | |
| 1431 | + }); | |
| 1432 | + return obj; | |
| 1433 | +} | |
| 1434 | + | |
| 1435 | +function toKeyValue(obj) { | |
| 1436 | + var parts = []; | |
| 1437 | + forEach(obj, function(value, key) { | |
| 1438 | + if (isArray(value)) { | |
| 1439 | + forEach(value, function(arrayValue) { | |
| 1440 | + parts.push(encodeUriQuery(key, true) + | |
| 1441 | + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); | |
| 1442 | + }); | |
| 1443 | + } else { | |
| 1444 | + parts.push(encodeUriQuery(key, true) + | |
| 1445 | + (value === true ? '' : '=' + encodeUriQuery(value, true))); | |
| 1446 | + } | |
| 1447 | + }); | |
| 1448 | + return parts.length ? parts.join('&') : ''; | |
| 1449 | +} | |
| 1450 | + | |
| 1451 | + | |
| 1452 | +/** | |
| 1453 | + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow | |
| 1454 | + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path | |
| 1455 | + * segments: | |
| 1456 | + * segment = *pchar | |
| 1457 | + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" | |
| 1458 | + * pct-encoded = "%" HEXDIG HEXDIG | |
| 1459 | + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" | |
| 1460 | + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | |
| 1461 | + * / "*" / "+" / "," / ";" / "=" | |
| 1462 | + */ | |
| 1463 | +function encodeUriSegment(val) { | |
| 1464 | + return encodeUriQuery(val, true). | |
| 1465 | + replace(/%26/gi, '&'). | |
| 1466 | + replace(/%3D/gi, '='). | |
| 1467 | + replace(/%2B/gi, '+'); | |
| 1468 | +} | |
| 1469 | + | |
| 1470 | + | |
| 1471 | +/** | |
| 1472 | + * This method is intended for encoding *key* or *value* parts of query component. We need a custom | |
| 1473 | + * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be | |
| 1474 | + * encoded per http://tools.ietf.org/html/rfc3986: | |
| 1475 | + * query = *( pchar / "/" / "?" ) | |
| 1476 | + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" | |
| 1477 | + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" | |
| 1478 | + * pct-encoded = "%" HEXDIG HEXDIG | |
| 1479 | + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | |
| 1480 | + * / "*" / "+" / "," / ";" / "=" | |
| 1481 | + */ | |
| 1482 | +function encodeUriQuery(val, pctEncodeSpaces) { | |
| 1483 | + return encodeURIComponent(val). | |
| 1484 | + replace(/%40/gi, '@'). | |
| 1485 | + replace(/%3A/gi, ':'). | |
| 1486 | + replace(/%24/g, '$'). | |
| 1487 | + replace(/%2C/gi, ','). | |
| 1488 | + replace(/%3B/gi, ';'). | |
| 1489 | + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); | |
| 1490 | +} | |
| 1491 | + | |
| 1492 | +var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; | |
| 1493 | + | |
| 1494 | +function getNgAttribute(element, ngAttr) { | |
| 1495 | + var attr, i, ii = ngAttrPrefixes.length; | |
| 1496 | + for (i = 0; i < ii; ++i) { | |
| 1497 | + attr = ngAttrPrefixes[i] + ngAttr; | |
| 1498 | + if (isString(attr = element.getAttribute(attr))) { | |
| 1499 | + return attr; | |
| 1500 | + } | |
| 1501 | + } | |
| 1502 | + return null; | |
| 1503 | +} | |
| 1504 | + | |
| 1505 | +/** | |
| 1506 | + * @ngdoc directive | |
| 1507 | + * @name ngApp | |
| 1508 | + * @module ng | |
| 1509 | + * | |
| 1510 | + * @element ANY | |
| 1511 | + * @param {angular.Module} ngApp an optional application | |
| 1512 | + * {@link angular.module module} name to load. | |
| 1513 | + * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be | |
| 1514 | + * created in "strict-di" mode. This means that the application will fail to invoke functions which | |
| 1515 | + * do not use explicit function annotation (and are thus unsuitable for minification), as described | |
| 1516 | + * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in | |
| 1517 | + * tracking down the root of these bugs. | |
| 1518 | + * | |
| 1519 | + * @description | |
| 1520 | + * | |
| 1521 | + * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive | |
| 1522 | + * designates the **root element** of the application and is typically placed near the root element | |
| 1523 | + * of the page - e.g. on the `<body>` or `<html>` tags. | |
| 1524 | + * | |
| 1525 | + * There are a few things to keep in mind when using `ngApp`: | |
| 1526 | + * - only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` | |
| 1527 | + * found in the document will be used to define the root element to auto-bootstrap as an | |
| 1528 | + * application. To run multiple applications in an HTML document you must manually bootstrap them using | |
| 1529 | + * {@link angular.bootstrap} instead. | |
| 1530 | + * - AngularJS applications cannot be nested within each other. | |
| 1531 | + * - Do not use a directive that uses {@link ng.$compile#transclusion transclusion} on the same element as `ngApp`. | |
| 1532 | + * This includes directives such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and | |
| 1533 | + * {@link ngRoute.ngView `ngView`}. | |
| 1534 | + * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector}, | |
| 1535 | + * causing animations to stop working and making the injector inaccessible from outside the app. | |
| 1536 | + * | |
| 1537 | + * You can specify an **AngularJS module** to be used as the root module for the application. This | |
| 1538 | + * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It | |
| 1539 | + * should contain the application code needed or have dependencies on other modules that will | |
| 1540 | + * contain the code. See {@link angular.module} for more information. | |
| 1541 | + * | |
| 1542 | + * In the example below if the `ngApp` directive were not placed on the `html` element then the | |
| 1543 | + * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` | |
| 1544 | + * would not be resolved to `3`. | |
| 1545 | + * | |
| 1546 | + * `ngApp` is the easiest, and most common way to bootstrap an application. | |
| 1547 | + * | |
| 1548 | + <example module="ngAppDemo"> | |
| 1549 | + <file name="index.html"> | |
| 1550 | + <div ng-controller="ngAppDemoController"> | |
| 1551 | + I can add: {{a}} + {{b}} = {{ a+b }} | |
| 1552 | + </div> | |
| 1553 | + </file> | |
| 1554 | + <file name="script.js"> | |
| 1555 | + angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { | |
| 1556 | + $scope.a = 1; | |
| 1557 | + $scope.b = 2; | |
| 1558 | + }); | |
| 1559 | + </file> | |
| 1560 | + </example> | |
| 1561 | + * | |
| 1562 | + * Using `ngStrictDi`, you would see something like this: | |
| 1563 | + * | |
| 1564 | + <example ng-app-included="true"> | |
| 1565 | + <file name="index.html"> | |
| 1566 | + <div ng-app="ngAppStrictDemo" ng-strict-di> | |
| 1567 | + <div ng-controller="GoodController1"> | |
| 1568 | + I can add: {{a}} + {{b}} = {{ a+b }} | |
| 1569 | + | |
| 1570 | + <p>This renders because the controller does not fail to | |
| 1571 | + instantiate, by using explicit annotation style (see | |
| 1572 | + script.js for details) | |
| 1573 | + </p> | |
| 1574 | + </div> | |
| 1575 | + | |
| 1576 | + <div ng-controller="GoodController2"> | |
| 1577 | + Name: <input ng-model="name"><br /> | |
| 1578 | + Hello, {{name}}! | |
| 1579 | + | |
| 1580 | + <p>This renders because the controller does not fail to | |
| 1581 | + instantiate, by using explicit annotation style | |
| 1582 | + (see script.js for details) | |
| 1583 | + </p> | |
| 1584 | + </div> | |
| 1585 | + | |
| 1586 | + <div ng-controller="BadController"> | |
| 1587 | + I can add: {{a}} + {{b}} = {{ a+b }} | |
| 1588 | + | |
| 1589 | + <p>The controller could not be instantiated, due to relying | |
| 1590 | + on automatic function annotations (which are disabled in | |
| 1591 | + strict mode). As such, the content of this section is not | |
| 1592 | + interpolated, and there should be an error in your web console. | |
| 1593 | + </p> | |
| 1594 | + </div> | |
| 1595 | + </div> | |
| 1596 | + </file> | |
| 1597 | + <file name="script.js"> | |
| 1598 | + angular.module('ngAppStrictDemo', []) | |
| 1599 | + // BadController will fail to instantiate, due to relying on automatic function annotation, | |
| 1600 | + // rather than an explicit annotation | |
| 1601 | + .controller('BadController', function($scope) { | |
| 1602 | + $scope.a = 1; | |
| 1603 | + $scope.b = 2; | |
| 1604 | + }) | |
| 1605 | + // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated, | |
| 1606 | + // due to using explicit annotations using the array style and $inject property, respectively. | |
| 1607 | + .controller('GoodController1', ['$scope', function($scope) { | |
| 1608 | + $scope.a = 1; | |
| 1609 | + $scope.b = 2; | |
| 1610 | + }]) | |
| 1611 | + .controller('GoodController2', GoodController2); | |
| 1612 | + function GoodController2($scope) { | |
| 1613 | + $scope.name = "World"; | |
| 1614 | + } | |
| 1615 | + GoodController2.$inject = ['$scope']; | |
| 1616 | + </file> | |
| 1617 | + <file name="style.css"> | |
| 1618 | + div[ng-controller] { | |
| 1619 | + margin-bottom: 1em; | |
| 1620 | + -webkit-border-radius: 4px; | |
| 1621 | + border-radius: 4px; | |
| 1622 | + border: 1px solid; | |
| 1623 | + padding: .5em; | |
| 1624 | + } | |
| 1625 | + div[ng-controller^=Good] { | |
| 1626 | + border-color: #d6e9c6; | |
| 1627 | + background-color: #dff0d8; | |
| 1628 | + color: #3c763d; | |
| 1629 | + } | |
| 1630 | + div[ng-controller^=Bad] { | |
| 1631 | + border-color: #ebccd1; | |
| 1632 | + background-color: #f2dede; | |
| 1633 | + color: #a94442; | |
| 1634 | + margin-bottom: 0; | |
| 1635 | + } | |
| 1636 | + </file> | |
| 1637 | + </example> | |
| 1638 | + */ | |
| 1639 | +function angularInit(element, bootstrap) { | |
| 1640 | + var appElement, | |
| 1641 | + module, | |
| 1642 | + config = {}; | |
| 1643 | + | |
| 1644 | + // The element `element` has priority over any other element. | |
| 1645 | + forEach(ngAttrPrefixes, function(prefix) { | |
| 1646 | + var name = prefix + 'app'; | |
| 1647 | + | |
| 1648 | + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { | |
| 1649 | + appElement = element; | |
| 1650 | + module = element.getAttribute(name); | |
| 1651 | + } | |
| 1652 | + }); | |
| 1653 | + forEach(ngAttrPrefixes, function(prefix) { | |
| 1654 | + var name = prefix + 'app'; | |
| 1655 | + var candidate; | |
| 1656 | + | |
| 1657 | + if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { | |
| 1658 | + appElement = candidate; | |
| 1659 | + module = candidate.getAttribute(name); | |
| 1660 | + } | |
| 1661 | + }); | |
| 1662 | + if (appElement) { | |
| 1663 | + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; | |
| 1664 | + bootstrap(appElement, module ? [module] : [], config); | |
| 1665 | + } | |
| 1666 | +} | |
| 1667 | + | |
| 1668 | +/** | |
| 1669 | + * @ngdoc function | |
| 1670 | + * @name angular.bootstrap | |
| 1671 | + * @module ng | |
| 1672 | + * @description | |
| 1673 | + * Use this function to manually start up angular application. | |
| 1674 | + * | |
| 1675 | + * For more information, see the {@link guide/bootstrap Bootstrap guide}. | |
| 1676 | + * | |
| 1677 | + * Angular will detect if it has been loaded into the browser more than once and only allow the | |
| 1678 | + * first loaded script to be bootstrapped and will report a warning to the browser console for | |
| 1679 | + * each of the subsequent scripts. This prevents strange results in applications, where otherwise | |
| 1680 | + * multiple instances of Angular try to work on the DOM. | |
| 1681 | + * | |
| 1682 | + * <div class="alert alert-warning"> | |
| 1683 | + * **Note:** Protractor based end-to-end tests cannot use this function to bootstrap manually. | |
| 1684 | + * They must use {@link ng.directive:ngApp ngApp}. | |
| 1685 | + * </div> | |
| 1686 | + * | |
| 1687 | + * <div class="alert alert-warning"> | |
| 1688 | + * **Note:** Do not bootstrap the app on an element with a directive that uses {@link ng.$compile#transclusion transclusion}, | |
| 1689 | + * such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and {@link ngRoute.ngView `ngView`}. | |
| 1690 | + * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector}, | |
| 1691 | + * causing animations to stop working and making the injector inaccessible from outside the app. | |
| 1692 | + * </div> | |
| 1693 | + * | |
| 1694 | + * ```html | |
| 1695 | + * <!doctype html> | |
| 1696 | + * <html> | |
| 1697 | + * <body> | |
| 1698 | + * <div ng-controller="WelcomeController"> | |
| 1699 | + * {{greeting}} | |
| 1700 | + * </div> | |
| 1701 | + * | |
| 1702 | + * <script src="angular.js"></script> | |
| 1703 | + * <script> | |
| 1704 | + * var app = angular.module('demo', []) | |
| 1705 | + * .controller('WelcomeController', function($scope) { | |
| 1706 | + * $scope.greeting = 'Welcome!'; | |
| 1707 | + * }); | |
| 1708 | + * angular.bootstrap(document, ['demo']); | |
| 1709 | + * </script> | |
| 1710 | + * </body> | |
| 1711 | + * </html> | |
| 1712 | + * ``` | |
| 1713 | + * | |
| 1714 | + * @param {DOMElement} element DOM element which is the root of angular application. | |
| 1715 | + * @param {Array<String|Function|Array>=} modules an array of modules to load into the application. | |
| 1716 | + * Each item in the array should be the name of a predefined module or a (DI annotated) | |
| 1717 | + * function that will be invoked by the injector as a `config` block. | |
| 1718 | + * See: {@link angular.module modules} | |
| 1719 | + * @param {Object=} config an object for defining configuration options for the application. The | |
| 1720 | + * following keys are supported: | |
| 1721 | + * | |
| 1722 | + * * `strictDi` - disable automatic function annotation for the application. This is meant to | |
| 1723 | + * assist in finding bugs which break minified code. Defaults to `false`. | |
| 1724 | + * | |
| 1725 | + * @returns {auto.$injector} Returns the newly created injector for this app. | |
| 1726 | + */ | |
| 1727 | +function bootstrap(element, modules, config) { | |
| 1728 | + if (!isObject(config)) config = {}; | |
| 1729 | + var defaultConfig = { | |
| 1730 | + strictDi: false | |
| 1731 | + }; | |
| 1732 | + config = extend(defaultConfig, config); | |
| 1733 | + var doBootstrap = function() { | |
| 1734 | + element = jqLite(element); | |
| 1735 | + | |
| 1736 | + if (element.injector()) { | |
| 1737 | + var tag = (element[0] === window.document) ? 'document' : startingTag(element); | |
| 1738 | + // Encode angle brackets to prevent input from being sanitized to empty string #8683. | |
| 1739 | + throw ngMinErr( | |
| 1740 | + 'btstrpd', | |
| 1741 | + "App already bootstrapped with this element '{0}'", | |
| 1742 | + tag.replace(/</,'<').replace(/>/,'>')); | |
| 1743 | + } | |
| 1744 | + | |
| 1745 | + modules = modules || []; | |
| 1746 | + modules.unshift(['$provide', function($provide) { | |
| 1747 | + $provide.value('$rootElement', element); | |
| 1748 | + }]); | |
| 1749 | + | |
| 1750 | + if (config.debugInfoEnabled) { | |
| 1751 | + // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`. | |
| 1752 | + modules.push(['$compileProvider', function($compileProvider) { | |
| 1753 | + $compileProvider.debugInfoEnabled(true); | |
| 1754 | + }]); | |
| 1755 | + } | |
| 1756 | + | |
| 1757 | + modules.unshift('ng'); | |
| 1758 | + var injector = createInjector(modules, config.strictDi); | |
| 1759 | + injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', | |
| 1760 | + function bootstrapApply(scope, element, compile, injector) { | |
| 1761 | + scope.$apply(function() { | |
| 1762 | + element.data('$injector', injector); | |
| 1763 | + compile(element)(scope); | |
| 1764 | + }); | |
| 1765 | + }] | |
| 1766 | + ); | |
| 1767 | + return injector; | |
| 1768 | + }; | |
| 1769 | + | |
| 1770 | + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; | |
| 1771 | + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; | |
| 1772 | + | |
| 1773 | + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { | |
| 1774 | + config.debugInfoEnabled = true; | |
| 1775 | + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ''); | |
| 1776 | + } | |
| 1777 | + | |
| 1778 | + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { | |
| 1779 | + return doBootstrap(); | |
| 1780 | + } | |
| 1781 | + | |
| 1782 | + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); | |
| 1783 | + angular.resumeBootstrap = function(extraModules) { | |
| 1784 | + forEach(extraModules, function(module) { | |
| 1785 | + modules.push(module); | |
| 1786 | + }); | |
| 1787 | + return doBootstrap(); | |
| 1788 | + }; | |
| 1789 | + | |
| 1790 | + if (isFunction(angular.resumeDeferredBootstrap)) { | |
| 1791 | + angular.resumeDeferredBootstrap(); | |
| 1792 | + } | |
| 1793 | +} | |
| 1794 | + | |
| 1795 | +/** | |
| 1796 | + * @ngdoc function | |
| 1797 | + * @name angular.reloadWithDebugInfo | |
| 1798 | + * @module ng | |
| 1799 | + * @description | |
| 1800 | + * Use this function to reload the current application with debug information turned on. | |
| 1801 | + * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`. | |
| 1802 | + * | |
| 1803 | + * See {@link ng.$compileProvider#debugInfoEnabled} for more. | |
| 1804 | + */ | |
| 1805 | +function reloadWithDebugInfo() { | |
| 1806 | + window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name; | |
| 1807 | + window.location.reload(); | |
| 1808 | +} | |
| 1809 | + | |
| 1810 | +/** | |
| 1811 | + * @name angular.getTestability | |
| 1812 | + * @module ng | |
| 1813 | + * @description | |
| 1814 | + * Get the testability service for the instance of Angular on the given | |
| 1815 | + * element. | |
| 1816 | + * @param {DOMElement} element DOM element which is the root of angular application. | |
| 1817 | + */ | |
| 1818 | +function getTestability(rootElement) { | |
| 1819 | + var injector = angular.element(rootElement).injector(); | |
| 1820 | + if (!injector) { | |
| 1821 | + throw ngMinErr('test', | |
| 1822 | + 'no injector found for element argument to getTestability'); | |
| 1823 | + } | |
| 1824 | + return injector.get('$$testability'); | |
| 1825 | +} | |
| 1826 | + | |
| 1827 | +var SNAKE_CASE_REGEXP = /[A-Z]/g; | |
| 1828 | +function snake_case(name, separator) { | |
| 1829 | + separator = separator || '_'; | |
| 1830 | + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { | |
| 1831 | + return (pos ? separator : '') + letter.toLowerCase(); | |
| 1832 | + }); | |
| 1833 | +} | |
| 1834 | + | |
| 1835 | +var bindJQueryFired = false; | |
| 1836 | +function bindJQuery() { | |
| 1837 | + var originalCleanData; | |
| 1838 | + | |
| 1839 | + if (bindJQueryFired) { | |
| 1840 | + return; | |
| 1841 | + } | |
| 1842 | + | |
| 1843 | + // bind to jQuery if present; | |
| 1844 | + var jqName = jq(); | |
| 1845 | + jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present) | |
| 1846 | + !jqName ? undefined : // use jqLite | |
| 1847 | + window[jqName]; // use jQuery specified by `ngJq` | |
| 1848 | + | |
| 1849 | + // Use jQuery if it exists with proper functionality, otherwise default to us. | |
| 1850 | + // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. | |
| 1851 | + // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older | |
| 1852 | + // versions. It will not work for sure with jQuery <1.7, though. | |
| 1853 | + if (jQuery && jQuery.fn.on) { | |
| 1854 | + jqLite = jQuery; | |
| 1855 | + extend(jQuery.fn, { | |
| 1856 | + scope: JQLitePrototype.scope, | |
| 1857 | + isolateScope: JQLitePrototype.isolateScope, | |
| 1858 | + controller: JQLitePrototype.controller, | |
| 1859 | + injector: JQLitePrototype.injector, | |
| 1860 | + inheritedData: JQLitePrototype.inheritedData | |
| 1861 | + }); | |
| 1862 | + | |
| 1863 | + // All nodes removed from the DOM via various jQuery APIs like .remove() | |
| 1864 | + // are passed through jQuery.cleanData. Monkey-patch this method to fire | |
| 1865 | + // the $destroy event on all removed nodes. | |
| 1866 | + originalCleanData = jQuery.cleanData; | |
| 1867 | + jQuery.cleanData = function(elems) { | |
| 1868 | + var events; | |
| 1869 | + for (var i = 0, elem; (elem = elems[i]) != null; i++) { | |
| 1870 | + events = jQuery._data(elem, "events"); | |
| 1871 | + if (events && events.$destroy) { | |
| 1872 | + jQuery(elem).triggerHandler('$destroy'); | |
| 1873 | + } | |
| 1874 | + } | |
| 1875 | + originalCleanData(elems); | |
| 1876 | + }; | |
| 1877 | + } else { | |
| 1878 | + jqLite = JQLite; | |
| 1879 | + } | |
| 1880 | + | |
| 1881 | + angular.element = jqLite; | |
| 1882 | + | |
| 1883 | + // Prevent double-proxying. | |
| 1884 | + bindJQueryFired = true; | |
| 1885 | +} | |
| 1886 | + | |
| 1887 | +/** | |
| 1888 | + * throw error if the argument is falsy. | |
| 1889 | + */ | |
| 1890 | +function assertArg(arg, name, reason) { | |
| 1891 | + if (!arg) { | |
| 1892 | + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); | |
| 1893 | + } | |
| 1894 | + return arg; | |
| 1895 | +} | |
| 1896 | + | |
| 1897 | +function assertArgFn(arg, name, acceptArrayAnnotation) { | |
| 1898 | + if (acceptArrayAnnotation && isArray(arg)) { | |
| 1899 | + arg = arg[arg.length - 1]; | |
| 1900 | + } | |
| 1901 | + | |
| 1902 | + assertArg(isFunction(arg), name, 'not a function, got ' + | |
| 1903 | + (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg)); | |
| 1904 | + return arg; | |
| 1905 | +} | |
| 1906 | + | |
| 1907 | +/** | |
| 1908 | + * throw error if the name given is hasOwnProperty | |
| 1909 | + * @param {String} name the name to test | |
| 1910 | + * @param {String} context the context in which the name is used, such as module or directive | |
| 1911 | + */ | |
| 1912 | +function assertNotHasOwnProperty(name, context) { | |
| 1913 | + if (name === 'hasOwnProperty') { | |
| 1914 | + throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); | |
| 1915 | + } | |
| 1916 | +} | |
| 1917 | + | |
| 1918 | +/** | |
| 1919 | + * Return the value accessible from the object by path. Any undefined traversals are ignored | |
| 1920 | + * @param {Object} obj starting object | |
| 1921 | + * @param {String} path path to traverse | |
| 1922 | + * @param {boolean} [bindFnToScope=true] | |
| 1923 | + * @returns {Object} value as accessible by path | |
| 1924 | + */ | |
| 1925 | +//TODO(misko): this function needs to be removed | |
| 1926 | +function getter(obj, path, bindFnToScope) { | |
| 1927 | + if (!path) return obj; | |
| 1928 | + var keys = path.split('.'); | |
| 1929 | + var key; | |
| 1930 | + var lastInstance = obj; | |
| 1931 | + var len = keys.length; | |
| 1932 | + | |
| 1933 | + for (var i = 0; i < len; i++) { | |
| 1934 | + key = keys[i]; | |
| 1935 | + if (obj) { | |
| 1936 | + obj = (lastInstance = obj)[key]; | |
| 1937 | + } | |
| 1938 | + } | |
| 1939 | + if (!bindFnToScope && isFunction(obj)) { | |
| 1940 | + return bind(lastInstance, obj); | |
| 1941 | + } | |
| 1942 | + return obj; | |
| 1943 | +} | |
| 1944 | + | |
| 1945 | +/** | |
| 1946 | + * Return the DOM siblings between the first and last node in the given array. | |
| 1947 | + * @param {Array} array like object | |
| 1948 | + * @returns {Array} the inputted object or a jqLite collection containing the nodes | |
| 1949 | + */ | |
| 1950 | +function getBlockNodes(nodes) { | |
| 1951 | + // TODO(perf): update `nodes` instead of creating a new object? | |
| 1952 | + var node = nodes[0]; | |
| 1953 | + var endNode = nodes[nodes.length - 1]; | |
| 1954 | + var blockNodes; | |
| 1955 | + | |
| 1956 | + for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { | |
| 1957 | + if (blockNodes || nodes[i] !== node) { | |
| 1958 | + if (!blockNodes) { | |
| 1959 | + blockNodes = jqLite(slice.call(nodes, 0, i)); | |
| 1960 | + } | |
| 1961 | + blockNodes.push(node); | |
| 1962 | + } | |
| 1963 | + } | |
| 1964 | + | |
| 1965 | + return blockNodes || nodes; | |
| 1966 | +} | |
| 1967 | + | |
| 1968 | + | |
| 1969 | +/** | |
| 1970 | + * Creates a new object without a prototype. This object is useful for lookup without having to | |
| 1971 | + * guard against prototypically inherited properties via hasOwnProperty. | |
| 1972 | + * | |
| 1973 | + * Related micro-benchmarks: | |
| 1974 | + * - http://jsperf.com/object-create2 | |
| 1975 | + * - http://jsperf.com/proto-map-lookup/2 | |
| 1976 | + * - http://jsperf.com/for-in-vs-object-keys2 | |
| 1977 | + * | |
| 1978 | + * @returns {Object} | |
| 1979 | + */ | |
| 1980 | +function createMap() { | |
| 1981 | + return Object.create(null); | |
| 1982 | +} | |
| 1983 | + | |
| 1984 | +var NODE_TYPE_ELEMENT = 1; | |
| 1985 | +var NODE_TYPE_ATTRIBUTE = 2; | |
| 1986 | +var NODE_TYPE_TEXT = 3; | |
| 1987 | +var NODE_TYPE_COMMENT = 8; | |
| 1988 | +var NODE_TYPE_DOCUMENT = 9; | |
| 1989 | +var NODE_TYPE_DOCUMENT_FRAGMENT = 11; | |
| 1990 | + | |
| 1991 | +/** | |
| 1992 | + * @ngdoc type | |
| 1993 | + * @name angular.Module | |
| 1994 | + * @module ng | |
| 1995 | + * @description | |
| 1996 | + * | |
| 1997 | + * Interface for configuring angular {@link angular.module modules}. | |
| 1998 | + */ | |
| 1999 | + | |
| 2000 | +function setupModuleLoader(window) { | |
| 2001 | + | |
| 2002 | + var $injectorMinErr = minErr('$injector'); | |
| 2003 | + var ngMinErr = minErr('ng'); | |
| 2004 | + | |
| 2005 | + function ensure(obj, name, factory) { | |
| 2006 | + return obj[name] || (obj[name] = factory()); | |
| 2007 | + } | |
| 2008 | + | |
| 2009 | + var angular = ensure(window, 'angular', Object); | |
| 2010 | + | |
| 2011 | + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap | |
| 2012 | + angular.$$minErr = angular.$$minErr || minErr; | |
| 2013 | + | |
| 2014 | + return ensure(angular, 'module', function() { | |
| 2015 | + /** @type {Object.<string, angular.Module>} */ | |
| 2016 | + var modules = {}; | |
| 2017 | + | |
| 2018 | + /** | |
| 2019 | + * @ngdoc function | |
| 2020 | + * @name angular.module | |
| 2021 | + * @module ng | |
| 2022 | + * @description | |
| 2023 | + * | |
| 2024 | + * The `angular.module` is a global place for creating, registering and retrieving Angular | |
| 2025 | + * modules. | |
| 2026 | + * All modules (angular core or 3rd party) that should be available to an application must be | |
| 2027 | + * registered using this mechanism. | |
| 2028 | + * | |
| 2029 | + * Passing one argument retrieves an existing {@link angular.Module}, | |
| 2030 | + * whereas passing more than one argument creates a new {@link angular.Module} | |
| 2031 | + * | |
| 2032 | + * | |
| 2033 | + * # Module | |
| 2034 | + * | |
| 2035 | + * A module is a collection of services, directives, controllers, filters, and configuration information. | |
| 2036 | + * `angular.module` is used to configure the {@link auto.$injector $injector}. | |
| 2037 | + * | |
| 2038 | + * ```js | |
| 2039 | + * // Create a new module | |
| 2040 | + * var myModule = angular.module('myModule', []); | |
| 2041 | + * | |
| 2042 | + * // register a new service | |
| 2043 | + * myModule.value('appName', 'MyCoolApp'); | |
| 2044 | + * | |
| 2045 | + * // configure existing services inside initialization blocks. | |
| 2046 | + * myModule.config(['$locationProvider', function($locationProvider) { | |
| 2047 | + * // Configure existing providers | |
| 2048 | + * $locationProvider.hashPrefix('!'); | |
| 2049 | + * }]); | |
| 2050 | + * ``` | |
| 2051 | + * | |
| 2052 | + * Then you can create an injector and load your modules like this: | |
| 2053 | + * | |
| 2054 | + * ```js | |
| 2055 | + * var injector = angular.injector(['ng', 'myModule']) | |
| 2056 | + * ``` | |
| 2057 | + * | |
| 2058 | + * However it's more likely that you'll just use | |
| 2059 | + * {@link ng.directive:ngApp ngApp} or | |
| 2060 | + * {@link angular.bootstrap} to simplify this process for you. | |
| 2061 | + * | |
| 2062 | + * @param {!string} name The name of the module to create or retrieve. | |
| 2063 | + * @param {!Array.<string>=} requires If specified then new module is being created. If | |
| 2064 | + * unspecified then the module is being retrieved for further configuration. | |
| 2065 | + * @param {Function=} configFn Optional configuration function for the module. Same as | |
| 2066 | + * {@link angular.Module#config Module#config()}. | |
| 2067 | + * @returns {angular.Module} new module with the {@link angular.Module} api. | |
| 2068 | + */ | |
| 2069 | + return function module(name, requires, configFn) { | |
| 2070 | + var assertNotHasOwnProperty = function(name, context) { | |
| 2071 | + if (name === 'hasOwnProperty') { | |
| 2072 | + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); | |
| 2073 | + } | |
| 2074 | + }; | |
| 2075 | + | |
| 2076 | + assertNotHasOwnProperty(name, 'module'); | |
| 2077 | + if (requires && modules.hasOwnProperty(name)) { | |
| 2078 | + modules[name] = null; | |
| 2079 | + } | |
| 2080 | + return ensure(modules, name, function() { | |
| 2081 | + if (!requires) { | |
| 2082 | + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + | |
| 2083 | + "the module name or forgot to load it. If registering a module ensure that you " + | |
| 2084 | + "specify the dependencies as the second argument.", name); | |
| 2085 | + } | |
| 2086 | + | |
| 2087 | + /** @type {!Array.<Array.<*>>} */ | |
| 2088 | + var invokeQueue = []; | |
| 2089 | + | |
| 2090 | + /** @type {!Array.<Function>} */ | |
| 2091 | + var configBlocks = []; | |
| 2092 | + | |
| 2093 | + /** @type {!Array.<Function>} */ | |
| 2094 | + var runBlocks = []; | |
| 2095 | + | |
| 2096 | + var config = invokeLater('$injector', 'invoke', 'push', configBlocks); | |
| 2097 | + | |
| 2098 | + /** @type {angular.Module} */ | |
| 2099 | + var moduleInstance = { | |
| 2100 | + // Private state | |
| 2101 | + _invokeQueue: invokeQueue, | |
| 2102 | + _configBlocks: configBlocks, | |
| 2103 | + _runBlocks: runBlocks, | |
| 2104 | + | |
| 2105 | + /** | |
| 2106 | + * @ngdoc property | |
| 2107 | + * @name angular.Module#requires | |
| 2108 | + * @module ng | |
| 2109 | + * | |
| 2110 | + * @description | |
| 2111 | + * Holds the list of modules which the injector will load before the current module is | |
| 2112 | + * loaded. | |
| 2113 | + */ | |
| 2114 | + requires: requires, | |
| 2115 | + | |
| 2116 | + /** | |
| 2117 | + * @ngdoc property | |
| 2118 | + * @name angular.Module#name | |
| 2119 | + * @module ng | |
| 2120 | + * | |
| 2121 | + * @description | |
| 2122 | + * Name of the module. | |
| 2123 | + */ | |
| 2124 | + name: name, | |
| 2125 | + | |
| 2126 | + | |
| 2127 | + /** | |
| 2128 | + * @ngdoc method | |
| 2129 | + * @name angular.Module#provider | |
| 2130 | + * @module ng | |
| 2131 | + * @param {string} name service name | |
| 2132 | + * @param {Function} providerType Construction function for creating new instance of the | |
| 2133 | + * service. | |
| 2134 | + * @description | |
| 2135 | + * See {@link auto.$provide#provider $provide.provider()}. | |
| 2136 | + */ | |
| 2137 | + provider: invokeLaterAndSetModuleName('$provide', 'provider'), | |
| 2138 | + | |
| 2139 | + /** | |
| 2140 | + * @ngdoc method | |
| 2141 | + * @name angular.Module#factory | |
| 2142 | + * @module ng | |
| 2143 | + * @param {string} name service name | |
| 2144 | + * @param {Function} providerFunction Function for creating new instance of the service. | |
| 2145 | + * @description | |
| 2146 | + * See {@link auto.$provide#factory $provide.factory()}. | |
| 2147 | + */ | |
| 2148 | + factory: invokeLaterAndSetModuleName('$provide', 'factory'), | |
| 2149 | + | |
| 2150 | + /** | |
| 2151 | + * @ngdoc method | |
| 2152 | + * @name angular.Module#service | |
| 2153 | + * @module ng | |
| 2154 | + * @param {string} name service name | |
| 2155 | + * @param {Function} constructor A constructor function that will be instantiated. | |
| 2156 | + * @description | |
| 2157 | + * See {@link auto.$provide#service $provide.service()}. | |
| 2158 | + */ | |
| 2159 | + service: invokeLaterAndSetModuleName('$provide', 'service'), | |
| 2160 | + | |
| 2161 | + /** | |
| 2162 | + * @ngdoc method | |
| 2163 | + * @name angular.Module#value | |
| 2164 | + * @module ng | |
| 2165 | + * @param {string} name service name | |
| 2166 | + * @param {*} object Service instance object. | |
| 2167 | + * @description | |
| 2168 | + * See {@link auto.$provide#value $provide.value()}. | |
| 2169 | + */ | |
| 2170 | + value: invokeLater('$provide', 'value'), | |
| 2171 | + | |
| 2172 | + /** | |
| 2173 | + * @ngdoc method | |
| 2174 | + * @name angular.Module#constant | |
| 2175 | + * @module ng | |
| 2176 | + * @param {string} name constant name | |
| 2177 | + * @param {*} object Constant value. | |
| 2178 | + * @description | |
| 2179 | + * Because the constants are fixed, they get applied before other provide methods. | |
| 2180 | + * See {@link auto.$provide#constant $provide.constant()}. | |
| 2181 | + */ | |
| 2182 | + constant: invokeLater('$provide', 'constant', 'unshift'), | |
| 2183 | + | |
| 2184 | + /** | |
| 2185 | + * @ngdoc method | |
| 2186 | + * @name angular.Module#decorator | |
| 2187 | + * @module ng | |
| 2188 | + * @param {string} name The name of the service to decorate. | |
| 2189 | + * @param {Function} decorFn This function will be invoked when the service needs to be | |
| 2190 | + * instantiated and should return the decorated service instance. | |
| 2191 | + * @description | |
| 2192 | + * See {@link auto.$provide#decorator $provide.decorator()}. | |
| 2193 | + */ | |
| 2194 | + decorator: invokeLaterAndSetModuleName('$provide', 'decorator'), | |
| 2195 | + | |
| 2196 | + /** | |
| 2197 | + * @ngdoc method | |
| 2198 | + * @name angular.Module#animation | |
| 2199 | + * @module ng | |
| 2200 | + * @param {string} name animation name | |
| 2201 | + * @param {Function} animationFactory Factory function for creating new instance of an | |
| 2202 | + * animation. | |
| 2203 | + * @description | |
| 2204 | + * | |
| 2205 | + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. | |
| 2206 | + * | |
| 2207 | + * | |
| 2208 | + * Defines an animation hook that can be later used with | |
| 2209 | + * {@link $animate $animate} service and directives that use this service. | |
| 2210 | + * | |
| 2211 | + * ```js | |
| 2212 | + * module.animation('.animation-name', function($inject1, $inject2) { | |
| 2213 | + * return { | |
| 2214 | + * eventName : function(element, done) { | |
| 2215 | + * //code to run the animation | |
| 2216 | + * //once complete, then run done() | |
| 2217 | + * return function cancellationFunction(element) { | |
| 2218 | + * //code to cancel the animation | |
| 2219 | + * } | |
| 2220 | + * } | |
| 2221 | + * } | |
| 2222 | + * }) | |
| 2223 | + * ``` | |
| 2224 | + * | |
| 2225 | + * See {@link ng.$animateProvider#register $animateProvider.register()} and | |
| 2226 | + * {@link ngAnimate ngAnimate module} for more information. | |
| 2227 | + */ | |
| 2228 | + animation: invokeLaterAndSetModuleName('$animateProvider', 'register'), | |
| 2229 | + | |
| 2230 | + /** | |
| 2231 | + * @ngdoc method | |
| 2232 | + * @name angular.Module#filter | |
| 2233 | + * @module ng | |
| 2234 | + * @param {string} name Filter name - this must be a valid angular expression identifier | |
| 2235 | + * @param {Function} filterFactory Factory function for creating new instance of filter. | |
| 2236 | + * @description | |
| 2237 | + * See {@link ng.$filterProvider#register $filterProvider.register()}. | |
| 2238 | + * | |
| 2239 | + * <div class="alert alert-warning"> | |
| 2240 | + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. | |
| 2241 | + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace | |
| 2242 | + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores | |
| 2243 | + * (`myapp_subsection_filterx`). | |
| 2244 | + * </div> | |
| 2245 | + */ | |
| 2246 | + filter: invokeLaterAndSetModuleName('$filterProvider', 'register'), | |
| 2247 | + | |
| 2248 | + /** | |
| 2249 | + * @ngdoc method | |
| 2250 | + * @name angular.Module#controller | |
| 2251 | + * @module ng | |
| 2252 | + * @param {string|Object} name Controller name, or an object map of controllers where the | |
| 2253 | + * keys are the names and the values are the constructors. | |
| 2254 | + * @param {Function} constructor Controller constructor function. | |
| 2255 | + * @description | |
| 2256 | + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. | |
| 2257 | + */ | |
| 2258 | + controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'), | |
| 2259 | + | |
| 2260 | + /** | |
| 2261 | + * @ngdoc method | |
| 2262 | + * @name angular.Module#directive | |
| 2263 | + * @module ng | |
| 2264 | + * @param {string|Object} name Directive name, or an object map of directives where the | |
| 2265 | + * keys are the names and the values are the factories. | |
| 2266 | + * @param {Function} directiveFactory Factory function for creating new instance of | |
| 2267 | + * directives. | |
| 2268 | + * @description | |
| 2269 | + * See {@link ng.$compileProvider#directive $compileProvider.directive()}. | |
| 2270 | + */ | |
| 2271 | + directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'), | |
| 2272 | + | |
| 2273 | + /** | |
| 2274 | + * @ngdoc method | |
| 2275 | + * @name angular.Module#component | |
| 2276 | + * @module ng | |
| 2277 | + * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp) | |
| 2278 | + * @param {Object} options Component definition object (a simplified | |
| 2279 | + * {@link ng.$compile#directive-definition-object directive definition object}) | |
| 2280 | + * | |
| 2281 | + * @description | |
| 2282 | + * See {@link ng.$compileProvider#component $compileProvider.component()}. | |
| 2283 | + */ | |
| 2284 | + component: invokeLaterAndSetModuleName('$compileProvider', 'component'), | |
| 2285 | + | |
| 2286 | + /** | |
| 2287 | + * @ngdoc method | |
| 2288 | + * @name angular.Module#config | |
| 2289 | + * @module ng | |
| 2290 | + * @param {Function} configFn Execute this function on module load. Useful for service | |
| 2291 | + * configuration. | |
| 2292 | + * @description | |
| 2293 | + * Use this method to register work which needs to be performed on module loading. | |
| 2294 | + * For more about how to configure services, see | |
| 2295 | + * {@link providers#provider-recipe Provider Recipe}. | |
| 2296 | + */ | |
| 2297 | + config: config, | |
| 2298 | + | |
| 2299 | + /** | |
| 2300 | + * @ngdoc method | |
| 2301 | + * @name angular.Module#run | |
| 2302 | + * @module ng | |
| 2303 | + * @param {Function} initializationFn Execute this function after injector creation. | |
| 2304 | + * Useful for application initialization. | |
| 2305 | + * @description | |
| 2306 | + * Use this method to register work which should be performed when the injector is done | |
| 2307 | + * loading all modules. | |
| 2308 | + */ | |
| 2309 | + run: function(block) { | |
| 2310 | + runBlocks.push(block); | |
| 2311 | + return this; | |
| 2312 | + } | |
| 2313 | + }; | |
| 2314 | + | |
| 2315 | + if (configFn) { | |
| 2316 | + config(configFn); | |
| 2317 | + } | |
| 2318 | + | |
| 2319 | + return moduleInstance; | |
| 2320 | + | |
| 2321 | + /** | |
| 2322 | + * @param {string} provider | |
| 2323 | + * @param {string} method | |
| 2324 | + * @param {String=} insertMethod | |
| 2325 | + * @returns {angular.Module} | |
| 2326 | + */ | |
| 2327 | + function invokeLater(provider, method, insertMethod, queue) { | |
| 2328 | + if (!queue) queue = invokeQueue; | |
| 2329 | + return function() { | |
| 2330 | + queue[insertMethod || 'push']([provider, method, arguments]); | |
| 2331 | + return moduleInstance; | |
| 2332 | + }; | |
| 2333 | + } | |
| 2334 | + | |
| 2335 | + /** | |
| 2336 | + * @param {string} provider | |
| 2337 | + * @param {string} method | |
| 2338 | + * @returns {angular.Module} | |
| 2339 | + */ | |
| 2340 | + function invokeLaterAndSetModuleName(provider, method) { | |
| 2341 | + return function(recipeName, factoryFunction) { | |
| 2342 | + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; | |
| 2343 | + invokeQueue.push([provider, method, arguments]); | |
| 2344 | + return moduleInstance; | |
| 2345 | + }; | |
| 2346 | + } | |
| 2347 | + }); | |
| 2348 | + }; | |
| 2349 | + }); | |
| 2350 | + | |
| 2351 | +} | |
| 2352 | + | |
| 2353 | +/* global shallowCopy: true */ | |
| 2354 | + | |
| 2355 | +/** | |
| 2356 | + * Creates a shallow copy of an object, an array or a primitive. | |
| 2357 | + * | |
| 2358 | + * Assumes that there are no proto properties for objects. | |
| 2359 | + */ | |
| 2360 | +function shallowCopy(src, dst) { | |
| 2361 | + if (isArray(src)) { | |
| 2362 | + dst = dst || []; | |
| 2363 | + | |
| 2364 | + for (var i = 0, ii = src.length; i < ii; i++) { | |
| 2365 | + dst[i] = src[i]; | |
| 2366 | + } | |
| 2367 | + } else if (isObject(src)) { | |
| 2368 | + dst = dst || {}; | |
| 2369 | + | |
| 2370 | + for (var key in src) { | |
| 2371 | + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { | |
| 2372 | + dst[key] = src[key]; | |
| 2373 | + } | |
| 2374 | + } | |
| 2375 | + } | |
| 2376 | + | |
| 2377 | + return dst || src; | |
| 2378 | +} | |
| 2379 | + | |
| 2380 | +/* global toDebugString: true */ | |
| 2381 | + | |
| 2382 | +function serializeObject(obj) { | |
| 2383 | + var seen = []; | |
| 2384 | + | |
| 2385 | + return JSON.stringify(obj, function(key, val) { | |
| 2386 | + val = toJsonReplacer(key, val); | |
| 2387 | + if (isObject(val)) { | |
| 2388 | + | |
| 2389 | + if (seen.indexOf(val) >= 0) return '...'; | |
| 2390 | + | |
| 2391 | + seen.push(val); | |
| 2392 | + } | |
| 2393 | + return val; | |
| 2394 | + }); | |
| 2395 | +} | |
| 2396 | + | |
| 2397 | +function toDebugString(obj) { | |
| 2398 | + if (typeof obj === 'function') { | |
| 2399 | + return obj.toString().replace(/ \{[\s\S]*$/, ''); | |
| 2400 | + } else if (isUndefined(obj)) { | |
| 2401 | + return 'undefined'; | |
| 2402 | + } else if (typeof obj !== 'string') { | |
| 2403 | + return serializeObject(obj); | |
| 2404 | + } | |
| 2405 | + return obj; | |
| 2406 | +} | |
| 2407 | + | |
| 2408 | +/* global angularModule: true, | |
| 2409 | + version: true, | |
| 2410 | + | |
| 2411 | + $CompileProvider, | |
| 2412 | + | |
| 2413 | + htmlAnchorDirective, | |
| 2414 | + inputDirective, | |
| 2415 | + inputDirective, | |
| 2416 | + formDirective, | |
| 2417 | + scriptDirective, | |
| 2418 | + selectDirective, | |
| 2419 | + styleDirective, | |
| 2420 | + optionDirective, | |
| 2421 | + ngBindDirective, | |
| 2422 | + ngBindHtmlDirective, | |
| 2423 | + ngBindTemplateDirective, | |
| 2424 | + ngClassDirective, | |
| 2425 | + ngClassEvenDirective, | |
| 2426 | + ngClassOddDirective, | |
| 2427 | + ngCloakDirective, | |
| 2428 | + ngControllerDirective, | |
| 2429 | + ngFormDirective, | |
| 2430 | + ngHideDirective, | |
| 2431 | + ngIfDirective, | |
| 2432 | + ngIncludeDirective, | |
| 2433 | + ngIncludeFillContentDirective, | |
| 2434 | + ngInitDirective, | |
| 2435 | + ngNonBindableDirective, | |
| 2436 | + ngPluralizeDirective, | |
| 2437 | + ngRepeatDirective, | |
| 2438 | + ngShowDirective, | |
| 2439 | + ngStyleDirective, | |
| 2440 | + ngSwitchDirective, | |
| 2441 | + ngSwitchWhenDirective, | |
| 2442 | + ngSwitchDefaultDirective, | |
| 2443 | + ngOptionsDirective, | |
| 2444 | + ngTranscludeDirective, | |
| 2445 | + ngModelDirective, | |
| 2446 | + ngListDirective, | |
| 2447 | + ngChangeDirective, | |
| 2448 | + patternDirective, | |
| 2449 | + patternDirective, | |
| 2450 | + requiredDirective, | |
| 2451 | + requiredDirective, | |
| 2452 | + minlengthDirective, | |
| 2453 | + minlengthDirective, | |
| 2454 | + maxlengthDirective, | |
| 2455 | + maxlengthDirective, | |
| 2456 | + ngValueDirective, | |
| 2457 | + ngModelOptionsDirective, | |
| 2458 | + ngAttributeAliasDirectives, | |
| 2459 | + ngEventDirectives, | |
| 2460 | + | |
| 2461 | + $AnchorScrollProvider, | |
| 2462 | + $AnimateProvider, | |
| 2463 | + $CoreAnimateCssProvider, | |
| 2464 | + $$CoreAnimateJsProvider, | |
| 2465 | + $$CoreAnimateQueueProvider, | |
| 2466 | + $$AnimateRunnerFactoryProvider, | |
| 2467 | + $$AnimateAsyncRunFactoryProvider, | |
| 2468 | + $BrowserProvider, | |
| 2469 | + $CacheFactoryProvider, | |
| 2470 | + $ControllerProvider, | |
| 2471 | + $DateProvider, | |
| 2472 | + $DocumentProvider, | |
| 2473 | + $ExceptionHandlerProvider, | |
| 2474 | + $FilterProvider, | |
| 2475 | + $$ForceReflowProvider, | |
| 2476 | + $InterpolateProvider, | |
| 2477 | + $IntervalProvider, | |
| 2478 | + $$HashMapProvider, | |
| 2479 | + $HttpProvider, | |
| 2480 | + $HttpParamSerializerProvider, | |
| 2481 | + $HttpParamSerializerJQLikeProvider, | |
| 2482 | + $HttpBackendProvider, | |
| 2483 | + $xhrFactoryProvider, | |
| 2484 | + $jsonpCallbacksProvider, | |
| 2485 | + $LocationProvider, | |
| 2486 | + $LogProvider, | |
| 2487 | + $ParseProvider, | |
| 2488 | + $RootScopeProvider, | |
| 2489 | + $QProvider, | |
| 2490 | + $$QProvider, | |
| 2491 | + $$SanitizeUriProvider, | |
| 2492 | + $SceProvider, | |
| 2493 | + $SceDelegateProvider, | |
| 2494 | + $SnifferProvider, | |
| 2495 | + $TemplateCacheProvider, | |
| 2496 | + $TemplateRequestProvider, | |
| 2497 | + $$TestabilityProvider, | |
| 2498 | + $TimeoutProvider, | |
| 2499 | + $$RAFProvider, | |
| 2500 | + $WindowProvider, | |
| 2501 | + $$jqLiteProvider, | |
| 2502 | + $$CookieReaderProvider | |
| 2503 | +*/ | |
| 2504 | + | |
| 2505 | + | |
| 2506 | +/** | |
| 2507 | + * @ngdoc object | |
| 2508 | + * @name angular.version | |
| 2509 | + * @module ng | |
| 2510 | + * @description | |
| 2511 | + * An object that contains information about the current AngularJS version. | |
| 2512 | + * | |
| 2513 | + * This object has the following properties: | |
| 2514 | + * | |
| 2515 | + * - `full` – `{string}` – Full version string, such as "0.9.18". | |
| 2516 | + * - `major` – `{number}` – Major version number, such as "0". | |
| 2517 | + * - `minor` – `{number}` – Minor version number, such as "9". | |
| 2518 | + * - `dot` – `{number}` – Dot version number, such as "18". | |
| 2519 | + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". | |
| 2520 | + */ | |
| 2521 | +var version = { | |
| 2522 | + full: '1.5.8', // all of these placeholder strings will be replaced by grunt's | |
| 2523 | + major: 1, // package task | |
| 2524 | + minor: 5, | |
| 2525 | + dot: 8, | |
| 2526 | + codeName: 'arbitrary-fallbacks' | |
| 2527 | +}; | |
| 2528 | + | |
| 2529 | + | |
| 2530 | +function publishExternalAPI(angular) { | |
| 2531 | + extend(angular, { | |
| 2532 | + 'bootstrap': bootstrap, | |
| 2533 | + 'copy': copy, | |
| 2534 | + 'extend': extend, | |
| 2535 | + 'merge': merge, | |
| 2536 | + 'equals': equals, | |
| 2537 | + 'element': jqLite, | |
| 2538 | + 'forEach': forEach, | |
| 2539 | + 'injector': createInjector, | |
| 2540 | + 'noop': noop, | |
| 2541 | + 'bind': bind, | |
| 2542 | + 'toJson': toJson, | |
| 2543 | + 'fromJson': fromJson, | |
| 2544 | + 'identity': identity, | |
| 2545 | + 'isUndefined': isUndefined, | |
| 2546 | + 'isDefined': isDefined, | |
| 2547 | + 'isString': isString, | |
| 2548 | + 'isFunction': isFunction, | |
| 2549 | + 'isObject': isObject, | |
| 2550 | + 'isNumber': isNumber, | |
| 2551 | + 'isElement': isElement, | |
| 2552 | + 'isArray': isArray, | |
| 2553 | + 'version': version, | |
| 2554 | + 'isDate': isDate, | |
| 2555 | + 'lowercase': lowercase, | |
| 2556 | + 'uppercase': uppercase, | |
| 2557 | + 'callbacks': {$$counter: 0}, | |
| 2558 | + 'getTestability': getTestability, | |
| 2559 | + '$$minErr': minErr, | |
| 2560 | + '$$csp': csp, | |
| 2561 | + 'reloadWithDebugInfo': reloadWithDebugInfo | |
| 2562 | + }); | |
| 2563 | + | |
| 2564 | + angularModule = setupModuleLoader(window); | |
| 2565 | + | |
| 2566 | + angularModule('ng', ['ngLocale'], ['$provide', | |
| 2567 | + function ngModule($provide) { | |
| 2568 | + // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. | |
| 2569 | + $provide.provider({ | |
| 2570 | + $$sanitizeUri: $$SanitizeUriProvider | |
| 2571 | + }); | |
| 2572 | + $provide.provider('$compile', $CompileProvider). | |
| 2573 | + directive({ | |
| 2574 | + a: htmlAnchorDirective, | |
| 2575 | + input: inputDirective, | |
| 2576 | + textarea: inputDirective, | |
| 2577 | + form: formDirective, | |
| 2578 | + script: scriptDirective, | |
| 2579 | + select: selectDirective, | |
| 2580 | + style: styleDirective, | |
| 2581 | + option: optionDirective, | |
| 2582 | + ngBind: ngBindDirective, | |
| 2583 | + ngBindHtml: ngBindHtmlDirective, | |
| 2584 | + ngBindTemplate: ngBindTemplateDirective, | |
| 2585 | + ngClass: ngClassDirective, | |
| 2586 | + ngClassEven: ngClassEvenDirective, | |
| 2587 | + ngClassOdd: ngClassOddDirective, | |
| 2588 | + ngCloak: ngCloakDirective, | |
| 2589 | + ngController: ngControllerDirective, | |
| 2590 | + ngForm: ngFormDirective, | |
| 2591 | + ngHide: ngHideDirective, | |
| 2592 | + ngIf: ngIfDirective, | |
| 2593 | + ngInclude: ngIncludeDirective, | |
| 2594 | + ngInit: ngInitDirective, | |
| 2595 | + ngNonBindable: ngNonBindableDirective, | |
| 2596 | + ngPluralize: ngPluralizeDirective, | |
| 2597 | + ngRepeat: ngRepeatDirective, | |
| 2598 | + ngShow: ngShowDirective, | |
| 2599 | + ngStyle: ngStyleDirective, | |
| 2600 | + ngSwitch: ngSwitchDirective, | |
| 2601 | + ngSwitchWhen: ngSwitchWhenDirective, | |
| 2602 | + ngSwitchDefault: ngSwitchDefaultDirective, | |
| 2603 | + ngOptions: ngOptionsDirective, | |
| 2604 | + ngTransclude: ngTranscludeDirective, | |
| 2605 | + ngModel: ngModelDirective, | |
| 2606 | + ngList: ngListDirective, | |
| 2607 | + ngChange: ngChangeDirective, | |
| 2608 | + pattern: patternDirective, | |
| 2609 | + ngPattern: patternDirective, | |
| 2610 | + required: requiredDirective, | |
| 2611 | + ngRequired: requiredDirective, | |
| 2612 | + minlength: minlengthDirective, | |
| 2613 | + ngMinlength: minlengthDirective, | |
| 2614 | + maxlength: maxlengthDirective, | |
| 2615 | + ngMaxlength: maxlengthDirective, | |
| 2616 | + ngValue: ngValueDirective, | |
| 2617 | + ngModelOptions: ngModelOptionsDirective | |
| 2618 | + }). | |
| 2619 | + directive({ | |
| 2620 | + ngInclude: ngIncludeFillContentDirective | |
| 2621 | + }). | |
| 2622 | + directive(ngAttributeAliasDirectives). | |
| 2623 | + directive(ngEventDirectives); | |
| 2624 | + $provide.provider({ | |
| 2625 | + $anchorScroll: $AnchorScrollProvider, | |
| 2626 | + $animate: $AnimateProvider, | |
| 2627 | + $animateCss: $CoreAnimateCssProvider, | |
| 2628 | + $$animateJs: $$CoreAnimateJsProvider, | |
| 2629 | + $$animateQueue: $$CoreAnimateQueueProvider, | |
| 2630 | + $$AnimateRunner: $$AnimateRunnerFactoryProvider, | |
| 2631 | + $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider, | |
| 2632 | + $browser: $BrowserProvider, | |
| 2633 | + $cacheFactory: $CacheFactoryProvider, | |
| 2634 | + $controller: $ControllerProvider, | |
| 2635 | + $document: $DocumentProvider, | |
| 2636 | + $exceptionHandler: $ExceptionHandlerProvider, | |
| 2637 | + $filter: $FilterProvider, | |
| 2638 | + $$forceReflow: $$ForceReflowProvider, | |
| 2639 | + $interpolate: $InterpolateProvider, | |
| 2640 | + $interval: $IntervalProvider, | |
| 2641 | + $http: $HttpProvider, | |
| 2642 | + $httpParamSerializer: $HttpParamSerializerProvider, | |
| 2643 | + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, | |
| 2644 | + $httpBackend: $HttpBackendProvider, | |
| 2645 | + $xhrFactory: $xhrFactoryProvider, | |
| 2646 | + $jsonpCallbacks: $jsonpCallbacksProvider, | |
| 2647 | + $location: $LocationProvider, | |
| 2648 | + $log: $LogProvider, | |
| 2649 | + $parse: $ParseProvider, | |
| 2650 | + $rootScope: $RootScopeProvider, | |
| 2651 | + $q: $QProvider, | |
| 2652 | + $$q: $$QProvider, | |
| 2653 | + $sce: $SceProvider, | |
| 2654 | + $sceDelegate: $SceDelegateProvider, | |
| 2655 | + $sniffer: $SnifferProvider, | |
| 2656 | + $templateCache: $TemplateCacheProvider, | |
| 2657 | + $templateRequest: $TemplateRequestProvider, | |
| 2658 | + $$testability: $$TestabilityProvider, | |
| 2659 | + $timeout: $TimeoutProvider, | |
| 2660 | + $window: $WindowProvider, | |
| 2661 | + $$rAF: $$RAFProvider, | |
| 2662 | + $$jqLite: $$jqLiteProvider, | |
| 2663 | + $$HashMap: $$HashMapProvider, | |
| 2664 | + $$cookieReader: $$CookieReaderProvider | |
| 2665 | + }); | |
| 2666 | + } | |
| 2667 | + ]); | |
| 2668 | +} | |
| 2669 | + | |
| 2670 | +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
| 2671 | + * Any commits to this file should be reviewed with security in mind. * | |
| 2672 | + * Changes to this file can potentially create security vulnerabilities. * | |
| 2673 | + * An approval from 2 Core members with history of modifying * | |
| 2674 | + * this file is required. * | |
| 2675 | + * * | |
| 2676 | + * Does the change somehow allow for arbitrary javascript to be executed? * | |
| 2677 | + * Or allows for someone to change the prototype of built-in objects? * | |
| 2678 | + * Or gives undesired access to variables likes document or window? * | |
| 2679 | + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
| 2680 | + | |
| 2681 | +/* global JQLitePrototype: true, | |
| 2682 | + addEventListenerFn: true, | |
| 2683 | + removeEventListenerFn: true, | |
| 2684 | + BOOLEAN_ATTR: true, | |
| 2685 | + ALIASED_ATTR: true, | |
| 2686 | +*/ | |
| 2687 | + | |
| 2688 | +////////////////////////////////// | |
| 2689 | +//JQLite | |
| 2690 | +////////////////////////////////// | |
| 2691 | + | |
| 2692 | +/** | |
| 2693 | + * @ngdoc function | |
| 2694 | + * @name angular.element | |
| 2695 | + * @module ng | |
| 2696 | + * @kind function | |
| 2697 | + * | |
| 2698 | + * @description | |
| 2699 | + * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. | |
| 2700 | + * | |
| 2701 | + * If jQuery is available, `angular.element` is an alias for the | |
| 2702 | + * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` | |
| 2703 | + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**. | |
| 2704 | + * | |
| 2705 | + * jqLite is a tiny, API-compatible subset of jQuery that allows | |
| 2706 | + * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most | |
| 2707 | + * commonly needed functionality with the goal of having a very small footprint. | |
| 2708 | + * | |
| 2709 | + * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the | |
| 2710 | + * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a | |
| 2711 | + * specific version of jQuery if multiple versions exist on the page. | |
| 2712 | + * | |
| 2713 | + * <div class="alert alert-info">**Note:** All element references in Angular are always wrapped with jQuery or | |
| 2714 | + * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div> | |
| 2715 | + * | |
| 2716 | + * <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements | |
| 2717 | + * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)` | |
| 2718 | + * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div> | |
| 2719 | + * | |
| 2720 | + * ## Angular's jqLite | |
| 2721 | + * jqLite provides only the following jQuery methods: | |
| 2722 | + * | |
| 2723 | + * - [`addClass()`](http://api.jquery.com/addClass/) - Does not support a function as first argument | |
| 2724 | + * - [`after()`](http://api.jquery.com/after/) | |
| 2725 | + * - [`append()`](http://api.jquery.com/append/) | |
| 2726 | + * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters | |
| 2727 | + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData | |
| 2728 | + * - [`children()`](http://api.jquery.com/children/) - Does not support selectors | |
| 2729 | + * - [`clone()`](http://api.jquery.com/clone/) | |
| 2730 | + * - [`contents()`](http://api.jquery.com/contents/) | |
| 2731 | + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. | |
| 2732 | + * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing. | |
| 2733 | + * - [`data()`](http://api.jquery.com/data/) | |
| 2734 | + * - [`detach()`](http://api.jquery.com/detach/) | |
| 2735 | + * - [`empty()`](http://api.jquery.com/empty/) | |
| 2736 | + * - [`eq()`](http://api.jquery.com/eq/) | |
| 2737 | + * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name | |
| 2738 | + * - [`hasClass()`](http://api.jquery.com/hasClass/) | |
| 2739 | + * - [`html()`](http://api.jquery.com/html/) | |
| 2740 | + * - [`next()`](http://api.jquery.com/next/) - Does not support selectors | |
| 2741 | + * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData | |
| 2742 | + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter | |
| 2743 | + * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors | |
| 2744 | + * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors | |
| 2745 | + * - [`prepend()`](http://api.jquery.com/prepend/) | |
| 2746 | + * - [`prop()`](http://api.jquery.com/prop/) | |
| 2747 | + * - [`ready()`](http://api.jquery.com/ready/) | |
| 2748 | + * - [`remove()`](http://api.jquery.com/remove/) | |
| 2749 | + * - [`removeAttr()`](http://api.jquery.com/removeAttr/) | |
| 2750 | + * - [`removeClass()`](http://api.jquery.com/removeClass/) - Does not support a function as first argument | |
| 2751 | + * - [`removeData()`](http://api.jquery.com/removeData/) | |
| 2752 | + * - [`replaceWith()`](http://api.jquery.com/replaceWith/) | |
| 2753 | + * - [`text()`](http://api.jquery.com/text/) | |
| 2754 | + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument | |
| 2755 | + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers | |
| 2756 | + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter | |
| 2757 | + * - [`val()`](http://api.jquery.com/val/) | |
| 2758 | + * - [`wrap()`](http://api.jquery.com/wrap/) | |
| 2759 | + * | |
| 2760 | + * ## jQuery/jqLite Extras | |
| 2761 | + * Angular also provides the following additional methods and events to both jQuery and jqLite: | |
| 2762 | + * | |
| 2763 | + * ### Events | |
| 2764 | + * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event | |
| 2765 | + * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM | |
| 2766 | + * element before it is removed. | |
| 2767 | + * | |
| 2768 | + * ### Methods | |
| 2769 | + * - `controller(name)` - retrieves the controller of the current element or its parent. By default | |
| 2770 | + * retrieves controller associated with the `ngController` directive. If `name` is provided as | |
| 2771 | + * camelCase directive name, then the controller for this directive will be retrieved (e.g. | |
| 2772 | + * `'ngModel'`). | |
| 2773 | + * - `injector()` - retrieves the injector of the current element or its parent. | |
| 2774 | + * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current | |
| 2775 | + * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to | |
| 2776 | + * be enabled. | |
| 2777 | + * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the | |
| 2778 | + * current element. This getter should be used only on elements that contain a directive which starts a new isolate | |
| 2779 | + * scope. Calling `scope()` on this element always returns the original non-isolate scope. | |
| 2780 | + * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled. | |
| 2781 | + * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top | |
| 2782 | + * parent element is reached. | |
| 2783 | + * | |
| 2784 | + * @knownIssue You cannot spy on `angular.element` if you are using Jasmine version 1.x. See | |
| 2785 | + * https://github.com/angular/angular.js/issues/14251 for more information. | |
| 2786 | + * | |
| 2787 | + * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. | |
| 2788 | + * @returns {Object} jQuery object. | |
| 2789 | + */ | |
| 2790 | + | |
| 2791 | +JQLite.expando = 'ng339'; | |
| 2792 | + | |
| 2793 | +var jqCache = JQLite.cache = {}, | |
| 2794 | + jqId = 1, | |
| 2795 | + addEventListenerFn = function(element, type, fn) { | |
| 2796 | + element.addEventListener(type, fn, false); | |
| 2797 | + }, | |
| 2798 | + removeEventListenerFn = function(element, type, fn) { | |
| 2799 | + element.removeEventListener(type, fn, false); | |
| 2800 | + }; | |
| 2801 | + | |
| 2802 | +/* | |
| 2803 | + * !!! This is an undocumented "private" function !!! | |
| 2804 | + */ | |
| 2805 | +JQLite._data = function(node) { | |
| 2806 | + //jQuery always returns an object on cache miss | |
| 2807 | + return this.cache[node[this.expando]] || {}; | |
| 2808 | +}; | |
| 2809 | + | |
| 2810 | +function jqNextId() { return ++jqId; } | |
| 2811 | + | |
| 2812 | + | |
| 2813 | +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; | |
| 2814 | +var MOZ_HACK_REGEXP = /^moz([A-Z])/; | |
| 2815 | +var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; | |
| 2816 | +var jqLiteMinErr = minErr('jqLite'); | |
| 2817 | + | |
| 2818 | +/** | |
| 2819 | + * Converts snake_case to camelCase. | |
| 2820 | + * Also there is special case for Moz prefix starting with upper case letter. | |
| 2821 | + * @param name Name to normalize | |
| 2822 | + */ | |
| 2823 | +function camelCase(name) { | |
| 2824 | + return name. | |
| 2825 | + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { | |
| 2826 | + return offset ? letter.toUpperCase() : letter; | |
| 2827 | + }). | |
| 2828 | + replace(MOZ_HACK_REGEXP, 'Moz$1'); | |
| 2829 | +} | |
| 2830 | + | |
| 2831 | +var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; | |
| 2832 | +var HTML_REGEXP = /<|&#?\w+;/; | |
| 2833 | +var TAG_NAME_REGEXP = /<([\w:-]+)/; | |
| 2834 | +var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; | |
| 2835 | + | |
| 2836 | +var wrapMap = { | |
| 2837 | + 'option': [1, '<select multiple="multiple">', '</select>'], | |
| 2838 | + | |
| 2839 | + 'thead': [1, '<table>', '</table>'], | |
| 2840 | + 'col': [2, '<table><colgroup>', '</colgroup></table>'], | |
| 2841 | + 'tr': [2, '<table><tbody>', '</tbody></table>'], | |
| 2842 | + 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'], | |
| 2843 | + '_default': [0, "", ""] | |
| 2844 | +}; | |
| 2845 | + | |
| 2846 | +wrapMap.optgroup = wrapMap.option; | |
| 2847 | +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; | |
| 2848 | +wrapMap.th = wrapMap.td; | |
| 2849 | + | |
| 2850 | + | |
| 2851 | +function jqLiteIsTextNode(html) { | |
| 2852 | + return !HTML_REGEXP.test(html); | |
| 2853 | +} | |
| 2854 | + | |
| 2855 | +function jqLiteAcceptsData(node) { | |
| 2856 | + // The window object can accept data but has no nodeType | |
| 2857 | + // Otherwise we are only interested in elements (1) and documents (9) | |
| 2858 | + var nodeType = node.nodeType; | |
| 2859 | + return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; | |
| 2860 | +} | |
| 2861 | + | |
| 2862 | +function jqLiteHasData(node) { | |
| 2863 | + for (var key in jqCache[node.ng339]) { | |
| 2864 | + return true; | |
| 2865 | + } | |
| 2866 | + return false; | |
| 2867 | +} | |
| 2868 | + | |
| 2869 | +function jqLiteCleanData(nodes) { | |
| 2870 | + for (var i = 0, ii = nodes.length; i < ii; i++) { | |
| 2871 | + jqLiteRemoveData(nodes[i]); | |
| 2872 | + } | |
| 2873 | +} | |
| 2874 | + | |
| 2875 | +function jqLiteBuildFragment(html, context) { | |
| 2876 | + var tmp, tag, wrap, | |
| 2877 | + fragment = context.createDocumentFragment(), | |
| 2878 | + nodes = [], i; | |
| 2879 | + | |
| 2880 | + if (jqLiteIsTextNode(html)) { | |
| 2881 | + // Convert non-html into a text node | |
| 2882 | + nodes.push(context.createTextNode(html)); | |
| 2883 | + } else { | |
| 2884 | + // Convert html into DOM nodes | |
| 2885 | + tmp = fragment.appendChild(context.createElement("div")); | |
| 2886 | + tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); | |
| 2887 | + wrap = wrapMap[tag] || wrapMap._default; | |
| 2888 | + tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2]; | |
| 2889 | + | |
| 2890 | + // Descend through wrappers to the right content | |
| 2891 | + i = wrap[0]; | |
| 2892 | + while (i--) { | |
| 2893 | + tmp = tmp.lastChild; | |
| 2894 | + } | |
| 2895 | + | |
| 2896 | + nodes = concat(nodes, tmp.childNodes); | |
| 2897 | + | |
| 2898 | + tmp = fragment.firstChild; | |
| 2899 | + tmp.textContent = ""; | |
| 2900 | + } | |
| 2901 | + | |
| 2902 | + // Remove wrapper from fragment | |
| 2903 | + fragment.textContent = ""; | |
| 2904 | + fragment.innerHTML = ""; // Clear inner HTML | |
| 2905 | + forEach(nodes, function(node) { | |
| 2906 | + fragment.appendChild(node); | |
| 2907 | + }); | |
| 2908 | + | |
| 2909 | + return fragment; | |
| 2910 | +} | |
| 2911 | + | |
| 2912 | +function jqLiteParseHTML(html, context) { | |
| 2913 | + context = context || window.document; | |
| 2914 | + var parsed; | |
| 2915 | + | |
| 2916 | + if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { | |
| 2917 | + return [context.createElement(parsed[1])]; | |
| 2918 | + } | |
| 2919 | + | |
| 2920 | + if ((parsed = jqLiteBuildFragment(html, context))) { | |
| 2921 | + return parsed.childNodes; | |
| 2922 | + } | |
| 2923 | + | |
| 2924 | + return []; | |
| 2925 | +} | |
| 2926 | + | |
| 2927 | +function jqLiteWrapNode(node, wrapper) { | |
| 2928 | + var parent = node.parentNode; | |
| 2929 | + | |
| 2930 | + if (parent) { | |
| 2931 | + parent.replaceChild(wrapper, node); | |
| 2932 | + } | |
| 2933 | + | |
| 2934 | + wrapper.appendChild(node); | |
| 2935 | +} | |
| 2936 | + | |
| 2937 | + | |
| 2938 | +// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259. | |
| 2939 | +var jqLiteContains = window.Node.prototype.contains || function(arg) { | |
| 2940 | + // jshint bitwise: false | |
| 2941 | + return !!(this.compareDocumentPosition(arg) & 16); | |
| 2942 | + // jshint bitwise: true | |
| 2943 | +}; | |
| 2944 | + | |
| 2945 | +///////////////////////////////////////////// | |
| 2946 | +function JQLite(element) { | |
| 2947 | + if (element instanceof JQLite) { | |
| 2948 | + return element; | |
| 2949 | + } | |
| 2950 | + | |
| 2951 | + var argIsString; | |
| 2952 | + | |
| 2953 | + if (isString(element)) { | |
| 2954 | + element = trim(element); | |
| 2955 | + argIsString = true; | |
| 2956 | + } | |
| 2957 | + if (!(this instanceof JQLite)) { | |
| 2958 | + if (argIsString && element.charAt(0) != '<') { | |
| 2959 | + throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); | |
| 2960 | + } | |
| 2961 | + return new JQLite(element); | |
| 2962 | + } | |
| 2963 | + | |
| 2964 | + if (argIsString) { | |
| 2965 | + jqLiteAddNodes(this, jqLiteParseHTML(element)); | |
| 2966 | + } else { | |
| 2967 | + jqLiteAddNodes(this, element); | |
| 2968 | + } | |
| 2969 | +} | |
| 2970 | + | |
| 2971 | +function jqLiteClone(element) { | |
| 2972 | + return element.cloneNode(true); | |
| 2973 | +} | |
| 2974 | + | |
| 2975 | +function jqLiteDealoc(element, onlyDescendants) { | |
| 2976 | + if (!onlyDescendants) jqLiteRemoveData(element); | |
| 2977 | + | |
| 2978 | + if (element.querySelectorAll) { | |
| 2979 | + var descendants = element.querySelectorAll('*'); | |
| 2980 | + for (var i = 0, l = descendants.length; i < l; i++) { | |
| 2981 | + jqLiteRemoveData(descendants[i]); | |
| 2982 | + } | |
| 2983 | + } | |
| 2984 | +} | |
| 2985 | + | |
| 2986 | +function jqLiteOff(element, type, fn, unsupported) { | |
| 2987 | + if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); | |
| 2988 | + | |
| 2989 | + var expandoStore = jqLiteExpandoStore(element); | |
| 2990 | + var events = expandoStore && expandoStore.events; | |
| 2991 | + var handle = expandoStore && expandoStore.handle; | |
| 2992 | + | |
| 2993 | + if (!handle) return; //no listeners registered | |
| 2994 | + | |
| 2995 | + if (!type) { | |
| 2996 | + for (type in events) { | |
| 2997 | + if (type !== '$destroy') { | |
| 2998 | + removeEventListenerFn(element, type, handle); | |
| 2999 | + } | |
| 3000 | + delete events[type]; | |
| 3001 | + } | |
| 3002 | + } else { | |
| 3003 | + | |
| 3004 | + var removeHandler = function(type) { | |
| 3005 | + var listenerFns = events[type]; | |
| 3006 | + if (isDefined(fn)) { | |
| 3007 | + arrayRemove(listenerFns || [], fn); | |
| 3008 | + } | |
| 3009 | + if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) { | |
| 3010 | + removeEventListenerFn(element, type, handle); | |
| 3011 | + delete events[type]; | |
| 3012 | + } | |
| 3013 | + }; | |
| 3014 | + | |
| 3015 | + forEach(type.split(' '), function(type) { | |
| 3016 | + removeHandler(type); | |
| 3017 | + if (MOUSE_EVENT_MAP[type]) { | |
| 3018 | + removeHandler(MOUSE_EVENT_MAP[type]); | |
| 3019 | + } | |
| 3020 | + }); | |
| 3021 | + } | |
| 3022 | +} | |
| 3023 | + | |
| 3024 | +function jqLiteRemoveData(element, name) { | |
| 3025 | + var expandoId = element.ng339; | |
| 3026 | + var expandoStore = expandoId && jqCache[expandoId]; | |
| 3027 | + | |
| 3028 | + if (expandoStore) { | |
| 3029 | + if (name) { | |
| 3030 | + delete expandoStore.data[name]; | |
| 3031 | + return; | |
| 3032 | + } | |
| 3033 | + | |
| 3034 | + if (expandoStore.handle) { | |
| 3035 | + if (expandoStore.events.$destroy) { | |
| 3036 | + expandoStore.handle({}, '$destroy'); | |
| 3037 | + } | |
| 3038 | + jqLiteOff(element); | |
| 3039 | + } | |
| 3040 | + delete jqCache[expandoId]; | |
| 3041 | + element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it | |
| 3042 | + } | |
| 3043 | +} | |
| 3044 | + | |
| 3045 | + | |
| 3046 | +function jqLiteExpandoStore(element, createIfNecessary) { | |
| 3047 | + var expandoId = element.ng339, | |
| 3048 | + expandoStore = expandoId && jqCache[expandoId]; | |
| 3049 | + | |
| 3050 | + if (createIfNecessary && !expandoStore) { | |
| 3051 | + element.ng339 = expandoId = jqNextId(); | |
| 3052 | + expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined}; | |
| 3053 | + } | |
| 3054 | + | |
| 3055 | + return expandoStore; | |
| 3056 | +} | |
| 3057 | + | |
| 3058 | + | |
| 3059 | +function jqLiteData(element, key, value) { | |
| 3060 | + if (jqLiteAcceptsData(element)) { | |
| 3061 | + | |
| 3062 | + var isSimpleSetter = isDefined(value); | |
| 3063 | + var isSimpleGetter = !isSimpleSetter && key && !isObject(key); | |
| 3064 | + var massGetter = !key; | |
| 3065 | + var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); | |
| 3066 | + var data = expandoStore && expandoStore.data; | |
| 3067 | + | |
| 3068 | + if (isSimpleSetter) { // data('key', value) | |
| 3069 | + data[key] = value; | |
| 3070 | + } else { | |
| 3071 | + if (massGetter) { // data() | |
| 3072 | + return data; | |
| 3073 | + } else { | |
| 3074 | + if (isSimpleGetter) { // data('key') | |
| 3075 | + // don't force creation of expandoStore if it doesn't exist yet | |
| 3076 | + return data && data[key]; | |
| 3077 | + } else { // mass-setter: data({key1: val1, key2: val2}) | |
| 3078 | + extend(data, key); | |
| 3079 | + } | |
| 3080 | + } | |
| 3081 | + } | |
| 3082 | + } | |
| 3083 | +} | |
| 3084 | + | |
| 3085 | +function jqLiteHasClass(element, selector) { | |
| 3086 | + if (!element.getAttribute) return false; | |
| 3087 | + return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). | |
| 3088 | + indexOf(" " + selector + " ") > -1); | |
| 3089 | +} | |
| 3090 | + | |
| 3091 | +function jqLiteRemoveClass(element, cssClasses) { | |
| 3092 | + if (cssClasses && element.setAttribute) { | |
| 3093 | + forEach(cssClasses.split(' '), function(cssClass) { | |
| 3094 | + element.setAttribute('class', trim( | |
| 3095 | + (" " + (element.getAttribute('class') || '') + " ") | |
| 3096 | + .replace(/[\n\t]/g, " ") | |
| 3097 | + .replace(" " + trim(cssClass) + " ", " ")) | |
| 3098 | + ); | |
| 3099 | + }); | |
| 3100 | + } | |
| 3101 | +} | |
| 3102 | + | |
| 3103 | +function jqLiteAddClass(element, cssClasses) { | |
| 3104 | + if (cssClasses && element.setAttribute) { | |
| 3105 | + var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') | |
| 3106 | + .replace(/[\n\t]/g, " "); | |
| 3107 | + | |
| 3108 | + forEach(cssClasses.split(' '), function(cssClass) { | |
| 3109 | + cssClass = trim(cssClass); | |
| 3110 | + if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { | |
| 3111 | + existingClasses += cssClass + ' '; | |
| 3112 | + } | |
| 3113 | + }); | |
| 3114 | + | |
| 3115 | + element.setAttribute('class', trim(existingClasses)); | |
| 3116 | + } | |
| 3117 | +} | |
| 3118 | + | |
| 3119 | + | |
| 3120 | +function jqLiteAddNodes(root, elements) { | |
| 3121 | + // THIS CODE IS VERY HOT. Don't make changes without benchmarking. | |
| 3122 | + | |
| 3123 | + if (elements) { | |
| 3124 | + | |
| 3125 | + // if a Node (the most common case) | |
| 3126 | + if (elements.nodeType) { | |
| 3127 | + root[root.length++] = elements; | |
| 3128 | + } else { | |
| 3129 | + var length = elements.length; | |
| 3130 | + | |
| 3131 | + // if an Array or NodeList and not a Window | |
| 3132 | + if (typeof length === 'number' && elements.window !== elements) { | |
| 3133 | + if (length) { | |
| 3134 | + for (var i = 0; i < length; i++) { | |
| 3135 | + root[root.length++] = elements[i]; | |
| 3136 | + } | |
| 3137 | + } | |
| 3138 | + } else { | |
| 3139 | + root[root.length++] = elements; | |
| 3140 | + } | |
| 3141 | + } | |
| 3142 | + } | |
| 3143 | +} | |
| 3144 | + | |
| 3145 | + | |
| 3146 | +function jqLiteController(element, name) { | |
| 3147 | + return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller'); | |
| 3148 | +} | |
| 3149 | + | |
| 3150 | +function jqLiteInheritedData(element, name, value) { | |
| 3151 | + // if element is the document object work with the html element instead | |
| 3152 | + // this makes $(document).scope() possible | |
| 3153 | + if (element.nodeType == NODE_TYPE_DOCUMENT) { | |
| 3154 | + element = element.documentElement; | |
| 3155 | + } | |
| 3156 | + var names = isArray(name) ? name : [name]; | |
| 3157 | + | |
| 3158 | + while (element) { | |
| 3159 | + for (var i = 0, ii = names.length; i < ii; i++) { | |
| 3160 | + if (isDefined(value = jqLite.data(element, names[i]))) return value; | |
| 3161 | + } | |
| 3162 | + | |
| 3163 | + // If dealing with a document fragment node with a host element, and no parent, use the host | |
| 3164 | + // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM | |
| 3165 | + // to lookup parent controllers. | |
| 3166 | + element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host); | |
| 3167 | + } | |
| 3168 | +} | |
| 3169 | + | |
| 3170 | +function jqLiteEmpty(element) { | |
| 3171 | + jqLiteDealoc(element, true); | |
| 3172 | + while (element.firstChild) { | |
| 3173 | + element.removeChild(element.firstChild); | |
| 3174 | + } | |
| 3175 | +} | |
| 3176 | + | |
| 3177 | +function jqLiteRemove(element, keepData) { | |
| 3178 | + if (!keepData) jqLiteDealoc(element); | |
| 3179 | + var parent = element.parentNode; | |
| 3180 | + if (parent) parent.removeChild(element); | |
| 3181 | +} | |
| 3182 | + | |
| 3183 | + | |
| 3184 | +function jqLiteDocumentLoaded(action, win) { | |
| 3185 | + win = win || window; | |
| 3186 | + if (win.document.readyState === 'complete') { | |
| 3187 | + // Force the action to be run async for consistent behavior | |
| 3188 | + // from the action's point of view | |
| 3189 | + // i.e. it will definitely not be in a $apply | |
| 3190 | + win.setTimeout(action); | |
| 3191 | + } else { | |
| 3192 | + // No need to unbind this handler as load is only ever called once | |
| 3193 | + jqLite(win).on('load', action); | |
| 3194 | + } | |
| 3195 | +} | |
| 3196 | + | |
| 3197 | +////////////////////////////////////////// | |
| 3198 | +// Functions which are declared directly. | |
| 3199 | +////////////////////////////////////////// | |
| 3200 | +var JQLitePrototype = JQLite.prototype = { | |
| 3201 | + ready: function(fn) { | |
| 3202 | + var fired = false; | |
| 3203 | + | |
| 3204 | + function trigger() { | |
| 3205 | + if (fired) return; | |
| 3206 | + fired = true; | |
| 3207 | + fn(); | |
| 3208 | + } | |
| 3209 | + | |
| 3210 | + // check if document is already loaded | |
| 3211 | + if (window.document.readyState === 'complete') { | |
| 3212 | + window.setTimeout(trigger); | |
| 3213 | + } else { | |
| 3214 | + this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 | |
| 3215 | + // we can not use jqLite since we are not done loading and jQuery could be loaded later. | |
| 3216 | + // jshint -W064 | |
| 3217 | + JQLite(window).on('load', trigger); // fallback to window.onload for others | |
| 3218 | + // jshint +W064 | |
| 3219 | + } | |
| 3220 | + }, | |
| 3221 | + toString: function() { | |
| 3222 | + var value = []; | |
| 3223 | + forEach(this, function(e) { value.push('' + e);}); | |
| 3224 | + return '[' + value.join(', ') + ']'; | |
| 3225 | + }, | |
| 3226 | + | |
| 3227 | + eq: function(index) { | |
| 3228 | + return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); | |
| 3229 | + }, | |
| 3230 | + | |
| 3231 | + length: 0, | |
| 3232 | + push: push, | |
| 3233 | + sort: [].sort, | |
| 3234 | + splice: [].splice | |
| 3235 | +}; | |
| 3236 | + | |
| 3237 | +////////////////////////////////////////// | |
| 3238 | +// Functions iterating getter/setters. | |
| 3239 | +// these functions return self on setter and | |
| 3240 | +// value on get. | |
| 3241 | +////////////////////////////////////////// | |
| 3242 | +var BOOLEAN_ATTR = {}; | |
| 3243 | +forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { | |
| 3244 | + BOOLEAN_ATTR[lowercase(value)] = value; | |
| 3245 | +}); | |
| 3246 | +var BOOLEAN_ELEMENTS = {}; | |
| 3247 | +forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { | |
| 3248 | + BOOLEAN_ELEMENTS[value] = true; | |
| 3249 | +}); | |
| 3250 | +var ALIASED_ATTR = { | |
| 3251 | + 'ngMinlength': 'minlength', | |
| 3252 | + 'ngMaxlength': 'maxlength', | |
| 3253 | + 'ngMin': 'min', | |
| 3254 | + 'ngMax': 'max', | |
| 3255 | + 'ngPattern': 'pattern' | |
| 3256 | +}; | |
| 3257 | + | |
| 3258 | +function getBooleanAttrName(element, name) { | |
| 3259 | + // check dom last since we will most likely fail on name | |
| 3260 | + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; | |
| 3261 | + | |
| 3262 | + // booleanAttr is here twice to minimize DOM access | |
| 3263 | + return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; | |
| 3264 | +} | |
| 3265 | + | |
| 3266 | +function getAliasedAttrName(name) { | |
| 3267 | + return ALIASED_ATTR[name]; | |
| 3268 | +} | |
| 3269 | + | |
| 3270 | +forEach({ | |
| 3271 | + data: jqLiteData, | |
| 3272 | + removeData: jqLiteRemoveData, | |
| 3273 | + hasData: jqLiteHasData, | |
| 3274 | + cleanData: jqLiteCleanData | |
| 3275 | +}, function(fn, name) { | |
| 3276 | + JQLite[name] = fn; | |
| 3277 | +}); | |
| 3278 | + | |
| 3279 | +forEach({ | |
| 3280 | + data: jqLiteData, | |
| 3281 | + inheritedData: jqLiteInheritedData, | |
| 3282 | + | |
| 3283 | + scope: function(element) { | |
| 3284 | + // Can't use jqLiteData here directly so we stay compatible with jQuery! | |
| 3285 | + return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); | |
| 3286 | + }, | |
| 3287 | + | |
| 3288 | + isolateScope: function(element) { | |
| 3289 | + // Can't use jqLiteData here directly so we stay compatible with jQuery! | |
| 3290 | + return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate'); | |
| 3291 | + }, | |
| 3292 | + | |
| 3293 | + controller: jqLiteController, | |
| 3294 | + | |
| 3295 | + injector: function(element) { | |
| 3296 | + return jqLiteInheritedData(element, '$injector'); | |
| 3297 | + }, | |
| 3298 | + | |
| 3299 | + removeAttr: function(element, name) { | |
| 3300 | + element.removeAttribute(name); | |
| 3301 | + }, | |
| 3302 | + | |
| 3303 | + hasClass: jqLiteHasClass, | |
| 3304 | + | |
| 3305 | + css: function(element, name, value) { | |
| 3306 | + name = camelCase(name); | |
| 3307 | + | |
| 3308 | + if (isDefined(value)) { | |
| 3309 | + element.style[name] = value; | |
| 3310 | + } else { | |
| 3311 | + return element.style[name]; | |
| 3312 | + } | |
| 3313 | + }, | |
| 3314 | + | |
| 3315 | + attr: function(element, name, value) { | |
| 3316 | + var nodeType = element.nodeType; | |
| 3317 | + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { | |
| 3318 | + return; | |
| 3319 | + } | |
| 3320 | + var lowercasedName = lowercase(name); | |
| 3321 | + if (BOOLEAN_ATTR[lowercasedName]) { | |
| 3322 | + if (isDefined(value)) { | |
| 3323 | + if (!!value) { | |
| 3324 | + element[name] = true; | |
| 3325 | + element.setAttribute(name, lowercasedName); | |
| 3326 | + } else { | |
| 3327 | + element[name] = false; | |
| 3328 | + element.removeAttribute(lowercasedName); | |
| 3329 | + } | |
| 3330 | + } else { | |
| 3331 | + return (element[name] || | |
| 3332 | + (element.attributes.getNamedItem(name) || noop).specified) | |
| 3333 | + ? lowercasedName | |
| 3334 | + : undefined; | |
| 3335 | + } | |
| 3336 | + } else if (isDefined(value)) { | |
| 3337 | + element.setAttribute(name, value); | |
| 3338 | + } else if (element.getAttribute) { | |
| 3339 | + // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code | |
| 3340 | + // some elements (e.g. Document) don't have get attribute, so return undefined | |
| 3341 | + var ret = element.getAttribute(name, 2); | |
| 3342 | + // normalize non-existing attributes to undefined (as jQuery) | |
| 3343 | + return ret === null ? undefined : ret; | |
| 3344 | + } | |
| 3345 | + }, | |
| 3346 | + | |
| 3347 | + prop: function(element, name, value) { | |
| 3348 | + if (isDefined(value)) { | |
| 3349 | + element[name] = value; | |
| 3350 | + } else { | |
| 3351 | + return element[name]; | |
| 3352 | + } | |
| 3353 | + }, | |
| 3354 | + | |
| 3355 | + text: (function() { | |
| 3356 | + getText.$dv = ''; | |
| 3357 | + return getText; | |
| 3358 | + | |
| 3359 | + function getText(element, value) { | |
| 3360 | + if (isUndefined(value)) { | |
| 3361 | + var nodeType = element.nodeType; | |
| 3362 | + return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : ''; | |
| 3363 | + } | |
| 3364 | + element.textContent = value; | |
| 3365 | + } | |
| 3366 | + })(), | |
| 3367 | + | |
| 3368 | + val: function(element, value) { | |
| 3369 | + if (isUndefined(value)) { | |
| 3370 | + if (element.multiple && nodeName_(element) === 'select') { | |
| 3371 | + var result = []; | |
| 3372 | + forEach(element.options, function(option) { | |
| 3373 | + if (option.selected) { | |
| 3374 | + result.push(option.value || option.text); | |
| 3375 | + } | |
| 3376 | + }); | |
| 3377 | + return result.length === 0 ? null : result; | |
| 3378 | + } | |
| 3379 | + return element.value; | |
| 3380 | + } | |
| 3381 | + element.value = value; | |
| 3382 | + }, | |
| 3383 | + | |
| 3384 | + html: function(element, value) { | |
| 3385 | + if (isUndefined(value)) { | |
| 3386 | + return element.innerHTML; | |
| 3387 | + } | |
| 3388 | + jqLiteDealoc(element, true); | |
| 3389 | + element.innerHTML = value; | |
| 3390 | + }, | |
| 3391 | + | |
| 3392 | + empty: jqLiteEmpty | |
| 3393 | +}, function(fn, name) { | |
| 3394 | + /** | |
| 3395 | + * Properties: writes return selection, reads return first value | |
| 3396 | + */ | |
| 3397 | + JQLite.prototype[name] = function(arg1, arg2) { | |
| 3398 | + var i, key; | |
| 3399 | + var nodeCount = this.length; | |
| 3400 | + | |
| 3401 | + // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it | |
| 3402 | + // in a way that survives minification. | |
| 3403 | + // jqLiteEmpty takes no arguments but is a setter. | |
| 3404 | + if (fn !== jqLiteEmpty && | |
| 3405 | + (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) { | |
| 3406 | + if (isObject(arg1)) { | |
| 3407 | + | |
| 3408 | + // we are a write, but the object properties are the key/values | |
| 3409 | + for (i = 0; i < nodeCount; i++) { | |
| 3410 | + if (fn === jqLiteData) { | |
| 3411 | + // data() takes the whole object in jQuery | |
| 3412 | + fn(this[i], arg1); | |
| 3413 | + } else { | |
| 3414 | + for (key in arg1) { | |
| 3415 | + fn(this[i], key, arg1[key]); | |
| 3416 | + } | |
| 3417 | + } | |
| 3418 | + } | |
| 3419 | + // return self for chaining | |
| 3420 | + return this; | |
| 3421 | + } else { | |
| 3422 | + // we are a read, so read the first child. | |
| 3423 | + // TODO: do we still need this? | |
| 3424 | + var value = fn.$dv; | |
| 3425 | + // Only if we have $dv do we iterate over all, otherwise it is just the first element. | |
| 3426 | + var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount; | |
| 3427 | + for (var j = 0; j < jj; j++) { | |
| 3428 | + var nodeValue = fn(this[j], arg1, arg2); | |
| 3429 | + value = value ? value + nodeValue : nodeValue; | |
| 3430 | + } | |
| 3431 | + return value; | |
| 3432 | + } | |
| 3433 | + } else { | |
| 3434 | + // we are a write, so apply to all children | |
| 3435 | + for (i = 0; i < nodeCount; i++) { | |
| 3436 | + fn(this[i], arg1, arg2); | |
| 3437 | + } | |
| 3438 | + // return self for chaining | |
| 3439 | + return this; | |
| 3440 | + } | |
| 3441 | + }; | |
| 3442 | +}); | |
| 3443 | + | |
| 3444 | +function createEventHandler(element, events) { | |
| 3445 | + var eventHandler = function(event, type) { | |
| 3446 | + // jQuery specific api | |
| 3447 | + event.isDefaultPrevented = function() { | |
| 3448 | + return event.defaultPrevented; | |
| 3449 | + }; | |
| 3450 | + | |
| 3451 | + var eventFns = events[type || event.type]; | |
| 3452 | + var eventFnsLength = eventFns ? eventFns.length : 0; | |
| 3453 | + | |
| 3454 | + if (!eventFnsLength) return; | |
| 3455 | + | |
| 3456 | + if (isUndefined(event.immediatePropagationStopped)) { | |
| 3457 | + var originalStopImmediatePropagation = event.stopImmediatePropagation; | |
| 3458 | + event.stopImmediatePropagation = function() { | |
| 3459 | + event.immediatePropagationStopped = true; | |
| 3460 | + | |
| 3461 | + if (event.stopPropagation) { | |
| 3462 | + event.stopPropagation(); | |
| 3463 | + } | |
| 3464 | + | |
| 3465 | + if (originalStopImmediatePropagation) { | |
| 3466 | + originalStopImmediatePropagation.call(event); | |
| 3467 | + } | |
| 3468 | + }; | |
| 3469 | + } | |
| 3470 | + | |
| 3471 | + event.isImmediatePropagationStopped = function() { | |
| 3472 | + return event.immediatePropagationStopped === true; | |
| 3473 | + }; | |
| 3474 | + | |
| 3475 | + // Some events have special handlers that wrap the real handler | |
| 3476 | + var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper; | |
| 3477 | + | |
| 3478 | + // Copy event handlers in case event handlers array is modified during execution. | |
| 3479 | + if ((eventFnsLength > 1)) { | |
| 3480 | + eventFns = shallowCopy(eventFns); | |
| 3481 | + } | |
| 3482 | + | |
| 3483 | + for (var i = 0; i < eventFnsLength; i++) { | |
| 3484 | + if (!event.isImmediatePropagationStopped()) { | |
| 3485 | + handlerWrapper(element, event, eventFns[i]); | |
| 3486 | + } | |
| 3487 | + } | |
| 3488 | + }; | |
| 3489 | + | |
| 3490 | + // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all | |
| 3491 | + // events on `element` | |
| 3492 | + eventHandler.elem = element; | |
| 3493 | + return eventHandler; | |
| 3494 | +} | |
| 3495 | + | |
| 3496 | +function defaultHandlerWrapper(element, event, handler) { | |
| 3497 | + handler.call(element, event); | |
| 3498 | +} | |
| 3499 | + | |
| 3500 | +function specialMouseHandlerWrapper(target, event, handler) { | |
| 3501 | + // Refer to jQuery's implementation of mouseenter & mouseleave | |
| 3502 | + // Read about mouseenter and mouseleave: | |
| 3503 | + // http://www.quirksmode.org/js/events_mouse.html#link8 | |
| 3504 | + var related = event.relatedTarget; | |
| 3505 | + // For mousenter/leave call the handler if related is outside the target. | |
| 3506 | + // NB: No relatedTarget if the mouse left/entered the browser window | |
| 3507 | + if (!related || (related !== target && !jqLiteContains.call(target, related))) { | |
| 3508 | + handler.call(target, event); | |
| 3509 | + } | |
| 3510 | +} | |
| 3511 | + | |
| 3512 | +////////////////////////////////////////// | |
| 3513 | +// Functions iterating traversal. | |
| 3514 | +// These functions chain results into a single | |
| 3515 | +// selector. | |
| 3516 | +////////////////////////////////////////// | |
| 3517 | +forEach({ | |
| 3518 | + removeData: jqLiteRemoveData, | |
| 3519 | + | |
| 3520 | + on: function jqLiteOn(element, type, fn, unsupported) { | |
| 3521 | + if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); | |
| 3522 | + | |
| 3523 | + // Do not add event handlers to non-elements because they will not be cleaned up. | |
| 3524 | + if (!jqLiteAcceptsData(element)) { | |
| 3525 | + return; | |
| 3526 | + } | |
| 3527 | + | |
| 3528 | + var expandoStore = jqLiteExpandoStore(element, true); | |
| 3529 | + var events = expandoStore.events; | |
| 3530 | + var handle = expandoStore.handle; | |
| 3531 | + | |
| 3532 | + if (!handle) { | |
| 3533 | + handle = expandoStore.handle = createEventHandler(element, events); | |
| 3534 | + } | |
| 3535 | + | |
| 3536 | + // http://jsperf.com/string-indexof-vs-split | |
| 3537 | + var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; | |
| 3538 | + var i = types.length; | |
| 3539 | + | |
| 3540 | + var addHandler = function(type, specialHandlerWrapper, noEventListener) { | |
| 3541 | + var eventFns = events[type]; | |
| 3542 | + | |
| 3543 | + if (!eventFns) { | |
| 3544 | + eventFns = events[type] = []; | |
| 3545 | + eventFns.specialHandlerWrapper = specialHandlerWrapper; | |
| 3546 | + if (type !== '$destroy' && !noEventListener) { | |
| 3547 | + addEventListenerFn(element, type, handle); | |
| 3548 | + } | |
| 3549 | + } | |
| 3550 | + | |
| 3551 | + eventFns.push(fn); | |
| 3552 | + }; | |
| 3553 | + | |
| 3554 | + while (i--) { | |
| 3555 | + type = types[i]; | |
| 3556 | + if (MOUSE_EVENT_MAP[type]) { | |
| 3557 | + addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper); | |
| 3558 | + addHandler(type, undefined, true); | |
| 3559 | + } else { | |
| 3560 | + addHandler(type); | |
| 3561 | + } | |
| 3562 | + } | |
| 3563 | + }, | |
| 3564 | + | |
| 3565 | + off: jqLiteOff, | |
| 3566 | + | |
| 3567 | + one: function(element, type, fn) { | |
| 3568 | + element = jqLite(element); | |
| 3569 | + | |
| 3570 | + //add the listener twice so that when it is called | |
| 3571 | + //you can remove the original function and still be | |
| 3572 | + //able to call element.off(ev, fn) normally | |
| 3573 | + element.on(type, function onFn() { | |
| 3574 | + element.off(type, fn); | |
| 3575 | + element.off(type, onFn); | |
| 3576 | + }); | |
| 3577 | + element.on(type, fn); | |
| 3578 | + }, | |
| 3579 | + | |
| 3580 | + replaceWith: function(element, replaceNode) { | |
| 3581 | + var index, parent = element.parentNode; | |
| 3582 | + jqLiteDealoc(element); | |
| 3583 | + forEach(new JQLite(replaceNode), function(node) { | |
| 3584 | + if (index) { | |
| 3585 | + parent.insertBefore(node, index.nextSibling); | |
| 3586 | + } else { | |
| 3587 | + parent.replaceChild(node, element); | |
| 3588 | + } | |
| 3589 | + index = node; | |
| 3590 | + }); | |
| 3591 | + }, | |
| 3592 | + | |
| 3593 | + children: function(element) { | |
| 3594 | + var children = []; | |
| 3595 | + forEach(element.childNodes, function(element) { | |
| 3596 | + if (element.nodeType === NODE_TYPE_ELEMENT) { | |
| 3597 | + children.push(element); | |
| 3598 | + } | |
| 3599 | + }); | |
| 3600 | + return children; | |
| 3601 | + }, | |
| 3602 | + | |
| 3603 | + contents: function(element) { | |
| 3604 | + return element.contentDocument || element.childNodes || []; | |
| 3605 | + }, | |
| 3606 | + | |
| 3607 | + append: function(element, node) { | |
| 3608 | + var nodeType = element.nodeType; | |
| 3609 | + if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; | |
| 3610 | + | |
| 3611 | + node = new JQLite(node); | |
| 3612 | + | |
| 3613 | + for (var i = 0, ii = node.length; i < ii; i++) { | |
| 3614 | + var child = node[i]; | |
| 3615 | + element.appendChild(child); | |
| 3616 | + } | |
| 3617 | + }, | |
| 3618 | + | |
| 3619 | + prepend: function(element, node) { | |
| 3620 | + if (element.nodeType === NODE_TYPE_ELEMENT) { | |
| 3621 | + var index = element.firstChild; | |
| 3622 | + forEach(new JQLite(node), function(child) { | |
| 3623 | + element.insertBefore(child, index); | |
| 3624 | + }); | |
| 3625 | + } | |
| 3626 | + }, | |
| 3627 | + | |
| 3628 | + wrap: function(element, wrapNode) { | |
| 3629 | + jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]); | |
| 3630 | + }, | |
| 3631 | + | |
| 3632 | + remove: jqLiteRemove, | |
| 3633 | + | |
| 3634 | + detach: function(element) { | |
| 3635 | + jqLiteRemove(element, true); | |
| 3636 | + }, | |
| 3637 | + | |
| 3638 | + after: function(element, newElement) { | |
| 3639 | + var index = element, parent = element.parentNode; | |
| 3640 | + newElement = new JQLite(newElement); | |
| 3641 | + | |
| 3642 | + for (var i = 0, ii = newElement.length; i < ii; i++) { | |
| 3643 | + var node = newElement[i]; | |
| 3644 | + parent.insertBefore(node, index.nextSibling); | |
| 3645 | + index = node; | |
| 3646 | + } | |
| 3647 | + }, | |
| 3648 | + | |
| 3649 | + addClass: jqLiteAddClass, | |
| 3650 | + removeClass: jqLiteRemoveClass, | |
| 3651 | + | |
| 3652 | + toggleClass: function(element, selector, condition) { | |
| 3653 | + if (selector) { | |
| 3654 | + forEach(selector.split(' '), function(className) { | |
| 3655 | + var classCondition = condition; | |
| 3656 | + if (isUndefined(classCondition)) { | |
| 3657 | + classCondition = !jqLiteHasClass(element, className); | |
| 3658 | + } | |
| 3659 | + (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); | |
| 3660 | + }); | |
| 3661 | + } | |
| 3662 | + }, | |
| 3663 | + | |
| 3664 | + parent: function(element) { | |
| 3665 | + var parent = element.parentNode; | |
| 3666 | + return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; | |
| 3667 | + }, | |
| 3668 | + | |
| 3669 | + next: function(element) { | |
| 3670 | + return element.nextElementSibling; | |
| 3671 | + }, | |
| 3672 | + | |
| 3673 | + find: function(element, selector) { | |
| 3674 | + if (element.getElementsByTagName) { | |
| 3675 | + return element.getElementsByTagName(selector); | |
| 3676 | + } else { | |
| 3677 | + return []; | |
| 3678 | + } | |
| 3679 | + }, | |
| 3680 | + | |
| 3681 | + clone: jqLiteClone, | |
| 3682 | + | |
| 3683 | + triggerHandler: function(element, event, extraParameters) { | |
| 3684 | + | |
| 3685 | + var dummyEvent, eventFnsCopy, handlerArgs; | |
| 3686 | + var eventName = event.type || event; | |
| 3687 | + var expandoStore = jqLiteExpandoStore(element); | |
| 3688 | + var events = expandoStore && expandoStore.events; | |
| 3689 | + var eventFns = events && events[eventName]; | |
| 3690 | + | |
| 3691 | + if (eventFns) { | |
| 3692 | + // Create a dummy event to pass to the handlers | |
| 3693 | + dummyEvent = { | |
| 3694 | + preventDefault: function() { this.defaultPrevented = true; }, | |
| 3695 | + isDefaultPrevented: function() { return this.defaultPrevented === true; }, | |
| 3696 | + stopImmediatePropagation: function() { this.immediatePropagationStopped = true; }, | |
| 3697 | + isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; }, | |
| 3698 | + stopPropagation: noop, | |
| 3699 | + type: eventName, | |
| 3700 | + target: element | |
| 3701 | + }; | |
| 3702 | + | |
| 3703 | + // If a custom event was provided then extend our dummy event with it | |
| 3704 | + if (event.type) { | |
| 3705 | + dummyEvent = extend(dummyEvent, event); | |
| 3706 | + } | |
| 3707 | + | |
| 3708 | + // Copy event handlers in case event handlers array is modified during execution. | |
| 3709 | + eventFnsCopy = shallowCopy(eventFns); | |
| 3710 | + handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent]; | |
| 3711 | + | |
| 3712 | + forEach(eventFnsCopy, function(fn) { | |
| 3713 | + if (!dummyEvent.isImmediatePropagationStopped()) { | |
| 3714 | + fn.apply(element, handlerArgs); | |
| 3715 | + } | |
| 3716 | + }); | |
| 3717 | + } | |
| 3718 | + } | |
| 3719 | +}, function(fn, name) { | |
| 3720 | + /** | |
| 3721 | + * chaining functions | |
| 3722 | + */ | |
| 3723 | + JQLite.prototype[name] = function(arg1, arg2, arg3) { | |
| 3724 | + var value; | |
| 3725 | + | |
| 3726 | + for (var i = 0, ii = this.length; i < ii; i++) { | |
| 3727 | + if (isUndefined(value)) { | |
| 3728 | + value = fn(this[i], arg1, arg2, arg3); | |
| 3729 | + if (isDefined(value)) { | |
| 3730 | + // any function which returns a value needs to be wrapped | |
| 3731 | + value = jqLite(value); | |
| 3732 | + } | |
| 3733 | + } else { | |
| 3734 | + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); | |
| 3735 | + } | |
| 3736 | + } | |
| 3737 | + return isDefined(value) ? value : this; | |
| 3738 | + }; | |
| 3739 | + | |
| 3740 | + // bind legacy bind/unbind to on/off | |
| 3741 | + JQLite.prototype.bind = JQLite.prototype.on; | |
| 3742 | + JQLite.prototype.unbind = JQLite.prototype.off; | |
| 3743 | +}); | |
| 3744 | + | |
| 3745 | + | |
| 3746 | +// Provider for private $$jqLite service | |
| 3747 | +function $$jqLiteProvider() { | |
| 3748 | + this.$get = function $$jqLite() { | |
| 3749 | + return extend(JQLite, { | |
| 3750 | + hasClass: function(node, classes) { | |
| 3751 | + if (node.attr) node = node[0]; | |
| 3752 | + return jqLiteHasClass(node, classes); | |
| 3753 | + }, | |
| 3754 | + addClass: function(node, classes) { | |
| 3755 | + if (node.attr) node = node[0]; | |
| 3756 | + return jqLiteAddClass(node, classes); | |
| 3757 | + }, | |
| 3758 | + removeClass: function(node, classes) { | |
| 3759 | + if (node.attr) node = node[0]; | |
| 3760 | + return jqLiteRemoveClass(node, classes); | |
| 3761 | + } | |
| 3762 | + }); | |
| 3763 | + }; | |
| 3764 | +} | |
| 3765 | + | |
| 3766 | +/** | |
| 3767 | + * Computes a hash of an 'obj'. | |
| 3768 | + * Hash of a: | |
| 3769 | + * string is string | |
| 3770 | + * number is number as string | |
| 3771 | + * object is either result of calling $$hashKey function on the object or uniquely generated id, | |
| 3772 | + * that is also assigned to the $$hashKey property of the object. | |
| 3773 | + * | |
| 3774 | + * @param obj | |
| 3775 | + * @returns {string} hash string such that the same input will have the same hash string. | |
| 3776 | + * The resulting string key is in 'type:hashKey' format. | |
| 3777 | + */ | |
| 3778 | +function hashKey(obj, nextUidFn) { | |
| 3779 | + var key = obj && obj.$$hashKey; | |
| 3780 | + | |
| 3781 | + if (key) { | |
| 3782 | + if (typeof key === 'function') { | |
| 3783 | + key = obj.$$hashKey(); | |
| 3784 | + } | |
| 3785 | + return key; | |
| 3786 | + } | |
| 3787 | + | |
| 3788 | + var objType = typeof obj; | |
| 3789 | + if (objType == 'function' || (objType == 'object' && obj !== null)) { | |
| 3790 | + key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)(); | |
| 3791 | + } else { | |
| 3792 | + key = objType + ':' + obj; | |
| 3793 | + } | |
| 3794 | + | |
| 3795 | + return key; | |
| 3796 | +} | |
| 3797 | + | |
| 3798 | +/** | |
| 3799 | + * HashMap which can use objects as keys | |
| 3800 | + */ | |
| 3801 | +function HashMap(array, isolatedUid) { | |
| 3802 | + if (isolatedUid) { | |
| 3803 | + var uid = 0; | |
| 3804 | + this.nextUid = function() { | |
| 3805 | + return ++uid; | |
| 3806 | + }; | |
| 3807 | + } | |
| 3808 | + forEach(array, this.put, this); | |
| 3809 | +} | |
| 3810 | +HashMap.prototype = { | |
| 3811 | + /** | |
| 3812 | + * Store key value pair | |
| 3813 | + * @param key key to store can be any type | |
| 3814 | + * @param value value to store can be any type | |
| 3815 | + */ | |
| 3816 | + put: function(key, value) { | |
| 3817 | + this[hashKey(key, this.nextUid)] = value; | |
| 3818 | + }, | |
| 3819 | + | |
| 3820 | + /** | |
| 3821 | + * @param key | |
| 3822 | + * @returns {Object} the value for the key | |
| 3823 | + */ | |
| 3824 | + get: function(key) { | |
| 3825 | + return this[hashKey(key, this.nextUid)]; | |
| 3826 | + }, | |
| 3827 | + | |
| 3828 | + /** | |
| 3829 | + * Remove the key/value pair | |
| 3830 | + * @param key | |
| 3831 | + */ | |
| 3832 | + remove: function(key) { | |
| 3833 | + var value = this[key = hashKey(key, this.nextUid)]; | |
| 3834 | + delete this[key]; | |
| 3835 | + return value; | |
| 3836 | + } | |
| 3837 | +}; | |
| 3838 | + | |
| 3839 | +var $$HashMapProvider = [function() { | |
| 3840 | + this.$get = [function() { | |
| 3841 | + return HashMap; | |
| 3842 | + }]; | |
| 3843 | +}]; | |
| 3844 | + | |
| 3845 | +/** | |
| 3846 | + * @ngdoc function | |
| 3847 | + * @module ng | |
| 3848 | + * @name angular.injector | |
| 3849 | + * @kind function | |
| 3850 | + * | |
| 3851 | + * @description | |
| 3852 | + * Creates an injector object that can be used for retrieving services as well as for | |
| 3853 | + * dependency injection (see {@link guide/di dependency injection}). | |
| 3854 | + * | |
| 3855 | + * @param {Array.<string|Function>} modules A list of module functions or their aliases. See | |
| 3856 | + * {@link angular.module}. The `ng` module must be explicitly added. | |
| 3857 | + * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which | |
| 3858 | + * disallows argument name annotation inference. | |
| 3859 | + * @returns {injector} Injector object. See {@link auto.$injector $injector}. | |
| 3860 | + * | |
| 3861 | + * @example | |
| 3862 | + * Typical usage | |
| 3863 | + * ```js | |
| 3864 | + * // create an injector | |
| 3865 | + * var $injector = angular.injector(['ng']); | |
| 3866 | + * | |
| 3867 | + * // use the injector to kick off your application | |
| 3868 | + * // use the type inference to auto inject arguments, or use implicit injection | |
| 3869 | + * $injector.invoke(function($rootScope, $compile, $document) { | |
| 3870 | + * $compile($document)($rootScope); | |
| 3871 | + * $rootScope.$digest(); | |
| 3872 | + * }); | |
| 3873 | + * ``` | |
| 3874 | + * | |
| 3875 | + * Sometimes you want to get access to the injector of a currently running Angular app | |
| 3876 | + * from outside Angular. Perhaps, you want to inject and compile some markup after the | |
| 3877 | + * application has been bootstrapped. You can do this using the extra `injector()` added | |
| 3878 | + * to JQuery/jqLite elements. See {@link angular.element}. | |
| 3879 | + * | |
| 3880 | + * *This is fairly rare but could be the case if a third party library is injecting the | |
| 3881 | + * markup.* | |
| 3882 | + * | |
| 3883 | + * In the following example a new block of HTML containing a `ng-controller` | |
| 3884 | + * directive is added to the end of the document body by JQuery. We then compile and link | |
| 3885 | + * it into the current AngularJS scope. | |
| 3886 | + * | |
| 3887 | + * ```js | |
| 3888 | + * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>'); | |
| 3889 | + * $(document.body).append($div); | |
| 3890 | + * | |
| 3891 | + * angular.element(document).injector().invoke(function($compile) { | |
| 3892 | + * var scope = angular.element($div).scope(); | |
| 3893 | + * $compile($div)(scope); | |
| 3894 | + * }); | |
| 3895 | + * ``` | |
| 3896 | + */ | |
| 3897 | + | |
| 3898 | + | |
| 3899 | +/** | |
| 3900 | + * @ngdoc module | |
| 3901 | + * @name auto | |
| 3902 | + * @installation | |
| 3903 | + * @description | |
| 3904 | + * | |
| 3905 | + * Implicit module which gets automatically added to each {@link auto.$injector $injector}. | |
| 3906 | + */ | |
| 3907 | + | |
| 3908 | +var ARROW_ARG = /^([^\(]+?)=>/; | |
| 3909 | +var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m; | |
| 3910 | +var FN_ARG_SPLIT = /,/; | |
| 3911 | +var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; | |
| 3912 | +var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | |
| 3913 | +var $injectorMinErr = minErr('$injector'); | |
| 3914 | + | |
| 3915 | +function stringifyFn(fn) { | |
| 3916 | + // Support: Chrome 50-51 only | |
| 3917 | + // Creating a new string by adding `' '` at the end, to hack around some bug in Chrome v50/51 | |
| 3918 | + // (See https://github.com/angular/angular.js/issues/14487.) | |
| 3919 | + // TODO (gkalpak): Remove workaround when Chrome v52 is released | |
| 3920 | + return Function.prototype.toString.call(fn) + ' '; | |
| 3921 | +} | |
| 3922 | + | |
| 3923 | +function extractArgs(fn) { | |
| 3924 | + var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), | |
| 3925 | + args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); | |
| 3926 | + return args; | |
| 3927 | +} | |
| 3928 | + | |
| 3929 | +function anonFn(fn) { | |
| 3930 | + // For anonymous functions, showing at the very least the function signature can help in | |
| 3931 | + // debugging. | |
| 3932 | + var args = extractArgs(fn); | |
| 3933 | + if (args) { | |
| 3934 | + return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; | |
| 3935 | + } | |
| 3936 | + return 'fn'; | |
| 3937 | +} | |
| 3938 | + | |
| 3939 | +function annotate(fn, strictDi, name) { | |
| 3940 | + var $inject, | |
| 3941 | + argDecl, | |
| 3942 | + last; | |
| 3943 | + | |
| 3944 | + if (typeof fn === 'function') { | |
| 3945 | + if (!($inject = fn.$inject)) { | |
| 3946 | + $inject = []; | |
| 3947 | + if (fn.length) { | |
| 3948 | + if (strictDi) { | |
| 3949 | + if (!isString(name) || !name) { | |
| 3950 | + name = fn.name || anonFn(fn); | |
| 3951 | + } | |
| 3952 | + throw $injectorMinErr('strictdi', | |
| 3953 | + '{0} is not using explicit annotation and cannot be invoked in strict mode', name); | |
| 3954 | + } | |
| 3955 | + argDecl = extractArgs(fn); | |
| 3956 | + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { | |
| 3957 | + arg.replace(FN_ARG, function(all, underscore, name) { | |
| 3958 | + $inject.push(name); | |
| 3959 | + }); | |
| 3960 | + }); | |
| 3961 | + } | |
| 3962 | + fn.$inject = $inject; | |
| 3963 | + } | |
| 3964 | + } else if (isArray(fn)) { | |
| 3965 | + last = fn.length - 1; | |
| 3966 | + assertArgFn(fn[last], 'fn'); | |
| 3967 | + $inject = fn.slice(0, last); | |
| 3968 | + } else { | |
| 3969 | + assertArgFn(fn, 'fn', true); | |
| 3970 | + } | |
| 3971 | + return $inject; | |
| 3972 | +} | |
| 3973 | + | |
| 3974 | +/////////////////////////////////////// | |
| 3975 | + | |
| 3976 | +/** | |
| 3977 | + * @ngdoc service | |
| 3978 | + * @name $injector | |
| 3979 | + * | |
| 3980 | + * @description | |
| 3981 | + * | |
| 3982 | + * `$injector` is used to retrieve object instances as defined by | |
| 3983 | + * {@link auto.$provide provider}, instantiate types, invoke methods, | |
| 3984 | + * and load modules. | |
| 3985 | + * | |
| 3986 | + * The following always holds true: | |
| 3987 | + * | |
| 3988 | + * ```js | |
| 3989 | + * var $injector = angular.injector(); | |
| 3990 | + * expect($injector.get('$injector')).toBe($injector); | |
| 3991 | + * expect($injector.invoke(function($injector) { | |
| 3992 | + * return $injector; | |
| 3993 | + * })).toBe($injector); | |
| 3994 | + * ``` | |
| 3995 | + * | |
| 3996 | + * # Injection Function Annotation | |
| 3997 | + * | |
| 3998 | + * JavaScript does not have annotations, and annotations are needed for dependency injection. The | |
| 3999 | + * following are all valid ways of annotating function with injection arguments and are equivalent. | |
| 4000 | + * | |
| 4001 | + * ```js | |
| 4002 | + * // inferred (only works if code not minified/obfuscated) | |
| 4003 | + * $injector.invoke(function(serviceA){}); | |
| 4004 | + * | |
| 4005 | + * // annotated | |
| 4006 | + * function explicit(serviceA) {}; | |
| 4007 | + * explicit.$inject = ['serviceA']; | |
| 4008 | + * $injector.invoke(explicit); | |
| 4009 | + * | |
| 4010 | + * // inline | |
| 4011 | + * $injector.invoke(['serviceA', function(serviceA){}]); | |
| 4012 | + * ``` | |
| 4013 | + * | |
| 4014 | + * ## Inference | |
| 4015 | + * | |
| 4016 | + * In JavaScript calling `toString()` on a function returns the function definition. The definition | |
| 4017 | + * can then be parsed and the function arguments can be extracted. This method of discovering | |
| 4018 | + * annotations is disallowed when the injector is in strict mode. | |
| 4019 | + * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the | |
| 4020 | + * argument names. | |
| 4021 | + * | |
| 4022 | + * ## `$inject` Annotation | |
| 4023 | + * By adding an `$inject` property onto a function the injection parameters can be specified. | |
| 4024 | + * | |
| 4025 | + * ## Inline | |
| 4026 | + * As an array of injection names, where the last item in the array is the function to call. | |
| 4027 | + */ | |
| 4028 | + | |
| 4029 | +/** | |
| 4030 | + * @ngdoc method | |
| 4031 | + * @name $injector#get | |
| 4032 | + * | |
| 4033 | + * @description | |
| 4034 | + * Return an instance of the service. | |
| 4035 | + * | |
| 4036 | + * @param {string} name The name of the instance to retrieve. | |
| 4037 | + * @param {string=} caller An optional string to provide the origin of the function call for error messages. | |
| 4038 | + * @return {*} The instance. | |
| 4039 | + */ | |
| 4040 | + | |
| 4041 | +/** | |
| 4042 | + * @ngdoc method | |
| 4043 | + * @name $injector#invoke | |
| 4044 | + * | |
| 4045 | + * @description | |
| 4046 | + * Invoke the method and supply the method arguments from the `$injector`. | |
| 4047 | + * | |
| 4048 | + * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are | |
| 4049 | + * injected according to the {@link guide/di $inject Annotation} rules. | |
| 4050 | + * @param {Object=} self The `this` for the invoked method. | |
| 4051 | + * @param {Object=} locals Optional object. If preset then any argument names are read from this | |
| 4052 | + * object first, before the `$injector` is consulted. | |
| 4053 | + * @returns {*} the value returned by the invoked `fn` function. | |
| 4054 | + */ | |
| 4055 | + | |
| 4056 | +/** | |
| 4057 | + * @ngdoc method | |
| 4058 | + * @name $injector#has | |
| 4059 | + * | |
| 4060 | + * @description | |
| 4061 | + * Allows the user to query if the particular service exists. | |
| 4062 | + * | |
| 4063 | + * @param {string} name Name of the service to query. | |
| 4064 | + * @returns {boolean} `true` if injector has given service. | |
| 4065 | + */ | |
| 4066 | + | |
| 4067 | +/** | |
| 4068 | + * @ngdoc method | |
| 4069 | + * @name $injector#instantiate | |
| 4070 | + * @description | |
| 4071 | + * Create a new instance of JS type. The method takes a constructor function, invokes the new | |
| 4072 | + * operator, and supplies all of the arguments to the constructor function as specified by the | |
| 4073 | + * constructor annotation. | |
| 4074 | + * | |
| 4075 | + * @param {Function} Type Annotated constructor function. | |
| 4076 | + * @param {Object=} locals Optional object. If preset then any argument names are read from this | |
| 4077 | + * object first, before the `$injector` is consulted. | |
| 4078 | + * @returns {Object} new instance of `Type`. | |
| 4079 | + */ | |
| 4080 | + | |
| 4081 | +/** | |
| 4082 | + * @ngdoc method | |
| 4083 | + * @name $injector#annotate | |
| 4084 | + * | |
| 4085 | + * @description | |
| 4086 | + * Returns an array of service names which the function is requesting for injection. This API is | |
| 4087 | + * used by the injector to determine which services need to be injected into the function when the | |
| 4088 | + * function is invoked. There are three ways in which the function can be annotated with the needed | |
| 4089 | + * dependencies. | |
| 4090 | + * | |
| 4091 | + * # Argument names | |
| 4092 | + * | |
| 4093 | + * The simplest form is to extract the dependencies from the arguments of the function. This is done | |
| 4094 | + * by converting the function into a string using `toString()` method and extracting the argument | |
| 4095 | + * names. | |
| 4096 | + * ```js | |
| 4097 | + * // Given | |
| 4098 | + * function MyController($scope, $route) { | |
| 4099 | + * // ... | |
| 4100 | + * } | |
| 4101 | + * | |
| 4102 | + * // Then | |
| 4103 | + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); | |
| 4104 | + * ``` | |
| 4105 | + * | |
| 4106 | + * You can disallow this method by using strict injection mode. | |
| 4107 | + * | |
| 4108 | + * This method does not work with code minification / obfuscation. For this reason the following | |
| 4109 | + * annotation strategies are supported. | |
| 4110 | + * | |
| 4111 | + * # The `$inject` property | |
| 4112 | + * | |
| 4113 | + * If a function has an `$inject` property and its value is an array of strings, then the strings | |
| 4114 | + * represent names of services to be injected into the function. | |
| 4115 | + * ```js | |
| 4116 | + * // Given | |
| 4117 | + * var MyController = function(obfuscatedScope, obfuscatedRoute) { | |
| 4118 | + * // ... | |
| 4119 | + * } | |
| 4120 | + * // Define function dependencies | |
| 4121 | + * MyController['$inject'] = ['$scope', '$route']; | |
| 4122 | + * | |
| 4123 | + * // Then | |
| 4124 | + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); | |
| 4125 | + * ``` | |
| 4126 | + * | |
| 4127 | + * # The array notation | |
| 4128 | + * | |
| 4129 | + * It is often desirable to inline Injected functions and that's when setting the `$inject` property | |
| 4130 | + * is very inconvenient. In these situations using the array notation to specify the dependencies in | |
| 4131 | + * a way that survives minification is a better choice: | |
| 4132 | + * | |
| 4133 | + * ```js | |
| 4134 | + * // We wish to write this (not minification / obfuscation safe) | |
| 4135 | + * injector.invoke(function($compile, $rootScope) { | |
| 4136 | + * // ... | |
| 4137 | + * }); | |
| 4138 | + * | |
| 4139 | + * // We are forced to write break inlining | |
| 4140 | + * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) { | |
| 4141 | + * // ... | |
| 4142 | + * }; | |
| 4143 | + * tmpFn.$inject = ['$compile', '$rootScope']; | |
| 4144 | + * injector.invoke(tmpFn); | |
| 4145 | + * | |
| 4146 | + * // To better support inline function the inline annotation is supported | |
| 4147 | + * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) { | |
| 4148 | + * // ... | |
| 4149 | + * }]); | |
| 4150 | + * | |
| 4151 | + * // Therefore | |
| 4152 | + * expect(injector.annotate( | |
| 4153 | + * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}]) | |
| 4154 | + * ).toEqual(['$compile', '$rootScope']); | |
| 4155 | + * ``` | |
| 4156 | + * | |
| 4157 | + * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to | |
| 4158 | + * be retrieved as described above. | |
| 4159 | + * | |
| 4160 | + * @param {boolean=} [strictDi=false] Disallow argument name annotation inference. | |
| 4161 | + * | |
| 4162 | + * @returns {Array.<string>} The names of the services which the function requires. | |
| 4163 | + */ | |
| 4164 | + | |
| 4165 | + | |
| 4166 | + | |
| 4167 | + | |
| 4168 | +/** | |
| 4169 | + * @ngdoc service | |
| 4170 | + * @name $provide | |
| 4171 | + * | |
| 4172 | + * @description | |
| 4173 | + * | |
| 4174 | + * The {@link auto.$provide $provide} service has a number of methods for registering components | |
| 4175 | + * with the {@link auto.$injector $injector}. Many of these functions are also exposed on | |
| 4176 | + * {@link angular.Module}. | |
| 4177 | + * | |
| 4178 | + * An Angular **service** is a singleton object created by a **service factory**. These **service | |
| 4179 | + * factories** are functions which, in turn, are created by a **service provider**. | |
| 4180 | + * The **service providers** are constructor functions. When instantiated they must contain a | |
| 4181 | + * property called `$get`, which holds the **service factory** function. | |
| 4182 | + * | |
| 4183 | + * When you request a service, the {@link auto.$injector $injector} is responsible for finding the | |
| 4184 | + * correct **service provider**, instantiating it and then calling its `$get` **service factory** | |
| 4185 | + * function to get the instance of the **service**. | |
| 4186 | + * | |
| 4187 | + * Often services have no configuration options and there is no need to add methods to the service | |
| 4188 | + * provider. The provider will be no more than a constructor function with a `$get` property. For | |
| 4189 | + * these cases the {@link auto.$provide $provide} service has additional helper methods to register | |
| 4190 | + * services without specifying a provider. | |
| 4191 | + * | |
| 4192 | + * * {@link auto.$provide#provider provider(name, provider)} - registers a **service provider** with the | |
| 4193 | + * {@link auto.$injector $injector} | |
| 4194 | + * * {@link auto.$provide#constant constant(name, obj)} - registers a value/object that can be accessed by | |
| 4195 | + * providers and services. | |
| 4196 | + * * {@link auto.$provide#value value(name, obj)} - registers a value/object that can only be accessed by | |
| 4197 | + * services, not providers. | |
| 4198 | + * * {@link auto.$provide#factory factory(name, fn)} - registers a service **factory function** | |
| 4199 | + * that will be wrapped in a **service provider** object, whose `$get` property will contain the | |
| 4200 | + * given factory function. | |
| 4201 | + * * {@link auto.$provide#service service(name, Fn)} - registers a **constructor function** | |
| 4202 | + * that will be wrapped in a **service provider** object, whose `$get` property will instantiate | |
| 4203 | + * a new object using the given constructor function. | |
| 4204 | + * * {@link auto.$provide#decorator decorator(name, decorFn)} - registers a **decorator function** that | |
| 4205 | + * will be able to modify or replace the implementation of another service. | |
| 4206 | + * | |
| 4207 | + * See the individual methods for more information and examples. | |
| 4208 | + */ | |
| 4209 | + | |
| 4210 | +/** | |
| 4211 | + * @ngdoc method | |
| 4212 | + * @name $provide#provider | |
| 4213 | + * @description | |
| 4214 | + * | |
| 4215 | + * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions | |
| 4216 | + * are constructor functions, whose instances are responsible for "providing" a factory for a | |
| 4217 | + * service. | |
| 4218 | + * | |
| 4219 | + * Service provider names start with the name of the service they provide followed by `Provider`. | |
| 4220 | + * For example, the {@link ng.$log $log} service has a provider called | |
| 4221 | + * {@link ng.$logProvider $logProvider}. | |
| 4222 | + * | |
| 4223 | + * Service provider objects can have additional methods which allow configuration of the provider | |
| 4224 | + * and its service. Importantly, you can configure what kind of service is created by the `$get` | |
| 4225 | + * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a | |
| 4226 | + * method {@link ng.$logProvider#debugEnabled debugEnabled} | |
| 4227 | + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the | |
| 4228 | + * console or not. | |
| 4229 | + * | |
| 4230 | + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + | |
| 4231 | + 'Provider'` key. | |
| 4232 | + * @param {(Object|function())} provider If the provider is: | |
| 4233 | + * | |
| 4234 | + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using | |
| 4235 | + * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created. | |
| 4236 | + * - `Constructor`: a new instance of the provider will be created using | |
| 4237 | + * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`. | |
| 4238 | + * | |
| 4239 | + * @returns {Object} registered provider instance | |
| 4240 | + | |
| 4241 | + * @example | |
| 4242 | + * | |
| 4243 | + * The following example shows how to create a simple event tracking service and register it using | |
| 4244 | + * {@link auto.$provide#provider $provide.provider()}. | |
| 4245 | + * | |
| 4246 | + * ```js | |
| 4247 | + * // Define the eventTracker provider | |
| 4248 | + * function EventTrackerProvider() { | |
| 4249 | + * var trackingUrl = '/track'; | |
| 4250 | + * | |
| 4251 | + * // A provider method for configuring where the tracked events should been saved | |
| 4252 | + * this.setTrackingUrl = function(url) { | |
| 4253 | + * trackingUrl = url; | |
| 4254 | + * }; | |
| 4255 | + * | |
| 4256 | + * // The service factory function | |
| 4257 | + * this.$get = ['$http', function($http) { | |
| 4258 | + * var trackedEvents = {}; | |
| 4259 | + * return { | |
| 4260 | + * // Call this to track an event | |
| 4261 | + * event: function(event) { | |
| 4262 | + * var count = trackedEvents[event] || 0; | |
| 4263 | + * count += 1; | |
| 4264 | + * trackedEvents[event] = count; | |
| 4265 | + * return count; | |
| 4266 | + * }, | |
| 4267 | + * // Call this to save the tracked events to the trackingUrl | |
| 4268 | + * save: function() { | |
| 4269 | + * $http.post(trackingUrl, trackedEvents); | |
| 4270 | + * } | |
| 4271 | + * }; | |
| 4272 | + * }]; | |
| 4273 | + * } | |
| 4274 | + * | |
| 4275 | + * describe('eventTracker', function() { | |
| 4276 | + * var postSpy; | |
| 4277 | + * | |
| 4278 | + * beforeEach(module(function($provide) { | |
| 4279 | + * // Register the eventTracker provider | |
| 4280 | + * $provide.provider('eventTracker', EventTrackerProvider); | |
| 4281 | + * })); | |
| 4282 | + * | |
| 4283 | + * beforeEach(module(function(eventTrackerProvider) { | |
| 4284 | + * // Configure eventTracker provider | |
| 4285 | + * eventTrackerProvider.setTrackingUrl('/custom-track'); | |
| 4286 | + * })); | |
| 4287 | + * | |
| 4288 | + * it('tracks events', inject(function(eventTracker) { | |
| 4289 | + * expect(eventTracker.event('login')).toEqual(1); | |
| 4290 | + * expect(eventTracker.event('login')).toEqual(2); | |
| 4291 | + * })); | |
| 4292 | + * | |
| 4293 | + * it('saves to the tracking url', inject(function(eventTracker, $http) { | |
| 4294 | + * postSpy = spyOn($http, 'post'); | |
| 4295 | + * eventTracker.event('login'); | |
| 4296 | + * eventTracker.save(); | |
| 4297 | + * expect(postSpy).toHaveBeenCalled(); | |
| 4298 | + * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track'); | |
| 4299 | + * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track'); | |
| 4300 | + * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 }); | |
| 4301 | + * })); | |
| 4302 | + * }); | |
| 4303 | + * ``` | |
| 4304 | + */ | |
| 4305 | + | |
| 4306 | +/** | |
| 4307 | + * @ngdoc method | |
| 4308 | + * @name $provide#factory | |
| 4309 | + * @description | |
| 4310 | + * | |
| 4311 | + * Register a **service factory**, which will be called to return the service instance. | |
| 4312 | + * This is short for registering a service where its provider consists of only a `$get` property, | |
| 4313 | + * which is the given service factory function. | |
| 4314 | + * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to | |
| 4315 | + * configure your service in a provider. | |
| 4316 | + * | |
| 4317 | + * @param {string} name The name of the instance. | |
| 4318 | + * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation. | |
| 4319 | + * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`. | |
| 4320 | + * @returns {Object} registered provider instance | |
| 4321 | + * | |
| 4322 | + * @example | |
| 4323 | + * Here is an example of registering a service | |
| 4324 | + * ```js | |
| 4325 | + * $provide.factory('ping', ['$http', function($http) { | |
| 4326 | + * return function ping() { | |
| 4327 | + * return $http.send('/ping'); | |
| 4328 | + * }; | |
| 4329 | + * }]); | |
| 4330 | + * ``` | |
| 4331 | + * You would then inject and use this service like this: | |
| 4332 | + * ```js | |
| 4333 | + * someModule.controller('Ctrl', ['ping', function(ping) { | |
| 4334 | + * ping(); | |
| 4335 | + * }]); | |
| 4336 | + * ``` | |
| 4337 | + */ | |
| 4338 | + | |
| 4339 | + | |
| 4340 | +/** | |
| 4341 | + * @ngdoc method | |
| 4342 | + * @name $provide#service | |
| 4343 | + * @description | |
| 4344 | + * | |
| 4345 | + * Register a **service constructor**, which will be invoked with `new` to create the service | |
| 4346 | + * instance. | |
| 4347 | + * This is short for registering a service where its provider's `$get` property is a factory | |
| 4348 | + * function that returns an instance instantiated by the injector from the service constructor | |
| 4349 | + * function. | |
| 4350 | + * | |
| 4351 | + * Internally it looks a bit like this: | |
| 4352 | + * | |
| 4353 | + * ``` | |
| 4354 | + * { | |
| 4355 | + * $get: function() { | |
| 4356 | + * return $injector.instantiate(constructor); | |
| 4357 | + * } | |
| 4358 | + * } | |
| 4359 | + * ``` | |
| 4360 | + * | |
| 4361 | + * | |
| 4362 | + * You should use {@link auto.$provide#service $provide.service(class)} if you define your service | |
| 4363 | + * as a type/class. | |
| 4364 | + * | |
| 4365 | + * @param {string} name The name of the instance. | |
| 4366 | + * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function) | |
| 4367 | + * that will be instantiated. | |
| 4368 | + * @returns {Object} registered provider instance | |
| 4369 | + * | |
| 4370 | + * @example | |
| 4371 | + * Here is an example of registering a service using | |
| 4372 | + * {@link auto.$provide#service $provide.service(class)}. | |
| 4373 | + * ```js | |
| 4374 | + * var Ping = function($http) { | |
| 4375 | + * this.$http = $http; | |
| 4376 | + * }; | |
| 4377 | + * | |
| 4378 | + * Ping.$inject = ['$http']; | |
| 4379 | + * | |
| 4380 | + * Ping.prototype.send = function() { | |
| 4381 | + * return this.$http.get('/ping'); | |
| 4382 | + * }; | |
| 4383 | + * $provide.service('ping', Ping); | |
| 4384 | + * ``` | |
| 4385 | + * You would then inject and use this service like this: | |
| 4386 | + * ```js | |
| 4387 | + * someModule.controller('Ctrl', ['ping', function(ping) { | |
| 4388 | + * ping.send(); | |
| 4389 | + * }]); | |
| 4390 | + * ``` | |
| 4391 | + */ | |
| 4392 | + | |
| 4393 | + | |
| 4394 | +/** | |
| 4395 | + * @ngdoc method | |
| 4396 | + * @name $provide#value | |
| 4397 | + * @description | |
| 4398 | + * | |
| 4399 | + * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a | |
| 4400 | + * number, an array, an object or a function. This is short for registering a service where its | |
| 4401 | + * provider's `$get` property is a factory function that takes no arguments and returns the **value | |
| 4402 | + * service**. That also means it is not possible to inject other services into a value service. | |
| 4403 | + * | |
| 4404 | + * Value services are similar to constant services, except that they cannot be injected into a | |
| 4405 | + * module configuration function (see {@link angular.Module#config}) but they can be overridden by | |
| 4406 | + * an Angular {@link auto.$provide#decorator decorator}. | |
| 4407 | + * | |
| 4408 | + * @param {string} name The name of the instance. | |
| 4409 | + * @param {*} value The value. | |
| 4410 | + * @returns {Object} registered provider instance | |
| 4411 | + * | |
| 4412 | + * @example | |
| 4413 | + * Here are some examples of creating value services. | |
| 4414 | + * ```js | |
| 4415 | + * $provide.value('ADMIN_USER', 'admin'); | |
| 4416 | + * | |
| 4417 | + * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 }); | |
| 4418 | + * | |
| 4419 | + * $provide.value('halfOf', function(value) { | |
| 4420 | + * return value / 2; | |
| 4421 | + * }); | |
| 4422 | + * ``` | |
| 4423 | + */ | |
| 4424 | + | |
| 4425 | + | |
| 4426 | +/** | |
| 4427 | + * @ngdoc method | |
| 4428 | + * @name $provide#constant | |
| 4429 | + * @description | |
| 4430 | + * | |
| 4431 | + * Register a **constant service** with the {@link auto.$injector $injector}, such as a string, | |
| 4432 | + * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not | |
| 4433 | + * possible to inject other services into a constant. | |
| 4434 | + * | |
| 4435 | + * But unlike {@link auto.$provide#value value}, a constant can be | |
| 4436 | + * injected into a module configuration function (see {@link angular.Module#config}) and it cannot | |
| 4437 | + * be overridden by an Angular {@link auto.$provide#decorator decorator}. | |
| 4438 | + * | |
| 4439 | + * @param {string} name The name of the constant. | |
| 4440 | + * @param {*} value The constant value. | |
| 4441 | + * @returns {Object} registered instance | |
| 4442 | + * | |
| 4443 | + * @example | |
| 4444 | + * Here a some examples of creating constants: | |
| 4445 | + * ```js | |
| 4446 | + * $provide.constant('SHARD_HEIGHT', 306); | |
| 4447 | + * | |
| 4448 | + * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); | |
| 4449 | + * | |
| 4450 | + * $provide.constant('double', function(value) { | |
| 4451 | + * return value * 2; | |
| 4452 | + * }); | |
| 4453 | + * ``` | |
| 4454 | + */ | |
| 4455 | + | |
| 4456 | + | |
| 4457 | +/** | |
| 4458 | + * @ngdoc method | |
| 4459 | + * @name $provide#decorator | |
| 4460 | + * @description | |
| 4461 | + * | |
| 4462 | + * Register a **decorator function** with the {@link auto.$injector $injector}. A decorator function | |
| 4463 | + * intercepts the creation of a service, allowing it to override or modify the behavior of the | |
| 4464 | + * service. The return value of the decorator function may be the original service, or a new service | |
| 4465 | + * that replaces (or wraps and delegates to) the original service. | |
| 4466 | + * | |
| 4467 | + * You can find out more about using decorators in the {@link guide/decorators} guide. | |
| 4468 | + * | |
| 4469 | + * @param {string} name The name of the service to decorate. | |
| 4470 | + * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be | |
| 4471 | + * provided and should return the decorated service instance. The function is called using | |
| 4472 | + * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. | |
| 4473 | + * Local injection arguments: | |
| 4474 | + * | |
| 4475 | + * * `$delegate` - The original service instance, which can be replaced, monkey patched, configured, | |
| 4476 | + * decorated or delegated to. | |
| 4477 | + * | |
| 4478 | + * @example | |
| 4479 | + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting | |
| 4480 | + * calls to {@link ng.$log#error $log.warn()}. | |
| 4481 | + * ```js | |
| 4482 | + * $provide.decorator('$log', ['$delegate', function($delegate) { | |
| 4483 | + * $delegate.warn = $delegate.error; | |
| 4484 | + * return $delegate; | |
| 4485 | + * }]); | |
| 4486 | + * ``` | |
| 4487 | + */ | |
| 4488 | + | |
| 4489 | + | |
| 4490 | +function createInjector(modulesToLoad, strictDi) { | |
| 4491 | + strictDi = (strictDi === true); | |
| 4492 | + var INSTANTIATING = {}, | |
| 4493 | + providerSuffix = 'Provider', | |
| 4494 | + path = [], | |
| 4495 | + loadedModules = new HashMap([], true), | |
| 4496 | + providerCache = { | |
| 4497 | + $provide: { | |
| 4498 | + provider: supportObject(provider), | |
| 4499 | + factory: supportObject(factory), | |
| 4500 | + service: supportObject(service), | |
| 4501 | + value: supportObject(value), | |
| 4502 | + constant: supportObject(constant), | |
| 4503 | + decorator: decorator | |
| 4504 | + } | |
| 4505 | + }, | |
| 4506 | + providerInjector = (providerCache.$injector = | |
| 4507 | + createInternalInjector(providerCache, function(serviceName, caller) { | |
| 4508 | + if (angular.isString(caller)) { | |
| 4509 | + path.push(caller); | |
| 4510 | + } | |
| 4511 | + throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); | |
| 4512 | + })), | |
| 4513 | + instanceCache = {}, | |
| 4514 | + protoInstanceInjector = | |
| 4515 | + createInternalInjector(instanceCache, function(serviceName, caller) { | |
| 4516 | + var provider = providerInjector.get(serviceName + providerSuffix, caller); | |
| 4517 | + return instanceInjector.invoke( | |
| 4518 | + provider.$get, provider, undefined, serviceName); | |
| 4519 | + }), | |
| 4520 | + instanceInjector = protoInstanceInjector; | |
| 4521 | + | |
| 4522 | + providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) }; | |
| 4523 | + var runBlocks = loadModules(modulesToLoad); | |
| 4524 | + instanceInjector = protoInstanceInjector.get('$injector'); | |
| 4525 | + instanceInjector.strictDi = strictDi; | |
| 4526 | + forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); }); | |
| 4527 | + | |
| 4528 | + return instanceInjector; | |
| 4529 | + | |
| 4530 | + //////////////////////////////////// | |
| 4531 | + // $provider | |
| 4532 | + //////////////////////////////////// | |
| 4533 | + | |
| 4534 | + function supportObject(delegate) { | |
| 4535 | + return function(key, value) { | |
| 4536 | + if (isObject(key)) { | |
| 4537 | + forEach(key, reverseParams(delegate)); | |
| 4538 | + } else { | |
| 4539 | + return delegate(key, value); | |
| 4540 | + } | |
| 4541 | + }; | |
| 4542 | + } | |
| 4543 | + | |
| 4544 | + function provider(name, provider_) { | |
| 4545 | + assertNotHasOwnProperty(name, 'service'); | |
| 4546 | + if (isFunction(provider_) || isArray(provider_)) { | |
| 4547 | + provider_ = providerInjector.instantiate(provider_); | |
| 4548 | + } | |
| 4549 | + if (!provider_.$get) { | |
| 4550 | + throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); | |
| 4551 | + } | |
| 4552 | + return providerCache[name + providerSuffix] = provider_; | |
| 4553 | + } | |
| 4554 | + | |
| 4555 | + function enforceReturnValue(name, factory) { | |
| 4556 | + return function enforcedReturnValue() { | |
| 4557 | + var result = instanceInjector.invoke(factory, this); | |
| 4558 | + if (isUndefined(result)) { | |
| 4559 | + throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name); | |
| 4560 | + } | |
| 4561 | + return result; | |
| 4562 | + }; | |
| 4563 | + } | |
| 4564 | + | |
| 4565 | + function factory(name, factoryFn, enforce) { | |
| 4566 | + return provider(name, { | |
| 4567 | + $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn | |
| 4568 | + }); | |
| 4569 | + } | |
| 4570 | + | |
| 4571 | + function service(name, constructor) { | |
| 4572 | + return factory(name, ['$injector', function($injector) { | |
| 4573 | + return $injector.instantiate(constructor); | |
| 4574 | + }]); | |
| 4575 | + } | |
| 4576 | + | |
| 4577 | + function value(name, val) { return factory(name, valueFn(val), false); } | |
| 4578 | + | |
| 4579 | + function constant(name, value) { | |
| 4580 | + assertNotHasOwnProperty(name, 'constant'); | |
| 4581 | + providerCache[name] = value; | |
| 4582 | + instanceCache[name] = value; | |
| 4583 | + } | |
| 4584 | + | |
| 4585 | + function decorator(serviceName, decorFn) { | |
| 4586 | + var origProvider = providerInjector.get(serviceName + providerSuffix), | |
| 4587 | + orig$get = origProvider.$get; | |
| 4588 | + | |
| 4589 | + origProvider.$get = function() { | |
| 4590 | + var origInstance = instanceInjector.invoke(orig$get, origProvider); | |
| 4591 | + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); | |
| 4592 | + }; | |
| 4593 | + } | |
| 4594 | + | |
| 4595 | + //////////////////////////////////// | |
| 4596 | + // Module Loading | |
| 4597 | + //////////////////////////////////// | |
| 4598 | + function loadModules(modulesToLoad) { | |
| 4599 | + assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array'); | |
| 4600 | + var runBlocks = [], moduleFn; | |
| 4601 | + forEach(modulesToLoad, function(module) { | |
| 4602 | + if (loadedModules.get(module)) return; | |
| 4603 | + loadedModules.put(module, true); | |
| 4604 | + | |
| 4605 | + function runInvokeQueue(queue) { | |
| 4606 | + var i, ii; | |
| 4607 | + for (i = 0, ii = queue.length; i < ii; i++) { | |
| 4608 | + var invokeArgs = queue[i], | |
| 4609 | + provider = providerInjector.get(invokeArgs[0]); | |
| 4610 | + | |
| 4611 | + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); | |
| 4612 | + } | |
| 4613 | + } | |
| 4614 | + | |
| 4615 | + try { | |
| 4616 | + if (isString(module)) { | |
| 4617 | + moduleFn = angularModule(module); | |
| 4618 | + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); | |
| 4619 | + runInvokeQueue(moduleFn._invokeQueue); | |
| 4620 | + runInvokeQueue(moduleFn._configBlocks); | |
| 4621 | + } else if (isFunction(module)) { | |
| 4622 | + runBlocks.push(providerInjector.invoke(module)); | |
| 4623 | + } else if (isArray(module)) { | |
| 4624 | + runBlocks.push(providerInjector.invoke(module)); | |
| 4625 | + } else { | |
| 4626 | + assertArgFn(module, 'module'); | |
| 4627 | + } | |
| 4628 | + } catch (e) { | |
| 4629 | + if (isArray(module)) { | |
| 4630 | + module = module[module.length - 1]; | |
| 4631 | + } | |
| 4632 | + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { | |
| 4633 | + // Safari & FF's stack traces don't contain error.message content | |
| 4634 | + // unlike those of Chrome and IE | |
| 4635 | + // So if stack doesn't contain message, we create a new string that contains both. | |
| 4636 | + // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. | |
| 4637 | + /* jshint -W022 */ | |
| 4638 | + e = e.message + '\n' + e.stack; | |
| 4639 | + } | |
| 4640 | + throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", | |
| 4641 | + module, e.stack || e.message || e); | |
| 4642 | + } | |
| 4643 | + }); | |
| 4644 | + return runBlocks; | |
| 4645 | + } | |
| 4646 | + | |
| 4647 | + //////////////////////////////////// | |
| 4648 | + // internal Injector | |
| 4649 | + //////////////////////////////////// | |
| 4650 | + | |
| 4651 | + function createInternalInjector(cache, factory) { | |
| 4652 | + | |
| 4653 | + function getService(serviceName, caller) { | |
| 4654 | + if (cache.hasOwnProperty(serviceName)) { | |
| 4655 | + if (cache[serviceName] === INSTANTIATING) { | |
| 4656 | + throw $injectorMinErr('cdep', 'Circular dependency found: {0}', | |
| 4657 | + serviceName + ' <- ' + path.join(' <- ')); | |
| 4658 | + } | |
| 4659 | + return cache[serviceName]; | |
| 4660 | + } else { | |
| 4661 | + try { | |
| 4662 | + path.unshift(serviceName); | |
| 4663 | + cache[serviceName] = INSTANTIATING; | |
| 4664 | + return cache[serviceName] = factory(serviceName, caller); | |
| 4665 | + } catch (err) { | |
| 4666 | + if (cache[serviceName] === INSTANTIATING) { | |
| 4667 | + delete cache[serviceName]; | |
| 4668 | + } | |
| 4669 | + throw err; | |
| 4670 | + } finally { | |
| 4671 | + path.shift(); | |
| 4672 | + } | |
| 4673 | + } | |
| 4674 | + } | |
| 4675 | + | |
| 4676 | + | |
| 4677 | + function injectionArgs(fn, locals, serviceName) { | |
| 4678 | + var args = [], | |
| 4679 | + $inject = createInjector.$$annotate(fn, strictDi, serviceName); | |
| 4680 | + | |
| 4681 | + for (var i = 0, length = $inject.length; i < length; i++) { | |
| 4682 | + var key = $inject[i]; | |
| 4683 | + if (typeof key !== 'string') { | |
| 4684 | + throw $injectorMinErr('itkn', | |
| 4685 | + 'Incorrect injection token! Expected service name as string, got {0}', key); | |
| 4686 | + } | |
| 4687 | + args.push(locals && locals.hasOwnProperty(key) ? locals[key] : | |
| 4688 | + getService(key, serviceName)); | |
| 4689 | + } | |
| 4690 | + return args; | |
| 4691 | + } | |
| 4692 | + | |
| 4693 | + function isClass(func) { | |
| 4694 | + // IE 9-11 do not support classes and IE9 leaks with the code below. | |
| 4695 | + if (msie <= 11) { | |
| 4696 | + return false; | |
| 4697 | + } | |
| 4698 | + // Support: Edge 12-13 only | |
| 4699 | + // See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6156135/ | |
| 4700 | + return typeof func === 'function' | |
| 4701 | + && /^(?:class\b|constructor\()/.test(stringifyFn(func)); | |
| 4702 | + } | |
| 4703 | + | |
| 4704 | + function invoke(fn, self, locals, serviceName) { | |
| 4705 | + if (typeof locals === 'string') { | |
| 4706 | + serviceName = locals; | |
| 4707 | + locals = null; | |
| 4708 | + } | |
| 4709 | + | |
| 4710 | + var args = injectionArgs(fn, locals, serviceName); | |
| 4711 | + if (isArray(fn)) { | |
| 4712 | + fn = fn[fn.length - 1]; | |
| 4713 | + } | |
| 4714 | + | |
| 4715 | + if (!isClass(fn)) { | |
| 4716 | + // http://jsperf.com/angularjs-invoke-apply-vs-switch | |
| 4717 | + // #5388 | |
| 4718 | + return fn.apply(self, args); | |
| 4719 | + } else { | |
| 4720 | + args.unshift(null); | |
| 4721 | + return new (Function.prototype.bind.apply(fn, args))(); | |
| 4722 | + } | |
| 4723 | + } | |
| 4724 | + | |
| 4725 | + | |
| 4726 | + function instantiate(Type, locals, serviceName) { | |
| 4727 | + // Check if Type is annotated and use just the given function at n-1 as parameter | |
| 4728 | + // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); | |
| 4729 | + var ctor = (isArray(Type) ? Type[Type.length - 1] : Type); | |
| 4730 | + var args = injectionArgs(Type, locals, serviceName); | |
| 4731 | + // Empty object at position 0 is ignored for invocation with `new`, but required. | |
| 4732 | + args.unshift(null); | |
| 4733 | + return new (Function.prototype.bind.apply(ctor, args))(); | |
| 4734 | + } | |
| 4735 | + | |
| 4736 | + | |
| 4737 | + return { | |
| 4738 | + invoke: invoke, | |
| 4739 | + instantiate: instantiate, | |
| 4740 | + get: getService, | |
| 4741 | + annotate: createInjector.$$annotate, | |
| 4742 | + has: function(name) { | |
| 4743 | + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); | |
| 4744 | + } | |
| 4745 | + }; | |
| 4746 | + } | |
| 4747 | +} | |
| 4748 | + | |
| 4749 | +createInjector.$$annotate = annotate; | |
| 4750 | + | |
| 4751 | +/** | |
| 4752 | + * @ngdoc provider | |
| 4753 | + * @name $anchorScrollProvider | |
| 4754 | + * | |
| 4755 | + * @description | |
| 4756 | + * Use `$anchorScrollProvider` to disable automatic scrolling whenever | |
| 4757 | + * {@link ng.$location#hash $location.hash()} changes. | |
| 4758 | + */ | |
| 4759 | +function $AnchorScrollProvider() { | |
| 4760 | + | |
| 4761 | + var autoScrollingEnabled = true; | |
| 4762 | + | |
| 4763 | + /** | |
| 4764 | + * @ngdoc method | |
| 4765 | + * @name $anchorScrollProvider#disableAutoScrolling | |
| 4766 | + * | |
| 4767 | + * @description | |
| 4768 | + * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to | |
| 4769 | + * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br /> | |
| 4770 | + * Use this method to disable automatic scrolling. | |
| 4771 | + * | |
| 4772 | + * If automatic scrolling is disabled, one must explicitly call | |
| 4773 | + * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the | |
| 4774 | + * current hash. | |
| 4775 | + */ | |
| 4776 | + this.disableAutoScrolling = function() { | |
| 4777 | + autoScrollingEnabled = false; | |
| 4778 | + }; | |
| 4779 | + | |
| 4780 | + /** | |
| 4781 | + * @ngdoc service | |
| 4782 | + * @name $anchorScroll | |
| 4783 | + * @kind function | |
| 4784 | + * @requires $window | |
| 4785 | + * @requires $location | |
| 4786 | + * @requires $rootScope | |
| 4787 | + * | |
| 4788 | + * @description | |
| 4789 | + * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the | |
| 4790 | + * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified | |
| 4791 | + * in the | |
| 4792 | + * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#an-indicated-part-of-the-document). | |
| 4793 | + * | |
| 4794 | + * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to | |
| 4795 | + * match any anchor whenever it changes. This can be disabled by calling | |
| 4796 | + * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}. | |
| 4797 | + * | |
| 4798 | + * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a | |
| 4799 | + * vertical scroll-offset (either fixed or dynamic). | |
| 4800 | + * | |
| 4801 | + * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of | |
| 4802 | + * {@link ng.$location#hash $location.hash()} will be used. | |
| 4803 | + * | |
| 4804 | + * @property {(number|function|jqLite)} yOffset | |
| 4805 | + * If set, specifies a vertical scroll-offset. This is often useful when there are fixed | |
| 4806 | + * positioned elements at the top of the page, such as navbars, headers etc. | |
| 4807 | + * | |
| 4808 | + * `yOffset` can be specified in various ways: | |
| 4809 | + * - **number**: A fixed number of pixels to be used as offset.<br /><br /> | |
| 4810 | + * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return | |
| 4811 | + * a number representing the offset (in pixels).<br /><br /> | |
| 4812 | + * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from | |
| 4813 | + * the top of the page to the element's bottom will be used as offset.<br /> | |
| 4814 | + * **Note**: The element will be taken into account only as long as its `position` is set to | |
| 4815 | + * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust | |
| 4816 | + * their height and/or positioning according to the viewport's size. | |
| 4817 | + * | |
| 4818 | + * <br /> | |
| 4819 | + * <div class="alert alert-warning"> | |
| 4820 | + * In order for `yOffset` to work properly, scrolling should take place on the document's root and | |
| 4821 | + * not some child element. | |
| 4822 | + * </div> | |
| 4823 | + * | |
| 4824 | + * @example | |
| 4825 | + <example module="anchorScrollExample"> | |
| 4826 | + <file name="index.html"> | |
| 4827 | + <div id="scrollArea" ng-controller="ScrollController"> | |
| 4828 | + <a ng-click="gotoBottom()">Go to bottom</a> | |
| 4829 | + <a id="bottom"></a> You're at the bottom! | |
| 4830 | + </div> | |
| 4831 | + </file> | |
| 4832 | + <file name="script.js"> | |
| 4833 | + angular.module('anchorScrollExample', []) | |
| 4834 | + .controller('ScrollController', ['$scope', '$location', '$anchorScroll', | |
| 4835 | + function ($scope, $location, $anchorScroll) { | |
| 4836 | + $scope.gotoBottom = function() { | |
| 4837 | + // set the location.hash to the id of | |
| 4838 | + // the element you wish to scroll to. | |
| 4839 | + $location.hash('bottom'); | |
| 4840 | + | |
| 4841 | + // call $anchorScroll() | |
| 4842 | + $anchorScroll(); | |
| 4843 | + }; | |
| 4844 | + }]); | |
| 4845 | + </file> | |
| 4846 | + <file name="style.css"> | |
| 4847 | + #scrollArea { | |
| 4848 | + height: 280px; | |
| 4849 | + overflow: auto; | |
| 4850 | + } | |
| 4851 | + | |
| 4852 | + #bottom { | |
| 4853 | + display: block; | |
| 4854 | + margin-top: 2000px; | |
| 4855 | + } | |
| 4856 | + </file> | |
| 4857 | + </example> | |
| 4858 | + * | |
| 4859 | + * <hr /> | |
| 4860 | + * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value). | |
| 4861 | + * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details. | |
| 4862 | + * | |
| 4863 | + * @example | |
| 4864 | + <example module="anchorScrollOffsetExample"> | |
| 4865 | + <file name="index.html"> | |
| 4866 | + <div class="fixed-header" ng-controller="headerCtrl"> | |
| 4867 | + <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]"> | |
| 4868 | + Go to anchor {{x}} | |
| 4869 | + </a> | |
| 4870 | + </div> | |
| 4871 | + <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]"> | |
| 4872 | + Anchor {{x}} of 5 | |
| 4873 | + </div> | |
| 4874 | + </file> | |
| 4875 | + <file name="script.js"> | |
| 4876 | + angular.module('anchorScrollOffsetExample', []) | |
| 4877 | + .run(['$anchorScroll', function($anchorScroll) { | |
| 4878 | + $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels | |
| 4879 | + }]) | |
| 4880 | + .controller('headerCtrl', ['$anchorScroll', '$location', '$scope', | |
| 4881 | + function ($anchorScroll, $location, $scope) { | |
| 4882 | + $scope.gotoAnchor = function(x) { | |
| 4883 | + var newHash = 'anchor' + x; | |
| 4884 | + if ($location.hash() !== newHash) { | |
| 4885 | + // set the $location.hash to `newHash` and | |
| 4886 | + // $anchorScroll will automatically scroll to it | |
| 4887 | + $location.hash('anchor' + x); | |
| 4888 | + } else { | |
| 4889 | + // call $anchorScroll() explicitly, | |
| 4890 | + // since $location.hash hasn't changed | |
| 4891 | + $anchorScroll(); | |
| 4892 | + } | |
| 4893 | + }; | |
| 4894 | + } | |
| 4895 | + ]); | |
| 4896 | + </file> | |
| 4897 | + <file name="style.css"> | |
| 4898 | + body { | |
| 4899 | + padding-top: 50px; | |
| 4900 | + } | |
| 4901 | + | |
| 4902 | + .anchor { | |
| 4903 | + border: 2px dashed DarkOrchid; | |
| 4904 | + padding: 10px 10px 200px 10px; | |
| 4905 | + } | |
| 4906 | + | |
| 4907 | + .fixed-header { | |
| 4908 | + background-color: rgba(0, 0, 0, 0.2); | |
| 4909 | + height: 50px; | |
| 4910 | + position: fixed; | |
| 4911 | + top: 0; left: 0; right: 0; | |
| 4912 | + } | |
| 4913 | + | |
| 4914 | + .fixed-header > a { | |
| 4915 | + display: inline-block; | |
| 4916 | + margin: 5px 15px; | |
| 4917 | + } | |
| 4918 | + </file> | |
| 4919 | + </example> | |
| 4920 | + */ | |
| 4921 | + this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { | |
| 4922 | + var document = $window.document; | |
| 4923 | + | |
| 4924 | + // Helper function to get first anchor from a NodeList | |
| 4925 | + // (using `Array#some()` instead of `angular#forEach()` since it's more performant | |
| 4926 | + // and working in all supported browsers.) | |
| 4927 | + function getFirstAnchor(list) { | |
| 4928 | + var result = null; | |
| 4929 | + Array.prototype.some.call(list, function(element) { | |
| 4930 | + if (nodeName_(element) === 'a') { | |
| 4931 | + result = element; | |
| 4932 | + return true; | |
| 4933 | + } | |
| 4934 | + }); | |
| 4935 | + return result; | |
| 4936 | + } | |
| 4937 | + | |
| 4938 | + function getYOffset() { | |
| 4939 | + | |
| 4940 | + var offset = scroll.yOffset; | |
| 4941 | + | |
| 4942 | + if (isFunction(offset)) { | |
| 4943 | + offset = offset(); | |
| 4944 | + } else if (isElement(offset)) { | |
| 4945 | + var elem = offset[0]; | |
| 4946 | + var style = $window.getComputedStyle(elem); | |
| 4947 | + if (style.position !== 'fixed') { | |
| 4948 | + offset = 0; | |
| 4949 | + } else { | |
| 4950 | + offset = elem.getBoundingClientRect().bottom; | |
| 4951 | + } | |
| 4952 | + } else if (!isNumber(offset)) { | |
| 4953 | + offset = 0; | |
| 4954 | + } | |
| 4955 | + | |
| 4956 | + return offset; | |
| 4957 | + } | |
| 4958 | + | |
| 4959 | + function scrollTo(elem) { | |
| 4960 | + if (elem) { | |
| 4961 | + elem.scrollIntoView(); | |
| 4962 | + | |
| 4963 | + var offset = getYOffset(); | |
| 4964 | + | |
| 4965 | + if (offset) { | |
| 4966 | + // `offset` is the number of pixels we should scroll UP in order to align `elem` properly. | |
| 4967 | + // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the | |
| 4968 | + // top of the viewport. | |
| 4969 | + // | |
| 4970 | + // IF the number of pixels from the top of `elem` to the end of the page's content is less | |
| 4971 | + // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some | |
| 4972 | + // way down the page. | |
| 4973 | + // | |
| 4974 | + // This is often the case for elements near the bottom of the page. | |
| 4975 | + // | |
| 4976 | + // In such cases we do not need to scroll the whole `offset` up, just the difference between | |
| 4977 | + // the top of the element and the offset, which is enough to align the top of `elem` at the | |
| 4978 | + // desired position. | |
| 4979 | + var elemTop = elem.getBoundingClientRect().top; | |
| 4980 | + $window.scrollBy(0, elemTop - offset); | |
| 4981 | + } | |
| 4982 | + } else { | |
| 4983 | + $window.scrollTo(0, 0); | |
| 4984 | + } | |
| 4985 | + } | |
| 4986 | + | |
| 4987 | + function scroll(hash) { | |
| 4988 | + hash = isString(hash) ? hash : $location.hash(); | |
| 4989 | + var elm; | |
| 4990 | + | |
| 4991 | + // empty hash, scroll to the top of the page | |
| 4992 | + if (!hash) scrollTo(null); | |
| 4993 | + | |
| 4994 | + // element with given id | |
| 4995 | + else if ((elm = document.getElementById(hash))) scrollTo(elm); | |
| 4996 | + | |
| 4997 | + // first anchor with given name :-D | |
| 4998 | + else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm); | |
| 4999 | + | |
26769 more lines aren’t shown here.
| @@ -786,25 +786,25 @@ $.fn.disable = function() { · 785 unmodified lines | ||
| 786 | 786 | |
| 787 | 787 | $.fn.visible = function() { |
| 788 | 788 | return this.each(function() { |
| 789 | − this.css("visibility", "visible"); | |
| 789 | + $(this).css("visibility", "visible"); | |
| 790 | 790 | }); |
| 791 | 791 | } |
| 792 | 792 | |
| 793 | 793 | $.fn.invisible = function() { |
| 794 | 794 | return this.each(function() { |
| 795 | − this.css("visibility", "hidden"); | |
| 795 | + $(this).css("visibility", "hidden"); | |
| 796 | 796 | }); |
| 797 | 797 | } |
| 798 | 798 | |
| 799 | 799 | $.fn.readCookie = function(name) { |
| 800 | − this.val(Cookies.get(name)); | |
| 800 | + $(this).val(Cookies.get(name)); | |
| 801 | 801 | } |
| 802 | 802 | |
| 803 | 803 | $.fn.writeCookie = function(name, expiration) { |
| 804 | 804 | if (expiration) // Date or number of days |
| 805 | − Cookies.set(name, this.val(), { expires: expiration }); | |
| 805 | + Cookies.set(name, $(this).val(), { expires: expiration }); | |
| 806 | 806 | else |
| 807 | − Cookies.set(name, this.val()); | |
| 807 | + Cookies.set(name, $(this).val()); | |
| 808 | 808 | } |
| 809 | 809 | |
| 810 | 810 | $.fn.removeCookie = function(name) { |
| @@ -0,0 +1,16617 @@ | ||
| 1 | +/*! jQuery UI - v1.11.4 - 2016-03-31 | |
| 2 | +* http://jqueryui.com | |
| 3 | +* Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, menu.js, progressbar.js, selectmenu.js, slider.js, spinner.js, tabs.js, tooltip.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js | |
| 4 | +* Copyright jQuery Foundation and other contributors; Licensed MIT */ | |
| 5 | + | |
| 6 | +(function( factory ) { | |
| 7 | + if ( typeof define === "function" && define.amd ) { | |
| 8 | + | |
| 9 | + // AMD. Register as an anonymous module. | |
| 10 | + define([ "jquery" ], factory ); | |
| 11 | + } else { | |
| 12 | + | |
| 13 | + // Browser globals | |
| 14 | + factory( jQuery ); | |
| 15 | + } | |
| 16 | +}(function( $ ) { | |
| 17 | +/*! | |
| 18 | + * jQuery UI Core 1.11.4 | |
| 19 | + * http://jqueryui.com | |
| 20 | + * | |
| 21 | + * Copyright jQuery Foundation and other contributors | |
| 22 | + * Released under the MIT license. | |
| 23 | + * http://jquery.org/license | |
| 24 | + * | |
| 25 | + * http://api.jqueryui.com/category/ui-core/ | |
| 26 | + */ | |
| 27 | + | |
| 28 | + | |
| 29 | +// $.ui might exist from components with no dependencies, e.g., $.ui.position | |
| 30 | +$.ui = $.ui || {}; | |
| 31 | + | |
| 32 | +$.extend( $.ui, { | |
| 33 | + version: "1.11.4", | |
| 34 | + | |
| 35 | + keyCode: { | |
| 36 | + BACKSPACE: 8, | |
| 37 | + COMMA: 188, | |
| 38 | + DELETE: 46, | |
| 39 | + DOWN: 40, | |
| 40 | + END: 35, | |
| 41 | + ENTER: 13, | |
| 42 | + ESCAPE: 27, | |
| 43 | + HOME: 36, | |
| 44 | + LEFT: 37, | |
| 45 | + PAGE_DOWN: 34, | |
| 46 | + PAGE_UP: 33, | |
| 47 | + PERIOD: 190, | |
| 48 | + RIGHT: 39, | |
| 49 | + SPACE: 32, | |
| 50 | + TAB: 9, | |
| 51 | + UP: 38 | |
| 52 | + } | |
| 53 | +}); | |
| 54 | + | |
| 55 | +// plugins | |
| 56 | +$.fn.extend({ | |
| 57 | + scrollParent: function( includeHidden ) { | |
| 58 | + var position = this.css( "position" ), | |
| 59 | + excludeStaticParent = position === "absolute", | |
| 60 | + overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, | |
| 61 | + scrollParent = this.parents().filter( function() { | |
| 62 | + var parent = $( this ); | |
| 63 | + if ( excludeStaticParent && parent.css( "position" ) === "static" ) { | |
| 64 | + return false; | |
| 65 | + } | |
| 66 | + return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) ); | |
| 67 | + }).eq( 0 ); | |
| 68 | + | |
| 69 | + return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent; | |
| 70 | + }, | |
| 71 | + | |
| 72 | + uniqueId: (function() { | |
| 73 | + var uuid = 0; | |
| 74 | + | |
| 75 | + return function() { | |
| 76 | + return this.each(function() { | |
| 77 | + if ( !this.id ) { | |
| 78 | + this.id = "ui-id-" + ( ++uuid ); | |
| 79 | + } | |
| 80 | + }); | |
| 81 | + }; | |
| 82 | + })(), | |
| 83 | + | |
| 84 | + removeUniqueId: function() { | |
| 85 | + return this.each(function() { | |
| 86 | + if ( /^ui-id-\d+$/.test( this.id ) ) { | |
| 87 | + $( this ).removeAttr( "id" ); | |
| 88 | + } | |
| 89 | + }); | |
| 90 | + } | |
| 91 | +}); | |
| 92 | + | |
| 93 | +// selectors | |
| 94 | +function focusable( element, isTabIndexNotNaN ) { | |
| 95 | + var map, mapName, img, | |
| 96 | + nodeName = element.nodeName.toLowerCase(); | |
| 97 | + if ( "area" === nodeName ) { | |
| 98 | + map = element.parentNode; | |
| 99 | + mapName = map.name; | |
| 100 | + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { | |
| 101 | + return false; | |
| 102 | + } | |
| 103 | + img = $( "img[usemap='#" + mapName + "']" )[ 0 ]; | |
| 104 | + return !!img && visible( img ); | |
| 105 | + } | |
| 106 | + return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ? | |
| 107 | + !element.disabled : | |
| 108 | + "a" === nodeName ? | |
| 109 | + element.href || isTabIndexNotNaN : | |
| 110 | + isTabIndexNotNaN) && | |
| 111 | + // the element and all of its ancestors must be visible | |
| 112 | + visible( element ); | |
| 113 | +} | |
| 114 | + | |
| 115 | +function visible( element ) { | |
| 116 | + return $.expr.filters.visible( element ) && | |
| 117 | + !$( element ).parents().addBack().filter(function() { | |
| 118 | + return $.css( this, "visibility" ) === "hidden"; | |
| 119 | + }).length; | |
| 120 | +} | |
| 121 | + | |
| 122 | +$.extend( $.expr[ ":" ], { | |
| 123 | + data: $.expr.createPseudo ? | |
| 124 | + $.expr.createPseudo(function( dataName ) { | |
| 125 | + return function( elem ) { | |
| 126 | + return !!$.data( elem, dataName ); | |
| 127 | + }; | |
| 128 | + }) : | |
| 129 | + // support: jQuery <1.8 | |
| 130 | + function( elem, i, match ) { | |
| 131 | + return !!$.data( elem, match[ 3 ] ); | |
| 132 | + }, | |
| 133 | + | |
| 134 | + focusable: function( element ) { | |
| 135 | + return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); | |
| 136 | + }, | |
| 137 | + | |
| 138 | + tabbable: function( element ) { | |
| 139 | + var tabIndex = $.attr( element, "tabindex" ), | |
| 140 | + isTabIndexNaN = isNaN( tabIndex ); | |
| 141 | + return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); | |
| 142 | + } | |
| 143 | +}); | |
| 144 | + | |
| 145 | +// support: jQuery <1.8 | |
| 146 | +if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { | |
| 147 | + $.each( [ "Width", "Height" ], function( i, name ) { | |
| 148 | + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], | |
| 149 | + type = name.toLowerCase(), | |
| 150 | + orig = { | |
| 151 | + innerWidth: $.fn.innerWidth, | |
| 152 | + innerHeight: $.fn.innerHeight, | |
| 153 | + outerWidth: $.fn.outerWidth, | |
| 154 | + outerHeight: $.fn.outerHeight | |
| 155 | + }; | |
| 156 | + | |
| 157 | + function reduce( elem, size, border, margin ) { | |
| 158 | + $.each( side, function() { | |
| 159 | + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; | |
| 160 | + if ( border ) { | |
| 161 | + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; | |
| 162 | + } | |
| 163 | + if ( margin ) { | |
| 164 | + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; | |
| 165 | + } | |
| 166 | + }); | |
| 167 | + return size; | |
| 168 | + } | |
| 169 | + | |
| 170 | + $.fn[ "inner" + name ] = function( size ) { | |
| 171 | + if ( size === undefined ) { | |
| 172 | + return orig[ "inner" + name ].call( this ); | |
| 173 | + } | |
| 174 | + | |
| 175 | + return this.each(function() { | |
| 176 | + $( this ).css( type, reduce( this, size ) + "px" ); | |
| 177 | + }); | |
| 178 | + }; | |
| 179 | + | |
| 180 | + $.fn[ "outer" + name] = function( size, margin ) { | |
| 181 | + if ( typeof size !== "number" ) { | |
| 182 | + return orig[ "outer" + name ].call( this, size ); | |
| 183 | + } | |
| 184 | + | |
| 185 | + return this.each(function() { | |
| 186 | + $( this).css( type, reduce( this, size, true, margin ) + "px" ); | |
| 187 | + }); | |
| 188 | + }; | |
| 189 | + }); | |
| 190 | +} | |
| 191 | + | |
| 192 | +// support: jQuery <1.8 | |
| 193 | +if ( !$.fn.addBack ) { | |
| 194 | + $.fn.addBack = function( selector ) { | |
| 195 | + return this.add( selector == null ? | |
| 196 | + this.prevObject : this.prevObject.filter( selector ) | |
| 197 | + ); | |
| 198 | + }; | |
| 199 | +} | |
| 200 | + | |
| 201 | +// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) | |
| 202 | +if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { | |
| 203 | + $.fn.removeData = (function( removeData ) { | |
| 204 | + return function( key ) { | |
| 205 | + if ( arguments.length ) { | |
| 206 | + return removeData.call( this, $.camelCase( key ) ); | |
| 207 | + } else { | |
| 208 | + return removeData.call( this ); | |
| 209 | + } | |
| 210 | + }; | |
| 211 | + })( $.fn.removeData ); | |
| 212 | +} | |
| 213 | + | |
| 214 | +// deprecated | |
| 215 | +$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); | |
| 216 | + | |
| 217 | +$.fn.extend({ | |
| 218 | + focus: (function( orig ) { | |
| 219 | + return function( delay, fn ) { | |
| 220 | + return typeof delay === "number" ? | |
| 221 | + this.each(function() { | |
| 222 | + var elem = this; | |
| 223 | + setTimeout(function() { | |
| 224 | + $( elem ).focus(); | |
| 225 | + if ( fn ) { | |
| 226 | + fn.call( elem ); | |
| 227 | + } | |
| 228 | + }, delay ); | |
| 229 | + }) : | |
| 230 | + orig.apply( this, arguments ); | |
| 231 | + }; | |
| 232 | + })( $.fn.focus ), | |
| 233 | + | |
| 234 | + disableSelection: (function() { | |
| 235 | + var eventType = "onselectstart" in document.createElement( "div" ) ? | |
| 236 | + "selectstart" : | |
| 237 | + "mousedown"; | |
| 238 | + | |
| 239 | + return function() { | |
| 240 | + return this.bind( eventType + ".ui-disableSelection", function( event ) { | |
| 241 | + event.preventDefault(); | |
| 242 | + }); | |
| 243 | + }; | |
| 244 | + })(), | |
| 245 | + | |
| 246 | + enableSelection: function() { | |
| 247 | + return this.unbind( ".ui-disableSelection" ); | |
| 248 | + }, | |
| 249 | + | |
| 250 | + zIndex: function( zIndex ) { | |
| 251 | + if ( zIndex !== undefined ) { | |
| 252 | + return this.css( "zIndex", zIndex ); | |
| 253 | + } | |
| 254 | + | |
| 255 | + if ( this.length ) { | |
| 256 | + var elem = $( this[ 0 ] ), position, value; | |
| 257 | + while ( elem.length && elem[ 0 ] !== document ) { | |
| 258 | + // Ignore z-index if position is set to a value where z-index is ignored by the browser | |
| 259 | + // This makes behavior of this function consistent across browsers | |
| 260 | + // WebKit always returns auto if the element is positioned | |
| 261 | + position = elem.css( "position" ); | |
| 262 | + if ( position === "absolute" || position === "relative" || position === "fixed" ) { | |
| 263 | + // IE returns 0 when zIndex is not specified | |
| 264 | + // other browsers return a string | |
| 265 | + // we ignore the case of nested elements with an explicit value of 0 | |
| 266 | + // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> | |
| 267 | + value = parseInt( elem.css( "zIndex" ), 10 ); | |
| 268 | + if ( !isNaN( value ) && value !== 0 ) { | |
| 269 | + return value; | |
| 270 | + } | |
| 271 | + } | |
| 272 | + elem = elem.parent(); | |
| 273 | + } | |
| 274 | + } | |
| 275 | + | |
| 276 | + return 0; | |
| 277 | + } | |
| 278 | +}); | |
| 279 | + | |
| 280 | +// $.ui.plugin is deprecated. Use $.widget() extensions instead. | |
| 281 | +$.ui.plugin = { | |
| 282 | + add: function( module, option, set ) { | |
| 283 | + var i, | |
| 284 | + proto = $.ui[ module ].prototype; | |
| 285 | + for ( i in set ) { | |
| 286 | + proto.plugins[ i ] = proto.plugins[ i ] || []; | |
| 287 | + proto.plugins[ i ].push( [ option, set[ i ] ] ); | |
| 288 | + } | |
| 289 | + }, | |
| 290 | + call: function( instance, name, args, allowDisconnected ) { | |
| 291 | + var i, | |
| 292 | + set = instance.plugins[ name ]; | |
| 293 | + | |
| 294 | + if ( !set ) { | |
| 295 | + return; | |
| 296 | + } | |
| 297 | + | |
| 298 | + if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) { | |
| 299 | + return; | |
| 300 | + } | |
| 301 | + | |
| 302 | + for ( i = 0; i < set.length; i++ ) { | |
| 303 | + if ( instance.options[ set[ i ][ 0 ] ] ) { | |
| 304 | + set[ i ][ 1 ].apply( instance.element, args ); | |
| 305 | + } | |
| 306 | + } | |
| 307 | + } | |
| 308 | +}; | |
| 309 | + | |
| 310 | + | |
| 311 | +/*! | |
| 312 | + * jQuery UI Widget 1.11.4 | |
| 313 | + * http://jqueryui.com | |
| 314 | + * | |
| 315 | + * Copyright jQuery Foundation and other contributors | |
| 316 | + * Released under the MIT license. | |
| 317 | + * http://jquery.org/license | |
| 318 | + * | |
| 319 | + * http://api.jqueryui.com/jQuery.widget/ | |
| 320 | + */ | |
| 321 | + | |
| 322 | + | |
| 323 | +var widget_uuid = 0, | |
| 324 | + widget_slice = Array.prototype.slice; | |
| 325 | + | |
| 326 | +$.cleanData = (function( orig ) { | |
| 327 | + return function( elems ) { | |
| 328 | + var events, elem, i; | |
| 329 | + for ( i = 0; (elem = elems[i]) != null; i++ ) { | |
| 330 | + try { | |
| 331 | + | |
| 332 | + // Only trigger remove when necessary to save time | |
| 333 | + events = $._data( elem, "events" ); | |
| 334 | + if ( events && events.remove ) { | |
| 335 | + $( elem ).triggerHandler( "remove" ); | |
| 336 | + } | |
| 337 | + | |
| 338 | + // http://bugs.jquery.com/ticket/8235 | |
| 339 | + } catch ( e ) {} | |
| 340 | + } | |
| 341 | + orig( elems ); | |
| 342 | + }; | |
| 343 | +})( $.cleanData ); | |
| 344 | + | |
| 345 | +$.widget = function( name, base, prototype ) { | |
| 346 | + var fullName, existingConstructor, constructor, basePrototype, | |
| 347 | + // proxiedPrototype allows the provided prototype to remain unmodified | |
| 348 | + // so that it can be used as a mixin for multiple widgets (#8876) | |
| 349 | + proxiedPrototype = {}, | |
| 350 | + namespace = name.split( "." )[ 0 ]; | |
| 351 | + | |
| 352 | + name = name.split( "." )[ 1 ]; | |
| 353 | + fullName = namespace + "-" + name; | |
| 354 | + | |
| 355 | + if ( !prototype ) { | |
| 356 | + prototype = base; | |
| 357 | + base = $.Widget; | |
| 358 | + } | |
| 359 | + | |
| 360 | + // create selector for plugin | |
| 361 | + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { | |
| 362 | + return !!$.data( elem, fullName ); | |
| 363 | + }; | |
| 364 | + | |
| 365 | + $[ namespace ] = $[ namespace ] || {}; | |
| 366 | + existingConstructor = $[ namespace ][ name ]; | |
| 367 | + constructor = $[ namespace ][ name ] = function( options, element ) { | |
| 368 | + // allow instantiation without "new" keyword | |
| 369 | + if ( !this._createWidget ) { | |
| 370 | + return new constructor( options, element ); | |
| 371 | + } | |
| 372 | + | |
| 373 | + // allow instantiation without initializing for simple inheritance | |
| 374 | + // must use "new" keyword (the code above always passes args) | |
| 375 | + if ( arguments.length ) { | |
| 376 | + this._createWidget( options, element ); | |
| 377 | + } | |
| 378 | + }; | |
| 379 | + // extend with the existing constructor to carry over any static properties | |
| 380 | + $.extend( constructor, existingConstructor, { | |
| 381 | + version: prototype.version, | |
| 382 | + // copy the object used to create the prototype in case we need to | |
| 383 | + // redefine the widget later | |
| 384 | + _proto: $.extend( {}, prototype ), | |
| 385 | + // track widgets that inherit from this widget in case this widget is | |
| 386 | + // redefined after a widget inherits from it | |
| 387 | + _childConstructors: [] | |
| 388 | + }); | |
| 389 | + | |
| 390 | + basePrototype = new base(); | |
| 391 | + // we need to make the options hash a property directly on the new instance | |
| 392 | + // otherwise we'll modify the options hash on the prototype that we're | |
| 393 | + // inheriting from | |
| 394 | + basePrototype.options = $.widget.extend( {}, basePrototype.options ); | |
| 395 | + $.each( prototype, function( prop, value ) { | |
| 396 | + if ( !$.isFunction( value ) ) { | |
| 397 | + proxiedPrototype[ prop ] = value; | |
| 398 | + return; | |
| 399 | + } | |
| 400 | + proxiedPrototype[ prop ] = (function() { | |
| 401 | + var _super = function() { | |
| 402 | + return base.prototype[ prop ].apply( this, arguments ); | |
| 403 | + }, | |
| 404 | + _superApply = function( args ) { | |
| 405 | + return base.prototype[ prop ].apply( this, args ); | |
| 406 | + }; | |
| 407 | + return function() { | |
| 408 | + var __super = this._super, | |
| 409 | + __superApply = this._superApply, | |
| 410 | + returnValue; | |
| 411 | + | |
| 412 | + this._super = _super; | |
| 413 | + this._superApply = _superApply; | |
| 414 | + | |
| 415 | + returnValue = value.apply( this, arguments ); | |
| 416 | + | |
| 417 | + this._super = __super; | |
| 418 | + this._superApply = __superApply; | |
| 419 | + | |
| 420 | + return returnValue; | |
| 421 | + }; | |
| 422 | + })(); | |
| 423 | + }); | |
| 424 | + constructor.prototype = $.widget.extend( basePrototype, { | |
| 425 | + // TODO: remove support for widgetEventPrefix | |
| 426 | + // always use the name + a colon as the prefix, e.g., draggable:start | |
| 427 | + // don't prefix for widgets that aren't DOM-based | |
| 428 | + widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name | |
| 429 | + }, proxiedPrototype, { | |
| 430 | + constructor: constructor, | |
| 431 | + namespace: namespace, | |
| 432 | + widgetName: name, | |
| 433 | + widgetFullName: fullName | |
| 434 | + }); | |
| 435 | + | |
| 436 | + // If this widget is being redefined then we need to find all widgets that | |
| 437 | + // are inheriting from it and redefine all of them so that they inherit from | |
| 438 | + // the new version of this widget. We're essentially trying to replace one | |
| 439 | + // level in the prototype chain. | |
| 440 | + if ( existingConstructor ) { | |
| 441 | + $.each( existingConstructor._childConstructors, function( i, child ) { | |
| 442 | + var childPrototype = child.prototype; | |
| 443 | + | |
| 444 | + // redefine the child widget using the same prototype that was | |
| 445 | + // originally used, but inherit from the new version of the base | |
| 446 | + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); | |
| 447 | + }); | |
| 448 | + // remove the list of existing child constructors from the old constructor | |
| 449 | + // so the old child constructors can be garbage collected | |
| 450 | + delete existingConstructor._childConstructors; | |
| 451 | + } else { | |
| 452 | + base._childConstructors.push( constructor ); | |
| 453 | + } | |
| 454 | + | |
| 455 | + $.widget.bridge( name, constructor ); | |
| 456 | + | |
| 457 | + return constructor; | |
| 458 | +}; | |
| 459 | + | |
| 460 | +$.widget.extend = function( target ) { | |
| 461 | + var input = widget_slice.call( arguments, 1 ), | |
| 462 | + inputIndex = 0, | |
| 463 | + inputLength = input.length, | |
| 464 | + key, | |
| 465 | + value; | |
| 466 | + for ( ; inputIndex < inputLength; inputIndex++ ) { | |
| 467 | + for ( key in input[ inputIndex ] ) { | |
| 468 | + value = input[ inputIndex ][ key ]; | |
| 469 | + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { | |
| 470 | + // Clone objects | |
| 471 | + if ( $.isPlainObject( value ) ) { | |
| 472 | + target[ key ] = $.isPlainObject( target[ key ] ) ? | |
| 473 | + $.widget.extend( {}, target[ key ], value ) : | |
| 474 | + // Don't extend strings, arrays, etc. with objects | |
| 475 | + $.widget.extend( {}, value ); | |
| 476 | + // Copy everything else by reference | |
| 477 | + } else { | |
| 478 | + target[ key ] = value; | |
| 479 | + } | |
| 480 | + } | |
| 481 | + } | |
| 482 | + } | |
| 483 | + return target; | |
| 484 | +}; | |
| 485 | + | |
| 486 | +$.widget.bridge = function( name, object ) { | |
| 487 | + var fullName = object.prototype.widgetFullName || name; | |
| 488 | + $.fn[ name ] = function( options ) { | |
| 489 | + var isMethodCall = typeof options === "string", | |
| 490 | + args = widget_slice.call( arguments, 1 ), | |
| 491 | + returnValue = this; | |
| 492 | + | |
| 493 | + if ( isMethodCall ) { | |
| 494 | + this.each(function() { | |
| 495 | + var methodValue, | |
| 496 | + instance = $.data( this, fullName ); | |
| 497 | + if ( options === "instance" ) { | |
| 498 | + returnValue = instance; | |
| 499 | + return false; | |
| 500 | + } | |
| 501 | + if ( !instance ) { | |
| 502 | + return $.error( "cannot call methods on " + name + " prior to initialization; " + | |
| 503 | + "attempted to call method '" + options + "'" ); | |
| 504 | + } | |
| 505 | + if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { | |
| 506 | + return $.error( "no such method '" + options + "' for " + name + " widget instance" ); | |
| 507 | + } | |
| 508 | + methodValue = instance[ options ].apply( instance, args ); | |
| 509 | + if ( methodValue !== instance && methodValue !== undefined ) { | |
| 510 | + returnValue = methodValue && methodValue.jquery ? | |
| 511 | + returnValue.pushStack( methodValue.get() ) : | |
| 512 | + methodValue; | |
| 513 | + return false; | |
| 514 | + } | |
| 515 | + }); | |
| 516 | + } else { | |
| 517 | + | |
| 518 | + // Allow multiple hashes to be passed on init | |
| 519 | + if ( args.length ) { | |
| 520 | + options = $.widget.extend.apply( null, [ options ].concat(args) ); | |
| 521 | + } | |
| 522 | + | |
| 523 | + this.each(function() { | |
| 524 | + var instance = $.data( this, fullName ); | |
| 525 | + if ( instance ) { | |
| 526 | + instance.option( options || {} ); | |
| 527 | + if ( instance._init ) { | |
| 528 | + instance._init(); | |
| 529 | + } | |
| 530 | + } else { | |
| 531 | + $.data( this, fullName, new object( options, this ) ); | |
| 532 | + } | |
| 533 | + }); | |
| 534 | + } | |
| 535 | + | |
| 536 | + return returnValue; | |
| 537 | + }; | |
| 538 | +}; | |
| 539 | + | |
| 540 | +$.Widget = function( /* options, element */ ) {}; | |
| 541 | +$.Widget._childConstructors = []; | |
| 542 | + | |
| 543 | +$.Widget.prototype = { | |
| 544 | + widgetName: "widget", | |
| 545 | + widgetEventPrefix: "", | |
| 546 | + defaultElement: "<div>", | |
| 547 | + options: { | |
| 548 | + disabled: false, | |
| 549 | + | |
| 550 | + // callbacks | |
| 551 | + create: null | |
| 552 | + }, | |
| 553 | + _createWidget: function( options, element ) { | |
| 554 | + element = $( element || this.defaultElement || this )[ 0 ]; | |
| 555 | + this.element = $( element ); | |
| 556 | + this.uuid = widget_uuid++; | |
| 557 | + this.eventNamespace = "." + this.widgetName + this.uuid; | |
| 558 | + | |
| 559 | + this.bindings = $(); | |
| 560 | + this.hoverable = $(); | |
| 561 | + this.focusable = $(); | |
| 562 | + | |
| 563 | + if ( element !== this ) { | |
| 564 | + $.data( element, this.widgetFullName, this ); | |
| 565 | + this._on( true, this.element, { | |
| 566 | + remove: function( event ) { | |
| 567 | + if ( event.target === element ) { | |
| 568 | + this.destroy(); | |
| 569 | + } | |
| 570 | + } | |
| 571 | + }); | |
| 572 | + this.document = $( element.style ? | |
| 573 | + // element within the document | |
| 574 | + element.ownerDocument : | |
| 575 | + // element is window or document | |
| 576 | + element.document || element ); | |
| 577 | + this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); | |
| 578 | + } | |
| 579 | + | |
| 580 | + this.options = $.widget.extend( {}, | |
| 581 | + this.options, | |
| 582 | + this._getCreateOptions(), | |
| 583 | + options ); | |
| 584 | + | |
| 585 | + this._create(); | |
| 586 | + this._trigger( "create", null, this._getCreateEventData() ); | |
| 587 | + this._init(); | |
| 588 | + }, | |
| 589 | + _getCreateOptions: $.noop, | |
| 590 | + _getCreateEventData: $.noop, | |
| 591 | + _create: $.noop, | |
| 592 | + _init: $.noop, | |
| 593 | + | |
| 594 | + destroy: function() { | |
| 595 | + this._destroy(); | |
| 596 | + // we can probably remove the unbind calls in 2.0 | |
| 597 | + // all event bindings should go through this._on() | |
| 598 | + this.element | |
| 599 | + .unbind( this.eventNamespace ) | |
| 600 | + .removeData( this.widgetFullName ) | |
| 601 | + // support: jquery <1.6.3 | |
| 602 | + // http://bugs.jquery.com/ticket/9413 | |
| 603 | + .removeData( $.camelCase( this.widgetFullName ) ); | |
| 604 | + this.widget() | |
| 605 | + .unbind( this.eventNamespace ) | |
| 606 | + .removeAttr( "aria-disabled" ) | |
| 607 | + .removeClass( | |
| 608 | + this.widgetFullName + "-disabled " + | |
| 609 | + "ui-state-disabled" ); | |
| 610 | + | |
| 611 | + // clean up events and states | |
| 612 | + this.bindings.unbind( this.eventNamespace ); | |
| 613 | + this.hoverable.removeClass( "ui-state-hover" ); | |
| 614 | + this.focusable.removeClass( "ui-state-focus" ); | |
| 615 | + }, | |
| 616 | + _destroy: $.noop, | |
| 617 | + | |
| 618 | + widget: function() { | |
| 619 | + return this.element; | |
| 620 | + }, | |
| 621 | + | |
| 622 | + option: function( key, value ) { | |
| 623 | + var options = key, | |
| 624 | + parts, | |
| 625 | + curOption, | |
| 626 | + i; | |
| 627 | + | |
| 628 | + if ( arguments.length === 0 ) { | |
| 629 | + // don't return a reference to the internal hash | |
| 630 | + return $.widget.extend( {}, this.options ); | |
| 631 | + } | |
| 632 | + | |
| 633 | + if ( typeof key === "string" ) { | |
| 634 | + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } | |
| 635 | + options = {}; | |
| 636 | + parts = key.split( "." ); | |
| 637 | + key = parts.shift(); | |
| 638 | + if ( parts.length ) { | |
| 639 | + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); | |
| 640 | + for ( i = 0; i < parts.length - 1; i++ ) { | |
| 641 | + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; | |
| 642 | + curOption = curOption[ parts[ i ] ]; | |
| 643 | + } | |
| 644 | + key = parts.pop(); | |
| 645 | + if ( arguments.length === 1 ) { | |
| 646 | + return curOption[ key ] === undefined ? null : curOption[ key ]; | |
| 647 | + } | |
| 648 | + curOption[ key ] = value; | |
| 649 | + } else { | |
| 650 | + if ( arguments.length === 1 ) { | |
| 651 | + return this.options[ key ] === undefined ? null : this.options[ key ]; | |
| 652 | + } | |
| 653 | + options[ key ] = value; | |
| 654 | + } | |
| 655 | + } | |
| 656 | + | |
| 657 | + this._setOptions( options ); | |
| 658 | + | |
| 659 | + return this; | |
| 660 | + }, | |
| 661 | + _setOptions: function( options ) { | |
| 662 | + var key; | |
| 663 | + | |
| 664 | + for ( key in options ) { | |
| 665 | + this._setOption( key, options[ key ] ); | |
| 666 | + } | |
| 667 | + | |
| 668 | + return this; | |
| 669 | + }, | |
| 670 | + _setOption: function( key, value ) { | |
| 671 | + this.options[ key ] = value; | |
| 672 | + | |
| 673 | + if ( key === "disabled" ) { | |
| 674 | + this.widget() | |
| 675 | + .toggleClass( this.widgetFullName + "-disabled", !!value ); | |
| 676 | + | |
| 677 | + // If the widget is becoming disabled, then nothing is interactive | |
| 678 | + if ( value ) { | |
| 679 | + this.hoverable.removeClass( "ui-state-hover" ); | |
| 680 | + this.focusable.removeClass( "ui-state-focus" ); | |
| 681 | + } | |
| 682 | + } | |
| 683 | + | |
| 684 | + return this; | |
| 685 | + }, | |
| 686 | + | |
| 687 | + enable: function() { | |
| 688 | + return this._setOptions({ disabled: false }); | |
| 689 | + }, | |
| 690 | + disable: function() { | |
| 691 | + return this._setOptions({ disabled: true }); | |
| 692 | + }, | |
| 693 | + | |
| 694 | + _on: function( suppressDisabledCheck, element, handlers ) { | |
| 695 | + var delegateElement, | |
| 696 | + instance = this; | |
| 697 | + | |
| 698 | + // no suppressDisabledCheck flag, shuffle arguments | |
| 699 | + if ( typeof suppressDisabledCheck !== "boolean" ) { | |
| 700 | + handlers = element; | |
| 701 | + element = suppressDisabledCheck; | |
| 702 | + suppressDisabledCheck = false; | |
| 703 | + } | |
| 704 | + | |
| 705 | + // no element argument, shuffle and use this.element | |
| 706 | + if ( !handlers ) { | |
| 707 | + handlers = element; | |
| 708 | + element = this.element; | |
| 709 | + delegateElement = this.widget(); | |
| 710 | + } else { | |
| 711 | + element = delegateElement = $( element ); | |
| 712 | + this.bindings = this.bindings.add( element ); | |
| 713 | + } | |
| 714 | + | |
| 715 | + $.each( handlers, function( event, handler ) { | |
| 716 | + function handlerProxy() { | |
| 717 | + // allow widgets to customize the disabled handling | |
| 718 | + // - disabled as an array instead of boolean | |
| 719 | + // - disabled class as method for disabling individual parts | |
| 720 | + if ( !suppressDisabledCheck && | |
| 721 | + ( instance.options.disabled === true || | |
| 722 | + $( this ).hasClass( "ui-state-disabled" ) ) ) { | |
| 723 | + return; | |
| 724 | + } | |
| 725 | + return ( typeof handler === "string" ? instance[ handler ] : handler ) | |
| 726 | + .apply( instance, arguments ); | |
| 727 | + } | |
| 728 | + | |
| 729 | + // copy the guid so direct unbinding works | |
| 730 | + if ( typeof handler !== "string" ) { | |
| 731 | + handlerProxy.guid = handler.guid = | |
| 732 | + handler.guid || handlerProxy.guid || $.guid++; | |
| 733 | + } | |
| 734 | + | |
| 735 | + var match = event.match( /^([\w:-]*)\s*(.*)$/ ), | |
| 736 | + eventName = match[1] + instance.eventNamespace, | |
| 737 | + selector = match[2]; | |
| 738 | + if ( selector ) { | |
| 739 | + delegateElement.delegate( selector, eventName, handlerProxy ); | |
| 740 | + } else { | |
| 741 | + element.bind( eventName, handlerProxy ); | |
| 742 | + } | |
| 743 | + }); | |
| 744 | + }, | |
| 745 | + | |
| 746 | + _off: function( element, eventName ) { | |
| 747 | + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + | |
| 748 | + this.eventNamespace; | |
| 749 | + element.unbind( eventName ).undelegate( eventName ); | |
| 750 | + | |
| 751 | + // Clear the stack to avoid memory leaks (#10056) | |
| 752 | + this.bindings = $( this.bindings.not( element ).get() ); | |
| 753 | + this.focusable = $( this.focusable.not( element ).get() ); | |
| 754 | + this.hoverable = $( this.hoverable.not( element ).get() ); | |
| 755 | + }, | |
| 756 | + | |
| 757 | + _delay: function( handler, delay ) { | |
| 758 | + function handlerProxy() { | |
| 759 | + return ( typeof handler === "string" ? instance[ handler ] : handler ) | |
| 760 | + .apply( instance, arguments ); | |
| 761 | + } | |
| 762 | + var instance = this; | |
| 763 | + return setTimeout( handlerProxy, delay || 0 ); | |
| 764 | + }, | |
| 765 | + | |
| 766 | + _hoverable: function( element ) { | |
| 767 | + this.hoverable = this.hoverable.add( element ); | |
| 768 | + this._on( element, { | |
| 769 | + mouseenter: function( event ) { | |
| 770 | + $( event.currentTarget ).addClass( "ui-state-hover" ); | |
| 771 | + }, | |
| 772 | + mouseleave: function( event ) { | |
| 773 | + $( event.currentTarget ).removeClass( "ui-state-hover" ); | |
| 774 | + } | |
| 775 | + }); | |
| 776 | + }, | |
| 777 | + | |
| 778 | + _focusable: function( element ) { | |
| 779 | + this.focusable = this.focusable.add( element ); | |
| 780 | + this._on( element, { | |
| 781 | + focusin: function( event ) { | |
| 782 | + $( event.currentTarget ).addClass( "ui-state-focus" ); | |
| 783 | + }, | |
| 784 | + focusout: function( event ) { | |
| 785 | + $( event.currentTarget ).removeClass( "ui-state-focus" ); | |
| 786 | + } | |
| 787 | + }); | |
| 788 | + }, | |
| 789 | + | |
| 790 | + _trigger: function( type, event, data ) { | |
| 791 | + var prop, orig, | |
| 792 | + callback = this.options[ type ]; | |
| 793 | + | |
| 794 | + data = data || {}; | |
| 795 | + event = $.Event( event ); | |
| 796 | + event.type = ( type === this.widgetEventPrefix ? | |
| 797 | + type : | |
| 798 | + this.widgetEventPrefix + type ).toLowerCase(); | |
| 799 | + // the original event may come from any element | |
| 800 | + // so we need to reset the target on the new event | |
| 801 | + event.target = this.element[ 0 ]; | |
| 802 | + | |
| 803 | + // copy original event properties over to the new event | |
| 804 | + orig = event.originalEvent; | |
| 805 | + if ( orig ) { | |
| 806 | + for ( prop in orig ) { | |
| 807 | + if ( !( prop in event ) ) { | |
| 808 | + event[ prop ] = orig[ prop ]; | |
| 809 | + } | |
| 810 | + } | |
| 811 | + } | |
| 812 | + | |
| 813 | + this.element.trigger( event, data ); | |
| 814 | + return !( $.isFunction( callback ) && | |
| 815 | + callback.apply( this.element[0], [ event ].concat( data ) ) === false || | |
| 816 | + event.isDefaultPrevented() ); | |
| 817 | + } | |
| 818 | +}; | |
| 819 | + | |
| 820 | +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { | |
| 821 | + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { | |
| 822 | + if ( typeof options === "string" ) { | |
| 823 | + options = { effect: options }; | |
| 824 | + } | |
| 825 | + var hasOptions, | |
| 826 | + effectName = !options ? | |
| 827 | + method : | |
| 828 | + options === true || typeof options === "number" ? | |
| 829 | + defaultEffect : | |
| 830 | + options.effect || defaultEffect; | |
| 831 | + options = options || {}; | |
| 832 | + if ( typeof options === "number" ) { | |
| 833 | + options = { duration: options }; | |
| 834 | + } | |
| 835 | + hasOptions = !$.isEmptyObject( options ); | |
| 836 | + options.complete = callback; | |
| 837 | + if ( options.delay ) { | |
| 838 | + element.delay( options.delay ); | |
| 839 | + } | |
| 840 | + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { | |
| 841 | + element[ method ]( options ); | |
| 842 | + } else if ( effectName !== method && element[ effectName ] ) { | |
| 843 | + element[ effectName ]( options.duration, options.easing, callback ); | |
| 844 | + } else { | |
| 845 | + element.queue(function( next ) { | |
| 846 | + $( this )[ method ](); | |
| 847 | + if ( callback ) { | |
| 848 | + callback.call( element[ 0 ] ); | |
| 849 | + } | |
| 850 | + next(); | |
| 851 | + }); | |
| 852 | + } | |
| 853 | + }; | |
| 854 | +}); | |
| 855 | + | |
| 856 | +var widget = $.widget; | |
| 857 | + | |
| 858 | + | |
| 859 | +/*! | |
| 860 | + * jQuery UI Mouse 1.11.4 | |
| 861 | + * http://jqueryui.com | |
| 862 | + * | |
| 863 | + * Copyright jQuery Foundation and other contributors | |
| 864 | + * Released under the MIT license. | |
| 865 | + * http://jquery.org/license | |
| 866 | + * | |
| 867 | + * http://api.jqueryui.com/mouse/ | |
| 868 | + */ | |
| 869 | + | |
| 870 | + | |
| 871 | +var mouseHandled = false; | |
| 872 | +$( document ).mouseup( function() { | |
| 873 | + mouseHandled = false; | |
| 874 | +}); | |
| 875 | + | |
| 876 | +var mouse = $.widget("ui.mouse", { | |
| 877 | + version: "1.11.4", | |
| 878 | + options: { | |
| 879 | + cancel: "input,textarea,button,select,option", | |
| 880 | + distance: 1, | |
| 881 | + delay: 0 | |
| 882 | + }, | |
| 883 | + _mouseInit: function() { | |
| 884 | + var that = this; | |
| 885 | + | |
| 886 | + this.element | |
| 887 | + .bind("mousedown." + this.widgetName, function(event) { | |
| 888 | + return that._mouseDown(event); | |
| 889 | + }) | |
| 890 | + .bind("click." + this.widgetName, function(event) { | |
| 891 | + if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { | |
| 892 | + $.removeData(event.target, that.widgetName + ".preventClickEvent"); | |
| 893 | + event.stopImmediatePropagation(); | |
| 894 | + return false; | |
| 895 | + } | |
| 896 | + }); | |
| 897 | + | |
| 898 | + this.started = false; | |
| 899 | + }, | |
| 900 | + | |
| 901 | + // TODO: make sure destroying one instance of mouse doesn't mess with | |
| 902 | + // other instances of mouse | |
| 903 | + _mouseDestroy: function() { | |
| 904 | + this.element.unbind("." + this.widgetName); | |
| 905 | + if ( this._mouseMoveDelegate ) { | |
| 906 | + this.document | |
| 907 | + .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate) | |
| 908 | + .unbind("mouseup." + this.widgetName, this._mouseUpDelegate); | |
| 909 | + } | |
| 910 | + }, | |
| 911 | + | |
| 912 | + _mouseDown: function(event) { | |
| 913 | + // don't let more than one widget handle mouseStart | |
| 914 | + if ( mouseHandled ) { | |
| 915 | + return; | |
| 916 | + } | |
| 917 | + | |
| 918 | + this._mouseMoved = false; | |
| 919 | + | |
| 920 | + // we may have missed mouseup (out of window) | |
| 921 | + (this._mouseStarted && this._mouseUp(event)); | |
| 922 | + | |
| 923 | + this._mouseDownEvent = event; | |
| 924 | + | |
| 925 | + var that = this, | |
| 926 | + btnIsLeft = (event.which === 1), | |
| 927 | + // event.target.nodeName works around a bug in IE 8 with | |
| 928 | + // disabled inputs (#7620) | |
| 929 | + elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); | |
| 930 | + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { | |
| 931 | + return true; | |
| 932 | + } | |
| 933 | + | |
| 934 | + this.mouseDelayMet = !this.options.delay; | |
| 935 | + if (!this.mouseDelayMet) { | |
| 936 | + this._mouseDelayTimer = setTimeout(function() { | |
| 937 | + that.mouseDelayMet = true; | |
| 938 | + }, this.options.delay); | |
| 939 | + } | |
| 940 | + | |
| 941 | + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { | |
| 942 | + this._mouseStarted = (this._mouseStart(event) !== false); | |
| 943 | + if (!this._mouseStarted) { | |
| 944 | + event.preventDefault(); | |
| 945 | + return true; | |
| 946 | + } | |
| 947 | + } | |
| 948 | + | |
| 949 | + // Click event may never have fired (Gecko & Opera) | |
| 950 | + if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { | |
| 951 | + $.removeData(event.target, this.widgetName + ".preventClickEvent"); | |
| 952 | + } | |
| 953 | + | |
| 954 | + // these delegates are required to keep context | |
| 955 | + this._mouseMoveDelegate = function(event) { | |
| 956 | + return that._mouseMove(event); | |
| 957 | + }; | |
| 958 | + this._mouseUpDelegate = function(event) { | |
| 959 | + return that._mouseUp(event); | |
| 960 | + }; | |
| 961 | + | |
| 962 | + this.document | |
| 963 | + .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) | |
| 964 | + .bind( "mouseup." + this.widgetName, this._mouseUpDelegate ); | |
| 965 | + | |
| 966 | + event.preventDefault(); | |
| 967 | + | |
| 968 | + mouseHandled = true; | |
| 969 | + return true; | |
| 970 | + }, | |
| 971 | + | |
| 972 | + _mouseMove: function(event) { | |
| 973 | + // Only check for mouseups outside the document if you've moved inside the document | |
| 974 | + // at least once. This prevents the firing of mouseup in the case of IE<9, which will | |
| 975 | + // fire a mousemove event if content is placed under the cursor. See #7778 | |
| 976 | + // Support: IE <9 | |
| 977 | + if ( this._mouseMoved ) { | |
| 978 | + // IE mouseup check - mouseup happened when mouse was out of window | |
| 979 | + if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { | |
| 980 | + return this._mouseUp(event); | |
| 981 | + | |
| 982 | + // Iframe mouseup check - mouseup occurred in another document | |
| 983 | + } else if ( !event.which ) { | |
| 984 | + return this._mouseUp( event ); | |
| 985 | + } | |
| 986 | + } | |
| 987 | + | |
| 988 | + if ( event.which || event.button ) { | |
| 989 | + this._mouseMoved = true; | |
| 990 | + } | |
| 991 | + | |
| 992 | + if (this._mouseStarted) { | |
| 993 | + this._mouseDrag(event); | |
| 994 | + return event.preventDefault(); | |
| 995 | + } | |
| 996 | + | |
| 997 | + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { | |
| 998 | + this._mouseStarted = | |
| 999 | + (this._mouseStart(this._mouseDownEvent, event) !== false); | |
| 1000 | + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); | |
| 1001 | + } | |
| 1002 | + | |
| 1003 | + return !this._mouseStarted; | |
| 1004 | + }, | |
| 1005 | + | |
| 1006 | + _mouseUp: function(event) { | |
| 1007 | + this.document | |
| 1008 | + .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) | |
| 1009 | + .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate ); | |
| 1010 | + | |
| 1011 | + if (this._mouseStarted) { | |
| 1012 | + this._mouseStarted = false; | |
| 1013 | + | |
| 1014 | + if (event.target === this._mouseDownEvent.target) { | |
| 1015 | + $.data(event.target, this.widgetName + ".preventClickEvent", true); | |
| 1016 | + } | |
| 1017 | + | |
| 1018 | + this._mouseStop(event); | |
| 1019 | + } | |
| 1020 | + | |
| 1021 | + mouseHandled = false; | |
| 1022 | + return false; | |
| 1023 | + }, | |
| 1024 | + | |
| 1025 | + _mouseDistanceMet: function(event) { | |
| 1026 | + return (Math.max( | |
| 1027 | + Math.abs(this._mouseDownEvent.pageX - event.pageX), | |
| 1028 | + Math.abs(this._mouseDownEvent.pageY - event.pageY) | |
| 1029 | + ) >= this.options.distance | |
| 1030 | + ); | |
| 1031 | + }, | |
| 1032 | + | |
| 1033 | + _mouseDelayMet: function(/* event */) { | |
| 1034 | + return this.mouseDelayMet; | |
| 1035 | + }, | |
| 1036 | + | |
| 1037 | + // These are placeholder methods, to be overriden by extending plugin | |
| 1038 | + _mouseStart: function(/* event */) {}, | |
| 1039 | + _mouseDrag: function(/* event */) {}, | |
| 1040 | + _mouseStop: function(/* event */) {}, | |
| 1041 | + _mouseCapture: function(/* event */) { return true; } | |
| 1042 | +}); | |
| 1043 | + | |
| 1044 | + | |
| 1045 | +/*! | |
| 1046 | + * jQuery UI Position 1.11.4 | |
| 1047 | + * http://jqueryui.com | |
| 1048 | + * | |
| 1049 | + * Copyright jQuery Foundation and other contributors | |
| 1050 | + * Released under the MIT license. | |
| 1051 | + * http://jquery.org/license | |
| 1052 | + * | |
| 1053 | + * http://api.jqueryui.com/position/ | |
| 1054 | + */ | |
| 1055 | + | |
| 1056 | +(function() { | |
| 1057 | + | |
| 1058 | +$.ui = $.ui || {}; | |
| 1059 | + | |
| 1060 | +var cachedScrollbarWidth, supportsOffsetFractions, | |
| 1061 | + max = Math.max, | |
| 1062 | + abs = Math.abs, | |
| 1063 | + round = Math.round, | |
| 1064 | + rhorizontal = /left|center|right/, | |
| 1065 | + rvertical = /top|center|bottom/, | |
| 1066 | + roffset = /[\+\-]\d+(\.[\d]+)?%?/, | |
| 1067 | + rposition = /^\w+/, | |
| 1068 | + rpercent = /%$/, | |
| 1069 | + _position = $.fn.position; | |
| 1070 | + | |
| 1071 | +function getOffsets( offsets, width, height ) { | |
| 1072 | + return [ | |
| 1073 | + parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), | |
| 1074 | + parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) | |
| 1075 | + ]; | |
| 1076 | +} | |
| 1077 | + | |
| 1078 | +function parseCss( element, property ) { | |
| 1079 | + return parseInt( $.css( element, property ), 10 ) || 0; | |
| 1080 | +} | |
| 1081 | + | |
| 1082 | +function getDimensions( elem ) { | |
| 1083 | + var raw = elem[0]; | |
| 1084 | + if ( raw.nodeType === 9 ) { | |
| 1085 | + return { | |
| 1086 | + width: elem.width(), | |
| 1087 | + height: elem.height(), | |
| 1088 | + offset: { top: 0, left: 0 } | |
| 1089 | + }; | |
| 1090 | + } | |
| 1091 | + if ( $.isWindow( raw ) ) { | |
| 1092 | + return { | |
| 1093 | + width: elem.width(), | |
| 1094 | + height: elem.height(), | |
| 1095 | + offset: { top: elem.scrollTop(), left: elem.scrollLeft() } | |
| 1096 | + }; | |
| 1097 | + } | |
| 1098 | + if ( raw.preventDefault ) { | |
| 1099 | + return { | |
| 1100 | + width: 0, | |
| 1101 | + height: 0, | |
| 1102 | + offset: { top: raw.pageY, left: raw.pageX } | |
| 1103 | + }; | |
| 1104 | + } | |
| 1105 | + return { | |
| 1106 | + width: elem.outerWidth(), | |
| 1107 | + height: elem.outerHeight(), | |
| 1108 | + offset: elem.offset() | |
| 1109 | + }; | |
| 1110 | +} | |
| 1111 | + | |
| 1112 | +$.position = { | |
| 1113 | + scrollbarWidth: function() { | |
| 1114 | + if ( cachedScrollbarWidth !== undefined ) { | |
| 1115 | + return cachedScrollbarWidth; | |
| 1116 | + } | |
| 1117 | + var w1, w2, | |
| 1118 | + div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), | |
| 1119 | + innerDiv = div.children()[0]; | |
| 1120 | + | |
| 1121 | + $( "body" ).append( div ); | |
| 1122 | + w1 = innerDiv.offsetWidth; | |
| 1123 | + div.css( "overflow", "scroll" ); | |
| 1124 | + | |
| 1125 | + w2 = innerDiv.offsetWidth; | |
| 1126 | + | |
| 1127 | + if ( w1 === w2 ) { | |
| 1128 | + w2 = div[0].clientWidth; | |
| 1129 | + } | |
| 1130 | + | |
| 1131 | + div.remove(); | |
| 1132 | + | |
| 1133 | + return (cachedScrollbarWidth = w1 - w2); | |
| 1134 | + }, | |
| 1135 | + getScrollInfo: function( within ) { | |
| 1136 | + var overflowX = within.isWindow || within.isDocument ? "" : | |
| 1137 | + within.element.css( "overflow-x" ), | |
| 1138 | + overflowY = within.isWindow || within.isDocument ? "" : | |
| 1139 | + within.element.css( "overflow-y" ), | |
| 1140 | + hasOverflowX = overflowX === "scroll" || | |
| 1141 | + ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), | |
| 1142 | + hasOverflowY = overflowY === "scroll" || | |
| 1143 | + ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); | |
| 1144 | + return { | |
| 1145 | + width: hasOverflowY ? $.position.scrollbarWidth() : 0, | |
| 1146 | + height: hasOverflowX ? $.position.scrollbarWidth() : 0 | |
| 1147 | + }; | |
| 1148 | + }, | |
| 1149 | + getWithinInfo: function( element ) { | |
| 1150 | + var withinElement = $( element || window ), | |
| 1151 | + isWindow = $.isWindow( withinElement[0] ), | |
| 1152 | + isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; | |
| 1153 | + return { | |
| 1154 | + element: withinElement, | |
| 1155 | + isWindow: isWindow, | |
| 1156 | + isDocument: isDocument, | |
| 1157 | + offset: withinElement.offset() || { left: 0, top: 0 }, | |
| 1158 | + scrollLeft: withinElement.scrollLeft(), | |
| 1159 | + scrollTop: withinElement.scrollTop(), | |
| 1160 | + | |
| 1161 | + // support: jQuery 1.6.x | |
| 1162 | + // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows | |
| 1163 | + width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(), | |
| 1164 | + height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight() | |
| 1165 | + }; | |
| 1166 | + } | |
| 1167 | +}; | |
| 1168 | + | |
| 1169 | +$.fn.position = function( options ) { | |
| 1170 | + if ( !options || !options.of ) { | |
| 1171 | + return _position.apply( this, arguments ); | |
| 1172 | + } | |
| 1173 | + | |
| 1174 | + // make a copy, we don't want to modify arguments | |
| 1175 | + options = $.extend( {}, options ); | |
| 1176 | + | |
| 1177 | + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, | |
| 1178 | + target = $( options.of ), | |
| 1179 | + within = $.position.getWithinInfo( options.within ), | |
| 1180 | + scrollInfo = $.position.getScrollInfo( within ), | |
| 1181 | + collision = ( options.collision || "flip" ).split( " " ), | |
| 1182 | + offsets = {}; | |
| 1183 | + | |
| 1184 | + dimensions = getDimensions( target ); | |
| 1185 | + if ( target[0].preventDefault ) { | |
| 1186 | + // force left top to allow flipping | |
| 1187 | + options.at = "left top"; | |
| 1188 | + } | |
| 1189 | + targetWidth = dimensions.width; | |
| 1190 | + targetHeight = dimensions.height; | |
| 1191 | + targetOffset = dimensions.offset; | |
| 1192 | + // clone to reuse original targetOffset later | |
| 1193 | + basePosition = $.extend( {}, targetOffset ); | |
| 1194 | + | |
| 1195 | + // force my and at to have valid horizontal and vertical positions | |
| 1196 | + // if a value is missing or invalid, it will be converted to center | |
| 1197 | + $.each( [ "my", "at" ], function() { | |
| 1198 | + var pos = ( options[ this ] || "" ).split( " " ), | |
| 1199 | + horizontalOffset, | |
| 1200 | + verticalOffset; | |
| 1201 | + | |
| 1202 | + if ( pos.length === 1) { | |
| 1203 | + pos = rhorizontal.test( pos[ 0 ] ) ? | |
| 1204 | + pos.concat( [ "center" ] ) : | |
| 1205 | + rvertical.test( pos[ 0 ] ) ? | |
| 1206 | + [ "center" ].concat( pos ) : | |
| 1207 | + [ "center", "center" ]; | |
| 1208 | + } | |
| 1209 | + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; | |
| 1210 | + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; | |
| 1211 | + | |
| 1212 | + // calculate offsets | |
| 1213 | + horizontalOffset = roffset.exec( pos[ 0 ] ); | |
| 1214 | + verticalOffset = roffset.exec( pos[ 1 ] ); | |
| 1215 | + offsets[ this ] = [ | |
| 1216 | + horizontalOffset ? horizontalOffset[ 0 ] : 0, | |
| 1217 | + verticalOffset ? verticalOffset[ 0 ] : 0 | |
| 1218 | + ]; | |
| 1219 | + | |
| 1220 | + // reduce to just the positions without the offsets | |
| 1221 | + options[ this ] = [ | |
| 1222 | + rposition.exec( pos[ 0 ] )[ 0 ], | |
| 1223 | + rposition.exec( pos[ 1 ] )[ 0 ] | |
| 1224 | + ]; | |
| 1225 | + }); | |
| 1226 | + | |
| 1227 | + // normalize collision option | |
| 1228 | + if ( collision.length === 1 ) { | |
| 1229 | + collision[ 1 ] = collision[ 0 ]; | |
| 1230 | + } | |
| 1231 | + | |
| 1232 | + if ( options.at[ 0 ] === "right" ) { | |
| 1233 | + basePosition.left += targetWidth; | |
| 1234 | + } else if ( options.at[ 0 ] === "center" ) { | |
| 1235 | + basePosition.left += targetWidth / 2; | |
| 1236 | + } | |
| 1237 | + | |
| 1238 | + if ( options.at[ 1 ] === "bottom" ) { | |
| 1239 | + basePosition.top += targetHeight; | |
| 1240 | + } else if ( options.at[ 1 ] === "center" ) { | |
| 1241 | + basePosition.top += targetHeight / 2; | |
| 1242 | + } | |
| 1243 | + | |
| 1244 | + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); | |
| 1245 | + basePosition.left += atOffset[ 0 ]; | |
| 1246 | + basePosition.top += atOffset[ 1 ]; | |
| 1247 | + | |
| 1248 | + return this.each(function() { | |
| 1249 | + var collisionPosition, using, | |
| 1250 | + elem = $( this ), | |
| 1251 | + elemWidth = elem.outerWidth(), | |
| 1252 | + elemHeight = elem.outerHeight(), | |
| 1253 | + marginLeft = parseCss( this, "marginLeft" ), | |
| 1254 | + marginTop = parseCss( this, "marginTop" ), | |
| 1255 | + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, | |
| 1256 | + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, | |
| 1257 | + position = $.extend( {}, basePosition ), | |
| 1258 | + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); | |
| 1259 | + | |
| 1260 | + if ( options.my[ 0 ] === "right" ) { | |
| 1261 | + position.left -= elemWidth; | |
| 1262 | + } else if ( options.my[ 0 ] === "center" ) { | |
| 1263 | + position.left -= elemWidth / 2; | |
| 1264 | + } | |
| 1265 | + | |
| 1266 | + if ( options.my[ 1 ] === "bottom" ) { | |
| 1267 | + position.top -= elemHeight; | |
| 1268 | + } else if ( options.my[ 1 ] === "center" ) { | |
| 1269 | + position.top -= elemHeight / 2; | |
| 1270 | + } | |
| 1271 | + | |
| 1272 | + position.left += myOffset[ 0 ]; | |
| 1273 | + position.top += myOffset[ 1 ]; | |
| 1274 | + | |
| 1275 | + // if the browser doesn't support fractions, then round for consistent results | |
| 1276 | + if ( !supportsOffsetFractions ) { | |
| 1277 | + position.left = round( position.left ); | |
| 1278 | + position.top = round( position.top ); | |
| 1279 | + } | |
| 1280 | + | |
| 1281 | + collisionPosition = { | |
| 1282 | + marginLeft: marginLeft, | |
| 1283 | + marginTop: marginTop | |
| 1284 | + }; | |
| 1285 | + | |
| 1286 | + $.each( [ "left", "top" ], function( i, dir ) { | |
| 1287 | + if ( $.ui.position[ collision[ i ] ] ) { | |
| 1288 | + $.ui.position[ collision[ i ] ][ dir ]( position, { | |
| 1289 | + targetWidth: targetWidth, | |
| 1290 | + targetHeight: targetHeight, | |
| 1291 | + elemWidth: elemWidth, | |
| 1292 | + elemHeight: elemHeight, | |
| 1293 | + collisionPosition: collisionPosition, | |
| 1294 | + collisionWidth: collisionWidth, | |
| 1295 | + collisionHeight: collisionHeight, | |
| 1296 | + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], | |
| 1297 | + my: options.my, | |
| 1298 | + at: options.at, | |
| 1299 | + within: within, | |
| 1300 | + elem: elem | |
| 1301 | + }); | |
| 1302 | + } | |
| 1303 | + }); | |
| 1304 | + | |
| 1305 | + if ( options.using ) { | |
| 1306 | + // adds feedback as second argument to using callback, if present | |
| 1307 | + using = function( props ) { | |
| 1308 | + var left = targetOffset.left - position.left, | |
| 1309 | + right = left + targetWidth - elemWidth, | |
| 1310 | + top = targetOffset.top - position.top, | |
| 1311 | + bottom = top + targetHeight - elemHeight, | |
| 1312 | + feedback = { | |
| 1313 | + target: { | |
| 1314 | + element: target, | |
| 1315 | + left: targetOffset.left, | |
| 1316 | + top: targetOffset.top, | |
| 1317 | + width: targetWidth, | |
| 1318 | + height: targetHeight | |
| 1319 | + }, | |
| 1320 | + element: { | |
| 1321 | + element: elem, | |
| 1322 | + left: position.left, | |
| 1323 | + top: position.top, | |
| 1324 | + width: elemWidth, | |
| 1325 | + height: elemHeight | |
| 1326 | + }, | |
| 1327 | + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", | |
| 1328 | + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" | |
| 1329 | + }; | |
| 1330 | + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { | |
| 1331 | + feedback.horizontal = "center"; | |
| 1332 | + } | |
| 1333 | + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { | |
| 1334 | + feedback.vertical = "middle"; | |
| 1335 | + } | |
| 1336 | + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { | |
| 1337 | + feedback.important = "horizontal"; | |
| 1338 | + } else { | |
| 1339 | + feedback.important = "vertical"; | |
| 1340 | + } | |
| 1341 | + options.using.call( this, props, feedback ); | |
| 1342 | + }; | |
| 1343 | + } | |
| 1344 | + | |
| 1345 | + elem.offset( $.extend( position, { using: using } ) ); | |
| 1346 | + }); | |
| 1347 | +}; | |
| 1348 | + | |
| 1349 | +$.ui.position = { | |
| 1350 | + fit: { | |
| 1351 | + left: function( position, data ) { | |
| 1352 | + var within = data.within, | |
| 1353 | + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, | |
| 1354 | + outerWidth = within.width, | |
| 1355 | + collisionPosLeft = position.left - data.collisionPosition.marginLeft, | |
| 1356 | + overLeft = withinOffset - collisionPosLeft, | |
| 1357 | + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, | |
| 1358 | + newOverRight; | |
| 1359 | + | |
| 1360 | + // element is wider than within | |
| 1361 | + if ( data.collisionWidth > outerWidth ) { | |
| 1362 | + // element is initially over the left side of within | |
| 1363 | + if ( overLeft > 0 && overRight <= 0 ) { | |
| 1364 | + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; | |
| 1365 | + position.left += overLeft - newOverRight; | |
| 1366 | + // element is initially over right side of within | |
| 1367 | + } else if ( overRight > 0 && overLeft <= 0 ) { | |
| 1368 | + position.left = withinOffset; | |
| 1369 | + // element is initially over both left and right sides of within | |
| 1370 | + } else { | |
| 1371 | + if ( overLeft > overRight ) { | |
| 1372 | + position.left = withinOffset + outerWidth - data.collisionWidth; | |
| 1373 | + } else { | |
| 1374 | + position.left = withinOffset; | |
| 1375 | + } | |
| 1376 | + } | |
| 1377 | + // too far left -> align with left edge | |
| 1378 | + } else if ( overLeft > 0 ) { | |
| 1379 | + position.left += overLeft; | |
| 1380 | + // too far right -> align with right edge | |
| 1381 | + } else if ( overRight > 0 ) { | |
| 1382 | + position.left -= overRight; | |
| 1383 | + // adjust based on position and margin | |
| 1384 | + } else { | |
| 1385 | + position.left = max( position.left - collisionPosLeft, position.left ); | |
| 1386 | + } | |
| 1387 | + }, | |
| 1388 | + top: function( position, data ) { | |
| 1389 | + var within = data.within, | |
| 1390 | + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, | |
| 1391 | + outerHeight = data.within.height, | |
| 1392 | + collisionPosTop = position.top - data.collisionPosition.marginTop, | |
| 1393 | + overTop = withinOffset - collisionPosTop, | |
| 1394 | + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, | |
| 1395 | + newOverBottom; | |
| 1396 | + | |
| 1397 | + // element is taller than within | |
| 1398 | + if ( data.collisionHeight > outerHeight ) { | |
| 1399 | + // element is initially over the top of within | |
| 1400 | + if ( overTop > 0 && overBottom <= 0 ) { | |
| 1401 | + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; | |
| 1402 | + position.top += overTop - newOverBottom; | |
| 1403 | + // element is initially over bottom of within | |
| 1404 | + } else if ( overBottom > 0 && overTop <= 0 ) { | |
| 1405 | + position.top = withinOffset; | |
| 1406 | + // element is initially over both top and bottom of within | |
| 1407 | + } else { | |
| 1408 | + if ( overTop > overBottom ) { | |
| 1409 | + position.top = withinOffset + outerHeight - data.collisionHeight; | |
| 1410 | + } else { | |
| 1411 | + position.top = withinOffset; | |
| 1412 | + } | |
| 1413 | + } | |
| 1414 | + // too far up -> align with top | |
| 1415 | + } else if ( overTop > 0 ) { | |
| 1416 | + position.top += overTop; | |
| 1417 | + // too far down -> align with bottom edge | |
| 1418 | + } else if ( overBottom > 0 ) { | |
| 1419 | + position.top -= overBottom; | |
| 1420 | + // adjust based on position and margin | |
| 1421 | + } else { | |
| 1422 | + position.top = max( position.top - collisionPosTop, position.top ); | |
| 1423 | + } | |
| 1424 | + } | |
| 1425 | + }, | |
| 1426 | + flip: { | |
| 1427 | + left: function( position, data ) { | |
| 1428 | + var within = data.within, | |
| 1429 | + withinOffset = within.offset.left + within.scrollLeft, | |
| 1430 | + outerWidth = within.width, | |
| 1431 | + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, | |
| 1432 | + collisionPosLeft = position.left - data.collisionPosition.marginLeft, | |
| 1433 | + overLeft = collisionPosLeft - offsetLeft, | |
| 1434 | + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, | |
| 1435 | + myOffset = data.my[ 0 ] === "left" ? | |
| 1436 | + -data.elemWidth : | |
| 1437 | + data.my[ 0 ] === "right" ? | |
| 1438 | + data.elemWidth : | |
| 1439 | + 0, | |
| 1440 | + atOffset = data.at[ 0 ] === "left" ? | |
| 1441 | + data.targetWidth : | |
| 1442 | + data.at[ 0 ] === "right" ? | |
| 1443 | + -data.targetWidth : | |
| 1444 | + 0, | |
| 1445 | + offset = -2 * data.offset[ 0 ], | |
| 1446 | + newOverRight, | |
| 1447 | + newOverLeft; | |
| 1448 | + | |
| 1449 | + if ( overLeft < 0 ) { | |
| 1450 | + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; | |
| 1451 | + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { | |
| 1452 | + position.left += myOffset + atOffset + offset; | |
| 1453 | + } | |
| 1454 | + } else if ( overRight > 0 ) { | |
| 1455 | + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; | |
| 1456 | + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { | |
| 1457 | + position.left += myOffset + atOffset + offset; | |
| 1458 | + } | |
| 1459 | + } | |
| 1460 | + }, | |
| 1461 | + top: function( position, data ) { | |
| 1462 | + var within = data.within, | |
| 1463 | + withinOffset = within.offset.top + within.scrollTop, | |
| 1464 | + outerHeight = within.height, | |
| 1465 | + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, | |
| 1466 | + collisionPosTop = position.top - data.collisionPosition.marginTop, | |
| 1467 | + overTop = collisionPosTop - offsetTop, | |
| 1468 | + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, | |
| 1469 | + top = data.my[ 1 ] === "top", | |
| 1470 | + myOffset = top ? | |
| 1471 | + -data.elemHeight : | |
| 1472 | + data.my[ 1 ] === "bottom" ? | |
| 1473 | + data.elemHeight : | |
| 1474 | + 0, | |
| 1475 | + atOffset = data.at[ 1 ] === "top" ? | |
| 1476 | + data.targetHeight : | |
| 1477 | + data.at[ 1 ] === "bottom" ? | |
| 1478 | + -data.targetHeight : | |
| 1479 | + 0, | |
| 1480 | + offset = -2 * data.offset[ 1 ], | |
| 1481 | + newOverTop, | |
| 1482 | + newOverBottom; | |
| 1483 | + if ( overTop < 0 ) { | |
| 1484 | + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; | |
| 1485 | + if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { | |
| 1486 | + position.top += myOffset + atOffset + offset; | |
| 1487 | + } | |
| 1488 | + } else if ( overBottom > 0 ) { | |
| 1489 | + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; | |
| 1490 | + if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { | |
| 1491 | + position.top += myOffset + atOffset + offset; | |
| 1492 | + } | |
| 1493 | + } | |
| 1494 | + } | |
| 1495 | + }, | |
| 1496 | + flipfit: { | |
| 1497 | + left: function() { | |
| 1498 | + $.ui.position.flip.left.apply( this, arguments ); | |
| 1499 | + $.ui.position.fit.left.apply( this, arguments ); | |
| 1500 | + }, | |
| 1501 | + top: function() { | |
| 1502 | + $.ui.position.flip.top.apply( this, arguments ); | |
| 1503 | + $.ui.position.fit.top.apply( this, arguments ); | |
| 1504 | + } | |
| 1505 | + } | |
| 1506 | +}; | |
| 1507 | + | |
| 1508 | +// fraction support test | |
| 1509 | +(function() { | |
| 1510 | + var testElement, testElementParent, testElementStyle, offsetLeft, i, | |
| 1511 | + body = document.getElementsByTagName( "body" )[ 0 ], | |
| 1512 | + div = document.createElement( "div" ); | |
| 1513 | + | |
| 1514 | + //Create a "fake body" for testing based on method used in jQuery.support | |
| 1515 | + testElement = document.createElement( body ? "div" : "body" ); | |
| 1516 | + testElementStyle = { | |
| 1517 | + visibility: "hidden", | |
| 1518 | + width: 0, | |
| 1519 | + height: 0, | |
| 1520 | + border: 0, | |
| 1521 | + margin: 0, | |
| 1522 | + background: "none" | |
| 1523 | + }; | |
| 1524 | + if ( body ) { | |
| 1525 | + $.extend( testElementStyle, { | |
| 1526 | + position: "absolute", | |
| 1527 | + left: "-1000px", | |
| 1528 | + top: "-1000px" | |
| 1529 | + }); | |
| 1530 | + } | |
| 1531 | + for ( i in testElementStyle ) { | |
| 1532 | + testElement.style[ i ] = testElementStyle[ i ]; | |
| 1533 | + } | |
| 1534 | + testElement.appendChild( div ); | |
| 1535 | + testElementParent = body || document.documentElement; | |
| 1536 | + testElementParent.insertBefore( testElement, testElementParent.firstChild ); | |
| 1537 | + | |
| 1538 | + div.style.cssText = "position: absolute; left: 10.7432222px;"; | |
| 1539 | + | |
| 1540 | + offsetLeft = $( div ).offset().left; | |
| 1541 | + supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11; | |
| 1542 | + | |
| 1543 | + testElement.innerHTML = ""; | |
| 1544 | + testElementParent.removeChild( testElement ); | |
| 1545 | +})(); | |
| 1546 | + | |
| 1547 | +})(); | |
| 1548 | + | |
| 1549 | +var position = $.ui.position; | |
| 1550 | + | |
| 1551 | + | |
| 1552 | +/*! | |
| 1553 | + * jQuery UI Draggable 1.11.4 | |
| 1554 | + * http://jqueryui.com | |
| 1555 | + * | |
| 1556 | + * Copyright jQuery Foundation and other contributors | |
| 1557 | + * Released under the MIT license. | |
| 1558 | + * http://jquery.org/license | |
| 1559 | + * | |
| 1560 | + * http://api.jqueryui.com/draggable/ | |
| 1561 | + */ | |
| 1562 | + | |
| 1563 | + | |
| 1564 | +$.widget("ui.draggable", $.ui.mouse, { | |
| 1565 | + version: "1.11.4", | |
| 1566 | + widgetEventPrefix: "drag", | |
| 1567 | + options: { | |
| 1568 | + addClasses: true, | |
| 1569 | + appendTo: "parent", | |
| 1570 | + axis: false, | |
| 1571 | + connectToSortable: false, | |
| 1572 | + containment: false, | |
| 1573 | + cursor: "auto", | |
| 1574 | + cursorAt: false, | |
| 1575 | + grid: false, | |
| 1576 | + handle: false, | |
| 1577 | + helper: "original", | |
| 1578 | + iframeFix: false, | |
| 1579 | + opacity: false, | |
| 1580 | + refreshPositions: false, | |
| 1581 | + revert: false, | |
| 1582 | + revertDuration: 500, | |
| 1583 | + scope: "default", | |
| 1584 | + scroll: true, | |
| 1585 | + scrollSensitivity: 20, | |
| 1586 | + scrollSpeed: 20, | |
| 1587 | + snap: false, | |
| 1588 | + snapMode: "both", | |
| 1589 | + snapTolerance: 20, | |
| 1590 | + stack: false, | |
| 1591 | + zIndex: false, | |
| 1592 | + | |
| 1593 | + // callbacks | |
| 1594 | + drag: null, | |
| 1595 | + start: null, | |
| 1596 | + stop: null | |
| 1597 | + }, | |
| 1598 | + _create: function() { | |
| 1599 | + | |
| 1600 | + if ( this.options.helper === "original" ) { | |
| 1601 | + this._setPositionRelative(); | |
| 1602 | + } | |
| 1603 | + if (this.options.addClasses){ | |
| 1604 | + this.element.addClass("ui-draggable"); | |
| 1605 | + } | |
| 1606 | + if (this.options.disabled){ | |
| 1607 | + this.element.addClass("ui-draggable-disabled"); | |
| 1608 | + } | |
| 1609 | + this._setHandleClassName(); | |
| 1610 | + | |
| 1611 | + this._mouseInit(); | |
| 1612 | + }, | |
| 1613 | + | |
| 1614 | + _setOption: function( key, value ) { | |
| 1615 | + this._super( key, value ); | |
| 1616 | + if ( key === "handle" ) { | |
| 1617 | + this._removeHandleClassName(); | |
| 1618 | + this._setHandleClassName(); | |
| 1619 | + } | |
| 1620 | + }, | |
| 1621 | + | |
| 1622 | + _destroy: function() { | |
| 1623 | + if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { | |
| 1624 | + this.destroyOnClear = true; | |
| 1625 | + return; | |
| 1626 | + } | |
| 1627 | + this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); | |
| 1628 | + this._removeHandleClassName(); | |
| 1629 | + this._mouseDestroy(); | |
| 1630 | + }, | |
| 1631 | + | |
| 1632 | + _mouseCapture: function(event) { | |
| 1633 | + var o = this.options; | |
| 1634 | + | |
| 1635 | + this._blurActiveElement( event ); | |
| 1636 | + | |
| 1637 | + // among others, prevent a drag on a resizable-handle | |
| 1638 | + if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { | |
| 1639 | + return false; | |
| 1640 | + } | |
| 1641 | + | |
| 1642 | + //Quit if we're not on a valid handle | |
| 1643 | + this.handle = this._getHandle(event); | |
| 1644 | + if (!this.handle) { | |
| 1645 | + return false; | |
| 1646 | + } | |
| 1647 | + | |
| 1648 | + this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); | |
| 1649 | + | |
| 1650 | + return true; | |
| 1651 | + | |
| 1652 | + }, | |
| 1653 | + | |
| 1654 | + _blockFrames: function( selector ) { | |
| 1655 | + this.iframeBlocks = this.document.find( selector ).map(function() { | |
| 1656 | + var iframe = $( this ); | |
| 1657 | + | |
| 1658 | + return $( "<div>" ) | |
| 1659 | + .css( "position", "absolute" ) | |
| 1660 | + .appendTo( iframe.parent() ) | |
| 1661 | + .outerWidth( iframe.outerWidth() ) | |
| 1662 | + .outerHeight( iframe.outerHeight() ) | |
| 1663 | + .offset( iframe.offset() )[ 0 ]; | |
| 1664 | + }); | |
| 1665 | + }, | |
| 1666 | + | |
| 1667 | + _unblockFrames: function() { | |
| 1668 | + if ( this.iframeBlocks ) { | |
| 1669 | + this.iframeBlocks.remove(); | |
| 1670 | + delete this.iframeBlocks; | |
| 1671 | + } | |
| 1672 | + }, | |
| 1673 | + | |
| 1674 | + _blurActiveElement: function( event ) { | |
| 1675 | + var document = this.document[ 0 ]; | |
| 1676 | + | |
| 1677 | + // Only need to blur if the event occurred on the draggable itself, see #10527 | |
| 1678 | + if ( !this.handleElement.is( event.target ) ) { | |
| 1679 | + return; | |
| 1680 | + } | |
| 1681 | + | |
| 1682 | + // support: IE9 | |
| 1683 | + // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> | |
| 1684 | + try { | |
| 1685 | + | |
| 1686 | + // Support: IE9, IE10 | |
| 1687 | + // If the <body> is blurred, IE will switch windows, see #9520 | |
| 1688 | + if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) { | |
| 1689 | + | |
| 1690 | + // Blur any element that currently has focus, see #4261 | |
| 1691 | + $( document.activeElement ).blur(); | |
| 1692 | + } | |
| 1693 | + } catch ( error ) {} | |
| 1694 | + }, | |
| 1695 | + | |
| 1696 | + _mouseStart: function(event) { | |
| 1697 | + | |
| 1698 | + var o = this.options; | |
| 1699 | + | |
| 1700 | + //Create and append the visible helper | |
| 1701 | + this.helper = this._createHelper(event); | |
| 1702 | + | |
| 1703 | + this.helper.addClass("ui-draggable-dragging"); | |
| 1704 | + | |
| 1705 | + //Cache the helper size | |
| 1706 | + this._cacheHelperProportions(); | |
| 1707 | + | |
| 1708 | + //If ddmanager is used for droppables, set the global draggable | |
| 1709 | + if ($.ui.ddmanager) { | |
| 1710 | + $.ui.ddmanager.current = this; | |
| 1711 | + } | |
| 1712 | + | |
| 1713 | + /* | |
| 1714 | + * - Position generation - | |
| 1715 | + * This block generates everything position related - it's the core of draggables. | |
| 1716 | + */ | |
| 1717 | + | |
| 1718 | + //Cache the margins of the original element | |
| 1719 | + this._cacheMargins(); | |
| 1720 | + | |
| 1721 | + //Store the helper's css position | |
| 1722 | + this.cssPosition = this.helper.css( "position" ); | |
| 1723 | + this.scrollParent = this.helper.scrollParent( true ); | |
| 1724 | + this.offsetParent = this.helper.offsetParent(); | |
| 1725 | + this.hasFixedAncestor = this.helper.parents().filter(function() { | |
| 1726 | + return $( this ).css( "position" ) === "fixed"; | |
| 1727 | + }).length > 0; | |
| 1728 | + | |
| 1729 | + //The element's absolute position on the page minus margins | |
| 1730 | + this.positionAbs = this.element.offset(); | |
| 1731 | + this._refreshOffsets( event ); | |
| 1732 | + | |
| 1733 | + //Generate the original position | |
| 1734 | + this.originalPosition = this.position = this._generatePosition( event, false ); | |
| 1735 | + this.originalPageX = event.pageX; | |
| 1736 | + this.originalPageY = event.pageY; | |
| 1737 | + | |
| 1738 | + //Adjust the mouse offset relative to the helper if "cursorAt" is supplied | |
| 1739 | + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); | |
| 1740 | + | |
| 1741 | + //Set a containment if given in the options | |
| 1742 | + this._setContainment(); | |
| 1743 | + | |
| 1744 | + //Trigger event + callbacks | |
| 1745 | + if (this._trigger("start", event) === false) { | |
| 1746 | + this._clear(); | |
| 1747 | + return false; | |
| 1748 | + } | |
| 1749 | + | |
| 1750 | + //Recache the helper size | |
| 1751 | + this._cacheHelperProportions(); | |
| 1752 | + | |
| 1753 | + //Prepare the droppable offsets | |
| 1754 | + if ($.ui.ddmanager && !o.dropBehaviour) { | |
| 1755 | + $.ui.ddmanager.prepareOffsets(this, event); | |
| 1756 | + } | |
| 1757 | + | |
| 1758 | + // Reset helper's right/bottom css if they're set and set explicit width/height instead | |
| 1759 | + // as this prevents resizing of elements with right/bottom set (see #7772) | |
| 1760 | + this._normalizeRightBottom(); | |
| 1761 | + | |
| 1762 | + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position | |
| 1763 | + | |
| 1764 | + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) | |
| 1765 | + if ( $.ui.ddmanager ) { | |
| 1766 | + $.ui.ddmanager.dragStart(this, event); | |
| 1767 | + } | |
| 1768 | + | |
| 1769 | + return true; | |
| 1770 | + }, | |
| 1771 | + | |
| 1772 | + _refreshOffsets: function( event ) { | |
| 1773 | + this.offset = { | |
| 1774 | + top: this.positionAbs.top - this.margins.top, | |
| 1775 | + left: this.positionAbs.left - this.margins.left, | |
| 1776 | + scroll: false, | |
| 1777 | + parent: this._getParentOffset(), | |
| 1778 | + relative: this._getRelativeOffset() | |
| 1779 | + }; | |
| 1780 | + | |
| 1781 | + this.offset.click = { | |
| 1782 | + left: event.pageX - this.offset.left, | |
| 1783 | + top: event.pageY - this.offset.top | |
| 1784 | + }; | |
| 1785 | + }, | |
| 1786 | + | |
| 1787 | + _mouseDrag: function(event, noPropagation) { | |
| 1788 | + // reset any necessary cached properties (see #5009) | |
| 1789 | + if ( this.hasFixedAncestor ) { | |
| 1790 | + this.offset.parent = this._getParentOffset(); | |
| 1791 | + } | |
| 1792 | + | |
| 1793 | + //Compute the helpers position | |
| 1794 | + this.position = this._generatePosition( event, true ); | |
| 1795 | + this.positionAbs = this._convertPositionTo("absolute"); | |
| 1796 | + | |
| 1797 | + //Call plugins and callbacks and use the resulting position if something is returned | |
| 1798 | + if (!noPropagation) { | |
| 1799 | + var ui = this._uiHash(); | |
| 1800 | + if (this._trigger("drag", event, ui) === false) { | |
| 1801 | + this._mouseUp({}); | |
| 1802 | + return false; | |
| 1803 | + } | |
| 1804 | + this.position = ui.position; | |
| 1805 | + } | |
| 1806 | + | |
| 1807 | + this.helper[ 0 ].style.left = this.position.left + "px"; | |
| 1808 | + this.helper[ 0 ].style.top = this.position.top + "px"; | |
| 1809 | + | |
| 1810 | + if ($.ui.ddmanager) { | |
| 1811 | + $.ui.ddmanager.drag(this, event); | |
| 1812 | + } | |
| 1813 | + | |
| 1814 | + return false; | |
| 1815 | + }, | |
| 1816 | + | |
| 1817 | + _mouseStop: function(event) { | |
| 1818 | + | |
| 1819 | + //If we are using droppables, inform the manager about the drop | |
| 1820 | + var that = this, | |
| 1821 | + dropped = false; | |
| 1822 | + if ($.ui.ddmanager && !this.options.dropBehaviour) { | |
| 1823 | + dropped = $.ui.ddmanager.drop(this, event); | |
| 1824 | + } | |
| 1825 | + | |
| 1826 | + //if a drop comes from outside (a sortable) | |
| 1827 | + if (this.dropped) { | |
| 1828 | + dropped = this.dropped; | |
| 1829 | + this.dropped = false; | |
| 1830 | + } | |
| 1831 | + | |
| 1832 | + if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { | |
| 1833 | + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { | |
| 1834 | + if (that._trigger("stop", event) !== false) { | |
| 1835 | + that._clear(); | |
| 1836 | + } | |
| 1837 | + }); | |
| 1838 | + } else { | |
| 1839 | + if (this._trigger("stop", event) !== false) { | |
| 1840 | + this._clear(); | |
| 1841 | + } | |
| 1842 | + } | |
| 1843 | + | |
| 1844 | + return false; | |
| 1845 | + }, | |
| 1846 | + | |
| 1847 | + _mouseUp: function( event ) { | |
| 1848 | + this._unblockFrames(); | |
| 1849 | + | |
| 1850 | + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) | |
| 1851 | + if ( $.ui.ddmanager ) { | |
| 1852 | + $.ui.ddmanager.dragStop(this, event); | |
| 1853 | + } | |
| 1854 | + | |
| 1855 | + // Only need to focus if the event occurred on the draggable itself, see #10527 | |
| 1856 | + if ( this.handleElement.is( event.target ) ) { | |
| 1857 | + // The interaction is over; whether or not the click resulted in a drag, focus the element | |
| 1858 | + this.element.focus(); | |
| 1859 | + } | |
| 1860 | + | |
| 1861 | + return $.ui.mouse.prototype._mouseUp.call(this, event); | |
| 1862 | + }, | |
| 1863 | + | |
| 1864 | + cancel: function() { | |
| 1865 | + | |
| 1866 | + if (this.helper.is(".ui-draggable-dragging")) { | |
| 1867 | + this._mouseUp({}); | |
| 1868 | + } else { | |
| 1869 | + this._clear(); | |
| 1870 | + } | |
| 1871 | + | |
| 1872 | + return this; | |
| 1873 | + | |
| 1874 | + }, | |
| 1875 | + | |
| 1876 | + _getHandle: function(event) { | |
| 1877 | + return this.options.handle ? | |
| 1878 | + !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : | |
| 1879 | + true; | |
| 1880 | + }, | |
| 1881 | + | |
| 1882 | + _setHandleClassName: function() { | |
| 1883 | + this.handleElement = this.options.handle ? | |
| 1884 | + this.element.find( this.options.handle ) : this.element; | |
| 1885 | + this.handleElement.addClass( "ui-draggable-handle" ); | |
| 1886 | + }, | |
| 1887 | + | |
| 1888 | + _removeHandleClassName: function() { | |
| 1889 | + this.handleElement.removeClass( "ui-draggable-handle" ); | |
| 1890 | + }, | |
| 1891 | + | |
| 1892 | + _createHelper: function(event) { | |
| 1893 | + | |
| 1894 | + var o = this.options, | |
| 1895 | + helperIsFunction = $.isFunction( o.helper ), | |
| 1896 | + helper = helperIsFunction ? | |
| 1897 | + $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : | |
| 1898 | + ( o.helper === "clone" ? | |
| 1899 | + this.element.clone().removeAttr( "id" ) : | |
| 1900 | + this.element ); | |
| 1901 | + | |
| 1902 | + if (!helper.parents("body").length) { | |
| 1903 | + helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); | |
| 1904 | + } | |
| 1905 | + | |
| 1906 | + // http://bugs.jqueryui.com/ticket/9446 | |
| 1907 | + // a helper function can return the original element | |
| 1908 | + // which wouldn't have been set to relative in _create | |
| 1909 | + if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { | |
| 1910 | + this._setPositionRelative(); | |
| 1911 | + } | |
| 1912 | + | |
| 1913 | + if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { | |
| 1914 | + helper.css("position", "absolute"); | |
| 1915 | + } | |
| 1916 | + | |
| 1917 | + return helper; | |
| 1918 | + | |
| 1919 | + }, | |
| 1920 | + | |
| 1921 | + _setPositionRelative: function() { | |
| 1922 | + if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { | |
| 1923 | + this.element[ 0 ].style.position = "relative"; | |
| 1924 | + } | |
| 1925 | + }, | |
| 1926 | + | |
| 1927 | + _adjustOffsetFromHelper: function(obj) { | |
| 1928 | + if (typeof obj === "string") { | |
| 1929 | + obj = obj.split(" "); | |
| 1930 | + } | |
| 1931 | + if ($.isArray(obj)) { | |
| 1932 | + obj = { left: +obj[0], top: +obj[1] || 0 }; | |
| 1933 | + } | |
| 1934 | + if ("left" in obj) { | |
| 1935 | + this.offset.click.left = obj.left + this.margins.left; | |
| 1936 | + } | |
| 1937 | + if ("right" in obj) { | |
| 1938 | + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; | |
| 1939 | + } | |
| 1940 | + if ("top" in obj) { | |
| 1941 | + this.offset.click.top = obj.top + this.margins.top; | |
| 1942 | + } | |
| 1943 | + if ("bottom" in obj) { | |
| 1944 | + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; | |
| 1945 | + } | |
| 1946 | + }, | |
| 1947 | + | |
| 1948 | + _isRootNode: function( element ) { | |
| 1949 | + return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; | |
| 1950 | + }, | |
| 1951 | + | |
| 1952 | + _getParentOffset: function() { | |
| 1953 | + | |
| 1954 | + //Get the offsetParent and cache its position | |
| 1955 | + var po = this.offsetParent.offset(), | |
| 1956 | + document = this.document[ 0 ]; | |
| 1957 | + | |
| 1958 | + // This is a special case where we need to modify a offset calculated on start, since the following happened: | |
| 1959 | + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent | |
| 1960 | + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that | |
| 1961 | + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag | |
| 1962 | + if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { | |
| 1963 | + po.left += this.scrollParent.scrollLeft(); | |
| 1964 | + po.top += this.scrollParent.scrollTop(); | |
| 1965 | + } | |
| 1966 | + | |
| 1967 | + if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { | |
| 1968 | + po = { top: 0, left: 0 }; | |
| 1969 | + } | |
| 1970 | + | |
| 1971 | + return { | |
| 1972 | + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), | |
| 1973 | + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) | |
| 1974 | + }; | |
| 1975 | + | |
| 1976 | + }, | |
| 1977 | + | |
| 1978 | + _getRelativeOffset: function() { | |
| 1979 | + if ( this.cssPosition !== "relative" ) { | |
| 1980 | + return { top: 0, left: 0 }; | |
| 1981 | + } | |
| 1982 | + | |
| 1983 | + var p = this.element.position(), | |
| 1984 | + scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); | |
| 1985 | + | |
| 1986 | + return { | |
| 1987 | + top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), | |
| 1988 | + left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) | |
| 1989 | + }; | |
| 1990 | + | |
| 1991 | + }, | |
| 1992 | + | |
| 1993 | + _cacheMargins: function() { | |
| 1994 | + this.margins = { | |
| 1995 | + left: (parseInt(this.element.css("marginLeft"), 10) || 0), | |
| 1996 | + top: (parseInt(this.element.css("marginTop"), 10) || 0), | |
| 1997 | + right: (parseInt(this.element.css("marginRight"), 10) || 0), | |
| 1998 | + bottom: (parseInt(this.element.css("marginBottom"), 10) || 0) | |
| 1999 | + }; | |
| 2000 | + }, | |
| 2001 | + | |
| 2002 | + _cacheHelperProportions: function() { | |
| 2003 | + this.helperProportions = { | |
| 2004 | + width: this.helper.outerWidth(), | |
| 2005 | + height: this.helper.outerHeight() | |
| 2006 | + }; | |
| 2007 | + }, | |
| 2008 | + | |
| 2009 | + _setContainment: function() { | |
| 2010 | + | |
| 2011 | + var isUserScrollable, c, ce, | |
| 2012 | + o = this.options, | |
| 2013 | + document = this.document[ 0 ]; | |
| 2014 | + | |
| 2015 | + this.relativeContainer = null; | |
| 2016 | + | |
| 2017 | + if ( !o.containment ) { | |
| 2018 | + this.containment = null; | |
| 2019 | + return; | |
| 2020 | + } | |
| 2021 | + | |
| 2022 | + if ( o.containment === "window" ) { | |
| 2023 | + this.containment = [ | |
| 2024 | + $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, | |
| 2025 | + $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, | |
| 2026 | + $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, | |
| 2027 | + $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top | |
| 2028 | + ]; | |
| 2029 | + return; | |
| 2030 | + } | |
| 2031 | + | |
| 2032 | + if ( o.containment === "document") { | |
| 2033 | + this.containment = [ | |
| 2034 | + 0, | |
| 2035 | + 0, | |
| 2036 | + $( document ).width() - this.helperProportions.width - this.margins.left, | |
| 2037 | + ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top | |
| 2038 | + ]; | |
| 2039 | + return; | |
| 2040 | + } | |
| 2041 | + | |
| 2042 | + if ( o.containment.constructor === Array ) { | |
| 2043 | + this.containment = o.containment; | |
| 2044 | + return; | |
| 2045 | + } | |
| 2046 | + | |
| 2047 | + if ( o.containment === "parent" ) { | |
| 2048 | + o.containment = this.helper[ 0 ].parentNode; | |
| 2049 | + } | |
| 2050 | + | |
| 2051 | + c = $( o.containment ); | |
| 2052 | + ce = c[ 0 ]; | |
| 2053 | + | |
| 2054 | + if ( !ce ) { | |
| 2055 | + return; | |
| 2056 | + } | |
| 2057 | + | |
| 2058 | + isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); | |
| 2059 | + | |
| 2060 | + this.containment = [ | |
| 2061 | + ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), | |
| 2062 | + ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), | |
| 2063 | + ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - | |
| 2064 | + ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - | |
| 2065 | + ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - | |
| 2066 | + this.helperProportions.width - | |
| 2067 | + this.margins.left - | |
| 2068 | + this.margins.right, | |
| 2069 | + ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - | |
| 2070 | + ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - | |
| 2071 | + ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - | |
| 2072 | + this.helperProportions.height - | |
| 2073 | + this.margins.top - | |
| 2074 | + this.margins.bottom | |
| 2075 | + ]; | |
| 2076 | + this.relativeContainer = c; | |
| 2077 | + }, | |
| 2078 | + | |
| 2079 | + _convertPositionTo: function(d, pos) { | |
| 2080 | + | |
| 2081 | + if (!pos) { | |
| 2082 | + pos = this.position; | |
| 2083 | + } | |
| 2084 | + | |
| 2085 | + var mod = d === "absolute" ? 1 : -1, | |
| 2086 | + scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); | |
| 2087 | + | |
| 2088 | + return { | |
| 2089 | + top: ( | |
| 2090 | + pos.top + // The absolute mouse position | |
| 2091 | + this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
| 2092 | + this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) | |
| 2093 | + ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod) | |
| 2094 | + ), | |
| 2095 | + left: ( | |
| 2096 | + pos.left + // The absolute mouse position | |
| 2097 | + this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
| 2098 | + this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) | |
| 2099 | + ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod) | |
| 2100 | + ) | |
| 2101 | + }; | |
| 2102 | + | |
| 2103 | + }, | |
| 2104 | + | |
| 2105 | + _generatePosition: function( event, constrainPosition ) { | |
| 2106 | + | |
| 2107 | + var containment, co, top, left, | |
| 2108 | + o = this.options, | |
| 2109 | + scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), | |
| 2110 | + pageX = event.pageX, | |
| 2111 | + pageY = event.pageY; | |
| 2112 | + | |
| 2113 | + // Cache the scroll | |
| 2114 | + if ( !scrollIsRootNode || !this.offset.scroll ) { | |
| 2115 | + this.offset.scroll = { | |
| 2116 | + top: this.scrollParent.scrollTop(), | |
| 2117 | + left: this.scrollParent.scrollLeft() | |
| 2118 | + }; | |
| 2119 | + } | |
| 2120 | + | |
| 2121 | + /* | |
| 2122 | + * - Position constraining - | |
| 2123 | + * Constrain the position to a mix of grid, containment. | |
| 2124 | + */ | |
| 2125 | + | |
| 2126 | + // If we are not dragging yet, we won't check for options | |
| 2127 | + if ( constrainPosition ) { | |
| 2128 | + if ( this.containment ) { | |
| 2129 | + if ( this.relativeContainer ){ | |
| 2130 | + co = this.relativeContainer.offset(); | |
| 2131 | + containment = [ | |
| 2132 | + this.containment[ 0 ] + co.left, | |
| 2133 | + this.containment[ 1 ] + co.top, | |
| 2134 | + this.containment[ 2 ] + co.left, | |
| 2135 | + this.containment[ 3 ] + co.top | |
| 2136 | + ]; | |
| 2137 | + } else { | |
| 2138 | + containment = this.containment; | |
| 2139 | + } | |
| 2140 | + | |
| 2141 | + if (event.pageX - this.offset.click.left < containment[0]) { | |
| 2142 | + pageX = containment[0] + this.offset.click.left; | |
| 2143 | + } | |
| 2144 | + if (event.pageY - this.offset.click.top < containment[1]) { | |
| 2145 | + pageY = containment[1] + this.offset.click.top; | |
| 2146 | + } | |
| 2147 | + if (event.pageX - this.offset.click.left > containment[2]) { | |
| 2148 | + pageX = containment[2] + this.offset.click.left; | |
| 2149 | + } | |
| 2150 | + if (event.pageY - this.offset.click.top > containment[3]) { | |
| 2151 | + pageY = containment[3] + this.offset.click.top; | |
| 2152 | + } | |
| 2153 | + } | |
| 2154 | + | |
| 2155 | + if (o.grid) { | |
| 2156 | + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) | |
| 2157 | + top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; | |
| 2158 | + pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; | |
| 2159 | + | |
| 2160 | + left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; | |
| 2161 | + pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; | |
| 2162 | + } | |
| 2163 | + | |
| 2164 | + if ( o.axis === "y" ) { | |
| 2165 | + pageX = this.originalPageX; | |
| 2166 | + } | |
| 2167 | + | |
| 2168 | + if ( o.axis === "x" ) { | |
| 2169 | + pageY = this.originalPageY; | |
| 2170 | + } | |
| 2171 | + } | |
| 2172 | + | |
| 2173 | + return { | |
| 2174 | + top: ( | |
| 2175 | + pageY - // The absolute mouse position | |
| 2176 | + this.offset.click.top - // Click offset (relative to the element) | |
| 2177 | + this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent | |
| 2178 | + this.offset.parent.top + // The offsetParent's offset without borders (offset + border) | |
| 2179 | + ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) | |
| 2180 | + ), | |
| 2181 | + left: ( | |
| 2182 | + pageX - // The absolute mouse position | |
| 2183 | + this.offset.click.left - // Click offset (relative to the element) | |
| 2184 | + this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent | |
| 2185 | + this.offset.parent.left + // The offsetParent's offset without borders (offset + border) | |
| 2186 | + ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) | |
| 2187 | + ) | |
| 2188 | + }; | |
| 2189 | + | |
| 2190 | + }, | |
| 2191 | + | |
| 2192 | + _clear: function() { | |
| 2193 | + this.helper.removeClass("ui-draggable-dragging"); | |
| 2194 | + if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { | |
| 2195 | + this.helper.remove(); | |
| 2196 | + } | |
| 2197 | + this.helper = null; | |
| 2198 | + this.cancelHelperRemoval = false; | |
| 2199 | + if ( this.destroyOnClear ) { | |
| 2200 | + this.destroy(); | |
| 2201 | + } | |
| 2202 | + }, | |
| 2203 | + | |
| 2204 | + _normalizeRightBottom: function() { | |
| 2205 | + if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) { | |
| 2206 | + this.helper.width( this.helper.width() ); | |
| 2207 | + this.helper.css( "right", "auto" ); | |
| 2208 | + } | |
| 2209 | + if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) { | |
| 2210 | + this.helper.height( this.helper.height() ); | |
| 2211 | + this.helper.css( "bottom", "auto" ); | |
| 2212 | + } | |
| 2213 | + }, | |
| 2214 | + | |
| 2215 | + // From now on bulk stuff - mainly helpers | |
| 2216 | + | |
| 2217 | + _trigger: function( type, event, ui ) { | |
| 2218 | + ui = ui || this._uiHash(); | |
| 2219 | + $.ui.plugin.call( this, type, [ event, ui, this ], true ); | |
| 2220 | + | |
| 2221 | + // Absolute position and offset (see #6884 ) have to be recalculated after plugins | |
| 2222 | + if ( /^(drag|start|stop)/.test( type ) ) { | |
| 2223 | + this.positionAbs = this._convertPositionTo( "absolute" ); | |
| 2224 | + ui.offset = this.positionAbs; | |
| 2225 | + } | |
| 2226 | + return $.Widget.prototype._trigger.call( this, type, event, ui ); | |
| 2227 | + }, | |
| 2228 | + | |
| 2229 | + plugins: {}, | |
| 2230 | + | |
| 2231 | + _uiHash: function() { | |
| 2232 | + return { | |
| 2233 | + helper: this.helper, | |
| 2234 | + position: this.position, | |
| 2235 | + originalPosition: this.originalPosition, | |
| 2236 | + offset: this.positionAbs | |
| 2237 | + }; | |
| 2238 | + } | |
| 2239 | + | |
| 2240 | +}); | |
| 2241 | + | |
| 2242 | +$.ui.plugin.add( "draggable", "connectToSortable", { | |
| 2243 | + start: function( event, ui, draggable ) { | |
| 2244 | + var uiSortable = $.extend( {}, ui, { | |
| 2245 | + item: draggable.element | |
| 2246 | + }); | |
| 2247 | + | |
| 2248 | + draggable.sortables = []; | |
| 2249 | + $( draggable.options.connectToSortable ).each(function() { | |
| 2250 | + var sortable = $( this ).sortable( "instance" ); | |
| 2251 | + | |
| 2252 | + if ( sortable && !sortable.options.disabled ) { | |
| 2253 | + draggable.sortables.push( sortable ); | |
| 2254 | + | |
| 2255 | + // refreshPositions is called at drag start to refresh the containerCache | |
| 2256 | + // which is used in drag. This ensures it's initialized and synchronized | |
| 2257 | + // with any changes that might have happened on the page since initialization. | |
| 2258 | + sortable.refreshPositions(); | |
| 2259 | + sortable._trigger("activate", event, uiSortable); | |
| 2260 | + } | |
| 2261 | + }); | |
| 2262 | + }, | |
| 2263 | + stop: function( event, ui, draggable ) { | |
| 2264 | + var uiSortable = $.extend( {}, ui, { | |
| 2265 | + item: draggable.element | |
| 2266 | + }); | |
| 2267 | + | |
| 2268 | + draggable.cancelHelperRemoval = false; | |
| 2269 | + | |
| 2270 | + $.each( draggable.sortables, function() { | |
| 2271 | + var sortable = this; | |
| 2272 | + | |
| 2273 | + if ( sortable.isOver ) { | |
| 2274 | + sortable.isOver = 0; | |
| 2275 | + | |
| 2276 | + // Allow this sortable to handle removing the helper | |
| 2277 | + draggable.cancelHelperRemoval = true; | |
| 2278 | + sortable.cancelHelperRemoval = false; | |
| 2279 | + | |
| 2280 | + // Use _storedCSS To restore properties in the sortable, | |
| 2281 | + // as this also handles revert (#9675) since the draggable | |
| 2282 | + // may have modified them in unexpected ways (#8809) | |
| 2283 | + sortable._storedCSS = { | |
| 2284 | + position: sortable.placeholder.css( "position" ), | |
| 2285 | + top: sortable.placeholder.css( "top" ), | |
| 2286 | + left: sortable.placeholder.css( "left" ) | |
| 2287 | + }; | |
| 2288 | + | |
| 2289 | + sortable._mouseStop(event); | |
| 2290 | + | |
| 2291 | + // Once drag has ended, the sortable should return to using | |
| 2292 | + // its original helper, not the shared helper from draggable | |
| 2293 | + sortable.options.helper = sortable.options._helper; | |
| 2294 | + } else { | |
| 2295 | + // Prevent this Sortable from removing the helper. | |
| 2296 | + // However, don't set the draggable to remove the helper | |
| 2297 | + // either as another connected Sortable may yet handle the removal. | |
| 2298 | + sortable.cancelHelperRemoval = true; | |
| 2299 | + | |
| 2300 | + sortable._trigger( "deactivate", event, uiSortable ); | |
| 2301 | + } | |
| 2302 | + }); | |
| 2303 | + }, | |
| 2304 | + drag: function( event, ui, draggable ) { | |
| 2305 | + $.each( draggable.sortables, function() { | |
| 2306 | + var innermostIntersecting = false, | |
| 2307 | + sortable = this; | |
| 2308 | + | |
| 2309 | + // Copy over variables that sortable's _intersectsWith uses | |
| 2310 | + sortable.positionAbs = draggable.positionAbs; | |
| 2311 | + sortable.helperProportions = draggable.helperProportions; | |
| 2312 | + sortable.offset.click = draggable.offset.click; | |
| 2313 | + | |
| 2314 | + if ( sortable._intersectsWith( sortable.containerCache ) ) { | |
| 2315 | + innermostIntersecting = true; | |
| 2316 | + | |
| 2317 | + $.each( draggable.sortables, function() { | |
| 2318 | + // Copy over variables that sortable's _intersectsWith uses | |
| 2319 | + this.positionAbs = draggable.positionAbs; | |
| 2320 | + this.helperProportions = draggable.helperProportions; | |
| 2321 | + this.offset.click = draggable.offset.click; | |
| 2322 | + | |
| 2323 | + if ( this !== sortable && | |
| 2324 | + this._intersectsWith( this.containerCache ) && | |
| 2325 | + $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { | |
| 2326 | + innermostIntersecting = false; | |
| 2327 | + } | |
| 2328 | + | |
| 2329 | + return innermostIntersecting; | |
| 2330 | + }); | |
| 2331 | + } | |
| 2332 | + | |
| 2333 | + if ( innermostIntersecting ) { | |
| 2334 | + // If it intersects, we use a little isOver variable and set it once, | |
| 2335 | + // so that the move-in stuff gets fired only once. | |
| 2336 | + if ( !sortable.isOver ) { | |
| 2337 | + sortable.isOver = 1; | |
| 2338 | + | |
| 2339 | + // Store draggable's parent in case we need to reappend to it later. | |
| 2340 | + draggable._parent = ui.helper.parent(); | |
| 2341 | + | |
| 2342 | + sortable.currentItem = ui.helper | |
| 2343 | + .appendTo( sortable.element ) | |
| 2344 | + .data( "ui-sortable-item", true ); | |
| 2345 | + | |
| 2346 | + // Store helper option to later restore it | |
| 2347 | + sortable.options._helper = sortable.options.helper; | |
| 2348 | + | |
| 2349 | + sortable.options.helper = function() { | |
| 2350 | + return ui.helper[ 0 ]; | |
| 2351 | + }; | |
| 2352 | + | |
| 2353 | + // Fire the start events of the sortable with our passed browser event, | |
| 2354 | + // and our own helper (so it doesn't create a new one) | |
| 2355 | + event.target = sortable.currentItem[ 0 ]; | |
| 2356 | + sortable._mouseCapture( event, true ); | |
| 2357 | + sortable._mouseStart( event, true, true ); | |
| 2358 | + | |
| 2359 | + // Because the browser event is way off the new appended portlet, | |
| 2360 | + // modify necessary variables to reflect the changes | |
| 2361 | + sortable.offset.click.top = draggable.offset.click.top; | |
| 2362 | + sortable.offset.click.left = draggable.offset.click.left; | |
| 2363 | + sortable.offset.parent.left -= draggable.offset.parent.left - | |
| 2364 | + sortable.offset.parent.left; | |
| 2365 | + sortable.offset.parent.top -= draggable.offset.parent.top - | |
| 2366 | + sortable.offset.parent.top; | |
| 2367 | + | |
| 2368 | + draggable._trigger( "toSortable", event ); | |
| 2369 | + | |
| 2370 | + // Inform draggable that the helper is in a valid drop zone, | |
| 2371 | + // used solely in the revert option to handle "valid/invalid". | |
| 2372 | + draggable.dropped = sortable.element; | |
| 2373 | + | |
| 2374 | + // Need to refreshPositions of all sortables in the case that | |
| 2375 | + // adding to one sortable changes the location of the other sortables (#9675) | |
| 2376 | + $.each( draggable.sortables, function() { | |
| 2377 | + this.refreshPositions(); | |
| 2378 | + }); | |
| 2379 | + | |
| 2380 | + // hack so receive/update callbacks work (mostly) | |
| 2381 | + draggable.currentItem = draggable.element; | |
| 2382 | + sortable.fromOutside = draggable; | |
| 2383 | + } | |
| 2384 | + | |
| 2385 | + if ( sortable.currentItem ) { | |
| 2386 | + sortable._mouseDrag( event ); | |
| 2387 | + // Copy the sortable's position because the draggable's can potentially reflect | |
| 2388 | + // a relative position, while sortable is always absolute, which the dragged | |
| 2389 | + // element has now become. (#8809) | |
| 2390 | + ui.position = sortable.position; | |
| 2391 | + } | |
| 2392 | + } else { | |
| 2393 | + // If it doesn't intersect with the sortable, and it intersected before, | |
| 2394 | + // we fake the drag stop of the sortable, but make sure it doesn't remove | |
| 2395 | + // the helper by using cancelHelperRemoval. | |
| 2396 | + if ( sortable.isOver ) { | |
| 2397 | + | |
| 2398 | + sortable.isOver = 0; | |
| 2399 | + sortable.cancelHelperRemoval = true; | |
| 2400 | + | |
| 2401 | + // Calling sortable's mouseStop would trigger a revert, | |
| 2402 | + // so revert must be temporarily false until after mouseStop is called. | |
| 2403 | + sortable.options._revert = sortable.options.revert; | |
| 2404 | + sortable.options.revert = false; | |
| 2405 | + | |
| 2406 | + sortable._trigger( "out", event, sortable._uiHash( sortable ) ); | |
| 2407 | + sortable._mouseStop( event, true ); | |
| 2408 | + | |
| 2409 | + // restore sortable behaviors that were modfied | |
| 2410 | + // when the draggable entered the sortable area (#9481) | |
| 2411 | + sortable.options.revert = sortable.options._revert; | |
| 2412 | + sortable.options.helper = sortable.options._helper; | |
| 2413 | + | |
| 2414 | + if ( sortable.placeholder ) { | |
| 2415 | + sortable.placeholder.remove(); | |
| 2416 | + } | |
| 2417 | + | |
| 2418 | + // Restore and recalculate the draggable's offset considering the sortable | |
| 2419 | + // may have modified them in unexpected ways. (#8809, #10669) | |
| 2420 | + ui.helper.appendTo( draggable._parent ); | |
| 2421 | + draggable._refreshOffsets( event ); | |
| 2422 | + ui.position = draggable._generatePosition( event, true ); | |
| 2423 | + | |
| 2424 | + draggable._trigger( "fromSortable", event ); | |
| 2425 | + | |
| 2426 | + // Inform draggable that the helper is no longer in a valid drop zone | |
| 2427 | + draggable.dropped = false; | |
| 2428 | + | |
| 2429 | + // Need to refreshPositions of all sortables just in case removing | |
| 2430 | + // from one sortable changes the location of other sortables (#9675) | |
| 2431 | + $.each( draggable.sortables, function() { | |
| 2432 | + this.refreshPositions(); | |
| 2433 | + }); | |
| 2434 | + } | |
| 2435 | + } | |
| 2436 | + }); | |
| 2437 | + } | |
| 2438 | +}); | |
| 2439 | + | |
| 2440 | +$.ui.plugin.add("draggable", "cursor", { | |
| 2441 | + start: function( event, ui, instance ) { | |
| 2442 | + var t = $( "body" ), | |
| 2443 | + o = instance.options; | |
| 2444 | + | |
| 2445 | + if (t.css("cursor")) { | |
| 2446 | + o._cursor = t.css("cursor"); | |
| 2447 | + } | |
| 2448 | + t.css("cursor", o.cursor); | |
| 2449 | + }, | |
| 2450 | + stop: function( event, ui, instance ) { | |
| 2451 | + var o = instance.options; | |
| 2452 | + if (o._cursor) { | |
| 2453 | + $("body").css("cursor", o._cursor); | |
| 2454 | + } | |
| 2455 | + } | |
| 2456 | +}); | |
| 2457 | + | |
| 2458 | +$.ui.plugin.add("draggable", "opacity", { | |
| 2459 | + start: function( event, ui, instance ) { | |
| 2460 | + var t = $( ui.helper ), | |
| 2461 | + o = instance.options; | |
| 2462 | + if (t.css("opacity")) { | |
| 2463 | + o._opacity = t.css("opacity"); | |
| 2464 | + } | |
| 2465 | + t.css("opacity", o.opacity); | |
| 2466 | + }, | |
| 2467 | + stop: function( event, ui, instance ) { | |
| 2468 | + var o = instance.options; | |
| 2469 | + if (o._opacity) { | |
| 2470 | + $(ui.helper).css("opacity", o._opacity); | |
| 2471 | + } | |
| 2472 | + } | |
| 2473 | +}); | |
| 2474 | + | |
| 2475 | +$.ui.plugin.add("draggable", "scroll", { | |
| 2476 | + start: function( event, ui, i ) { | |
| 2477 | + if ( !i.scrollParentNotHidden ) { | |
| 2478 | + i.scrollParentNotHidden = i.helper.scrollParent( false ); | |
| 2479 | + } | |
| 2480 | + | |
| 2481 | + if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { | |
| 2482 | + i.overflowOffset = i.scrollParentNotHidden.offset(); | |
| 2483 | + } | |
| 2484 | + }, | |
| 2485 | + drag: function( event, ui, i ) { | |
| 2486 | + | |
| 2487 | + var o = i.options, | |
| 2488 | + scrolled = false, | |
| 2489 | + scrollParent = i.scrollParentNotHidden[ 0 ], | |
| 2490 | + document = i.document[ 0 ]; | |
| 2491 | + | |
| 2492 | + if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { | |
| 2493 | + if ( !o.axis || o.axis !== "x" ) { | |
| 2494 | + if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) { | |
| 2495 | + scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; | |
| 2496 | + } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { | |
| 2497 | + scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; | |
| 2498 | + } | |
| 2499 | + } | |
| 2500 | + | |
| 2501 | + if ( !o.axis || o.axis !== "y" ) { | |
| 2502 | + if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) { | |
| 2503 | + scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; | |
| 2504 | + } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { | |
| 2505 | + scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; | |
| 2506 | + } | |
| 2507 | + } | |
| 2508 | + | |
| 2509 | + } else { | |
| 2510 | + | |
| 2511 | + if (!o.axis || o.axis !== "x") { | |
| 2512 | + if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) { | |
| 2513 | + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); | |
| 2514 | + } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { | |
| 2515 | + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); | |
| 2516 | + } | |
| 2517 | + } | |
| 2518 | + | |
| 2519 | + if (!o.axis || o.axis !== "y") { | |
| 2520 | + if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { | |
| 2521 | + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); | |
| 2522 | + } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { | |
| 2523 | + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); | |
| 2524 | + } | |
| 2525 | + } | |
| 2526 | + | |
| 2527 | + } | |
| 2528 | + | |
| 2529 | + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { | |
| 2530 | + $.ui.ddmanager.prepareOffsets(i, event); | |
| 2531 | + } | |
| 2532 | + | |
| 2533 | + } | |
| 2534 | +}); | |
| 2535 | + | |
| 2536 | +$.ui.plugin.add("draggable", "snap", { | |
| 2537 | + start: function( event, ui, i ) { | |
| 2538 | + | |
| 2539 | + var o = i.options; | |
| 2540 | + | |
| 2541 | + i.snapElements = []; | |
| 2542 | + | |
| 2543 | + $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { | |
| 2544 | + var $t = $(this), | |
| 2545 | + $o = $t.offset(); | |
| 2546 | + if (this !== i.element[0]) { | |
| 2547 | + i.snapElements.push({ | |
| 2548 | + item: this, | |
| 2549 | + width: $t.outerWidth(), height: $t.outerHeight(), | |
| 2550 | + top: $o.top, left: $o.left | |
| 2551 | + }); | |
| 2552 | + } | |
| 2553 | + }); | |
| 2554 | + | |
| 2555 | + }, | |
| 2556 | + drag: function( event, ui, inst ) { | |
| 2557 | + | |
| 2558 | + var ts, bs, ls, rs, l, r, t, b, i, first, | |
| 2559 | + o = inst.options, | |
| 2560 | + d = o.snapTolerance, | |
| 2561 | + x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, | |
| 2562 | + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; | |
| 2563 | + | |
| 2564 | + for (i = inst.snapElements.length - 1; i >= 0; i--){ | |
| 2565 | + | |
| 2566 | + l = inst.snapElements[i].left - inst.margins.left; | |
| 2567 | + r = l + inst.snapElements[i].width; | |
| 2568 | + t = inst.snapElements[i].top - inst.margins.top; | |
| 2569 | + b = t + inst.snapElements[i].height; | |
| 2570 | + | |
| 2571 | + if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { | |
| 2572 | + if (inst.snapElements[i].snapping) { | |
| 2573 | + (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); | |
| 2574 | + } | |
| 2575 | + inst.snapElements[i].snapping = false; | |
| 2576 | + continue; | |
| 2577 | + } | |
| 2578 | + | |
| 2579 | + if (o.snapMode !== "inner") { | |
| 2580 | + ts = Math.abs(t - y2) <= d; | |
| 2581 | + bs = Math.abs(b - y1) <= d; | |
| 2582 | + ls = Math.abs(l - x2) <= d; | |
| 2583 | + rs = Math.abs(r - x1) <= d; | |
| 2584 | + if (ts) { | |
| 2585 | + ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top; | |
| 2586 | + } | |
| 2587 | + if (bs) { | |
| 2588 | + ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top; | |
| 2589 | + } | |
| 2590 | + if (ls) { | |
| 2591 | + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left; | |
| 2592 | + } | |
| 2593 | + if (rs) { | |
| 2594 | + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left; | |
| 2595 | + } | |
| 2596 | + } | |
| 2597 | + | |
| 2598 | + first = (ts || bs || ls || rs); | |
| 2599 | + | |
| 2600 | + if (o.snapMode !== "outer") { | |
| 2601 | + ts = Math.abs(t - y1) <= d; | |
| 2602 | + bs = Math.abs(b - y2) <= d; | |
| 2603 | + ls = Math.abs(l - x1) <= d; | |
| 2604 | + rs = Math.abs(r - x2) <= d; | |
| 2605 | + if (ts) { | |
| 2606 | + ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top; | |
| 2607 | + } | |
| 2608 | + if (bs) { | |
| 2609 | + ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top; | |
| 2610 | + } | |
| 2611 | + if (ls) { | |
| 2612 | + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left; | |
| 2613 | + } | |
| 2614 | + if (rs) { | |
| 2615 | + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left; | |
| 2616 | + } | |
| 2617 | + } | |
| 2618 | + | |
| 2619 | + if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { | |
| 2620 | + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); | |
| 2621 | + } | |
| 2622 | + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); | |
| 2623 | + | |
| 2624 | + } | |
| 2625 | + | |
| 2626 | + } | |
| 2627 | +}); | |
| 2628 | + | |
| 2629 | +$.ui.plugin.add("draggable", "stack", { | |
| 2630 | + start: function( event, ui, instance ) { | |
| 2631 | + var min, | |
| 2632 | + o = instance.options, | |
| 2633 | + group = $.makeArray($(o.stack)).sort(function(a, b) { | |
| 2634 | + return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0); | |
| 2635 | + }); | |
| 2636 | + | |
| 2637 | + if (!group.length) { return; } | |
| 2638 | + | |
| 2639 | + min = parseInt($(group[0]).css("zIndex"), 10) || 0; | |
| 2640 | + $(group).each(function(i) { | |
| 2641 | + $(this).css("zIndex", min + i); | |
| 2642 | + }); | |
| 2643 | + this.css("zIndex", (min + group.length)); | |
| 2644 | + } | |
| 2645 | +}); | |
| 2646 | + | |
| 2647 | +$.ui.plugin.add("draggable", "zIndex", { | |
| 2648 | + start: function( event, ui, instance ) { | |
| 2649 | + var t = $( ui.helper ), | |
| 2650 | + o = instance.options; | |
| 2651 | + | |
| 2652 | + if (t.css("zIndex")) { | |
| 2653 | + o._zIndex = t.css("zIndex"); | |
| 2654 | + } | |
| 2655 | + t.css("zIndex", o.zIndex); | |
| 2656 | + }, | |
| 2657 | + stop: function( event, ui, instance ) { | |
| 2658 | + var o = instance.options; | |
| 2659 | + | |
| 2660 | + if (o._zIndex) { | |
| 2661 | + $(ui.helper).css("zIndex", o._zIndex); | |
| 2662 | + } | |
| 2663 | + } | |
| 2664 | +}); | |
| 2665 | + | |
| 2666 | +var draggable = $.ui.draggable; | |
| 2667 | + | |
| 2668 | + | |
| 2669 | +/*! | |
| 2670 | + * jQuery UI Droppable 1.11.4 | |
| 2671 | + * http://jqueryui.com | |
| 2672 | + * | |
| 2673 | + * Copyright jQuery Foundation and other contributors | |
| 2674 | + * Released under the MIT license. | |
| 2675 | + * http://jquery.org/license | |
| 2676 | + * | |
| 2677 | + * http://api.jqueryui.com/droppable/ | |
| 2678 | + */ | |
| 2679 | + | |
| 2680 | + | |
| 2681 | +$.widget( "ui.droppable", { | |
| 2682 | + version: "1.11.4", | |
| 2683 | + widgetEventPrefix: "drop", | |
| 2684 | + options: { | |
| 2685 | + accept: "*", | |
| 2686 | + activeClass: false, | |
| 2687 | + addClasses: true, | |
| 2688 | + greedy: false, | |
| 2689 | + hoverClass: false, | |
| 2690 | + scope: "default", | |
| 2691 | + tolerance: "intersect", | |
| 2692 | + | |
| 2693 | + // callbacks | |
| 2694 | + activate: null, | |
| 2695 | + deactivate: null, | |
| 2696 | + drop: null, | |
| 2697 | + out: null, | |
| 2698 | + over: null | |
| 2699 | + }, | |
| 2700 | + _create: function() { | |
| 2701 | + | |
| 2702 | + var proportions, | |
| 2703 | + o = this.options, | |
| 2704 | + accept = o.accept; | |
| 2705 | + | |
| 2706 | + this.isover = false; | |
| 2707 | + this.isout = true; | |
| 2708 | + | |
| 2709 | + this.accept = $.isFunction( accept ) ? accept : function( d ) { | |
| 2710 | + return d.is( accept ); | |
| 2711 | + }; | |
| 2712 | + | |
| 2713 | + this.proportions = function( /* valueToWrite */ ) { | |
| 2714 | + if ( arguments.length ) { | |
| 2715 | + // Store the droppable's proportions | |
| 2716 | + proportions = arguments[ 0 ]; | |
| 2717 | + } else { | |
| 2718 | + // Retrieve or derive the droppable's proportions | |
| 2719 | + return proportions ? | |
| 2720 | + proportions : | |
| 2721 | + proportions = { | |
| 2722 | + width: this.element[ 0 ].offsetWidth, | |
| 2723 | + height: this.element[ 0 ].offsetHeight | |
| 2724 | + }; | |
| 2725 | + } | |
| 2726 | + }; | |
| 2727 | + | |
| 2728 | + this._addToManager( o.scope ); | |
| 2729 | + | |
| 2730 | + o.addClasses && this.element.addClass( "ui-droppable" ); | |
| 2731 | + | |
| 2732 | + }, | |
| 2733 | + | |
| 2734 | + _addToManager: function( scope ) { | |
| 2735 | + // Add the reference and positions to the manager | |
| 2736 | + $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; | |
| 2737 | + $.ui.ddmanager.droppables[ scope ].push( this ); | |
| 2738 | + }, | |
| 2739 | + | |
| 2740 | + _splice: function( drop ) { | |
| 2741 | + var i = 0; | |
| 2742 | + for ( ; i < drop.length; i++ ) { | |
| 2743 | + if ( drop[ i ] === this ) { | |
| 2744 | + drop.splice( i, 1 ); | |
| 2745 | + } | |
| 2746 | + } | |
| 2747 | + }, | |
| 2748 | + | |
| 2749 | + _destroy: function() { | |
| 2750 | + var drop = $.ui.ddmanager.droppables[ this.options.scope ]; | |
| 2751 | + | |
| 2752 | + this._splice( drop ); | |
| 2753 | + | |
| 2754 | + this.element.removeClass( "ui-droppable ui-droppable-disabled" ); | |
| 2755 | + }, | |
| 2756 | + | |
| 2757 | + _setOption: function( key, value ) { | |
| 2758 | + | |
| 2759 | + if ( key === "accept" ) { | |
| 2760 | + this.accept = $.isFunction( value ) ? value : function( d ) { | |
| 2761 | + return d.is( value ); | |
| 2762 | + }; | |
| 2763 | + } else if ( key === "scope" ) { | |
| 2764 | + var drop = $.ui.ddmanager.droppables[ this.options.scope ]; | |
| 2765 | + | |
| 2766 | + this._splice( drop ); | |
| 2767 | + this._addToManager( value ); | |
| 2768 | + } | |
| 2769 | + | |
| 2770 | + this._super( key, value ); | |
| 2771 | + }, | |
| 2772 | + | |
| 2773 | + _activate: function( event ) { | |
| 2774 | + var draggable = $.ui.ddmanager.current; | |
| 2775 | + if ( this.options.activeClass ) { | |
| 2776 | + this.element.addClass( this.options.activeClass ); | |
| 2777 | + } | |
| 2778 | + if ( draggable ){ | |
| 2779 | + this._trigger( "activate", event, this.ui( draggable ) ); | |
| 2780 | + } | |
| 2781 | + }, | |
| 2782 | + | |
| 2783 | + _deactivate: function( event ) { | |
| 2784 | + var draggable = $.ui.ddmanager.current; | |
| 2785 | + if ( this.options.activeClass ) { | |
| 2786 | + this.element.removeClass( this.options.activeClass ); | |
| 2787 | + } | |
| 2788 | + if ( draggable ){ | |
| 2789 | + this._trigger( "deactivate", event, this.ui( draggable ) ); | |
| 2790 | + } | |
| 2791 | + }, | |
| 2792 | + | |
| 2793 | + _over: function( event ) { | |
| 2794 | + | |
| 2795 | + var draggable = $.ui.ddmanager.current; | |
| 2796 | + | |
| 2797 | + // Bail if draggable and droppable are same element | |
| 2798 | + if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { | |
| 2799 | + return; | |
| 2800 | + } | |
| 2801 | + | |
| 2802 | + if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { | |
| 2803 | + if ( this.options.hoverClass ) { | |
| 2804 | + this.element.addClass( this.options.hoverClass ); | |
| 2805 | + } | |
| 2806 | + this._trigger( "over", event, this.ui( draggable ) ); | |
| 2807 | + } | |
| 2808 | + | |
| 2809 | + }, | |
| 2810 | + | |
| 2811 | + _out: function( event ) { | |
| 2812 | + | |
| 2813 | + var draggable = $.ui.ddmanager.current; | |
| 2814 | + | |
| 2815 | + // Bail if draggable and droppable are same element | |
| 2816 | + if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { | |
| 2817 | + return; | |
| 2818 | + } | |
| 2819 | + | |
| 2820 | + if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { | |
| 2821 | + if ( this.options.hoverClass ) { | |
| 2822 | + this.element.removeClass( this.options.hoverClass ); | |
| 2823 | + } | |
| 2824 | + this._trigger( "out", event, this.ui( draggable ) ); | |
| 2825 | + } | |
| 2826 | + | |
| 2827 | + }, | |
| 2828 | + | |
| 2829 | + _drop: function( event, custom ) { | |
| 2830 | + | |
| 2831 | + var draggable = custom || $.ui.ddmanager.current, | |
| 2832 | + childrenIntersection = false; | |
| 2833 | + | |
| 2834 | + // Bail if draggable and droppable are same element | |
| 2835 | + if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { | |
| 2836 | + return false; | |
| 2837 | + } | |
| 2838 | + | |
| 2839 | + this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() { | |
| 2840 | + var inst = $( this ).droppable( "instance" ); | |
| 2841 | + if ( | |
| 2842 | + inst.options.greedy && | |
| 2843 | + !inst.options.disabled && | |
| 2844 | + inst.options.scope === draggable.options.scope && | |
| 2845 | + inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) && | |
| 2846 | + $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event ) | |
| 2847 | + ) { childrenIntersection = true; return false; } | |
| 2848 | + }); | |
| 2849 | + if ( childrenIntersection ) { | |
| 2850 | + return false; | |
| 2851 | + } | |
| 2852 | + | |
| 2853 | + if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { | |
| 2854 | + if ( this.options.activeClass ) { | |
| 2855 | + this.element.removeClass( this.options.activeClass ); | |
| 2856 | + } | |
| 2857 | + if ( this.options.hoverClass ) { | |
| 2858 | + this.element.removeClass( this.options.hoverClass ); | |
| 2859 | + } | |
| 2860 | + this._trigger( "drop", event, this.ui( draggable ) ); | |
| 2861 | + return this.element; | |
| 2862 | + } | |
| 2863 | + | |
| 2864 | + return false; | |
| 2865 | + | |
| 2866 | + }, | |
| 2867 | + | |
| 2868 | + ui: function( c ) { | |
| 2869 | + return { | |
| 2870 | + draggable: ( c.currentItem || c.element ), | |
| 2871 | + helper: c.helper, | |
| 2872 | + position: c.position, | |
| 2873 | + offset: c.positionAbs | |
| 2874 | + }; | |
| 2875 | + } | |
| 2876 | + | |
| 2877 | +}); | |
| 2878 | + | |
| 2879 | +$.ui.intersect = (function() { | |
| 2880 | + function isOverAxis( x, reference, size ) { | |
| 2881 | + return ( x >= reference ) && ( x < ( reference + size ) ); | |
| 2882 | + } | |
| 2883 | + | |
| 2884 | + return function( draggable, droppable, toleranceMode, event ) { | |
| 2885 | + | |
| 2886 | + if ( !droppable.offset ) { | |
| 2887 | + return false; | |
| 2888 | + } | |
| 2889 | + | |
| 2890 | + var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left, | |
| 2891 | + y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top, | |
| 2892 | + x2 = x1 + draggable.helperProportions.width, | |
| 2893 | + y2 = y1 + draggable.helperProportions.height, | |
| 2894 | + l = droppable.offset.left, | |
| 2895 | + t = droppable.offset.top, | |
| 2896 | + r = l + droppable.proportions().width, | |
| 2897 | + b = t + droppable.proportions().height; | |
| 2898 | + | |
| 2899 | + switch ( toleranceMode ) { | |
| 2900 | + case "fit": | |
| 2901 | + return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); | |
| 2902 | + case "intersect": | |
| 2903 | + return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half | |
| 2904 | + x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half | |
| 2905 | + t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half | |
| 2906 | + y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half | |
| 2907 | + case "pointer": | |
| 2908 | + return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width ); | |
| 2909 | + case "touch": | |
| 2910 | + return ( | |
| 2911 | + ( y1 >= t && y1 <= b ) || // Top edge touching | |
| 2912 | + ( y2 >= t && y2 <= b ) || // Bottom edge touching | |
| 2913 | + ( y1 < t && y2 > b ) // Surrounded vertically | |
| 2914 | + ) && ( | |
| 2915 | + ( x1 >= l && x1 <= r ) || // Left edge touching | |
| 2916 | + ( x2 >= l && x2 <= r ) || // Right edge touching | |
| 2917 | + ( x1 < l && x2 > r ) // Surrounded horizontally | |
| 2918 | + ); | |
| 2919 | + default: | |
| 2920 | + return false; | |
| 2921 | + } | |
| 2922 | + }; | |
| 2923 | +})(); | |
| 2924 | + | |
| 2925 | +/* | |
| 2926 | + This manager tracks offsets of draggables and droppables | |
| 2927 | +*/ | |
| 2928 | +$.ui.ddmanager = { | |
| 2929 | + current: null, | |
| 2930 | + droppables: { "default": [] }, | |
| 2931 | + prepareOffsets: function( t, event ) { | |
| 2932 | + | |
| 2933 | + var i, j, | |
| 2934 | + m = $.ui.ddmanager.droppables[ t.options.scope ] || [], | |
| 2935 | + type = event ? event.type : null, // workaround for #2317 | |
| 2936 | + list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); | |
| 2937 | + | |
| 2938 | + droppablesLoop: for ( i = 0; i < m.length; i++ ) { | |
| 2939 | + | |
| 2940 | + // No disabled and non-accepted | |
| 2941 | + if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) { | |
| 2942 | + continue; | |
| 2943 | + } | |
| 2944 | + | |
| 2945 | + // Filter out elements in the current dragged item | |
| 2946 | + for ( j = 0; j < list.length; j++ ) { | |
| 2947 | + if ( list[ j ] === m[ i ].element[ 0 ] ) { | |
| 2948 | + m[ i ].proportions().height = 0; | |
| 2949 | + continue droppablesLoop; | |
| 2950 | + } | |
| 2951 | + } | |
| 2952 | + | |
| 2953 | + m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; | |
| 2954 | + if ( !m[ i ].visible ) { | |
| 2955 | + continue; | |
| 2956 | + } | |
| 2957 | + | |
| 2958 | + // Activate the droppable if used directly from draggables | |
| 2959 | + if ( type === "mousedown" ) { | |
| 2960 | + m[ i ]._activate.call( m[ i ], event ); | |
| 2961 | + } | |
| 2962 | + | |
| 2963 | + m[ i ].offset = m[ i ].element.offset(); | |
| 2964 | + m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); | |
| 2965 | + | |
| 2966 | + } | |
| 2967 | + | |
| 2968 | + }, | |
| 2969 | + drop: function( draggable, event ) { | |
| 2970 | + | |
| 2971 | + var dropped = false; | |
| 2972 | + // Create a copy of the droppables in case the list changes during the drop (#9116) | |
| 2973 | + $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { | |
| 2974 | + | |
| 2975 | + if ( !this.options ) { | |
| 2976 | + return; | |
| 2977 | + } | |
| 2978 | + if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { | |
| 2979 | + dropped = this._drop.call( this, event ) || dropped; | |
| 2980 | + } | |
| 2981 | + | |
| 2982 | + if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { | |
| 2983 | + this.isout = true; | |
| 2984 | + this.isover = false; | |
| 2985 | + this._deactivate.call( this, event ); | |
| 2986 | + } | |
| 2987 | + | |
| 2988 | + }); | |
| 2989 | + return dropped; | |
| 2990 | + | |
| 2991 | + }, | |
| 2992 | + dragStart: function( draggable, event ) { | |
| 2993 | + // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) | |
| 2994 | + draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { | |
| 2995 | + if ( !draggable.options.refreshPositions ) { | |
| 2996 | + $.ui.ddmanager.prepareOffsets( draggable, event ); | |
| 2997 | + } | |
| 2998 | + }); | |
| 2999 | + }, | |
| 3000 | + drag: function( draggable, event ) { | |
| 3001 | + | |
| 3002 | + // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. | |
| 3003 | + if ( draggable.options.refreshPositions ) { | |
| 3004 | + $.ui.ddmanager.prepareOffsets( draggable, event ); | |
| 3005 | + } | |
| 3006 | + | |
| 3007 | + // Run through all droppables and check their positions based on specific tolerance options | |
| 3008 | + $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { | |
| 3009 | + | |
| 3010 | + if ( this.options.disabled || this.greedyChild || !this.visible ) { | |
| 3011 | + return; | |
| 3012 | + } | |
| 3013 | + | |
| 3014 | + var parentInstance, scope, parent, | |
| 3015 | + intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), | |
| 3016 | + c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null ); | |
| 3017 | + if ( !c ) { | |
| 3018 | + return; | |
| 3019 | + } | |
| 3020 | + | |
| 3021 | + if ( this.options.greedy ) { | |
| 3022 | + // find droppable parents with same scope | |
| 3023 | + scope = this.options.scope; | |
| 3024 | + parent = this.element.parents( ":data(ui-droppable)" ).filter(function() { | |
| 3025 | + return $( this ).droppable( "instance" ).options.scope === scope; | |
| 3026 | + }); | |
| 3027 | + | |
| 3028 | + if ( parent.length ) { | |
| 3029 | + parentInstance = $( parent[ 0 ] ).droppable( "instance" ); | |
| 3030 | + parentInstance.greedyChild = ( c === "isover" ); | |
| 3031 | + } | |
| 3032 | + } | |
| 3033 | + | |
| 3034 | + // we just moved into a greedy child | |
| 3035 | + if ( parentInstance && c === "isover" ) { | |
| 3036 | + parentInstance.isover = false; | |
| 3037 | + parentInstance.isout = true; | |
| 3038 | + parentInstance._out.call( parentInstance, event ); | |
| 3039 | + } | |
| 3040 | + | |
| 3041 | + this[ c ] = true; | |
| 3042 | + this[c === "isout" ? "isover" : "isout"] = false; | |
| 3043 | + this[c === "isover" ? "_over" : "_out"].call( this, event ); | |
| 3044 | + | |
| 3045 | + // we just moved out of a greedy child | |
| 3046 | + if ( parentInstance && c === "isout" ) { | |
| 3047 | + parentInstance.isout = false; | |
| 3048 | + parentInstance.isover = true; | |
| 3049 | + parentInstance._over.call( parentInstance, event ); | |
| 3050 | + } | |
| 3051 | + }); | |
| 3052 | + | |
| 3053 | + }, | |
| 3054 | + dragStop: function( draggable, event ) { | |
| 3055 | + draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); | |
| 3056 | + // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) | |
| 3057 | + if ( !draggable.options.refreshPositions ) { | |
| 3058 | + $.ui.ddmanager.prepareOffsets( draggable, event ); | |
| 3059 | + } | |
| 3060 | + } | |
| 3061 | +}; | |
| 3062 | + | |
| 3063 | +var droppable = $.ui.droppable; | |
| 3064 | + | |
| 3065 | + | |
| 3066 | +/*! | |
| 3067 | + * jQuery UI Resizable 1.11.4 | |
| 3068 | + * http://jqueryui.com | |
| 3069 | + * | |
| 3070 | + * Copyright jQuery Foundation and other contributors | |
| 3071 | + * Released under the MIT license. | |
| 3072 | + * http://jquery.org/license | |
| 3073 | + * | |
| 3074 | + * http://api.jqueryui.com/resizable/ | |
| 3075 | + */ | |
| 3076 | + | |
| 3077 | + | |
| 3078 | +$.widget("ui.resizable", $.ui.mouse, { | |
| 3079 | + version: "1.11.4", | |
| 3080 | + widgetEventPrefix: "resize", | |
| 3081 | + options: { | |
| 3082 | + alsoResize: false, | |
| 3083 | + animate: false, | |
| 3084 | + animateDuration: "slow", | |
| 3085 | + animateEasing: "swing", | |
| 3086 | + aspectRatio: false, | |
| 3087 | + autoHide: false, | |
| 3088 | + containment: false, | |
| 3089 | + ghost: false, | |
| 3090 | + grid: false, | |
| 3091 | + handles: "e,s,se", | |
| 3092 | + helper: false, | |
| 3093 | + maxHeight: null, | |
| 3094 | + maxWidth: null, | |
| 3095 | + minHeight: 10, | |
| 3096 | + minWidth: 10, | |
| 3097 | + // See #7960 | |
| 3098 | + zIndex: 90, | |
| 3099 | + | |
| 3100 | + // callbacks | |
| 3101 | + resize: null, | |
| 3102 | + start: null, | |
| 3103 | + stop: null | |
| 3104 | + }, | |
| 3105 | + | |
| 3106 | + _num: function( value ) { | |
| 3107 | + return parseInt( value, 10 ) || 0; | |
| 3108 | + }, | |
| 3109 | + | |
| 3110 | + _isNumber: function( value ) { | |
| 3111 | + return !isNaN( parseInt( value, 10 ) ); | |
| 3112 | + }, | |
| 3113 | + | |
| 3114 | + _hasScroll: function( el, a ) { | |
| 3115 | + | |
| 3116 | + if ( $( el ).css( "overflow" ) === "hidden") { | |
| 3117 | + return false; | |
| 3118 | + } | |
| 3119 | + | |
| 3120 | + var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", | |
| 3121 | + has = false; | |
| 3122 | + | |
| 3123 | + if ( el[ scroll ] > 0 ) { | |
| 3124 | + return true; | |
| 3125 | + } | |
| 3126 | + | |
| 3127 | + // TODO: determine which cases actually cause this to happen | |
| 3128 | + // if the element doesn't have the scroll set, see if it's possible to | |
| 3129 | + // set the scroll | |
| 3130 | + el[ scroll ] = 1; | |
| 3131 | + has = ( el[ scroll ] > 0 ); | |
| 3132 | + el[ scroll ] = 0; | |
| 3133 | + return has; | |
| 3134 | + }, | |
| 3135 | + | |
| 3136 | + _create: function() { | |
| 3137 | + | |
| 3138 | + var n, i, handle, axis, hname, | |
| 3139 | + that = this, | |
| 3140 | + o = this.options; | |
| 3141 | + this.element.addClass("ui-resizable"); | |
| 3142 | + | |
| 3143 | + $.extend(this, { | |
| 3144 | + _aspectRatio: !!(o.aspectRatio), | |
| 3145 | + aspectRatio: o.aspectRatio, | |
| 3146 | + originalElement: this.element, | |
| 3147 | + _proportionallyResizeElements: [], | |
| 3148 | + _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null | |
| 3149 | + }); | |
| 3150 | + | |
| 3151 | + // Wrap the element if it cannot hold child nodes | |
| 3152 | + if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) { | |
| 3153 | + | |
| 3154 | + this.element.wrap( | |
| 3155 | + $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ | |
| 3156 | + position: this.element.css("position"), | |
| 3157 | + width: this.element.outerWidth(), | |
| 3158 | + height: this.element.outerHeight(), | |
| 3159 | + top: this.element.css("top"), | |
| 3160 | + left: this.element.css("left") | |
| 3161 | + }) | |
| 3162 | + ); | |
| 3163 | + | |
| 3164 | + this.element = this.element.parent().data( | |
| 3165 | + "ui-resizable", this.element.resizable( "instance" ) | |
| 3166 | + ); | |
| 3167 | + | |
| 3168 | + this.elementIsWrapper = true; | |
| 3169 | + | |
| 3170 | + this.element.css({ | |
| 3171 | + marginLeft: this.originalElement.css("marginLeft"), | |
| 3172 | + marginTop: this.originalElement.css("marginTop"), | |
| 3173 | + marginRight: this.originalElement.css("marginRight"), | |
| 3174 | + marginBottom: this.originalElement.css("marginBottom") | |
| 3175 | + }); | |
| 3176 | + this.originalElement.css({ | |
| 3177 | + marginLeft: 0, | |
| 3178 | + marginTop: 0, | |
| 3179 | + marginRight: 0, | |
| 3180 | + marginBottom: 0 | |
| 3181 | + }); | |
| 3182 | + // support: Safari | |
| 3183 | + // Prevent Safari textarea resize | |
| 3184 | + this.originalResizeStyle = this.originalElement.css("resize"); | |
| 3185 | + this.originalElement.css("resize", "none"); | |
| 3186 | + | |
| 3187 | + this._proportionallyResizeElements.push( this.originalElement.css({ | |
| 3188 | + position: "static", | |
| 3189 | + zoom: 1, | |
| 3190 | + display: "block" | |
| 3191 | + }) ); | |
| 3192 | + | |
| 3193 | + // support: IE9 | |
| 3194 | + // avoid IE jump (hard set the margin) | |
| 3195 | + this.originalElement.css({ margin: this.originalElement.css("margin") }); | |
| 3196 | + | |
| 3197 | + this._proportionallyResize(); | |
| 3198 | + } | |
| 3199 | + | |
| 3200 | + this.handles = o.handles || | |
| 3201 | + ( !$(".ui-resizable-handle", this.element).length ? | |
| 3202 | + "e,s,se" : { | |
| 3203 | + n: ".ui-resizable-n", | |
| 3204 | + e: ".ui-resizable-e", | |
| 3205 | + s: ".ui-resizable-s", | |
| 3206 | + w: ".ui-resizable-w", | |
| 3207 | + se: ".ui-resizable-se", | |
| 3208 | + sw: ".ui-resizable-sw", | |
| 3209 | + ne: ".ui-resizable-ne", | |
| 3210 | + nw: ".ui-resizable-nw" | |
| 3211 | + } ); | |
| 3212 | + | |
| 3213 | + this._handles = $(); | |
| 3214 | + if ( this.handles.constructor === String ) { | |
| 3215 | + | |
| 3216 | + if ( this.handles === "all") { | |
| 3217 | + this.handles = "n,e,s,w,se,sw,ne,nw"; | |
| 3218 | + } | |
| 3219 | + | |
| 3220 | + n = this.handles.split(","); | |
| 3221 | + this.handles = {}; | |
| 3222 | + | |
| 3223 | + for (i = 0; i < n.length; i++) { | |
| 3224 | + | |
| 3225 | + handle = $.trim(n[i]); | |
| 3226 | + hname = "ui-resizable-" + handle; | |
| 3227 | + axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); | |
| 3228 | + | |
| 3229 | + axis.css({ zIndex: o.zIndex }); | |
| 3230 | + | |
| 3231 | + // TODO : What's going on here? | |
| 3232 | + if ("se" === handle) { | |
| 3233 | + axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); | |
| 3234 | + } | |
| 3235 | + | |
| 3236 | + this.handles[handle] = ".ui-resizable-" + handle; | |
| 3237 | + this.element.append(axis); | |
| 3238 | + } | |
| 3239 | + | |
| 3240 | + } | |
| 3241 | + | |
| 3242 | + this._renderAxis = function(target) { | |
| 3243 | + | |
| 3244 | + var i, axis, padPos, padWrapper; | |
| 3245 | + | |
| 3246 | + target = target || this.element; | |
| 3247 | + | |
| 3248 | + for (i in this.handles) { | |
| 3249 | + | |
| 3250 | + if (this.handles[i].constructor === String) { | |
| 3251 | + this.handles[i] = this.element.children( this.handles[ i ] ).first().show(); | |
| 3252 | + } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { | |
| 3253 | + this.handles[ i ] = $( this.handles[ i ] ); | |
| 3254 | + this._on( this.handles[ i ], { "mousedown": that._mouseDown }); | |
| 3255 | + } | |
| 3256 | + | |
| 3257 | + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) { | |
| 3258 | + | |
| 3259 | + axis = $(this.handles[i], this.element); | |
| 3260 | + | |
| 3261 | + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); | |
| 3262 | + | |
| 3263 | + padPos = [ "padding", | |
| 3264 | + /ne|nw|n/.test(i) ? "Top" : | |
| 3265 | + /se|sw|s/.test(i) ? "Bottom" : | |
| 3266 | + /^e$/.test(i) ? "Right" : "Left" ].join(""); | |
| 3267 | + | |
| 3268 | + target.css(padPos, padWrapper); | |
| 3269 | + | |
| 3270 | + this._proportionallyResize(); | |
| 3271 | + } | |
| 3272 | + | |
| 3273 | + this._handles = this._handles.add( this.handles[ i ] ); | |
| 3274 | + } | |
| 3275 | + }; | |
| 3276 | + | |
| 3277 | + // TODO: make renderAxis a prototype function | |
| 3278 | + this._renderAxis(this.element); | |
| 3279 | + | |
| 3280 | + this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); | |
| 3281 | + this._handles.disableSelection(); | |
| 3282 | + | |
| 3283 | + this._handles.mouseover(function() { | |
| 3284 | + if (!that.resizing) { | |
| 3285 | + if (this.className) { | |
| 3286 | + axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); | |
| 3287 | + } | |
| 3288 | + that.axis = axis && axis[1] ? axis[1] : "se"; | |
| 3289 | + } | |
| 3290 | + }); | |
| 3291 | + | |
| 3292 | + if (o.autoHide) { | |
| 3293 | + this._handles.hide(); | |
| 3294 | + $(this.element) | |
| 3295 | + .addClass("ui-resizable-autohide") | |
| 3296 | + .mouseenter(function() { | |
| 3297 | + if (o.disabled) { | |
| 3298 | + return; | |
| 3299 | + } | |
| 3300 | + $(this).removeClass("ui-resizable-autohide"); | |
| 3301 | + that._handles.show(); | |
| 3302 | + }) | |
| 3303 | + .mouseleave(function() { | |
| 3304 | + if (o.disabled) { | |
| 3305 | + return; | |
| 3306 | + } | |
| 3307 | + if (!that.resizing) { | |
| 3308 | + $(this).addClass("ui-resizable-autohide"); | |
| 3309 | + that._handles.hide(); | |
| 3310 | + } | |
| 3311 | + }); | |
| 3312 | + } | |
| 3313 | + | |
| 3314 | + this._mouseInit(); | |
| 3315 | + }, | |
| 3316 | + | |
| 3317 | + _destroy: function() { | |
| 3318 | + | |
| 3319 | + this._mouseDestroy(); | |
| 3320 | + | |
| 3321 | + var wrapper, | |
| 3322 | + _destroy = function(exp) { | |
| 3323 | + $(exp) | |
| 3324 | + .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") | |
| 3325 | + .removeData("resizable") | |
| 3326 | + .removeData("ui-resizable") | |
| 3327 | + .unbind(".resizable") | |
| 3328 | + .find(".ui-resizable-handle") | |
| 3329 | + .remove(); | |
| 3330 | + }; | |
| 3331 | + | |
| 3332 | + // TODO: Unwrap at same DOM position | |
| 3333 | + if (this.elementIsWrapper) { | |
| 3334 | + _destroy(this.element); | |
| 3335 | + wrapper = this.element; | |
| 3336 | + this.originalElement.css({ | |
| 3337 | + position: wrapper.css("position"), | |
| 3338 | + width: wrapper.outerWidth(), | |
| 3339 | + height: wrapper.outerHeight(), | |
| 3340 | + top: wrapper.css("top"), | |
| 3341 | + left: wrapper.css("left") | |
| 3342 | + }).insertAfter( wrapper ); | |
| 3343 | + wrapper.remove(); | |
| 3344 | + } | |
| 3345 | + | |
| 3346 | + this.originalElement.css("resize", this.originalResizeStyle); | |
| 3347 | + _destroy(this.originalElement); | |
| 3348 | + | |
| 3349 | + return this; | |
| 3350 | + }, | |
| 3351 | + | |
| 3352 | + _mouseCapture: function(event) { | |
| 3353 | + var i, handle, | |
| 3354 | + capture = false; | |
| 3355 | + | |
| 3356 | + for (i in this.handles) { | |
| 3357 | + handle = $(this.handles[i])[0]; | |
| 3358 | + if (handle === event.target || $.contains(handle, event.target)) { | |
| 3359 | + capture = true; | |
| 3360 | + } | |
| 3361 | + } | |
| 3362 | + | |
| 3363 | + return !this.options.disabled && capture; | |
| 3364 | + }, | |
| 3365 | + | |
| 3366 | + _mouseStart: function(event) { | |
| 3367 | + | |
| 3368 | + var curleft, curtop, cursor, | |
| 3369 | + o = this.options, | |
| 3370 | + el = this.element; | |
| 3371 | + | |
| 3372 | + this.resizing = true; | |
| 3373 | + | |
| 3374 | + this._renderProxy(); | |
| 3375 | + | |
| 3376 | + curleft = this._num(this.helper.css("left")); | |
| 3377 | + curtop = this._num(this.helper.css("top")); | |
| 3378 | + | |
| 3379 | + if (o.containment) { | |
| 3380 | + curleft += $(o.containment).scrollLeft() || 0; | |
| 3381 | + curtop += $(o.containment).scrollTop() || 0; | |
| 3382 | + } | |
| 3383 | + | |
| 3384 | + this.offset = this.helper.offset(); | |
| 3385 | + this.position = { left: curleft, top: curtop }; | |
| 3386 | + | |
| 3387 | + this.size = this._helper ? { | |
| 3388 | + width: this.helper.width(), | |
| 3389 | + height: this.helper.height() | |
| 3390 | + } : { | |
| 3391 | + width: el.width(), | |
| 3392 | + height: el.height() | |
| 3393 | + }; | |
| 3394 | + | |
| 3395 | + this.originalSize = this._helper ? { | |
| 3396 | + width: el.outerWidth(), | |
| 3397 | + height: el.outerHeight() | |
| 3398 | + } : { | |
| 3399 | + width: el.width(), | |
| 3400 | + height: el.height() | |
| 3401 | + }; | |
| 3402 | + | |
| 3403 | + this.sizeDiff = { | |
| 3404 | + width: el.outerWidth() - el.width(), | |
| 3405 | + height: el.outerHeight() - el.height() | |
| 3406 | + }; | |
| 3407 | + | |
| 3408 | + this.originalPosition = { left: curleft, top: curtop }; | |
| 3409 | + this.originalMousePosition = { left: event.pageX, top: event.pageY }; | |
| 3410 | + | |
| 3411 | + this.aspectRatio = (typeof o.aspectRatio === "number") ? | |
| 3412 | + o.aspectRatio : | |
| 3413 | + ((this.originalSize.width / this.originalSize.height) || 1); | |
| 3414 | + | |
| 3415 | + cursor = $(".ui-resizable-" + this.axis).css("cursor"); | |
| 3416 | + $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); | |
| 3417 | + | |
| 3418 | + el.addClass("ui-resizable-resizing"); | |
| 3419 | + this._propagate("start", event); | |
| 3420 | + return true; | |
| 3421 | + }, | |
| 3422 | + | |
| 3423 | + _mouseDrag: function(event) { | |
| 3424 | + | |
| 3425 | + var data, props, | |
| 3426 | + smp = this.originalMousePosition, | |
| 3427 | + a = this.axis, | |
| 3428 | + dx = (event.pageX - smp.left) || 0, | |
| 3429 | + dy = (event.pageY - smp.top) || 0, | |
| 3430 | + trigger = this._change[a]; | |
| 3431 | + | |
| 3432 | + this._updatePrevProperties(); | |
| 3433 | + | |
| 3434 | + if (!trigger) { | |
| 3435 | + return false; | |
| 3436 | + } | |
| 3437 | + | |
| 3438 | + data = trigger.apply(this, [ event, dx, dy ]); | |
| 3439 | + | |
| 3440 | + this._updateVirtualBoundaries(event.shiftKey); | |
| 3441 | + if (this._aspectRatio || event.shiftKey) { | |
| 3442 | + data = this._updateRatio(data, event); | |
| 3443 | + } | |
| 3444 | + | |
| 3445 | + data = this._respectSize(data, event); | |
| 3446 | + | |
| 3447 | + this._updateCache(data); | |
| 3448 | + | |
| 3449 | + this._propagate("resize", event); | |
| 3450 | + | |
| 3451 | + props = this._applyChanges(); | |
| 3452 | + | |
| 3453 | + if ( !this._helper && this._proportionallyResizeElements.length ) { | |
| 3454 | + this._proportionallyResize(); | |
| 3455 | + } | |
| 3456 | + | |
| 3457 | + if ( !$.isEmptyObject( props ) ) { | |
| 3458 | + this._updatePrevProperties(); | |
| 3459 | + this._trigger( "resize", event, this.ui() ); | |
| 3460 | + this._applyChanges(); | |
| 3461 | + } | |
| 3462 | + | |
| 3463 | + return false; | |
| 3464 | + }, | |
| 3465 | + | |
| 3466 | + _mouseStop: function(event) { | |
| 3467 | + | |
| 3468 | + this.resizing = false; | |
| 3469 | + var pr, ista, soffseth, soffsetw, s, left, top, | |
| 3470 | + o = this.options, that = this; | |
| 3471 | + | |
| 3472 | + if (this._helper) { | |
| 3473 | + | |
| 3474 | + pr = this._proportionallyResizeElements; | |
| 3475 | + ista = pr.length && (/textarea/i).test(pr[0].nodeName); | |
| 3476 | + soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height; | |
| 3477 | + soffsetw = ista ? 0 : that.sizeDiff.width; | |
| 3478 | + | |
| 3479 | + s = { | |
| 3480 | + width: (that.helper.width() - soffsetw), | |
| 3481 | + height: (that.helper.height() - soffseth) | |
| 3482 | + }; | |
| 3483 | + left = (parseInt(that.element.css("left"), 10) + | |
| 3484 | + (that.position.left - that.originalPosition.left)) || null; | |
| 3485 | + top = (parseInt(that.element.css("top"), 10) + | |
| 3486 | + (that.position.top - that.originalPosition.top)) || null; | |
| 3487 | + | |
| 3488 | + if (!o.animate) { | |
| 3489 | + this.element.css($.extend(s, { top: top, left: left })); | |
| 3490 | + } | |
| 3491 | + | |
| 3492 | + that.helper.height(that.size.height); | |
| 3493 | + that.helper.width(that.size.width); | |
| 3494 | + | |
| 3495 | + if (this._helper && !o.animate) { | |
| 3496 | + this._proportionallyResize(); | |
| 3497 | + } | |
| 3498 | + } | |
| 3499 | + | |
| 3500 | + $("body").css("cursor", "auto"); | |
| 3501 | + | |
| 3502 | + this.element.removeClass("ui-resizable-resizing"); | |
| 3503 | + | |
| 3504 | + this._propagate("stop", event); | |
| 3505 | + | |
| 3506 | + if (this._helper) { | |
| 3507 | + this.helper.remove(); | |
| 3508 | + } | |
| 3509 | + | |
| 3510 | + return false; | |
| 3511 | + | |
| 3512 | + }, | |
| 3513 | + | |
| 3514 | + _updatePrevProperties: function() { | |
| 3515 | + this.prevPosition = { | |
| 3516 | + top: this.position.top, | |
| 3517 | + left: this.position.left | |
| 3518 | + }; | |
| 3519 | + this.prevSize = { | |
| 3520 | + width: this.size.width, | |
| 3521 | + height: this.size.height | |
| 3522 | + }; | |
| 3523 | + }, | |
| 3524 | + | |
| 3525 | + _applyChanges: function() { | |
| 3526 | + var props = {}; | |
| 3527 | + | |
| 3528 | + if ( this.position.top !== this.prevPosition.top ) { | |
| 3529 | + props.top = this.position.top + "px"; | |
| 3530 | + } | |
| 3531 | + if ( this.position.left !== this.prevPosition.left ) { | |
| 3532 | + props.left = this.position.left + "px"; | |
| 3533 | + } | |
| 3534 | + if ( this.size.width !== this.prevSize.width ) { | |
| 3535 | + props.width = this.size.width + "px"; | |
| 3536 | + } | |
| 3537 | + if ( this.size.height !== this.prevSize.height ) { | |
| 3538 | + props.height = this.size.height + "px"; | |
| 3539 | + } | |
| 3540 | + | |
| 3541 | + this.helper.css( props ); | |
| 3542 | + | |
| 3543 | + return props; | |
| 3544 | + }, | |
| 3545 | + | |
| 3546 | + _updateVirtualBoundaries: function(forceAspectRatio) { | |
| 3547 | + var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, | |
| 3548 | + o = this.options; | |
| 3549 | + | |
| 3550 | + b = { | |
| 3551 | + minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0, | |
| 3552 | + maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity, | |
| 3553 | + minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0, | |
| 3554 | + maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity | |
| 3555 | + }; | |
| 3556 | + | |
| 3557 | + if (this._aspectRatio || forceAspectRatio) { | |
| 3558 | + pMinWidth = b.minHeight * this.aspectRatio; | |
| 3559 | + pMinHeight = b.minWidth / this.aspectRatio; | |
| 3560 | + pMaxWidth = b.maxHeight * this.aspectRatio; | |
| 3561 | + pMaxHeight = b.maxWidth / this.aspectRatio; | |
| 3562 | + | |
| 3563 | + if (pMinWidth > b.minWidth) { | |
| 3564 | + b.minWidth = pMinWidth; | |
| 3565 | + } | |
| 3566 | + if (pMinHeight > b.minHeight) { | |
| 3567 | + b.minHeight = pMinHeight; | |
| 3568 | + } | |
| 3569 | + if (pMaxWidth < b.maxWidth) { | |
| 3570 | + b.maxWidth = pMaxWidth; | |
| 3571 | + } | |
| 3572 | + if (pMaxHeight < b.maxHeight) { | |
| 3573 | + b.maxHeight = pMaxHeight; | |
| 3574 | + } | |
| 3575 | + } | |
| 3576 | + this._vBoundaries = b; | |
| 3577 | + }, | |
| 3578 | + | |
| 3579 | + _updateCache: function(data) { | |
| 3580 | + this.offset = this.helper.offset(); | |
| 3581 | + if (this._isNumber(data.left)) { | |
| 3582 | + this.position.left = data.left; | |
| 3583 | + } | |
| 3584 | + if (this._isNumber(data.top)) { | |
| 3585 | + this.position.top = data.top; | |
| 3586 | + } | |
| 3587 | + if (this._isNumber(data.height)) { | |
| 3588 | + this.size.height = data.height; | |
| 3589 | + } | |
| 3590 | + if (this._isNumber(data.width)) { | |
| 3591 | + this.size.width = data.width; | |
| 3592 | + } | |
| 3593 | + }, | |
| 3594 | + | |
| 3595 | + _updateRatio: function( data ) { | |
| 3596 | + | |
| 3597 | + var cpos = this.position, | |
| 3598 | + csize = this.size, | |
| 3599 | + a = this.axis; | |
| 3600 | + | |
| 3601 | + if (this._isNumber(data.height)) { | |
| 3602 | + data.width = (data.height * this.aspectRatio); | |
| 3603 | + } else if (this._isNumber(data.width)) { | |
| 3604 | + data.height = (data.width / this.aspectRatio); | |
| 3605 | + } | |
| 3606 | + | |
| 3607 | + if (a === "sw") { | |
| 3608 | + data.left = cpos.left + (csize.width - data.width); | |
| 3609 | + data.top = null; | |
| 3610 | + } | |
| 3611 | + if (a === "nw") { | |
| 3612 | + data.top = cpos.top + (csize.height - data.height); | |
| 3613 | + data.left = cpos.left + (csize.width - data.width); | |
| 3614 | + } | |
| 3615 | + | |
| 3616 | + return data; | |
| 3617 | + }, | |
| 3618 | + | |
| 3619 | + _respectSize: function( data ) { | |
| 3620 | + | |
| 3621 | + var o = this._vBoundaries, | |
| 3622 | + a = this.axis, | |
| 3623 | + ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), | |
| 3624 | + ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), | |
| 3625 | + isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), | |
| 3626 | + isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height), | |
| 3627 | + dw = this.originalPosition.left + this.originalSize.width, | |
| 3628 | + dh = this.position.top + this.size.height, | |
| 3629 | + cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); | |
| 3630 | + if (isminw) { | |
| 3631 | + data.width = o.minWidth; | |
| 3632 | + } | |
| 3633 | + if (isminh) { | |
| 3634 | + data.height = o.minHeight; | |
| 3635 | + } | |
| 3636 | + if (ismaxw) { | |
| 3637 | + data.width = o.maxWidth; | |
| 3638 | + } | |
| 3639 | + if (ismaxh) { | |
| 3640 | + data.height = o.maxHeight; | |
| 3641 | + } | |
| 3642 | + | |
| 3643 | + if (isminw && cw) { | |
| 3644 | + data.left = dw - o.minWidth; | |
| 3645 | + } | |
| 3646 | + if (ismaxw && cw) { | |
| 3647 | + data.left = dw - o.maxWidth; | |
| 3648 | + } | |
| 3649 | + if (isminh && ch) { | |
| 3650 | + data.top = dh - o.minHeight; | |
| 3651 | + } | |
| 3652 | + if (ismaxh && ch) { | |
| 3653 | + data.top = dh - o.maxHeight; | |
| 3654 | + } | |
| 3655 | + | |
| 3656 | + // Fixing jump error on top/left - bug #2330 | |
| 3657 | + if (!data.width && !data.height && !data.left && data.top) { | |
| 3658 | + data.top = null; | |
| 3659 | + } else if (!data.width && !data.height && !data.top && data.left) { | |
| 3660 | + data.left = null; | |
| 3661 | + } | |
| 3662 | + | |
| 3663 | + return data; | |
| 3664 | + }, | |
| 3665 | + | |
| 3666 | + _getPaddingPlusBorderDimensions: function( element ) { | |
| 3667 | + var i = 0, | |
| 3668 | + widths = [], | |
| 3669 | + borders = [ | |
| 3670 | + element.css( "borderTopWidth" ), | |
| 3671 | + element.css( "borderRightWidth" ), | |
| 3672 | + element.css( "borderBottomWidth" ), | |
| 3673 | + element.css( "borderLeftWidth" ) | |
| 3674 | + ], | |
| 3675 | + paddings = [ | |
| 3676 | + element.css( "paddingTop" ), | |
| 3677 | + element.css( "paddingRight" ), | |
| 3678 | + element.css( "paddingBottom" ), | |
| 3679 | + element.css( "paddingLeft" ) | |
| 3680 | + ]; | |
| 3681 | + | |
| 3682 | + for ( ; i < 4; i++ ) { | |
| 3683 | + widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 ); | |
| 3684 | + widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 ); | |
| 3685 | + } | |
| 3686 | + | |
| 3687 | + return { | |
| 3688 | + height: widths[ 0 ] + widths[ 2 ], | |
| 3689 | + width: widths[ 1 ] + widths[ 3 ] | |
| 3690 | + }; | |
| 3691 | + }, | |
| 3692 | + | |
| 3693 | + _proportionallyResize: function() { | |
| 3694 | + | |
| 3695 | + if (!this._proportionallyResizeElements.length) { | |
| 3696 | + return; | |
| 3697 | + } | |
| 3698 | + | |
| 3699 | + var prel, | |
| 3700 | + i = 0, | |
| 3701 | + element = this.helper || this.element; | |
| 3702 | + | |
| 3703 | + for ( ; i < this._proportionallyResizeElements.length; i++) { | |
| 3704 | + | |
| 3705 | + prel = this._proportionallyResizeElements[i]; | |
| 3706 | + | |
| 3707 | + // TODO: Seems like a bug to cache this.outerDimensions | |
| 3708 | + // considering that we are in a loop. | |
| 3709 | + if (!this.outerDimensions) { | |
| 3710 | + this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); | |
| 3711 | + } | |
| 3712 | + | |
| 3713 | + prel.css({ | |
| 3714 | + height: (element.height() - this.outerDimensions.height) || 0, | |
| 3715 | + width: (element.width() - this.outerDimensions.width) || 0 | |
| 3716 | + }); | |
| 3717 | + | |
| 3718 | + } | |
| 3719 | + | |
| 3720 | + }, | |
| 3721 | + | |
| 3722 | + _renderProxy: function() { | |
| 3723 | + | |
| 3724 | + var el = this.element, o = this.options; | |
| 3725 | + this.elementOffset = el.offset(); | |
| 3726 | + | |
| 3727 | + if (this._helper) { | |
| 3728 | + | |
| 3729 | + this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); | |
| 3730 | + | |
| 3731 | + this.helper.addClass(this._helper).css({ | |
| 3732 | + width: this.element.outerWidth() - 1, | |
| 3733 | + height: this.element.outerHeight() - 1, | |
| 3734 | + position: "absolute", | |
| 3735 | + left: this.elementOffset.left + "px", | |
| 3736 | + top: this.elementOffset.top + "px", | |
| 3737 | + zIndex: ++o.zIndex //TODO: Don't modify option | |
| 3738 | + }); | |
| 3739 | + | |
| 3740 | + this.helper | |
| 3741 | + .appendTo("body") | |
| 3742 | + .disableSelection(); | |
| 3743 | + | |
| 3744 | + } else { | |
| 3745 | + this.helper = this.element; | |
| 3746 | + } | |
| 3747 | + | |
| 3748 | + }, | |
| 3749 | + | |
| 3750 | + _change: { | |
| 3751 | + e: function(event, dx) { | |
| 3752 | + return { width: this.originalSize.width + dx }; | |
| 3753 | + }, | |
| 3754 | + w: function(event, dx) { | |
| 3755 | + var cs = this.originalSize, sp = this.originalPosition; | |
| 3756 | + return { left: sp.left + dx, width: cs.width - dx }; | |
| 3757 | + }, | |
| 3758 | + n: function(event, dx, dy) { | |
| 3759 | + var cs = this.originalSize, sp = this.originalPosition; | |
| 3760 | + return { top: sp.top + dy, height: cs.height - dy }; | |
| 3761 | + }, | |
| 3762 | + s: function(event, dx, dy) { | |
| 3763 | + return { height: this.originalSize.height + dy }; | |
| 3764 | + }, | |
| 3765 | + se: function(event, dx, dy) { | |
| 3766 | + return $.extend(this._change.s.apply(this, arguments), | |
| 3767 | + this._change.e.apply(this, [ event, dx, dy ])); | |
| 3768 | + }, | |
| 3769 | + sw: function(event, dx, dy) { | |
| 3770 | + return $.extend(this._change.s.apply(this, arguments), | |
| 3771 | + this._change.w.apply(this, [ event, dx, dy ])); | |
| 3772 | + }, | |
| 3773 | + ne: function(event, dx, dy) { | |
| 3774 | + return $.extend(this._change.n.apply(this, arguments), | |
| 3775 | + this._change.e.apply(this, [ event, dx, dy ])); | |
| 3776 | + }, | |
| 3777 | + nw: function(event, dx, dy) { | |
| 3778 | + return $.extend(this._change.n.apply(this, arguments), | |
| 3779 | + this._change.w.apply(this, [ event, dx, dy ])); | |
| 3780 | + } | |
| 3781 | + }, | |
| 3782 | + | |
| 3783 | + _propagate: function(n, event) { | |
| 3784 | + $.ui.plugin.call(this, n, [ event, this.ui() ]); | |
| 3785 | + (n !== "resize" && this._trigger(n, event, this.ui())); | |
| 3786 | + }, | |
| 3787 | + | |
| 3788 | + plugins: {}, | |
| 3789 | + | |
| 3790 | + ui: function() { | |
| 3791 | + return { | |
| 3792 | + originalElement: this.originalElement, | |
| 3793 | + element: this.element, | |
| 3794 | + helper: this.helper, | |
| 3795 | + position: this.position, | |
| 3796 | + size: this.size, | |
| 3797 | + originalSize: this.originalSize, | |
| 3798 | + originalPosition: this.originalPosition | |
| 3799 | + }; | |
| 3800 | + } | |
| 3801 | + | |
| 3802 | +}); | |
| 3803 | + | |
| 3804 | +/* | |
| 3805 | + * Resizable Extensions | |
| 3806 | + */ | |
| 3807 | + | |
| 3808 | +$.ui.plugin.add("resizable", "animate", { | |
| 3809 | + | |
| 3810 | + stop: function( event ) { | |
| 3811 | + var that = $(this).resizable( "instance" ), | |
| 3812 | + o = that.options, | |
| 3813 | + pr = that._proportionallyResizeElements, | |
| 3814 | + ista = pr.length && (/textarea/i).test(pr[0].nodeName), | |
| 3815 | + soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height, | |
| 3816 | + soffsetw = ista ? 0 : that.sizeDiff.width, | |
| 3817 | + style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, | |
| 3818 | + left = (parseInt(that.element.css("left"), 10) + | |
| 3819 | + (that.position.left - that.originalPosition.left)) || null, | |
| 3820 | + top = (parseInt(that.element.css("top"), 10) + | |
| 3821 | + (that.position.top - that.originalPosition.top)) || null; | |
| 3822 | + | |
| 3823 | + that.element.animate( | |
| 3824 | + $.extend(style, top && left ? { top: top, left: left } : {}), { | |
| 3825 | + duration: o.animateDuration, | |
| 3826 | + easing: o.animateEasing, | |
| 3827 | + step: function() { | |
| 3828 | + | |
| 3829 | + var data = { | |
| 3830 | + width: parseInt(that.element.css("width"), 10), | |
| 3831 | + height: parseInt(that.element.css("height"), 10), | |
| 3832 | + top: parseInt(that.element.css("top"), 10), | |
| 3833 | + left: parseInt(that.element.css("left"), 10) | |
| 3834 | + }; | |
| 3835 | + | |
| 3836 | + if (pr && pr.length) { | |
| 3837 | + $(pr[0]).css({ width: data.width, height: data.height }); | |
| 3838 | + } | |
| 3839 | + | |
| 3840 | + // propagating resize, and updating values for each animation step | |
| 3841 | + that._updateCache(data); | |
| 3842 | + that._propagate("resize", event); | |
| 3843 | + | |
| 3844 | + } | |
| 3845 | + } | |
| 3846 | + ); | |
| 3847 | + } | |
| 3848 | + | |
| 3849 | +}); | |
| 3850 | + | |
| 3851 | +$.ui.plugin.add( "resizable", "containment", { | |
| 3852 | + | |
| 3853 | + start: function() { | |
| 3854 | + var element, p, co, ch, cw, width, height, | |
| 3855 | + that = $( this ).resizable( "instance" ), | |
| 3856 | + o = that.options, | |
| 3857 | + el = that.element, | |
| 3858 | + oc = o.containment, | |
| 3859 | + ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; | |
| 3860 | + | |
| 3861 | + if ( !ce ) { | |
| 3862 | + return; | |
| 3863 | + } | |
| 3864 | + | |
| 3865 | + that.containerElement = $( ce ); | |
| 3866 | + | |
| 3867 | + if ( /document/.test( oc ) || oc === document ) { | |
| 3868 | + that.containerOffset = { | |
| 3869 | + left: 0, | |
| 3870 | + top: 0 | |
| 3871 | + }; | |
| 3872 | + that.containerPosition = { | |
| 3873 | + left: 0, | |
| 3874 | + top: 0 | |
| 3875 | + }; | |
| 3876 | + | |
| 3877 | + that.parentData = { | |
| 3878 | + element: $( document ), | |
| 3879 | + left: 0, | |
| 3880 | + top: 0, | |
| 3881 | + width: $( document ).width(), | |
| 3882 | + height: $( document ).height() || document.body.parentNode.scrollHeight | |
| 3883 | + }; | |
| 3884 | + } else { | |
| 3885 | + element = $( ce ); | |
| 3886 | + p = []; | |
| 3887 | + $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) { | |
| 3888 | + p[ i ] = that._num( element.css( "padding" + name ) ); | |
| 3889 | + }); | |
| 3890 | + | |
| 3891 | + that.containerOffset = element.offset(); | |
| 3892 | + that.containerPosition = element.position(); | |
| 3893 | + that.containerSize = { | |
| 3894 | + height: ( element.innerHeight() - p[ 3 ] ), | |
| 3895 | + width: ( element.innerWidth() - p[ 1 ] ) | |
| 3896 | + }; | |
| 3897 | + | |
| 3898 | + co = that.containerOffset; | |
| 3899 | + ch = that.containerSize.height; | |
| 3900 | + cw = that.containerSize.width; | |
| 3901 | + width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw ); | |
| 3902 | + height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ; | |
| 3903 | + | |
| 3904 | + that.parentData = { | |
| 3905 | + element: ce, | |
| 3906 | + left: co.left, | |
| 3907 | + top: co.top, | |
| 3908 | + width: width, | |
| 3909 | + height: height | |
| 3910 | + }; | |
| 3911 | + } | |
| 3912 | + }, | |
| 3913 | + | |
| 3914 | + resize: function( event ) { | |
| 3915 | + var woset, hoset, isParent, isOffsetRelative, | |
| 3916 | + that = $( this ).resizable( "instance" ), | |
| 3917 | + o = that.options, | |
| 3918 | + co = that.containerOffset, | |
| 3919 | + cp = that.position, | |
| 3920 | + pRatio = that._aspectRatio || event.shiftKey, | |
| 3921 | + cop = { | |
| 3922 | + top: 0, | |
| 3923 | + left: 0 | |
| 3924 | + }, | |
| 3925 | + ce = that.containerElement, | |
| 3926 | + continueResize = true; | |
| 3927 | + | |
| 3928 | + if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { | |
| 3929 | + cop = co; | |
| 3930 | + } | |
| 3931 | + | |
| 3932 | + if ( cp.left < ( that._helper ? co.left : 0 ) ) { | |
| 3933 | + that.size.width = that.size.width + | |
| 3934 | + ( that._helper ? | |
| 3935 | + ( that.position.left - co.left ) : | |
| 3936 | + ( that.position.left - cop.left ) ); | |
| 3937 | + | |
| 3938 | + if ( pRatio ) { | |
| 3939 | + that.size.height = that.size.width / that.aspectRatio; | |
| 3940 | + continueResize = false; | |
| 3941 | + } | |
| 3942 | + that.position.left = o.helper ? co.left : 0; | |
| 3943 | + } | |
| 3944 | + | |
| 3945 | + if ( cp.top < ( that._helper ? co.top : 0 ) ) { | |
| 3946 | + that.size.height = that.size.height + | |
| 3947 | + ( that._helper ? | |
| 3948 | + ( that.position.top - co.top ) : | |
| 3949 | + that.position.top ); | |
| 3950 | + | |
| 3951 | + if ( pRatio ) { | |
| 3952 | + that.size.width = that.size.height * that.aspectRatio; | |
| 3953 | + continueResize = false; | |
| 3954 | + } | |
| 3955 | + that.position.top = that._helper ? co.top : 0; | |
| 3956 | + } | |
| 3957 | + | |
| 3958 | + isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); | |
| 3959 | + isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); | |
| 3960 | + | |
| 3961 | + if ( isParent && isOffsetRelative ) { | |
| 3962 | + that.offset.left = that.parentData.left + that.position.left; | |
| 3963 | + that.offset.top = that.parentData.top + that.position.top; | |
| 3964 | + } else { | |
| 3965 | + that.offset.left = that.element.offset().left; | |
| 3966 | + that.offset.top = that.element.offset().top; | |
| 3967 | + } | |
| 3968 | + | |
| 3969 | + woset = Math.abs( that.sizeDiff.width + | |
| 3970 | + (that._helper ? | |
| 3971 | + that.offset.left - cop.left : | |
| 3972 | + (that.offset.left - co.left)) ); | |
| 3973 | + | |
| 3974 | + hoset = Math.abs( that.sizeDiff.height + | |
| 3975 | + (that._helper ? | |
| 3976 | + that.offset.top - cop.top : | |
| 3977 | + (that.offset.top - co.top)) ); | |
| 3978 | + | |
| 3979 | + if ( woset + that.size.width >= that.parentData.width ) { | |
| 3980 | + that.size.width = that.parentData.width - woset; | |
| 3981 | + if ( pRatio ) { | |
| 3982 | + that.size.height = that.size.width / that.aspectRatio; | |
| 3983 | + continueResize = false; | |
| 3984 | + } | |
| 3985 | + } | |
| 3986 | + | |
| 3987 | + if ( hoset + that.size.height >= that.parentData.height ) { | |
| 3988 | + that.size.height = that.parentData.height - hoset; | |
| 3989 | + if ( pRatio ) { | |
| 3990 | + that.size.width = that.size.height * that.aspectRatio; | |
| 3991 | + continueResize = false; | |
| 3992 | + } | |
| 3993 | + } | |
| 3994 | + | |
| 3995 | + if ( !continueResize ) { | |
| 3996 | + that.position.left = that.prevPosition.left; | |
| 3997 | + that.position.top = that.prevPosition.top; | |
| 3998 | + that.size.width = that.prevSize.width; | |
| 3999 | + that.size.height = that.prevSize.height; | |
| 4000 | + } | |
| 4001 | + }, | |
| 4002 | + | |
| 4003 | + stop: function() { | |
| 4004 | + var that = $( this ).resizable( "instance" ), | |
| 4005 | + o = that.options, | |
| 4006 | + co = that.containerOffset, | |
| 4007 | + cop = that.containerPosition, | |
| 4008 | + ce = that.containerElement, | |
| 4009 | + helper = $( that.helper ), | |
| 4010 | + ho = helper.offset(), | |
| 4011 | + w = helper.outerWidth() - that.sizeDiff.width, | |
| 4012 | + h = helper.outerHeight() - that.sizeDiff.height; | |
| 4013 | + | |
| 4014 | + if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { | |
| 4015 | + $( this ).css({ | |
| 4016 | + left: ho.left - cop.left - co.left, | |
| 4017 | + width: w, | |
| 4018 | + height: h | |
| 4019 | + }); | |
| 4020 | + } | |
| 4021 | + | |
| 4022 | + if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { | |
| 4023 | + $( this ).css({ | |
| 4024 | + left: ho.left - cop.left - co.left, | |
| 4025 | + width: w, | |
| 4026 | + height: h | |
| 4027 | + }); | |
| 4028 | + } | |
| 4029 | + } | |
| 4030 | +}); | |
| 4031 | + | |
| 4032 | +$.ui.plugin.add("resizable", "alsoResize", { | |
| 4033 | + | |
| 4034 | + start: function() { | |
| 4035 | + var that = $(this).resizable( "instance" ), | |
| 4036 | + o = that.options; | |
| 4037 | + | |
| 4038 | + $(o.alsoResize).each(function() { | |
| 4039 | + var el = $(this); | |
| 4040 | + el.data("ui-resizable-alsoresize", { | |
| 4041 | + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), | |
| 4042 | + left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) | |
| 4043 | + }); | |
| 4044 | + }); | |
| 4045 | + }, | |
| 4046 | + | |
| 4047 | + resize: function(event, ui) { | |
| 4048 | + var that = $(this).resizable( "instance" ), | |
| 4049 | + o = that.options, | |
| 4050 | + os = that.originalSize, | |
| 4051 | + op = that.originalPosition, | |
| 4052 | + delta = { | |
| 4053 | + height: (that.size.height - os.height) || 0, | |
| 4054 | + width: (that.size.width - os.width) || 0, | |
| 4055 | + top: (that.position.top - op.top) || 0, | |
| 4056 | + left: (that.position.left - op.left) || 0 | |
| 4057 | + }; | |
| 4058 | + | |
| 4059 | + $(o.alsoResize).each(function() { | |
| 4060 | + var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, | |
| 4061 | + css = el.parents(ui.originalElement[0]).length ? | |
| 4062 | + [ "width", "height" ] : | |
| 4063 | + [ "width", "height", "top", "left" ]; | |
| 4064 | + | |
| 4065 | + $.each(css, function(i, prop) { | |
| 4066 | + var sum = (start[prop] || 0) + (delta[prop] || 0); | |
| 4067 | + if (sum && sum >= 0) { | |
| 4068 | + style[prop] = sum || null; | |
| 4069 | + } | |
| 4070 | + }); | |
| 4071 | + | |
| 4072 | + el.css(style); | |
| 4073 | + }); | |
| 4074 | + }, | |
| 4075 | + | |
| 4076 | + stop: function() { | |
| 4077 | + $(this).removeData("resizable-alsoresize"); | |
| 4078 | + } | |
| 4079 | +}); | |
| 4080 | + | |
| 4081 | +$.ui.plugin.add("resizable", "ghost", { | |
| 4082 | + | |
| 4083 | + start: function() { | |
| 4084 | + | |
| 4085 | + var that = $(this).resizable( "instance" ), o = that.options, cs = that.size; | |
| 4086 | + | |
| 4087 | + that.ghost = that.originalElement.clone(); | |
| 4088 | + that.ghost | |
| 4089 | + .css({ | |
| 4090 | + opacity: 0.25, | |
| 4091 | + display: "block", | |
| 4092 | + position: "relative", | |
| 4093 | + height: cs.height, | |
| 4094 | + width: cs.width, | |
| 4095 | + margin: 0, | |
| 4096 | + left: 0, | |
| 4097 | + top: 0 | |
| 4098 | + }) | |
| 4099 | + .addClass("ui-resizable-ghost") | |
| 4100 | + .addClass(typeof o.ghost === "string" ? o.ghost : ""); | |
| 4101 | + | |
| 4102 | + that.ghost.appendTo(that.helper); | |
| 4103 | + | |
| 4104 | + }, | |
| 4105 | + | |
| 4106 | + resize: function() { | |
| 4107 | + var that = $(this).resizable( "instance" ); | |
| 4108 | + if (that.ghost) { | |
| 4109 | + that.ghost.css({ | |
| 4110 | + position: "relative", | |
| 4111 | + height: that.size.height, | |
| 4112 | + width: that.size.width | |
| 4113 | + }); | |
| 4114 | + } | |
| 4115 | + }, | |
| 4116 | + | |
| 4117 | + stop: function() { | |
| 4118 | + var that = $(this).resizable( "instance" ); | |
| 4119 | + if (that.ghost && that.helper) { | |
| 4120 | + that.helper.get(0).removeChild(that.ghost.get(0)); | |
| 4121 | + } | |
| 4122 | + } | |
| 4123 | + | |
| 4124 | +}); | |
| 4125 | + | |
| 4126 | +$.ui.plugin.add("resizable", "grid", { | |
| 4127 | + | |
| 4128 | + resize: function() { | |
| 4129 | + var outerDimensions, | |
| 4130 | + that = $(this).resizable( "instance" ), | |
| 4131 | + o = that.options, | |
| 4132 | + cs = that.size, | |
| 4133 | + os = that.originalSize, | |
| 4134 | + op = that.originalPosition, | |
| 4135 | + a = that.axis, | |
| 4136 | + grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, | |
| 4137 | + gridX = (grid[0] || 1), | |
| 4138 | + gridY = (grid[1] || 1), | |
| 4139 | + ox = Math.round((cs.width - os.width) / gridX) * gridX, | |
| 4140 | + oy = Math.round((cs.height - os.height) / gridY) * gridY, | |
| 4141 | + newWidth = os.width + ox, | |
| 4142 | + newHeight = os.height + oy, | |
| 4143 | + isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), | |
| 4144 | + isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), | |
| 4145 | + isMinWidth = o.minWidth && (o.minWidth > newWidth), | |
| 4146 | + isMinHeight = o.minHeight && (o.minHeight > newHeight); | |
| 4147 | + | |
| 4148 | + o.grid = grid; | |
| 4149 | + | |
| 4150 | + if (isMinWidth) { | |
| 4151 | + newWidth += gridX; | |
| 4152 | + } | |
| 4153 | + if (isMinHeight) { | |
| 4154 | + newHeight += gridY; | |
| 4155 | + } | |
| 4156 | + if (isMaxWidth) { | |
| 4157 | + newWidth -= gridX; | |
| 4158 | + } | |
| 4159 | + if (isMaxHeight) { | |
| 4160 | + newHeight -= gridY; | |
| 4161 | + } | |
| 4162 | + | |
| 4163 | + if (/^(se|s|e)$/.test(a)) { | |
| 4164 | + that.size.width = newWidth; | |
| 4165 | + that.size.height = newHeight; | |
| 4166 | + } else if (/^(ne)$/.test(a)) { | |
| 4167 | + that.size.width = newWidth; | |
| 4168 | + that.size.height = newHeight; | |
| 4169 | + that.position.top = op.top - oy; | |
| 4170 | + } else if (/^(sw)$/.test(a)) { | |
| 4171 | + that.size.width = newWidth; | |
| 4172 | + that.size.height = newHeight; | |
| 4173 | + that.position.left = op.left - ox; | |
| 4174 | + } else { | |
| 4175 | + if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) { | |
| 4176 | + outerDimensions = that._getPaddingPlusBorderDimensions( this ); | |
| 4177 | + } | |
| 4178 | + | |
| 4179 | + if ( newHeight - gridY > 0 ) { | |
| 4180 | + that.size.height = newHeight; | |
| 4181 | + that.position.top = op.top - oy; | |
| 4182 | + } else { | |
| 4183 | + newHeight = gridY - outerDimensions.height; | |
| 4184 | + that.size.height = newHeight; | |
| 4185 | + that.position.top = op.top + os.height - newHeight; | |
| 4186 | + } | |
| 4187 | + if ( newWidth - gridX > 0 ) { | |
| 4188 | + that.size.width = newWidth; | |
| 4189 | + that.position.left = op.left - ox; | |
| 4190 | + } else { | |
| 4191 | + newWidth = gridX - outerDimensions.width; | |
| 4192 | + that.size.width = newWidth; | |
| 4193 | + that.position.left = op.left + os.width - newWidth; | |
| 4194 | + } | |
| 4195 | + } | |
| 4196 | + } | |
| 4197 | + | |
| 4198 | +}); | |
| 4199 | + | |
| 4200 | +var resizable = $.ui.resizable; | |
| 4201 | + | |
| 4202 | + | |
| 4203 | +/*! | |
| 4204 | + * jQuery UI Selectable 1.11.4 | |
| 4205 | + * http://jqueryui.com | |
| 4206 | + * | |
| 4207 | + * Copyright jQuery Foundation and other contributors | |
| 4208 | + * Released under the MIT license. | |
| 4209 | + * http://jquery.org/license | |
| 4210 | + * | |
| 4211 | + * http://api.jqueryui.com/selectable/ | |
| 4212 | + */ | |
| 4213 | + | |
| 4214 | + | |
| 4215 | +var selectable = $.widget("ui.selectable", $.ui.mouse, { | |
| 4216 | + version: "1.11.4", | |
| 4217 | + options: { | |
| 4218 | + appendTo: "body", | |
| 4219 | + autoRefresh: true, | |
| 4220 | + distance: 0, | |
| 4221 | + filter: "*", | |
| 4222 | + tolerance: "touch", | |
| 4223 | + | |
| 4224 | + // callbacks | |
| 4225 | + selected: null, | |
| 4226 | + selecting: null, | |
| 4227 | + start: null, | |
| 4228 | + stop: null, | |
| 4229 | + unselected: null, | |
| 4230 | + unselecting: null | |
| 4231 | + }, | |
| 4232 | + _create: function() { | |
| 4233 | + var selectees, | |
| 4234 | + that = this; | |
| 4235 | + | |
| 4236 | + this.element.addClass("ui-selectable"); | |
| 4237 | + | |
| 4238 | + this.dragged = false; | |
| 4239 | + | |
| 4240 | + // cache selectee children based on filter | |
| 4241 | + this.refresh = function() { | |
| 4242 | + selectees = $(that.options.filter, that.element[0]); | |
| 4243 | + selectees.addClass("ui-selectee"); | |
| 4244 | + selectees.each(function() { | |
| 4245 | + var $this = $(this), | |
| 4246 | + pos = $this.offset(); | |
| 4247 | + $.data(this, "selectable-item", { | |
| 4248 | + element: this, | |
| 4249 | + $element: $this, | |
| 4250 | + left: pos.left, | |
| 4251 | + top: pos.top, | |
| 4252 | + right: pos.left + $this.outerWidth(), | |
| 4253 | + bottom: pos.top + $this.outerHeight(), | |
| 4254 | + startselected: false, | |
| 4255 | + selected: $this.hasClass("ui-selected"), | |
| 4256 | + selecting: $this.hasClass("ui-selecting"), | |
| 4257 | + unselecting: $this.hasClass("ui-unselecting") | |
| 4258 | + }); | |
| 4259 | + }); | |
| 4260 | + }; | |
| 4261 | + this.refresh(); | |
| 4262 | + | |
| 4263 | + this.selectees = selectees.addClass("ui-selectee"); | |
| 4264 | + | |
| 4265 | + this._mouseInit(); | |
| 4266 | + | |
| 4267 | + this.helper = $("<div class='ui-selectable-helper'></div>"); | |
| 4268 | + }, | |
| 4269 | + | |
| 4270 | + _destroy: function() { | |
| 4271 | + this.selectees | |
| 4272 | + .removeClass("ui-selectee") | |
| 4273 | + .removeData("selectable-item"); | |
| 4274 | + this.element | |
| 4275 | + .removeClass("ui-selectable ui-selectable-disabled"); | |
| 4276 | + this._mouseDestroy(); | |
| 4277 | + }, | |
| 4278 | + | |
| 4279 | + _mouseStart: function(event) { | |
| 4280 | + var that = this, | |
| 4281 | + options = this.options; | |
| 4282 | + | |
| 4283 | + this.opos = [ event.pageX, event.pageY ]; | |
| 4284 | + | |
| 4285 | + if (this.options.disabled) { | |
| 4286 | + return; | |
| 4287 | + } | |
| 4288 | + | |
| 4289 | + this.selectees = $(options.filter, this.element[0]); | |
| 4290 | + | |
| 4291 | + this._trigger("start", event); | |
| 4292 | + | |
| 4293 | + $(options.appendTo).append(this.helper); | |
| 4294 | + // position helper (lasso) | |
| 4295 | + this.helper.css({ | |
| 4296 | + "left": event.pageX, | |
| 4297 | + "top": event.pageY, | |
| 4298 | + "width": 0, | |
| 4299 | + "height": 0 | |
| 4300 | + }); | |
| 4301 | + | |
| 4302 | + if (options.autoRefresh) { | |
| 4303 | + this.refresh(); | |
| 4304 | + } | |
| 4305 | + | |
| 4306 | + this.selectees.filter(".ui-selected").each(function() { | |
| 4307 | + var selectee = $.data(this, "selectable-item"); | |
| 4308 | + selectee.startselected = true; | |
| 4309 | + if (!event.metaKey && !event.ctrlKey) { | |
| 4310 | + selectee.$element.removeClass("ui-selected"); | |
| 4311 | + selectee.selected = false; | |
| 4312 | + selectee.$element.addClass("ui-unselecting"); | |
| 4313 | + selectee.unselecting = true; | |
| 4314 | + // selectable UNSELECTING callback | |
| 4315 | + that._trigger("unselecting", event, { | |
| 4316 | + unselecting: selectee.element | |
| 4317 | + }); | |
| 4318 | + } | |
| 4319 | + }); | |
| 4320 | + | |
| 4321 | + $(event.target).parents().addBack().each(function() { | |
| 4322 | + var doSelect, | |
| 4323 | + selectee = $.data(this, "selectable-item"); | |
| 4324 | + if (selectee) { | |
| 4325 | + doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); | |
| 4326 | + selectee.$element | |
| 4327 | + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") | |
| 4328 | + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); | |
| 4329 | + selectee.unselecting = !doSelect; | |
| 4330 | + selectee.selecting = doSelect; | |
| 4331 | + selectee.selected = doSelect; | |
| 4332 | + // selectable (UN)SELECTING callback | |
| 4333 | + if (doSelect) { | |
| 4334 | + that._trigger("selecting", event, { | |
| 4335 | + selecting: selectee.element | |
| 4336 | + }); | |
| 4337 | + } else { | |
| 4338 | + that._trigger("unselecting", event, { | |
| 4339 | + unselecting: selectee.element | |
| 4340 | + }); | |
| 4341 | + } | |
| 4342 | + return false; | |
| 4343 | + } | |
| 4344 | + }); | |
| 4345 | + | |
| 4346 | + }, | |
| 4347 | + | |
| 4348 | + _mouseDrag: function(event) { | |
| 4349 | + | |
| 4350 | + this.dragged = true; | |
| 4351 | + | |
| 4352 | + if (this.options.disabled) { | |
| 4353 | + return; | |
| 4354 | + } | |
| 4355 | + | |
| 4356 | + var tmp, | |
| 4357 | + that = this, | |
| 4358 | + options = this.options, | |
| 4359 | + x1 = this.opos[0], | |
| 4360 | + y1 = this.opos[1], | |
| 4361 | + x2 = event.pageX, | |
| 4362 | + y2 = event.pageY; | |
| 4363 | + | |
| 4364 | + if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } | |
| 4365 | + if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } | |
| 4366 | + this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 }); | |
| 4367 | + | |
| 4368 | + this.selectees.each(function() { | |
| 4369 | + var selectee = $.data(this, "selectable-item"), | |
| 4370 | + hit = false; | |
| 4371 | + | |
| 4372 | + //prevent helper from being selected if appendTo: selectable | |
| 4373 | + if (!selectee || selectee.element === that.element[0]) { | |
| 4374 | + return; | |
| 4375 | + } | |
| 4376 | + | |
| 4377 | + if (options.tolerance === "touch") { | |
| 4378 | + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); | |
| 4379 | + } else if (options.tolerance === "fit") { | |
| 4380 | + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); | |
| 4381 | + } | |
| 4382 | + | |
| 4383 | + if (hit) { | |
| 4384 | + // SELECT | |
| 4385 | + if (selectee.selected) { | |
| 4386 | + selectee.$element.removeClass("ui-selected"); | |
| 4387 | + selectee.selected = false; | |
| 4388 | + } | |
| 4389 | + if (selectee.unselecting) { | |
| 4390 | + selectee.$element.removeClass("ui-unselecting"); | |
| 4391 | + selectee.unselecting = false; | |
| 4392 | + } | |
| 4393 | + if (!selectee.selecting) { | |
| 4394 | + selectee.$element.addClass("ui-selecting"); | |
| 4395 | + selectee.selecting = true; | |
| 4396 | + // selectable SELECTING callback | |
| 4397 | + that._trigger("selecting", event, { | |
| 4398 | + selecting: selectee.element | |
| 4399 | + }); | |
| 4400 | + } | |
| 4401 | + } else { | |
| 4402 | + // UNSELECT | |
| 4403 | + if (selectee.selecting) { | |
| 4404 | + if ((event.metaKey || event.ctrlKey) && selectee.startselected) { | |
| 4405 | + selectee.$element.removeClass("ui-selecting"); | |
| 4406 | + selectee.selecting = false; | |
| 4407 | + selectee.$element.addClass("ui-selected"); | |
| 4408 | + selectee.selected = true; | |
| 4409 | + } else { | |
| 4410 | + selectee.$element.removeClass("ui-selecting"); | |
| 4411 | + selectee.selecting = false; | |
| 4412 | + if (selectee.startselected) { | |
| 4413 | + selectee.$element.addClass("ui-unselecting"); | |
| 4414 | + selectee.unselecting = true; | |
| 4415 | + } | |
| 4416 | + // selectable UNSELECTING callback | |
| 4417 | + that._trigger("unselecting", event, { | |
| 4418 | + unselecting: selectee.element | |
| 4419 | + }); | |
| 4420 | + } | |
| 4421 | + } | |
| 4422 | + if (selectee.selected) { | |
| 4423 | + if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { | |
| 4424 | + selectee.$element.removeClass("ui-selected"); | |
| 4425 | + selectee.selected = false; | |
| 4426 | + | |
| 4427 | + selectee.$element.addClass("ui-unselecting"); | |
| 4428 | + selectee.unselecting = true; | |
| 4429 | + // selectable UNSELECTING callback | |
| 4430 | + that._trigger("unselecting", event, { | |
| 4431 | + unselecting: selectee.element | |
| 4432 | + }); | |
| 4433 | + } | |
| 4434 | + } | |
| 4435 | + } | |
| 4436 | + }); | |
| 4437 | + | |
| 4438 | + return false; | |
| 4439 | + }, | |
| 4440 | + | |
| 4441 | + _mouseStop: function(event) { | |
| 4442 | + var that = this; | |
| 4443 | + | |
| 4444 | + this.dragged = false; | |
| 4445 | + | |
| 4446 | + $(".ui-unselecting", this.element[0]).each(function() { | |
| 4447 | + var selectee = $.data(this, "selectable-item"); | |
| 4448 | + selectee.$element.removeClass("ui-unselecting"); | |
| 4449 | + selectee.unselecting = false; | |
| 4450 | + selectee.startselected = false; | |
| 4451 | + that._trigger("unselected", event, { | |
| 4452 | + unselected: selectee.element | |
| 4453 | + }); | |
| 4454 | + }); | |
| 4455 | + $(".ui-selecting", this.element[0]).each(function() { | |
| 4456 | + var selectee = $.data(this, "selectable-item"); | |
| 4457 | + selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); | |
| 4458 | + selectee.selecting = false; | |
| 4459 | + selectee.selected = true; | |
| 4460 | + selectee.startselected = true; | |
| 4461 | + that._trigger("selected", event, { | |
| 4462 | + selected: selectee.element | |
| 4463 | + }); | |
| 4464 | + }); | |
| 4465 | + this._trigger("stop", event); | |
| 4466 | + | |
| 4467 | + this.helper.remove(); | |
| 4468 | + | |
| 4469 | + return false; | |
| 4470 | + } | |
| 4471 | + | |
| 4472 | +}); | |
| 4473 | + | |
| 4474 | + | |
| 4475 | +/*! | |
| 4476 | + * jQuery UI Sortable 1.11.4 | |
| 4477 | + * http://jqueryui.com | |
| 4478 | + * | |
| 4479 | + * Copyright jQuery Foundation and other contributors | |
| 4480 | + * Released under the MIT license. | |
| 4481 | + * http://jquery.org/license | |
| 4482 | + * | |
| 4483 | + * http://api.jqueryui.com/sortable/ | |
| 4484 | + */ | |
| 4485 | + | |
| 4486 | + | |
| 4487 | +var sortable = $.widget("ui.sortable", $.ui.mouse, { | |
| 4488 | + version: "1.11.4", | |
| 4489 | + widgetEventPrefix: "sort", | |
| 4490 | + ready: false, | |
| 4491 | + options: { | |
| 4492 | + appendTo: "parent", | |
| 4493 | + axis: false, | |
| 4494 | + connectWith: false, | |
| 4495 | + containment: false, | |
| 4496 | + cursor: "auto", | |
| 4497 | + cursorAt: false, | |
| 4498 | + dropOnEmpty: true, | |
| 4499 | + forcePlaceholderSize: false, | |
| 4500 | + forceHelperSize: false, | |
| 4501 | + grid: false, | |
| 4502 | + handle: false, | |
| 4503 | + helper: "original", | |
| 4504 | + items: "> *", | |
| 4505 | + opacity: false, | |
| 4506 | + placeholder: false, | |
| 4507 | + revert: false, | |
| 4508 | + scroll: true, | |
| 4509 | + scrollSensitivity: 20, | |
| 4510 | + scrollSpeed: 20, | |
| 4511 | + scope: "default", | |
| 4512 | + tolerance: "intersect", | |
| 4513 | + zIndex: 1000, | |
| 4514 | + | |
| 4515 | + // callbacks | |
| 4516 | + activate: null, | |
| 4517 | + beforeStop: null, | |
| 4518 | + change: null, | |
| 4519 | + deactivate: null, | |
| 4520 | + out: null, | |
| 4521 | + over: null, | |
| 4522 | + receive: null, | |
| 4523 | + remove: null, | |
| 4524 | + sort: null, | |
| 4525 | + start: null, | |
| 4526 | + stop: null, | |
| 4527 | + update: null | |
| 4528 | + }, | |
| 4529 | + | |
| 4530 | + _isOverAxis: function( x, reference, size ) { | |
| 4531 | + return ( x >= reference ) && ( x < ( reference + size ) ); | |
| 4532 | + }, | |
| 4533 | + | |
| 4534 | + _isFloating: function( item ) { | |
| 4535 | + return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); | |
| 4536 | + }, | |
| 4537 | + | |
| 4538 | + _create: function() { | |
| 4539 | + this.containerCache = {}; | |
| 4540 | + this.element.addClass("ui-sortable"); | |
| 4541 | + | |
| 4542 | + //Get the items | |
| 4543 | + this.refresh(); | |
| 4544 | + | |
| 4545 | + //Let's determine the parent's offset | |
| 4546 | + this.offset = this.element.offset(); | |
| 4547 | + | |
| 4548 | + //Initialize mouse events for interaction | |
| 4549 | + this._mouseInit(); | |
| 4550 | + | |
| 4551 | + this._setHandleClassName(); | |
| 4552 | + | |
| 4553 | + //We're ready to go | |
| 4554 | + this.ready = true; | |
| 4555 | + | |
| 4556 | + }, | |
| 4557 | + | |
| 4558 | + _setOption: function( key, value ) { | |
| 4559 | + this._super( key, value ); | |
| 4560 | + | |
| 4561 | + if ( key === "handle" ) { | |
| 4562 | + this._setHandleClassName(); | |
| 4563 | + } | |
| 4564 | + }, | |
| 4565 | + | |
| 4566 | + _setHandleClassName: function() { | |
| 4567 | + this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" ); | |
| 4568 | + $.each( this.items, function() { | |
| 4569 | + ( this.instance.options.handle ? | |
| 4570 | + this.item.find( this.instance.options.handle ) : this.item ) | |
| 4571 | + .addClass( "ui-sortable-handle" ); | |
| 4572 | + }); | |
| 4573 | + }, | |
| 4574 | + | |
| 4575 | + _destroy: function() { | |
| 4576 | + this.element | |
| 4577 | + .removeClass( "ui-sortable ui-sortable-disabled" ) | |
| 4578 | + .find( ".ui-sortable-handle" ) | |
| 4579 | + .removeClass( "ui-sortable-handle" ); | |
| 4580 | + this._mouseDestroy(); | |
| 4581 | + | |
| 4582 | + for ( var i = this.items.length - 1; i >= 0; i-- ) { | |
| 4583 | + this.items[i].item.removeData(this.widgetName + "-item"); | |
| 4584 | + } | |
| 4585 | + | |
| 4586 | + return this; | |
| 4587 | + }, | |
| 4588 | + | |
| 4589 | + _mouseCapture: function(event, overrideHandle) { | |
| 4590 | + var currentItem = null, | |
| 4591 | + validHandle = false, | |
| 4592 | + that = this; | |
| 4593 | + | |
| 4594 | + if (this.reverting) { | |
| 4595 | + return false; | |
| 4596 | + } | |
| 4597 | + | |
| 4598 | + if(this.options.disabled || this.options.type === "static") { | |
| 4599 | + return false; | |
| 4600 | + } | |
| 4601 | + | |
| 4602 | + //We have to refresh the items data once first | |
| 4603 | + this._refreshItems(event); | |
| 4604 | + | |
| 4605 | + //Find out if the clicked node (or one of its parents) is a actual item in this.items | |
| 4606 | + $(event.target).parents().each(function() { | |
| 4607 | + if($.data(this, that.widgetName + "-item") === that) { | |
| 4608 | + currentItem = $(this); | |
| 4609 | + return false; | |
| 4610 | + } | |
| 4611 | + }); | |
| 4612 | + if($.data(event.target, that.widgetName + "-item") === that) { | |
| 4613 | + currentItem = $(event.target); | |
| 4614 | + } | |
| 4615 | + | |
| 4616 | + if(!currentItem) { | |
| 4617 | + return false; | |
| 4618 | + } | |
| 4619 | + if(this.options.handle && !overrideHandle) { | |
| 4620 | + $(this.options.handle, currentItem).find("*").addBack().each(function() { | |
| 4621 | + if(this === event.target) { | |
| 4622 | + validHandle = true; | |
| 4623 | + } | |
| 4624 | + }); | |
| 4625 | + if(!validHandle) { | |
| 4626 | + return false; | |
| 4627 | + } | |
| 4628 | + } | |
| 4629 | + | |
| 4630 | + this.currentItem = currentItem; | |
| 4631 | + this._removeCurrentsFromItems(); | |
| 4632 | + return true; | |
| 4633 | + | |
| 4634 | + }, | |
| 4635 | + | |
| 4636 | + _mouseStart: function(event, overrideHandle, noActivation) { | |
| 4637 | + | |
| 4638 | + var i, body, | |
| 4639 | + o = this.options; | |
| 4640 | + | |
| 4641 | + this.currentContainer = this; | |
| 4642 | + | |
| 4643 | + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture | |
| 4644 | + this.refreshPositions(); | |
| 4645 | + | |
| 4646 | + //Create and append the visible helper | |
| 4647 | + this.helper = this._createHelper(event); | |
| 4648 | + | |
| 4649 | + //Cache the helper size | |
| 4650 | + this._cacheHelperProportions(); | |
| 4651 | + | |
| 4652 | + /* | |
| 4653 | + * - Position generation - | |
| 4654 | + * This block generates everything position related - it's the core of draggables. | |
| 4655 | + */ | |
| 4656 | + | |
| 4657 | + //Cache the margins of the original element | |
| 4658 | + this._cacheMargins(); | |
| 4659 | + | |
| 4660 | + //Get the next scrolling parent | |
| 4661 | + this.scrollParent = this.helper.scrollParent(); | |
| 4662 | + | |
| 4663 | + //The element's absolute position on the page minus margins | |
| 4664 | + this.offset = this.currentItem.offset(); | |
| 4665 | + this.offset = { | |
| 4666 | + top: this.offset.top - this.margins.top, | |
| 4667 | + left: this.offset.left - this.margins.left | |
| 4668 | + }; | |
| 4669 | + | |
| 4670 | + $.extend(this.offset, { | |
| 4671 | + click: { //Where the click happened, relative to the element | |
| 4672 | + left: event.pageX - this.offset.left, | |
| 4673 | + top: event.pageY - this.offset.top | |
| 4674 | + }, | |
| 4675 | + parent: this._getParentOffset(), | |
| 4676 | + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper | |
| 4677 | + }); | |
| 4678 | + | |
| 4679 | + // Only after we got the offset, we can change the helper's position to absolute | |
| 4680 | + // TODO: Still need to figure out a way to make relative sorting possible | |
| 4681 | + this.helper.css("position", "absolute"); | |
| 4682 | + this.cssPosition = this.helper.css("position"); | |
| 4683 | + | |
| 4684 | + //Generate the original position | |
| 4685 | + this.originalPosition = this._generatePosition(event); | |
| 4686 | + this.originalPageX = event.pageX; | |
| 4687 | + this.originalPageY = event.pageY; | |
| 4688 | + | |
| 4689 | + //Adjust the mouse offset relative to the helper if "cursorAt" is supplied | |
| 4690 | + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); | |
| 4691 | + | |
| 4692 | + //Cache the former DOM position | |
| 4693 | + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; | |
| 4694 | + | |
| 4695 | + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way | |
| 4696 | + if(this.helper[0] !== this.currentItem[0]) { | |
| 4697 | + this.currentItem.hide(); | |
| 4698 | + } | |
| 4699 | + | |
| 4700 | + //Create the placeholder | |
| 4701 | + this._createPlaceholder(); | |
| 4702 | + | |
| 4703 | + //Set a containment if given in the options | |
| 4704 | + if(o.containment) { | |
| 4705 | + this._setContainment(); | |
| 4706 | + } | |
| 4707 | + | |
| 4708 | + if( o.cursor && o.cursor !== "auto" ) { // cursor option | |
| 4709 | + body = this.document.find( "body" ); | |
| 4710 | + | |
| 4711 | + // support: IE | |
| 4712 | + this.storedCursor = body.css( "cursor" ); | |
| 4713 | + body.css( "cursor", o.cursor ); | |
| 4714 | + | |
| 4715 | + this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); | |
| 4716 | + } | |
| 4717 | + | |
| 4718 | + if(o.opacity) { // opacity option | |
| 4719 | + if (this.helper.css("opacity")) { | |
| 4720 | + this._storedOpacity = this.helper.css("opacity"); | |
| 4721 | + } | |
| 4722 | + this.helper.css("opacity", o.opacity); | |
| 4723 | + } | |
| 4724 | + | |
| 4725 | + if(o.zIndex) { // zIndex option | |
| 4726 | + if (this.helper.css("zIndex")) { | |
| 4727 | + this._storedZIndex = this.helper.css("zIndex"); | |
| 4728 | + } | |
| 4729 | + this.helper.css("zIndex", o.zIndex); | |
| 4730 | + } | |
| 4731 | + | |
| 4732 | + //Prepare scrolling | |
| 4733 | + if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { | |
| 4734 | + this.overflowOffset = this.scrollParent.offset(); | |
| 4735 | + } | |
| 4736 | + | |
| 4737 | + //Call callbacks | |
| 4738 | + this._trigger("start", event, this._uiHash()); | |
| 4739 | + | |
| 4740 | + //Recache the helper size | |
| 4741 | + if(!this._preserveHelperProportions) { | |
| 4742 | + this._cacheHelperProportions(); | |
| 4743 | + } | |
| 4744 | + | |
| 4745 | + | |
| 4746 | + //Post "activate" events to possible containers | |
| 4747 | + if( !noActivation ) { | |
| 4748 | + for ( i = this.containers.length - 1; i >= 0; i-- ) { | |
| 4749 | + this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); | |
| 4750 | + } | |
| 4751 | + } | |
| 4752 | + | |
| 4753 | + //Prepare possible droppables | |
| 4754 | + if($.ui.ddmanager) { | |
| 4755 | + $.ui.ddmanager.current = this; | |
| 4756 | + } | |
| 4757 | + | |
| 4758 | + if ($.ui.ddmanager && !o.dropBehaviour) { | |
| 4759 | + $.ui.ddmanager.prepareOffsets(this, event); | |
| 4760 | + } | |
| 4761 | + | |
| 4762 | + this.dragging = true; | |
| 4763 | + | |
| 4764 | + this.helper.addClass("ui-sortable-helper"); | |
| 4765 | + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position | |
| 4766 | + return true; | |
| 4767 | + | |
| 4768 | + }, | |
| 4769 | + | |
| 4770 | + _mouseDrag: function(event) { | |
| 4771 | + var i, item, itemElement, intersection, | |
| 4772 | + o = this.options, | |
| 4773 | + scrolled = false; | |
| 4774 | + | |
| 4775 | + //Compute the helpers position | |
| 4776 | + this.position = this._generatePosition(event); | |
| 4777 | + this.positionAbs = this._convertPositionTo("absolute"); | |
| 4778 | + | |
| 4779 | + if (!this.lastPositionAbs) { | |
| 4780 | + this.lastPositionAbs = this.positionAbs; | |
| 4781 | + } | |
| 4782 | + | |
| 4783 | + //Do scrolling | |
| 4784 | + if(this.options.scroll) { | |
| 4785 | + if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { | |
| 4786 | + | |
| 4787 | + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { | |
| 4788 | + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; | |
| 4789 | + } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { | |
| 4790 | + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; | |
| 4791 | + } | |
| 4792 | + | |
| 4793 | + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { | |
| 4794 | + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; | |
| 4795 | + } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { | |
| 4796 | + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; | |
| 4797 | + } | |
| 4798 | + | |
| 4799 | + } else { | |
| 4800 | + | |
| 4801 | + if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) { | |
| 4802 | + scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed); | |
| 4803 | + } else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) { | |
| 4804 | + scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed); | |
| 4805 | + } | |
| 4806 | + | |
| 4807 | + if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) { | |
| 4808 | + scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed); | |
| 4809 | + } else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) { | |
| 4810 | + scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed); | |
| 4811 | + } | |
| 4812 | + | |
| 4813 | + } | |
| 4814 | + | |
| 4815 | + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { | |
| 4816 | + $.ui.ddmanager.prepareOffsets(this, event); | |
| 4817 | + } | |
| 4818 | + } | |
| 4819 | + | |
| 4820 | + //Regenerate the absolute position used for position checks | |
| 4821 | + this.positionAbs = this._convertPositionTo("absolute"); | |
| 4822 | + | |
| 4823 | + //Set the helper position | |
| 4824 | + if(!this.options.axis || this.options.axis !== "y") { | |
| 4825 | + this.helper[0].style.left = this.position.left+"px"; | |
| 4826 | + } | |
| 4827 | + if(!this.options.axis || this.options.axis !== "x") { | |
| 4828 | + this.helper[0].style.top = this.position.top+"px"; | |
| 4829 | + } | |
| 4830 | + | |
| 4831 | + //Rearrange | |
| 4832 | + for (i = this.items.length - 1; i >= 0; i--) { | |
| 4833 | + | |
| 4834 | + //Cache variables and intersection, continue if no intersection | |
| 4835 | + item = this.items[i]; | |
| 4836 | + itemElement = item.item[0]; | |
| 4837 | + intersection = this._intersectsWithPointer(item); | |
| 4838 | + if (!intersection) { | |
| 4839 | + continue; | |
| 4840 | + } | |
| 4841 | + | |
| 4842 | + // Only put the placeholder inside the current Container, skip all | |
| 4843 | + // items from other containers. This works because when moving | |
| 4844 | + // an item from one container to another the | |
| 4845 | + // currentContainer is switched before the placeholder is moved. | |
| 4846 | + // | |
| 4847 | + // Without this, moving items in "sub-sortables" can cause | |
| 4848 | + // the placeholder to jitter between the outer and inner container. | |
| 4849 | + if (item.instance !== this.currentContainer) { | |
| 4850 | + continue; | |
| 4851 | + } | |
| 4852 | + | |
| 4853 | + // cannot intersect with itself | |
| 4854 | + // no useless actions that have been done before | |
| 4855 | + // no action if the item moved is the parent of the item checked | |
| 4856 | + if (itemElement !== this.currentItem[0] && | |
| 4857 | + this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && | |
| 4858 | + !$.contains(this.placeholder[0], itemElement) && | |
| 4859 | + (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) | |
| 4860 | + ) { | |
| 4861 | + | |
| 4862 | + this.direction = intersection === 1 ? "down" : "up"; | |
| 4863 | + | |
| 4864 | + if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { | |
| 4865 | + this._rearrange(event, item); | |
| 4866 | + } else { | |
| 4867 | + break; | |
| 4868 | + } | |
| 4869 | + | |
| 4870 | + this._trigger("change", event, this._uiHash()); | |
| 4871 | + break; | |
| 4872 | + } | |
| 4873 | + } | |
| 4874 | + | |
| 4875 | + //Post events to containers | |
| 4876 | + this._contactContainers(event); | |
| 4877 | + | |
| 4878 | + //Interconnect with droppables | |
| 4879 | + if($.ui.ddmanager) { | |
| 4880 | + $.ui.ddmanager.drag(this, event); | |
| 4881 | + } | |
| 4882 | + | |
| 4883 | + //Call callbacks | |
| 4884 | + this._trigger("sort", event, this._uiHash()); | |
| 4885 | + | |
| 4886 | + this.lastPositionAbs = this.positionAbs; | |
| 4887 | + return false; | |
| 4888 | + | |
| 4889 | + }, | |
| 4890 | + | |
| 4891 | + _mouseStop: function(event, noPropagation) { | |
| 4892 | + | |
| 4893 | + if(!event) { | |
| 4894 | + return; | |
| 4895 | + } | |
| 4896 | + | |
| 4897 | + //If we are using droppables, inform the manager about the drop | |
| 4898 | + if ($.ui.ddmanager && !this.options.dropBehaviour) { | |
| 4899 | + $.ui.ddmanager.drop(this, event); | |
| 4900 | + } | |
| 4901 | + | |
| 4902 | + if(this.options.revert) { | |
| 4903 | + var that = this, | |
| 4904 | + cur = this.placeholder.offset(), | |
| 4905 | + axis = this.options.axis, | |
| 4906 | + animation = {}; | |
| 4907 | + | |
| 4908 | + if ( !axis || axis === "x" ) { | |
| 4909 | + animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft); | |
| 4910 | + } | |
| 4911 | + if ( !axis || axis === "y" ) { | |
| 4912 | + animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop); | |
| 4913 | + } | |
| 4914 | + this.reverting = true; | |
| 4915 | + $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { | |
| 4916 | + that._clear(event); | |
| 4917 | + }); | |
| 4918 | + } else { | |
| 4919 | + this._clear(event, noPropagation); | |
| 4920 | + } | |
| 4921 | + | |
| 4922 | + return false; | |
| 4923 | + | |
| 4924 | + }, | |
| 4925 | + | |
| 4926 | + cancel: function() { | |
| 4927 | + | |
| 4928 | + if(this.dragging) { | |
| 4929 | + | |
| 4930 | + this._mouseUp({ target: null }); | |
| 4931 | + | |
| 4932 | + if(this.options.helper === "original") { | |
| 4933 | + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); | |
| 4934 | + } else { | |
| 4935 | + this.currentItem.show(); | |
| 4936 | + } | |
| 4937 | + | |
| 4938 | + //Post deactivating events to containers | |
| 4939 | + for (var i = this.containers.length - 1; i >= 0; i--){ | |
| 4940 | + this.containers[i]._trigger("deactivate", null, this._uiHash(this)); | |
| 4941 | + if(this.containers[i].containerCache.over) { | |
| 4942 | + this.containers[i]._trigger("out", null, this._uiHash(this)); | |
| 4943 | + this.containers[i].containerCache.over = 0; | |
| 4944 | + } | |
| 4945 | + } | |
| 4946 | + | |
| 4947 | + } | |
| 4948 | + | |
| 4949 | + if (this.placeholder) { | |
| 4950 | + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! | |
| 4951 | + if(this.placeholder[0].parentNode) { | |
| 4952 | + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); | |
| 4953 | + } | |
| 4954 | + if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { | |
| 4955 | + this.helper.remove(); | |
| 4956 | + } | |
| 4957 | + | |
| 4958 | + $.extend(this, { | |
| 4959 | + helper: null, | |
| 4960 | + dragging: false, | |
| 4961 | + reverting: false, | |
| 4962 | + _noFinalSort: null | |
| 4963 | + }); | |
| 4964 | + | |
| 4965 | + if(this.domPosition.prev) { | |
| 4966 | + $(this.domPosition.prev).after(this.currentItem); | |
| 4967 | + } else { | |
| 4968 | + $(this.domPosition.parent).prepend(this.currentItem); | |
| 4969 | + } | |
| 4970 | + } | |
| 4971 | + | |
| 4972 | + return this; | |
| 4973 | + | |
| 4974 | + }, | |
| 4975 | + | |
| 4976 | + serialize: function(o) { | |
| 4977 | + | |
| 4978 | + var items = this._getItemsAsjQuery(o && o.connected), | |
| 4979 | + str = []; | |
| 4980 | + o = o || {}; | |
| 4981 | + | |
| 4982 | + $(items).each(function() { | |
| 4983 | + var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); | |
| 4984 | + if (res) { | |
| 4985 | + str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); | |
| 4986 | + } | |
| 4987 | + }); | |
| 4988 | + | |
| 4989 | + if(!str.length && o.key) { | |
| 4990 | + str.push(o.key + "="); | |
| 4991 | + } | |
| 4992 | + | |
| 4993 | + return str.join("&"); | |
| 4994 | + | |
| 4995 | + }, | |
| 4996 | + | |
| 4997 | + toArray: function(o) { | |
| 4998 | + | |
| 4999 | + var items = this._getItemsAsjQuery(o && o.connected), | |
11618 more lines aren’t shown here.
| @@ -0,0 +1,13963 @@ | ||
| 1 | +/** | |
| 2 | + * PUI Object | |
| 3 | + */ | |
| 4 | +var PUI = { | |
| 5 | + | |
| 6 | + zindex : 1000, | |
| 7 | + | |
| 8 | + gridColumns: { | |
| 9 | + '1': 'ui-grid-col-12', | |
| 10 | + '2': 'ui-grid-col-6', | |
| 11 | + '3': 'ui-grid-col-4', | |
| 12 | + '4': 'ui-grid-col-3', | |
| 13 | + '6': 'ui-grid-col-2', | |
| 14 | + '12': 'ui-grid-col-11' | |
| 15 | + }, | |
| 16 | + | |
| 17 | + charSet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * Aligns container scrollbar to keep item in container viewport, algorithm copied from jquery-ui menu widget | |
| 21 | + */ | |
| 22 | + scrollInView: function(container, item) { | |
| 23 | + var borderTop = parseFloat(container.css('borderTopWidth')) || 0, | |
| 24 | + paddingTop = parseFloat(container.css('paddingTop')) || 0, | |
| 25 | + offset = item.offset().top - container.offset().top - borderTop - paddingTop, | |
| 26 | + scroll = container.scrollTop(), | |
| 27 | + elementHeight = container.height(), | |
| 28 | + itemHeight = item.outerHeight(true); | |
| 29 | + | |
| 30 | + if(offset < 0) { | |
| 31 | + container.scrollTop(scroll + offset); | |
| 32 | + } | |
| 33 | + else if((offset + itemHeight) > elementHeight) { | |
| 34 | + container.scrollTop(scroll + offset - elementHeight + itemHeight); | |
| 35 | + } | |
| 36 | + }, | |
| 37 | + | |
| 38 | + generateRandomId: function() { | |
| 39 | + var id = ''; | |
| 40 | + for (var i = 1; i <= 10; i++) { | |
| 41 | + var randPos = Math.floor(Math.random() * this.charSet.length); | |
| 42 | + id += this.charSet[randPos]; | |
| 43 | + } | |
| 44 | + return id; | |
| 45 | + }, | |
| 46 | + | |
| 47 | + isIE: function(version) { | |
| 48 | + return (this.browser.msie && parseInt(this.browser.version, 10) === version); | |
| 49 | + }, | |
| 50 | + | |
| 51 | + escapeRegExp: function(text) { | |
| 52 | + return text.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); | |
| 53 | + }, | |
| 54 | + | |
| 55 | + escapeHTML: function(value) { | |
| 56 | + return value.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); | |
| 57 | + }, | |
| 58 | + | |
| 59 | + escapeClientId: function(id) { | |
| 60 | + return "#" + id.replace(/:/g,"\\:"); | |
| 61 | + }, | |
| 62 | + | |
| 63 | + clearSelection: function() { | |
| 64 | + if(window.getSelection) { | |
| 65 | + if(window.getSelection().empty) { | |
| 66 | + window.getSelection().empty(); | |
| 67 | + } else if(window.getSelection().removeAllRanges) { | |
| 68 | + window.getSelection().removeAllRanges(); | |
| 69 | + } | |
| 70 | + } else if(document.selection && document.selection.empty) { | |
| 71 | + document.selection.empty(); | |
| 72 | + } | |
| 73 | + }, | |
| 74 | + | |
| 75 | + inArray: function(arr, item) { | |
| 76 | + for(var i = 0; i < arr.length; i++) { | |
| 77 | + if(arr[i] === item) { | |
| 78 | + return true; | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + return false; | |
| 83 | + }, | |
| 84 | + | |
| 85 | + calculateScrollbarWidth: function() { | |
| 86 | + if(!this.scrollbarWidth) { | |
| 87 | + if(this.browser.msie) { | |
| 88 | + var $textarea1 = $('<textarea cols="10" rows="2"></textarea>') | |
| 89 | + .css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body'), | |
| 90 | + $textarea2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>') | |
| 91 | + .css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body'); | |
| 92 | + this.scrollbarWidth = $textarea1.width() - $textarea2.width(); | |
| 93 | + $textarea1.add($textarea2).remove(); | |
| 94 | + } | |
| 95 | + else { | |
| 96 | + var $div = $('<div />') | |
| 97 | + .css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: -1000 }) | |
| 98 | + .prependTo('body').append('<div />').find('div') | |
| 99 | + .css({ width: '100%', height: 200 }); | |
| 100 | + this.scrollbarWidth = 100 - $div.width(); | |
| 101 | + $div.parent().remove(); | |
| 102 | + } | |
| 103 | + } | |
| 104 | + | |
| 105 | + return this.scrollbarWidth; | |
| 106 | + }, | |
| 107 | + | |
| 108 | + //adapted from jquery browser plugin | |
| 109 | + resolveUserAgent: function() { | |
| 110 | + var matched, browser; | |
| 111 | + | |
| 112 | + jQuery.uaMatch = function( ua ) { | |
| 113 | + ua = ua.toLowerCase(); | |
| 114 | + | |
| 115 | + var match = /(opr)[\/]([\w.]+)/.exec( ua ) || | |
| 116 | + /(chrome)[ \/]([\w.]+)/.exec( ua ) || | |
| 117 | + /(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec( ua ) || | |
| 118 | + /(webkit)[ \/]([\w.]+)/.exec( ua ) || | |
| 119 | + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || | |
| 120 | + /(msie) ([\w.]+)/.exec( ua ) || | |
| 121 | + ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec( ua ) || | |
| 122 | + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || | |
| 123 | + []; | |
| 124 | + | |
| 125 | + var platform_match = /(ipad)/.exec( ua ) || | |
| 126 | + /(iphone)/.exec( ua ) || | |
| 127 | + /(android)/.exec( ua ) || | |
| 128 | + /(windows phone)/.exec( ua ) || | |
| 129 | + /(win)/.exec( ua ) || | |
| 130 | + /(mac)/.exec( ua ) || | |
| 131 | + /(linux)/.exec( ua ) || | |
| 132 | + /(cros)/i.exec( ua ) || | |
| 133 | + []; | |
| 134 | + | |
| 135 | + return { | |
| 136 | + browser: match[ 3 ] || match[ 1 ] || "", | |
| 137 | + version: match[ 2 ] || "0", | |
| 138 | + platform: platform_match[ 0 ] || "" | |
| 139 | + }; | |
| 140 | + }; | |
| 141 | + | |
| 142 | + matched = jQuery.uaMatch( window.navigator.userAgent ); | |
| 143 | + browser = {}; | |
| 144 | + | |
| 145 | + if ( matched.browser ) { | |
| 146 | + browser[ matched.browser ] = true; | |
| 147 | + browser.version = matched.version; | |
| 148 | + browser.versionNumber = parseInt(matched.version); | |
| 149 | + } | |
| 150 | + | |
| 151 | + if ( matched.platform ) { | |
| 152 | + browser[ matched.platform ] = true; | |
| 153 | + } | |
| 154 | + | |
| 155 | + // These are all considered mobile platforms, meaning they run a mobile browser | |
| 156 | + if ( browser.android || browser.ipad || browser.iphone || browser[ "windows phone" ] ) { | |
| 157 | + browser.mobile = true; | |
| 158 | + } | |
| 159 | + | |
| 160 | + // These are all considered desktop platforms, meaning they run a desktop browser | |
| 161 | + if ( browser.cros || browser.mac || browser.linux || browser.win ) { | |
| 162 | + browser.desktop = true; | |
| 163 | + } | |
| 164 | + | |
| 165 | + // Chrome, Opera 15+ and Safari are webkit based browsers | |
| 166 | + if ( browser.chrome || browser.opr || browser.safari ) { | |
| 167 | + browser.webkit = true; | |
| 168 | + } | |
| 169 | + | |
| 170 | + // IE11 has a new token so we will assign it msie to avoid breaking changes | |
| 171 | + if ( browser.rv ) | |
| 172 | + { | |
| 173 | + var ie = "msie"; | |
| 174 | + | |
| 175 | + matched.browser = ie; | |
| 176 | + browser[ie] = true; | |
| 177 | + } | |
| 178 | + | |
| 179 | + // Opera 15+ are identified as opr | |
| 180 | + if ( browser.opr ) | |
| 181 | + { | |
| 182 | + var opera = "opera"; | |
| 183 | + | |
| 184 | + matched.browser = opera; | |
| 185 | + browser[opera] = true; | |
| 186 | + } | |
| 187 | + | |
| 188 | + // Stock Android browsers are marked as Safari on Android. | |
| 189 | + if ( browser.safari && browser.android ) | |
| 190 | + { | |
| 191 | + var android = "android"; | |
| 192 | + | |
| 193 | + matched.browser = android; | |
| 194 | + browser[android] = true; | |
| 195 | + } | |
| 196 | + | |
| 197 | + // Assign the name and platform variable | |
| 198 | + browser.name = matched.browser; | |
| 199 | + browser.platform = matched.platform; | |
| 200 | + | |
| 201 | + this.browser = browser; | |
| 202 | + $.browser = browser; | |
| 203 | + }, | |
| 204 | + | |
| 205 | + getGridColumn: function(number) { | |
| 206 | + return this.gridColumns[number + '']; | |
| 207 | + }, | |
| 208 | + | |
| 209 | + executeFunctionByName: function(functionName /*, args */) { | |
| 210 | + var args = [].slice.call(arguments).splice(1), | |
| 211 | + context = window, | |
| 212 | + namespaces = functionName.split("."), | |
| 213 | + func = namespaces.pop(); | |
| 214 | + for(var i = 0; i < namespaces.length; i++) { | |
| 215 | + context = context[namespaces[i]]; | |
| 216 | + } | |
| 217 | + return context[func].apply(this, args); | |
| 218 | + }, | |
| 219 | + | |
| 220 | + resolveObjectByName: function(name) { | |
| 221 | + if(name) { | |
| 222 | + var parts = name.split("."); | |
| 223 | + for(var i = 0, len = parts.length, obj = window; i < len; ++i) { | |
| 224 | + obj = obj[parts[i]]; | |
| 225 | + } | |
| 226 | + return obj; | |
| 227 | + } | |
| 228 | + else { | |
| 229 | + return null; | |
| 230 | + } | |
| 231 | + }, | |
| 232 | + | |
| 233 | + getCookie : function(name) { | |
| 234 | + return $.cookie(name); | |
| 235 | + }, | |
| 236 | + | |
| 237 | + setCookie : function(name, value, cfg) { | |
| 238 | + $.cookie(name, value, cfg); | |
| 239 | + }, | |
| 240 | + | |
| 241 | + deleteCookie: function(name, cfg) { | |
| 242 | + $.removeCookie(name, cfg); | |
| 243 | + } | |
| 244 | + | |
| 245 | +}; | |
| 246 | + | |
| 247 | +PUI.resolveUserAgent(); | |
| 248 | +/** | |
| 249 | + * PrimeUI Accordion widget | |
| 250 | + */ | |
| 251 | +(function() { | |
| 252 | + | |
| 253 | + $.widget("primeui.puiaccordion", { | |
| 254 | + | |
| 255 | + options: { | |
| 256 | + activeIndex: 0, | |
| 257 | + multiple: false | |
| 258 | + }, | |
| 259 | + | |
| 260 | + _create: function() { | |
| 261 | + if(this.options.multiple) { | |
| 262 | + this.options.activeIndex = this.options.activeIndex||[0]; | |
| 263 | + } | |
| 264 | + | |
| 265 | + var $this = this; | |
| 266 | + this.element.addClass('ui-accordion ui-widget ui-helper-reset'); | |
| 267 | + | |
| 268 | + var tabContainers = this.element.children(); | |
| 269 | + | |
| 270 | + //primeui | |
| 271 | + if(tabContainers.is('div')) { | |
| 272 | + this.panelMode = 'native'; | |
| 273 | + this.headers = this.element.children('h3'); | |
| 274 | + this.panels = this.element.children('div'); | |
| 275 | + } | |
| 276 | + //primeng | |
| 277 | + else { | |
| 278 | + this.panelMode = 'wrapped'; | |
| 279 | + this.headers = tabContainers.children('h3'); | |
| 280 | + this.panels = tabContainers.children('div'); | |
| 281 | + } | |
| 282 | + | |
| 283 | + this.headers.addClass('ui-accordion-header ui-helper-reset ui-state-default').each(function(i) { | |
| 284 | + var header = $(this), | |
| 285 | + title = header.html(), | |
| 286 | + active = $this.options.multiple ? ($.inArray(i, $this.options.activeIndex) !== -1) : (i == $this.options.activeIndex), | |
| 287 | + headerClass = (active) ? 'ui-state-active ui-corner-top' : 'ui-corner-all', | |
| 288 | + iconClass = (active) ? 'fa fa-fw fa-caret-down' : 'fa fa-fw fa-caret-right'; | |
| 289 | + | |
| 290 | + header.addClass(headerClass).html('<span class="' + iconClass + '"></span><a href="#">' + title + '</a>'); | |
| 291 | + }); | |
| 292 | + | |
| 293 | + this.panels.each(function(i) { | |
| 294 | + var content = $(this); | |
| 295 | + content.addClass('ui-accordion-content ui-helper-reset ui-widget-content'), | |
| 296 | + active = $this.options.multiple ? ($.inArray(i, $this.options.activeIndex) !== -1) : (i == $this.options.activeIndex); | |
| 297 | + | |
| 298 | + if(!active) { | |
| 299 | + content.addClass('ui-helper-hidden'); | |
| 300 | + } | |
| 301 | + }); | |
| 302 | + | |
| 303 | + this.headers.children('a').disableSelection(); | |
| 304 | + | |
| 305 | + this._bindEvents(); | |
| 306 | + }, | |
| 307 | + | |
| 308 | + _destroy: function() { | |
| 309 | + this._unbindEvents(); | |
| 310 | + this.element.removeClass('ui-accordion ui-widget ui-helper-reset'); | |
| 311 | + this.headers.removeClass('ui-accordion-header ui-helper-reset ui-state-default ui-state-hover ui-state-active ui-state-disabled ui-corner-all ui-corner-top'); | |
| 312 | + this.panels.removeClass('ui-accordion-content ui-helper-reset ui-widget-content ui-helper-hidden'); | |
| 313 | + this.headers.children('.fa').remove(); | |
| 314 | + this.headers.children('a').contents().unwrap(); | |
| 315 | + }, | |
| 316 | + | |
| 317 | + _bindEvents: function() { | |
| 318 | + var $this = this; | |
| 319 | + | |
| 320 | + this.headers.on('mouseover.puiaccordion', function() { | |
| 321 | + var element = $(this); | |
| 322 | + if(!element.hasClass('ui-state-active')&&!element.hasClass('ui-state-disabled')) { | |
| 323 | + element.addClass('ui-state-hover'); | |
| 324 | + } | |
| 325 | + }).on('mouseout.puiaccordion', function() { | |
| 326 | + var element = $(this); | |
| 327 | + if(!element.hasClass('ui-state-active')&&!element.hasClass('ui-state-disabled')) { | |
| 328 | + element.removeClass('ui-state-hover'); | |
| 329 | + } | |
| 330 | + }).on('click.puiaccordion', function(e) { | |
| 331 | + var element = $(this); | |
| 332 | + if(!element.hasClass('ui-state-disabled')) { | |
| 333 | + var tabIndex = ($this.panelMode === 'native') ? element.index() / 2 : element.parent().index(); | |
| 334 | + | |
| 335 | + if(element.hasClass('ui-state-active')) { | |
| 336 | + $this.unselect(tabIndex); | |
| 337 | + } | |
| 338 | + else { | |
| 339 | + $this.select(tabIndex, false); | |
| 340 | + } | |
| 341 | + } | |
| 342 | + | |
| 343 | + e.preventDefault(); | |
| 344 | + }); | |
| 345 | + }, | |
| 346 | + | |
| 347 | + _unbindEvents: function() { | |
| 348 | + this.headers.off('mouseover.puiaccordion mouseout.puiaccordion click.puiaccordion'); | |
| 349 | + }, | |
| 350 | + | |
| 351 | + /** | |
| 352 | + * Activates a tab with given index | |
| 353 | + */ | |
| 354 | + select: function(index, silent) { | |
| 355 | + var panel = this.panels.eq(index); | |
| 356 | + | |
| 357 | + if(!silent) { | |
| 358 | + this._trigger('change', null, {'index': index}); | |
| 359 | + } | |
| 360 | + | |
| 361 | + //update state | |
| 362 | + if(this.options.multiple) { | |
| 363 | + this._addToSelection(index); | |
| 364 | + } | |
| 365 | + else { | |
| 366 | + this.options.activeIndex = index; | |
| 367 | + } | |
| 368 | + this._show(panel); | |
| 369 | + }, | |
| 370 | + | |
| 371 | + /** | |
| 372 | + * Deactivates a tab with given index | |
| 373 | + */ | |
| 374 | + unselect: function(index) { | |
| 375 | + var panel = this.panels.eq(index), | |
| 376 | + header = panel.prev(); | |
| 377 | + | |
| 378 | + header.attr('aria-expanded', false).children('.fa').removeClass('fa-caret-down').addClass('fa-caret-right'); | |
| 379 | + header.removeClass('ui-state-active ui-corner-top').addClass('ui-corner-all'); | |
| 380 | + panel.attr('aria-hidden', true).slideUp(); | |
| 381 | + | |
| 382 | + this._removeFromSelection(index); | |
| 383 | + }, | |
| 384 | + | |
| 385 | + _show: function(panel) { | |
| 386 | + //deactivate current | |
| 387 | + if(!this.options.multiple) { | |
| 388 | + var oldHeader = this.headers.filter('.ui-state-active'); | |
| 389 | + oldHeader.children('.fa').removeClass('fa-caret-down').addClass('fa-caret-right'); | |
| 390 | + oldHeader.attr('aria-expanded', false).removeClass('ui-state-active ui-corner-top').addClass('ui-corner-all').next().attr('aria-hidden', true).slideUp(); | |
| 391 | + } | |
| 392 | + | |
| 393 | + //activate selected | |
| 394 | + var newHeader = panel.prev(); | |
| 395 | + newHeader.attr('aria-expanded', true).addClass('ui-state-active ui-corner-top').removeClass('ui-state-hover ui-corner-all') | |
| 396 | + .children('.fa').removeClass('fa-caret-right').addClass('fa-caret-down'); | |
| 397 | + | |
| 398 | + panel.attr('aria-hidden', false).slideDown('normal'); | |
| 399 | + }, | |
| 400 | + | |
| 401 | + _addToSelection: function(nodeId) { | |
| 402 | + this.options.activeIndex.push(nodeId); | |
| 403 | + }, | |
| 404 | + | |
| 405 | + _removeFromSelection: function(index) { | |
| 406 | + this.options.activeIndex = $.grep(this.options.activeIndex, function(r) { | |
| 407 | + return r != index; | |
| 408 | + }); | |
| 409 | + }, | |
| 410 | + | |
| 411 | + _setOption: function(key, value) { | |
| 412 | + if(key === 'activeIndex') { | |
| 413 | + this.select(value, true); | |
| 414 | + } | |
| 415 | + else { | |
| 416 | + $.Widget.prototype._setOption.apply(this, arguments); | |
| 417 | + } | |
| 418 | + } | |
| 419 | + | |
| 420 | + }); | |
| 421 | +})(); | |
| 422 | +/** | |
| 423 | + * PrimeUI autocomplete widget | |
| 424 | + */ | |
| 425 | +(function() { | |
| 426 | + | |
| 427 | + $.widget("primeui.puiautocomplete", { | |
| 428 | + | |
| 429 | + options: { | |
| 430 | + delay: 300, | |
| 431 | + minQueryLength: 1, | |
| 432 | + multiple: false, | |
| 433 | + dropdown: false, | |
| 434 | + scrollHeight: 200, | |
| 435 | + forceSelection: false, | |
| 436 | + effect:null, | |
| 437 | + effectOptions: {}, | |
| 438 | + effectSpeed: 'normal', | |
| 439 | + content: null, | |
| 440 | + caseSensitive: false | |
| 441 | + }, | |
| 442 | + | |
| 443 | + _create: function() { | |
| 444 | + this.element.wrap('<span class="ui-autocomplete ui-widget" />'); | |
| 445 | + this.element.puiinputtext(); | |
| 446 | + this.panel = $('<div class="ui-autocomplete-panel ui-widget-content ui-corner-all ui-helper-hidden ui-shadow"></div>').appendTo('body'); | |
| 447 | + | |
| 448 | + if(this.options.multiple) { | |
| 449 | + this.element.wrap('<ul class="ui-autocomplete-multiple ui-widget ui-inputtext ui-state-default ui-corner-all">' + | |
| 450 | + '<li class="ui-autocomplete-input-token"></li></ul>'); | |
| 451 | + this.inputContainer = this.element.parent(); | |
| 452 | + this.multiContainer = this.inputContainer.parent(); | |
| 453 | + } | |
| 454 | + else { | |
| 455 | + if(this.options.dropdown) { | |
| 456 | + this.dropdown = $('<button type="button" class="ui-autocomplete-dropdown ui-button ui-widget ui-state-default ui-corner-right ui-button-icon-only">' + | |
| 457 | + '<span class="fa fa-fw fa-caret-down"></span><span class="ui-button-text"> </span></button>') | |
| 458 | + .insertAfter(this.element); | |
| 459 | + this.element.removeClass('ui-corner-all').addClass('ui-corner-left'); | |
| 460 | + } | |
| 461 | + } | |
| 462 | + | |
| 463 | + this._bindEvents(); | |
| 464 | + }, | |
| 465 | + | |
| 466 | + _bindEvents: function() { | |
| 467 | + var $this = this; | |
| 468 | + | |
| 469 | + this._bindKeyEvents(); | |
| 470 | + | |
| 471 | + if(this.options.dropdown) { | |
| 472 | + this.dropdown.on('mouseenter.puiautocomplete', function() { | |
| 473 | + if(!$this.element.prop('disabled')) { | |
| 474 | + $this.dropdown.addClass('ui-state-hover'); | |
| 475 | + } | |
| 476 | + }) | |
| 477 | + .on('mouseleave.puiautocomplete', function() { | |
| 478 | + $this.dropdown.removeClass('ui-state-hover'); | |
| 479 | + }) | |
| 480 | + .on('mousedown.puiautocomplete', function() { | |
| 481 | + if(!$this.element.prop('disabled')) { | |
| 482 | + $this.dropdown.addClass('ui-state-active'); | |
| 483 | + } | |
| 484 | + }) | |
| 485 | + .on('mouseup.puiautocomplete', function() { | |
| 486 | + if(!$this.element.prop('disabled')) { | |
| 487 | + $this.dropdown.removeClass('ui-state-active'); | |
| 488 | + $this.search(''); | |
| 489 | + $this.element.focus(); | |
| 490 | + } | |
| 491 | + }) | |
| 492 | + .on('focus.puiautocomplete', function() { | |
| 493 | + $this.dropdown.addClass('ui-state-focus'); | |
| 494 | + }) | |
| 495 | + .on('blur.puiautocomplete', function() { | |
| 496 | + $this.dropdown.removeClass('ui-state-focus'); | |
| 497 | + }) | |
| 498 | + .on('keydown.puiautocomplete', function(e) { | |
| 499 | + var keyCode = $.ui.keyCode; | |
| 500 | + | |
| 501 | + if(e.which == keyCode.ENTER || e.which == keyCode.NUMPAD_ENTER) { | |
| 502 | + $this.search(''); | |
| 503 | + $this.input.focus(); | |
| 504 | + | |
| 505 | + e.preventDefault(); | |
| 506 | + } | |
| 507 | + }); | |
| 508 | + } | |
| 509 | + | |
| 510 | + if(this.options.multiple) { | |
| 511 | + this.multiContainer.on('hover.puiautocomplete', function() { | |
| 512 | + $(this).toggleClass('ui-state-hover'); | |
| 513 | + }) | |
| 514 | + .on('click.puiautocomplete', function() { | |
| 515 | + $this.element.trigger('focus'); | |
| 516 | + }); | |
| 517 | + | |
| 518 | + this.element.on('focus.ui-autocomplete', function() { | |
| 519 | + $this.multiContainer.addClass('ui-state-focus'); | |
| 520 | + }) | |
| 521 | + .on('blur.ui-autocomplete', function(e) { | |
| 522 | + $this.multiContainer.removeClass('ui-state-focus'); | |
| 523 | + }); | |
| 524 | + } | |
| 525 | + | |
| 526 | + if(this.options.forceSelection) { | |
| 527 | + this.currentItems = [this.element.val()]; | |
| 528 | + | |
| 529 | + this.element.on('blur.puiautocomplete', function() { | |
| 530 | + var value = $(this).val(), | |
| 531 | + valid = false; | |
| 532 | + | |
| 533 | + for(var i = 0; i < $this.currentItems.length; i++) { | |
| 534 | + if($this.currentItems[i] === value) { | |
| 535 | + valid = true; | |
| 536 | + break; | |
| 537 | + } | |
| 538 | + } | |
| 539 | + | |
| 540 | + if(!valid) { | |
| 541 | + $this.element.val(''); | |
| 542 | + } | |
| 543 | + }); | |
| 544 | + } | |
| 545 | + | |
| 546 | + $(document.body).bind('mousedown.puiautocomplete', function (e) { | |
| 547 | + if($this.panel.is(":hidden")) { | |
| 548 | + return; | |
| 549 | + } | |
| 550 | + | |
| 551 | + if(e.target === $this.element.get(0)) { | |
| 552 | + return; | |
| 553 | + } | |
| 554 | + | |
| 555 | + var offset = $this.panel.offset(); | |
| 556 | + if (e.pageX < offset.left || | |
| 557 | + e.pageX > offset.left + $this.panel.width() || | |
| 558 | + e.pageY < offset.top || | |
| 559 | + e.pageY > offset.top + $this.panel.height()) { | |
| 560 | + $this.hide(); | |
| 561 | + } | |
| 562 | + }); | |
| 563 | + | |
| 564 | + $(window).bind('resize.' + this.element.id, function() { | |
| 565 | + if($this.panel.is(':visible')) { | |
| 566 | + $this._alignPanel(); | |
| 567 | + } | |
| 568 | + }); | |
| 569 | + }, | |
| 570 | + | |
| 571 | + _bindKeyEvents: function() { | |
| 572 | + var $this = this; | |
| 573 | + | |
| 574 | + this.element.on('keyup.puiautocomplete', function(e) { | |
| 575 | + var keyCode = $.ui.keyCode, | |
| 576 | + key = e.which, | |
| 577 | + shouldSearch = true; | |
| 578 | + | |
| 579 | + if(key == keyCode.UP || | |
| 580 | + key == keyCode.LEFT || | |
| 581 | + key == keyCode.DOWN || | |
| 582 | + key == keyCode.RIGHT || | |
| 583 | + key == keyCode.TAB || | |
| 584 | + key == keyCode.SHIFT || | |
| 585 | + key == keyCode.ENTER || | |
| 586 | + key == keyCode.NUMPAD_ENTER) { | |
| 587 | + shouldSearch = false; | |
| 588 | + } | |
| 589 | + | |
| 590 | + if(shouldSearch) { | |
| 591 | + var value = $this.element.val(); | |
| 592 | + | |
| 593 | + if(!value.length) { | |
| 594 | + $this.hide(); | |
| 595 | + } | |
| 596 | + | |
| 597 | + if(value.length >= $this.options.minQueryLength) { | |
| 598 | + if($this.timeout) { | |
| 599 | + window.clearTimeout($this.timeout); | |
| 600 | + } | |
| 601 | + | |
| 602 | + $this.timeout = window.setTimeout(function() { | |
| 603 | + $this.search(value); | |
| 604 | + }, | |
| 605 | + $this.options.delay); | |
| 606 | + } | |
| 607 | + } | |
| 608 | + | |
| 609 | + }).on('keydown.puiautocomplete', function(e) { | |
| 610 | + if($this.panel.is(':visible')) { | |
| 611 | + var keyCode = $.ui.keyCode, | |
| 612 | + highlightedItem = $this.items.filter('.ui-state-highlight'); | |
| 613 | + | |
| 614 | + switch(e.which) { | |
| 615 | + case keyCode.UP: | |
| 616 | + case keyCode.LEFT: | |
| 617 | + var prev = highlightedItem.prev(); | |
| 618 | + | |
| 619 | + if(prev.length == 1) { | |
| 620 | + highlightedItem.removeClass('ui-state-highlight'); | |
| 621 | + prev.addClass('ui-state-highlight'); | |
| 622 | + | |
| 623 | + if($this.options.scrollHeight) { | |
| 624 | + PUI.scrollInView($this.panel, prev); | |
| 625 | + } | |
| 626 | + } | |
| 627 | + | |
| 628 | + e.preventDefault(); | |
| 629 | + break; | |
| 630 | + | |
| 631 | + case keyCode.DOWN: | |
| 632 | + case keyCode.RIGHT: | |
| 633 | + var next = highlightedItem.next(); | |
| 634 | + | |
| 635 | + if(next.length == 1) { | |
| 636 | + highlightedItem.removeClass('ui-state-highlight'); | |
| 637 | + next.addClass('ui-state-highlight'); | |
| 638 | + | |
| 639 | + if($this.options.scrollHeight) { | |
| 640 | + PUI.scrollInView($this.panel, next); | |
| 641 | + } | |
| 642 | + } | |
| 643 | + | |
| 644 | + e.preventDefault(); | |
| 645 | + break; | |
| 646 | + | |
| 647 | + case keyCode.ENTER: | |
| 648 | + case keyCode.NUMPAD_ENTER: | |
| 649 | + highlightedItem.trigger('click'); | |
| 650 | + | |
| 651 | + e.preventDefault(); | |
| 652 | + break; | |
| 653 | + | |
| 654 | + case keyCode.ALT: | |
| 655 | + case 224: | |
| 656 | + break; | |
| 657 | + | |
| 658 | + case keyCode.TAB: | |
| 659 | + highlightedItem.trigger('click'); | |
| 660 | + $this.hide(); | |
| 661 | + break; | |
| 662 | + } | |
| 663 | + } | |
| 664 | + | |
| 665 | + }); | |
| 666 | + }, | |
| 667 | + | |
| 668 | + _bindDynamicEvents: function() { | |
| 669 | + var $this = this; | |
| 670 | + | |
| 671 | + this.items.on('mouseover.puiautocomplete', function() { | |
| 672 | + var item = $(this); | |
| 673 | + | |
| 674 | + if(!item.hasClass('ui-state-highlight')) { | |
| 675 | + $this.items.filter('.ui-state-highlight').removeClass('ui-state-highlight'); | |
| 676 | + item.addClass('ui-state-highlight'); | |
| 677 | + } | |
| 678 | + }) | |
| 679 | + .on('click.puiautocomplete', function(event) { | |
| 680 | + var item = $(this); | |
| 681 | + | |
| 682 | + if($this.options.multiple) { | |
| 683 | + var tokenMarkup = '<li class="ui-autocomplete-token ui-state-active ui-corner-all ui-helper-hidden">'; | |
| 684 | + tokenMarkup += '<span class="ui-autocomplete-token-icon fa fa-fw fa-close" />'; | |
| 685 | + tokenMarkup += '<span class="ui-autocomplete-token-label">' + item.data('label') + '</span></li>'; | |
| 686 | + | |
| 687 | + $(tokenMarkup).data(item.data()) | |
| 688 | + .insertBefore($this.inputContainer).fadeIn() | |
| 689 | + .children('.ui-autocomplete-token-icon').on('click.ui-autocomplete', function(e) { | |
| 690 | + var token = $(this).parent(); | |
| 691 | + $this._removeItem(token); | |
| 692 | + $this._trigger('unselect', e, token); | |
| 693 | + }); | |
| 694 | + | |
| 695 | + $this.element.val('').trigger('focus'); | |
| 696 | + } | |
| 697 | + else { | |
| 698 | + $this.element.val(item.data('label')).focus(); | |
| 699 | + } | |
| 700 | + | |
| 701 | + $this._trigger('select', event, item); | |
| 702 | + $this.hide(); | |
| 703 | + }); | |
| 704 | + }, | |
| 705 | + | |
| 706 | + search: function(q) { | |
| 707 | + this.query = this.options.caseSensitive ? q : q.toLowerCase(); | |
| 708 | + | |
| 709 | + var request = { | |
| 710 | + query: this.query | |
| 711 | + }; | |
| 712 | + | |
| 713 | + if(this.options.completeSource) { | |
| 714 | + if($.isArray(this.options.completeSource)) { | |
| 715 | + var sourceArr = this.options.completeSource, | |
| 716 | + data = [], | |
| 717 | + emptyQuery = ($.trim(q) === ''); | |
| 718 | + | |
| 719 | + for(var i = 0 ; i < sourceArr.length; i++) { | |
| 720 | + var item = sourceArr[i], | |
| 721 | + itemLabel = item.label||item; | |
| 722 | + | |
| 723 | + if(!this.options.caseSensitive) { | |
| 724 | + itemLabel = itemLabel.toLowerCase(); | |
| 725 | + } | |
| 726 | + | |
| 727 | + if(emptyQuery||itemLabel.indexOf(this.query) === 0) { | |
| 728 | + data.push({label:sourceArr[i], value: item}); | |
| 729 | + } | |
| 730 | + } | |
| 731 | + | |
| 732 | + this._handleData(data); | |
| 733 | + } | |
| 734 | + else { | |
| 735 | + this.options.completeSource.call(this, request, this._handleData); | |
| 736 | + } | |
| 737 | + } | |
| 738 | + }, | |
| 739 | + | |
| 740 | + _handleData: function(data) { | |
| 741 | + var $this = this; | |
| 742 | + this.panel.html(''); | |
| 743 | + this.listContainer = $('<ul class="ui-autocomplete-items ui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset"></ul>').appendTo(this.panel); | |
| 744 | + | |
| 745 | + for(var i = 0; i < data.length; i++) { | |
| 746 | + var item = $('<li class="ui-autocomplete-item ui-autocomplete-list-item ui-corner-all"></li>'); | |
| 747 | + item.data(data[i]); | |
| 748 | + | |
| 749 | + if(this.options.content) | |
| 750 | + item.html(this.options.content.call(this, data[i])); | |
| 751 | + else | |
| 752 | + item.text(data[i].label); | |
| 753 | + | |
| 754 | + this.listContainer.append(item); | |
| 755 | + } | |
| 756 | + | |
| 757 | + this.items = this.listContainer.children('.ui-autocomplete-item'); | |
| 758 | + | |
| 759 | + this._bindDynamicEvents(); | |
| 760 | + | |
| 761 | + if(this.items.length > 0) { | |
| 762 | + var firstItem = $this.items.eq(0), | |
| 763 | + hidden = this.panel.is(':hidden'); | |
| 764 | + firstItem.addClass('ui-state-highlight'); | |
| 765 | + | |
| 766 | + if($this.query.length > 0 && !$this.options.content) { | |
| 767 | + $this.items.each(function() { | |
| 768 | + var item = $(this), | |
| 769 | + text = item.html(), | |
| 770 | + re = new RegExp(PUI.escapeRegExp($this.query), 'gi'), | |
| 771 | + highlighedText = text.replace(re, '<span class="ui-autocomplete-query">$&</span>'); | |
| 772 | + | |
| 773 | + item.html(highlighedText); | |
| 774 | + }); | |
| 775 | + } | |
| 776 | + | |
| 777 | + if(this.options.forceSelection) { | |
| 778 | + this.currentItems = []; | |
| 779 | + $.each(data, function(i, item) { | |
| 780 | + $this.currentItems.push(item.label); | |
| 781 | + }); | |
| 782 | + } | |
| 783 | + | |
| 784 | + //adjust height | |
| 785 | + if($this.options.scrollHeight) { | |
| 786 | + var heightConstraint = hidden ? $this.panel.height() : $this.panel.children().height(); | |
| 787 | + | |
| 788 | + if(heightConstraint > $this.options.scrollHeight) | |
| 789 | + $this.panel.height($this.options.scrollHeight); | |
| 790 | + else | |
| 791 | + $this.panel.css('height', 'auto'); | |
| 792 | + | |
| 793 | + } | |
| 794 | + | |
| 795 | + if(hidden) { | |
| 796 | + $this.show(); | |
| 797 | + } | |
| 798 | + else { | |
| 799 | + $this._alignPanel(); | |
| 800 | + } | |
| 801 | + } | |
| 802 | + else { | |
| 803 | + this.panel.hide(); | |
| 804 | + } | |
| 805 | + }, | |
| 806 | + | |
| 807 | + show: function() { | |
| 808 | + this._alignPanel(); | |
| 809 | + | |
| 810 | + if(this.options.effect) | |
| 811 | + this.panel.show(this.options.effect, {}, this.options.effectSpeed); | |
| 812 | + else | |
| 813 | + this.panel.show(); | |
| 814 | + }, | |
| 815 | + | |
| 816 | + hide: function() { | |
| 817 | + this.panel.hide(); | |
| 818 | + this.panel.css('height', 'auto'); | |
| 819 | + }, | |
| 820 | + | |
| 821 | + _removeItem: function(item) { | |
| 822 | + item.fadeOut('fast', function() { | |
| 823 | + var token = $(this); | |
| 824 | + | |
| 825 | + token.remove(); | |
| 826 | + }); | |
| 827 | + }, | |
| 828 | + | |
| 829 | + _alignPanel: function() { | |
| 830 | + var panelWidth = null; | |
| 831 | + | |
| 832 | + if(this.options.multiple) { | |
| 833 | + panelWidth = this.multiContainer.innerWidth() - (this.element.position().left - this.multiContainer.position().left); | |
| 834 | + } | |
| 835 | + else { | |
| 836 | + if(this.panel.is(':visible')) { | |
| 837 | + panelWidth = this.panel.children('.ui-autocomplete-items').outerWidth(); | |
| 838 | + } | |
| 839 | + else { | |
| 840 | + this.panel.css({'visibility':'hidden','display':'block'}); | |
| 841 | + panelWidth = this.panel.children('.ui-autocomplete-items').outerWidth(); | |
| 842 | + this.panel.css({'visibility':'visible','display':'none'}); | |
| 843 | + } | |
| 844 | + | |
| 845 | + var inputWidth = this.element.outerWidth(); | |
| 846 | + if(panelWidth < inputWidth) { | |
| 847 | + panelWidth = inputWidth; | |
| 848 | + } | |
| 849 | + } | |
| 850 | + | |
| 851 | + this.panel.css({ | |
| 852 | + 'left':'', | |
| 853 | + 'top':'', | |
| 854 | + 'width': panelWidth, | |
| 855 | + 'z-index': ++PUI.zindex | |
| 856 | + }) | |
| 857 | + .position({ | |
| 858 | + my: 'left top', | |
| 859 | + at: 'left bottom', | |
| 860 | + of: this.element | |
| 861 | + }); | |
| 862 | + } | |
| 863 | + }); | |
| 864 | + | |
| 865 | +})(); | |
| 866 | +/** | |
| 867 | + * PrimeFaces Button Widget | |
| 868 | + */ | |
| 869 | +(function() { | |
| 870 | + | |
| 871 | + $.widget("primeui.puibutton", { | |
| 872 | + | |
| 873 | + options: { | |
| 874 | + value: null, | |
| 875 | + icon: null, | |
| 876 | + iconPos: 'left', | |
| 877 | + click: null | |
| 878 | + }, | |
| 879 | + | |
| 880 | + _create: function() { | |
| 881 | + var element = this.element; | |
| 882 | + this.elementText = this.element.text(); | |
| 883 | + | |
| 884 | + var value = this.options.value||(this.elementText === '' ? 'ui-button' : this.elementText), | |
| 885 | + disabled = element.prop('disabled'), | |
| 886 | + styleClass = null; | |
| 887 | + | |
| 888 | + if(this.options.icon) { | |
| 889 | + styleClass = (value === 'ui-button') ? 'ui-button-icon-only' : 'ui-button-text-icon-' + this.options.iconPos; | |
| 890 | + } | |
| 891 | + else { | |
| 892 | + styleClass = 'ui-button-text-only'; | |
| 893 | + } | |
| 894 | + | |
| 895 | + if(disabled) { | |
| 896 | + styleClass += ' ui-state-disabled'; | |
| 897 | + } | |
| 898 | + | |
| 899 | + this.element.addClass('ui-button ui-widget ui-state-default ui-corner-all ' + styleClass).text(''); | |
| 900 | + | |
| 901 | + if(this.options.icon) { | |
| 902 | + this.element.append('<span class="ui-button-icon-' + this.options.iconPos + ' ui-c fa fa-fw ' + this.options.icon + '" />'); | |
| 903 | + } | |
| 904 | + | |
| 905 | + this.element.append('<span class="ui-button-text ui-c">' + value + '</span>'); | |
| 906 | + | |
| 907 | + if(!disabled) { | |
| 908 | + this._bindEvents(); | |
| 909 | + } | |
| 910 | + }, | |
| 911 | + | |
| 912 | + _destroy: function() { | |
| 913 | + this.element.removeClass('ui-button ui-widget ui-state-default ui-state-hover ui-state-active ui-state-disabled ui-state-focus ui-corner-all ' + | |
| 914 | + 'ui-button-text-only ui-button-icon-only ui-button-text-icon-right ui-button-text-icon-left'); | |
| 915 | + this._unbindEvents(); | |
| 916 | + this.element.children('.fa').remove(); | |
| 917 | + this.element.children('.ui-button-text').remove(); | |
| 918 | + this.element.text(this.elementText); | |
| 919 | + }, | |
| 920 | + | |
| 921 | + _bindEvents: function() { | |
| 922 | + var element = this.element, | |
| 923 | + $this = this; | |
| 924 | + | |
| 925 | + element.on('mouseover.puibutton', function(){ | |
| 926 | + if(!element.prop('disabled')) { | |
| 927 | + element.addClass('ui-state-hover'); | |
| 928 | + } | |
| 929 | + }).on('mouseout.puibutton', function() { | |
| 930 | + $(this).removeClass('ui-state-active ui-state-hover'); | |
| 931 | + }).on('mousedown.puibutton', function() { | |
| 932 | + if(!element.hasClass('ui-state-disabled')) { | |
| 933 | + element.addClass('ui-state-active').removeClass('ui-state-hover'); | |
| 934 | + } | |
| 935 | + }).on('mouseup.puibutton', function(e) { | |
| 936 | + element.removeClass('ui-state-active').addClass('ui-state-hover'); | |
| 937 | + | |
| 938 | + $this._trigger('click', e); | |
| 939 | + }).on('focus.puibutton', function() { | |
| 940 | + element.addClass('ui-state-focus'); | |
| 941 | + }).on('blur.puibutton', function() { | |
| 942 | + element.removeClass('ui-state-focus'); | |
| 943 | + }).on('keydown.puibutton',function(e) { | |
| 944 | + if(e.keyCode == $.ui.keyCode.SPACE || e.keyCode == $.ui.keyCode.ENTER || e.keyCode == $.ui.keyCode.NUMPAD_ENTER) { | |
| 945 | + element.addClass('ui-state-active'); | |
| 946 | + } | |
| 947 | + }).on('keyup.puibutton', function() { | |
| 948 | + element.removeClass('ui-state-active'); | |
| 949 | + }); | |
| 950 | + | |
| 951 | + return this; | |
| 952 | + }, | |
| 953 | + | |
| 954 | + _unbindEvents: function() { | |
| 955 | + this.element.off('mouseover.puibutton mouseout.puibutton mousedown.puibutton mouseup.puibutton focus.puibutton blur.puibutton keydown.puibutton keyup.puibutton'); | |
| 956 | + }, | |
| 957 | + | |
| 958 | + disable: function() { | |
| 959 | + this._unbindEvents(); | |
| 960 | + this.element.addClass('ui-state-disabled').prop('disabled',true); | |
| 961 | + }, | |
| 962 | + | |
| 963 | + enable: function() { | |
| 964 | + if(this.element.prop('disabled')) { | |
| 965 | + this._bindEvents(); | |
| 966 | + this.element.prop('disabled', false).removeClass('ui-state-disabled'); | |
| 967 | + } | |
| 968 | + }, | |
| 969 | + | |
| 970 | + _setOption: function(key, value) { | |
| 971 | + if(key === 'disabled') { | |
| 972 | + if(value) | |
| 973 | + this.disable(); | |
| 974 | + else | |
| 975 | + this.enable(); | |
| 976 | + } | |
| 977 | + else { | |
| 978 | + $.Widget.prototype._setOption.apply(this, arguments); | |
| 979 | + } | |
| 980 | + } | |
| 981 | + | |
| 982 | + }); | |
| 983 | +})(); | |
| 984 | +/** | |
| 985 | + * PrimeUI Carousel widget | |
| 986 | + */ | |
| 987 | +(function() { | |
| 988 | + | |
| 989 | + $.widget("primeui.puicarousel", { | |
| 990 | + | |
| 991 | + options: { | |
| 992 | + datasource: null, | |
| 993 | + numVisible: 3, | |
| 994 | + firstVisible: 0, | |
| 995 | + headerText: null, | |
| 996 | + effectDuration: 500, | |
| 997 | + circular :false, | |
| 998 | + breakpoint: 560, | |
| 999 | + itemContent: null, | |
| 1000 | + responsive: true, | |
| 1001 | + autoplayInterval: 0, | |
| 1002 | + easing: 'easeInOutCirc', | |
| 1003 | + pageLinks: 3, | |
| 1004 | + style: null, | |
| 1005 | + styleClass: null, | |
| 1006 | + template: null, | |
| 1007 | + enhanced: false | |
| 1008 | + }, | |
| 1009 | + | |
| 1010 | + _create: function() { | |
| 1011 | + this.id = this.element.attr('id'); | |
| 1012 | + if(!this.id) { | |
| 1013 | + this.id = this.element.uniqueId().attr('id'); | |
| 1014 | + } | |
| 1015 | + | |
| 1016 | + if(!this.options.enhanced) { | |
| 1017 | + this.element.wrap('<div class="ui-carousel ui-widget ui-widget-content ui-corner-all"><div class="ui-carousel-viewport"></div></div>'); | |
| 1018 | + } | |
| 1019 | + | |
| 1020 | + this.container = this.element.parent().parent(); | |
| 1021 | + this.element.addClass('ui-carousel-items'); | |
| 1022 | + this.viewport = this.element.parent(); | |
| 1023 | + this.container.prepend('<div class="ui-carousel-header ui-widget-header"><div class="ui-carousel-header-title"></div></div>'); | |
| 1024 | + this.header = this.container.children('.ui-carousel-header'); | |
| 1025 | + this.header.append('<span class="ui-carousel-button ui-carousel-next-button fa fa-arrow-circle-right"></span>' + | |
| 1026 | + '<span class="ui-carousel-button ui-carousel-prev-button fa fa-arrow-circle-left"></span>'); | |
| 1027 | + | |
| 1028 | + if(this.options.headerText) { | |
| 1029 | + this.header.children('.ui-carousel-header-title').html(this.options.headerText); | |
| 1030 | + } | |
| 1031 | + | |
| 1032 | + if(this.options.styleClass) { | |
| 1033 | + this.container.addClass(this.options.styleClass); | |
| 1034 | + } | |
| 1035 | + | |
| 1036 | + if(this.options.style) { | |
| 1037 | + this.container.attr('style', this.options.style); | |
| 1038 | + } | |
| 1039 | + | |
| 1040 | + if(this.options.datasource) | |
| 1041 | + this._loadData(); | |
| 1042 | + else | |
| 1043 | + this._render(); | |
| 1044 | + }, | |
| 1045 | + | |
| 1046 | + _destroy: function() { | |
| 1047 | + this._unbindEvents(); | |
| 1048 | + this.header.remove(); | |
| 1049 | + this.items.removeClass('ui-carousel-item ui-widget-content ui-corner-all').css('width','auto'); | |
| 1050 | + this.element.removeClass('ui-carousel-items').css('left','auto'); | |
| 1051 | + | |
| 1052 | + if(!this.options.enhanced) { | |
| 1053 | + this.element.unwrap().unwrap(); | |
| 1054 | + } | |
| 1055 | + | |
| 1056 | + if(this.options.datasource) { | |
| 1057 | + this.items.remove(); | |
| 1058 | + } | |
| 1059 | + }, | |
| 1060 | + | |
| 1061 | + _loadData: function() { | |
| 1062 | + if($.isArray(this.options.datasource)) | |
| 1063 | + this._render(this.options.datasource); | |
| 1064 | + else if($.type(this.options.datasource) === 'function') | |
| 1065 | + this.options.datasource.call(this, this._render); | |
| 1066 | + }, | |
| 1067 | + | |
| 1068 | + _updateDatasource: function(value) { | |
| 1069 | + this.options.datasource = value; | |
| 1070 | + this.element.children().remove(); | |
| 1071 | + this.header.children('.ui-carousel-page-links').remove(); | |
| 1072 | + this.header.children('select').remove(); | |
| 1073 | + this._loadData(); | |
| 1074 | + }, | |
| 1075 | + | |
| 1076 | + _render: function(data) { | |
| 1077 | + this.data = data; | |
| 1078 | + | |
| 1079 | + if(this.data) { | |
| 1080 | + for(var i = 0; i < data.length; i++) { | |
| 1081 | + var itemContent = this._createItemContent(data[i]); | |
| 1082 | + if($.type(itemContent) === 'string') | |
| 1083 | + this.element.append('<li>' + itemContent + '</li>'); | |
| 1084 | + else | |
| 1085 | + this.element.append($('<li></li>').wrapInner(itemContent)); | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | + | |
| 1089 | + this.items = this.element.children('li'); | |
| 1090 | + this.items.addClass('ui-carousel-item ui-widget-content ui-corner-all'); | |
| 1091 | + this.itemsCount = this.items.length; | |
| 1092 | + this.columns = this.options.numVisible; | |
| 1093 | + this.first = this.options.firstVisible; | |
| 1094 | + this.page = parseInt(this.first/this.columns); | |
| 1095 | + this.totalPages = Math.ceil(this.itemsCount/this.options.numVisible); | |
| 1096 | + | |
| 1097 | + this._renderPageLinks(); | |
| 1098 | + | |
| 1099 | + this.prevNav = this.header.children('.ui-carousel-prev-button'); | |
| 1100 | + this.nextNav = this.header.children('.ui-carousel-next-button'); | |
| 1101 | + this.pageLinks = this.header.find('> .ui-carousel-page-links > .ui-carousel-page-link'); | |
| 1102 | + this.dropdown = this.header.children('.ui-carousel-dropdown'); | |
| 1103 | + this.mobileDropdown = this.header.children('.ui-carousel-mobiledropdown'); | |
| 1104 | + | |
| 1105 | + this._bindEvents(); | |
| 1106 | + | |
| 1107 | + if(this.options.responsive) { | |
| 1108 | + this.refreshDimensions(); | |
| 1109 | + } | |
| 1110 | + else { | |
| 1111 | + this.calculateItemWidths(); | |
| 1112 | + this.container.width(this.container.width()); | |
| 1113 | + this.updateNavigators(); | |
| 1114 | + } | |
| 1115 | + }, | |
| 1116 | + | |
| 1117 | + _renderPageLinks: function() { | |
| 1118 | + if(this.totalPages <= this.options.pageLinks) { | |
| 1119 | + this.pageLinksContainer = $('<div class="ui-carousel-page-links"></div>'); | |
| 1120 | + for(var i = 0; i < this.totalPages; i++) { | |
| 1121 | + this.pageLinksContainer.append('<a href="#" class="ui-carousel-page-link fa fa-circle-o"></a>'); | |
| 1122 | + } | |
| 1123 | + this.header.append(this.pageLinksContainer); | |
| 1124 | + } | |
| 1125 | + else { | |
| 1126 | + this.dropdown = $('<select class="ui-carousel-dropdown ui-widget ui-state-default ui-corner-left"></select>'); | |
| 1127 | + for(var i = 0; i < this.totalPages; i++) { | |
| 1128 | + var pageNumber = (i+1); | |
| 1129 | + this.dropdown.append('<option value="' + pageNumber + '">' + pageNumber + '</option>'); | |
| 1130 | + } | |
| 1131 | + this.header.append(this.dropdown); | |
| 1132 | + } | |
| 1133 | + | |
| 1134 | + if(this.options.responsive) { | |
| 1135 | + this.mobileDropdown = $('<select class="ui-carousel-mobiledropdown ui-widget ui-state-default ui-corner-left"></select>'); | |
| 1136 | + for(var i = 0; i < this.itemsCount; i++) { | |
| 1137 | + var pageNumber = (i+1); | |
| 1138 | + this.mobileDropdown.append('<option value="' + pageNumber + '">' + pageNumber + '</option>'); | |
| 1139 | + } | |
| 1140 | + this.header.append(this.mobileDropdown); | |
| 1141 | + } | |
| 1142 | + }, | |
| 1143 | + | |
| 1144 | + calculateItemWidths: function() { | |
| 1145 | + var firstItem = this.items.eq(0); | |
| 1146 | + if(firstItem.length) { | |
| 1147 | + var itemFrameWidth = firstItem.outerWidth(true) - firstItem.width(); //sum of margin, border and padding | |
| 1148 | + this.items.width((this.viewport.innerWidth() - itemFrameWidth * this.columns) / this.columns); | |
| 1149 | + } | |
| 1150 | + }, | |
| 1151 | + | |
| 1152 | + refreshDimensions: function() { | |
| 1153 | + var win = $(window); | |
| 1154 | + if(win.width() <= this.options.breakpoint) { | |
| 1155 | + this.columns = 1; | |
| 1156 | + this.calculateItemWidths(this.columns); | |
| 1157 | + this.totalPages = this.itemsCount; | |
| 1158 | + this.mobileDropdown.show(); | |
| 1159 | + this.pageLinks.hide(); | |
| 1160 | + } | |
| 1161 | + else { | |
| 1162 | + this.columns = this.options.numVisible; | |
| 1163 | + this.calculateItemWidths(); | |
| 1164 | + this.totalPages = Math.ceil(this.itemsCount / this.options.numVisible); | |
| 1165 | + this.mobileDropdown.hide(); | |
| 1166 | + this.pageLinks.show(); | |
| 1167 | + } | |
| 1168 | + | |
| 1169 | + this.page = parseInt(this.first / this.columns); | |
| 1170 | + this.updateNavigators(); | |
| 1171 | + this.element.css('left', (-1 * (this.viewport.innerWidth() * this.page))); | |
| 1172 | + }, | |
| 1173 | + | |
| 1174 | + _bindEvents: function() { | |
| 1175 | + var $this = this; | |
| 1176 | + | |
| 1177 | + if(this.eventsBound) { | |
| 1178 | + return; | |
| 1179 | + } | |
| 1180 | + | |
| 1181 | + this.prevNav.on('click.puicarousel', function() { | |
| 1182 | + if($this.page !== 0) { | |
| 1183 | + $this.setPage($this.page - 1); | |
| 1184 | + } | |
| 1185 | + else if($this.options.circular) { | |
| 1186 | + $this.setPage($this.totalPages - 1); | |
| 1187 | + } | |
| 1188 | + }); | |
| 1189 | + | |
| 1190 | + this.nextNav.on('click.puicarousel', function() { | |
| 1191 | + var lastPage = ($this.page === ($this.totalPages - 1)); | |
| 1192 | + | |
| 1193 | + if(!lastPage) { | |
| 1194 | + $this.setPage($this.page + 1); | |
| 1195 | + } | |
| 1196 | + else if($this.options.circular) { | |
| 1197 | + $this.setPage(0); | |
| 1198 | + } | |
| 1199 | + }); | |
| 1200 | + | |
| 1201 | + if($.swipe) { | |
| 1202 | + this.element.swipe({ | |
| 1203 | + swipe:function(event, direction) { | |
| 1204 | + if(direction === 'left') { | |
| 1205 | + if($this.page === ($this.totalPages - 1)) { | |
| 1206 | + if($this.options.circular) | |
| 1207 | + $this.setPage(0); | |
| 1208 | + } | |
| 1209 | + else { | |
| 1210 | + $this.setPage($this.page + 1); | |
| 1211 | + } | |
| 1212 | + } | |
| 1213 | + else if(direction === 'right') { | |
| 1214 | + if($this.page === 0) { | |
| 1215 | + if($this.options.circular) | |
| 1216 | + $this.setPage($this.totalPages - 1); | |
| 1217 | + } | |
| 1218 | + else { | |
| 1219 | + $this.setPage($this.page - 1); | |
| 1220 | + } | |
| 1221 | + } | |
| 1222 | + } | |
| 1223 | + }); | |
| 1224 | + } | |
| 1225 | + | |
| 1226 | + if(this.pageLinks.length) { | |
| 1227 | + this.pageLinks.on('click.puicarousel', function(e) { | |
| 1228 | + $this.setPage($(this).index()); | |
| 1229 | + e.preventDefault(); | |
| 1230 | + }); | |
| 1231 | + } | |
| 1232 | + | |
| 1233 | + this.header.children('select').on('change.puicarousel', function() { | |
| 1234 | + $this.setPage(parseInt($(this).val()) - 1); | |
| 1235 | + }); | |
| 1236 | + | |
| 1237 | + if(this.options.autoplayInterval) { | |
| 1238 | + this.options.circular = true; | |
| 1239 | + this.startAutoplay(); | |
| 1240 | + } | |
| 1241 | + | |
| 1242 | + if(this.options.responsive) { | |
| 1243 | + var resizeNS = 'resize.' + this.id; | |
| 1244 | + $(window).off(resizeNS).on(resizeNS, function() { | |
| 1245 | + $this.refreshDimensions(); | |
| 1246 | + }); | |
| 1247 | + } | |
| 1248 | + | |
| 1249 | + this.eventsBound = true; | |
| 1250 | + }, | |
| 1251 | + | |
| 1252 | + _unbindEvents: function() { | |
| 1253 | + this.prevNav.off('click.puicarousel'); | |
| 1254 | + this.nextNav.off('click.puicarousel'); | |
| 1255 | + if(this.pageLinks.length) { | |
| 1256 | + this.pageLinks.off('click.puicarousel'); | |
| 1257 | + } | |
| 1258 | + this.header.children('select').off('change.puicarousel'); | |
| 1259 | + | |
| 1260 | + if(this.options.autoplayInterval) { | |
| 1261 | + this.stopAutoplay(); | |
| 1262 | + } | |
| 1263 | + | |
| 1264 | + if(this.options.responsive) { | |
| 1265 | + $(window).off('resize.' + this.id) | |
| 1266 | + } | |
| 1267 | + }, | |
| 1268 | + | |
| 1269 | + updateNavigators: function() { | |
| 1270 | + if(!this.options.circular) { | |
| 1271 | + if(this.page === 0) { | |
| 1272 | + this.prevNav.addClass('ui-state-disabled'); | |
| 1273 | + this.nextNav.removeClass('ui-state-disabled'); | |
| 1274 | + } | |
| 1275 | + else if(this.page === (this.totalPages - 1)) { | |
| 1276 | + this.prevNav.removeClass('ui-state-disabled'); | |
| 1277 | + this.nextNav.addClass('ui-state-disabled'); | |
| 1278 | + } | |
| 1279 | + else { | |
| 1280 | + this.prevNav.removeClass('ui-state-disabled'); | |
| 1281 | + this.nextNav.removeClass('ui-state-disabled'); | |
| 1282 | + } | |
| 1283 | + } | |
| 1284 | + | |
| 1285 | + if(this.pageLinks.length) { | |
| 1286 | + this.pageLinks.filter('.fa-dot-circle-o').removeClass('fa-dot-circle-o'); | |
| 1287 | + this.pageLinks.eq(this.page).addClass('fa-dot-circle-o'); | |
| 1288 | + } | |
| 1289 | + | |
| 1290 | + if(this.dropdown.length) { | |
| 1291 | + this.dropdown.val(this.page + 1); | |
| 1292 | + } | |
| 1293 | + | |
| 1294 | + if(this.mobileDropdown.length) { | |
| 1295 | + this.mobileDropdown.val(this.page + 1); | |
| 1296 | + } | |
| 1297 | + }, | |
| 1298 | + | |
| 1299 | + setPage: function(p) { | |
| 1300 | + if(p !== this.page && !this.element.is(':animated')) { | |
| 1301 | + var $this = this; | |
| 1302 | + | |
| 1303 | + this.element.animate({ | |
| 1304 | + left: -1 * (this.viewport.innerWidth() * p) | |
| 1305 | + ,easing: this.options.easing | |
| 1306 | + }, | |
| 1307 | + { | |
| 1308 | + duration: this.options.effectDuration, | |
| 1309 | + easing: this.options.easing, | |
| 1310 | + complete: function() { | |
| 1311 | + $this.page = p; | |
| 1312 | + $this.first = $this.page * $this.columns; | |
| 1313 | + $this.updateNavigators(); | |
| 1314 | + $this._trigger('pageChange', null, {'page':p}); | |
| 1315 | + } | |
| 1316 | + }); | |
| 1317 | + } | |
| 1318 | + }, | |
| 1319 | + | |
| 1320 | + startAutoplay: function() { | |
| 1321 | + var $this = this; | |
| 1322 | + | |
| 1323 | + this.interval = setInterval(function() { | |
| 1324 | + if($this.page === ($this.totalPages - 1)) | |
| 1325 | + $this.setPage(0); | |
| 1326 | + else | |
| 1327 | + $this.setPage($this.page + 1); | |
| 1328 | + }, this.options.autoplayInterval); | |
| 1329 | + }, | |
| 1330 | + | |
| 1331 | + stopAutoplay: function() { | |
| 1332 | + clearInterval(this.interval); | |
| 1333 | + }, | |
| 1334 | + | |
| 1335 | + _setOption: function(key, value) { | |
| 1336 | + if(key === 'datasource') | |
| 1337 | + this._updateDatasource(value); | |
| 1338 | + else | |
| 1339 | + $.Widget.prototype._setOption.apply(this, arguments); | |
| 1340 | + }, | |
| 1341 | + | |
| 1342 | + _createItemContent: function(obj) { | |
| 1343 | + if(this.options.template) { | |
| 1344 | + var template = this.options.template.html(); | |
| 1345 | + Mustache.parse(template); | |
| 1346 | + return Mustache.render(template, obj); | |
| 1347 | + } | |
| 1348 | + else { | |
| 1349 | + return this.options.itemContent.call(this, obj); | |
| 1350 | + } | |
| 1351 | + } | |
| 1352 | + | |
| 1353 | + }); | |
| 1354 | + | |
| 1355 | +})(); | |
| 1356 | +/** | |
| 1357 | + * PrimeUI checkbox widget | |
| 1358 | + */ | |
| 1359 | +(function() { | |
| 1360 | + | |
| 1361 | + $.widget("primeui.puicheckbox", { | |
| 1362 | + | |
| 1363 | + _create: function() { | |
| 1364 | + this.element.wrap('<div class="ui-chkbox ui-widget"><div class="ui-helper-hidden-accessible"></div></div>'); | |
| 1365 | + this.container = this.element.parent().parent(); | |
| 1366 | + this.box = $('<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">').appendTo(this.container); | |
| 1367 | + this.icon = $('<span class="ui-chkbox-icon ui-c"></span>').appendTo(this.box); | |
| 1368 | + this.disabled = this.element.prop('disabled'); | |
| 1369 | + this.label = $('label[for="' + this.element.attr('id') + '"]'); | |
| 1370 | + | |
| 1371 | + if(this.isChecked()) { | |
| 1372 | + this.box.addClass('ui-state-active'); | |
| 1373 | + this.icon.addClass('fa fa-fw fa-check'); | |
| 1374 | + } | |
| 1375 | + | |
| 1376 | + if(this.disabled) { | |
| 1377 | + this.box.addClass('ui-state-disabled'); | |
| 1378 | + } else { | |
| 1379 | + this._bindEvents(); | |
| 1380 | + } | |
| 1381 | + }, | |
| 1382 | + | |
| 1383 | + _bindEvents: function() { | |
| 1384 | + var $this = this; | |
| 1385 | + | |
| 1386 | + this.box.on('mouseover.puicheckbox', function() { | |
| 1387 | + if(!$this.isChecked()) | |
| 1388 | + $this.box.addClass('ui-state-hover'); | |
| 1389 | + }) | |
| 1390 | + .on('mouseout.puicheckbox', function() { | |
| 1391 | + $this.box.removeClass('ui-state-hover'); | |
| 1392 | + }) | |
| 1393 | + .on('click.puicheckbox', function() { | |
| 1394 | + $this.toggle(); | |
| 1395 | + }); | |
| 1396 | + | |
| 1397 | + this.element.on('focus.puicheckbox', function() { | |
| 1398 | + if($this.isChecked()) { | |
| 1399 | + $this.box.removeClass('ui-state-active'); | |
| 1400 | + } | |
| 1401 | + | |
| 1402 | + $this.box.addClass('ui-state-focus'); | |
| 1403 | + }) | |
| 1404 | + .on('blur.puicheckbox', function() { | |
| 1405 | + if($this.isChecked()) { | |
| 1406 | + $this.box.addClass('ui-state-active'); | |
| 1407 | + } | |
| 1408 | + | |
| 1409 | + $this.box.removeClass('ui-state-focus'); | |
| 1410 | + }) | |
| 1411 | + .on('keydown.puicheckbox', function(e) { | |
| 1412 | + var keyCode = $.ui.keyCode; | |
| 1413 | + if(e.which == keyCode.SPACE) { | |
| 1414 | + e.preventDefault(); | |
| 1415 | + } | |
| 1416 | + }) | |
| 1417 | + .on('keyup.puicheckbox', function(e) { | |
| 1418 | + var keyCode = $.ui.keyCode; | |
| 1419 | + if(e.which == keyCode.SPACE) { | |
| 1420 | + $this.toggle(true); | |
| 1421 | + | |
| 1422 | + e.preventDefault(); | |
| 1423 | + } | |
| 1424 | + }); | |
| 1425 | + | |
| 1426 | + this.label.on('click.puicheckbox', function(e) { | |
| 1427 | + $this.toggle(); | |
| 1428 | + e.preventDefault(); | |
| 1429 | + }); | |
| 1430 | + }, | |
| 1431 | + | |
| 1432 | + toggle: function(keypress) { | |
| 1433 | + if(this.isChecked()) { | |
| 1434 | + this.uncheck(keypress); | |
| 1435 | + } else { | |
| 1436 | + this.check(keypress); | |
| 1437 | + } | |
| 1438 | + | |
| 1439 | + this._trigger('change', null, this.isChecked()); | |
| 1440 | + }, | |
| 1441 | + | |
| 1442 | + isChecked: function() { | |
| 1443 | + return this.element.prop('checked'); | |
| 1444 | + }, | |
| 1445 | + | |
| 1446 | + check: function(activate, silent) { | |
| 1447 | + if(!this.isChecked()) { | |
| 1448 | + this.element.prop('checked', true); | |
| 1449 | + this.icon.addClass('fa fa-fw fa-check'); | |
| 1450 | + | |
| 1451 | + if(!activate) { | |
| 1452 | + this.box.addClass('ui-state-active'); | |
| 1453 | + } | |
| 1454 | + | |
| 1455 | + if(!silent) { | |
| 1456 | + this.element.trigger('change'); | |
| 1457 | + } | |
| 1458 | + } | |
| 1459 | + }, | |
| 1460 | + | |
| 1461 | + uncheck: function() { | |
| 1462 | + if(this.isChecked()) { | |
| 1463 | + this.element.prop('checked', false); | |
| 1464 | + this.box.removeClass('ui-state-active'); | |
| 1465 | + this.icon.removeClass('fa fa-fw fa-check'); | |
| 1466 | + | |
| 1467 | + this.element.trigger('change'); | |
| 1468 | + } | |
| 1469 | + }, | |
| 1470 | + | |
| 1471 | + _unbindEvents: function() { | |
| 1472 | + this.box.off('mouseover.puicheckbox mouseout.puicheckbox click.puicheckbox'); | |
| 1473 | + this.element.off('focus.puicheckbox blur.puicheckbox keydown.puicheckbox keyup.puicheckbox'); | |
| 1474 | + | |
| 1475 | + if (this.label.length) { | |
| 1476 | + this.label.off('click.puicheckbox'); | |
| 1477 | + } | |
| 1478 | + }, | |
| 1479 | + | |
| 1480 | + disable: function() { | |
| 1481 | + this.box.prop('disabled', true); | |
| 1482 | + this.box.attr('aria-disabled', true); | |
| 1483 | + this.box.addClass('ui-state-disabled').removeClass('ui-state-hover'); | |
| 1484 | + this._unbindEvents(); | |
| 1485 | + }, | |
| 1486 | + | |
| 1487 | + enable: function() { | |
| 1488 | + this.box.prop('disabled', false); | |
| 1489 | + this.box.attr('aria-disabled', false); | |
| 1490 | + this.box.removeClass('ui-state-disabled'); | |
| 1491 | + this._bindEvents(); | |
| 1492 | + }, | |
| 1493 | + | |
| 1494 | + _destroy: function() { | |
| 1495 | + this._unbindEvents(); | |
| 1496 | + this.container.removeClass('ui-chkbox ui-widget'); | |
| 1497 | + this.box.remove(); | |
| 1498 | + this.element.unwrap().unwrap(); | |
| 1499 | + } | |
| 1500 | + | |
| 1501 | + }); | |
| 1502 | + | |
| 1503 | +})(); | |
| 1504 | +/** | |
| 1505 | + * PrimeUI Datagrid Widget | |
| 1506 | + */ | |
| 1507 | +(function() { | |
| 1508 | + | |
| 1509 | + $.widget("primeui.puidatagrid", { | |
| 1510 | + | |
| 1511 | + options: { | |
| 1512 | + columns: 3, | |
| 1513 | + datasource: null, | |
| 1514 | + paginator: null, | |
| 1515 | + header: null, | |
| 1516 | + footer: null, | |
| 1517 | + content: null, | |
| 1518 | + lazy: false, | |
| 1519 | + template: null | |
| 1520 | + }, | |
| 1521 | + | |
| 1522 | + _create: function() { | |
| 1523 | + this.id = this.element.attr('id'); | |
| 1524 | + if(!this.id) { | |
| 1525 | + this.id = this.element.uniqueId().attr('id'); | |
| 1526 | + } | |
| 1527 | + | |
| 1528 | + this.element.addClass('ui-datagrid ui-widget'); | |
| 1529 | + | |
| 1530 | + //header | |
| 1531 | + if(this.options.header) { | |
| 1532 | + this.element.append('<div class="ui-datagrid-header ui-widget-header ui-corner-top">' + this.options.header + '</div>'); | |
| 1533 | + } | |
| 1534 | + | |
| 1535 | + //content | |
| 1536 | + this.content = $('<div class="ui-datagrid-content ui-widget-content ui-datagrid-col-' + this.options.columns + '"></div>').appendTo(this.element); | |
| 1537 | + | |
| 1538 | + //footer | |
| 1539 | + if(this.options.footer) { | |
| 1540 | + this.element.append('<div class="ui-datagrid-footer ui-widget-header ui-corner-top">' + this.options.footer + '</div>'); | |
| 1541 | + } | |
| 1542 | + | |
| 1543 | + //data | |
| 1544 | + if(this.options.datasource) { | |
| 1545 | + this._initDatasource(); | |
| 1546 | + } | |
| 1547 | + }, | |
| 1548 | + | |
| 1549 | + _onDataInit: function(data) { | |
| 1550 | + this._onDataUpdate(data); | |
| 1551 | + this._initPaginator(); | |
| 1552 | + }, | |
| 1553 | + | |
| 1554 | + _onDataUpdate: function(data) { | |
| 1555 | + this.data = data; | |
| 1556 | + if(!this.data) { | |
| 1557 | + this.data = []; | |
| 1558 | + } | |
| 1559 | + | |
| 1560 | + this.reset(); | |
| 1561 | + | |
| 1562 | + this._renderData(); | |
| 1563 | + }, | |
| 1564 | + | |
| 1565 | + _onLazyLoad: function(data) { | |
| 1566 | + this.data = data; | |
| 1567 | + if(!this.data) { | |
| 1568 | + this.data = []; | |
| 1569 | + } | |
| 1570 | + | |
| 1571 | + this._renderData(); | |
| 1572 | + }, | |
| 1573 | + | |
| 1574 | + reset: function() { | |
| 1575 | + if(this.paginator) { | |
| 1576 | + this.paginator.puipaginator('setState', { | |
| 1577 | + page: 0, | |
| 1578 | + totalRecords: this.options.lazy ? this.options.paginator.totalRecords : this.data.length | |
| 1579 | + }); | |
| 1580 | + } | |
| 1581 | + }, | |
| 1582 | + | |
| 1583 | + paginate: function() { | |
| 1584 | + if(this.options.lazy) { | |
| 1585 | + this.options.datasource.call(this, this._onLazyLoad, this._createStateMeta()); | |
| 1586 | + } | |
| 1587 | + else { | |
| 1588 | + this._renderData(); | |
| 1589 | + } | |
| 1590 | + }, | |
| 1591 | + | |
| 1592 | + _renderData: function() { | |
| 1593 | + if(this.data) { | |
| 1594 | + this.content.html(''); | |
| 1595 | + | |
| 1596 | + var firstNonLazy = this._getFirst(), | |
| 1597 | + first = this.options.lazy ? 0 : firstNonLazy, | |
| 1598 | + rows = this._getRows(), | |
| 1599 | + gridRow = null; | |
| 1600 | + | |
| 1601 | + for(var i = first; i < (first + rows); i++) { | |
| 1602 | + var dataValue = this.data[i]; | |
| 1603 | + | |
| 1604 | + if(dataValue) { | |
| 1605 | + var gridColumn = $('<div></div>').appendTo(this.content), | |
| 1606 | + markup = this._createItemContent(dataValue); | |
| 1607 | + gridColumn.append(markup); | |
| 1608 | + } | |
| 1609 | + } | |
| 1610 | + } | |
| 1611 | + }, | |
| 1612 | + | |
| 1613 | + _getFirst: function() { | |
| 1614 | + if(this.paginator) { | |
| 1615 | + var page = this.paginator.puipaginator('option', 'page'), | |
| 1616 | + rows = this.paginator.puipaginator('option', 'rows'); | |
| 1617 | + | |
| 1618 | + return (page * rows); | |
| 1619 | + } | |
| 1620 | + else { | |
| 1621 | + return 0; | |
| 1622 | + } | |
| 1623 | + }, | |
| 1624 | + | |
| 1625 | + _getRows: function() { | |
| 1626 | + if(this.options.paginator) | |
| 1627 | + return this.paginator ? this.paginator.puipaginator('option', 'rows') : this.options.paginator.rows; | |
| 1628 | + else | |
| 1629 | + return this.data ? this.data.length : 0; | |
| 1630 | + }, | |
| 1631 | + | |
| 1632 | + _createStateMeta: function() { | |
| 1633 | + var state = { | |
| 1634 | + first: this._getFirst(), | |
| 1635 | + rows: this._getRows() | |
| 1636 | + }; | |
| 1637 | + | |
| 1638 | + return state; | |
| 1639 | + }, | |
| 1640 | + | |
| 1641 | + _initPaginator: function() { | |
| 1642 | + var $this = this; | |
| 1643 | + if(this.options.paginator) { | |
| 1644 | + this.options.paginator.paginate = function(event, state) { | |
| 1645 | + $this.paginate(); | |
| 1646 | + }; | |
| 1647 | + | |
| 1648 | + this.options.paginator.totalRecords = this.options.lazy ? this.options.paginator.totalRecords : this.data.length; | |
| 1649 | + this.paginator = $('<div></div>').insertAfter(this.content).puipaginator(this.options.paginator); | |
| 1650 | + } | |
| 1651 | + }, | |
| 1652 | + | |
| 1653 | + _initDatasource: function() { | |
| 1654 | + if($.isArray(this.options.datasource)) { | |
| 1655 | + this._onDataInit(this.options.datasource); | |
| 1656 | + } | |
| 1657 | + else { | |
| 1658 | + if($.type(this.options.datasource) === 'string') { | |
| 1659 | + var $this = this, | |
| 1660 | + dataURL = this.options.datasource; | |
| 1661 | + | |
| 1662 | + this.options.datasource = function() { | |
| 1663 | + $.ajax({ | |
| 1664 | + type: 'GET', | |
| 1665 | + url: dataURL, | |
| 1666 | + dataType: "json", | |
| 1667 | + context: $this, | |
| 1668 | + success: function (response) { | |
| 1669 | + this._onDataInit(response); | |
| 1670 | + } | |
| 1671 | + }); | |
| 1672 | + }; | |
| 1673 | + } | |
| 1674 | + | |
| 1675 | + if($.type(this.options.datasource) === 'function') { | |
| 1676 | + if(this.options.lazy) | |
| 1677 | + this.options.datasource.call(this, this._onDataInit, {first:0, rows: this._getRows()}); | |
| 1678 | + else | |
| 1679 | + this.options.datasource.call(this, this._onDataInit); | |
| 1680 | + } | |
| 1681 | + } | |
| 1682 | + }, | |
| 1683 | + | |
| 1684 | + _updateDatasource: function(datasource) { | |
| 1685 | + this.options.datasource = datasource; | |
| 1686 | + | |
| 1687 | + if($.isArray(this.options.datasource)) { | |
| 1688 | + this._onDataUpdate(this.options.datasource); | |
| 1689 | + } | |
| 1690 | + else if($.type(this.options.datasource) === 'function') { | |
| 1691 | + if(this.options.lazy) | |
| 1692 | + this.options.datasource.call(this, this._onDataUpdate, {first:0, rows: this._getRows()}); | |
| 1693 | + else | |
| 1694 | + this.options.datasource.call(this, this._onDataUpdate); | |
| 1695 | + } | |
| 1696 | + }, | |
| 1697 | + | |
| 1698 | + _setOption: function(key, value) { | |
| 1699 | + if(key === 'datasource') { | |
| 1700 | + this._updateDatasource(value); | |
| 1701 | + } | |
| 1702 | + else { | |
| 1703 | + $.Widget.prototype._setOption.apply(this, arguments); | |
| 1704 | + } | |
| 1705 | + }, | |
| 1706 | + | |
| 1707 | + _createItemContent: function(obj) { | |
| 1708 | + if(this.options.template) { | |
| 1709 | + var templateContent = this.options.template.html(); | |
| 1710 | + Mustache.parse(templateContent); | |
| 1711 | + return Mustache.render(templateContent, obj); | |
| 1712 | + } | |
| 1713 | + else { | |
| 1714 | + return this.options.content.call(this, obj); | |
| 1715 | + } | |
| 1716 | + } | |
| 1717 | + | |
| 1718 | + }); | |
| 1719 | +})(); | |
| 1720 | +/** | |
| 1721 | + * PrimeUI Datascroller Widget | |
| 1722 | + */ | |
| 1723 | +(function() { | |
| 1724 | + | |
| 1725 | + $.widget("primeui.puidatascroller", { | |
| 1726 | + | |
| 1727 | + options: { | |
| 1728 | + header: null, | |
| 1729 | + buffer: 0.9, | |
| 1730 | + chunkSize: 10, | |
| 1731 | + datasource: null, | |
| 1732 | + lazy: false, | |
| 1733 | + content: null, | |
| 1734 | + template: null, | |
| 1735 | + mode: 'document', | |
| 1736 | + loader: null, | |
| 1737 | + scrollHeight: null, | |
| 1738 | + totalSize: null | |
| 1739 | + }, | |
| 1740 | + | |
| 1741 | + _create: function() { | |
| 1742 | + this.id = this.element.attr('id'); | |
| 1743 | + if(!this.id) { | |
| 1744 | + this.id = this.element.uniqueId().attr('id'); | |
| 1745 | + } | |
| 1746 | + | |
| 1747 | + this.element.addClass('ui-datascroller ui-widget'); | |
| 1748 | + if(this.options.header) { | |
| 1749 | + this.header = this.element.append('<div class="ui-datascroller-header ui-widget-header ui-corner-top">' + this.options.header + '</div>').children('.ui-datascroller-header'); | |
| 1750 | + } | |
| 1751 | + | |
| 1752 | + this.content = this.element.append('<div class="ui-datascroller-content ui-widget-content ui-corner-bottom"></div>').children('.ui-datascroller-content'); | |
| 1753 | + this.list = this.content.append('<ul class="ui-datascroller-list"></ul>').children('.ui-datascroller-list'); | |
| 1754 | + this.loaderContainer = this.content.append('<div class="ui-datascroller-loader"></div>').children('.ui-datascroller-loader'); | |
| 1755 | + this.loadStatus = $('<div class="ui-datascroller-loading"></div>'); | |
| 1756 | + this.loading = false; | |
| 1757 | + this.allLoaded = false; | |
| 1758 | + this.offset = 0; | |
| 1759 | + | |
| 1760 | + if(this.options.mode === 'self') { | |
| 1761 | + this.element.addClass('ui-datascroller-inline'); | |
| 1762 | + | |
| 1763 | + if(this.options.scrollHeight) { | |
| 1764 | + this.content.css('height', this.options.scrollHeight); | |
| 1765 | + } | |
| 1766 | + } | |
| 1767 | + | |
| 1768 | + if(this.options.loader) { | |
| 1769 | + this.bindManualLoader(); | |
| 1770 | + } | |
| 1771 | + else { | |
| 1772 | + this.bindScrollListener(); | |
| 1773 | + } | |
| 1774 | + | |
| 1775 | + if(this.options.datasource) { | |
| 1776 | + if($.isArray(this.options.datasource)) { | |
| 1777 | + this._onDataInit(this.options.datasource); | |
| 1778 | + } | |
| 1779 | + else { | |
| 1780 | + if($.type(this.options.datasource) === 'string') { | |
| 1781 | + var $this = this, | |
| 1782 | + dataURL = this.options.datasource; | |
| 1783 | + | |
| 1784 | + this.options.datasource = function() { | |
| 1785 | + $.ajax({ | |
| 1786 | + type: 'GET', | |
| 1787 | + url: dataURL, | |
| 1788 | + dataType: "json", | |
| 1789 | + context: $this, | |
| 1790 | + success: function (response) { | |
| 1791 | + this._onDataInit(response); | |
| 1792 | + } | |
| 1793 | + }); | |
| 1794 | + }; | |
| 1795 | + } | |
| 1796 | + | |
| 1797 | + if($.type(this.options.datasource) === 'function') { | |
| 1798 | + if(this.options.lazy) | |
| 1799 | + this.options.datasource.call(this, this._onLazyLoad, {first:this.offset}); | |
| 1800 | + else | |
| 1801 | + this.options.datasource.call(this, this._onDataInit); | |
| 1802 | + } | |
| 1803 | + } | |
| 1804 | + } | |
| 1805 | + }, | |
| 1806 | + | |
| 1807 | + _onDataInit: function(data) { | |
| 1808 | + this.data = data||[]; | |
| 1809 | + this.options.totalSize = this.data.length; | |
| 1810 | + | |
| 1811 | + this._load(); | |
| 1812 | + }, | |
| 1813 | + | |
| 1814 | + _onLazyLoad: function(data) { | |
| 1815 | + this._renderData(data, 0, this.options.chunkSize); | |
| 1816 | + | |
| 1817 | + this._onloadComplete(); | |
| 1818 | + }, | |
| 1819 | + | |
| 1820 | + bindScrollListener: function() { | |
| 1821 | + var $this = this; | |
| 1822 | + | |
| 1823 | + if(this.options.mode === 'document') { | |
| 1824 | + var win = $(window), | |
| 1825 | + doc = $(document), | |
| 1826 | + $this = this, | |
| 1827 | + NS = 'scroll.' + this.id; | |
| 1828 | + | |
| 1829 | + win.off(NS).on(NS, function () { | |
| 1830 | + if(win.scrollTop() >= ((doc.height() * $this.options.buffer) - win.height()) && $this.shouldLoad()) { | |
| 1831 | + $this._load(); | |
| 1832 | + } | |
| 1833 | + }); | |
| 1834 | + } | |
| 1835 | + else { | |
| 1836 | + this.content.on('scroll', function () { | |
| 1837 | + var scrollTop = this.scrollTop, | |
| 1838 | + scrollHeight = this.scrollHeight, | |
| 1839 | + viewportHeight = this.clientHeight; | |
| 1840 | + | |
| 1841 | + if((scrollTop >= ((scrollHeight * $this.options.buffer) - (viewportHeight))) && $this.shouldLoad()) { | |
| 1842 | + $this._load(); | |
| 1843 | + } | |
| 1844 | + }); | |
| 1845 | + } | |
| 1846 | + }, | |
| 1847 | + | |
| 1848 | + bindManualLoader: function() { | |
| 1849 | + var $this = this; | |
| 1850 | + | |
| 1851 | + this.options.loader.on('click.dataScroller', function(e) { | |
| 1852 | + $this._load(); | |
| 1853 | + e.preventDefault(); | |
| 1854 | + }); | |
| 1855 | + }, | |
| 1856 | + | |
| 1857 | + _load: function() { | |
| 1858 | + this.loading = true; | |
| 1859 | + this.loadStatus.appendTo(this.loaderContainer); | |
| 1860 | + if(this.options.loader) { | |
| 1861 | + this.options.loader.hide(); | |
| 1862 | + } | |
| 1863 | + | |
| 1864 | + if(this.options.lazy) { | |
| 1865 | + this.options.datasource.call(this, this._onLazyLoad, {first: this.offset}); | |
| 1866 | + } | |
| 1867 | + else { | |
| 1868 | + this._renderData(this.data, this.offset, (this.offset + this.options.chunkSize)); | |
| 1869 | + this._onloadComplete(); | |
| 1870 | + } | |
| 1871 | + }, | |
| 1872 | + | |
| 1873 | + _renderData: function(data, start, end) { | |
| 1874 | + if(data && data.length) { | |
| 1875 | + for(var i = start; i < end; i++) { | |
| 1876 | + var listItem = $('<li class="ui-datascroller-item"></li>'), | |
| 1877 | + content = this._createItemContent(data[i]); | |
| 1878 | + listItem.append(content); | |
| 1879 | + | |
| 1880 | + this.list.append(listItem); | |
| 1881 | + } | |
| 1882 | + } | |
| 1883 | + }, | |
| 1884 | + | |
| 1885 | + shouldLoad: function() { | |
| 1886 | + return (!this.loading && !this.allLoaded); | |
| 1887 | + }, | |
| 1888 | + | |
| 1889 | + _createItemContent: function(obj) { | |
| 1890 | + if(this.options.template) { | |
| 1891 | + var template = this.options.template.html(); | |
| 1892 | + Mustache.parse(template); | |
| 1893 | + return Mustache.render(template, obj); | |
| 1894 | + } | |
| 1895 | + else { | |
| 1896 | + return this.options.content.call(this, obj); | |
| 1897 | + } | |
| 1898 | + }, | |
| 1899 | + | |
| 1900 | + _onloadComplete: function() { | |
| 1901 | + this.offset += this.options.chunkSize; | |
| 1902 | + this.loading = false; | |
| 1903 | + this.allLoaded = this.offset >= this.options.totalSize; | |
| 1904 | + | |
| 1905 | + this.loadStatus.remove(); | |
| 1906 | + | |
| 1907 | + if(this.options.loader && !this.allLoaded) { | |
| 1908 | + this.options.loader.show(); | |
| 1909 | + } | |
| 1910 | + } | |
| 1911 | + | |
| 1912 | + }); | |
| 1913 | + | |
| 1914 | +})(); | |
| 1915 | +/** | |
| 1916 | + * PrimeUI Datatable Widget | |
| 1917 | + */ | |
| 1918 | +(function() { | |
| 1919 | + | |
| 1920 | + $.widget("primeui.puidatatable", { | |
| 1921 | + | |
| 1922 | + options: { | |
| 1923 | + columns: null, | |
| 1924 | + datasource: null, | |
| 1925 | + paginator: null, | |
| 1926 | + globalFilter:null, | |
| 1927 | + selectionMode: null, | |
| 1928 | + caption: null, | |
| 1929 | + footer: null, | |
| 1930 | + sortField: null, | |
| 1931 | + sortOrder: 1, | |
| 1932 | + sortMeta: [], | |
| 1933 | + sortMode: null, | |
| 1934 | + scrollable: false, | |
| 1935 | + scrollHeight: null, | |
| 1936 | + scrollWidth: null, | |
| 1937 | + responsive: false, | |
| 1938 | + expandableRows: false, | |
| 1939 | + expandedRowContent: null, | |
| 1940 | + rowExpandMode: 'multiple', | |
| 1941 | + draggableColumns: false, | |
| 1942 | + resizableColumns: false, | |
| 1943 | + columnResizeMode: 'fit', | |
| 1944 | + draggableRows: false, | |
| 1945 | + filterDelay: 300, | |
| 1946 | + stickyHeader: false, | |
| 1947 | + editMode: null, | |
| 1948 | + tabindex: 0, | |
| 1949 | + emptyMessage: 'No records found', | |
| 1950 | + sort: null, | |
| 1951 | + rowSelect: null, | |
| 1952 | + rowUnselect: null, | |
| 1953 | + rowSelectContextMenu: null, | |
| 1954 | + rowCollapse: null, | |
| 1955 | + rowExpand: null, | |
| 1956 | + colReorder: null, | |
| 1957 | + colResize: null, | |
| 1958 | + rowReorder: null, | |
| 1959 | + cellEdit: null | |
| 1960 | + }, | |
| 1961 | + | |
| 1962 | + _create: function() { | |
| 1963 | + this.id = this.element.attr('id'); | |
| 1964 | + if(!this.id) { | |
| 1965 | + this.id = this.element.uniqueId().attr('id'); | |
| 1966 | + } | |
| 1967 | + | |
| 1968 | + this.element.addClass('ui-datatable ui-widget'); | |
| 1969 | + if(this.options.responsive) { | |
| 1970 | + this.element.addClass('ui-datatable-reflow'); | |
| 1971 | + } | |
| 1972 | + | |
| 1973 | + if(this.options.scrollable) { | |
| 1974 | + this._createScrollableDatatable(); | |
| 1975 | + } | |
| 1976 | + else { | |
| 1977 | + this._createRegularDatatable(); | |
| 1978 | + } | |
| 1979 | + | |
| 1980 | + if(this.options.datasource) { | |
| 1981 | + if($.isArray(this.options.datasource)) { | |
| 1982 | + this._onDataInit(this.options.datasource); | |
| 1983 | + } | |
| 1984 | + else { | |
| 1985 | + if($.type(this.options.datasource) === 'string') { | |
| 1986 | + var $this = this, | |
| 1987 | + dataURL = this.options.datasource; | |
| 1988 | + | |
| 1989 | + this.options.datasource = function() { | |
| 1990 | + $.ajax({ | |
| 1991 | + type: 'GET', | |
| 1992 | + url: dataURL, | |
| 1993 | + dataType: "json", | |
| 1994 | + context: $this, | |
| 1995 | + success: function (response) { | |
| 1996 | + this._onDataInit(response); | |
| 1997 | + } | |
| 1998 | + }); | |
| 1999 | + }; | |
| 2000 | + } | |
| 2001 | + | |
| 2002 | + if($.type(this.options.datasource) === 'function') { | |
| 2003 | + if(this.options.lazy) | |
| 2004 | + this.options.datasource.call(this, this._onDataInit, {first:0, rows:this._getRows(), sortField:this.options.sortField, sortOrder:this.options.sortOrder, filters: this._createFilterMap()}); | |
| 2005 | + else | |
| 2006 | + this.options.datasource.call(this, this._onDataInit); | |
| 2007 | + } | |
| 2008 | + } | |
| 2009 | + } | |
| 2010 | + }, | |
| 2011 | + | |
| 2012 | + _createRegularDatatable: function() { | |
| 2013 | + this.tableWrapper = $('<div class="ui-datatable-tablewrapper" />').appendTo(this.element); | |
| 2014 | + this.table = $('<table><thead></thead><tbody></tbody></table>').appendTo(this.tableWrapper); | |
| 2015 | + this.thead = this.table.children('thead'); | |
| 2016 | + this.tbody = this.table.children('tbody').addClass('ui-datatable-data ui-widget-content'); | |
| 2017 | + | |
| 2018 | + if(this.containsFooter()) { | |
| 2019 | + this.tfoot = this.thead.after('<tfoot></tfoot>').next(); | |
| 2020 | + } | |
| 2021 | + }, | |
| 2022 | + | |
| 2023 | + _createScrollableDatatable: function() { | |
| 2024 | + this.element.append('<div class="ui-widget-header ui-datatable-scrollable-header"><div class="ui-datatable-scrollable-header-box"><table><thead></thead></table></div></div>') | |
| 2025 | + .append('<div class="ui-datatable-scrollable-body"><table><tbody></tbody></table></div>'); | |
| 2026 | + | |
| 2027 | + this.thead = this.element.find('> .ui-datatable-scrollable-header > .ui-datatable-scrollable-header-box > table > thead'); | |
| 2028 | + this.tbody = this.element.find('> .ui-datatable-scrollable-body > table > tbody'); | |
| 2029 | + | |
| 2030 | + if(this.containsFooter()) { | |
| 2031 | + this.element.append('<div class="ui-widget-header ui-datatable-scrollable-footer"><div class="ui-datatable-scrollable-footer-box"><table><tfoot></tfoot></table></div></div>'); | |
| 2032 | + this.tfoot = this.element.find('> .ui-datatable-scrollable-footer > .ui-datatable-scrollable-footer-box > table > tfoot'); | |
| 2033 | + } | |
| 2034 | + }, | |
| 2035 | + | |
| 2036 | + _initialize: function() { | |
| 2037 | + var $this = this; | |
| 2038 | + | |
| 2039 | + this._initHeader(); | |
| 2040 | + this._initFooter(); | |
| 2041 | + | |
| 2042 | + if(this.options.caption) { | |
| 2043 | + this.element.prepend('<div class="ui-datatable-header ui-widget-header">' + this.options.caption + '</div>'); | |
| 2044 | + } | |
| 2045 | + | |
| 2046 | + if(this.options.paginator) { | |
| 2047 | + this.options.paginator.paginate = function(event, state) { | |
| 2048 | + $this.paginate(); | |
| 2049 | + }; | |
| 2050 | + | |
| 2051 | + this.options.paginator.totalRecords = this.options.lazy ? this.options.paginator.totalRecords : this.data.length; | |
| 2052 | + this.paginator = $('<div></div>').insertAfter(this.tableWrapper).puipaginator(this.options.paginator); | |
| 2053 | + if(this.options.paginator.contentLeft) { | |
| 2054 | + this.paginator.prepend(this.options.paginator.contentLeft.call()); | |
| 2055 | + } | |
| 2056 | + if(this.options.paginator.contentRight) { | |
| 2057 | + this.paginator.append(this.options.paginator.contentRight.call()); | |
| 2058 | + } | |
| 2059 | + } | |
| 2060 | + | |
| 2061 | + if(this.options.footer) { | |
| 2062 | + this.element.append('<div class="ui-datatable-footer ui-widget-header">' + this.options.footer + '</div>'); | |
| 2063 | + } | |
| 2064 | + | |
| 2065 | + if(this._isSortingEnabled()) { | |
| 2066 | + this._initSorting(); | |
| 2067 | + } | |
| 2068 | + | |
| 2069 | + if(this.hasFiltering) { | |
| 2070 | + this._initFiltering(); | |
| 2071 | + } | |
| 2072 | + | |
| 2073 | + if(this.options.selectionMode) { | |
| 2074 | + this._initSelection(); | |
| 2075 | + } | |
| 2076 | + | |
| 2077 | + if(this.options.expandableRows) { | |
| 2078 | + this._initExpandableRows(); | |
| 2079 | + } | |
| 2080 | + | |
| 2081 | + if(this.options.draggableColumns) { | |
| 2082 | + this._initDraggableColumns(); | |
| 2083 | + } | |
| 2084 | + | |
| 2085 | + if(this.options.stickyHeader) { | |
| 2086 | + this._initStickyHeader(); | |
| 2087 | + } | |
| 2088 | + | |
| 2089 | + if ((this.options.sortField && this.options.sortOrder) || this.options.sortMeta.length) { | |
| 2090 | + this.sortByDefault(); | |
| 2091 | + } | |
| 2092 | + else { | |
| 2093 | + this._renderData(); | |
| 2094 | + } | |
| 2095 | + | |
| 2096 | + if(this.options.scrollable) { | |
| 2097 | + this._initScrolling(); | |
| 2098 | + } | |
| 2099 | + | |
| 2100 | + if(this.options.resizableColumns) { | |
| 2101 | + this._initResizableColumns(); | |
| 2102 | + } | |
| 2103 | + | |
| 2104 | + if(this.options.draggableRows) { | |
| 2105 | + this._initDraggableRows(); | |
| 2106 | + } | |
| 2107 | + | |
| 2108 | + if(this.options.editMode) { | |
| 2109 | + this._initEditing(); | |
| 2110 | + } | |
| 2111 | + | |
| 2112 | + }, | |
| 2113 | + | |
| 2114 | + _initHeader: function() { | |
| 2115 | + if(this.options.headerRows) { | |
| 2116 | + for(var i = 0; i < this.options.headerRows.length; i++) { | |
| 2117 | + this._initHeaderColumns(this.options.headerRows[i].columns); | |
| 2118 | + } | |
| 2119 | + } | |
| 2120 | + else if(this.options.columns) { | |
| 2121 | + this._initHeaderColumns(this.options.columns); | |
| 2122 | + } | |
| 2123 | + }, | |
| 2124 | + | |
| 2125 | + _initFooter: function() { | |
| 2126 | + if(this.containsFooter()) { | |
| 2127 | + if(this.options.footerRows) { | |
| 2128 | + for(var i = 0; i < this.options.footerRows.length; i++) { | |
| 2129 | + this._initFooterColumns(this.options.footerRows[i].columns); | |
| 2130 | + } | |
| 2131 | + } | |
| 2132 | + else if(this.options.columns) { | |
| 2133 | + this._initFooterColumns(this.options.columns); | |
| 2134 | + } | |
| 2135 | + } | |
| 2136 | + }, | |
| 2137 | + | |
| 2138 | + _initHeaderColumns: function(columns) { | |
| 2139 | + var headerRow = $('<tr class="ui-state-default"></tr>').appendTo(this.thead), | |
| 2140 | + $this = this; | |
| 2141 | + | |
| 2142 | + $.each(columns, function(i, col) { | |
| 2143 | + var cell = $('<th class="ui-state-default"><span class="ui-column-title"></span></th>').data('field', col.field).uniqueId().appendTo(headerRow); | |
| 2144 | + | |
| 2145 | + if(col.headerClass) { | |
| 2146 | + cell.addClass(col.headerClass); | |
| 2147 | + } | |
| 2148 | + | |
| 2149 | + if(col.headerStyle) { | |
| 2150 | + cell.attr('style', col.headerStyle); | |
| 2151 | + } | |
| 2152 | + | |
| 2153 | + if(col.headerText) | |
| 2154 | + cell.children('.ui-column-title').text(col.headerText); | |
| 2155 | + else if(col.headerContent) | |
| 2156 | + cell.children('.ui-column-title').append(col.headerContent.call(this, col)); | |
| 2157 | + | |
| 2158 | + if(col.rowspan) { | |
| 2159 | + cell.attr('rowspan', col.rowspan); | |
| 2160 | + } | |
| 2161 | + | |
| 2162 | + if(col.colspan) { | |
| 2163 | + cell.attr('colspan', col.colspan); | |
| 2164 | + } | |
| 2165 | + | |
| 2166 | + if(col.sortable) { | |
| 2167 | + cell.addClass('ui-sortable-column') | |
| 2168 | + .data('order', 0) | |
| 2169 | + .append('<span class="ui-sortable-column-icon fa fa-fw fa-sort"></span>'); | |
| 2170 | + } | |
| 2171 | + | |
| 2172 | + if(col.filter) { | |
| 2173 | + $this.hasFiltering = true; | |
| 2174 | + | |
| 2175 | + var filterElement = $('<input type="text" class="ui-column-filter" />').puiinputtext().data({ | |
| 2176 | + 'field': col.field, | |
| 2177 | + 'filtermatchmode': col.filterMatchMode||'startsWith' | |
| 2178 | + }).appendTo(cell); | |
| 2179 | + | |
| 2180 | + if(col.filterFunction) { | |
| 2181 | + filterElement.on('filter', function(event, dataValue, filterValue) { | |
| 2182 | + return col.filterFunction.call($this, dataValue, filterValue); | |
| 2183 | + }); | |
| 2184 | + } | |
| 2185 | + } | |
| 2186 | + }); | |
| 2187 | + }, | |
| 2188 | + | |
| 2189 | + _initFooterColumns: function(columns) { | |
| 2190 | + var footerRow = $('<tr></tr>').appendTo(this.tfoot); | |
| 2191 | + $.each(columns, function(i, col) { | |
| 2192 | + var cell = $('<td class="ui-state-default"></td>'); | |
| 2193 | + if(col.footerText) { | |
| 2194 | + cell.text(col.footerText); | |
| 2195 | + } | |
| 2196 | + | |
| 2197 | + if(col.rowspan) { | |
| 2198 | + cell.attr('rowspan', col.rowspan); | |
| 2199 | + } | |
| 2200 | + | |
| 2201 | + if(col.colspan) { | |
| 2202 | + cell.attr('colspan', col.colspan); | |
| 2203 | + } | |
| 2204 | + | |
| 2205 | + cell.appendTo(footerRow); | |
| 2206 | + }); | |
| 2207 | + }, | |
| 2208 | + | |
| 2209 | + _indicateInitialSortColumn: function(sortField, sortOrder) { | |
| 2210 | + var $this = this; | |
| 2211 | + | |
| 2212 | + $.each(this.sortableColumns, function(i, column) { | |
| 2213 | + var $column = $(column), | |
| 2214 | + data = $column.data(); | |
| 2215 | + | |
| 2216 | + if (sortField === data.field) { | |
| 2217 | + var sortIcon = $column.children('.ui-sortable-column-icon'); | |
| 2218 | + $column.data('order', sortOrder).removeClass('ui-state-hover').addClass('ui-state-active'); | |
| 2219 | + | |
| 2220 | + if(sortOrder == -1) | |
| 2221 | + sortIcon.removeClass('fa-sort fa-sort-asc').addClass('fa-sort-desc'); | |
| 2222 | + else if(sortOrder == 1) | |
| 2223 | + sortIcon.removeClass('fa-sort fa-sort-desc').addClass('fa-sort-asc'); | |
| 2224 | + } | |
| 2225 | + }); | |
| 2226 | + }, | |
| 2227 | + | |
| 2228 | + _indicateInitialSortColumns: function() { | |
| 2229 | + var $this = this; | |
| 2230 | + | |
| 2231 | + for(var i = 0; i < this.options.sortMeta.length; i++) { | |
| 2232 | + var meta = this.options.sortMeta[i]; | |
| 2233 | + this._indicateInitialSortColumn(meta.field, meta.order); | |
| 2234 | + } | |
| 2235 | + }, | |
| 2236 | + | |
| 2237 | + _onDataInit: function(data) { | |
| 2238 | + this.data = data; | |
| 2239 | + if(!this.data) { | |
| 2240 | + this.data = []; | |
| 2241 | + } | |
| 2242 | + | |
| 2243 | + this._initialize(); | |
| 2244 | + }, | |
| 2245 | + | |
| 2246 | + _onDataUpdate: function(data) { | |
| 2247 | + this.data = data; | |
| 2248 | + if(!this.data) { | |
| 2249 | + this.data = []; | |
| 2250 | + } | |
| 2251 | + | |
| 2252 | + this.reset(); | |
| 2253 | + | |
| 2254 | + this._renderData(); | |
| 2255 | + }, | |
| 2256 | + | |
| 2257 | + _onLazyLoad: function(data) { | |
| 2258 | + this.data = data; | |
| 2259 | + if(!this.data) { | |
| 2260 | + this.data = []; | |
| 2261 | + } | |
| 2262 | + | |
| 2263 | + this._renderData(); | |
| 2264 | + }, | |
| 2265 | + | |
| 2266 | + reset: function() { | |
| 2267 | + if(this.options.selectionMode) { | |
| 2268 | + this.selection = []; | |
| 2269 | + } | |
| 2270 | + | |
| 2271 | + if(this.paginator) { | |
| 2272 | + this.paginator.puipaginator('setState', { | |
| 2273 | + page: 0, | |
| 2274 | + totalRecords: this.options.lazy ? this.options.paginator.totalRecords : this.data.length | |
| 2275 | + }); | |
| 2276 | + } | |
| 2277 | + | |
| 2278 | + this.thead.find('> tr > th.ui-sortable-column').data('order', 0).filter('.ui-state-active').removeClass('ui-state-active') | |
| 2279 | + .children('span.ui-sortable-column-icon').removeClass('fa-sort-asc fa-sort-desc').addClass('fa-sort'); | |
| 2280 | + }, | |
| 2281 | + | |
| 2282 | + _isMultiSort: function() { | |
| 2283 | + if(this.options.sortMode === 'multiple') | |
| 2284 | + return true; | |
| 2285 | + else | |
| 2286 | + return false; | |
| 2287 | + }, | |
| 2288 | + | |
| 2289 | + _resetSortState: function(column) { | |
| 2290 | + this.sortableColumns.filter('.ui-state-active').data('order', 0).removeClass('ui-state-active').children('span.ui-sortable-column-icon') | |
| 2291 | + .removeClass('fa-sort-asc fa-sort-desc').addClass('fa-sort'); | |
| 2292 | + }, | |
| 2293 | + | |
| 2294 | + _initSorting: function() { | |
| 2295 | + var $this = this; | |
| 2296 | + this.sortableColumns = this.thead.find('> tr > th.ui-sortable-column'); | |
| 2297 | + | |
| 2298 | + this.sortableColumns.on('mouseover.puidatatable', function() { | |
| 2299 | + var column = $(this); | |
| 2300 | + | |
| 2301 | + if(!column.hasClass('ui-state-active')) | |
| 2302 | + column.addClass('ui-state-hover'); | |
| 2303 | + }) | |
| 2304 | + .on('mouseout.puidatatable', function() { | |
| 2305 | + var column = $(this); | |
| 2306 | + | |
| 2307 | + if(!column.hasClass('ui-state-active')) | |
| 2308 | + column.removeClass('ui-state-hover'); | |
| 2309 | + }) | |
| 2310 | + .on('click.puidatatable', function(event) { | |
| 2311 | + if(!$(event.target).is('th,span')) { | |
| 2312 | + return; | |
| 2313 | + } | |
| 2314 | + | |
| 2315 | + var column = $(this), | |
| 2316 | + sortField = column.data('field'), | |
| 2317 | + order = column.data('order'), | |
| 2318 | + sortOrder = (order === 0) ? 1 : (order * -1), | |
| 2319 | + sortIcon = column.children('.ui-sortable-column-icon'), | |
| 2320 | + metaKey = event.metaKey||event.ctrlKey; | |
| 2321 | + | |
| 2322 | + if($this._isMultiSort()) { | |
| 2323 | + if(metaKey) { | |
| 2324 | + $this._addSortMeta({field: sortField, order: sortOrder}); | |
| 2325 | + $this.sort(); | |
| 2326 | + } | |
| 2327 | + else { | |
| 2328 | + $this.options.sortMeta = []; | |
| 2329 | + $this._addSortMeta({field: sortField, order: sortOrder}); | |
| 2330 | + $this._resetSortState(column); | |
| 2331 | + $this.sort(); | |
| 2332 | + } | |
| 2333 | + } | |
| 2334 | + else { | |
| 2335 | + //update state | |
| 2336 | + $this.options.sortField = sortField; | |
| 2337 | + $this.options.sortOrder = sortOrder; | |
| 2338 | + | |
| 2339 | + $this._resetSortState(column); | |
| 2340 | + $this.sort(); | |
| 2341 | + } | |
| 2342 | + | |
| 2343 | + //update visuals | |
| 2344 | + column.data('order', sortOrder).removeClass('ui-state-hover').addClass('ui-state-active'); | |
| 2345 | + if(sortOrder === -1) | |
| 2346 | + sortIcon.removeClass('fa-sort fa-sort-asc').addClass('fa-sort-desc'); | |
| 2347 | + else if(sortOrder === 1) | |
| 2348 | + sortIcon.removeClass('fa-sort fa-sort-desc').addClass('fa-sort-asc'); | |
| 2349 | + | |
| 2350 | + $this._trigger('sort', event, {'sortOrder': sortOrder, 'sortField': sortField}); | |
| 2351 | + }); | |
| 2352 | + }, | |
| 2353 | + | |
| 2354 | + _addSortMeta: function(meta) { | |
| 2355 | + var index = -1; | |
| 2356 | + for(var i = 0; i < this.options.sortMeta.length; i++) { | |
| 2357 | + if(this.options.sortMeta[i].field === meta.field) { | |
| 2358 | + index = i; | |
| 2359 | + } | |
| 2360 | + } | |
| 2361 | + | |
| 2362 | + if(index >= 0) | |
| 2363 | + this.options.sortMeta[index] = meta; | |
| 2364 | + else | |
| 2365 | + this.options.sortMeta.push(meta); | |
| 2366 | + }, | |
| 2367 | + | |
| 2368 | + paginate: function() { | |
| 2369 | + if(this.options.lazy) { | |
| 2370 | + this.options.datasource.call(this, this._onLazyLoad, this._createStateMeta()); | |
| 2371 | + } | |
| 2372 | + else { | |
| 2373 | + this._renderData(); | |
| 2374 | + } | |
| 2375 | + }, | |
| 2376 | + | |
| 2377 | + _multipleSort: function() { | |
| 2378 | + var $this = this; | |
| 2379 | + | |
| 2380 | + function multisort(data1,data2,sortMeta,index) { | |
| 2381 | + var value1 = data1[sortMeta[index].field], | |
| 2382 | + value2 = data2[sortMeta[index].field], | |
| 2383 | + result = null; | |
| 2384 | + | |
| 2385 | + if (typeof value1 == 'string' || value1 instanceof String) { | |
| 2386 | + if (value1.localeCompare && (value1 != value2)) { | |
| 2387 | + return (sortMeta[index].order * value1.localeCompare(value2)); | |
| 2388 | + } | |
| 2389 | + } | |
| 2390 | + else { | |
| 2391 | + result = (value1 < value2) ? -1 : 1; | |
| 2392 | + } | |
| 2393 | + | |
| 2394 | + if(value1 == value2) { | |
| 2395 | + return (sortMeta.length - 1) > (index) ? (multisort(data1, data2, sortMeta, index + 1)) : 0; | |
| 2396 | + } | |
| 2397 | + | |
| 2398 | + return (sortMeta[index].order * result); | |
| 2399 | + } | |
| 2400 | + | |
| 2401 | + this.data.sort(function (data1,data2) { | |
| 2402 | + return multisort(data1, data2, $this.options.sortMeta, 0); | |
| 2403 | + }); | |
| 2404 | + | |
| 2405 | + this._renderData(); | |
| 2406 | + }, | |
| 2407 | + | |
| 2408 | + sort: function() { | |
| 2409 | + if(this.options.lazy) { | |
| 2410 | + this.options.datasource.call(this, this._onLazyLoad, this._createStateMeta()); | |
| 2411 | + } | |
| 2412 | + else { | |
| 2413 | + if(this._isMultiSort()) | |
| 2414 | + this._multipleSort(); | |
| 2415 | + else | |
| 2416 | + this._singleSort(); | |
| 2417 | + } | |
| 2418 | + }, | |
| 2419 | + | |
| 2420 | + _singleSort: function() { | |
| 2421 | + var $this = this; | |
| 2422 | + | |
| 2423 | + this.data.sort(function(data1, data2) { | |
| 2424 | + var value1 = data1[$this.options.sortField], value2 = data2[$this.options.sortField], | |
| 2425 | + result = null; | |
| 2426 | + | |
| 2427 | + if (typeof value1 == 'string' || value1 instanceof String) { | |
| 2428 | + if ( value1.localeCompare ) { | |
| 2429 | + return ($this.options.sortOrder * value1.localeCompare(value2)); | |
| 2430 | + } | |
| 2431 | + else { | |
| 2432 | + if (value1.toLowerCase) { | |
| 2433 | + value1 = value1.toLowerCase(); | |
| 2434 | + } | |
| 2435 | + if (value2.toLowerCase) { | |
| 2436 | + value2 = value2.toLowerCase(); | |
| 2437 | + } | |
| 2438 | + result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; | |
| 2439 | + | |
| 2440 | + } | |
| 2441 | + } | |
| 2442 | + else { | |
| 2443 | + result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; | |
| 2444 | + } | |
| 2445 | + | |
| 2446 | + return ($this.options.sortOrder * result); | |
| 2447 | + }); | |
| 2448 | + | |
| 2449 | + if(this.paginator) { | |
| 2450 | + this.paginator.puipaginator('option', 'page', 0); | |
| 2451 | + } | |
| 2452 | + | |
| 2453 | + this._renderData(); | |
| 2454 | + }, | |
| 2455 | + | |
| 2456 | + sortByField: function(a, b) { | |
| 2457 | + var aName = a.name.toLowerCase(); | |
| 2458 | + var bName = b.name.toLowerCase(); | |
| 2459 | + return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0)); | |
| 2460 | + }, | |
| 2461 | + | |
| 2462 | + sortByDefault: function() { | |
| 2463 | + if(this._isMultiSort()) { | |
| 2464 | + if(this.options.sortMeta) { | |
| 2465 | + this._indicateInitialSortColumns(); | |
| 2466 | + this.sort(); | |
| 2467 | + } | |
| 2468 | + } | |
| 2469 | + else { | |
| 2470 | + this._indicateInitialSortColumn(this.options.sortField, this.options.sortOrder); | |
| 2471 | + this.sort(); | |
| 2472 | + } | |
| 2473 | + }, | |
| 2474 | + | |
| 2475 | + _renderData: function() { | |
| 2476 | + this.tbody.html(''); | |
| 2477 | + | |
| 2478 | + var dataToRender = this.filteredData||this.data; | |
| 2479 | + if(dataToRender && dataToRender.length) { | |
| 2480 | + var firstNonLazy = this._getFirst(), | |
| 2481 | + first = this.options.lazy ? 0 : firstNonLazy, | |
| 2482 | + rows = this._getRows(); | |
| 2483 | + | |
| 2484 | + for(var i = first; i < (first + rows); i++) { | |
| 2485 | + var rowData = dataToRender[i]; | |
| 2486 | + | |
| 2487 | + if(rowData) { | |
| 2488 | + var row = $('<tr class="ui-widget-content" />').appendTo(this.tbody), | |
| 2489 | + zebraStyle = (i%2 === 0) ? 'ui-datatable-even' : 'ui-datatable-odd', | |
| 2490 | + rowIndex = i; | |
| 2491 | + | |
| 2492 | + row.addClass(zebraStyle); | |
| 2493 | + row.data('rowdata', rowData); | |
| 2494 | + | |
| 2495 | + if(this.options.selectionMode && this._isSelected(rowData)) { | |
| 2496 | + row.addClass("ui-state-highlight"); | |
| 2497 | + } | |
| 2498 | + | |
| 2499 | + for(var j = 0; j < this.options.columns.length; j++) { | |
| 2500 | + var column = $('<td />').appendTo(row), | |
| 2501 | + columnOptions = this.options.columns[j]; | |
| 2502 | + | |
| 2503 | + if(columnOptions.bodyClass) { | |
| 2504 | + column.addClass(columnOptions.bodyClass); | |
| 2505 | + } | |
| 2506 | + | |
| 2507 | + if(columnOptions.bodyStyle) { | |
| 2508 | + column.attr('style', columnOptions.bodyStyle); | |
| 2509 | + } | |
| 2510 | + | |
| 2511 | + if(columnOptions.editor) { | |
| 2512 | + column.addClass('ui-editable-column').data({ | |
| 2513 | + 'editor': columnOptions.editor, | |
| 2514 | + 'rowdata': rowData, | |
| 2515 | + 'field': columnOptions.field | |
| 2516 | + }); | |
| 2517 | + } | |
| 2518 | + | |
| 2519 | + if(columnOptions.content) { | |
| 2520 | + var content = columnOptions.content.call(this, rowData, columnOptions); | |
| 2521 | + if($.type(content) === 'string') | |
| 2522 | + column.html(content); | |
| 2523 | + else | |
| 2524 | + column.append(content); | |
| 2525 | + } | |
| 2526 | + else if(columnOptions.rowToggler) { | |
| 2527 | + column.append('<div class="ui-row-toggler fa fa-fw fa-chevron-circle-right ui-c"></div>'); | |
| 2528 | + } | |
| 2529 | + else if(columnOptions.field) { | |
| 2530 | + column.text(rowData[columnOptions.field]); | |
| 2531 | + } | |
| 2532 | + | |
| 2533 | + if(this.options.responsive && columnOptions.headerText) { | |
| 2534 | + column.prepend('<span class="ui-column-title">' + columnOptions.headerText + '</span>'); | |
| 2535 | + } | |
| 2536 | + } | |
| 2537 | + } | |
| 2538 | + } | |
| 2539 | + } | |
| 2540 | + else { | |
| 2541 | + var emptyRow = $('<tr class="ui-widget-content"></tr>').appendTo(this.tbody); | |
| 2542 | + var emptyColumn = $('<td></td>').attr('colspan',this.options.columns.length).appendTo(emptyRow); | |
| 2543 | + emptyColumn.html(this.options.emptyMessage); | |
| 2544 | + } | |
| 2545 | + }, | |
| 2546 | + | |
| 2547 | + _getFirst: function() { | |
| 2548 | + if(this.paginator) { | |
| 2549 | + var page = this.paginator.puipaginator('option', 'page'), | |
| 2550 | + rows = this.paginator.puipaginator('option', 'rows'); | |
| 2551 | + | |
| 2552 | + return (page * rows); | |
| 2553 | + } | |
| 2554 | + else { | |
| 2555 | + return 0; | |
| 2556 | + } | |
| 2557 | + }, | |
| 2558 | + | |
| 2559 | + _getRows: function() { | |
| 2560 | + return this.paginator ? this.paginator.puipaginator('option', 'rows') : (this.data ? this.data.length : 0); | |
| 2561 | + }, | |
| 2562 | + | |
| 2563 | + _isSortingEnabled: function() { | |
| 2564 | + var cols = this.options.columns; | |
| 2565 | + if(cols) { | |
| 2566 | + for(var i = 0; i < cols.length; i++) { | |
| 2567 | + if(cols[i].sortable) { | |
| 2568 | + return true; | |
| 2569 | + } | |
| 2570 | + } | |
| 2571 | + } | |
| 2572 | + | |
| 2573 | + return false; | |
| 2574 | + }, | |
| 2575 | + | |
| 2576 | + _initSelection: function() { | |
| 2577 | + var $this = this; | |
| 2578 | + this.selection = []; | |
| 2579 | + this.rowSelector = '> tr.ui-widget-content:not(.ui-datatable-empty-message,.ui-datatable-unselectable)'; | |
| 2580 | + | |
| 2581 | + //shift key based range selection | |
| 2582 | + if(this._isMultipleSelection()) { | |
| 2583 | + this.originRowIndex = 0; | |
| 2584 | + this.cursorIndex = null; | |
| 2585 | + } | |
| 2586 | + | |
| 2587 | + this.tbody.off('mouseover.puidatatable mouseout.puidatatable mousedown.puidatatable click.puidatatable', this.rowSelector) | |
| 2588 | + .on('mouseover.datatable', this.rowSelector, null, function() { | |
| 2589 | + var element = $(this); | |
| 2590 | + | |
| 2591 | + if(!element.hasClass('ui-state-highlight')) { | |
| 2592 | + element.addClass('ui-state-hover'); | |
| 2593 | + } | |
| 2594 | + }) | |
| 2595 | + .on('mouseout.datatable', this.rowSelector, null, function() { | |
| 2596 | + var element = $(this); | |
| 2597 | + | |
| 2598 | + if(!element.hasClass('ui-state-highlight')) { | |
| 2599 | + element.removeClass('ui-state-hover'); | |
| 2600 | + } | |
| 2601 | + }) | |
| 2602 | + .on('mousedown.datatable', this.rowSelector, null, function() { | |
| 2603 | + $this.mousedownOnRow = true; | |
| 2604 | + }) | |
| 2605 | + .on('click.datatable', this.rowSelector, null, function(e) { | |
| 2606 | + $this._onRowClick(e, this); | |
| 2607 | + $this.mousedownOnRow = false; | |
| 2608 | + }); | |
| 2609 | + | |
| 2610 | + this._bindSelectionKeyEvents(); | |
| 2611 | + }, | |
| 2612 | + | |
| 2613 | + _onRowClick: function(event, rowElement) { | |
| 2614 | + if(!$(event.target).is(':input,:button,a,.ui-c')) { | |
| 2615 | + var row = $(rowElement), | |
| 2616 | + selected = row.hasClass('ui-state-highlight'), | |
| 2617 | + metaKey = event.metaKey||event.ctrlKey, | |
| 2618 | + shiftKey = event.shiftKey; | |
| 2619 | + | |
| 2620 | + this.focusedRow = row; | |
| 2621 | + | |
| 2622 | + //unselect a selected row if metakey is on | |
| 2623 | + if(selected && metaKey) { | |
| 2624 | + this.unselectRow(row); | |
| 2625 | + } | |
| 2626 | + else { | |
| 2627 | + //unselect previous selection if this is single selection or multiple one with no keys | |
| 2628 | + if(this._isSingleSelection() || (this._isMultipleSelection() && !metaKey && !shiftKey)) { | |
| 2629 | + if (this._isMultipleSelection()) { | |
| 2630 | + var selections = this.getSelection(); | |
| 2631 | + for (var i = 0; i < selections.length; i++) { | |
| 2632 | + this._trigger('rowUnselect', null, selections[i]); | |
| 2633 | + } | |
| 2634 | + } | |
| 2635 | + | |
| 2636 | + this.unselectAllRows(); | |
| 2637 | + } | |
| 2638 | + | |
| 2639 | + this.selectRow(row, false, event); | |
| 2640 | + } | |
| 2641 | + | |
| 2642 | + PUI.clearSelection(); | |
| 2643 | + } | |
| 2644 | + }, | |
| 2645 | + | |
| 2646 | + onRowRightClick: function(event, rowElement) { | |
| 2647 | + var row = $(rowElement), | |
| 2648 | + selectedData = row.data('rowdata'), | |
| 2649 | + selected = row.hasClass('ui-state-highlight'); | |
| 2650 | + | |
| 2651 | + if(this._isSingleSelection() || !selected) { | |
| 2652 | + this.unselectAllRows(); | |
| 2653 | + } | |
| 2654 | + | |
| 2655 | + this.selectRow(row, true); | |
| 2656 | + this.dataSelectedByContextMenu = selectedData; | |
| 2657 | + this._trigger('rowSelectContextMenu', event, selectedData); | |
| 2658 | + | |
| 2659 | + PUI.clearSelection(); | |
| 2660 | + }, | |
| 2661 | + | |
| 2662 | + _bindSelectionKeyEvents: function() { | |
| 2663 | + var $this = this; | |
| 2664 | + | |
| 2665 | + this.tbody.attr('tabindex', this.options.tabindex).on('focus', function(e) { | |
| 2666 | + //ignore mouse click on row | |
| 2667 | + if(!$this.mousedownOnRow) { | |
| 2668 | + $this.focusedRow = $this.tbody.children('tr.ui-widget-content').eq(0); | |
| 2669 | + $this.focusedRow.addClass('ui-state-hover'); | |
| 2670 | + } | |
| 2671 | + }) | |
| 2672 | + .on('blur', function() { | |
| 2673 | + if($this.focusedRow) { | |
| 2674 | + $this.focusedRow.removeClass('ui-state-hover'); | |
| 2675 | + $this.focusedRow = null; | |
| 2676 | + } | |
| 2677 | + }) | |
| 2678 | + .on('keydown', function(e) { | |
| 2679 | + var keyCode = $.ui.keyCode, | |
| 2680 | + key = e.which; | |
| 2681 | + | |
| 2682 | + if($this.focusedRow) { | |
| 2683 | + switch(key) { | |
| 2684 | + case keyCode.UP: | |
| 2685 | + var prevRow = $this.focusedRow.prev('tr.ui-widget-content'); | |
| 2686 | + if(prevRow.length) { | |
| 2687 | + $this.focusedRow.removeClass('ui-state-hover'); | |
| 2688 | + $this.focusedRow = prevRow; | |
| 2689 | + $this.focusedRow.addClass('ui-state-hover'); | |
| 2690 | + } | |
| 2691 | + e.preventDefault(); | |
| 2692 | + break; | |
| 2693 | + | |
| 2694 | + case keyCode.DOWN: | |
| 2695 | + var nextRow = $this.focusedRow.next('tr.ui-widget-content'); | |
| 2696 | + if(nextRow.length) { | |
| 2697 | + $this.focusedRow.removeClass('ui-state-hover'); | |
| 2698 | + $this.focusedRow = nextRow; | |
| 2699 | + $this.focusedRow.addClass('ui-state-hover'); | |
| 2700 | + } | |
| 2701 | + e.preventDefault(); | |
| 2702 | + break; | |
| 2703 | + | |
| 2704 | + case keyCode.ENTER: | |
| 2705 | + case keyCode.NUMPAD_ENTER: | |
| 2706 | + case keyCode.SPACE: | |
| 2707 | + e.target = $this.focusedRow.children().eq(0).get(0); | |
| 2708 | + $this._onRowClick(e, $this.focusedRow.get(0)); | |
| 2709 | + e.preventDefault(); | |
| 2710 | + break; | |
| 2711 | + | |
| 2712 | + default: | |
| 2713 | + break; | |
| 2714 | + }; | |
| 2715 | + } | |
| 2716 | + }); | |
| 2717 | + | |
| 2718 | + }, | |
| 2719 | + | |
| 2720 | + _isSingleSelection: function() { | |
| 2721 | + return this.options.selectionMode === 'single'; | |
| 2722 | + }, | |
| 2723 | + | |
| 2724 | + _isMultipleSelection: function() { | |
| 2725 | + return this.options.selectionMode === 'multiple'; | |
| 2726 | + }, | |
| 2727 | + | |
| 2728 | + unselectAllRows: function() { | |
| 2729 | + this.tbody.children('tr.ui-state-highlight').removeClass('ui-state-highlight').attr('aria-selected', false); | |
| 2730 | + this.selection = []; | |
| 2731 | + }, | |
| 2732 | + | |
| 2733 | + unselectRow: function(row, silent) { | |
| 2734 | + var unselectedData = row.data('rowdata'); | |
| 2735 | + row.removeClass('ui-state-highlight').attr('aria-selected', false); | |
| 2736 | + | |
| 2737 | + this._removeSelection(unselectedData); | |
| 2738 | + | |
| 2739 | + if(!silent) { | |
| 2740 | + this._trigger('rowUnselect', null, unselectedData); | |
| 2741 | + } | |
| 2742 | + }, | |
| 2743 | + | |
| 2744 | + selectRow: function(row, silent, event) { | |
| 2745 | + var selectedData = row.data('rowdata'); | |
| 2746 | + row.removeClass('ui-state-hover').addClass('ui-state-highlight').attr('aria-selected', true); | |
| 2747 | + | |
| 2748 | + this._addSelection(selectedData); | |
| 2749 | + | |
| 2750 | + if(!silent) { | |
| 2751 | + this._trigger('rowSelect', event, selectedData); | |
| 2752 | + } | |
| 2753 | + }, | |
| 2754 | + | |
| 2755 | + getSelection: function() { | |
| 2756 | + return this.selection; | |
| 2757 | + }, | |
| 2758 | + | |
| 2759 | + _removeSelection: function(rowData) { | |
| 2760 | + this.selection = $.grep(this.selection, function(value) { | |
| 2761 | + return value !== rowData; | |
| 2762 | + }); | |
| 2763 | + }, | |
| 2764 | + | |
| 2765 | + _addSelection: function(rowData) { | |
| 2766 | + if(!this._isSelected(rowData)) { | |
| 2767 | + this.selection.push(rowData); | |
| 2768 | + } | |
| 2769 | + }, | |
| 2770 | + | |
| 2771 | + _isSelected: function(rowData) { | |
| 2772 | + return PUI.inArray(this.selection, rowData); | |
| 2773 | + }, | |
| 2774 | + | |
| 2775 | + _initExpandableRows: function() { | |
| 2776 | + var $this = this, | |
| 2777 | + togglerSelector = '> tr > td > div.ui-row-toggler'; | |
| 2778 | + | |
| 2779 | + this.tbody.off('click', togglerSelector) | |
| 2780 | + .on('click', togglerSelector, null, function() { | |
| 2781 | + $this.toggleExpansion($(this)); | |
| 2782 | + }) | |
| 2783 | + .on('keydown', togglerSelector, null, function(e) { | |
| 2784 | + var key = e.which, | |
| 2785 | + keyCode = $.ui.keyCode; | |
| 2786 | + | |
| 2787 | + if((key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER)) { | |
| 2788 | + $this.toggleExpansion($(this)); | |
| 2789 | + e.preventDefault(); | |
| 2790 | + } | |
| 2791 | + }); | |
| 2792 | + }, | |
| 2793 | + | |
| 2794 | + toggleExpansion: function(toggler) { | |
| 2795 | + var row = toggler.closest('tr'), | |
| 2796 | + expanded = toggler.hasClass('fa-chevron-circle-down'); | |
| 2797 | + | |
| 2798 | + if(expanded) { | |
| 2799 | + toggler.addClass('fa-chevron-circle-right').removeClass('fa-chevron-circle-down').attr('aria-expanded', false); | |
| 2800 | + | |
| 2801 | + this.collapseRow(row); | |
| 2802 | + this._trigger('rowCollapse', null, row.data('rowdata')); | |
| 2803 | + } | |
| 2804 | + else { | |
| 2805 | + if(this.options.rowExpandMode === 'single') { | |
| 2806 | + this.collapseAllRows(); | |
| 2807 | + } | |
| 2808 | + | |
| 2809 | + toggler.addClass('fa-chevron-circle-down').removeClass('fa-chevron-circle-right').attr('aria-expanded', true); | |
| 2810 | + | |
| 2811 | + this.loadExpandedRowContent(row); | |
| 2812 | + } | |
| 2813 | + }, | |
| 2814 | + | |
| 2815 | + loadExpandedRowContent: function(row) { | |
| 2816 | + var expandedRow = $('<tr class="ui-expanded-row-content ui-datatable-unselectable ui-widget-content"><td colspan="' + this.options.columns.length + '"></td></tr>'); | |
| 2817 | + expandedRow.children('td').append(this.options.expandedRowContent.call(this, row.data('rowdata'))); | |
| 2818 | + | |
| 2819 | + row.addClass('ui-expanded-row').after(expandedRow); | |
| 2820 | + this._trigger('rowExpand', null, row.data('rowdata')); | |
| 2821 | + }, | |
| 2822 | + | |
| 2823 | + collapseRow: function(row) { | |
| 2824 | + row.removeClass('ui-expanded-row').next('.ui-expanded-row-content').remove(); | |
| 2825 | + }, | |
| 2826 | + | |
| 2827 | + collapseAllRows: function() { | |
| 2828 | + var $this = this; | |
| 2829 | + | |
| 2830 | + this.getExpandedRows().each(function () { | |
| 2831 | + var expandedRow = $(this); | |
| 2832 | + $this.collapseRow(expandedRow); | |
| 2833 | + | |
| 2834 | + var columns = expandedRow.children('td'); | |
| 2835 | + for (var i = 0; i < columns.length; i++) { | |
| 2836 | + var column = columns.eq(i), | |
| 2837 | + toggler = column.children('.ui-row-toggler'); | |
| 2838 | + | |
| 2839 | + if (toggler.length) { | |
| 2840 | + toggler.addClass('fa-chevron-circle-right').removeClass('fa-chevron-circle-down'); | |
| 2841 | + } | |
| 2842 | + } | |
| 2843 | + }); | |
| 2844 | + }, | |
| 2845 | + | |
| 2846 | + getExpandedRows: function () { | |
| 2847 | + return this.tbody.children('.ui-expanded-row'); | |
| 2848 | + }, | |
| 2849 | + | |
| 2850 | + _createStateMeta: function() { | |
| 2851 | + var state = { | |
| 2852 | + first: this._getFirst(), | |
| 2853 | + rows: this._getRows(), | |
| 2854 | + sortField: this.options.sortField, | |
| 2855 | + sortOrder: this.options.sortOrder, | |
| 2856 | + sortMeta: this.options.sortMeta, | |
| 2857 | + filters: this.filterMetaMap | |
| 2858 | + }; | |
| 2859 | + | |
| 2860 | + return state; | |
| 2861 | + }, | |
| 2862 | + | |
| 2863 | + _updateDatasource: function(datasource) { | |
| 2864 | + this.options.datasource = datasource; | |
| 2865 | + | |
| 2866 | + if($.isArray(this.options.datasource)) { | |
| 2867 | + this._onDataUpdate(this.options.datasource); | |
| 2868 | + } | |
| 2869 | + else if($.type(this.options.datasource) === 'function') { | |
| 2870 | + if(this.options.lazy) | |
| 2871 | + this.options.datasource.call(this, this._onDataUpdate, {first:0, rows: this._getRows(), sortField:this.options.sortField, sortorder:this.options.sortOrder, filters: this._createFilterMap()}); | |
| 2872 | + else | |
| 2873 | + this.options.datasource.call(this, this._onDataUpdate); | |
| 2874 | + } | |
| 2875 | + }, | |
| 2876 | + | |
| 2877 | + _setOption: function(key, value) { | |
| 2878 | + if(key === 'datasource') { | |
| 2879 | + this._updateDatasource(value); | |
| 2880 | + } | |
| 2881 | + else { | |
| 2882 | + $.Widget.prototype._setOption.apply(this, arguments); | |
| 2883 | + } | |
| 2884 | + }, | |
| 2885 | + | |
| 2886 | + _initScrolling: function() { | |
| 2887 | + this.scrollHeader = this.element.children('.ui-datatable-scrollable-header'); | |
| 2888 | + this.scrollBody = this.element.children('.ui-datatable-scrollable-body'); | |
| 2889 | + this.scrollHeaderBox = this.scrollHeader.children('.ui-datatable-scrollable-header-box'); | |
| 2890 | + this.headerTable = this.scrollHeaderBox.children('table'); | |
| 2891 | + this.bodyTable = this.scrollBody.children('table'); | |
| 2892 | + this.percentageScrollHeight = this.options.scrollHeight && (this.options.scrollHeight.indexOf('%') !== -1); | |
| 2893 | + this.percentageScrollWidth = this.options.scrollWidth && (this.options.scrollWidth.indexOf('%') !== -1); | |
| 2894 | + var $this = this, | |
| 2895 | + scrollBarWidth = this.getScrollbarWidth() + 'px'; | |
| 2896 | + | |
| 2897 | + if(this.options.scrollHeight) { | |
| 2898 | + if(this.percentageScrollHeight) | |
| 2899 | + this.adjustScrollHeight(); | |
| 2900 | + else | |
| 2901 | + this.scrollBody.css('max-height', this.options.scrollHeight + 'px'); | |
| 2902 | + | |
| 2903 | + if(this.hasVerticalOverflow()) { | |
| 2904 | + this.scrollHeaderBox.css('margin-right', scrollBarWidth); | |
| 2905 | + } | |
| 2906 | + } | |
| 2907 | + | |
| 2908 | + this.fixColumnWidths(); | |
| 2909 | + | |
| 2910 | + if(this.options.scrollWidth) { | |
| 2911 | + if(this.percentageScrollWidth) | |
| 2912 | + this.adjustScrollWidth(); | |
| 2913 | + else | |
| 2914 | + this.setScrollWidth(parseInt(this.options.scrollWidth)); | |
| 2915 | + } | |
| 2916 | + | |
| 2917 | + this.cloneHead(); | |
| 2918 | + | |
| 2919 | + this.scrollBody.on('scroll.dataTable', function() { | |
| 2920 | + var scrollLeft = $this.scrollBody.scrollLeft(); | |
| 2921 | + $this.scrollHeaderBox.css('margin-left', -scrollLeft); | |
| 2922 | + }); | |
| 2923 | + | |
| 2924 | + this.scrollHeader.on('scroll.dataTable', function() { | |
| 2925 | + $this.scrollHeader.scrollLeft(0); | |
| 2926 | + }); | |
| 2927 | + | |
| 2928 | + var resizeNS = 'resize.' + this.id; | |
| 2929 | + $(window).off(resizeNS).on(resizeNS, function() { | |
| 2930 | + if($this.element.is(':visible')) { | |
| 2931 | + if($this.percentageScrollHeight) | |
| 2932 | + $this.adjustScrollHeight(); | |
| 2933 | + | |
| 2934 | + if($this.percentageScrollWidth) | |
| 2935 | + $this.adjustScrollWidth(); | |
| 2936 | + } | |
| 2937 | + }); | |
| 2938 | + }, | |
| 2939 | + | |
| 2940 | + cloneHead: function() { | |
| 2941 | + this.theadClone = this.thead.clone(); | |
| 2942 | + this.theadClone.find('th').each(function() { | |
| 2943 | + var header = $(this); | |
| 2944 | + header.attr('id', header.attr('id') + '_clone'); | |
| 2945 | + $(this).children().not('.ui-column-title').remove(); | |
| 2946 | + }); | |
| 2947 | + this.theadClone.removeAttr('id').addClass('ui-datatable-scrollable-theadclone').height(0).prependTo(this.bodyTable); | |
| 2948 | + | |
| 2949 | + //align horizontal scroller on keyboard tab | |
| 2950 | + if(this.options.scrollWidth) { | |
| 2951 | + var clonedSortableColumns = this.theadClone.find('> tr > th.ui-sortable-column'); | |
| 2952 | + clonedSortableColumns.each(function() { | |
| 2953 | + $(this).data('original', $(this).attr('id').split('_clone')[0]); | |
| 2954 | + }); | |
| 2955 | + | |
| 2956 | + clonedSortableColumns.on('blur.dataTable', function() { | |
| 2957 | + $(PUI.escapeClientId($(this).data('original'))).removeClass('ui-state-focus'); | |
| 2958 | + }) | |
| 2959 | + .on('focus.dataTable', function() { | |
| 2960 | + $(PUI.escapeClientId($(this).data('original'))).addClass('ui-state-focus'); | |
| 2961 | + }) | |
| 2962 | + .on('keydown.dataTable', function(e) { | |
| 2963 | + var key = e.which, | |
| 2964 | + keyCode = $.ui.keyCode; | |
| 2965 | + | |
| 2966 | + if((key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) && $(e.target).is(':not(:input)')) { | |
| 2967 | + $(PUI.escapeClientId($(this).data('original'))).trigger('click.dataTable', (e.metaKey||e.ctrlKey)); | |
| 2968 | + e.preventDefault(); | |
| 2969 | + } | |
| 2970 | + }); | |
| 2971 | + } | |
| 2972 | + }, | |
| 2973 | + | |
| 2974 | + adjustScrollHeight: function() { | |
| 2975 | + var relativeHeight = this.element.parent().innerHeight() * (parseInt(this.options.scrollHeight) / 100), | |
| 2976 | + tableHeaderHeight = this.element.children('.ui-datatable-header').outerHeight(true), | |
| 2977 | + tableFooterHeight = this.element.children('.ui-datatable-footer').outerHeight(true), | |
| 2978 | + scrollersHeight = (this.scrollHeader.outerHeight(true) + this.scrollFooter.outerHeight(true)), | |
| 2979 | + paginatorsHeight = this.paginator ? this.paginator.getContainerHeight(true) : 0, | |
| 2980 | + height = (relativeHeight - (scrollersHeight + paginatorsHeight + tableHeaderHeight + tableFooterHeight)); | |
| 2981 | + | |
| 2982 | + this.scrollBody.css('max-height', height + 'px'); | |
| 2983 | + }, | |
| 2984 | + | |
| 2985 | + adjustScrollWidth: function() { | |
| 2986 | + var width = parseInt((this.element.parent().innerWidth() * (parseInt(this.options.scrollWidth) / 100))); | |
| 2987 | + this.setScrollWidth(width); | |
| 2988 | + }, | |
| 2989 | + | |
| 2990 | + setOuterWidth: function(element, width) { | |
| 2991 | + var diff = element.outerWidth() - element.width(); | |
| 2992 | + element.width(width - diff); | |
| 2993 | + }, | |
| 2994 | + | |
| 2995 | + setScrollWidth: function(width) { | |
| 2996 | + var $this = this; | |
| 2997 | + this.element.children('.ui-widget-header').each(function() { | |
| 2998 | + $this.setOuterWidth($(this), width); | |
| 2999 | + }); | |
| 3000 | + this.scrollHeader.width(width); | |
| 3001 | + this.scrollBody.css('margin-right', 0).width(width); | |
| 3002 | + }, | |
| 3003 | + | |
| 3004 | + alignScrollBody: function() { | |
| 3005 | + var marginRight = this.hasVerticalOverflow() ? this.getScrollbarWidth() + 'px' : '0px'; | |
| 3006 | + | |
| 3007 | + this.scrollHeaderBox.css('margin-right', marginRight); | |
| 3008 | + }, | |
| 3009 | + | |
| 3010 | + getScrollbarWidth: function() { | |
| 3011 | + if(!this.scrollbarWidth) { | |
| 3012 | + this.scrollbarWidth = PUI.browser.webkit ? '15' : PUI.calculateScrollbarWidth(); | |
| 3013 | + } | |
| 3014 | + | |
| 3015 | + return this.scrollbarWidth; | |
| 3016 | + }, | |
| 3017 | + | |
| 3018 | + hasVerticalOverflow: function() { | |
| 3019 | + return (this.options.scrollHeight && this.bodyTable.outerHeight() > this.scrollBody.outerHeight()) | |
| 3020 | + }, | |
| 3021 | + | |
| 3022 | + restoreScrollState: function() { | |
| 3023 | + var scrollState = this.scrollStateHolder.val(), | |
| 3024 | + scrollValues = scrollState.split(','); | |
| 3025 | + | |
| 3026 | + this.scrollBody.scrollLeft(scrollValues[0]); | |
| 3027 | + this.scrollBody.scrollTop(scrollValues[1]); | |
| 3028 | + }, | |
| 3029 | + | |
| 3030 | + saveScrollState: function() { | |
| 3031 | + var scrollState = this.scrollBody.scrollLeft() + ',' + this.scrollBody.scrollTop(); | |
| 3032 | + | |
| 3033 | + this.scrollStateHolder.val(scrollState); | |
| 3034 | + }, | |
| 3035 | + | |
| 3036 | + clearScrollState: function() { | |
| 3037 | + this.scrollStateHolder.val('0,0'); | |
| 3038 | + }, | |
| 3039 | + | |
| 3040 | + fixColumnWidths: function() { | |
| 3041 | + if(!this.columnWidthsFixed) { | |
| 3042 | + if(this.options.scrollable) { | |
| 3043 | + this.scrollHeaderBox.find('> table > thead > tr > th').each(function() { | |
| 3044 | + var headerCol = $(this), | |
| 3045 | + width = headerCol.width(); | |
| 3046 | + headerCol.width(width); | |
| 3047 | + }); | |
| 3048 | + } | |
| 3049 | + else { | |
| 3050 | + this.element.find('> .ui-datatable-tablewrapper > table > thead > tr > th').each(function() { | |
| 3051 | + var col = $(this); | |
| 3052 | + col.width(col.width()); | |
| 3053 | + }); | |
| 3054 | + } | |
| 3055 | + | |
| 3056 | + this.columnWidthsFixed = true; | |
| 3057 | + } | |
| 3058 | + }, | |
| 3059 | + | |
| 3060 | + _initDraggableColumns: function() { | |
| 3061 | + var $this = this; | |
| 3062 | + | |
| 3063 | + this.dragIndicatorTop = $('<span class="fa fa-arrow-down" style="position:absolute"/></span>').hide().appendTo(this.element); | |
| 3064 | + this.dragIndicatorBottom = $('<span class="fa fa-arrow-up" style="position:absolute"/></span>').hide().appendTo(this.element); | |
| 3065 | + | |
| 3066 | + this.thead.find('> tr > th').draggable({ | |
| 3067 | + appendTo: 'body', | |
| 3068 | + opacity: 0.75, | |
| 3069 | + cursor: 'move', | |
| 3070 | + scope: this.id, | |
| 3071 | + cancel: ':input,.ui-column-resizer', | |
| 3072 | + drag: function(event, ui) { | |
| 3073 | + var droppable = ui.helper.data('droppable-column'); | |
| 3074 | + | |
| 3075 | + if(droppable) { | |
| 3076 | + var droppableOffset = droppable.offset(), | |
| 3077 | + topArrowY = droppableOffset.top - 10, | |
| 3078 | + bottomArrowY = droppableOffset.top + droppable.height() + 8, | |
| 3079 | + arrowX = null; | |
| 3080 | + | |
| 3081 | + //calculate coordinates of arrow depending on mouse location | |
| 3082 | + if(event.originalEvent.pageX >= droppableOffset.left + (droppable.width() / 2)) { | |
| 3083 | + var nextDroppable = droppable.next(); | |
| 3084 | + if(nextDroppable.length == 1) | |
| 3085 | + arrowX = nextDroppable.offset().left - 9; | |
| 3086 | + else | |
| 3087 | + arrowX = droppable.offset().left + droppable.innerWidth() - 9; | |
| 3088 | + | |
| 3089 | + ui.helper.data('drop-location', 1); //right | |
| 3090 | + } | |
| 3091 | + else { | |
| 3092 | + arrowX = droppableOffset.left - 9; | |
| 3093 | + ui.helper.data('drop-location', -1); //left | |
| 3094 | + } | |
| 3095 | + | |
| 3096 | + $this.dragIndicatorTop.offset({ | |
| 3097 | + 'left': arrowX, | |
| 3098 | + 'top': topArrowY - 3 | |
| 3099 | + }).show(); | |
| 3100 | + | |
| 3101 | + $this.dragIndicatorBottom.offset({ | |
| 3102 | + 'left': arrowX, | |
| 3103 | + 'top': bottomArrowY - 3 | |
| 3104 | + }).show(); | |
| 3105 | + } | |
| 3106 | + }, | |
| 3107 | + stop: function(event, ui) { | |
| 3108 | + //hide dnd arrows | |
| 3109 | + $this.dragIndicatorTop.css({ | |
| 3110 | + 'left':0, | |
| 3111 | + 'top':0 | |
| 3112 | + }).hide(); | |
| 3113 | + | |
| 3114 | + $this.dragIndicatorBottom.css({ | |
| 3115 | + 'left':0, | |
| 3116 | + 'top':0 | |
| 3117 | + }).hide(); | |
| 3118 | + }, | |
| 3119 | + helper: function() { | |
| 3120 | + var header = $(this), | |
| 3121 | + helper = $('<div class="ui-widget ui-state-default" style="padding:4px 10px;text-align:center;"></div>'); | |
| 3122 | + | |
| 3123 | + helper.width(header.width()); | |
| 3124 | + helper.height(header.height()); | |
| 3125 | + | |
| 3126 | + helper.html(header.html()); | |
| 3127 | + | |
| 3128 | + return helper.get(0); | |
| 3129 | + } | |
| 3130 | + }).droppable({ | |
| 3131 | + hoverClass:'ui-state-highlight', | |
| 3132 | + tolerance:'pointer', | |
| 3133 | + scope: this.id, | |
| 3134 | + over: function(event, ui) { | |
| 3135 | + ui.helper.data('droppable-column', $(this)); | |
| 3136 | + }, | |
| 3137 | + drop: function(event, ui) { | |
| 3138 | + var draggedColumnHeader = ui.draggable, | |
| 3139 | + dropLocation = ui.helper.data('drop-location'), | |
| 3140 | + droppedColumnHeader = $(this), | |
| 3141 | + draggedColumnFooter = null, | |
| 3142 | + droppedColumnFooter = null; | |
| 3143 | + | |
| 3144 | + var draggedCells = $this.tbody.find('> tr:not(.ui-expanded-row-content) > td:nth-child(' + (draggedColumnHeader.index() + 1) + ')'), | |
| 3145 | + droppedCells = $this.tbody.find('> tr:not(.ui-expanded-row-content) > td:nth-child(' + (droppedColumnHeader.index() + 1) + ')'); | |
| 3146 | + | |
| 3147 | + if($this.containsFooter()) { | |
| 3148 | + var footerColumns = $this.tfoot.find('> tr > td'), | |
| 3149 | + draggedColumnFooter = footerColumns.eq(draggedColumnHeader.index()), | |
| 3150 | + droppedColumnFooter = footerColumns.eq(droppedColumnHeader.index()); | |
| 3151 | + } | |
| 3152 | + | |
| 3153 | + //drop right | |
| 3154 | + if(dropLocation > 0) { | |
| 3155 | + /* TODO :Resizable columns | |
| 3156 | + * if($this.options.resizableColumns) { | |
| 3157 | + if(droppedColumnHeader.next().length) { | |
| 3158 | + droppedColumnHeader.children('span.ui-column-resizer').show(); | |
| 3159 | + draggedColumnHeader.children('span.ui-column-resizer').hide(); | |
| 3160 | + } | |
| 3161 | + }*/ | |
| 3162 | + | |
| 3163 | + draggedColumnHeader.insertAfter(droppedColumnHeader); | |
| 3164 | + | |
| 3165 | + draggedCells.each(function(i, item) { | |
| 3166 | + $(this).insertAfter(droppedCells.eq(i)); | |
| 3167 | + }); | |
| 3168 | + | |
| 3169 | + if(draggedColumnFooter && droppedColumnFooter) { | |
| 3170 | + draggedColumnFooter.insertAfter(droppedColumnFooter); | |
| 3171 | + } | |
| 3172 | + | |
| 3173 | + //sync clone | |
| 3174 | + if($this.options.scrollable) { | |
| 3175 | + var draggedColumnClone = $(document.getElementById(draggedColumnHeader.attr('id') + '_clone')), | |
| 3176 | + droppedColumnClone = $(document.getElementById(droppedColumnHeader.attr('id') + '_clone')); | |
| 3177 | + draggedColumnClone.insertAfter(droppedColumnClone); | |
| 3178 | + } | |
| 3179 | + } | |
| 3180 | + //drop left | |
| 3181 | + else { | |
| 3182 | + draggedColumnHeader.insertBefore(droppedColumnHeader); | |
| 3183 | + | |
| 3184 | + draggedCells.each(function(i, item) { | |
| 3185 | + $(this).insertBefore(droppedCells.eq(i)); | |
| 3186 | + }); | |
| 3187 | + | |
| 3188 | + if(draggedColumnFooter && droppedColumnFooter) { | |
| 3189 | + draggedColumnFooter.insertBefore(droppedColumnFooter); | |
| 3190 | + } | |
| 3191 | + | |
| 3192 | + //sync clone | |
| 3193 | + if($this.options.scrollable) { | |
| 3194 | + var draggedColumnClone = $(document.getElementById(draggedColumnHeader.attr('id') + '_clone')), | |
| 3195 | + droppedColumnClone = $(document.getElementById(droppedColumnHeader.attr('id') + '_clone')); | |
| 3196 | + draggedColumnClone.insertBefore(droppedColumnClone); | |
| 3197 | + } | |
| 3198 | + } | |
| 3199 | + | |
| 3200 | + //fire colReorder event | |
| 3201 | + $this._trigger('colReorder', null, { | |
| 3202 | + dragIndex: draggedColumnHeader.index(), | |
| 3203 | + dropIndex: droppedColumnHeader.index() | |
| 3204 | + }); | |
| 3205 | + } | |
| 3206 | + }); | |
| 3207 | + }, | |
| 3208 | + | |
| 3209 | + containsFooter: function() { | |
| 3210 | + if(this.hasFooter === undefined) { | |
| 3211 | + this.hasFooter = this.options.footerRows !== undefined; | |
| 3212 | + if(!this.hasFooter) { | |
| 3213 | + if(this.options.columns) { | |
| 3214 | + for(var i = 0; i < this.options.columns.length; i++) { | |
| 3215 | + if(this.options.columns[i].footerText !== undefined) { | |
| 3216 | + this.hasFooter = true; | |
| 3217 | + break; | |
| 3218 | + } | |
| 3219 | + } | |
| 3220 | + } | |
| 3221 | + } | |
| 3222 | + } | |
| 3223 | + | |
| 3224 | + return this.hasFooter; | |
| 3225 | + }, | |
| 3226 | + | |
| 3227 | + _initResizableColumns: function() { | |
| 3228 | + this.element.addClass('ui-datatable-resizable'); | |
| 3229 | + this.thead.find('> tr > th').addClass('ui-resizable-column'); | |
| 3230 | + this.resizerHelper = $('<div class="ui-column-resizer-helper ui-state-highlight"></div>').appendTo(this.element); | |
| 3231 | + this.addResizers(); | |
| 3232 | + var resizers = this.thead.find('> tr > th > span.ui-column-resizer'), | |
| 3233 | + $this = this; | |
| 3234 | + | |
| 3235 | + setTimeout(function() { | |
| 3236 | + $this.fixColumnWidths(); | |
| 3237 | + }, 5); | |
| 3238 | + | |
| 3239 | + resizers.draggable({ | |
| 3240 | + axis: 'x', | |
| 3241 | + start: function(event, ui) { | |
| 3242 | + ui.helper.data('originalposition', ui.helper.offset()); | |
| 3243 | + | |
| 3244 | + var height = $this.options.scrollable ? $this.scrollBody.height() : $this.thead.parent().height() - $this.thead.height() - 1; | |
| 3245 | + $this.resizerHelper.height(height); | |
| 3246 | + $this.resizerHelper.show(); | |
| 3247 | + }, | |
| 3248 | + drag: function(event, ui) { | |
| 3249 | + $this.resizerHelper.offset({ | |
| 3250 | + left: ui.helper.offset().left + ui.helper.width() / 2, | |
| 3251 | + top: $this.thead.offset().top + $this.thead.height() | |
| 3252 | + }); | |
| 3253 | + }, | |
| 3254 | + stop: function(event, ui) { | |
| 3255 | + ui.helper.css({ | |
| 3256 | + 'left': '', | |
| 3257 | + 'top': '0px', | |
| 3258 | + 'right': '0px' | |
| 3259 | + }); | |
| 3260 | + | |
| 3261 | + $this.resize(event, ui); | |
| 3262 | + $this.resizerHelper.hide(); | |
| 3263 | + | |
| 3264 | + if($this.options.columnResizeMode === 'expand') { | |
| 3265 | + setTimeout(function() { | |
| 3266 | + $this._trigger('colResize', null, {element: ui.helper.parent()}); | |
| 3267 | + }, 5); | |
| 3268 | + } | |
| 3269 | + else { | |
| 3270 | + $this._trigger('colResize', null, {element: ui.helper.parent()}); | |
| 3271 | + } | |
| 3272 | + | |
| 3273 | + if($this.options.stickyHeader) { | |
| 3274 | + $this.thead.find('.ui-column-filter').prop('disabled', false); | |
| 3275 | + $this.clone = $this.thead.clone(true); | |
| 3276 | + $this.cloneContainer.find('thead').remove(); | |
| 3277 | + $this.cloneContainer.children('table').append($this.clone); | |
| 3278 | + $this.thead.find('.ui-column-filter').prop('disabled', true); | |
| 3279 | + } | |
| 3280 | + }, | |
| 3281 | + containment: this.element | |
| 3282 | + }); | |
| 3283 | + }, | |
| 3284 | + | |
| 3285 | + resize: function(event, ui) { | |
| 3286 | + var columnHeader, nextColumnHeader, change = null, newWidth = null, nextColumnWidth = null, | |
| 3287 | + expandMode = (this.options.columnResizeMode === 'expand'), | |
| 3288 | + table = this.thead.parent(), | |
| 3289 | + columnHeader = ui.helper.parent(), | |
| 3290 | + nextColumnHeader = columnHeader.next(); | |
| 3291 | + | |
| 3292 | + change = (ui.position.left - ui.originalPosition.left), | |
| 3293 | + newWidth = (columnHeader.width() + change), | |
| 3294 | + nextColumnWidth = (nextColumnHeader.width() - change); | |
| 3295 | + | |
| 3296 | + if((newWidth > 15 && nextColumnWidth > 15) || (expandMode && newWidth > 15)) { | |
| 3297 | + if(expandMode) { | |
| 3298 | + table.width(table.width() + change); | |
| 3299 | + setTimeout(function() { | |
| 3300 | + columnHeader.width(newWidth); | |
| 3301 | + }, 1); | |
| 3302 | + } | |
| 3303 | + else { | |
| 3304 | + columnHeader.width(newWidth); | |
| 3305 | + nextColumnHeader.width(nextColumnWidth); | |
| 3306 | + } | |
| 3307 | + | |
| 3308 | + if(this.options.scrollable) { | |
| 3309 | + var cloneTable = this.theadClone.parent(), | |
| 3310 | + colIndex = columnHeader.index(); | |
| 3311 | + | |
| 3312 | + if(expandMode) { | |
| 3313 | + var $this = this; | |
| 3314 | + | |
| 3315 | + //body | |
| 3316 | + cloneTable.width(cloneTable.width() + change); | |
| 3317 | + | |
| 3318 | + //footer | |
| 3319 | + this.footerTable.width(this.footerTable.width() + change); | |
| 3320 | + | |
| 3321 | + setTimeout(function() { | |
| 3322 | + if($this.hasColumnGroup) { | |
| 3323 | + $this.theadClone.find('> tr:first').children('th').eq(colIndex).width(newWidth); //body | |
| 3324 | + $this.footerTable.find('> tfoot > tr:first').children('th').eq(colIndex).width(newWidth); //footer | |
| 3325 | + } | |
| 3326 | + else { | |
| 3327 | + $this.theadClone.find(PUI.escapeClientId(columnHeader.attr('id') + '_clone')).width(newWidth); //body | |
| 3328 | + $this.footerCols.eq(colIndex).width(newWidth); //footer | |
| 3329 | + } | |
| 3330 | + }, 1); | |
| 3331 | + } | |
| 3332 | + else { | |
| 3333 | + //body | |
| 3334 | + this.theadClone.find(PUI.escapeClientId(columnHeader.attr('id') + '_clone')).width(newWidth); | |
| 3335 | + this.theadClone.find(PUI.escapeClientId(nextColumnHeader.attr('id') + '_clone')).width(nextColumnWidth); | |
| 3336 | + | |
| 3337 | + //footer | |
| 3338 | + /*if(this.footerCols.length > 0) { | |
| 3339 | + var footerCol = this.footerCols.eq(colIndex), | |
| 3340 | + nextFooterCol = footerCol.next(); | |
| 3341 | + | |
| 3342 | + footerCol.width(newWidth); | |
| 3343 | + nextFooterCol.width(nextColumnWidth); | |
| 3344 | + }*/ | |
| 3345 | + } | |
| 3346 | + } | |
| 3347 | + } | |
| 3348 | + }, | |
| 3349 | + | |
| 3350 | + addResizers: function() { | |
| 3351 | + var resizableColumns = this.thead.find('> tr > th.ui-resizable-column'); | |
| 3352 | + resizableColumns.prepend('<span class="ui-column-resizer"> </span>'); | |
| 3353 | + | |
| 3354 | + if(this.options.columnResizeMode === 'fit') { | |
| 3355 | + resizableColumns.filter(':last-child').children('span.ui-column-resizer').hide(); | |
| 3356 | + } | |
| 3357 | + }, | |
| 3358 | + | |
| 3359 | + _initDraggableRows: function() { | |
| 3360 | + var $this = this; | |
| 3361 | + | |
| 3362 | + this.tbody.sortable({ | |
| 3363 | + placeholder: 'ui-datatable-rowordering ui-state-active', | |
| 3364 | + cursor: 'move', | |
| 3365 | + handle: 'td,span:not(.ui-c)', | |
| 3366 | + appendTo: document.body, | |
| 3367 | + helper: function(event, ui) { | |
| 3368 | + var cells = ui.children(), | |
| 3369 | + helper = $('<div class="ui-datatable ui-widget"><table><tbody></tbody></table></div>'), | |
| 3370 | + helperRow = ui.clone(), | |
| 3371 | + helperCells = helperRow.children(); | |
| 3372 | + | |
| 3373 | + for(var i = 0; i < helperCells.length; i++) { | |
| 3374 | + helperCells.eq(i).width(cells.eq(i).width()); | |
| 3375 | + } | |
| 3376 | + | |
| 3377 | + helperRow.appendTo(helper.find('tbody')); | |
| 3378 | + | |
| 3379 | + return helper; | |
| 3380 | + }, | |
| 3381 | + update: function(event, ui) { | |
| 3382 | + $this.syncRowParity(); | |
| 3383 | + | |
| 3384 | + $this._trigger('rowReorder', null, { | |
| 3385 | + fromIndex: ui.item.data('ri'), | |
| 3386 | + toIndex: $this._getFirst() + ui.item.index() | |
| 3387 | + }); | |
| 3388 | + }, | |
| 3389 | + change: function(event, ui) { | |
| 3390 | + if($this.options.scrollable) { | |
| 3391 | + PUI.scrollInView($this.scrollBody, ui.placeholder); | |
| 3392 | + } | |
| 3393 | + } | |
| 3394 | + }); | |
| 3395 | + }, | |
| 3396 | + | |
| 3397 | + syncRowParity: function() { | |
| 3398 | + var rows = this.tbody.children('tr.ui-widget-content'); | |
| 3399 | + | |
| 3400 | + for(var i = this._getFirst(); i < rows.length; i++) { | |
| 3401 | + var row = rows.eq(i); | |
| 3402 | + | |
| 3403 | + row.data('ri', i).removeClass('ui-datatable-even ui-datatable-odd'); | |
| 3404 | + | |
| 3405 | + if(i % 2 === 0) | |
| 3406 | + row.addClass('ui-datatable-even'); | |
| 3407 | + else | |
| 3408 | + row.addClass('ui-datatable-odd'); | |
| 3409 | + | |
| 3410 | + } | |
| 3411 | + }, | |
| 3412 | + | |
| 3413 | + getContextMenuSelection: function(data) { | |
| 3414 | + return this.dataSelectedByContextMenu; | |
| 3415 | + }, | |
| 3416 | + | |
| 3417 | + _initFiltering: function() { | |
| 3418 | + var $this = this; | |
| 3419 | + this.filterElements = this.thead.find('.ui-column-filter'); | |
| 3420 | + | |
| 3421 | + this.filterElements.on('keyup', function() { | |
| 3422 | + if($this.filterTimeout) { | |
| 3423 | + clearTimeout($this.filterTimeout); | |
| 3424 | + } | |
| 3425 | + | |
| 3426 | + $this.filterTimeout = setTimeout(function() { | |
| 3427 | + $this.filter(); | |
| 3428 | + $this.filterTimeout = null; | |
| 3429 | + }, | |
| 3430 | + $this.options.filterDelay); | |
| 3431 | + }); | |
| 3432 | + | |
| 3433 | + if(this.options.globalFilter) { | |
| 3434 | + $(this.options.globalFilter).on('keyup.puidatatable', function() { | |
| 3435 | + $this.filter(); | |
| 3436 | + }); | |
| 3437 | + } | |
| 3438 | + }, | |
| 3439 | + | |
| 3440 | + filter: function() { | |
| 3441 | + this.filterMetaMap = []; | |
| 3442 | + | |
| 3443 | + for(var i = 0; i < this.filterElements.length; i++) { | |
| 3444 | + var filterElement = this.filterElements.eq(i), | |
| 3445 | + filterElementValue = filterElement.val(); | |
| 3446 | + | |
| 3447 | + this.filterMetaMap.push({ | |
| 3448 | + field: filterElement.data('field'), | |
| 3449 | + filterMatchMode: filterElement.data('filtermatchmode'), | |
| 3450 | + value: filterElementValue.toLowerCase(), | |
| 3451 | + element: filterElement | |
| 3452 | + }); | |
| 3453 | + } | |
| 3454 | + | |
| 3455 | + if(this.options.lazy) { | |
| 3456 | + this.options.datasource.call(this, this._onLazyLoad, this._createStateMeta()); | |
| 3457 | + } | |
| 3458 | + else { | |
| 3459 | + var globalFilterValue = $(this.options.globalFilter).val(); | |
| 3460 | + this.filteredData = []; | |
| 3461 | + | |
| 3462 | + for(var i = 0; i < this.data.length; i++) { | |
| 3463 | + var localMatch = true; | |
| 3464 | + var globalMatch = false; | |
| 3465 | + | |
| 3466 | + for(var j = 0; j < this.filterMetaMap.length; j++) { | |
| 3467 | + var filterMeta = this.filterMetaMap[j], | |
| 3468 | + filterValue = filterMeta.value, | |
| 3469 | + filterField = filterMeta.field, | |
| 3470 | + dataFieldValue = this.data[i][filterField]; | |
| 3471 | + | |
| 3472 | + var filterConstraint = this.filterConstraints[filterMeta.filterMatchMode]; | |
| 3473 | + | |
| 3474 | + //global | |
| 3475 | + if(this.options.globalFilter && !globalMatch) { | |
| 3476 | + var filterConstraint = this.filterConstraints['contains']; | |
| 3477 | + globalMatch = filterConstraint(dataFieldValue, globalFilterValue); | |
| 3478 | + | |
| 3479 | + } | |
| 3480 | + | |
| 3481 | + //local | |
| 3482 | + if(filterMeta.filterMatchMode === 'custom') { | |
| 3483 | + localMatch = filterMeta.element.triggerHandler('filter', [dataFieldValue, filterValue]); | |
| 3484 | + } | |
| 3485 | + else { | |
| 3486 | + var filterConstraint = this.filterConstraints[filterMeta.filterMatchMode]; | |
| 3487 | + if(!filterConstraint(dataFieldValue, filterValue)) { | |
| 3488 | + localMatch = false; | |
| 3489 | + } | |
| 3490 | + } | |
| 3491 | + | |
| 3492 | + if(!localMatch) { | |
| 3493 | + break; | |
| 3494 | + } | |
| 3495 | + } | |
| 3496 | + | |
| 3497 | + var matches = localMatch; | |
| 3498 | + | |
| 3499 | + if(this.options.globalFilter) { | |
| 3500 | + matches = localMatch && globalMatch; | |
| 3501 | + } | |
| 3502 | + | |
| 3503 | + if(matches) { | |
| 3504 | + this.filteredData.push(this.data[i]); | |
| 3505 | + } | |
| 3506 | + } | |
| 3507 | + | |
| 3508 | + if(this.filteredData.length === this.data.length) { | |
| 3509 | + this.filteredData = null; | |
| 3510 | + } | |
| 3511 | + | |
| 3512 | + if(this.paginator) { | |
| 3513 | + this.paginator.puipaginator('option', 'totalRecords', this.filteredData ? this.filteredData.length : this.data ? this.data.length : 0); | |
| 3514 | + } | |
| 3515 | + | |
| 3516 | + this._renderData(); | |
| 3517 | + } | |
| 3518 | + }, | |
| 3519 | + | |
| 3520 | + filterConstraints: { | |
| 3521 | + | |
| 3522 | + startsWith: function(value, filter) { | |
| 3523 | + if(filter === undefined || filter === null || $.trim(filter) === '') { | |
| 3524 | + return true; | |
| 3525 | + } | |
| 3526 | + | |
| 3527 | + if(value === undefined || value === null) { | |
| 3528 | + return false; | |
| 3529 | + } | |
| 3530 | + | |
| 3531 | + return value.toString().toLowerCase().slice(0, filter.length) === filter; | |
| 3532 | + }, | |
| 3533 | + | |
| 3534 | + contains: function(value, filter) { | |
| 3535 | + if(filter === undefined || filter === null || $.trim(filter) === '') { | |
| 3536 | + return true; | |
| 3537 | + } | |
| 3538 | + | |
| 3539 | + if(value === undefined || value === null) { | |
| 3540 | + return false; | |
| 3541 | + } | |
| 3542 | + | |
| 3543 | + return value.toString().toLowerCase().indexOf(filter) !== -1; | |
| 3544 | + } | |
| 3545 | + | |
| 3546 | + }, | |
| 3547 | + | |
| 3548 | + _initStickyHeader: function() { | |
| 3549 | + var table = this.thead.parent(), | |
| 3550 | + offset = table.offset(), | |
| 3551 | + win = $(window), | |
| 3552 | + $this = this, | |
| 3553 | + stickyNS = 'scroll.' + this.id, | |
| 3554 | + resizeNS = 'resize.sticky-' + this.id; | |
| 3555 | + | |
| 3556 | + this.cloneContainer = $('<div class="ui-datatable ui-datatable-sticky ui-widget"><table></table></div>'); | |
| 3557 | + this.clone = this.thead.clone(true); | |
| 3558 | + this.cloneContainer.children('table').append(this.clone); | |
| 3559 | + | |
| 3560 | + this.cloneContainer.css({ | |
| 3561 | + position: 'absolute', | |
| 3562 | + width: table.outerWidth(), | |
| 3563 | + top: offset.top, | |
| 3564 | + left: offset.left, | |
| 3565 | + 'z-index': ++PUI.zindex | |
| 3566 | + }) | |
| 3567 | + .appendTo(this.element); | |
| 3568 | + | |
| 3569 | + win.off(stickyNS).on(stickyNS, function() { | |
| 3570 | + var scrollTop = win.scrollTop(), | |
| 3571 | + tableOffset = table.offset(); | |
| 3572 | + | |
| 3573 | + if(scrollTop > tableOffset.top) { | |
| 3574 | + $this.cloneContainer.css({ | |
| 3575 | + 'position': 'fixed', | |
| 3576 | + 'top': '0px' | |
| 3577 | + }) | |
| 3578 | + .addClass('ui-shadow ui-sticky'); | |
| 3579 | + | |
| 3580 | + if(scrollTop >= (tableOffset.top + $this.tbody.height())) | |
| 3581 | + $this.cloneContainer.hide(); | |
| 3582 | + else | |
| 3583 | + $this.cloneContainer.show(); | |
| 3584 | + } | |
| 3585 | + else { | |
| 3586 | + $this.cloneContainer.css({ | |
| 3587 | + 'position': 'absolute', | |
| 3588 | + 'top': tableOffset.top | |
| 3589 | + }) | |
| 3590 | + .removeClass('ui-shadow ui-sticky'); | |
| 3591 | + } | |
| 3592 | + }) | |
| 3593 | + .off(resizeNS).on(resizeNS, function() { | |
| 3594 | + $this.cloneContainer.width(table.outerWidth()); | |
| 3595 | + }); | |
| 3596 | + | |
| 3597 | + //filter support | |
| 3598 | + this.thead.find('.ui-column-filter').prop('disabled', true); | |
| 3599 | + }, | |
| 3600 | + | |
| 3601 | + _initEditing: function() { | |
| 3602 | + var cellSelector = '> tr > td.ui-editable-column', | |
| 3603 | + $this = this; | |
| 3604 | + | |
| 3605 | + this.tbody.off('click', cellSelector) | |
| 3606 | + .on('click', cellSelector, null, function(e) { | |
| 3607 | + var cell = $(this); | |
| 3608 | + if(!cell.hasClass('ui-cell-editing')) { | |
| 3609 | + $this._showCellEditor(cell); | |
| 3610 | + e.stopPropagation(); | |
| 3611 | + } | |
| 3612 | + }); | |
| 3613 | + }, | |
| 3614 | + | |
| 3615 | + _showCellEditor: function(cell) { | |
| 3616 | + var editor = this.editors[cell.data('editor')].call(), | |
| 3617 | + $this = this; | |
| 3618 | + | |
| 3619 | + editor.val(cell.data('rowdata')[cell.data('field')]); | |
| 3620 | + | |
| 3621 | + cell.addClass('ui-cell-editing').html('').append(editor); | |
| 3622 | + | |
| 3623 | + editor.focus().on('change', function() { | |
| 3624 | + $this._onCellEditorChange(cell); | |
| 3625 | + }) | |
| 3626 | + .on('blur', function() { | |
| 3627 | + $this._onCellEditorBlur(cell); | |
| 3628 | + }) | |
| 3629 | + .on('keydown', function(e) { | |
| 3630 | + var key = e.which, | |
| 3631 | + keyCode = $.ui.keyCode; | |
| 3632 | + | |
| 3633 | + if((key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER)) { | |
| 3634 | + $(this).trigger('change').trigger('blur'); | |
| 3635 | + e.preventDefault(); | |
| 3636 | + } | |
| 3637 | + else if(key === keyCode.TAB) { | |
| 3638 | + if(e.shiftKey) { | |
| 3639 | + var prevCell = cell.prevAll('td.ui-editable-column').eq(0); | |
| 3640 | + if(!prevCell.length) { | |
| 3641 | + prevCell = cell.parent().prev('tr').children('td.ui-editable-column:last'); | |
| 3642 | + } | |
| 3643 | + if(prevCell.length) { | |
| 3644 | + $this._showCellEditor(prevCell); | |
| 3645 | + } | |
| 3646 | + } | |
| 3647 | + else { | |
| 3648 | + var nextCell = cell.nextAll('td.ui-editable-column').eq(0); | |
| 3649 | + if(!nextCell.length) { | |
| 3650 | + nextCell = cell.parent().next('tr').children('td.ui-editable-column').eq(0); | |
| 3651 | + } | |
| 3652 | + if(nextCell.length) { | |
| 3653 | + $this._showCellEditor(nextCell); | |
| 3654 | + } | |
| 3655 | + } | |
| 3656 | + | |
| 3657 | + e.preventDefault(); | |
| 3658 | + } else if(key === keyCode.ESCAPE) { | |
| 3659 | + $this._onCellEditorBlur(cell); | |
| 3660 | + } | |
| 3661 | + | |
| 3662 | + }); | |
| 3663 | + }, | |
| 3664 | + | |
| 3665 | + _onCellEditorChange: function(cell) { | |
| 3666 | + var newCellValue = cell.children('.ui-cell-editor').val(); | |
| 3667 | + | |
| 3668 | + var retVal = this._trigger('cellEdit', null, { | |
| 3669 | + oldValue: cell.data('rowdata')[cell.data('field')], | |
| 3670 | + newValue: newCellValue, | |
| 3671 | + data: cell.data('rowdata'), | |
| 3672 | + field: cell.data('field') | |
| 3673 | + }); | |
| 3674 | + | |
| 3675 | + if(retVal !== false) { | |
| 3676 | + cell.data('rowdata')[cell.data('field')] = newCellValue; | |
| 3677 | + } | |
| 3678 | + }, | |
| 3679 | + | |
| 3680 | + _onCellEditorBlur: function(cell) { | |
| 3681 | + cell.removeClass('ui-cell-editing').text(cell.data('rowdata')[cell.data('field')]) | |
| 3682 | + .children('.ui-cell-editor').remove(); | |
| 3683 | + }, | |
| 3684 | + | |
| 3685 | + reload: function() { | |
| 3686 | + this._updateDatasource(this.options.datasource); | |
| 3687 | + }, | |
| 3688 | + | |
| 3689 | + getPaginator: function() { | |
| 3690 | + return this.paginator; | |
| 3691 | + }, | |
| 3692 | + | |
| 3693 | + setTotalRecords: function(val) { | |
| 3694 | + this.paginator.puipaginator('option','totalRecords', val); | |
| 3695 | + }, | |
| 3696 | + | |
| 3697 | + _createFilterMap: function() { | |
| 3698 | + var filters = null; | |
| 3699 | + if(this.filterElements) { | |
| 3700 | + filters = {}; | |
| 3701 | + for(var i = 0; i < this.filterElements.length; i++) { | |
| 3702 | + var filterElement = this.filterElements.eq(i), | |
| 3703 | + value = filterElement.val(); | |
| 3704 | + if($.trim(value).length) { | |
| 3705 | + filters[filterElement.data('field')] = value; | |
| 3706 | + } | |
| 3707 | + } | |
| 3708 | + } | |
| 3709 | + | |
| 3710 | + return filters; | |
| 3711 | + }, | |
| 3712 | + | |
| 3713 | + editors: { | |
| 3714 | + | |
| 3715 | + 'input': function() { | |
| 3716 | + return $('<input type="text" class="ui-cell-editor"/>'); | |
| 3717 | + } | |
| 3718 | + } | |
| 3719 | + | |
| 3720 | + }); | |
| 3721 | +})(); | |
| 3722 | + | |
| 3723 | +/** | |
| 3724 | + * PrimeUI Dialog Widget | |
| 3725 | + */ | |
| 3726 | +(function() { | |
| 3727 | + | |
| 3728 | + $.widget("primeui.puidialog", { | |
| 3729 | + | |
| 3730 | + options: { | |
| 3731 | + draggable: true, | |
| 3732 | + resizable: true, | |
| 3733 | + location: 'center', | |
| 3734 | + minWidth: 150, | |
| 3735 | + minHeight: 25, | |
| 3736 | + height: 'auto', | |
| 3737 | + width: '300px', | |
| 3738 | + visible: false, | |
| 3739 | + modal: false, | |
| 3740 | + showEffect: null, | |
| 3741 | + hideEffect: null, | |
| 3742 | + effectOptions: {}, | |
| 3743 | + effectSpeed: 'normal', | |
| 3744 | + closeOnEscape: true, | |
| 3745 | + rtl: false, | |
| 3746 | + closable: true, | |
| 3747 | + minimizable: false, | |
| 3748 | + maximizable: false, | |
| 3749 | + appendTo: null, | |
| 3750 | + buttons: null, | |
| 3751 | + responsive: false, | |
| 3752 | + title: null, | |
| 3753 | + enhanced: false | |
| 3754 | + }, | |
| 3755 | + | |
| 3756 | + _create: function() { | |
| 3757 | + this.id = this.element.attr('id'); | |
| 3758 | + if(!this.id) { | |
| 3759 | + this.id = this.element.uniqueId().attr('id'); | |
| 3760 | + } | |
| 3761 | + | |
| 3762 | + //container | |
| 3763 | + if(!this.options.enhanced) { | |
| 3764 | + this.element.addClass('ui-dialog ui-widget ui-widget-content ui-helper-hidden ui-corner-all ui-shadow') | |
| 3765 | + .contents().wrapAll('<div class="ui-dialog-content ui-widget-content" />'); | |
| 3766 | + | |
| 3767 | + //header | |
| 3768 | + var title = this.options.title||this.element.attr('title'); | |
| 3769 | + this.element.prepend('<div class="ui-dialog-titlebar ui-widget-header ui-helper-clearfix ui-corner-top">' + | |
| 3770 | + '<span id="' + this.element.attr('id') + '_label" class="ui-dialog-title">' + title + '</span>') | |
| 3771 | + .removeAttr('title'); | |
| 3772 | + | |
| 3773 | + //footer | |
| 3774 | + if(this.options.buttons) { | |
| 3775 | + this.footer = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"></div>').appendTo(this.element); | |
| 3776 | + for(var i = 0; i < this.options.buttons.length; i++) { | |
| 3777 | + var buttonMeta = this.options.buttons[i], | |
| 3778 | + button = $('<button type="button"></button>').appendTo(this.footer); | |
| 3779 | + if(buttonMeta.text) { | |
| 3780 | + button.text(buttonMeta.text); | |
| 3781 | + } | |
| 3782 | + | |
| 3783 | + button.puibutton(buttonMeta); | |
| 3784 | + } | |
| 3785 | + } | |
| 3786 | + | |
| 3787 | + if(this.options.rtl) { | |
| 3788 | + this.element.addClass('ui-dialog-rtl'); | |
| 3789 | + } | |
| 3790 | + } | |
| 3791 | + | |
| 3792 | + //elements | |
| 3793 | + this.content = this.element.children('.ui-dialog-content'); | |
| 3794 | + this.titlebar = this.element.children('.ui-dialog-titlebar'); | |
| 3795 | + | |
| 3796 | + if(!this.options.enhanced) { | |
| 3797 | + if(this.options.closable) { | |
| 3798 | + this._renderHeaderIcon('ui-dialog-titlebar-close', 'fa-close'); | |
| 3799 | + } | |
| 3800 | + | |
| 3801 | + if(this.options.maximizable) { | |
| 3802 | + this._renderHeaderIcon('ui-dialog-titlebar-maximize', 'fa-sort'); | |
| 3803 | + } | |
| 3804 | + | |
| 3805 | + if(this.options.minimizable) { | |
| 3806 | + this._renderHeaderIcon('ui-dialog-titlebar-minimize', 'fa-minus'); | |
| 3807 | + } | |
| 3808 | + } | |
| 3809 | + | |
| 3810 | + //icons | |
| 3811 | + this.icons = this.titlebar.children('.ui-dialog-titlebar-icon'); | |
| 3812 | + this.closeIcon = this.titlebar.children('.ui-dialog-titlebar-close'); | |
| 3813 | + this.minimizeIcon = this.titlebar.children('.ui-dialog-titlebar-minimize'); | |
| 3814 | + this.maximizeIcon = this.titlebar.children('.ui-dialog-titlebar-maximize'); | |
| 3815 | + | |
| 3816 | + this.blockEvents = 'focus.puidialog mousedown.puidialog mouseup.puidialog keydown.puidialog keyup.puidialog'; | |
| 3817 | + this.parent = this.element.parent(); | |
| 3818 | + | |
| 3819 | + //size | |
| 3820 | + this.element.css({'width': this.options.width, 'height': 'auto'}); | |
| 3821 | + this.content.height(this.options.height); | |
| 3822 | + | |
| 3823 | + //events | |
| 3824 | + this._bindEvents(); | |
| 3825 | + | |
| 3826 | + if(this.options.draggable) { | |
| 3827 | + this._setupDraggable(); | |
| 3828 | + } | |
| 3829 | + | |
| 3830 | + if(this.options.resizable) { | |
| 3831 | + this._setupResizable(); | |
| 3832 | + } | |
| 3833 | + | |
| 3834 | + if(this.options.appendTo) { | |
| 3835 | + this.element.appendTo(this.options.appendTo); | |
| 3836 | + } | |
| 3837 | + | |
| 3838 | + if(this.options.responsive) { | |
| 3839 | + this.resizeNS = 'resize.' + this.id; | |
| 3840 | + } | |
| 3841 | + | |
| 3842 | + //docking zone | |
| 3843 | + if($(document.body).children('.ui-dialog-docking-zone').length === 0) { | |
| 3844 | + $(document.body).append('<div class="ui-dialog-docking-zone"></div>'); | |
| 3845 | + } | |
| 3846 | + | |
| 3847 | + //aria | |
| 3848 | + this._applyARIA(); | |
| 3849 | + | |
| 3850 | + if(this.options.visible) { | |
| 3851 | + this.show(); | |
| 3852 | + } | |
| 3853 | + }, | |
| 3854 | + | |
| 3855 | + _destroy: function() { | |
| 3856 | + //restore dom | |
| 3857 | + if(!this.options.enhanced) { | |
| 3858 | + this.element.removeClass('ui-dialog ui-widget ui-widget-content ui-helper-hidden ui-corner-all ui-shadow'); | |
| 3859 | + | |
| 3860 | + if(this.options.buttons) { | |
| 3861 | + this.footer.children('button').puibutton('destroy'); | |
| 3862 | + this.footer.remove(); | |
| 3863 | + } | |
| 3864 | + | |
| 3865 | + if(this.options.rtl) { | |
| 3866 | + this.element.removeClass('ui-dialog-rtl'); | |
| 3867 | + } | |
| 3868 | + | |
| 3869 | + var title = this.titlebar.children('.ui-dialog-title').text()||this.options.title; | |
| 3870 | + if(title) { | |
| 3871 | + this.element.attr('title', title); | |
| 3872 | + } | |
| 3873 | + this.titlebar.remove(); | |
| 3874 | + | |
| 3875 | + this.content.contents().unwrap(); | |
| 3876 | + } | |
| 3877 | + | |
| 3878 | + //remove events | |
| 3879 | + this._unbindEvents(); | |
| 3880 | + | |
| 3881 | + if(this.options.draggable) { | |
| 3882 | + this.element.draggable('destroy'); | |
| 3883 | + } | |
| 3884 | + | |
| 3885 | + if(this.options.resizable) { | |
| 3886 | + this.element.resizable('destroy'); | |
| 3887 | + } | |
| 3888 | + | |
| 3889 | + if(this.options.appendTo) { | |
| 3890 | + this.element.appendTo(this.parent); | |
| 3891 | + } | |
| 3892 | + | |
| 3893 | + this._unbindResizeListener(); | |
| 3894 | + | |
| 3895 | + if(this.options.modal) { | |
| 3896 | + this._disableModality(); | |
| 3897 | + } | |
| 3898 | + | |
| 3899 | + this._removeARIA(); | |
| 3900 | + this.element.css({ | |
| 3901 | + 'width': 'auto', | |
| 3902 | + 'height': 'auto' | |
| 3903 | + }); | |
| 3904 | + }, | |
| 3905 | + | |
| 3906 | + _renderHeaderIcon: function(styleClass, icon) { | |
| 3907 | + this.titlebar.append('<a class="ui-dialog-titlebar-icon ' + styleClass + ' ui-corner-all" href="#" role="button">' + | |
| 3908 | + '<span class="fa fa-fw ' + icon + '"></span></a>'); | |
| 3909 | + }, | |
| 3910 | + | |
| 3911 | + _enableModality: function() { | |
| 3912 | + var $this = this, | |
| 3913 | + doc = $(document); | |
| 3914 | + | |
| 3915 | + this.modality = $('<div id="' + this.element.attr('id') + '_modal" class="ui-widget-overlay ui-dialog-mask"></div>').appendTo(document.body) | |
| 3916 | + .css('z-index', this.element.css('z-index') - 1); | |
| 3917 | + | |
| 3918 | + //Disable tabbing out of modal dialog and stop events from targets outside of dialog | |
| 3919 | + doc.on('keydown.puidialog', | |
| 3920 | + function(event) { | |
| 3921 | + if(event.keyCode == $.ui.keyCode.TAB) { | |
| 3922 | + var tabbables = $this.content.find(':tabbable'), | |
| 3923 | + first = tabbables.filter(':first'), | |
| 3924 | + last = tabbables.filter(':last'); | |
| 3925 | + | |
| 3926 | + if(event.target === last[0] && !event.shiftKey) { | |
| 3927 | + first.focus(1); | |
| 3928 | + return false; | |
| 3929 | + } | |
| 3930 | + else if (event.target === first[0] && event.shiftKey) { | |
| 3931 | + last.focus(1); | |
| 3932 | + return false; | |
| 3933 | + } | |
| 3934 | + } | |
| 3935 | + }) | |
| 3936 | + .bind(this.blockEvents, function(event) { | |
| 3937 | + if ($(event.target).zIndex() < $this.element.zIndex()) { | |
| 3938 | + return false; | |
| 3939 | + } | |
| 3940 | + }); | |
| 3941 | + }, | |
| 3942 | + | |
| 3943 | + _disableModality: function() { | |
| 3944 | + if(this.modality) { | |
| 3945 | + this.modality.remove(); | |
| 3946 | + this.modality = null; | |
| 3947 | + } | |
| 3948 | + | |
| 3949 | + $(document).off(this.blockEvents).off('keydown.dialog'); | |
| 3950 | + }, | |
| 3951 | + | |
| 3952 | + show: function() { | |
| 3953 | + if(this.element.is(':visible')) { | |
| 3954 | + return; | |
| 3955 | + } | |
| 3956 | + | |
| 3957 | + if(!this.positionInitialized) { | |
| 3958 | + this._initPosition(); | |
| 3959 | + } | |
| 3960 | + | |
| 3961 | + this._trigger('beforeShow', null); | |
| 3962 | + | |
| 3963 | + if(this.options.showEffect) { | |
| 3964 | + var $this = this; | |
| 3965 | + | |
| 3966 | + this.element.show(this.options.showEffect, this.options.effectOptions, this.options.effectSpeed, function() { | |
| 3967 | + $this._postShow(); | |
| 3968 | + }); | |
| 3969 | + } | |
| 3970 | + else { | |
| 3971 | + this.element.show(); | |
| 3972 | + | |
| 3973 | + this._postShow(); | |
| 3974 | + } | |
| 3975 | + | |
| 3976 | + this._moveToTop(); | |
| 3977 | + | |
| 3978 | + if(this.options.modal) { | |
| 3979 | + this._enableModality(); | |
| 3980 | + } | |
| 3981 | + }, | |
| 3982 | + | |
| 3983 | + _postShow: function() { | |
| 3984 | + //execute user defined callback | |
| 3985 | + this._trigger('afterShow', null); | |
| 3986 | + | |
| 3987 | + this.element.attr({ | |
| 3988 | + 'aria-hidden': false, | |
| 3989 | + 'aria-live': 'polite' | |
| 3990 | + }); | |
| 3991 | + | |
| 3992 | + this._applyFocus(); | |
| 3993 | + | |
| 3994 | + if(this.options.responsive) { | |
| 3995 | + this._bindResizeListener(); | |
| 3996 | + } | |
| 3997 | + }, | |
| 3998 | + | |
| 3999 | + hide: function() { | |
| 4000 | + if(this.element.is(':hidden')) { | |
| 4001 | + return; | |
| 4002 | + } | |
| 4003 | + | |
| 4004 | + this._trigger('beforeHide', null); | |
| 4005 | + | |
| 4006 | + if(this.options.hideEffect) { | |
| 4007 | + var _self = this; | |
| 4008 | + | |
| 4009 | + this.element.hide(this.options.hideEffect, this.options.effectOptions, this.options.effectSpeed, function() { | |
| 4010 | + _self._postHide(); | |
| 4011 | + }); | |
| 4012 | + } | |
| 4013 | + else { | |
| 4014 | + this.element.hide(); | |
| 4015 | + | |
| 4016 | + this._postHide(); | |
| 4017 | + } | |
| 4018 | + | |
| 4019 | + if(this.options.modal) { | |
| 4020 | + this._disableModality(); | |
| 4021 | + } | |
| 4022 | + }, | |
| 4023 | + | |
| 4024 | + _postHide: function() { | |
| 4025 | + //execute user defined callback | |
| 4026 | + this._trigger('afterHide', null); | |
| 4027 | + | |
| 4028 | + this.element.attr({ | |
| 4029 | + 'aria-hidden': true, | |
| 4030 | + 'aria-live': 'off' | |
| 4031 | + }); | |
| 4032 | + | |
| 4033 | + if(this.options.responsive) { | |
| 4034 | + this._unbindResizeListener(); | |
| 4035 | + } | |
| 4036 | + }, | |
| 4037 | + | |
| 4038 | + _applyFocus: function() { | |
| 4039 | + this.element.find(':not(:submit):not(:button):input:visible:enabled:first').focus(); | |
| 4040 | + }, | |
| 4041 | + | |
| 4042 | + _bindEvents: function() { | |
| 4043 | + var $this = this; | |
| 4044 | + this.element.on('mousedown.puidialog', function(e) { | |
| 4045 | + if(!$(e.target).data('ui-widget-overlay')) { | |
| 4046 | + $this._moveToTop(); | |
| 4047 | + } | |
| 4048 | + }); | |
| 4049 | + | |
| 4050 | + this.icons.mouseover(function() { | |
| 4051 | + $(this).addClass('ui-state-hover'); | |
| 4052 | + }).mouseout(function() { | |
| 4053 | + $(this).removeClass('ui-state-hover'); | |
| 4054 | + }); | |
| 4055 | + | |
| 4056 | + this.closeIcon.on('click.puidialog', function(e) { | |
| 4057 | + $this.hide(); | |
| 4058 | + $this._trigger('clickClose'); | |
| 4059 | + e.preventDefault(); | |
| 4060 | + }); | |
| 4061 | + | |
| 4062 | + this.maximizeIcon.click(function(e) { | |
| 4063 | + $this.toggleMaximize(); | |
| 4064 | + e.preventDefault(); | |
| 4065 | + }); | |
| 4066 | + | |
| 4067 | + this.minimizeIcon.click(function(e) { | |
| 4068 | + $this.toggleMinimize(); | |
| 4069 | + e.preventDefault(); | |
| 4070 | + }); | |
| 4071 | + | |
| 4072 | + if(this.options.closeOnEscape) { | |
| 4073 | + $(document).on('keydown.dialog_' + this.id, function(e) { | |
| 4074 | + var keyCode = $.ui.keyCode, | |
| 4075 | + active = parseInt($this.element.css('z-index'), 10) === PUI.zindex; | |
| 4076 | + | |
| 4077 | + if(e.which === keyCode.ESCAPE && $this.element.is(':visible') && active) { | |
| 4078 | + $this.hide(); | |
| 4079 | + $this._trigger('hideWithEscape'); | |
| 4080 | + } | |
| 4081 | + }); | |
| 4082 | + } | |
| 4083 | + }, | |
| 4084 | + | |
| 4085 | + _unbindEvents: function() { | |
| 4086 | + this.element.off('mousedown.puidialog'); | |
| 4087 | + this.icons.off(); | |
| 4088 | + $(document).off('keydown.dialog_' + this.id); | |
| 4089 | + }, | |
| 4090 | + | |
| 4091 | + _setupDraggable: function() { | |
| 4092 | + this.element.draggable({ | |
| 4093 | + cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', | |
| 4094 | + handle: '.ui-dialog-titlebar', | |
| 4095 | + containment : 'document' | |
| 4096 | + }); | |
| 4097 | + }, | |
| 4098 | + | |
| 4099 | + _setupResizable: function() { | |
| 4100 | + var $this = this; | |
| 4101 | + | |
| 4102 | + this.element.resizable({ | |
| 4103 | + minWidth : this.options.minWidth, | |
| 4104 | + minHeight : this.options.minHeight, | |
| 4105 | + alsoResize : this.content, | |
| 4106 | + containment: 'document', | |
| 4107 | + start: function(event, ui) { | |
| 4108 | + $this.element.data('offset', $this.element.offset()); | |
| 4109 | + }, | |
| 4110 | + stop: function(event, ui) { | |
| 4111 | + var offset = $this.element.data('offset'); | |
| 4112 | + | |
| 4113 | + $this.element.css('position', 'fixed'); | |
| 4114 | + $this.element.offset(offset); | |
| 4115 | + } | |
| 4116 | + }); | |
| 4117 | + | |
| 4118 | + this.resizers = this.element.children('.ui-resizable-handle'); | |
| 4119 | + }, | |
| 4120 | + | |
| 4121 | + _initPosition: function() { | |
| 4122 | + //reset | |
| 4123 | + this.element.css({left:0,top:0}); | |
| 4124 | + | |
| 4125 | + if(/(center|left|top|right|bottom)/.test(this.options.location)) { | |
| 4126 | + this.options.location = this.options.location.replace(',', ' '); | |
| 4127 | + | |
| 4128 | + this.element.position({ | |
| 4129 | + my: 'center', | |
| 4130 | + at: this.options.location, | |
| 4131 | + collision: 'fit', | |
| 4132 | + of: window, | |
| 4133 | + //make sure dialog stays in viewport | |
| 4134 | + using: function(pos) { | |
| 4135 | + var l = pos.left < 0 ? 0 : pos.left, | |
| 4136 | + t = pos.top < 0 ? 0 : pos.top; | |
| 4137 | + | |
| 4138 | + $(this).css({ | |
| 4139 | + left: l, | |
| 4140 | + top: t | |
| 4141 | + }); | |
| 4142 | + } | |
| 4143 | + }); | |
| 4144 | + } | |
| 4145 | + else { | |
| 4146 | + var coords = this.options.position.split(','), | |
| 4147 | + x = $.trim(coords[0]), | |
| 4148 | + y = $.trim(coords[1]); | |
| 4149 | + | |
| 4150 | + this.element.offset({ | |
| 4151 | + left: x, | |
| 4152 | + top: y | |
| 4153 | + }); | |
| 4154 | + } | |
| 4155 | + | |
| 4156 | + this.positionInitialized = true; | |
| 4157 | + }, | |
| 4158 | + | |
| 4159 | + _moveToTop: function() { | |
| 4160 | + this.element.css('z-index',++PUI.zindex); | |
| 4161 | + }, | |
| 4162 | + | |
| 4163 | + toggleMaximize: function() { | |
| 4164 | + if(this.minimized) { | |
| 4165 | + this.toggleMinimize(); | |
| 4166 | + } | |
| 4167 | + | |
| 4168 | + if(this.maximized) { | |
| 4169 | + this.element.removeClass('ui-dialog-maximized'); | |
| 4170 | + this._restoreState(); | |
| 4171 | + | |
| 4172 | + this.maximizeIcon.removeClass('ui-state-hover'); | |
| 4173 | + this.maximized = false; | |
| 4174 | + } | |
| 4175 | + else { | |
| 4176 | + this._saveState(); | |
| 4177 | + | |
| 4178 | + var win = $(window); | |
| 4179 | + | |
| 4180 | + this.element.addClass('ui-dialog-maximized').css({ | |
| 4181 | + 'width': win.width() - 6, | |
| 4182 | + 'height': win.height() | |
| 4183 | + }).offset({ | |
| 4184 | + top: win.scrollTop(), | |
| 4185 | + left: win.scrollLeft() | |
| 4186 | + }); | |
| 4187 | + | |
| 4188 | + //maximize content | |
| 4189 | + this.content.css({ | |
| 4190 | + width: 'auto', | |
| 4191 | + height: 'auto' | |
| 4192 | + }); | |
| 4193 | + | |
| 4194 | + this.maximizeIcon.removeClass('ui-state-hover'); | |
| 4195 | + this.maximized = true; | |
| 4196 | + this._trigger('maximize'); | |
| 4197 | + } | |
| 4198 | + }, | |
| 4199 | + | |
| 4200 | + toggleMinimize: function() { | |
| 4201 | + var animate = true, | |
| 4202 | + dockingZone = $(document.body).children('.ui-dialog-docking-zone'); | |
| 4203 | + | |
| 4204 | + if(this.maximized) { | |
| 4205 | + this.toggleMaximize(); | |
| 4206 | + animate = false; | |
| 4207 | + } | |
| 4208 | + | |
| 4209 | + var $this = this; | |
| 4210 | + | |
| 4211 | + if(this.minimized) { | |
| 4212 | + this.element.appendTo(this.parent).removeClass('ui-dialog-minimized').css({'position':'fixed', 'float':'none'}); | |
| 4213 | + this._restoreState(); | |
| 4214 | + this.content.show(); | |
| 4215 | + this.minimizeIcon.removeClass('ui-state-hover').children('.fa').removeClass('fa-plus').addClass('fa-minus'); | |
| 4216 | + this.minimized = false; | |
| 4217 | + | |
| 4218 | + if(this.options.resizable) { | |
| 4219 | + this.resizers.show(); | |
| 4220 | + } | |
| 4221 | + | |
| 4222 | + if(this.footer) { | |
| 4223 | + this.footer.show(); | |
| 4224 | + } | |
| 4225 | + } | |
| 4226 | + else { | |
| 4227 | + this._saveState(); | |
| 4228 | + | |
| 4229 | + if(animate) { | |
| 4230 | + this.element.effect('transfer', { | |
| 4231 | + to: dockingZone, | |
| 4232 | + className: 'ui-dialog-minimizing' | |
| 4233 | + }, 500, | |
| 4234 | + function() { | |
| 4235 | + $this._dock(dockingZone); | |
| 4236 | + $this.element.addClass('ui-dialog-minimized'); | |
| 4237 | + }); | |
| 4238 | + } | |
| 4239 | + else { | |
| 4240 | + this._dock(dockingZone); | |
| 4241 | + } | |
| 4242 | + } | |
| 4243 | + }, | |
| 4244 | + | |
| 4245 | + _dock: function(zone) { | |
| 4246 | + this.element.appendTo(zone).css('position', 'static'); | |
| 4247 | + this.element.css({'height':'auto', 'width':'auto', 'float': 'left'}); | |
| 4248 | + this.content.hide(); | |
| 4249 | + this.minimizeIcon.removeClass('ui-state-hover').children('.fa').removeClass('fa-minus').addClass('fa-plus'); | |
| 4250 | + this.minimized = true; | |
| 4251 | + | |
| 4252 | + if(this.options.resizable) { | |
| 4253 | + this.resizers.hide(); | |
| 4254 | + } | |
| 4255 | + | |
| 4256 | + if(this.footer) { | |
| 4257 | + this.footer.hide(); | |
| 4258 | + } | |
| 4259 | + | |
| 4260 | + zone.css('z-index',++PUI.zindex); | |
| 4261 | + | |
| 4262 | + this._trigger('minimize'); | |
| 4263 | + }, | |
| 4264 | + | |
| 4265 | + _saveState: function() { | |
| 4266 | + this.state = { | |
| 4267 | + width: this.element.width(), | |
| 4268 | + height: this.element.height() | |
| 4269 | + }; | |
| 4270 | + | |
| 4271 | + var win = $(window); | |
| 4272 | + this.state.offset = this.element.offset(); | |
| 4273 | + this.state.windowScrollLeft = win.scrollLeft(); | |
| 4274 | + this.state.windowScrollTop = win.scrollTop(); | |
| 4275 | + }, | |
| 4276 | + | |
| 4277 | + _restoreState: function() { | |
| 4278 | + this.element.width(this.state.width).height(this.state.height); | |
| 4279 | + | |
| 4280 | + var win = $(window); | |
| 4281 | + this.element.offset({ | |
| 4282 | + top: this.state.offset.top + (win.scrollTop() - this.state.windowScrollTop), | |
| 4283 | + left: this.state.offset.left + (win.scrollLeft() - this.state.windowScrollLeft) | |
| 4284 | + }); | |
| 4285 | + }, | |
| 4286 | + | |
| 4287 | + _applyARIA: function() { | |
| 4288 | + this.element.attr({ | |
| 4289 | + 'role': 'dialog', | |
| 4290 | + 'aria-labelledby': this.element.attr('id') + '_title', | |
| 4291 | + 'aria-hidden': !this.options.visible | |
| 4292 | + }); | |
| 4293 | + | |
| 4294 | + this.titlebar.children('a.ui-dialog-titlebar-icon').attr('role', 'button'); | |
| 4295 | + }, | |
| 4296 | + | |
| 4297 | + _removeARIA: function() { | |
| 4298 | + this.element.removeAttr('role').removeAttr('aria-labelledby').removeAttr('aria-hidden') | |
| 4299 | + .removeAttr('aria-live').removeAttr('aria-hidden'); | |
| 4300 | + }, | |
| 4301 | + | |
| 4302 | + _bindResizeListener: function() { | |
| 4303 | + var $this = this; | |
| 4304 | + $(window).on(this.resizeNS, function(e) { | |
| 4305 | + if(e.target === window) { | |
| 4306 | + $this._initPosition(); | |
| 4307 | + } | |
| 4308 | + }); | |
| 4309 | + }, | |
| 4310 | + | |
| 4311 | + _unbindResizeListener: function() { | |
| 4312 | + $(window).off(this.resizeNS); | |
| 4313 | + }, | |
| 4314 | + | |
| 4315 | + _setOption: function(key, value) { | |
| 4316 | + if(key === 'visible') { | |
| 4317 | + if(value) | |
| 4318 | + this.show(); | |
| 4319 | + else | |
| 4320 | + this.hide(); | |
| 4321 | + } | |
| 4322 | + else { | |
| 4323 | + $.Widget.prototype._setOption.apply(this, arguments); | |
| 4324 | + } | |
| 4325 | + } | |
| 4326 | + }); | |
| 4327 | +})(); | |
| 4328 | +/** | |
| 4329 | + * PrimeUI dropdown widget | |
| 4330 | + */ | |
| 4331 | +(function() { | |
| 4332 | + | |
| 4333 | + $.widget("primeui.puidropdown", { | |
| 4334 | + | |
| 4335 | + options: { | |
| 4336 | + effect: 'fade', | |
| 4337 | + effectSpeed: 'normal', | |
| 4338 | + filter: false, | |
| 4339 | + filterMatchMode: 'startsWith', | |
| 4340 | + caseSensitiveFilter: false, | |
| 4341 | + filterFunction: null, | |
| 4342 | + data: null, | |
| 4343 | + content: null, | |
| 4344 | + scrollHeight: 200, | |
| 4345 | + appendTo: 'body', | |
| 4346 | + editable: false, | |
| 4347 | + value: null, | |
| 4348 | + style: null, | |
| 4349 | + styleClass: null | |
| 4350 | + }, | |
| 4351 | + | |
| 4352 | + _create: function() { | |
| 4353 | + this.id = this.element.attr('id'); | |
| 4354 | + if(!this.id) { | |
| 4355 | + this.id = this.element.uniqueId().attr('id'); | |
| 4356 | + } | |
| 4357 | + | |
| 4358 | + if(!this.options.enhanced) { | |
| 4359 | + if(this.options.data) { | |
| 4360 | + if($.isArray(this.options.data)) { | |
| 4361 | + this._generateOptionElements(this.options.data); | |
| 4362 | + } | |
| 4363 | + else { | |
| 4364 | + if($.type(this.options.data) === 'function') { | |
| 4365 | + this.options.data.call(this, this._onRemoteOptionsLoad); | |
| 4366 | + return; | |
| 4367 | + } | |
| 4368 | + else { | |
| 4369 | + if($.type(this.options.data) === 'string') { | |
| 4370 | + var $this = this, | |
| 4371 | + dataURL = this.options.data; | |
| 4372 | + | |
| 4373 | + var loader = function() { | |
| 4374 | + $.ajax({ | |
| 4375 | + type: 'GET', | |
| 4376 | + url: dataURL, | |
| 4377 | + dataType: "json", | |
| 4378 | + context: $this, | |
| 4379 | + success: function (response) { | |
| 4380 | + this._onRemoteOptionsLoad(response); | |
| 4381 | + } | |
| 4382 | + }); | |
| 4383 | + }; | |
| 4384 | + loader.call(this); | |
| 4385 | + } | |
| 4386 | + } | |
| 4387 | + return; | |
| 4388 | + } | |
| 4389 | + } | |
| 4390 | + | |
| 4391 | + this._render(); | |
| 4392 | + } | |
| 4393 | + else { | |
| 4394 | + this.choices = this.element.children('option'); | |
| 4395 | + this.container = this.element.closest('.ui-dropdown'); | |
| 4396 | + this.focusElementContainer = this.container.children('.ui-helper-hidden-accessible:last'); | |
| 4397 | + this.focusElement = this.focusElementContainer.children('input'); | |
| 4398 | + this.label = this.container.children('.ui-dropdown-label'); | |
| 4399 | + this.menuIcon = this.container.children('.ui-dropdown-trigger'); | |
| 4400 | + this.panel = this.container.children('.ui-dropdown-panel'); | |
| 4401 | + this.itemsWrapper = this.panel.children('.ui-dropdown-items-wrapper'); | |
| 4402 | + this.itemsContainer = this.itemsWrapper.children('ul'); | |
| 4403 | + this.itemsContainer.addClass('ui-dropdown-items ui-dropdown-list ui-widget-content ui-widget ui-corner-all ui-helper-reset'); | |
| 4404 | + this.items = this.itemsContainer.children('li').addClass('ui-dropdown-item ui-dropdown-list-item ui-corner-all'); | |
| 4405 | + | |
| 4406 | + var $this = this; | |
| 4407 | + this.items.each(function(i) { | |
| 4408 | + $(this).data('label', $this.choices.eq(i).text()); | |
| 4409 | + }); | |
| 4410 | + | |
| 4411 | + if(this.options.filter) { | |
| 4412 | + this.filterContainer = this.panel.children('.ui-dropdown-filter-container'); | |
| 4413 | + this.filterInput = this.filterContainer.children('input'); | |
| 4414 | + } | |
| 4415 | + } | |
| 4416 | + | |
| 4417 | + this._postRender(); | |
| 4418 | + }, | |
| 4419 | + | |
| 4420 | + _render: function() { | |
| 4421 | + this.choices = this.element.children('option'); | |
| 4422 | + this.element.attr('tabindex', '-1').wrap('<div class="ui-dropdown ui-widget ui-state-default ui-corner-all ui-helper-clearfix" />') | |
| 4423 | + .wrap('<div class="ui-helper-hidden-accessible" />'); | |
| 4424 | + | |
| 4425 | + this.container = this.element.closest('.ui-dropdown'); | |
| 4426 | + this.focusElementContainer = $('<div class="ui-helper-hidden-accessible"><input type="text" /></div>').appendTo(this.container); | |
| 4427 | + this.focusElement = this.focusElementContainer.children('input'); | |
| 4428 | + this.label = this.options.editable ? $('<input type="text" class="ui-dropdown-label ui-inputtext ui-corner-all"">') | |
| 4429 | + : $('<label class="ui-dropdown-label ui-inputtext ui-corner-all"/>'); | |
| 4430 | + this.label.appendTo(this.container); | |
| 4431 | + this.menuIcon = $('<div class="ui-dropdown-trigger ui-state-default ui-corner-right"><span class="fa fa-fw fa-caret-down"></span></div>') | |
| 4432 | + .appendTo(this.container); | |
| 4433 | + | |
| 4434 | + //panel | |
| 4435 | + this.panel = $('<div class="ui-dropdown-panel ui-widget-content ui-corner-all ui-helper-hidden ui-shadow" />'); | |
| 4436 | + this.itemsWrapper = $('<div class="ui-dropdown-items-wrapper" />').appendTo(this.panel); | |
| 4437 | + this.itemsContainer = $('<ul class="ui-dropdown-items ui-dropdown-list ui-widget-content ui-widget ui-corner-all ui-helper-reset"></ul>') | |
| 4438 | + .appendTo(this.itemsWrapper); | |
| 4439 | + | |
| 4440 | + this.optGroupsSize = this.itemsContainer.children('li.puiselectonemenu-item-group').length; | |
| 4441 | + | |
| 4442 | + if(this.options.filter) { | |
| 4443 | + this.filterContainer = $('<div class="ui-dropdown-filter-container" />').prependTo(this.panel); | |
| 4444 | + this.filterInput = $('<input type="text" autocomplete="off" class="ui-dropdown-filter ui-inputtext ui-widget ui-state-default ui-corner-all" />') | |
| 4445 | + .appendTo(this.filterContainer); | |
| 4446 | + this.filterContainer.append('<span class="fa fa-search"></span>'); | |
| 4447 | + } | |
| 4448 | + | |
| 4449 | + this._generateItems(); | |
| 4450 | + }, | |
| 4451 | + | |
| 4452 | + _postRender: function() { | |
| 4453 | + if(this.options.style) { | |
| 4454 | + this.container.attr('style', this.options.style); | |
| 4455 | + } | |
| 4456 | + | |
| 4457 | + if(this.options.styleClass) { | |
| 4458 | + this.container.addClass(this.options.styleClass); | |
| 4459 | + } | |
| 4460 | + | |
| 4461 | + this.disabled = this.element.prop('disabled')||this.options.disabled; | |
| 4462 | + | |
| 4463 | + if(this.options.appendTo === 'self') | |
| 4464 | + this.panel.appendTo(this.container); | |
| 4465 | + else | |
| 4466 | + this.panel.appendTo(this.options.appendTo); | |
| 4467 | + | |
| 4468 | + if(this.options.scrollHeight && this.panel.outerHeight() > this.options.scrollHeight) { | |
| 4469 | + this.itemsWrapper.height(this.options.scrollHeight); | |
| 4470 | + } | |
| 4471 | + | |
| 4472 | + var $this = this; | |
| 4473 | + | |
| 4474 | + //preselection via value option | |
| 4475 | + if(this.options.value) { | |
| 4476 | + this.choices.filter('[value="'+this.options.value+'"]').prop('selected', true); | |
| 4477 | + } | |
| 4478 | + | |
| 4479 | + var selectedOption = this.choices.filter(':selected'); | |
| 4480 | + | |
| 4481 | + //disable options | |
| 4482 | + this.choices.filter(':disabled').each(function() { | |
| 4483 | + $this.items.eq($(this).index()).addClass('ui-state-disabled'); | |
| 4484 | + }); | |
| 4485 | + | |
| 4486 | + //triggers | |
| 4487 | + this.triggers = this.options.editable ? this.menuIcon : this.container.children('.ui-dropdown-trigger, .ui-dropdown-label'); | |
| 4488 | + | |
| 4489 | + //activate selected | |
| 4490 | + if(this.options.editable) { | |
| 4491 | + var customInputVal = this.label.val(); | |
| 4492 | + | |
| 4493 | + //predefined input | |
| 4494 | + if(customInputVal === selectedOption.text()) { | |
| 4495 | + this._highlightItem(this.items.eq(selectedOption.index())); | |
| 4496 | + } | |
| 4497 | + //custom input | |
| 4498 | + else { | |
| 4499 | + this.items.eq(0).addClass('ui-state-highlight'); | |
| 4500 | + this.customInput = true; | |
| 4501 | + this.customInputVal = customInputVal; | |
| 4502 | + } | |
| 4503 | + } | |
| 4504 | + else { | |
| 4505 | + this._highlightItem(this.items.eq(selectedOption.index())); | |
| 4506 | + } | |
| 4507 | + | |
| 4508 | + if(!this.disabled) { | |
| 4509 | + this._bindEvents(); | |
| 4510 | + this._bindConstantEvents(); | |
| 4511 | + } | |
| 4512 | + }, | |
| 4513 | + | |
| 4514 | + _onRemoteOptionsLoad: function(data) { | |
| 4515 | + this._generateOptionElements(data); | |
| 4516 | + this._render(); | |
| 4517 | + this._postRender(); | |
| 4518 | + }, | |
| 4519 | + | |
| 4520 | + _generateOptionElements: function(data) { | |
| 4521 | + for(var i = 0; i < data.length; i++) { | |
| 4522 | + var choice = data[i]; | |
| 4523 | + if(choice.label) | |
| 4524 | + this.element.append('<option value="' + choice.value + '">' + choice.label + '</option>'); | |
| 4525 | + else | |
| 4526 | + this.element.append('<option value="' + choice + '">' + choice + '</option>'); | |
| 4527 | + } | |
| 4528 | + }, | |
| 4529 | + | |
| 4530 | + _generateItems: function() { | |
| 4531 | + for(var i = 0; i < this.choices.length; i++) { | |
| 4532 | + var option = this.choices.eq(i), | |
| 4533 | + optionLabel = option.text(), | |
| 4534 | + content = this.options.content ? this.options.content.call(this, this.options.data[i]) : optionLabel; | |
| 4535 | + | |
| 4536 | + this.itemsContainer.append('<li data-label="' + optionLabel + '" class="ui-dropdown-item ui-dropdown-list-item ui-corner-all">' + content + '</li>'); | |
| 4537 | + } | |
| 4538 | + | |
| 4539 | + this.items = this.itemsContainer.children('.ui-dropdown-item'); | |
| 4540 | + }, | |
| 4541 | + | |
| 4542 | + _bindEvents: function() { | |
| 4543 | + var $this = this; | |
| 4544 | + | |
| 4545 | + this.items.filter(':not(.ui-state-disabled)').each(function(i, item) { | |
| 4546 | + $this._bindItemEvents($(item)); | |
| 4547 | + }); | |
| 4548 | + | |
| 4549 | + this.triggers.on('mouseenter.puidropdown', function() { | |
| 4550 | + if(!$this.container.hasClass('ui-state-focus')) { | |
| 4551 | + $this.container.addClass('ui-state-hover'); | |
| 4552 | + $this.menuIcon.addClass('ui-state-hover'); | |
| 4553 | + } | |
| 4554 | + }) | |
| 4555 | + .on('mouseleave.puidropdown', function() { | |
| 4556 | + $this.container.removeClass('ui-state-hover'); | |
| 4557 | + $this.menuIcon.removeClass('ui-state-hover'); | |
| 4558 | + }) | |
| 4559 | + .on('click.puidropdown', function(e) { | |
| 4560 | + if($this.panel.is(":hidden")) { | |
| 4561 | + $this._show(); | |
| 4562 | + } | |
| 4563 | + else { | |
| 4564 | + $this._hide(); | |
| 4565 | + | |
| 4566 | + $this._revert(); | |
| 4567 | + } | |
| 4568 | + | |
| 4569 | + $this.container.removeClass('ui-state-hover'); | |
| 4570 | + $this.menuIcon.removeClass('ui-state-hover'); | |
| 4571 | + $this.focusElement.trigger('focus.puidropdown'); | |
| 4572 | + e.preventDefault(); | |
| 4573 | + }); | |
| 4574 | + | |
| 4575 | + this.focusElement.on('focus.puidropdown', function() { | |
| 4576 | + $this.container.addClass('ui-state-focus'); | |
| 4577 | + $this.menuIcon.addClass('ui-state-focus'); | |
| 4578 | + }) | |
| 4579 | + .on('blur.puidropdown', function() { | |
| 4580 | + $this.container.removeClass('ui-state-focus'); | |
| 4581 | + $this.menuIcon.removeClass('ui-state-focus'); | |
| 4582 | + }); | |
| 4583 | + | |
| 4584 | + if(this.options.editable) { | |
| 4585 | + this.label.on('change.ui-dropdown', function() { | |
| 4586 | + $this._triggerChange(true); | |
| 4587 | + $this.customInput = true; | |
| 4588 | + $this.customInputVal = $(this).val(); | |
| 4589 | + $this.items.filter('.ui-state-highlight').removeClass('ui-state-highlight'); | |
| 4590 | + $this.items.eq(0).addClass('ui-state-highlight'); | |
| 4591 | + }); | |
| 4592 | + } | |
| 4593 | + | |
| 4594 | + this._bindKeyEvents(); | |
| 4595 | + | |
| 4596 | + if(this.options.filter) { | |
| 4597 | + this._setupFilterMatcher(); | |
| 4598 | + | |
| 4599 | + this.filterInput.puiinputtext(); | |
| 4600 | + | |
| 4601 | + this.filterInput.on('keyup.ui-dropdown', function() { | |
| 4602 | + $this._filter($(this).val()); | |
| 4603 | + }); | |
| 4604 | + } | |
| 4605 | + }, | |
| 4606 | + | |
| 4607 | + _bindItemEvents: function(item) { | |
| 4608 | + var $this = this; | |
| 4609 | + | |
| 4610 | + item.on('mouseover.puidropdown', function() { | |
| 4611 | + var el = $(this); | |
| 4612 | + | |
| 4613 | + if(!el.hasClass('ui-state-highlight')) | |
| 4614 | + $(this).addClass('ui-state-hover'); | |
| 4615 | + }) | |
| 4616 | + .on('mouseout.puidropdown', function() { | |
| 4617 | + $(this).removeClass('ui-state-hover'); | |
| 4618 | + }) | |
| 4619 | + .on('click.puidropdown', function() { | |
| 4620 | + $this._selectItem($(this)); | |
| 4621 | + }); | |
| 4622 | + }, | |
| 4623 | + | |
| 4624 | + _bindConstantEvents: function() { | |
| 4625 | + var $this = this; | |
| 4626 | + | |
| 4627 | + $(document.body).on('mousedown.ui-dropdown-' + this.id, function (e) { | |
| 4628 | + if($this.panel.is(":hidden")) { | |
| 4629 | + return; | |
| 4630 | + } | |
| 4631 | + | |
| 4632 | + var offset = $this.panel.offset(); | |
| 4633 | + if (e.target === $this.label.get(0) || | |
| 4634 | + e.target === $this.menuIcon.get(0) || | |
| 4635 | + e.target === $this.menuIcon.children().get(0)) { | |
| 4636 | + return; | |
| 4637 | + } | |
| 4638 | + | |
| 4639 | + if (e.pageX < offset.left || | |
| 4640 | + e.pageX > offset.left + $this.panel.width() || | |
| 4641 | + e.pageY < offset.top || | |
| 4642 | + e.pageY > offset.top + $this.panel.height()) { | |
| 4643 | + | |
| 4644 | + $this._hide(); | |
| 4645 | + $this._revert(); | |
| 4646 | + } | |
| 4647 | + }); | |
| 4648 | + | |
| 4649 | + this.resizeNS = 'resize.' + this.id; | |
| 4650 | + this._unbindResize(); | |
| 4651 | + this._bindResize(); | |
| 4652 | + }, | |
| 4653 | + | |
| 4654 | + _bindKeyEvents: function() { | |
| 4655 | + var $this = this; | |
| 4656 | + | |
| 4657 | + this.focusElement.on('keydown.puidropdown', function(e) { | |
| 4658 | + var keyCode = $.ui.keyCode, | |
| 4659 | + key = e.which, | |
| 4660 | + activeItem; | |
| 4661 | + | |
| 4662 | + switch(key) { | |
| 4663 | + case keyCode.UP: | |
| 4664 | + case keyCode.LEFT: | |
| 4665 | + activeItem = $this._getActiveItem(); | |
| 4666 | + var prev = activeItem.prevAll(':not(.ui-state-disabled,.ui-selectonemenu-item-group):first'); | |
| 4667 | + | |
| 4668 | + if(prev.length == 1) { | |
| 4669 | + if($this.panel.is(':hidden')) { | |
| 4670 | + $this._selectItem(prev); | |
| 4671 | + } | |
| 4672 | + else { | |
| 4673 | + $this._highlightItem(prev); | |
| 4674 | + PUI.scrollInView($this.itemsWrapper, prev); | |
| 4675 | + } | |
| 4676 | + } | |
| 4677 | + | |
| 4678 | + e.preventDefault(); | |
| 4679 | + break; | |
| 4680 | + | |
| 4681 | + case keyCode.DOWN: | |
| 4682 | + case keyCode.RIGHT: | |
| 4683 | + activeItem = $this._getActiveItem(); | |
| 4684 | + var next = activeItem.nextAll(':not(.ui-state-disabled,.ui-selectonemenu-item-group):first'); | |
| 4685 | + | |
| 4686 | + if(next.length == 1) { | |
| 4687 | + if($this.panel.is(':hidden')) { | |
| 4688 | + if(e.altKey) { | |
| 4689 | + $this._show(); | |
| 4690 | + } else { | |
| 4691 | + $this._selectItem(next); | |
| 4692 | + } | |
| 4693 | + } | |
| 4694 | + else { | |
| 4695 | + $this._highlightItem(next); | |
| 4696 | + PUI.scrollInView($this.itemsWrapper, next); | |
| 4697 | + } | |
| 4698 | + } | |
| 4699 | + | |
| 4700 | + e.preventDefault(); | |
| 4701 | + break; | |
| 4702 | + | |
| 4703 | + case keyCode.ENTER: | |
| 4704 | + case keyCode.NUMPAD_ENTER: | |
| 4705 | + if($this.panel.is(':hidden')) { | |
| 4706 | + $this._show(); | |
| 4707 | + } | |
| 4708 | + else { | |
| 4709 | + $this._selectItem($this._getActiveItem()); | |
| 4710 | + } | |
| 4711 | + | |
| 4712 | + e.preventDefault(); | |
| 4713 | + break; | |
| 4714 | + | |
| 4715 | + case keyCode.TAB: | |
| 4716 | + if($this.panel.is(':visible')) { | |
| 4717 | + $this._revert(); | |
| 4718 | + $this._hide(); | |
| 4719 | + } | |
| 4720 | + break; | |
| 4721 | + | |
| 4722 | + case keyCode.ESCAPE: | |
| 4723 | + if($this.panel.is(':visible')) { | |
| 4724 | + $this._revert(); | |
| 4725 | + $this._hide(); | |
| 4726 | + } | |
| 4727 | + break; | |
| 4728 | + | |
| 4729 | + default: | |
| 4730 | + var k = String.fromCharCode((96 <= key && key <= 105)? key-48 : key), | |
| 4731 | + currentItem = $this.items.filter('.ui-state-highlight'); | |
| 4732 | + | |
| 4733 | + //Search items forward from current to end and on no result, search from start until current | |
| 4734 | + var highlightItem = $this._search(k, currentItem.index() + 1, $this.options.length); | |
| 4735 | + if(!highlightItem) { | |
| 4736 | + highlightItem = $this._search(k, 0, currentItem.index()); | |
| 4737 | + } | |
| 4738 | + | |
| 4739 | + if(highlightItem) { | |
| 4740 | + if($this.panel.is(':hidden')) { | |
| 4741 | + $this._selectItem(highlightItem); | |
| 4742 | + } | |
| 4743 | + else { | |
| 4744 | + $this._highlightItem(highlightItem); | |
| 4745 | + PUI.scrollInView($this.itemsWrapper, highlightItem); | |
| 4746 | + } | |
| 4747 | + } | |
| 4748 | + | |
| 4749 | + break; | |
| 4750 | + } | |
| 4751 | + }); | |
| 4752 | + }, | |
| 4753 | + | |
| 4754 | + _unbindEvents: function() { | |
| 4755 | + this.items.off('mouseover.puidropdown mouseout.puidropdown click.puidropdown'); | |
| 4756 | + this.triggers.off('mouseenter.puidropdown mouseleave.puidropdown click.puidropdown'); | |
| 4757 | + this.focusElement.off('keydown.puidropdown focus.puidropdown blur.puidropdown'); | |
| 4758 | + | |
| 4759 | + if(this.options.editable) { | |
| 4760 | + this.label.off('change.puidropdown'); | |
| 4761 | + } | |
| 4762 | + | |
| 4763 | + if(this.options.filter) { | |
| 4764 | + this.filterInput.off('keyup.ui-dropdown'); | |
| 4765 | + } | |
| 4766 | + | |
| 4767 | + $(document.body).off('mousedown.ui-dropdown-' + this.id); | |
| 4768 | + this._unbindResize(); | |
| 4769 | + }, | |
| 4770 | + | |
| 4771 | + _selectItem: function(item, silent) { | |
| 4772 | + var selectedOption = this.choices.eq(this._resolveItemIndex(item)), | |
| 4773 | + currentOption = this.choices.filter(':selected'), | |
| 4774 | + sameOption = selectedOption.val() == currentOption.val(), | |
| 4775 | + shouldChange = null; | |
| 4776 | + | |
| 4777 | + if(this.options.editable) { | |
| 4778 | + shouldChange = (!sameOption)||(selectedOption.text() != this.label.val()); | |
| 4779 | + } | |
| 4780 | + else { | |
| 4781 | + shouldChange = !sameOption; | |
| 4782 | + } | |
| 4783 | + | |
| 4784 | + if(shouldChange) { | |
| 4785 | + this._highlightItem(item); | |
| 4786 | + this.element.val(selectedOption.val()); | |
| 4787 | + | |
| 4788 | + this._triggerChange(); | |
| 4789 | + | |
| 4790 | + if(this.options.editable) { | |
| 4791 | + this.customInput = false; | |
| 4792 | + } | |
| 4793 | + } | |
| 4794 | + | |
| 4795 | + if(!silent) { | |
| 4796 | + this.focusElement.trigger('focus.puidropdown'); | |
| 4797 | + } | |
| 4798 | + | |
| 4799 | + if(this.panel.is(':visible')) { | |
| 4800 | + this._hide(); | |
| 4801 | + } | |
| 4802 | + }, | |
| 4803 | + | |
| 4804 | + _highlightItem: function(item) { | |
| 4805 | + this.items.filter('.ui-state-highlight').removeClass('ui-state-highlight'); | |
| 4806 | + | |
| 4807 | + if(item.length) { | |
| 4808 | + item.addClass('ui-state-highlight'); | |
| 4809 | + | |
| 4810 | + this._setLabel(item.data('label')); | |
| 4811 | + } | |
| 4812 | + else { | |
| 4813 | + this._setLabel(' '); | |
| 4814 | + } | |
| 4815 | + }, | |
| 4816 | + | |
| 4817 | + _triggerChange: function(edited) { | |
| 4818 | + this.changed = false; | |
| 4819 | + var selectedOption = this.choices.filter(':selected'); | |
| 4820 | + | |
| 4821 | + if(this.options.change) { | |
| 4822 | + this._trigger('change', null, { | |
| 4823 | + value: selectedOption.val(), | |
| 4824 | + index: selectedOption.index() | |
| 4825 | + }); | |
| 4826 | + } | |
| 4827 | + | |
| 4828 | + if(!edited) { | |
| 4829 | + this.value = this.choices.filter(':selected').val(); | |
| 4830 | + } | |
| 4831 | + }, | |
| 4832 | + | |
| 4833 | + _resolveItemIndex: function(item) { | |
| 4834 | + if(this.optGroupsSize === 0) { | |
| 4835 | + return item.index(); | |
| 4836 | + } | |
| 4837 | + else { | |
| 4838 | + return item.index() - item.prevAll('li.ui-dropdown-item-group').length; | |
| 4839 | + } | |
| 4840 | + }, | |
| 4841 | + | |
| 4842 | + _setLabel: function(value) { | |
| 4843 | + if(this.options.editable) { | |
| 4844 | + this.label.val(value); | |
| 4845 | + } | |
| 4846 | + else { | |
| 4847 | + if(value === ' ') { | |
| 4848 | + this.label.html(' '); | |
| 4849 | + } | |
| 4850 | + else { | |
| 4851 | + this.label.text(value); | |
| 4852 | + } | |
| 4853 | + } | |
| 4854 | + }, | |
| 4855 | + | |
| 4856 | + _bindResize: function() { | |
| 4857 | + var $this = this; | |
| 4858 | + | |
| 4859 | + $(window).bind(this.resizeNS, function(e) { | |
| 4860 | + if($this.panel.is(':visible')) { | |
| 4861 | + $this._alignPanel(); | |
| 4862 | + } | |
| 4863 | + }); | |
| 4864 | + }, | |
| 4865 | + | |
| 4866 | + _unbindResize: function() { | |
| 4867 | + $(window).unbind(this.resizeNS); | |
| 4868 | + }, | |
| 4869 | + | |
| 4870 | + _alignPanelWidth: function() { | |
| 4871 | + if(!this.panelWidthAdjusted) { | |
| 4872 | + var jqWidth = this.container.outerWidth(); | |
| 4873 | + if(this.panel.outerWidth() < jqWidth) { | |
| 4874 | + this.panel.width(jqWidth); | |
| 4875 | + } | |
| 4876 | + | |
| 4877 | + this.panelWidthAdjusted = true; | |
| 4878 | + } | |
| 4879 | + }, | |
| 4880 | + | |
| 4881 | + _alignPanel: function() { | |
| 4882 | + if(this.panel.parent().is(this.container)) { | |
| 4883 | + this.panel.css({ | |
| 4884 | + left: '0px', | |
| 4885 | + top: this.container.outerHeight() + 'px' | |
| 4886 | + }) | |
| 4887 | + .width(this.container.outerWidth()); | |
| 4888 | + } | |
| 4889 | + else { | |
| 4890 | + this._alignPanelWidth(); | |
| 4891 | + this.panel.css({left:'', top:''}).position({ | |
| 4892 | + my: 'left top', | |
| 4893 | + at: 'left bottom', | |
| 4894 | + of: this.container, | |
| 4895 | + collision: 'flipfit' | |
| 4896 | + }); | |
| 4897 | + } | |
| 4898 | + }, | |
| 4899 | + | |
| 4900 | + _show: function() { | |
| 4901 | + this._alignPanel(); | |
| 4902 | + | |
| 4903 | + this.panel.css('z-index', ++PUI.zindex); | |
| 4904 | + | |
| 4905 | + if(this.options.effect !== 'none') { | |
| 4906 | + this.panel.show(this.options.effect, {}, this.options.effectSpeed); | |
| 4907 | + } | |
| 4908 | + else { | |
| 4909 | + this.panel.show(); | |
| 4910 | + } | |
| 4911 | + this.preShowValue = this.choices.filter(':selected'); | |
| 4912 | + }, | |
| 4913 | + | |
| 4914 | + _hide: function() { | |
| 4915 | + this.panel.hide(); | |
| 4916 | + }, | |
| 4917 | + | |
| 4918 | + _revert: function() { | |
| 4919 | + if(this.options.editable && this.customInput) { | |
| 4920 | + this._setLabel(this.customInputVal); | |
| 4921 | + this.items.filter('.ui-state-active').removeClass('ui-state-active'); | |
| 4922 | + this.items.eq(0).addClass('ui-state-active'); | |
| 4923 | + } | |
| 4924 | + else { | |
| 4925 | + this._highlightItem(this.items.eq(this.preShowValue.index())); | |
| 4926 | + } | |
| 4927 | + }, | |
| 4928 | + | |
| 4929 | + _getActiveItem: function() { | |
| 4930 | + return this.items.filter('.ui-state-highlight'); | |
| 4931 | + }, | |
| 4932 | + | |
| 4933 | + _setupFilterMatcher: function() { | |
| 4934 | + this.filterMatchers = { | |
| 4935 | + 'startsWith': this._startsWithFilter, | |
| 4936 | + 'contains': this._containsFilter, | |
| 4937 | + 'endsWith': this._endsWithFilter, | |
| 4938 | + 'custom': this.options.filterFunction | |
| 4939 | + }; | |
| 4940 | + | |
| 4941 | + this.filterMatcher = this.filterMatchers[this.options.filterMatchMode]; | |
| 4942 | + }, | |
| 4943 | + | |
| 4944 | + _startsWithFilter: function(value, filter) { | |
| 4945 | + return value.indexOf(filter) === 0; | |
| 4946 | + }, | |
| 4947 | + | |
| 4948 | + _containsFilter: function(value, filter) { | |
| 4949 | + return value.indexOf(filter) !== -1; | |
| 4950 | + }, | |
| 4951 | + | |
| 4952 | + _endsWithFilter: function(value, filter) { | |
| 4953 | + return value.indexOf(filter, value.length - filter.length) !== -1; | |
| 4954 | + }, | |
| 4955 | + | |
| 4956 | + _filter: function(value) { | |
| 4957 | + this.initialHeight = this.initialHeight||this.itemsWrapper.height(); | |
| 4958 | + var filterValue = this.options.caseSensitiveFilter ? $.trim(value) : $.trim(value).toLowerCase(); | |
| 4959 | + | |
| 4960 | + if(filterValue === '') { | |
| 4961 | + this.items.filter(':hidden').show(); | |
| 4962 | + } | |
| 4963 | + else { | |
| 4964 | + for(var i = 0; i < this.choices.length; i++) { | |
| 4965 | + var option = this.choices.eq(i), | |
| 4966 | + itemLabel = this.options.caseSensitiveFilter ? option.text() : option.text().toLowerCase(), | |
| 4967 | + item = this.items.eq(i); | |
| 4968 | + | |
| 4969 | + if(this.filterMatcher(itemLabel, filterValue)) | |
| 4970 | + item.show(); | |
| 4971 | + else | |
| 4972 | + item.hide(); | |
| 4973 | + } | |
| 4974 | + } | |
| 4975 | + | |
| 4976 | + if(this.itemsContainer.height() < this.initialHeight) { | |
| 4977 | + this.itemsWrapper.css('height', 'auto'); | |
| 4978 | + } | |
| 4979 | + else { | |
| 4980 | + this.itemsWrapper.height(this.initialHeight); | |
| 4981 | + } | |
| 4982 | + | |
| 4983 | + this._alignPanel(); | |
| 4984 | + }, | |
| 4985 | + | |
| 4986 | + _search: function(text, start, end) { | |
| 4987 | + for(var i = start; i < end; i++) { | |
| 4988 | + var option = this.choices.eq(i); | |
| 4989 | + | |
| 4990 | + if(option.text().indexOf(text) === 0) { | |
| 4991 | + return this.items.eq(i); | |
| 4992 | + } | |
| 4993 | + } | |
| 4994 | + | |
| 4995 | + return null; | |
| 4996 | + }, | |
| 4997 | + | |
| 4998 | + getSelectedValue: function() { | |
| 4999 | + return this.element.val(); | |
8964 more lines aren’t shown here.