forked from fanruan/fineui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73302 lines
2.3 MiB
73302 lines
2.3 MiB
/** |
|
* Created by richie on 15/7/8. |
|
*/ |
|
/** |
|
* 初始化BI对象 |
|
*/ |
|
var _global; |
|
if (typeof window !== "undefined") { |
|
_global = window; |
|
} else if (typeof global !== "undefined") { |
|
_global = global; |
|
} else if (typeof self !== "undefined") { |
|
_global = self; |
|
} else { |
|
_global = this; |
|
} |
|
if (_global.BI == null) { |
|
_global.BI = {prepares: []}; |
|
} |
|
if(_global.BI.prepares == null) { |
|
_global.BI.prepares = []; |
|
}/** |
|
* @license |
|
* Lodash (Custom Build) <https://lodash.com/> |
|
* Build: `lodash core plus="debounce,throttle,get,set,findIndex,findLastIndex,findKey,findLastKey,isArrayLike,invert,invertBy,uniq,uniqBy,omit,omitBy,zip,unzip,rest,range,random,reject,intersection,drop,countBy,union,zipObject,initial,cloneDeep,clamp,isPlainObject,take,takeRight,without,difference,defaultsDeep,trim,merge,groupBy,uniqBy"` |
|
* Copyright JS Foundation and other contributors <https://js.foundation/> |
|
* Released under MIT license <https://lodash.com/license> |
|
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> |
|
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors |
|
*/ |
|
;(function() { |
|
|
|
/** Used as a safe reference for `undefined` in pre-ES5 environments. */ |
|
var undefined; |
|
|
|
/** Used as the semantic version number. */ |
|
var VERSION = '4.17.5'; |
|
|
|
/** Used as the size to enable large array optimizations. */ |
|
var LARGE_ARRAY_SIZE = 200; |
|
|
|
/** Error message constants. */ |
|
var FUNC_ERROR_TEXT = 'Expected a function'; |
|
|
|
/** Used to stand-in for `undefined` hash values. */ |
|
var HASH_UNDEFINED = '__lodash_hash_undefined__'; |
|
|
|
/** Used as the maximum memoize cache size. */ |
|
var MAX_MEMOIZE_SIZE = 500; |
|
|
|
/** Used as the internal argument placeholder. */ |
|
var PLACEHOLDER = '__lodash_placeholder__'; |
|
|
|
/** Used to compose bitmasks for cloning. */ |
|
var CLONE_DEEP_FLAG = 1, |
|
CLONE_FLAT_FLAG = 2, |
|
CLONE_SYMBOLS_FLAG = 4; |
|
|
|
/** Used to compose bitmasks for value comparisons. */ |
|
var COMPARE_PARTIAL_FLAG = 1, |
|
COMPARE_UNORDERED_FLAG = 2; |
|
|
|
/** Used to compose bitmasks for function metadata. */ |
|
var WRAP_BIND_FLAG = 1, |
|
WRAP_BIND_KEY_FLAG = 2, |
|
WRAP_CURRY_BOUND_FLAG = 4, |
|
WRAP_CURRY_FLAG = 8, |
|
WRAP_CURRY_RIGHT_FLAG = 16, |
|
WRAP_PARTIAL_FLAG = 32, |
|
WRAP_PARTIAL_RIGHT_FLAG = 64, |
|
WRAP_ARY_FLAG = 128, |
|
WRAP_REARG_FLAG = 256, |
|
WRAP_FLIP_FLAG = 512; |
|
|
|
/** Used to detect hot functions by number of calls within a span of milliseconds. */ |
|
var HOT_COUNT = 800, |
|
HOT_SPAN = 16; |
|
|
|
/** Used to indicate the type of lazy iteratees. */ |
|
var LAZY_FILTER_FLAG = 1, |
|
LAZY_MAP_FLAG = 2, |
|
LAZY_WHILE_FLAG = 3; |
|
|
|
/** Used as references for various `Number` constants. */ |
|
var INFINITY = 1 / 0, |
|
MAX_SAFE_INTEGER = 9007199254740991, |
|
MAX_INTEGER = 1.7976931348623157e+308, |
|
NAN = 0 / 0; |
|
|
|
/** Used as references for the maximum length and index of an array. */ |
|
var MAX_ARRAY_LENGTH = 4294967295; |
|
|
|
/** Used to associate wrap methods with their bit flags. */ |
|
var wrapFlags = [ |
|
['ary', WRAP_ARY_FLAG], |
|
['bind', WRAP_BIND_FLAG], |
|
['bindKey', WRAP_BIND_KEY_FLAG], |
|
['curry', WRAP_CURRY_FLAG], |
|
['curryRight', WRAP_CURRY_RIGHT_FLAG], |
|
['flip', WRAP_FLIP_FLAG], |
|
['partial', WRAP_PARTIAL_FLAG], |
|
['partialRight', WRAP_PARTIAL_RIGHT_FLAG], |
|
['rearg', WRAP_REARG_FLAG] |
|
]; |
|
|
|
/** `Object#toString` result references. */ |
|
var argsTag = '[object Arguments]', |
|
arrayTag = '[object Array]', |
|
asyncTag = '[object AsyncFunction]', |
|
boolTag = '[object Boolean]', |
|
dateTag = '[object Date]', |
|
errorTag = '[object Error]', |
|
funcTag = '[object Function]', |
|
genTag = '[object GeneratorFunction]', |
|
mapTag = '[object Map]', |
|
numberTag = '[object Number]', |
|
nullTag = '[object Null]', |
|
objectTag = '[object Object]', |
|
promiseTag = '[object Promise]', |
|
proxyTag = '[object Proxy]', |
|
regexpTag = '[object RegExp]', |
|
setTag = '[object Set]', |
|
stringTag = '[object String]', |
|
symbolTag = '[object Symbol]', |
|
undefinedTag = '[object Undefined]', |
|
weakMapTag = '[object WeakMap]'; |
|
|
|
var arrayBufferTag = '[object ArrayBuffer]', |
|
dataViewTag = '[object DataView]', |
|
float32Tag = '[object Float32Array]', |
|
float64Tag = '[object Float64Array]', |
|
int8Tag = '[object Int8Array]', |
|
int16Tag = '[object Int16Array]', |
|
int32Tag = '[object Int32Array]', |
|
uint8Tag = '[object Uint8Array]', |
|
uint8ClampedTag = '[object Uint8ClampedArray]', |
|
uint16Tag = '[object Uint16Array]', |
|
uint32Tag = '[object Uint32Array]'; |
|
|
|
/** Used to match HTML entities and HTML characters. */ |
|
var reUnescapedHtml = /[&<>"']/g, |
|
reHasUnescapedHtml = RegExp(reUnescapedHtml.source); |
|
|
|
/** Used to match property names within property paths. */ |
|
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, |
|
reIsPlainProp = /^\w*$/, |
|
rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; |
|
|
|
/** |
|
* Used to match `RegExp` |
|
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). |
|
*/ |
|
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; |
|
|
|
/** Used to match leading and trailing whitespace. */ |
|
var reTrim = /^\s+|\s+$/g; |
|
|
|
/** Used to match wrap detail comments. */ |
|
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, |
|
reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, |
|
reSplitDetails = /,? & /; |
|
|
|
/** Used to match backslashes in property paths. */ |
|
var reEscapeChar = /\\(\\)?/g; |
|
|
|
/** Used to match `RegExp` flags from their coerced string values. */ |
|
var reFlags = /\w*$/; |
|
|
|
/** Used to detect bad signed hexadecimal string values. */ |
|
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; |
|
|
|
/** Used to detect binary string values. */ |
|
var reIsBinary = /^0b[01]+$/i; |
|
|
|
/** Used to detect host constructors (Safari). */ |
|
var reIsHostCtor = /^\[object .+?Constructor\]$/; |
|
|
|
/** Used to detect octal string values. */ |
|
var reIsOctal = /^0o[0-7]+$/i; |
|
|
|
/** Used to detect unsigned integer values. */ |
|
var reIsUint = /^(?:0|[1-9]\d*)$/; |
|
|
|
/** Used to compose unicode character classes. */ |
|
var rsAstralRange = '\\ud800-\\udfff', |
|
rsComboMarksRange = '\\u0300-\\u036f', |
|
reComboHalfMarksRange = '\\ufe20-\\ufe2f', |
|
rsComboSymbolsRange = '\\u20d0-\\u20ff', |
|
rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, |
|
rsVarRange = '\\ufe0e\\ufe0f'; |
|
|
|
/** Used to compose unicode capture groups. */ |
|
var rsAstral = '[' + rsAstralRange + ']', |
|
rsCombo = '[' + rsComboRange + ']', |
|
rsFitz = '\\ud83c[\\udffb-\\udfff]', |
|
rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', |
|
rsNonAstral = '[^' + rsAstralRange + ']', |
|
rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', |
|
rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', |
|
rsZWJ = '\\u200d'; |
|
|
|
/** Used to compose unicode regexes. */ |
|
var reOptMod = rsModifier + '?', |
|
rsOptVar = '[' + rsVarRange + ']?', |
|
rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', |
|
rsSeq = rsOptVar + reOptMod + rsOptJoin, |
|
rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; |
|
|
|
/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ |
|
var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); |
|
|
|
/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ |
|
var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); |
|
|
|
/** Used to identify `toStringTag` values of typed arrays. */ |
|
var typedArrayTags = {}; |
|
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = |
|
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = |
|
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = |
|
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = |
|
typedArrayTags[uint32Tag] = true; |
|
typedArrayTags[argsTag] = typedArrayTags[arrayTag] = |
|
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = |
|
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = |
|
typedArrayTags[errorTag] = typedArrayTags[funcTag] = |
|
typedArrayTags[mapTag] = typedArrayTags[numberTag] = |
|
typedArrayTags[objectTag] = typedArrayTags[regexpTag] = |
|
typedArrayTags[setTag] = typedArrayTags[stringTag] = |
|
typedArrayTags[weakMapTag] = false; |
|
|
|
/** Used to identify `toStringTag` values supported by `_.clone`. */ |
|
var cloneableTags = {}; |
|
cloneableTags[argsTag] = cloneableTags[arrayTag] = |
|
cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = |
|
cloneableTags[boolTag] = cloneableTags[dateTag] = |
|
cloneableTags[float32Tag] = cloneableTags[float64Tag] = |
|
cloneableTags[int8Tag] = cloneableTags[int16Tag] = |
|
cloneableTags[int32Tag] = cloneableTags[mapTag] = |
|
cloneableTags[numberTag] = cloneableTags[objectTag] = |
|
cloneableTags[regexpTag] = cloneableTags[setTag] = |
|
cloneableTags[stringTag] = cloneableTags[symbolTag] = |
|
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = |
|
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; |
|
cloneableTags[errorTag] = cloneableTags[funcTag] = |
|
cloneableTags[weakMapTag] = false; |
|
|
|
/** Used to map characters to HTML entities. */ |
|
var htmlEscapes = { |
|
'&': '&', |
|
'<': '<', |
|
'>': '>', |
|
'"': '"', |
|
"'": ''' |
|
}; |
|
|
|
/** Built-in method references without a dependency on `root`. */ |
|
var freeParseFloat = parseFloat, |
|
freeParseInt = parseInt; |
|
|
|
/** Detect free variable `global` from Node.js. */ |
|
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; |
|
|
|
/** Detect free variable `self`. */ |
|
var freeSelf = typeof self == 'object' && self && self.Object === Object && self; |
|
|
|
/** Used as a reference to the global object. */ |
|
var root = freeGlobal || freeSelf || Function('return this')(); |
|
|
|
/** Detect free variable `exports`. */ |
|
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; |
|
|
|
/** Detect free variable `module`. */ |
|
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; |
|
|
|
/** Detect the popular CommonJS extension `module.exports`. */ |
|
var moduleExports = freeModule && freeModule.exports === freeExports; |
|
|
|
/** Detect free variable `process` from Node.js. */ |
|
var freeProcess = moduleExports && freeGlobal.process; |
|
|
|
/** Used to access faster Node.js helpers. */ |
|
var nodeUtil = (function() { |
|
try { |
|
return freeProcess && freeProcess.binding && freeProcess.binding('util'); |
|
} catch (e) {} |
|
}()); |
|
|
|
/* Node.js helper references. */ |
|
var nodeIsDate = nodeUtil && nodeUtil.isDate, |
|
nodeIsMap = nodeUtil && nodeUtil.isMap, |
|
nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, |
|
nodeIsSet = nodeUtil && nodeUtil.isSet, |
|
nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; |
|
|
|
/*--------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* A faster alternative to `Function#apply`, this function invokes `func` |
|
* with the `this` binding of `thisArg` and the arguments of `args`. |
|
* |
|
* @private |
|
* @param {Function} func The function to invoke. |
|
* @param {*} thisArg The `this` binding of `func`. |
|
* @param {Array} args The arguments to invoke `func` with. |
|
* @returns {*} Returns the result of `func`. |
|
*/ |
|
function apply(func, thisArg, args) { |
|
switch (args.length) { |
|
case 0: return func.call(thisArg); |
|
case 1: return func.call(thisArg, args[0]); |
|
case 2: return func.call(thisArg, args[0], args[1]); |
|
case 3: return func.call(thisArg, args[0], args[1], args[2]); |
|
} |
|
return func.apply(thisArg, args); |
|
} |
|
|
|
/** |
|
* A specialized version of `baseAggregator` for arrays. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} setter The function to set `accumulator` values. |
|
* @param {Function} iteratee The iteratee to transform keys. |
|
* @param {Object} accumulator The initial aggregated object. |
|
* @returns {Function} Returns `accumulator`. |
|
*/ |
|
function arrayAggregator(array, setter, iteratee, accumulator) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length; |
|
|
|
while (++index < length) { |
|
var value = array[index]; |
|
setter(accumulator, value, iteratee(value), array); |
|
} |
|
return accumulator; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.forEach` for arrays without support for |
|
* iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Array} Returns `array`. |
|
*/ |
|
function arrayEach(array, iteratee) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length; |
|
|
|
while (++index < length) { |
|
if (iteratee(array[index], index, array) === false) { |
|
break; |
|
} |
|
} |
|
return array; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.every` for arrays without support for |
|
* iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @returns {boolean} Returns `true` if all elements pass the predicate check, |
|
* else `false`. |
|
*/ |
|
function arrayEvery(array, predicate) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length; |
|
|
|
while (++index < length) { |
|
if (!predicate(array[index], index, array)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.filter` for arrays without support for |
|
* iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @returns {Array} Returns the new filtered array. |
|
*/ |
|
function arrayFilter(array, predicate) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length, |
|
resIndex = 0, |
|
result = []; |
|
|
|
while (++index < length) { |
|
var value = array[index]; |
|
if (predicate(value, index, array)) { |
|
result[resIndex++] = value; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.includes` for arrays without support for |
|
* specifying an index to search from. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to inspect. |
|
* @param {*} target The value to search for. |
|
* @returns {boolean} Returns `true` if `target` is found, else `false`. |
|
*/ |
|
function arrayIncludes(array, value) { |
|
var length = array == null ? 0 : array.length; |
|
return !!length && baseIndexOf(array, value, 0) > -1; |
|
} |
|
|
|
/** |
|
* This function is like `arrayIncludes` except that it accepts a comparator. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to inspect. |
|
* @param {*} target The value to search for. |
|
* @param {Function} comparator The comparator invoked per element. |
|
* @returns {boolean} Returns `true` if `target` is found, else `false`. |
|
*/ |
|
function arrayIncludesWith(array, value, comparator) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length; |
|
|
|
while (++index < length) { |
|
if (comparator(value, array[index])) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.map` for arrays without support for iteratee |
|
* shorthands. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Array} Returns the new mapped array. |
|
*/ |
|
function arrayMap(array, iteratee) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length, |
|
result = Array(length); |
|
|
|
while (++index < length) { |
|
result[index] = iteratee(array[index], index, array); |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Appends the elements of `values` to `array`. |
|
* |
|
* @private |
|
* @param {Array} array The array to modify. |
|
* @param {Array} values The values to append. |
|
* @returns {Array} Returns `array`. |
|
*/ |
|
function arrayPush(array, values) { |
|
var index = -1, |
|
length = values.length, |
|
offset = array.length; |
|
|
|
while (++index < length) { |
|
array[offset + index] = values[index]; |
|
} |
|
return array; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.reduce` for arrays without support for |
|
* iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @param {*} [accumulator] The initial value. |
|
* @param {boolean} [initAccum] Specify using the first element of `array` as |
|
* the initial value. |
|
* @returns {*} Returns the accumulated value. |
|
*/ |
|
function arrayReduce(array, iteratee, accumulator, initAccum) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length; |
|
|
|
if (initAccum && length) { |
|
accumulator = array[++index]; |
|
} |
|
while (++index < length) { |
|
accumulator = iteratee(accumulator, array[index], index, array); |
|
} |
|
return accumulator; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.some` for arrays without support for iteratee |
|
* shorthands. |
|
* |
|
* @private |
|
* @param {Array} [array] The array to iterate over. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @returns {boolean} Returns `true` if any element passes the predicate check, |
|
* else `false`. |
|
*/ |
|
function arraySome(array, predicate) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length; |
|
|
|
while (++index < length) { |
|
if (predicate(array[index], index, array)) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* Gets the size of an ASCII `string`. |
|
* |
|
* @private |
|
* @param {string} string The string inspect. |
|
* @returns {number} Returns the string size. |
|
*/ |
|
var asciiSize = baseProperty('length'); |
|
|
|
/** |
|
* Converts an ASCII `string` to an array. |
|
* |
|
* @private |
|
* @param {string} string The string to convert. |
|
* @returns {Array} Returns the converted array. |
|
*/ |
|
function asciiToArray(string) { |
|
return string.split(''); |
|
} |
|
|
|
/** |
|
* The base implementation of methods like `_.findKey` and `_.findLastKey`, |
|
* without support for iteratee shorthands, which iterates over `collection` |
|
* using `eachFunc`. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to inspect. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @param {Function} eachFunc The function to iterate over `collection`. |
|
* @returns {*} Returns the found element or its key, else `undefined`. |
|
*/ |
|
function baseFindKey(collection, predicate, eachFunc) { |
|
var result; |
|
eachFunc(collection, function(value, key, collection) { |
|
if (predicate(value, key, collection)) { |
|
result = key; |
|
return false; |
|
} |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.findIndex` and `_.findLastIndex` without |
|
* support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @param {number} fromIndex The index to search from. |
|
* @param {boolean} [fromRight] Specify iterating from right to left. |
|
* @returns {number} Returns the index of the matched value, else `-1`. |
|
*/ |
|
function baseFindIndex(array, predicate, fromIndex, fromRight) { |
|
var length = array.length, |
|
index = fromIndex + (fromRight ? 1 : -1); |
|
|
|
while ((fromRight ? index-- : ++index < length)) { |
|
if (predicate(array[index], index, array)) { |
|
return index; |
|
} |
|
} |
|
return -1; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.indexOf` without `fromIndex` bounds checks. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {*} value The value to search for. |
|
* @param {number} fromIndex The index to search from. |
|
* @returns {number} Returns the index of the matched value, else `-1`. |
|
*/ |
|
function baseIndexOf(array, value, fromIndex) { |
|
return value === value |
|
? strictIndexOf(array, value, fromIndex) |
|
: baseFindIndex(array, baseIsNaN, fromIndex); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isNaN` without support for number objects. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. |
|
*/ |
|
function baseIsNaN(value) { |
|
return value !== value; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.property` without support for deep paths. |
|
* |
|
* @private |
|
* @param {string} key The key of the property to get. |
|
* @returns {Function} Returns the new accessor function. |
|
*/ |
|
function baseProperty(key) { |
|
return function(object) { |
|
return object == null ? undefined : object[key]; |
|
}; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.propertyOf` without support for deep paths. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Function} Returns the new accessor function. |
|
*/ |
|
function basePropertyOf(object) { |
|
return function(key) { |
|
return object == null ? undefined : object[key]; |
|
}; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.reduce` and `_.reduceRight`, without support |
|
* for iteratee shorthands, which iterates over `collection` using `eachFunc`. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @param {*} accumulator The initial value. |
|
* @param {boolean} initAccum Specify using the first or last element of |
|
* `collection` as the initial value. |
|
* @param {Function} eachFunc The function to iterate over `collection`. |
|
* @returns {*} Returns the accumulated value. |
|
*/ |
|
function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { |
|
eachFunc(collection, function(value, index, collection) { |
|
accumulator = initAccum |
|
? (initAccum = false, value) |
|
: iteratee(accumulator, value, index, collection); |
|
}); |
|
return accumulator; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.sortBy` which uses `comparer` to define the |
|
* sort order of `array` and replaces criteria objects with their corresponding |
|
* values. |
|
* |
|
* @private |
|
* @param {Array} array The array to sort. |
|
* @param {Function} comparer The function to define sort order. |
|
* @returns {Array} Returns `array`. |
|
*/ |
|
function baseSortBy(array, comparer) { |
|
var length = array.length; |
|
|
|
array.sort(comparer); |
|
while (length--) { |
|
array[length] = array[length].value; |
|
} |
|
return array; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.times` without support for iteratee shorthands |
|
* or max array length checks. |
|
* |
|
* @private |
|
* @param {number} n The number of times to invoke `iteratee`. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Array} Returns the array of results. |
|
*/ |
|
function baseTimes(n, iteratee) { |
|
var index = -1, |
|
result = Array(n); |
|
|
|
while (++index < n) { |
|
result[index] = iteratee(index); |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.unary` without support for storing metadata. |
|
* |
|
* @private |
|
* @param {Function} func The function to cap arguments for. |
|
* @returns {Function} Returns the new capped function. |
|
*/ |
|
function baseUnary(func) { |
|
return function(value) { |
|
return func(value); |
|
}; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.values` and `_.valuesIn` which creates an |
|
* array of `object` property values corresponding to the property names |
|
* of `props`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {Array} props The property names to get values for. |
|
* @returns {Object} Returns the array of property values. |
|
*/ |
|
function baseValues(object, props) { |
|
return arrayMap(props, function(key) { |
|
return object[key]; |
|
}); |
|
} |
|
|
|
/** |
|
* Checks if a `cache` value for `key` exists. |
|
* |
|
* @private |
|
* @param {Object} cache The cache to query. |
|
* @param {string} key The key of the entry to check. |
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
|
*/ |
|
function cacheHas(cache, key) { |
|
return cache.has(key); |
|
} |
|
|
|
/** |
|
* Used by `_.trim` and `_.trimStart` to get the index of the first string symbol |
|
* that is not found in the character symbols. |
|
* |
|
* @private |
|
* @param {Array} strSymbols The string symbols to inspect. |
|
* @param {Array} chrSymbols The character symbols to find. |
|
* @returns {number} Returns the index of the first unmatched string symbol. |
|
*/ |
|
function charsStartIndex(strSymbols, chrSymbols) { |
|
var index = -1, |
|
length = strSymbols.length; |
|
|
|
while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} |
|
return index; |
|
} |
|
|
|
/** |
|
* Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol |
|
* that is not found in the character symbols. |
|
* |
|
* @private |
|
* @param {Array} strSymbols The string symbols to inspect. |
|
* @param {Array} chrSymbols The character symbols to find. |
|
* @returns {number} Returns the index of the last unmatched string symbol. |
|
*/ |
|
function charsEndIndex(strSymbols, chrSymbols) { |
|
var index = strSymbols.length; |
|
|
|
while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} |
|
return index; |
|
} |
|
|
|
/** |
|
* Gets the number of `placeholder` occurrences in `array`. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {*} placeholder The placeholder to search for. |
|
* @returns {number} Returns the placeholder count. |
|
*/ |
|
function countHolders(array, placeholder) { |
|
var length = array.length, |
|
result = 0; |
|
|
|
while (length--) { |
|
if (array[length] === placeholder) { |
|
++result; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Used by `_.escape` to convert characters to HTML entities. |
|
* |
|
* @private |
|
* @param {string} chr The matched character to escape. |
|
* @returns {string} Returns the escaped character. |
|
*/ |
|
var escapeHtmlChar = basePropertyOf(htmlEscapes); |
|
|
|
/** |
|
* Gets the value at `key` of `object`. |
|
* |
|
* @private |
|
* @param {Object} [object] The object to query. |
|
* @param {string} key The key of the property to get. |
|
* @returns {*} Returns the property value. |
|
*/ |
|
function getValue(object, key) { |
|
return object == null ? undefined : object[key]; |
|
} |
|
|
|
/** |
|
* Checks if `string` contains Unicode symbols. |
|
* |
|
* @private |
|
* @param {string} string The string to inspect. |
|
* @returns {boolean} Returns `true` if a symbol is found, else `false`. |
|
*/ |
|
function hasUnicode(string) { |
|
return reHasUnicode.test(string); |
|
} |
|
|
|
/** |
|
* Converts `iterator` to an array. |
|
* |
|
* @private |
|
* @param {Object} iterator The iterator to convert. |
|
* @returns {Array} Returns the converted array. |
|
*/ |
|
function iteratorToArray(iterator) { |
|
var data, |
|
result = []; |
|
|
|
while (!(data = iterator.next()).done) { |
|
result.push(data.value); |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Converts `map` to its key-value pairs. |
|
* |
|
* @private |
|
* @param {Object} map The map to convert. |
|
* @returns {Array} Returns the key-value pairs. |
|
*/ |
|
function mapToArray(map) { |
|
var index = -1, |
|
result = Array(map.size); |
|
|
|
map.forEach(function(value, key) { |
|
result[++index] = [key, value]; |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* Creates a unary function that invokes `func` with its argument transformed. |
|
* |
|
* @private |
|
* @param {Function} func The function to wrap. |
|
* @param {Function} transform The argument transform. |
|
* @returns {Function} Returns the new function. |
|
*/ |
|
function overArg(func, transform) { |
|
return function(arg) { |
|
return func(transform(arg)); |
|
}; |
|
} |
|
|
|
/** |
|
* Replaces all `placeholder` elements in `array` with an internal placeholder |
|
* and returns an array of their indexes. |
|
* |
|
* @private |
|
* @param {Array} array The array to modify. |
|
* @param {*} placeholder The placeholder to replace. |
|
* @returns {Array} Returns the new array of placeholder indexes. |
|
*/ |
|
function replaceHolders(array, placeholder) { |
|
var index = -1, |
|
length = array.length, |
|
resIndex = 0, |
|
result = []; |
|
|
|
while (++index < length) { |
|
var value = array[index]; |
|
if (value === placeholder || value === PLACEHOLDER) { |
|
array[index] = PLACEHOLDER; |
|
result[resIndex++] = index; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Gets the value at `key`, unless `key` is "__proto__". |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {string} key The key of the property to get. |
|
* @returns {*} Returns the property value. |
|
*/ |
|
function safeGet(object, key) { |
|
return key == '__proto__' |
|
? undefined |
|
: object[key]; |
|
} |
|
|
|
/** |
|
* Converts `set` to an array of its values. |
|
* |
|
* @private |
|
* @param {Object} set The set to convert. |
|
* @returns {Array} Returns the values. |
|
*/ |
|
function setToArray(set) { |
|
var index = -1, |
|
result = Array(set.size); |
|
|
|
set.forEach(function(value) { |
|
result[++index] = value; |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.indexOf` which performs strict equality |
|
* comparisons of values, i.e. `===`. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {*} value The value to search for. |
|
* @param {number} fromIndex The index to search from. |
|
* @returns {number} Returns the index of the matched value, else `-1`. |
|
*/ |
|
function strictIndexOf(array, value, fromIndex) { |
|
var index = fromIndex - 1, |
|
length = array.length; |
|
|
|
while (++index < length) { |
|
if (array[index] === value) { |
|
return index; |
|
} |
|
} |
|
return -1; |
|
} |
|
|
|
/** |
|
* Gets the number of symbols in `string`. |
|
* |
|
* @private |
|
* @param {string} string The string to inspect. |
|
* @returns {number} Returns the string size. |
|
*/ |
|
function stringSize(string) { |
|
return hasUnicode(string) |
|
? unicodeSize(string) |
|
: asciiSize(string); |
|
} |
|
|
|
/** |
|
* Converts `string` to an array. |
|
* |
|
* @private |
|
* @param {string} string The string to convert. |
|
* @returns {Array} Returns the converted array. |
|
*/ |
|
function stringToArray(string) { |
|
return hasUnicode(string) |
|
? unicodeToArray(string) |
|
: asciiToArray(string); |
|
} |
|
|
|
/** |
|
* Gets the size of a Unicode `string`. |
|
* |
|
* @private |
|
* @param {string} string The string inspect. |
|
* @returns {number} Returns the string size. |
|
*/ |
|
function unicodeSize(string) { |
|
var result = reUnicode.lastIndex = 0; |
|
while (reUnicode.test(string)) { |
|
++result; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Converts a Unicode `string` to an array. |
|
* |
|
* @private |
|
* @param {string} string The string to convert. |
|
* @returns {Array} Returns the converted array. |
|
*/ |
|
function unicodeToArray(string) { |
|
return string.match(reUnicode) || []; |
|
} |
|
|
|
/*--------------------------------------------------------------------------*/ |
|
|
|
/** Used for built-in method references. */ |
|
var arrayProto = Array.prototype, |
|
funcProto = Function.prototype, |
|
objectProto = Object.prototype; |
|
|
|
/** Used to detect overreaching core-js shims. */ |
|
var coreJsData = root['__core-js_shared__']; |
|
|
|
/** Used to resolve the decompiled source of functions. */ |
|
var funcToString = funcProto.toString; |
|
|
|
/** Used to check objects for own properties. */ |
|
var hasOwnProperty = objectProto.hasOwnProperty; |
|
|
|
/** Used to generate unique IDs. */ |
|
var idCounter = 0; |
|
|
|
/** Used to detect methods masquerading as native. */ |
|
var maskSrcKey = (function() { |
|
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); |
|
return uid ? ('Symbol(src)_1.' + uid) : ''; |
|
}()); |
|
|
|
/** |
|
* Used to resolve the |
|
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) |
|
* of values. |
|
*/ |
|
var nativeObjectToString = objectProto.toString; |
|
|
|
/** Used to infer the `Object` constructor. */ |
|
var objectCtorString = funcToString.call(Object); |
|
|
|
/** Used to restore the original `_` reference in `_.noConflict`. */ |
|
var oldDash = root._; |
|
|
|
/** Used to detect if a method is native. */ |
|
var reIsNative = RegExp('^' + |
|
funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') |
|
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' |
|
); |
|
|
|
/** Built-in value references. */ |
|
var Buffer = moduleExports ? root.Buffer : undefined, |
|
Symbol = root.Symbol, |
|
Uint8Array = root.Uint8Array, |
|
allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, |
|
getPrototype = overArg(Object.getPrototypeOf, Object), |
|
objectCreate = Object.create, |
|
propertyIsEnumerable = objectProto.propertyIsEnumerable, |
|
splice = arrayProto.splice, |
|
spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, |
|
symIterator = Symbol ? Symbol.iterator : undefined, |
|
symToStringTag = Symbol ? Symbol.toStringTag : undefined; |
|
|
|
var defineProperty = (function() { |
|
try { |
|
var func = getNative(Object, 'defineProperty'); |
|
func({}, '', {}); |
|
return func; |
|
} catch (e) {} |
|
}()); |
|
|
|
/* Built-in method references for those with the same name as other `lodash` methods. */ |
|
var nativeCeil = Math.ceil, |
|
nativeFloor = Math.floor, |
|
nativeGetSymbols = Object.getOwnPropertySymbols, |
|
nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, |
|
nativeIsFinite = root.isFinite, |
|
nativeKeys = overArg(Object.keys, Object), |
|
nativeMax = Math.max, |
|
nativeMin = Math.min, |
|
nativeNow = Date.now, |
|
nativeRandom = Math.random, |
|
nativeReverse = arrayProto.reverse; |
|
|
|
/* Built-in method references that are verified to be native. */ |
|
var DataView = getNative(root, 'DataView'), |
|
Map = getNative(root, 'Map'), |
|
Promise = getNative(root, 'Promise'), |
|
Set = getNative(root, 'Set'), |
|
WeakMap = getNative(root, 'WeakMap'), |
|
nativeCreate = getNative(Object, 'create'); |
|
|
|
/** Used to store function metadata. */ |
|
var metaMap = WeakMap && new WeakMap; |
|
|
|
/** Used to lookup unminified function names. */ |
|
var realNames = {}; |
|
|
|
/** Used to detect maps, sets, and weakmaps. */ |
|
var dataViewCtorString = toSource(DataView), |
|
mapCtorString = toSource(Map), |
|
promiseCtorString = toSource(Promise), |
|
setCtorString = toSource(Set), |
|
weakMapCtorString = toSource(WeakMap); |
|
|
|
/** Used to convert symbols to primitives and strings. */ |
|
var symbolProto = Symbol ? Symbol.prototype : undefined, |
|
symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, |
|
symbolToString = symbolProto ? symbolProto.toString : undefined; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a `lodash` object which wraps `value` to enable implicit method |
|
* chain sequences. Methods that operate on and return arrays, collections, |
|
* and functions can be chained together. Methods that retrieve a single value |
|
* or may return a primitive value will automatically end the chain sequence |
|
* and return the unwrapped value. Otherwise, the value must be unwrapped |
|
* with `_#value`. |
|
* |
|
* Explicit chain sequences, which must be unwrapped with `_#value`, may be |
|
* enabled using `_.chain`. |
|
* |
|
* The execution of chained methods is lazy, that is, it's deferred until |
|
* `_#value` is implicitly or explicitly called. |
|
* |
|
* Lazy evaluation allows several methods to support shortcut fusion. |
|
* Shortcut fusion is an optimization to merge iteratee calls; this avoids |
|
* the creation of intermediate arrays and can greatly reduce the number of |
|
* iteratee executions. Sections of a chain sequence qualify for shortcut |
|
* fusion if the section is applied to an array and iteratees accept only |
|
* one argument. The heuristic for whether a section qualifies for shortcut |
|
* fusion is subject to change. |
|
* |
|
* Chaining is supported in custom builds as long as the `_#value` method is |
|
* directly or indirectly included in the build. |
|
* |
|
* In addition to lodash methods, wrappers have `Array` and `String` methods. |
|
* |
|
* The wrapper `Array` methods are: |
|
* `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` |
|
* |
|
* The wrapper `String` methods are: |
|
* `replace` and `split` |
|
* |
|
* The wrapper methods that support shortcut fusion are: |
|
* `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, |
|
* `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, |
|
* `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` |
|
* |
|
* The chainable wrapper methods are: |
|
* `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, |
|
* `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, |
|
* `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, |
|
* `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, |
|
* `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, |
|
* `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, |
|
* `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, |
|
* `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, |
|
* `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, |
|
* `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, |
|
* `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, |
|
* `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, |
|
* `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, |
|
* `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, |
|
* `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, |
|
* `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, |
|
* `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, |
|
* `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, |
|
* `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, |
|
* `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, |
|
* `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, |
|
* `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, |
|
* `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, |
|
* `zipObject`, `zipObjectDeep`, and `zipWith` |
|
* |
|
* The wrapper methods that are **not** chainable by default are: |
|
* `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, |
|
* `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, |
|
* `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, |
|
* `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, |
|
* `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, |
|
* `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, |
|
* `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, |
|
* `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, |
|
* `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, |
|
* `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, |
|
* `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, |
|
* `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, |
|
* `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, |
|
* `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, |
|
* `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, |
|
* `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, |
|
* `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, |
|
* `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, |
|
* `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, |
|
* `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, |
|
* `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, |
|
* `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, |
|
* `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, |
|
* `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, |
|
* `upperFirst`, `value`, and `words` |
|
* |
|
* @name _ |
|
* @constructor |
|
* @category Seq |
|
* @param {*} value The value to wrap in a `lodash` instance. |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* function square(n) { |
|
* return n * n; |
|
* } |
|
* |
|
* var wrapped = _([1, 2, 3]); |
|
* |
|
* // Returns an unwrapped value. |
|
* wrapped.reduce(_.add); |
|
* // => 6 |
|
* |
|
* // Returns a wrapped value. |
|
* var squares = wrapped.map(square); |
|
* |
|
* _.isArray(squares); |
|
* // => false |
|
* |
|
* _.isArray(squares.value()); |
|
* // => true |
|
*/ |
|
function lodash(value) { |
|
if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { |
|
if (value instanceof LodashWrapper) { |
|
return value; |
|
} |
|
if (hasOwnProperty.call(value, '__wrapped__')) { |
|
return wrapperClone(value); |
|
} |
|
} |
|
return new LodashWrapper(value); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.create` without support for assigning |
|
* properties to the created object. |
|
* |
|
* @private |
|
* @param {Object} proto The object to inherit from. |
|
* @returns {Object} Returns the new object. |
|
*/ |
|
var baseCreate = (function() { |
|
function object() {} |
|
return function(proto) { |
|
if (!isObject(proto)) { |
|
return {}; |
|
} |
|
if (objectCreate) { |
|
return objectCreate(proto); |
|
} |
|
object.prototype = proto; |
|
var result = new object; |
|
object.prototype = undefined; |
|
return result; |
|
}; |
|
}()); |
|
|
|
/** |
|
* The function whose prototype chain sequence wrappers inherit from. |
|
* |
|
* @private |
|
*/ |
|
function baseLodash() { |
|
// No operation performed. |
|
} |
|
|
|
/** |
|
* The base constructor for creating `lodash` wrapper objects. |
|
* |
|
* @private |
|
* @param {*} value The value to wrap. |
|
* @param {boolean} [chainAll] Enable explicit method chain sequences. |
|
*/ |
|
function LodashWrapper(value, chainAll) { |
|
this.__wrapped__ = value; |
|
this.__actions__ = []; |
|
this.__chain__ = !!chainAll; |
|
this.__index__ = 0; |
|
this.__values__ = undefined; |
|
} |
|
|
|
// Ensure wrappers are instances of `baseLodash`. |
|
lodash.prototype = baseLodash.prototype; |
|
lodash.prototype.constructor = lodash; |
|
|
|
LodashWrapper.prototype = baseCreate(baseLodash.prototype); |
|
LodashWrapper.prototype.constructor = LodashWrapper; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. |
|
* |
|
* @private |
|
* @constructor |
|
* @param {*} value The value to wrap. |
|
*/ |
|
function LazyWrapper(value) { |
|
this.__wrapped__ = value; |
|
this.__actions__ = []; |
|
this.__dir__ = 1; |
|
this.__filtered__ = false; |
|
this.__iteratees__ = []; |
|
this.__takeCount__ = MAX_ARRAY_LENGTH; |
|
this.__views__ = []; |
|
} |
|
|
|
/** |
|
* Creates a clone of the lazy wrapper object. |
|
* |
|
* @private |
|
* @name clone |
|
* @memberOf LazyWrapper |
|
* @returns {Object} Returns the cloned `LazyWrapper` object. |
|
*/ |
|
function lazyClone() { |
|
var result = new LazyWrapper(this.__wrapped__); |
|
result.__actions__ = copyArray(this.__actions__); |
|
result.__dir__ = this.__dir__; |
|
result.__filtered__ = this.__filtered__; |
|
result.__iteratees__ = copyArray(this.__iteratees__); |
|
result.__takeCount__ = this.__takeCount__; |
|
result.__views__ = copyArray(this.__views__); |
|
return result; |
|
} |
|
|
|
/** |
|
* Reverses the direction of lazy iteration. |
|
* |
|
* @private |
|
* @name reverse |
|
* @memberOf LazyWrapper |
|
* @returns {Object} Returns the new reversed `LazyWrapper` object. |
|
*/ |
|
function lazyReverse() { |
|
if (this.__filtered__) { |
|
var result = new LazyWrapper(this); |
|
result.__dir__ = -1; |
|
result.__filtered__ = true; |
|
} else { |
|
result = this.clone(); |
|
result.__dir__ *= -1; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Extracts the unwrapped value from its lazy wrapper. |
|
* |
|
* @private |
|
* @name value |
|
* @memberOf LazyWrapper |
|
* @returns {*} Returns the unwrapped value. |
|
*/ |
|
function lazyValue() { |
|
var array = this.__wrapped__.value(), |
|
dir = this.__dir__, |
|
isArr = isArray(array), |
|
isRight = dir < 0, |
|
arrLength = isArr ? array.length : 0, |
|
view = getView(0, arrLength, this.__views__), |
|
start = view.start, |
|
end = view.end, |
|
length = end - start, |
|
index = isRight ? end : (start - 1), |
|
iteratees = this.__iteratees__, |
|
iterLength = iteratees.length, |
|
resIndex = 0, |
|
takeCount = nativeMin(length, this.__takeCount__); |
|
|
|
if (!isArr || (!isRight && arrLength == length && takeCount == length)) { |
|
return baseWrapperValue(array, this.__actions__); |
|
} |
|
var result = []; |
|
|
|
outer: |
|
while (length-- && resIndex < takeCount) { |
|
index += dir; |
|
|
|
var iterIndex = -1, |
|
value = array[index]; |
|
|
|
while (++iterIndex < iterLength) { |
|
var data = iteratees[iterIndex], |
|
iteratee = data.iteratee, |
|
type = data.type, |
|
computed = iteratee(value); |
|
|
|
if (type == LAZY_MAP_FLAG) { |
|
value = computed; |
|
} else if (!computed) { |
|
if (type == LAZY_FILTER_FLAG) { |
|
continue outer; |
|
} else { |
|
break outer; |
|
} |
|
} |
|
} |
|
result[resIndex++] = value; |
|
} |
|
return result; |
|
} |
|
|
|
// Ensure `LazyWrapper` is an instance of `baseLodash`. |
|
LazyWrapper.prototype = baseCreate(baseLodash.prototype); |
|
LazyWrapper.prototype.constructor = LazyWrapper; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a hash object. |
|
* |
|
* @private |
|
* @constructor |
|
* @param {Array} [entries] The key-value pairs to cache. |
|
*/ |
|
function Hash(entries) { |
|
var index = -1, |
|
length = entries == null ? 0 : entries.length; |
|
|
|
this.clear(); |
|
while (++index < length) { |
|
var entry = entries[index]; |
|
this.set(entry[0], entry[1]); |
|
} |
|
} |
|
|
|
/** |
|
* Removes all key-value entries from the hash. |
|
* |
|
* @private |
|
* @name clear |
|
* @memberOf Hash |
|
*/ |
|
function hashClear() { |
|
this.__data__ = nativeCreate ? nativeCreate(null) : {}; |
|
this.size = 0; |
|
} |
|
|
|
/** |
|
* Removes `key` and its value from the hash. |
|
* |
|
* @private |
|
* @name delete |
|
* @memberOf Hash |
|
* @param {Object} hash The hash to modify. |
|
* @param {string} key The key of the value to remove. |
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`. |
|
*/ |
|
function hashDelete(key) { |
|
var result = this.has(key) && delete this.__data__[key]; |
|
this.size -= result ? 1 : 0; |
|
return result; |
|
} |
|
|
|
/** |
|
* Gets the hash value for `key`. |
|
* |
|
* @private |
|
* @name get |
|
* @memberOf Hash |
|
* @param {string} key The key of the value to get. |
|
* @returns {*} Returns the entry value. |
|
*/ |
|
function hashGet(key) { |
|
var data = this.__data__; |
|
if (nativeCreate) { |
|
var result = data[key]; |
|
return result === HASH_UNDEFINED ? undefined : result; |
|
} |
|
return hasOwnProperty.call(data, key) ? data[key] : undefined; |
|
} |
|
|
|
/** |
|
* Checks if a hash value for `key` exists. |
|
* |
|
* @private |
|
* @name has |
|
* @memberOf Hash |
|
* @param {string} key The key of the entry to check. |
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
|
*/ |
|
function hashHas(key) { |
|
var data = this.__data__; |
|
return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); |
|
} |
|
|
|
/** |
|
* Sets the hash `key` to `value`. |
|
* |
|
* @private |
|
* @name set |
|
* @memberOf Hash |
|
* @param {string} key The key of the value to set. |
|
* @param {*} value The value to set. |
|
* @returns {Object} Returns the hash instance. |
|
*/ |
|
function hashSet(key, value) { |
|
var data = this.__data__; |
|
this.size += this.has(key) ? 0 : 1; |
|
data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; |
|
return this; |
|
} |
|
|
|
// Add methods to `Hash`. |
|
Hash.prototype.clear = hashClear; |
|
Hash.prototype['delete'] = hashDelete; |
|
Hash.prototype.get = hashGet; |
|
Hash.prototype.has = hashHas; |
|
Hash.prototype.set = hashSet; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates an list cache object. |
|
* |
|
* @private |
|
* @constructor |
|
* @param {Array} [entries] The key-value pairs to cache. |
|
*/ |
|
function ListCache(entries) { |
|
var index = -1, |
|
length = entries == null ? 0 : entries.length; |
|
|
|
this.clear(); |
|
while (++index < length) { |
|
var entry = entries[index]; |
|
this.set(entry[0], entry[1]); |
|
} |
|
} |
|
|
|
/** |
|
* Removes all key-value entries from the list cache. |
|
* |
|
* @private |
|
* @name clear |
|
* @memberOf ListCache |
|
*/ |
|
function listCacheClear() { |
|
this.__data__ = []; |
|
this.size = 0; |
|
} |
|
|
|
/** |
|
* Removes `key` and its value from the list cache. |
|
* |
|
* @private |
|
* @name delete |
|
* @memberOf ListCache |
|
* @param {string} key The key of the value to remove. |
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`. |
|
*/ |
|
function listCacheDelete(key) { |
|
var data = this.__data__, |
|
index = assocIndexOf(data, key); |
|
|
|
if (index < 0) { |
|
return false; |
|
} |
|
var lastIndex = data.length - 1; |
|
if (index == lastIndex) { |
|
data.pop(); |
|
} else { |
|
splice.call(data, index, 1); |
|
} |
|
--this.size; |
|
return true; |
|
} |
|
|
|
/** |
|
* Gets the list cache value for `key`. |
|
* |
|
* @private |
|
* @name get |
|
* @memberOf ListCache |
|
* @param {string} key The key of the value to get. |
|
* @returns {*} Returns the entry value. |
|
*/ |
|
function listCacheGet(key) { |
|
var data = this.__data__, |
|
index = assocIndexOf(data, key); |
|
|
|
return index < 0 ? undefined : data[index][1]; |
|
} |
|
|
|
/** |
|
* Checks if a list cache value for `key` exists. |
|
* |
|
* @private |
|
* @name has |
|
* @memberOf ListCache |
|
* @param {string} key The key of the entry to check. |
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
|
*/ |
|
function listCacheHas(key) { |
|
return assocIndexOf(this.__data__, key) > -1; |
|
} |
|
|
|
/** |
|
* Sets the list cache `key` to `value`. |
|
* |
|
* @private |
|
* @name set |
|
* @memberOf ListCache |
|
* @param {string} key The key of the value to set. |
|
* @param {*} value The value to set. |
|
* @returns {Object} Returns the list cache instance. |
|
*/ |
|
function listCacheSet(key, value) { |
|
var data = this.__data__, |
|
index = assocIndexOf(data, key); |
|
|
|
if (index < 0) { |
|
++this.size; |
|
data.push([key, value]); |
|
} else { |
|
data[index][1] = value; |
|
} |
|
return this; |
|
} |
|
|
|
// Add methods to `ListCache`. |
|
ListCache.prototype.clear = listCacheClear; |
|
ListCache.prototype['delete'] = listCacheDelete; |
|
ListCache.prototype.get = listCacheGet; |
|
ListCache.prototype.has = listCacheHas; |
|
ListCache.prototype.set = listCacheSet; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a map cache object to store key-value pairs. |
|
* |
|
* @private |
|
* @constructor |
|
* @param {Array} [entries] The key-value pairs to cache. |
|
*/ |
|
function MapCache(entries) { |
|
var index = -1, |
|
length = entries == null ? 0 : entries.length; |
|
|
|
this.clear(); |
|
while (++index < length) { |
|
var entry = entries[index]; |
|
this.set(entry[0], entry[1]); |
|
} |
|
} |
|
|
|
/** |
|
* Removes all key-value entries from the map. |
|
* |
|
* @private |
|
* @name clear |
|
* @memberOf MapCache |
|
*/ |
|
function mapCacheClear() { |
|
this.size = 0; |
|
this.__data__ = { |
|
'hash': new Hash, |
|
'map': new (Map || ListCache), |
|
'string': new Hash |
|
}; |
|
} |
|
|
|
/** |
|
* Removes `key` and its value from the map. |
|
* |
|
* @private |
|
* @name delete |
|
* @memberOf MapCache |
|
* @param {string} key The key of the value to remove. |
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`. |
|
*/ |
|
function mapCacheDelete(key) { |
|
var result = getMapData(this, key)['delete'](key); |
|
this.size -= result ? 1 : 0; |
|
return result; |
|
} |
|
|
|
/** |
|
* Gets the map value for `key`. |
|
* |
|
* @private |
|
* @name get |
|
* @memberOf MapCache |
|
* @param {string} key The key of the value to get. |
|
* @returns {*} Returns the entry value. |
|
*/ |
|
function mapCacheGet(key) { |
|
return getMapData(this, key).get(key); |
|
} |
|
|
|
/** |
|
* Checks if a map value for `key` exists. |
|
* |
|
* @private |
|
* @name has |
|
* @memberOf MapCache |
|
* @param {string} key The key of the entry to check. |
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
|
*/ |
|
function mapCacheHas(key) { |
|
return getMapData(this, key).has(key); |
|
} |
|
|
|
/** |
|
* Sets the map `key` to `value`. |
|
* |
|
* @private |
|
* @name set |
|
* @memberOf MapCache |
|
* @param {string} key The key of the value to set. |
|
* @param {*} value The value to set. |
|
* @returns {Object} Returns the map cache instance. |
|
*/ |
|
function mapCacheSet(key, value) { |
|
var data = getMapData(this, key), |
|
size = data.size; |
|
|
|
data.set(key, value); |
|
this.size += data.size == size ? 0 : 1; |
|
return this; |
|
} |
|
|
|
// Add methods to `MapCache`. |
|
MapCache.prototype.clear = mapCacheClear; |
|
MapCache.prototype['delete'] = mapCacheDelete; |
|
MapCache.prototype.get = mapCacheGet; |
|
MapCache.prototype.has = mapCacheHas; |
|
MapCache.prototype.set = mapCacheSet; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* |
|
* Creates an array cache object to store unique values. |
|
* |
|
* @private |
|
* @constructor |
|
* @param {Array} [values] The values to cache. |
|
*/ |
|
function SetCache(values) { |
|
var index = -1, |
|
length = values == null ? 0 : values.length; |
|
|
|
this.__data__ = new MapCache; |
|
while (++index < length) { |
|
this.add(values[index]); |
|
} |
|
} |
|
|
|
/** |
|
* Adds `value` to the array cache. |
|
* |
|
* @private |
|
* @name add |
|
* @memberOf SetCache |
|
* @alias push |
|
* @param {*} value The value to cache. |
|
* @returns {Object} Returns the cache instance. |
|
*/ |
|
function setCacheAdd(value) { |
|
this.__data__.set(value, HASH_UNDEFINED); |
|
return this; |
|
} |
|
|
|
/** |
|
* Checks if `value` is in the array cache. |
|
* |
|
* @private |
|
* @name has |
|
* @memberOf SetCache |
|
* @param {*} value The value to search for. |
|
* @returns {number} Returns `true` if `value` is found, else `false`. |
|
*/ |
|
function setCacheHas(value) { |
|
return this.__data__.has(value); |
|
} |
|
|
|
// Add methods to `SetCache`. |
|
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; |
|
SetCache.prototype.has = setCacheHas; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a stack cache object to store key-value pairs. |
|
* |
|
* @private |
|
* @constructor |
|
* @param {Array} [entries] The key-value pairs to cache. |
|
*/ |
|
function Stack(entries) { |
|
var data = this.__data__ = new ListCache(entries); |
|
this.size = data.size; |
|
} |
|
|
|
/** |
|
* Removes all key-value entries from the stack. |
|
* |
|
* @private |
|
* @name clear |
|
* @memberOf Stack |
|
*/ |
|
function stackClear() { |
|
this.__data__ = new ListCache; |
|
this.size = 0; |
|
} |
|
|
|
/** |
|
* Removes `key` and its value from the stack. |
|
* |
|
* @private |
|
* @name delete |
|
* @memberOf Stack |
|
* @param {string} key The key of the value to remove. |
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`. |
|
*/ |
|
function stackDelete(key) { |
|
var data = this.__data__, |
|
result = data['delete'](key); |
|
|
|
this.size = data.size; |
|
return result; |
|
} |
|
|
|
/** |
|
* Gets the stack value for `key`. |
|
* |
|
* @private |
|
* @name get |
|
* @memberOf Stack |
|
* @param {string} key The key of the value to get. |
|
* @returns {*} Returns the entry value. |
|
*/ |
|
function stackGet(key) { |
|
return this.__data__.get(key); |
|
} |
|
|
|
/** |
|
* Checks if a stack value for `key` exists. |
|
* |
|
* @private |
|
* @name has |
|
* @memberOf Stack |
|
* @param {string} key The key of the entry to check. |
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
|
*/ |
|
function stackHas(key) { |
|
return this.__data__.has(key); |
|
} |
|
|
|
/** |
|
* Sets the stack `key` to `value`. |
|
* |
|
* @private |
|
* @name set |
|
* @memberOf Stack |
|
* @param {string} key The key of the value to set. |
|
* @param {*} value The value to set. |
|
* @returns {Object} Returns the stack cache instance. |
|
*/ |
|
function stackSet(key, value) { |
|
var data = this.__data__; |
|
if (data instanceof ListCache) { |
|
var pairs = data.__data__; |
|
if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { |
|
pairs.push([key, value]); |
|
this.size = ++data.size; |
|
return this; |
|
} |
|
data = this.__data__ = new MapCache(pairs); |
|
} |
|
data.set(key, value); |
|
this.size = data.size; |
|
return this; |
|
} |
|
|
|
// Add methods to `Stack`. |
|
Stack.prototype.clear = stackClear; |
|
Stack.prototype['delete'] = stackDelete; |
|
Stack.prototype.get = stackGet; |
|
Stack.prototype.has = stackHas; |
|
Stack.prototype.set = stackSet; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates an array of the enumerable property names of the array-like `value`. |
|
* |
|
* @private |
|
* @param {*} value The value to query. |
|
* @param {boolean} inherited Specify returning inherited property names. |
|
* @returns {Array} Returns the array of property names. |
|
*/ |
|
function arrayLikeKeys(value, inherited) { |
|
var isArr = isArray(value), |
|
isArg = !isArr && isArguments(value), |
|
isBuff = !isArr && !isArg && isBuffer(value), |
|
isType = !isArr && !isArg && !isBuff && isTypedArray(value), |
|
skipIndexes = isArr || isArg || isBuff || isType, |
|
result = skipIndexes ? baseTimes(value.length, String) : [], |
|
length = result.length; |
|
|
|
for (var key in value) { |
|
if ((inherited || hasOwnProperty.call(value, key)) && |
|
!(skipIndexes && ( |
|
// Safari 9 has enumerable `arguments.length` in strict mode. |
|
key == 'length' || |
|
// Node.js 0.10 has enumerable non-index properties on buffers. |
|
(isBuff && (key == 'offset' || key == 'parent')) || |
|
// PhantomJS 2 has enumerable non-index properties on typed arrays. |
|
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || |
|
// Skip index properties. |
|
isIndex(key, length) |
|
))) { |
|
result.push(key); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* This function is like `assignValue` except that it doesn't assign |
|
* `undefined` values. |
|
* |
|
* @private |
|
* @param {Object} object The object to modify. |
|
* @param {string} key The key of the property to assign. |
|
* @param {*} value The value to assign. |
|
*/ |
|
function assignMergeValue(object, key, value) { |
|
if ((value !== undefined && !eq(object[key], value)) || |
|
(value === undefined && !(key in object))) { |
|
baseAssignValue(object, key, value); |
|
} |
|
} |
|
|
|
/** |
|
* Assigns `value` to `key` of `object` if the existing value is not equivalent |
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons. |
|
* |
|
* @private |
|
* @param {Object} object The object to modify. |
|
* @param {string} key The key of the property to assign. |
|
* @param {*} value The value to assign. |
|
*/ |
|
function assignValue(object, key, value) { |
|
var objValue = object[key]; |
|
if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || |
|
(value === undefined && !(key in object))) { |
|
baseAssignValue(object, key, value); |
|
} |
|
} |
|
|
|
/** |
|
* Gets the index at which the `key` is found in `array` of key-value pairs. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {*} key The key to search for. |
|
* @returns {number} Returns the index of the matched value, else `-1`. |
|
*/ |
|
function assocIndexOf(array, key) { |
|
var length = array.length; |
|
while (length--) { |
|
if (eq(array[length][0], key)) { |
|
return length; |
|
} |
|
} |
|
return -1; |
|
} |
|
|
|
/** |
|
* Aggregates elements of `collection` on `accumulator` with keys transformed |
|
* by `iteratee` and values set by `setter`. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} setter The function to set `accumulator` values. |
|
* @param {Function} iteratee The iteratee to transform keys. |
|
* @param {Object} accumulator The initial aggregated object. |
|
* @returns {Function} Returns `accumulator`. |
|
*/ |
|
function baseAggregator(collection, setter, iteratee, accumulator) { |
|
baseEach(collection, function(value, key, collection) { |
|
setter(accumulator, value, iteratee(value), collection); |
|
}); |
|
return accumulator; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.assign` without support for multiple sources |
|
* or `customizer` functions. |
|
* |
|
* @private |
|
* @param {Object} object The destination object. |
|
* @param {Object} source The source object. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function baseAssign(object, source) { |
|
return object && copyObject(source, keys(source), object); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.assignIn` without support for multiple sources |
|
* or `customizer` functions. |
|
* |
|
* @private |
|
* @param {Object} object The destination object. |
|
* @param {Object} source The source object. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function baseAssignIn(object, source) { |
|
return object && copyObject(source, keysIn(source), object); |
|
} |
|
|
|
/** |
|
* The base implementation of `assignValue` and `assignMergeValue` without |
|
* value checks. |
|
* |
|
* @private |
|
* @param {Object} object The object to modify. |
|
* @param {string} key The key of the property to assign. |
|
* @param {*} value The value to assign. |
|
*/ |
|
function baseAssignValue(object, key, value) { |
|
if (key == '__proto__' && defineProperty) { |
|
defineProperty(object, key, { |
|
'configurable': true, |
|
'enumerable': true, |
|
'value': value, |
|
'writable': true |
|
}); |
|
} else { |
|
object[key] = value; |
|
} |
|
} |
|
|
|
/** |
|
* The base implementation of `_.at` without support for individual paths. |
|
* |
|
* @private |
|
* @param {Object} object The object to iterate over. |
|
* @param {string[]} paths The property paths to pick. |
|
* @returns {Array} Returns the picked elements. |
|
*/ |
|
function baseAt(object, paths) { |
|
var index = -1, |
|
length = paths.length, |
|
result = Array(length), |
|
skip = object == null; |
|
|
|
while (++index < length) { |
|
result[index] = skip ? undefined : get(object, paths[index]); |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.clamp` which doesn't coerce arguments. |
|
* |
|
* @private |
|
* @param {number} number The number to clamp. |
|
* @param {number} [lower] The lower bound. |
|
* @param {number} upper The upper bound. |
|
* @returns {number} Returns the clamped number. |
|
*/ |
|
function baseClamp(number, lower, upper) { |
|
if (number === number) { |
|
if (upper !== undefined) { |
|
number = number <= upper ? number : upper; |
|
} |
|
if (lower !== undefined) { |
|
number = number >= lower ? number : lower; |
|
} |
|
} |
|
return number; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.clone` and `_.cloneDeep` which tracks |
|
* traversed objects. |
|
* |
|
* @private |
|
* @param {*} value The value to clone. |
|
* @param {boolean} bitmask The bitmask flags. |
|
* 1 - Deep clone |
|
* 2 - Flatten inherited properties |
|
* 4 - Clone symbols |
|
* @param {Function} [customizer] The function to customize cloning. |
|
* @param {string} [key] The key of `value`. |
|
* @param {Object} [object] The parent object of `value`. |
|
* @param {Object} [stack] Tracks traversed objects and their clone counterparts. |
|
* @returns {*} Returns the cloned value. |
|
*/ |
|
function baseClone(value, bitmask, customizer, key, object, stack) { |
|
var result, |
|
isDeep = bitmask & CLONE_DEEP_FLAG, |
|
isFlat = bitmask & CLONE_FLAT_FLAG, |
|
isFull = bitmask & CLONE_SYMBOLS_FLAG; |
|
|
|
if (customizer) { |
|
result = object ? customizer(value, key, object, stack) : customizer(value); |
|
} |
|
if (result !== undefined) { |
|
return result; |
|
} |
|
if (!isObject(value)) { |
|
return value; |
|
} |
|
var isArr = isArray(value); |
|
if (isArr) { |
|
result = initCloneArray(value); |
|
if (!isDeep) { |
|
return copyArray(value, result); |
|
} |
|
} else { |
|
var tag = getTag(value), |
|
isFunc = tag == funcTag || tag == genTag; |
|
|
|
if (isBuffer(value)) { |
|
return cloneBuffer(value, isDeep); |
|
} |
|
if (tag == objectTag || tag == argsTag || (isFunc && !object)) { |
|
result = (isFlat || isFunc) ? {} : initCloneObject(value); |
|
if (!isDeep) { |
|
return isFlat |
|
? copySymbolsIn(value, baseAssignIn(result, value)) |
|
: copySymbols(value, baseAssign(result, value)); |
|
} |
|
} else { |
|
if (!cloneableTags[tag]) { |
|
return object ? value : {}; |
|
} |
|
result = initCloneByTag(value, tag, isDeep); |
|
} |
|
} |
|
// Check for circular references and return its corresponding clone. |
|
stack || (stack = new Stack); |
|
var stacked = stack.get(value); |
|
if (stacked) { |
|
return stacked; |
|
} |
|
stack.set(value, result); |
|
|
|
if (isSet(value)) { |
|
value.forEach(function(subValue) { |
|
result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); |
|
}); |
|
|
|
return result; |
|
} |
|
|
|
if (isMap(value)) { |
|
value.forEach(function(subValue, key) { |
|
result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); |
|
}); |
|
|
|
return result; |
|
} |
|
|
|
var keysFunc = isFull |
|
? (isFlat ? getAllKeysIn : getAllKeys) |
|
: (isFlat ? keysIn : keys); |
|
|
|
var props = isArr ? undefined : keysFunc(value); |
|
arrayEach(props || value, function(subValue, key) { |
|
if (props) { |
|
key = subValue; |
|
subValue = value[key]; |
|
} |
|
// Recursively populate clone (susceptible to call stack limits). |
|
assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.delay` and `_.defer` which accepts `args` |
|
* to provide to `func`. |
|
* |
|
* @private |
|
* @param {Function} func The function to delay. |
|
* @param {number} wait The number of milliseconds to delay invocation. |
|
* @param {Array} args The arguments to provide to `func`. |
|
* @returns {number|Object} Returns the timer id or timeout object. |
|
*/ |
|
function baseDelay(func, wait, args) { |
|
if (typeof func != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
return setTimeout(function() { func.apply(undefined, args); }, wait); |
|
} |
|
|
|
/** |
|
* The base implementation of methods like `_.difference` without support |
|
* for excluding multiple arrays or iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {Array} values The values to exclude. |
|
* @param {Function} [iteratee] The iteratee invoked per element. |
|
* @param {Function} [comparator] The comparator invoked per element. |
|
* @returns {Array} Returns the new array of filtered values. |
|
*/ |
|
function baseDifference(array, values, iteratee, comparator) { |
|
var index = -1, |
|
includes = arrayIncludes, |
|
isCommon = true, |
|
length = array.length, |
|
result = [], |
|
valuesLength = values.length; |
|
|
|
if (!length) { |
|
return result; |
|
} |
|
if (iteratee) { |
|
values = arrayMap(values, baseUnary(iteratee)); |
|
} |
|
if (comparator) { |
|
includes = arrayIncludesWith; |
|
isCommon = false; |
|
} |
|
else if (values.length >= LARGE_ARRAY_SIZE) { |
|
includes = cacheHas; |
|
isCommon = false; |
|
values = new SetCache(values); |
|
} |
|
outer: |
|
while (++index < length) { |
|
var value = array[index], |
|
computed = iteratee == null ? value : iteratee(value); |
|
|
|
value = (comparator || value !== 0) ? value : 0; |
|
if (isCommon && computed === computed) { |
|
var valuesIndex = valuesLength; |
|
while (valuesIndex--) { |
|
if (values[valuesIndex] === computed) { |
|
continue outer; |
|
} |
|
} |
|
result.push(value); |
|
} |
|
else if (!includes(values, computed, comparator)) { |
|
result.push(value); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.forEach` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Array|Object} Returns `collection`. |
|
*/ |
|
var baseEach = createBaseEach(baseForOwn); |
|
|
|
/** |
|
* The base implementation of `_.every` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @returns {boolean} Returns `true` if all elements pass the predicate check, |
|
* else `false` |
|
*/ |
|
function baseEvery(collection, predicate) { |
|
var result = true; |
|
baseEach(collection, function(value, index, collection) { |
|
result = !!predicate(value, index, collection); |
|
return result; |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of methods like `_.max` and `_.min` which accepts a |
|
* `comparator` to determine the extremum value. |
|
* |
|
* @private |
|
* @param {Array} array The array to iterate over. |
|
* @param {Function} iteratee The iteratee invoked per iteration. |
|
* @param {Function} comparator The comparator used to compare values. |
|
* @returns {*} Returns the extremum value. |
|
*/ |
|
function baseExtremum(array, iteratee, comparator) { |
|
var index = -1, |
|
length = array.length; |
|
|
|
while (++index < length) { |
|
var value = array[index], |
|
current = iteratee(value); |
|
|
|
if (current != null && (computed === undefined |
|
? (current === current && !isSymbol(current)) |
|
: comparator(current, computed) |
|
)) { |
|
var computed = current, |
|
result = value; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.filter` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @returns {Array} Returns the new filtered array. |
|
*/ |
|
function baseFilter(collection, predicate) { |
|
var result = []; |
|
baseEach(collection, function(value, index, collection) { |
|
if (predicate(value, index, collection)) { |
|
result.push(value); |
|
} |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.flatten` with support for restricting flattening. |
|
* |
|
* @private |
|
* @param {Array} array The array to flatten. |
|
* @param {number} depth The maximum recursion depth. |
|
* @param {boolean} [predicate=isFlattenable] The function invoked per iteration. |
|
* @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. |
|
* @param {Array} [result=[]] The initial result value. |
|
* @returns {Array} Returns the new flattened array. |
|
*/ |
|
function baseFlatten(array, depth, predicate, isStrict, result) { |
|
var index = -1, |
|
length = array.length; |
|
|
|
predicate || (predicate = isFlattenable); |
|
result || (result = []); |
|
|
|
while (++index < length) { |
|
var value = array[index]; |
|
if (depth > 0 && predicate(value)) { |
|
if (depth > 1) { |
|
// Recursively flatten arrays (susceptible to call stack limits). |
|
baseFlatten(value, depth - 1, predicate, isStrict, result); |
|
} else { |
|
arrayPush(result, value); |
|
} |
|
} else if (!isStrict) { |
|
result[result.length] = value; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `baseForOwn` which iterates over `object` |
|
* properties returned by `keysFunc` and invokes `iteratee` for each property. |
|
* Iteratee functions may exit iteration early by explicitly returning `false`. |
|
* |
|
* @private |
|
* @param {Object} object The object to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @param {Function} keysFunc The function to get the keys of `object`. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
var baseFor = createBaseFor(); |
|
|
|
/** |
|
* This function is like `baseFor` except that it iterates over properties |
|
* in the opposite order. |
|
* |
|
* @private |
|
* @param {Object} object The object to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @param {Function} keysFunc The function to get the keys of `object`. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
var baseForRight = createBaseFor(true); |
|
|
|
/** |
|
* The base implementation of `_.forOwn` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Object} object The object to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function baseForOwn(object, iteratee) { |
|
return object && baseFor(object, iteratee, keys); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.forOwnRight` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Object} object The object to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function baseForOwnRight(object, iteratee) { |
|
return object && baseForRight(object, iteratee, keys); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.functions` which creates an array of |
|
* `object` function property names filtered from `props`. |
|
* |
|
* @private |
|
* @param {Object} object The object to inspect. |
|
* @param {Array} props The property names to filter. |
|
* @returns {Array} Returns the function names. |
|
*/ |
|
function baseFunctions(object, props) { |
|
return arrayFilter(props, function(key) { |
|
return isFunction(object[key]); |
|
}); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.get` without support for default values. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path of the property to get. |
|
* @returns {*} Returns the resolved value. |
|
*/ |
|
function baseGet(object, path) { |
|
path = castPath(path, object); |
|
|
|
var index = 0, |
|
length = path.length; |
|
|
|
while (object != null && index < length) { |
|
object = object[toKey(path[index++])]; |
|
} |
|
return (index && index == length) ? object : undefined; |
|
} |
|
|
|
/** |
|
* The base implementation of `getAllKeys` and `getAllKeysIn` which uses |
|
* `keysFunc` and `symbolsFunc` to get the enumerable property names and |
|
* symbols of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {Function} keysFunc The function to get the keys of `object`. |
|
* @param {Function} symbolsFunc The function to get the symbols of `object`. |
|
* @returns {Array} Returns the array of property names and symbols. |
|
*/ |
|
function baseGetAllKeys(object, keysFunc, symbolsFunc) { |
|
var result = keysFunc(object); |
|
return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); |
|
} |
|
|
|
/** |
|
* The base implementation of `getTag` without fallbacks for buggy environments. |
|
* |
|
* @private |
|
* @param {*} value The value to query. |
|
* @returns {string} Returns the `toStringTag`. |
|
*/ |
|
function baseGetTag(value) { |
|
if (value == null) { |
|
return value === undefined ? undefinedTag : nullTag; |
|
} |
|
return (symToStringTag && symToStringTag in Object(value)) |
|
? getRawTag(value) |
|
: objectToString(value); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.gt` which doesn't coerce arguments. |
|
* |
|
* @private |
|
* @param {*} value The value to compare. |
|
* @param {*} other The other value to compare. |
|
* @returns {boolean} Returns `true` if `value` is greater than `other`, |
|
* else `false`. |
|
*/ |
|
function baseGt(value, other) { |
|
return value > other; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.has` without support for deep paths. |
|
* |
|
* @private |
|
* @param {Object} [object] The object to query. |
|
* @param {Array|string} key The key to check. |
|
* @returns {boolean} Returns `true` if `key` exists, else `false`. |
|
*/ |
|
function baseHas(object, key) { |
|
return object != null && hasOwnProperty.call(object, key); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.hasIn` without support for deep paths. |
|
* |
|
* @private |
|
* @param {Object} [object] The object to query. |
|
* @param {Array|string} key The key to check. |
|
* @returns {boolean} Returns `true` if `key` exists, else `false`. |
|
*/ |
|
function baseHasIn(object, key) { |
|
return object != null && key in Object(object); |
|
} |
|
|
|
/** |
|
* The base implementation of methods like `_.intersection`, without support |
|
* for iteratee shorthands, that accepts an array of arrays to inspect. |
|
* |
|
* @private |
|
* @param {Array} arrays The arrays to inspect. |
|
* @param {Function} [iteratee] The iteratee invoked per element. |
|
* @param {Function} [comparator] The comparator invoked per element. |
|
* @returns {Array} Returns the new array of shared values. |
|
*/ |
|
function baseIntersection(arrays, iteratee, comparator) { |
|
var includes = comparator ? arrayIncludesWith : arrayIncludes, |
|
length = arrays[0].length, |
|
othLength = arrays.length, |
|
othIndex = othLength, |
|
caches = Array(othLength), |
|
maxLength = Infinity, |
|
result = []; |
|
|
|
while (othIndex--) { |
|
var array = arrays[othIndex]; |
|
if (othIndex && iteratee) { |
|
array = arrayMap(array, baseUnary(iteratee)); |
|
} |
|
maxLength = nativeMin(array.length, maxLength); |
|
caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) |
|
? new SetCache(othIndex && array) |
|
: undefined; |
|
} |
|
array = arrays[0]; |
|
|
|
var index = -1, |
|
seen = caches[0]; |
|
|
|
outer: |
|
while (++index < length && result.length < maxLength) { |
|
var value = array[index], |
|
computed = iteratee ? iteratee(value) : value; |
|
|
|
value = (comparator || value !== 0) ? value : 0; |
|
if (!(seen |
|
? cacheHas(seen, computed) |
|
: includes(result, computed, comparator) |
|
)) { |
|
othIndex = othLength; |
|
while (--othIndex) { |
|
var cache = caches[othIndex]; |
|
if (!(cache |
|
? cacheHas(cache, computed) |
|
: includes(arrays[othIndex], computed, comparator)) |
|
) { |
|
continue outer; |
|
} |
|
} |
|
if (seen) { |
|
seen.push(computed); |
|
} |
|
result.push(value); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.invert` and `_.invertBy` which inverts |
|
* `object` with values transformed by `iteratee` and set by `setter`. |
|
* |
|
* @private |
|
* @param {Object} object The object to iterate over. |
|
* @param {Function} setter The function to set `accumulator` values. |
|
* @param {Function} iteratee The iteratee to transform values. |
|
* @param {Object} accumulator The initial inverted object. |
|
* @returns {Function} Returns `accumulator`. |
|
*/ |
|
function baseInverter(object, setter, iteratee, accumulator) { |
|
baseForOwn(object, function(value, key, object) { |
|
setter(accumulator, iteratee(value), key, object); |
|
}); |
|
return accumulator; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.invoke` without support for individual |
|
* method arguments. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path of the method to invoke. |
|
* @param {Array} args The arguments to invoke the method with. |
|
* @returns {*} Returns the result of the invoked method. |
|
*/ |
|
function baseInvoke(object, path, args) { |
|
path = castPath(path, object); |
|
object = parent(object, path); |
|
var func = object == null ? object : object[toKey(last(path))]; |
|
return func == null ? undefined : apply(func, object, args); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isArguments`. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is an `arguments` object, |
|
*/ |
|
function baseIsArguments(value) { |
|
return isObjectLike(value) && baseGetTag(value) == argsTag; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isDate` without Node.js optimizations. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a date object, else `false`. |
|
*/ |
|
function baseIsDate(value) { |
|
return isObjectLike(value) && baseGetTag(value) == dateTag; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isEqual` which supports partial comparisons |
|
* and tracks traversed objects. |
|
* |
|
* @private |
|
* @param {*} value The value to compare. |
|
* @param {*} other The other value to compare. |
|
* @param {boolean} bitmask The bitmask flags. |
|
* 1 - Unordered comparison |
|
* 2 - Partial comparison |
|
* @param {Function} [customizer] The function to customize comparisons. |
|
* @param {Object} [stack] Tracks traversed `value` and `other` objects. |
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`. |
|
*/ |
|
function baseIsEqual(value, other, bitmask, customizer, stack) { |
|
if (value === other) { |
|
return true; |
|
} |
|
if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { |
|
return value !== value && other !== other; |
|
} |
|
return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); |
|
} |
|
|
|
/** |
|
* A specialized version of `baseIsEqual` for arrays and objects which performs |
|
* deep comparisons and tracks traversed objects enabling objects with circular |
|
* references to be compared. |
|
* |
|
* @private |
|
* @param {Object} object The object to compare. |
|
* @param {Object} other The other object to compare. |
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. |
|
* @param {Function} customizer The function to customize comparisons. |
|
* @param {Function} equalFunc The function to determine equivalents of values. |
|
* @param {Object} [stack] Tracks traversed `object` and `other` objects. |
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`. |
|
*/ |
|
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { |
|
var objIsArr = isArray(object), |
|
othIsArr = isArray(other), |
|
objTag = objIsArr ? arrayTag : getTag(object), |
|
othTag = othIsArr ? arrayTag : getTag(other); |
|
|
|
objTag = objTag == argsTag ? objectTag : objTag; |
|
othTag = othTag == argsTag ? objectTag : othTag; |
|
|
|
var objIsObj = objTag == objectTag, |
|
othIsObj = othTag == objectTag, |
|
isSameTag = objTag == othTag; |
|
|
|
if (isSameTag && isBuffer(object)) { |
|
if (!isBuffer(other)) { |
|
return false; |
|
} |
|
objIsArr = true; |
|
objIsObj = false; |
|
} |
|
if (isSameTag && !objIsObj) { |
|
stack || (stack = new Stack); |
|
return (objIsArr || isTypedArray(object)) |
|
? equalArrays(object, other, bitmask, customizer, equalFunc, stack) |
|
: equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); |
|
} |
|
if (!(bitmask & COMPARE_PARTIAL_FLAG)) { |
|
var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), |
|
othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); |
|
|
|
if (objIsWrapped || othIsWrapped) { |
|
var objUnwrapped = objIsWrapped ? object.value() : object, |
|
othUnwrapped = othIsWrapped ? other.value() : other; |
|
|
|
stack || (stack = new Stack); |
|
return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); |
|
} |
|
} |
|
if (!isSameTag) { |
|
return false; |
|
} |
|
stack || (stack = new Stack); |
|
return equalObjects(object, other, bitmask, customizer, equalFunc, stack); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isMap` without Node.js optimizations. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a map, else `false`. |
|
*/ |
|
function baseIsMap(value) { |
|
return isObjectLike(value) && getTag(value) == mapTag; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isMatch` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Object} object The object to inspect. |
|
* @param {Object} source The object of property values to match. |
|
* @param {Array} matchData The property names, values, and compare flags to match. |
|
* @param {Function} [customizer] The function to customize comparisons. |
|
* @returns {boolean} Returns `true` if `object` is a match, else `false`. |
|
*/ |
|
function baseIsMatch(object, source, matchData, customizer) { |
|
var index = matchData.length, |
|
length = index, |
|
noCustomizer = !customizer; |
|
|
|
if (object == null) { |
|
return !length; |
|
} |
|
object = Object(object); |
|
while (index--) { |
|
var data = matchData[index]; |
|
if ((noCustomizer && data[2]) |
|
? data[1] !== object[data[0]] |
|
: !(data[0] in object) |
|
) { |
|
return false; |
|
} |
|
} |
|
while (++index < length) { |
|
data = matchData[index]; |
|
var key = data[0], |
|
objValue = object[key], |
|
srcValue = data[1]; |
|
|
|
if (noCustomizer && data[2]) { |
|
if (objValue === undefined && !(key in object)) { |
|
return false; |
|
} |
|
} else { |
|
var stack = new Stack; |
|
if (customizer) { |
|
var result = customizer(objValue, srcValue, key, object, source, stack); |
|
} |
|
if (!(result === undefined |
|
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) |
|
: result |
|
)) { |
|
return false; |
|
} |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isNative` without bad shim checks. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a native function, |
|
* else `false`. |
|
*/ |
|
function baseIsNative(value) { |
|
if (!isObject(value) || isMasked(value)) { |
|
return false; |
|
} |
|
var pattern = isFunction(value) ? reIsNative : reIsHostCtor; |
|
return pattern.test(toSource(value)); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isRegExp` without Node.js optimizations. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`. |
|
*/ |
|
function baseIsRegExp(value) { |
|
return isObjectLike(value) && baseGetTag(value) == regexpTag; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isSet` without Node.js optimizations. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a set, else `false`. |
|
*/ |
|
function baseIsSet(value) { |
|
return isObjectLike(value) && getTag(value) == setTag; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.isTypedArray` without Node.js optimizations. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`. |
|
*/ |
|
function baseIsTypedArray(value) { |
|
return isObjectLike(value) && |
|
isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.iteratee`. |
|
* |
|
* @private |
|
* @param {*} [value=_.identity] The value to convert to an iteratee. |
|
* @returns {Function} Returns the iteratee. |
|
*/ |
|
function baseIteratee(value) { |
|
// Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. |
|
// See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. |
|
if (typeof value == 'function') { |
|
return value; |
|
} |
|
if (value == null) { |
|
return identity; |
|
} |
|
if (typeof value == 'object') { |
|
return isArray(value) |
|
? baseMatchesProperty(value[0], value[1]) |
|
: baseMatches(value); |
|
} |
|
return property(value); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.keys` which doesn't treat sparse arrays as dense. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names. |
|
*/ |
|
function baseKeys(object) { |
|
if (!isPrototype(object)) { |
|
return nativeKeys(object); |
|
} |
|
var result = []; |
|
for (var key in Object(object)) { |
|
if (hasOwnProperty.call(object, key) && key != 'constructor') { |
|
result.push(key); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names. |
|
*/ |
|
function baseKeysIn(object) { |
|
if (!isObject(object)) { |
|
return nativeKeysIn(object); |
|
} |
|
var isProto = isPrototype(object), |
|
result = []; |
|
|
|
for (var key in object) { |
|
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { |
|
result.push(key); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.lt` which doesn't coerce arguments. |
|
* |
|
* @private |
|
* @param {*} value The value to compare. |
|
* @param {*} other The other value to compare. |
|
* @returns {boolean} Returns `true` if `value` is less than `other`, |
|
* else `false`. |
|
*/ |
|
function baseLt(value, other) { |
|
return value < other; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.map` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} iteratee The function invoked per iteration. |
|
* @returns {Array} Returns the new mapped array. |
|
*/ |
|
function baseMap(collection, iteratee) { |
|
var index = -1, |
|
result = isArrayLike(collection) ? Array(collection.length) : []; |
|
|
|
baseEach(collection, function(value, key, collection) { |
|
result[++index] = iteratee(value, key, collection); |
|
}); |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.matches` which doesn't clone `source`. |
|
* |
|
* @private |
|
* @param {Object} source The object of property values to match. |
|
* @returns {Function} Returns the new spec function. |
|
*/ |
|
function baseMatches(source) { |
|
var matchData = getMatchData(source); |
|
if (matchData.length == 1 && matchData[0][2]) { |
|
return matchesStrictComparable(matchData[0][0], matchData[0][1]); |
|
} |
|
return function(object) { |
|
return object === source || baseIsMatch(object, source, matchData); |
|
}; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. |
|
* |
|
* @private |
|
* @param {string} path The path of the property to get. |
|
* @param {*} srcValue The value to match. |
|
* @returns {Function} Returns the new spec function. |
|
*/ |
|
function baseMatchesProperty(path, srcValue) { |
|
if (isKey(path) && isStrictComparable(srcValue)) { |
|
return matchesStrictComparable(toKey(path), srcValue); |
|
} |
|
return function(object) { |
|
var objValue = get(object, path); |
|
return (objValue === undefined && objValue === srcValue) |
|
? hasIn(object, path) |
|
: baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); |
|
}; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.merge` without support for multiple sources. |
|
* |
|
* @private |
|
* @param {Object} object The destination object. |
|
* @param {Object} source The source object. |
|
* @param {number} srcIndex The index of `source`. |
|
* @param {Function} [customizer] The function to customize merged values. |
|
* @param {Object} [stack] Tracks traversed source values and their merged |
|
* counterparts. |
|
*/ |
|
function baseMerge(object, source, srcIndex, customizer, stack) { |
|
if (object === source) { |
|
return; |
|
} |
|
baseFor(source, function(srcValue, key) { |
|
if (isObject(srcValue)) { |
|
stack || (stack = new Stack); |
|
baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); |
|
} |
|
else { |
|
var newValue = customizer |
|
? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) |
|
: undefined; |
|
|
|
if (newValue === undefined) { |
|
newValue = srcValue; |
|
} |
|
assignMergeValue(object, key, newValue); |
|
} |
|
}, keysIn); |
|
} |
|
|
|
/** |
|
* A specialized version of `baseMerge` for arrays and objects which performs |
|
* deep merges and tracks traversed objects enabling objects with circular |
|
* references to be merged. |
|
* |
|
* @private |
|
* @param {Object} object The destination object. |
|
* @param {Object} source The source object. |
|
* @param {string} key The key of the value to merge. |
|
* @param {number} srcIndex The index of `source`. |
|
* @param {Function} mergeFunc The function to merge values. |
|
* @param {Function} [customizer] The function to customize assigned values. |
|
* @param {Object} [stack] Tracks traversed source values and their merged |
|
* counterparts. |
|
*/ |
|
function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { |
|
var objValue = safeGet(object, key), |
|
srcValue = safeGet(source, key), |
|
stacked = stack.get(srcValue); |
|
|
|
if (stacked) { |
|
assignMergeValue(object, key, stacked); |
|
return; |
|
} |
|
var newValue = customizer |
|
? customizer(objValue, srcValue, (key + ''), object, source, stack) |
|
: undefined; |
|
|
|
var isCommon = newValue === undefined; |
|
|
|
if (isCommon) { |
|
var isArr = isArray(srcValue), |
|
isBuff = !isArr && isBuffer(srcValue), |
|
isTyped = !isArr && !isBuff && isTypedArray(srcValue); |
|
|
|
newValue = srcValue; |
|
if (isArr || isBuff || isTyped) { |
|
if (isArray(objValue)) { |
|
newValue = objValue; |
|
} |
|
else if (isArrayLikeObject(objValue)) { |
|
newValue = copyArray(objValue); |
|
} |
|
else if (isBuff) { |
|
isCommon = false; |
|
newValue = cloneBuffer(srcValue, true); |
|
} |
|
else if (isTyped) { |
|
isCommon = false; |
|
newValue = cloneTypedArray(srcValue, true); |
|
} |
|
else { |
|
newValue = []; |
|
} |
|
} |
|
else if (isPlainObject(srcValue) || isArguments(srcValue)) { |
|
newValue = objValue; |
|
if (isArguments(objValue)) { |
|
newValue = toPlainObject(objValue); |
|
} |
|
else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { |
|
newValue = initCloneObject(srcValue); |
|
} |
|
} |
|
else { |
|
isCommon = false; |
|
} |
|
} |
|
if (isCommon) { |
|
// Recursively merge objects and arrays (susceptible to call stack limits). |
|
stack.set(srcValue, newValue); |
|
mergeFunc(newValue, srcValue, srcIndex, customizer, stack); |
|
stack['delete'](srcValue); |
|
} |
|
assignMergeValue(object, key, newValue); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.orderBy` without param guards. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. |
|
* @param {string[]} orders The sort orders of `iteratees`. |
|
* @returns {Array} Returns the new sorted array. |
|
*/ |
|
function baseOrderBy(collection, iteratees, orders) { |
|
var index = -1; |
|
iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(baseIteratee)); |
|
|
|
var result = baseMap(collection, function(value, key, collection) { |
|
var criteria = arrayMap(iteratees, function(iteratee) { |
|
return iteratee(value); |
|
}); |
|
return { 'criteria': criteria, 'index': ++index, 'value': value }; |
|
}); |
|
|
|
return baseSortBy(result, function(object, other) { |
|
return compareMultiple(object, other, orders); |
|
}); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.pick` without support for individual |
|
* property identifiers. |
|
* |
|
* @private |
|
* @param {Object} object The source object. |
|
* @param {string[]} paths The property paths to pick. |
|
* @returns {Object} Returns the new object. |
|
*/ |
|
function basePick(object, paths) { |
|
return basePickBy(object, paths, function(value, path) { |
|
return hasIn(object, path); |
|
}); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.pickBy` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Object} object The source object. |
|
* @param {string[]} paths The property paths to pick. |
|
* @param {Function} predicate The function invoked per property. |
|
* @returns {Object} Returns the new object. |
|
*/ |
|
function basePickBy(object, paths, predicate) { |
|
var index = -1, |
|
length = paths.length, |
|
result = {}; |
|
|
|
while (++index < length) { |
|
var path = paths[index], |
|
value = baseGet(object, path); |
|
|
|
if (predicate(value, path)) { |
|
baseSet(result, castPath(path, object), value); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* A specialized version of `baseProperty` which supports deep paths. |
|
* |
|
* @private |
|
* @param {Array|string} path The path of the property to get. |
|
* @returns {Function} Returns the new accessor function. |
|
*/ |
|
function basePropertyDeep(path) { |
|
return function(object) { |
|
return baseGet(object, path); |
|
}; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.random` without support for returning |
|
* floating-point numbers. |
|
* |
|
* @private |
|
* @param {number} lower The lower bound. |
|
* @param {number} upper The upper bound. |
|
* @returns {number} Returns the random number. |
|
*/ |
|
function baseRandom(lower, upper) { |
|
return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.range` and `_.rangeRight` which doesn't |
|
* coerce arguments. |
|
* |
|
* @private |
|
* @param {number} start The start of the range. |
|
* @param {number} end The end of the range. |
|
* @param {number} step The value to increment or decrement by. |
|
* @param {boolean} [fromRight] Specify iterating from right to left. |
|
* @returns {Array} Returns the range of numbers. |
|
*/ |
|
function baseRange(start, end, step, fromRight) { |
|
var index = -1, |
|
length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), |
|
result = Array(length); |
|
|
|
while (length--) { |
|
result[fromRight ? length : ++index] = start; |
|
start += step; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.rest` which doesn't validate or coerce arguments. |
|
* |
|
* @private |
|
* @param {Function} func The function to apply a rest parameter to. |
|
* @param {number} [start=func.length-1] The start position of the rest parameter. |
|
* @returns {Function} Returns the new function. |
|
*/ |
|
function baseRest(func, start) { |
|
return setToString(overRest(func, start, identity), func + ''); |
|
} |
|
|
|
/** |
|
* The base implementation of `_.set`. |
|
* |
|
* @private |
|
* @param {Object} object The object to modify. |
|
* @param {Array|string} path The path of the property to set. |
|
* @param {*} value The value to set. |
|
* @param {Function} [customizer] The function to customize path creation. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function baseSet(object, path, value, customizer) { |
|
if (!isObject(object)) { |
|
return object; |
|
} |
|
path = castPath(path, object); |
|
|
|
var index = -1, |
|
length = path.length, |
|
lastIndex = length - 1, |
|
nested = object; |
|
|
|
while (nested != null && ++index < length) { |
|
var key = toKey(path[index]), |
|
newValue = value; |
|
|
|
if (index != lastIndex) { |
|
var objValue = nested[key]; |
|
newValue = customizer ? customizer(objValue, key, nested) : undefined; |
|
if (newValue === undefined) { |
|
newValue = isObject(objValue) |
|
? objValue |
|
: (isIndex(path[index + 1]) ? [] : {}); |
|
} |
|
} |
|
assignValue(nested, key, newValue); |
|
nested = nested[key]; |
|
} |
|
return object; |
|
} |
|
|
|
/** |
|
* The base implementation of `setData` without support for hot loop shorting. |
|
* |
|
* @private |
|
* @param {Function} func The function to associate metadata with. |
|
* @param {*} data The metadata. |
|
* @returns {Function} Returns `func`. |
|
*/ |
|
var baseSetData = !metaMap ? identity : function(func, data) { |
|
metaMap.set(func, data); |
|
return func; |
|
}; |
|
|
|
/** |
|
* The base implementation of `setToString` without support for hot loop shorting. |
|
* |
|
* @private |
|
* @param {Function} func The function to modify. |
|
* @param {Function} string The `toString` result. |
|
* @returns {Function} Returns `func`. |
|
*/ |
|
var baseSetToString = !defineProperty ? identity : function(func, string) { |
|
return defineProperty(func, 'toString', { |
|
'configurable': true, |
|
'enumerable': false, |
|
'value': constant(string), |
|
'writable': true |
|
}); |
|
}; |
|
|
|
/** |
|
* The base implementation of `_.slice` without an iteratee call guard. |
|
* |
|
* @private |
|
* @param {Array} array The array to slice. |
|
* @param {number} [start=0] The start position. |
|
* @param {number} [end=array.length] The end position. |
|
* @returns {Array} Returns the slice of `array`. |
|
*/ |
|
function baseSlice(array, start, end) { |
|
var index = -1, |
|
length = array.length; |
|
|
|
if (start < 0) { |
|
start = -start > length ? 0 : (length + start); |
|
} |
|
end = end > length ? length : end; |
|
if (end < 0) { |
|
end += length; |
|
} |
|
length = start > end ? 0 : ((end - start) >>> 0); |
|
start >>>= 0; |
|
|
|
var result = Array(length); |
|
while (++index < length) { |
|
result[index] = array[index + start]; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.some` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} predicate The function invoked per iteration. |
|
* @returns {boolean} Returns `true` if any element passes the predicate check, |
|
* else `false`. |
|
*/ |
|
function baseSome(collection, predicate) { |
|
var result; |
|
|
|
baseEach(collection, function(value, index, collection) { |
|
result = predicate(value, index, collection); |
|
return !result; |
|
}); |
|
return !!result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.toString` which doesn't convert nullish |
|
* values to empty strings. |
|
* |
|
* @private |
|
* @param {*} value The value to process. |
|
* @returns {string} Returns the string. |
|
*/ |
|
function baseToString(value) { |
|
// Exit early for strings to avoid a performance hit in some environments. |
|
if (typeof value == 'string') { |
|
return value; |
|
} |
|
if (isArray(value)) { |
|
// Recursively convert values (susceptible to call stack limits). |
|
return arrayMap(value, baseToString) + ''; |
|
} |
|
if (isSymbol(value)) { |
|
return symbolToString ? symbolToString.call(value) : ''; |
|
} |
|
var result = (value + ''); |
|
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.uniqBy` without support for iteratee shorthands. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {Function} [iteratee] The iteratee invoked per element. |
|
* @param {Function} [comparator] The comparator invoked per element. |
|
* @returns {Array} Returns the new duplicate free array. |
|
*/ |
|
function baseUniq(array, iteratee, comparator) { |
|
var index = -1, |
|
includes = arrayIncludes, |
|
length = array.length, |
|
isCommon = true, |
|
result = [], |
|
seen = result; |
|
|
|
if (comparator) { |
|
isCommon = false; |
|
includes = arrayIncludesWith; |
|
} |
|
else if (length >= LARGE_ARRAY_SIZE) { |
|
var set = iteratee ? null : createSet(array); |
|
if (set) { |
|
return setToArray(set); |
|
} |
|
isCommon = false; |
|
includes = cacheHas; |
|
seen = new SetCache; |
|
} |
|
else { |
|
seen = iteratee ? [] : result; |
|
} |
|
outer: |
|
while (++index < length) { |
|
var value = array[index], |
|
computed = iteratee ? iteratee(value) : value; |
|
|
|
value = (comparator || value !== 0) ? value : 0; |
|
if (isCommon && computed === computed) { |
|
var seenIndex = seen.length; |
|
while (seenIndex--) { |
|
if (seen[seenIndex] === computed) { |
|
continue outer; |
|
} |
|
} |
|
if (iteratee) { |
|
seen.push(computed); |
|
} |
|
result.push(value); |
|
} |
|
else if (!includes(seen, computed, comparator)) { |
|
if (seen !== result) { |
|
seen.push(computed); |
|
} |
|
result.push(value); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* The base implementation of `_.unset`. |
|
* |
|
* @private |
|
* @param {Object} object The object to modify. |
|
* @param {Array|string} path The property path to unset. |
|
* @returns {boolean} Returns `true` if the property is deleted, else `false`. |
|
*/ |
|
function baseUnset(object, path) { |
|
path = castPath(path, object); |
|
object = parent(object, path); |
|
return object == null || delete object[toKey(last(path))]; |
|
} |
|
|
|
/** |
|
* The base implementation of `wrapperValue` which returns the result of |
|
* performing a sequence of actions on the unwrapped `value`, where each |
|
* successive action is supplied the return value of the previous. |
|
* |
|
* @private |
|
* @param {*} value The unwrapped value. |
|
* @param {Array} actions Actions to perform to resolve the unwrapped value. |
|
* @returns {*} Returns the resolved value. |
|
*/ |
|
function baseWrapperValue(value, actions) { |
|
var result = value; |
|
if (result instanceof LazyWrapper) { |
|
result = result.value(); |
|
} |
|
return arrayReduce(actions, function(result, action) { |
|
return action.func.apply(action.thisArg, arrayPush([result], action.args)); |
|
}, result); |
|
} |
|
|
|
/** |
|
* This base implementation of `_.zipObject` which assigns values using `assignFunc`. |
|
* |
|
* @private |
|
* @param {Array} props The property identifiers. |
|
* @param {Array} values The property values. |
|
* @param {Function} assignFunc The function to assign values. |
|
* @returns {Object} Returns the new object. |
|
*/ |
|
function baseZipObject(props, values, assignFunc) { |
|
var index = -1, |
|
length = props.length, |
|
valsLength = values.length, |
|
result = {}; |
|
|
|
while (++index < length) { |
|
var value = index < valsLength ? values[index] : undefined; |
|
assignFunc(result, props[index], value); |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Casts `value` to an empty array if it's not an array like object. |
|
* |
|
* @private |
|
* @param {*} value The value to inspect. |
|
* @returns {Array|Object} Returns the cast array-like object. |
|
*/ |
|
function castArrayLikeObject(value) { |
|
return isArrayLikeObject(value) ? value : []; |
|
} |
|
|
|
/** |
|
* Casts `value` to a path array if it's not one. |
|
* |
|
* @private |
|
* @param {*} value The value to inspect. |
|
* @param {Object} [object] The object to query keys on. |
|
* @returns {Array} Returns the cast property path array. |
|
*/ |
|
function castPath(value, object) { |
|
if (isArray(value)) { |
|
return value; |
|
} |
|
return isKey(value, object) ? [value] : stringToPath(toString(value)); |
|
} |
|
|
|
/** |
|
* Casts `array` to a slice if it's needed. |
|
* |
|
* @private |
|
* @param {Array} array The array to inspect. |
|
* @param {number} start The start position. |
|
* @param {number} [end=array.length] The end position. |
|
* @returns {Array} Returns the cast slice. |
|
*/ |
|
function castSlice(array, start, end) { |
|
var length = array.length; |
|
end = end === undefined ? length : end; |
|
return (!start && end >= length) ? array : baseSlice(array, start, end); |
|
} |
|
|
|
/** |
|
* Creates a clone of `buffer`. |
|
* |
|
* @private |
|
* @param {Buffer} buffer The buffer to clone. |
|
* @param {boolean} [isDeep] Specify a deep clone. |
|
* @returns {Buffer} Returns the cloned buffer. |
|
*/ |
|
function cloneBuffer(buffer, isDeep) { |
|
if (isDeep) { |
|
return buffer.slice(); |
|
} |
|
var length = buffer.length, |
|
result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); |
|
|
|
buffer.copy(result); |
|
return result; |
|
} |
|
|
|
/** |
|
* Creates a clone of `arrayBuffer`. |
|
* |
|
* @private |
|
* @param {ArrayBuffer} arrayBuffer The array buffer to clone. |
|
* @returns {ArrayBuffer} Returns the cloned array buffer. |
|
*/ |
|
function cloneArrayBuffer(arrayBuffer) { |
|
var result = new arrayBuffer.constructor(arrayBuffer.byteLength); |
|
new Uint8Array(result).set(new Uint8Array(arrayBuffer)); |
|
return result; |
|
} |
|
|
|
/** |
|
* Creates a clone of `dataView`. |
|
* |
|
* @private |
|
* @param {Object} dataView The data view to clone. |
|
* @param {boolean} [isDeep] Specify a deep clone. |
|
* @returns {Object} Returns the cloned data view. |
|
*/ |
|
function cloneDataView(dataView, isDeep) { |
|
var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; |
|
return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); |
|
} |
|
|
|
/** |
|
* Creates a clone of `regexp`. |
|
* |
|
* @private |
|
* @param {Object} regexp The regexp to clone. |
|
* @returns {Object} Returns the cloned regexp. |
|
*/ |
|
function cloneRegExp(regexp) { |
|
var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); |
|
result.lastIndex = regexp.lastIndex; |
|
return result; |
|
} |
|
|
|
/** |
|
* Creates a clone of the `symbol` object. |
|
* |
|
* @private |
|
* @param {Object} symbol The symbol object to clone. |
|
* @returns {Object} Returns the cloned symbol object. |
|
*/ |
|
function cloneSymbol(symbol) { |
|
return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; |
|
} |
|
|
|
/** |
|
* Creates a clone of `typedArray`. |
|
* |
|
* @private |
|
* @param {Object} typedArray The typed array to clone. |
|
* @param {boolean} [isDeep] Specify a deep clone. |
|
* @returns {Object} Returns the cloned typed array. |
|
*/ |
|
function cloneTypedArray(typedArray, isDeep) { |
|
var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; |
|
return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); |
|
} |
|
|
|
/** |
|
* Compares values to sort them in ascending order. |
|
* |
|
* @private |
|
* @param {*} value The value to compare. |
|
* @param {*} other The other value to compare. |
|
* @returns {number} Returns the sort order indicator for `value`. |
|
*/ |
|
function compareAscending(value, other) { |
|
if (value !== other) { |
|
var valIsDefined = value !== undefined, |
|
valIsNull = value === null, |
|
valIsReflexive = value === value, |
|
valIsSymbol = isSymbol(value); |
|
|
|
var othIsDefined = other !== undefined, |
|
othIsNull = other === null, |
|
othIsReflexive = other === other, |
|
othIsSymbol = isSymbol(other); |
|
|
|
if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || |
|
(valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || |
|
(valIsNull && othIsDefined && othIsReflexive) || |
|
(!valIsDefined && othIsReflexive) || |
|
!valIsReflexive) { |
|
return 1; |
|
} |
|
if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || |
|
(othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || |
|
(othIsNull && valIsDefined && valIsReflexive) || |
|
(!othIsDefined && valIsReflexive) || |
|
!othIsReflexive) { |
|
return -1; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
/** |
|
* Used by `_.orderBy` to compare multiple properties of a value to another |
|
* and stable sort them. |
|
* |
|
* If `orders` is unspecified, all values are sorted in ascending order. Otherwise, |
|
* specify an order of "desc" for descending or "asc" for ascending sort order |
|
* of corresponding values. |
|
* |
|
* @private |
|
* @param {Object} object The object to compare. |
|
* @param {Object} other The other object to compare. |
|
* @param {boolean[]|string[]} orders The order to sort by for each property. |
|
* @returns {number} Returns the sort order indicator for `object`. |
|
*/ |
|
function compareMultiple(object, other, orders) { |
|
var index = -1, |
|
objCriteria = object.criteria, |
|
othCriteria = other.criteria, |
|
length = objCriteria.length, |
|
ordersLength = orders.length; |
|
|
|
while (++index < length) { |
|
var result = compareAscending(objCriteria[index], othCriteria[index]); |
|
if (result) { |
|
if (index >= ordersLength) { |
|
return result; |
|
} |
|
var order = orders[index]; |
|
return result * (order == 'desc' ? -1 : 1); |
|
} |
|
} |
|
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications |
|
// that causes it, under certain circumstances, to provide the same value for |
|
// `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 |
|
// for more details. |
|
// |
|
// This also ensures a stable sort in V8 and other engines. |
|
// See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. |
|
return object.index - other.index; |
|
} |
|
|
|
/** |
|
* Creates an array that is the composition of partially applied arguments, |
|
* placeholders, and provided arguments into a single array of arguments. |
|
* |
|
* @private |
|
* @param {Array} args The provided arguments. |
|
* @param {Array} partials The arguments to prepend to those provided. |
|
* @param {Array} holders The `partials` placeholder indexes. |
|
* @params {boolean} [isCurried] Specify composing for a curried function. |
|
* @returns {Array} Returns the new array of composed arguments. |
|
*/ |
|
function composeArgs(args, partials, holders, isCurried) { |
|
var argsIndex = -1, |
|
argsLength = args.length, |
|
holdersLength = holders.length, |
|
leftIndex = -1, |
|
leftLength = partials.length, |
|
rangeLength = nativeMax(argsLength - holdersLength, 0), |
|
result = Array(leftLength + rangeLength), |
|
isUncurried = !isCurried; |
|
|
|
while (++leftIndex < leftLength) { |
|
result[leftIndex] = partials[leftIndex]; |
|
} |
|
while (++argsIndex < holdersLength) { |
|
if (isUncurried || argsIndex < argsLength) { |
|
result[holders[argsIndex]] = args[argsIndex]; |
|
} |
|
} |
|
while (rangeLength--) { |
|
result[leftIndex++] = args[argsIndex++]; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* This function is like `composeArgs` except that the arguments composition |
|
* is tailored for `_.partialRight`. |
|
* |
|
* @private |
|
* @param {Array} args The provided arguments. |
|
* @param {Array} partials The arguments to append to those provided. |
|
* @param {Array} holders The `partials` placeholder indexes. |
|
* @params {boolean} [isCurried] Specify composing for a curried function. |
|
* @returns {Array} Returns the new array of composed arguments. |
|
*/ |
|
function composeArgsRight(args, partials, holders, isCurried) { |
|
var argsIndex = -1, |
|
argsLength = args.length, |
|
holdersIndex = -1, |
|
holdersLength = holders.length, |
|
rightIndex = -1, |
|
rightLength = partials.length, |
|
rangeLength = nativeMax(argsLength - holdersLength, 0), |
|
result = Array(rangeLength + rightLength), |
|
isUncurried = !isCurried; |
|
|
|
while (++argsIndex < rangeLength) { |
|
result[argsIndex] = args[argsIndex]; |
|
} |
|
var offset = argsIndex; |
|
while (++rightIndex < rightLength) { |
|
result[offset + rightIndex] = partials[rightIndex]; |
|
} |
|
while (++holdersIndex < holdersLength) { |
|
if (isUncurried || argsIndex < argsLength) { |
|
result[offset + holders[holdersIndex]] = args[argsIndex++]; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Copies the values of `source` to `array`. |
|
* |
|
* @private |
|
* @param {Array} source The array to copy values from. |
|
* @param {Array} [array=[]] The array to copy values to. |
|
* @returns {Array} Returns `array`. |
|
*/ |
|
function copyArray(source, array) { |
|
var index = -1, |
|
length = source.length; |
|
|
|
array || (array = Array(length)); |
|
while (++index < length) { |
|
array[index] = source[index]; |
|
} |
|
return array; |
|
} |
|
|
|
/** |
|
* Copies properties of `source` to `object`. |
|
* |
|
* @private |
|
* @param {Object} source The object to copy properties from. |
|
* @param {Array} props The property identifiers to copy. |
|
* @param {Object} [object={}] The object to copy properties to. |
|
* @param {Function} [customizer] The function to customize copied values. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function copyObject(source, props, object, customizer) { |
|
var isNew = !object; |
|
object || (object = {}); |
|
|
|
var index = -1, |
|
length = props.length; |
|
|
|
while (++index < length) { |
|
var key = props[index]; |
|
|
|
var newValue = customizer |
|
? customizer(object[key], source[key], key, object, source) |
|
: undefined; |
|
|
|
if (newValue === undefined) { |
|
newValue = source[key]; |
|
} |
|
if (isNew) { |
|
baseAssignValue(object, key, newValue); |
|
} else { |
|
assignValue(object, key, newValue); |
|
} |
|
} |
|
return object; |
|
} |
|
|
|
/** |
|
* Copies own symbols of `source` to `object`. |
|
* |
|
* @private |
|
* @param {Object} source The object to copy symbols from. |
|
* @param {Object} [object={}] The object to copy symbols to. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function copySymbols(source, object) { |
|
return copyObject(source, getSymbols(source), object); |
|
} |
|
|
|
/** |
|
* Copies own and inherited symbols of `source` to `object`. |
|
* |
|
* @private |
|
* @param {Object} source The object to copy symbols from. |
|
* @param {Object} [object={}] The object to copy symbols to. |
|
* @returns {Object} Returns `object`. |
|
*/ |
|
function copySymbolsIn(source, object) { |
|
return copyObject(source, getSymbolsIn(source), object); |
|
} |
|
|
|
/** |
|
* Creates a function like `_.groupBy`. |
|
* |
|
* @private |
|
* @param {Function} setter The function to set accumulator values. |
|
* @param {Function} [initializer] The accumulator object initializer. |
|
* @returns {Function} Returns the new aggregator function. |
|
*/ |
|
function createAggregator(setter, initializer) { |
|
return function(collection, iteratee) { |
|
var func = isArray(collection) ? arrayAggregator : baseAggregator, |
|
accumulator = initializer ? initializer() : {}; |
|
|
|
return func(collection, setter, baseIteratee(iteratee, 2), accumulator); |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function like `_.assign`. |
|
* |
|
* @private |
|
* @param {Function} assigner The function to assign values. |
|
* @returns {Function} Returns the new assigner function. |
|
*/ |
|
function createAssigner(assigner) { |
|
return baseRest(function(object, sources) { |
|
var index = -1, |
|
length = sources.length, |
|
customizer = length > 1 ? sources[length - 1] : undefined, |
|
guard = length > 2 ? sources[2] : undefined; |
|
|
|
customizer = (assigner.length > 3 && typeof customizer == 'function') |
|
? (length--, customizer) |
|
: undefined; |
|
|
|
if (guard && isIterateeCall(sources[0], sources[1], guard)) { |
|
customizer = length < 3 ? undefined : customizer; |
|
length = 1; |
|
} |
|
object = Object(object); |
|
while (++index < length) { |
|
var source = sources[index]; |
|
if (source) { |
|
assigner(object, source, index, customizer); |
|
} |
|
} |
|
return object; |
|
}); |
|
} |
|
|
|
/** |
|
* Creates a `baseEach` or `baseEachRight` function. |
|
* |
|
* @private |
|
* @param {Function} eachFunc The function to iterate over a collection. |
|
* @param {boolean} [fromRight] Specify iterating from right to left. |
|
* @returns {Function} Returns the new base function. |
|
*/ |
|
function createBaseEach(eachFunc, fromRight) { |
|
return function(collection, iteratee) { |
|
if (collection == null) { |
|
return collection; |
|
} |
|
if (!isArrayLike(collection)) { |
|
return eachFunc(collection, iteratee); |
|
} |
|
var length = collection.length, |
|
index = fromRight ? length : -1, |
|
iterable = Object(collection); |
|
|
|
while ((fromRight ? index-- : ++index < length)) { |
|
if (iteratee(iterable[index], index, iterable) === false) { |
|
break; |
|
} |
|
} |
|
return collection; |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a base function for methods like `_.forIn` and `_.forOwn`. |
|
* |
|
* @private |
|
* @param {boolean} [fromRight] Specify iterating from right to left. |
|
* @returns {Function} Returns the new base function. |
|
*/ |
|
function createBaseFor(fromRight) { |
|
return function(object, iteratee, keysFunc) { |
|
var index = -1, |
|
iterable = Object(object), |
|
props = keysFunc(object), |
|
length = props.length; |
|
|
|
while (length--) { |
|
var key = props[fromRight ? length : ++index]; |
|
if (iteratee(iterable[key], key, iterable) === false) { |
|
break; |
|
} |
|
} |
|
return object; |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that wraps `func` to invoke it with the optional `this` |
|
* binding of `thisArg`. |
|
* |
|
* @private |
|
* @param {Function} func The function to wrap. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @param {*} [thisArg] The `this` binding of `func`. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createBind(func, bitmask, thisArg) { |
|
var isBind = bitmask & WRAP_BIND_FLAG, |
|
Ctor = createCtor(func); |
|
|
|
function wrapper() { |
|
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; |
|
return fn.apply(isBind ? thisArg : this, arguments); |
|
} |
|
return wrapper; |
|
} |
|
|
|
/** |
|
* Creates a function that produces an instance of `Ctor` regardless of |
|
* whether it was invoked as part of a `new` expression or by `call` or `apply`. |
|
* |
|
* @private |
|
* @param {Function} Ctor The constructor to wrap. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createCtor(Ctor) { |
|
return function() { |
|
// Use a `switch` statement to work with class constructors. See |
|
// http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist |
|
// for more details. |
|
var args = arguments; |
|
switch (args.length) { |
|
case 0: return new Ctor; |
|
case 1: return new Ctor(args[0]); |
|
case 2: return new Ctor(args[0], args[1]); |
|
case 3: return new Ctor(args[0], args[1], args[2]); |
|
case 4: return new Ctor(args[0], args[1], args[2], args[3]); |
|
case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); |
|
case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); |
|
case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); |
|
} |
|
var thisBinding = baseCreate(Ctor.prototype), |
|
result = Ctor.apply(thisBinding, args); |
|
|
|
// Mimic the constructor's `return` behavior. |
|
// See https://es5.github.io/#x13.2.2 for more details. |
|
return isObject(result) ? result : thisBinding; |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that wraps `func` to enable currying. |
|
* |
|
* @private |
|
* @param {Function} func The function to wrap. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @param {number} arity The arity of `func`. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createCurry(func, bitmask, arity) { |
|
var Ctor = createCtor(func); |
|
|
|
function wrapper() { |
|
var length = arguments.length, |
|
args = Array(length), |
|
index = length, |
|
placeholder = getHolder(wrapper); |
|
|
|
while (index--) { |
|
args[index] = arguments[index]; |
|
} |
|
var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) |
|
? [] |
|
: replaceHolders(args, placeholder); |
|
|
|
length -= holders.length; |
|
if (length < arity) { |
|
return createRecurry( |
|
func, bitmask, createHybrid, wrapper.placeholder, undefined, |
|
args, holders, undefined, undefined, arity - length); |
|
} |
|
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; |
|
return apply(fn, this, args); |
|
} |
|
return wrapper; |
|
} |
|
|
|
/** |
|
* Creates a `_.find` or `_.findLast` function. |
|
* |
|
* @private |
|
* @param {Function} findIndexFunc The function to find the collection index. |
|
* @returns {Function} Returns the new find function. |
|
*/ |
|
function createFind(findIndexFunc) { |
|
return function(collection, predicate, fromIndex) { |
|
var iterable = Object(collection); |
|
if (!isArrayLike(collection)) { |
|
var iteratee = baseIteratee(predicate, 3); |
|
collection = keys(collection); |
|
predicate = function(key) { return iteratee(iterable[key], key, iterable); }; |
|
} |
|
var index = findIndexFunc(collection, predicate, fromIndex); |
|
return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that wraps `func` to invoke it with optional `this` |
|
* binding of `thisArg`, partial application, and currying. |
|
* |
|
* @private |
|
* @param {Function|string} func The function or method name to wrap. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @param {*} [thisArg] The `this` binding of `func`. |
|
* @param {Array} [partials] The arguments to prepend to those provided to |
|
* the new function. |
|
* @param {Array} [holders] The `partials` placeholder indexes. |
|
* @param {Array} [partialsRight] The arguments to append to those provided |
|
* to the new function. |
|
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes. |
|
* @param {Array} [argPos] The argument positions of the new function. |
|
* @param {number} [ary] The arity cap of `func`. |
|
* @param {number} [arity] The arity of `func`. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { |
|
var isAry = bitmask & WRAP_ARY_FLAG, |
|
isBind = bitmask & WRAP_BIND_FLAG, |
|
isBindKey = bitmask & WRAP_BIND_KEY_FLAG, |
|
isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), |
|
isFlip = bitmask & WRAP_FLIP_FLAG, |
|
Ctor = isBindKey ? undefined : createCtor(func); |
|
|
|
function wrapper() { |
|
var length = arguments.length, |
|
args = Array(length), |
|
index = length; |
|
|
|
while (index--) { |
|
args[index] = arguments[index]; |
|
} |
|
if (isCurried) { |
|
var placeholder = getHolder(wrapper), |
|
holdersCount = countHolders(args, placeholder); |
|
} |
|
if (partials) { |
|
args = composeArgs(args, partials, holders, isCurried); |
|
} |
|
if (partialsRight) { |
|
args = composeArgsRight(args, partialsRight, holdersRight, isCurried); |
|
} |
|
length -= holdersCount; |
|
if (isCurried && length < arity) { |
|
var newHolders = replaceHolders(args, placeholder); |
|
return createRecurry( |
|
func, bitmask, createHybrid, wrapper.placeholder, thisArg, |
|
args, newHolders, argPos, ary, arity - length |
|
); |
|
} |
|
var thisBinding = isBind ? thisArg : this, |
|
fn = isBindKey ? thisBinding[func] : func; |
|
|
|
length = args.length; |
|
if (argPos) { |
|
args = reorder(args, argPos); |
|
} else if (isFlip && length > 1) { |
|
args.reverse(); |
|
} |
|
if (isAry && ary < length) { |
|
args.length = ary; |
|
} |
|
if (this && this !== root && this instanceof wrapper) { |
|
fn = Ctor || createCtor(fn); |
|
} |
|
return fn.apply(thisBinding, args); |
|
} |
|
return wrapper; |
|
} |
|
|
|
/** |
|
* Creates a function like `_.invertBy`. |
|
* |
|
* @private |
|
* @param {Function} setter The function to set accumulator values. |
|
* @param {Function} toIteratee The function to resolve iteratees. |
|
* @returns {Function} Returns the new inverter function. |
|
*/ |
|
function createInverter(setter, toIteratee) { |
|
return function(object, iteratee) { |
|
return baseInverter(object, setter, toIteratee(iteratee), {}); |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that wraps `func` to invoke it with the `this` binding |
|
* of `thisArg` and `partials` prepended to the arguments it receives. |
|
* |
|
* @private |
|
* @param {Function} func The function to wrap. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @param {*} thisArg The `this` binding of `func`. |
|
* @param {Array} partials The arguments to prepend to those provided to |
|
* the new function. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createPartial(func, bitmask, thisArg, partials) { |
|
var isBind = bitmask & WRAP_BIND_FLAG, |
|
Ctor = createCtor(func); |
|
|
|
function wrapper() { |
|
var argsIndex = -1, |
|
argsLength = arguments.length, |
|
leftIndex = -1, |
|
leftLength = partials.length, |
|
args = Array(leftLength + argsLength), |
|
fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; |
|
|
|
while (++leftIndex < leftLength) { |
|
args[leftIndex] = partials[leftIndex]; |
|
} |
|
while (argsLength--) { |
|
args[leftIndex++] = arguments[++argsIndex]; |
|
} |
|
return apply(fn, isBind ? thisArg : this, args); |
|
} |
|
return wrapper; |
|
} |
|
|
|
/** |
|
* Creates a `_.range` or `_.rangeRight` function. |
|
* |
|
* @private |
|
* @param {boolean} [fromRight] Specify iterating from right to left. |
|
* @returns {Function} Returns the new range function. |
|
*/ |
|
function createRange(fromRight) { |
|
return function(start, end, step) { |
|
if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { |
|
end = step = undefined; |
|
} |
|
// Ensure the sign of `-0` is preserved. |
|
start = toFinite(start); |
|
if (end === undefined) { |
|
end = start; |
|
start = 0; |
|
} else { |
|
end = toFinite(end); |
|
} |
|
step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); |
|
return baseRange(start, end, step, fromRight); |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that wraps `func` to continue currying. |
|
* |
|
* @private |
|
* @param {Function} func The function to wrap. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @param {Function} wrapFunc The function to create the `func` wrapper. |
|
* @param {*} placeholder The placeholder value. |
|
* @param {*} [thisArg] The `this` binding of `func`. |
|
* @param {Array} [partials] The arguments to prepend to those provided to |
|
* the new function. |
|
* @param {Array} [holders] The `partials` placeholder indexes. |
|
* @param {Array} [argPos] The argument positions of the new function. |
|
* @param {number} [ary] The arity cap of `func`. |
|
* @param {number} [arity] The arity of `func`. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { |
|
var isCurry = bitmask & WRAP_CURRY_FLAG, |
|
newHolders = isCurry ? holders : undefined, |
|
newHoldersRight = isCurry ? undefined : holders, |
|
newPartials = isCurry ? partials : undefined, |
|
newPartialsRight = isCurry ? undefined : partials; |
|
|
|
bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); |
|
bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); |
|
|
|
if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { |
|
bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); |
|
} |
|
var newData = [ |
|
func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, |
|
newHoldersRight, argPos, ary, arity |
|
]; |
|
|
|
var result = wrapFunc.apply(undefined, newData); |
|
if (isLaziable(func)) { |
|
setData(result, newData); |
|
} |
|
result.placeholder = placeholder; |
|
return setWrapToString(result, func, bitmask); |
|
} |
|
|
|
/** |
|
* Creates a set object of `values`. |
|
* |
|
* @private |
|
* @param {Array} values The values to add to the set. |
|
* @returns {Object} Returns the new set. |
|
*/ |
|
var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { |
|
return new Set(values); |
|
}; |
|
|
|
/** |
|
* Creates a function that either curries or invokes `func` with optional |
|
* `this` binding and partially applied arguments. |
|
* |
|
* @private |
|
* @param {Function|string} func The function or method name to wrap. |
|
* @param {number} bitmask The bitmask flags. |
|
* 1 - `_.bind` |
|
* 2 - `_.bindKey` |
|
* 4 - `_.curry` or `_.curryRight` of a bound function |
|
* 8 - `_.curry` |
|
* 16 - `_.curryRight` |
|
* 32 - `_.partial` |
|
* 64 - `_.partialRight` |
|
* 128 - `_.rearg` |
|
* 256 - `_.ary` |
|
* 512 - `_.flip` |
|
* @param {*} [thisArg] The `this` binding of `func`. |
|
* @param {Array} [partials] The arguments to be partially applied. |
|
* @param {Array} [holders] The `partials` placeholder indexes. |
|
* @param {Array} [argPos] The argument positions of the new function. |
|
* @param {number} [ary] The arity cap of `func`. |
|
* @param {number} [arity] The arity of `func`. |
|
* @returns {Function} Returns the new wrapped function. |
|
*/ |
|
function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { |
|
var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; |
|
if (!isBindKey && typeof func != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
var length = partials ? partials.length : 0; |
|
if (!length) { |
|
bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); |
|
partials = holders = undefined; |
|
} |
|
ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); |
|
arity = arity === undefined ? arity : toInteger(arity); |
|
length -= holders ? holders.length : 0; |
|
|
|
if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { |
|
var partialsRight = partials, |
|
holdersRight = holders; |
|
|
|
partials = holders = undefined; |
|
} |
|
var data = isBindKey ? undefined : getData(func); |
|
|
|
var newData = [ |
|
func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, |
|
argPos, ary, arity |
|
]; |
|
|
|
if (data) { |
|
mergeData(newData, data); |
|
} |
|
func = newData[0]; |
|
bitmask = newData[1]; |
|
thisArg = newData[2]; |
|
partials = newData[3]; |
|
holders = newData[4]; |
|
arity = newData[9] = newData[9] === undefined |
|
? (isBindKey ? 0 : func.length) |
|
: nativeMax(newData[9] - length, 0); |
|
|
|
if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { |
|
bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); |
|
} |
|
if (!bitmask || bitmask == WRAP_BIND_FLAG) { |
|
var result = createBind(func, bitmask, thisArg); |
|
} else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { |
|
result = createCurry(func, bitmask, arity); |
|
} else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { |
|
result = createPartial(func, bitmask, thisArg, partials); |
|
} else { |
|
result = createHybrid.apply(undefined, newData); |
|
} |
|
var setter = data ? baseSetData : setData; |
|
return setWrapToString(setter(result, newData), func, bitmask); |
|
} |
|
|
|
/** |
|
* Used by `_.defaultsDeep` to customize its `_.merge` use to merge source |
|
* objects into destination objects that are passed thru. |
|
* |
|
* @private |
|
* @param {*} objValue The destination value. |
|
* @param {*} srcValue The source value. |
|
* @param {string} key The key of the property to merge. |
|
* @param {Object} object The parent object of `objValue`. |
|
* @param {Object} source The parent object of `srcValue`. |
|
* @param {Object} [stack] Tracks traversed source values and their merged |
|
* counterparts. |
|
* @returns {*} Returns the value to assign. |
|
*/ |
|
function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { |
|
if (isObject(objValue) && isObject(srcValue)) { |
|
// Recursively merge objects and arrays (susceptible to call stack limits). |
|
stack.set(srcValue, objValue); |
|
baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); |
|
stack['delete'](srcValue); |
|
} |
|
return objValue; |
|
} |
|
|
|
/** |
|
* Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain |
|
* objects. |
|
* |
|
* @private |
|
* @param {*} value The value to inspect. |
|
* @param {string} key The key of the property to inspect. |
|
* @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. |
|
*/ |
|
function customOmitClone(value) { |
|
return isPlainObject(value) ? undefined : value; |
|
} |
|
|
|
/** |
|
* A specialized version of `baseIsEqualDeep` for arrays with support for |
|
* partial deep comparisons. |
|
* |
|
* @private |
|
* @param {Array} array The array to compare. |
|
* @param {Array} other The other array to compare. |
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. |
|
* @param {Function} customizer The function to customize comparisons. |
|
* @param {Function} equalFunc The function to determine equivalents of values. |
|
* @param {Object} stack Tracks traversed `array` and `other` objects. |
|
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. |
|
*/ |
|
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { |
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG, |
|
arrLength = array.length, |
|
othLength = other.length; |
|
|
|
if (arrLength != othLength && !(isPartial && othLength > arrLength)) { |
|
return false; |
|
} |
|
// Assume cyclic values are equal. |
|
var stacked = stack.get(array); |
|
if (stacked && stack.get(other)) { |
|
return stacked == other; |
|
} |
|
var index = -1, |
|
result = true, |
|
seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; |
|
|
|
stack.set(array, other); |
|
stack.set(other, array); |
|
|
|
// Ignore non-index properties. |
|
while (++index < arrLength) { |
|
var arrValue = array[index], |
|
othValue = other[index]; |
|
|
|
if (customizer) { |
|
var compared = isPartial |
|
? customizer(othValue, arrValue, index, other, array, stack) |
|
: customizer(arrValue, othValue, index, array, other, stack); |
|
} |
|
if (compared !== undefined) { |
|
if (compared) { |
|
continue; |
|
} |
|
result = false; |
|
break; |
|
} |
|
// Recursively compare arrays (susceptible to call stack limits). |
|
if (seen) { |
|
if (!arraySome(other, function(othValue, othIndex) { |
|
if (!cacheHas(seen, othIndex) && |
|
(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { |
|
return seen.push(othIndex); |
|
} |
|
})) { |
|
result = false; |
|
break; |
|
} |
|
} else if (!( |
|
arrValue === othValue || |
|
equalFunc(arrValue, othValue, bitmask, customizer, stack) |
|
)) { |
|
result = false; |
|
break; |
|
} |
|
} |
|
stack['delete'](array); |
|
stack['delete'](other); |
|
return result; |
|
} |
|
|
|
/** |
|
* A specialized version of `baseIsEqualDeep` for comparing objects of |
|
* the same `toStringTag`. |
|
* |
|
* **Note:** This function only supports comparing values with tags of |
|
* `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. |
|
* |
|
* @private |
|
* @param {Object} object The object to compare. |
|
* @param {Object} other The other object to compare. |
|
* @param {string} tag The `toStringTag` of the objects to compare. |
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. |
|
* @param {Function} customizer The function to customize comparisons. |
|
* @param {Function} equalFunc The function to determine equivalents of values. |
|
* @param {Object} stack Tracks traversed `object` and `other` objects. |
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`. |
|
*/ |
|
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { |
|
switch (tag) { |
|
case dataViewTag: |
|
if ((object.byteLength != other.byteLength) || |
|
(object.byteOffset != other.byteOffset)) { |
|
return false; |
|
} |
|
object = object.buffer; |
|
other = other.buffer; |
|
|
|
case arrayBufferTag: |
|
if ((object.byteLength != other.byteLength) || |
|
!equalFunc(new Uint8Array(object), new Uint8Array(other))) { |
|
return false; |
|
} |
|
return true; |
|
|
|
case boolTag: |
|
case dateTag: |
|
case numberTag: |
|
// Coerce booleans to `1` or `0` and dates to milliseconds. |
|
// Invalid dates are coerced to `NaN`. |
|
return eq(+object, +other); |
|
|
|
case errorTag: |
|
return object.name == other.name && object.message == other.message; |
|
|
|
case regexpTag: |
|
case stringTag: |
|
// Coerce regexes to strings and treat strings, primitives and objects, |
|
// as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring |
|
// for more details. |
|
return object == (other + ''); |
|
|
|
case mapTag: |
|
var convert = mapToArray; |
|
|
|
case setTag: |
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG; |
|
convert || (convert = setToArray); |
|
|
|
if (object.size != other.size && !isPartial) { |
|
return false; |
|
} |
|
// Assume cyclic values are equal. |
|
var stacked = stack.get(object); |
|
if (stacked) { |
|
return stacked == other; |
|
} |
|
bitmask |= COMPARE_UNORDERED_FLAG; |
|
|
|
// Recursively compare objects (susceptible to call stack limits). |
|
stack.set(object, other); |
|
var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); |
|
stack['delete'](object); |
|
return result; |
|
|
|
case symbolTag: |
|
if (symbolValueOf) { |
|
return symbolValueOf.call(object) == symbolValueOf.call(other); |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* A specialized version of `baseIsEqualDeep` for objects with support for |
|
* partial deep comparisons. |
|
* |
|
* @private |
|
* @param {Object} object The object to compare. |
|
* @param {Object} other The other object to compare. |
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. |
|
* @param {Function} customizer The function to customize comparisons. |
|
* @param {Function} equalFunc The function to determine equivalents of values. |
|
* @param {Object} stack Tracks traversed `object` and `other` objects. |
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`. |
|
*/ |
|
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { |
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG, |
|
objProps = getAllKeys(object), |
|
objLength = objProps.length, |
|
othProps = getAllKeys(other), |
|
othLength = othProps.length; |
|
|
|
if (objLength != othLength && !isPartial) { |
|
return false; |
|
} |
|
var index = objLength; |
|
while (index--) { |
|
var key = objProps[index]; |
|
if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { |
|
return false; |
|
} |
|
} |
|
// Assume cyclic values are equal. |
|
var stacked = stack.get(object); |
|
if (stacked && stack.get(other)) { |
|
return stacked == other; |
|
} |
|
var result = true; |
|
stack.set(object, other); |
|
stack.set(other, object); |
|
|
|
var skipCtor = isPartial; |
|
while (++index < objLength) { |
|
key = objProps[index]; |
|
var objValue = object[key], |
|
othValue = other[key]; |
|
|
|
if (customizer) { |
|
var compared = isPartial |
|
? customizer(othValue, objValue, key, other, object, stack) |
|
: customizer(objValue, othValue, key, object, other, stack); |
|
} |
|
// Recursively compare objects (susceptible to call stack limits). |
|
if (!(compared === undefined |
|
? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) |
|
: compared |
|
)) { |
|
result = false; |
|
break; |
|
} |
|
skipCtor || (skipCtor = key == 'constructor'); |
|
} |
|
if (result && !skipCtor) { |
|
var objCtor = object.constructor, |
|
othCtor = other.constructor; |
|
|
|
// Non `Object` object instances with different constructors are not equal. |
|
if (objCtor != othCtor && |
|
('constructor' in object && 'constructor' in other) && |
|
!(typeof objCtor == 'function' && objCtor instanceof objCtor && |
|
typeof othCtor == 'function' && othCtor instanceof othCtor)) { |
|
result = false; |
|
} |
|
} |
|
stack['delete'](object); |
|
stack['delete'](other); |
|
return result; |
|
} |
|
|
|
/** |
|
* A specialized version of `baseRest` which flattens the rest array. |
|
* |
|
* @private |
|
* @param {Function} func The function to apply a rest parameter to. |
|
* @returns {Function} Returns the new function. |
|
*/ |
|
function flatRest(func) { |
|
return setToString(overRest(func, undefined, flatten), func + ''); |
|
} |
|
|
|
/** |
|
* Creates an array of own enumerable property names and symbols of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names and symbols. |
|
*/ |
|
function getAllKeys(object) { |
|
return baseGetAllKeys(object, keys, getSymbols); |
|
} |
|
|
|
/** |
|
* Creates an array of own and inherited enumerable property names and |
|
* symbols of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names and symbols. |
|
*/ |
|
function getAllKeysIn(object) { |
|
return baseGetAllKeys(object, keysIn, getSymbolsIn); |
|
} |
|
|
|
/** |
|
* Gets metadata for `func`. |
|
* |
|
* @private |
|
* @param {Function} func The function to query. |
|
* @returns {*} Returns the metadata for `func`. |
|
*/ |
|
var getData = !metaMap ? noop : function(func) { |
|
return metaMap.get(func); |
|
}; |
|
|
|
/** |
|
* Gets the name of `func`. |
|
* |
|
* @private |
|
* @param {Function} func The function to query. |
|
* @returns {string} Returns the function name. |
|
*/ |
|
function getFuncName(func) { |
|
var result = (func.name + ''), |
|
array = realNames[result], |
|
length = hasOwnProperty.call(realNames, result) ? array.length : 0; |
|
|
|
while (length--) { |
|
var data = array[length], |
|
otherFunc = data.func; |
|
if (otherFunc == null || otherFunc == func) { |
|
return data.name; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Gets the argument placeholder value for `func`. |
|
* |
|
* @private |
|
* @param {Function} func The function to inspect. |
|
* @returns {*} Returns the placeholder value. |
|
*/ |
|
function getHolder(func) { |
|
var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; |
|
return object.placeholder; |
|
} |
|
|
|
/** |
|
* Gets the data for `map`. |
|
* |
|
* @private |
|
* @param {Object} map The map to query. |
|
* @param {string} key The reference key. |
|
* @returns {*} Returns the map data. |
|
*/ |
|
function getMapData(map, key) { |
|
var data = map.__data__; |
|
return isKeyable(key) |
|
? data[typeof key == 'string' ? 'string' : 'hash'] |
|
: data.map; |
|
} |
|
|
|
/** |
|
* Gets the property names, values, and compare flags of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the match data of `object`. |
|
*/ |
|
function getMatchData(object) { |
|
var result = keys(object), |
|
length = result.length; |
|
|
|
while (length--) { |
|
var key = result[length], |
|
value = object[key]; |
|
|
|
result[length] = [key, value, isStrictComparable(value)]; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Gets the native function at `key` of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {string} key The key of the method to get. |
|
* @returns {*} Returns the function if it's native, else `undefined`. |
|
*/ |
|
function getNative(object, key) { |
|
var value = getValue(object, key); |
|
return baseIsNative(value) ? value : undefined; |
|
} |
|
|
|
/** |
|
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. |
|
* |
|
* @private |
|
* @param {*} value The value to query. |
|
* @returns {string} Returns the raw `toStringTag`. |
|
*/ |
|
function getRawTag(value) { |
|
var isOwn = hasOwnProperty.call(value, symToStringTag), |
|
tag = value[symToStringTag]; |
|
|
|
try { |
|
value[symToStringTag] = undefined; |
|
var unmasked = true; |
|
} catch (e) {} |
|
|
|
var result = nativeObjectToString.call(value); |
|
if (unmasked) { |
|
if (isOwn) { |
|
value[symToStringTag] = tag; |
|
} else { |
|
delete value[symToStringTag]; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Creates an array of the own enumerable symbols of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of symbols. |
|
*/ |
|
var getSymbols = !nativeGetSymbols ? stubArray : function(object) { |
|
if (object == null) { |
|
return []; |
|
} |
|
object = Object(object); |
|
return arrayFilter(nativeGetSymbols(object), function(symbol) { |
|
return propertyIsEnumerable.call(object, symbol); |
|
}); |
|
}; |
|
|
|
/** |
|
* Creates an array of the own and inherited enumerable symbols of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of symbols. |
|
*/ |
|
var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { |
|
var result = []; |
|
while (object) { |
|
arrayPush(result, getSymbols(object)); |
|
object = getPrototype(object); |
|
} |
|
return result; |
|
}; |
|
|
|
/** |
|
* Gets the `toStringTag` of `value`. |
|
* |
|
* @private |
|
* @param {*} value The value to query. |
|
* @returns {string} Returns the `toStringTag`. |
|
*/ |
|
var getTag = baseGetTag; |
|
|
|
// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. |
|
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || |
|
(Map && getTag(new Map) != mapTag) || |
|
(Promise && getTag(Promise.resolve()) != promiseTag) || |
|
(Set && getTag(new Set) != setTag) || |
|
(WeakMap && getTag(new WeakMap) != weakMapTag)) { |
|
getTag = function(value) { |
|
var result = baseGetTag(value), |
|
Ctor = result == objectTag ? value.constructor : undefined, |
|
ctorString = Ctor ? toSource(Ctor) : ''; |
|
|
|
if (ctorString) { |
|
switch (ctorString) { |
|
case dataViewCtorString: return dataViewTag; |
|
case mapCtorString: return mapTag; |
|
case promiseCtorString: return promiseTag; |
|
case setCtorString: return setTag; |
|
case weakMapCtorString: return weakMapTag; |
|
} |
|
} |
|
return result; |
|
}; |
|
} |
|
|
|
/** |
|
* Gets the view, applying any `transforms` to the `start` and `end` positions. |
|
* |
|
* @private |
|
* @param {number} start The start of the view. |
|
* @param {number} end The end of the view. |
|
* @param {Array} transforms The transformations to apply to the view. |
|
* @returns {Object} Returns an object containing the `start` and `end` |
|
* positions of the view. |
|
*/ |
|
function getView(start, end, transforms) { |
|
var index = -1, |
|
length = transforms.length; |
|
|
|
while (++index < length) { |
|
var data = transforms[index], |
|
size = data.size; |
|
|
|
switch (data.type) { |
|
case 'drop': start += size; break; |
|
case 'dropRight': end -= size; break; |
|
case 'take': end = nativeMin(end, start + size); break; |
|
case 'takeRight': start = nativeMax(start, end - size); break; |
|
} |
|
} |
|
return { 'start': start, 'end': end }; |
|
} |
|
|
|
/** |
|
* Extracts wrapper details from the `source` body comment. |
|
* |
|
* @private |
|
* @param {string} source The source to inspect. |
|
* @returns {Array} Returns the wrapper details. |
|
*/ |
|
function getWrapDetails(source) { |
|
var match = source.match(reWrapDetails); |
|
return match ? match[1].split(reSplitDetails) : []; |
|
} |
|
|
|
/** |
|
* Checks if `path` exists on `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path to check. |
|
* @param {Function} hasFunc The function to check properties. |
|
* @returns {boolean} Returns `true` if `path` exists, else `false`. |
|
*/ |
|
function hasPath(object, path, hasFunc) { |
|
path = castPath(path, object); |
|
|
|
var index = -1, |
|
length = path.length, |
|
result = false; |
|
|
|
while (++index < length) { |
|
var key = toKey(path[index]); |
|
if (!(result = object != null && hasFunc(object, key))) { |
|
break; |
|
} |
|
object = object[key]; |
|
} |
|
if (result || ++index != length) { |
|
return result; |
|
} |
|
length = object == null ? 0 : object.length; |
|
return !!length && isLength(length) && isIndex(key, length) && |
|
(isArray(object) || isArguments(object)); |
|
} |
|
|
|
/** |
|
* Initializes an array clone. |
|
* |
|
* @private |
|
* @param {Array} array The array to clone. |
|
* @returns {Array} Returns the initialized clone. |
|
*/ |
|
function initCloneArray(array) { |
|
var length = array.length, |
|
result = new array.constructor(length); |
|
|
|
// Add properties assigned by `RegExp#exec`. |
|
if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { |
|
result.index = array.index; |
|
result.input = array.input; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Initializes an object clone. |
|
* |
|
* @private |
|
* @param {Object} object The object to clone. |
|
* @returns {Object} Returns the initialized clone. |
|
*/ |
|
function initCloneObject(object) { |
|
return (typeof object.constructor == 'function' && !isPrototype(object)) |
|
? baseCreate(getPrototype(object)) |
|
: {}; |
|
} |
|
|
|
/** |
|
* Initializes an object clone based on its `toStringTag`. |
|
* |
|
* **Note:** This function only supports cloning values with tags of |
|
* `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. |
|
* |
|
* @private |
|
* @param {Object} object The object to clone. |
|
* @param {string} tag The `toStringTag` of the object to clone. |
|
* @param {boolean} [isDeep] Specify a deep clone. |
|
* @returns {Object} Returns the initialized clone. |
|
*/ |
|
function initCloneByTag(object, tag, isDeep) { |
|
var Ctor = object.constructor; |
|
switch (tag) { |
|
case arrayBufferTag: |
|
return cloneArrayBuffer(object); |
|
|
|
case boolTag: |
|
case dateTag: |
|
return new Ctor(+object); |
|
|
|
case dataViewTag: |
|
return cloneDataView(object, isDeep); |
|
|
|
case float32Tag: case float64Tag: |
|
case int8Tag: case int16Tag: case int32Tag: |
|
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: |
|
return cloneTypedArray(object, isDeep); |
|
|
|
case mapTag: |
|
return new Ctor; |
|
|
|
case numberTag: |
|
case stringTag: |
|
return new Ctor(object); |
|
|
|
case regexpTag: |
|
return cloneRegExp(object); |
|
|
|
case setTag: |
|
return new Ctor; |
|
|
|
case symbolTag: |
|
return cloneSymbol(object); |
|
} |
|
} |
|
|
|
/** |
|
* Inserts wrapper `details` in a comment at the top of the `source` body. |
|
* |
|
* @private |
|
* @param {string} source The source to modify. |
|
* @returns {Array} details The details to insert. |
|
* @returns {string} Returns the modified source. |
|
*/ |
|
function insertWrapDetails(source, details) { |
|
var length = details.length; |
|
if (!length) { |
|
return source; |
|
} |
|
var lastIndex = length - 1; |
|
details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; |
|
details = details.join(length > 2 ? ', ' : ' '); |
|
return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); |
|
} |
|
|
|
/** |
|
* Checks if `value` is a flattenable `arguments` object or array. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is flattenable, else `false`. |
|
*/ |
|
function isFlattenable(value) { |
|
return isArray(value) || isArguments(value) || |
|
!!(spreadableSymbol && value && value[spreadableSymbol]); |
|
} |
|
|
|
/** |
|
* Checks if `value` is a valid array-like index. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. |
|
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`. |
|
*/ |
|
function isIndex(value, length) { |
|
var type = typeof value; |
|
length = length == null ? MAX_SAFE_INTEGER : length; |
|
|
|
return !!length && |
|
(type == 'number' || |
|
(type != 'symbol' && reIsUint.test(value))) && |
|
(value > -1 && value % 1 == 0 && value < length); |
|
} |
|
|
|
/** |
|
* Checks if the given arguments are from an iteratee call. |
|
* |
|
* @private |
|
* @param {*} value The potential iteratee value argument. |
|
* @param {*} index The potential iteratee index or key argument. |
|
* @param {*} object The potential iteratee object argument. |
|
* @returns {boolean} Returns `true` if the arguments are from an iteratee call, |
|
* else `false`. |
|
*/ |
|
function isIterateeCall(value, index, object) { |
|
if (!isObject(object)) { |
|
return false; |
|
} |
|
var type = typeof index; |
|
if (type == 'number' |
|
? (isArrayLike(object) && isIndex(index, object.length)) |
|
: (type == 'string' && index in object) |
|
) { |
|
return eq(object[index], value); |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* Checks if `value` is a property name and not a property path. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @param {Object} [object] The object to query keys on. |
|
* @returns {boolean} Returns `true` if `value` is a property name, else `false`. |
|
*/ |
|
function isKey(value, object) { |
|
if (isArray(value)) { |
|
return false; |
|
} |
|
var type = typeof value; |
|
if (type == 'number' || type == 'symbol' || type == 'boolean' || |
|
value == null || isSymbol(value)) { |
|
return true; |
|
} |
|
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || |
|
(object != null && value in Object(object)); |
|
} |
|
|
|
/** |
|
* Checks if `value` is suitable for use as unique object key. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is suitable, else `false`. |
|
*/ |
|
function isKeyable(value) { |
|
var type = typeof value; |
|
return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') |
|
? (value !== '__proto__') |
|
: (value === null); |
|
} |
|
|
|
/** |
|
* Checks if `func` has a lazy counterpart. |
|
* |
|
* @private |
|
* @param {Function} func The function to check. |
|
* @returns {boolean} Returns `true` if `func` has a lazy counterpart, |
|
* else `false`. |
|
*/ |
|
function isLaziable(func) { |
|
var funcName = getFuncName(func), |
|
other = lodash[funcName]; |
|
|
|
if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { |
|
return false; |
|
} |
|
if (func === other) { |
|
return true; |
|
} |
|
var data = getData(other); |
|
return !!data && func === data[0]; |
|
} |
|
|
|
/** |
|
* Checks if `func` has its source masked. |
|
* |
|
* @private |
|
* @param {Function} func The function to check. |
|
* @returns {boolean} Returns `true` if `func` is masked, else `false`. |
|
*/ |
|
function isMasked(func) { |
|
return !!maskSrcKey && (maskSrcKey in func); |
|
} |
|
|
|
/** |
|
* Checks if `value` is likely a prototype object. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a prototype, else `false`. |
|
*/ |
|
function isPrototype(value) { |
|
var Ctor = value && value.constructor, |
|
proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; |
|
|
|
return value === proto; |
|
} |
|
|
|
/** |
|
* Checks if `value` is suitable for strict equality comparisons, i.e. `===`. |
|
* |
|
* @private |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` if suitable for strict |
|
* equality comparisons, else `false`. |
|
*/ |
|
function isStrictComparable(value) { |
|
return value === value && !isObject(value); |
|
} |
|
|
|
/** |
|
* A specialized version of `matchesProperty` for source values suitable |
|
* for strict equality comparisons, i.e. `===`. |
|
* |
|
* @private |
|
* @param {string} key The key of the property to get. |
|
* @param {*} srcValue The value to match. |
|
* @returns {Function} Returns the new spec function. |
|
*/ |
|
function matchesStrictComparable(key, srcValue) { |
|
return function(object) { |
|
if (object == null) { |
|
return false; |
|
} |
|
return object[key] === srcValue && |
|
(srcValue !== undefined || (key in Object(object))); |
|
}; |
|
} |
|
|
|
/** |
|
* A specialized version of `_.memoize` which clears the memoized function's |
|
* cache when it exceeds `MAX_MEMOIZE_SIZE`. |
|
* |
|
* @private |
|
* @param {Function} func The function to have its output memoized. |
|
* @returns {Function} Returns the new memoized function. |
|
*/ |
|
function memoizeCapped(func) { |
|
var result = memoize(func, function(key) { |
|
if (cache.size === MAX_MEMOIZE_SIZE) { |
|
cache.clear(); |
|
} |
|
return key; |
|
}); |
|
|
|
var cache = result.cache; |
|
return result; |
|
} |
|
|
|
/** |
|
* Merges the function metadata of `source` into `data`. |
|
* |
|
* Merging metadata reduces the number of wrappers used to invoke a function. |
|
* This is possible because methods like `_.bind`, `_.curry`, and `_.partial` |
|
* may be applied regardless of execution order. Methods like `_.ary` and |
|
* `_.rearg` modify function arguments, making the order in which they are |
|
* executed important, preventing the merging of metadata. However, we make |
|
* an exception for a safe combined case where curried functions have `_.ary` |
|
* and or `_.rearg` applied. |
|
* |
|
* @private |
|
* @param {Array} data The destination metadata. |
|
* @param {Array} source The source metadata. |
|
* @returns {Array} Returns `data`. |
|
*/ |
|
function mergeData(data, source) { |
|
var bitmask = data[1], |
|
srcBitmask = source[1], |
|
newBitmask = bitmask | srcBitmask, |
|
isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); |
|
|
|
var isCombo = |
|
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || |
|
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || |
|
((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); |
|
|
|
// Exit early if metadata can't be merged. |
|
if (!(isCommon || isCombo)) { |
|
return data; |
|
} |
|
// Use source `thisArg` if available. |
|
if (srcBitmask & WRAP_BIND_FLAG) { |
|
data[2] = source[2]; |
|
// Set when currying a bound function. |
|
newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; |
|
} |
|
// Compose partial arguments. |
|
var value = source[3]; |
|
if (value) { |
|
var partials = data[3]; |
|
data[3] = partials ? composeArgs(partials, value, source[4]) : value; |
|
data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; |
|
} |
|
// Compose partial right arguments. |
|
value = source[5]; |
|
if (value) { |
|
partials = data[5]; |
|
data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; |
|
data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; |
|
} |
|
// Use source `argPos` if available. |
|
value = source[7]; |
|
if (value) { |
|
data[7] = value; |
|
} |
|
// Use source `ary` if it's smaller. |
|
if (srcBitmask & WRAP_ARY_FLAG) { |
|
data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); |
|
} |
|
// Use source `arity` if one is not provided. |
|
if (data[9] == null) { |
|
data[9] = source[9]; |
|
} |
|
// Use source `func` and merge bitmasks. |
|
data[0] = source[0]; |
|
data[1] = newBitmask; |
|
|
|
return data; |
|
} |
|
|
|
/** |
|
* This function is like |
|
* [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) |
|
* except that it includes inherited enumerable properties. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names. |
|
*/ |
|
function nativeKeysIn(object) { |
|
var result = []; |
|
if (object != null) { |
|
for (var key in Object(object)) { |
|
result.push(key); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Converts `value` to a string using `Object.prototype.toString`. |
|
* |
|
* @private |
|
* @param {*} value The value to convert. |
|
* @returns {string} Returns the converted string. |
|
*/ |
|
function objectToString(value) { |
|
return nativeObjectToString.call(value); |
|
} |
|
|
|
/** |
|
* A specialized version of `baseRest` which transforms the rest array. |
|
* |
|
* @private |
|
* @param {Function} func The function to apply a rest parameter to. |
|
* @param {number} [start=func.length-1] The start position of the rest parameter. |
|
* @param {Function} transform The rest array transform. |
|
* @returns {Function} Returns the new function. |
|
*/ |
|
function overRest(func, start, transform) { |
|
start = nativeMax(start === undefined ? (func.length - 1) : start, 0); |
|
return function() { |
|
var args = arguments, |
|
index = -1, |
|
length = nativeMax(args.length - start, 0), |
|
array = Array(length); |
|
|
|
while (++index < length) { |
|
array[index] = args[start + index]; |
|
} |
|
index = -1; |
|
var otherArgs = Array(start + 1); |
|
while (++index < start) { |
|
otherArgs[index] = args[index]; |
|
} |
|
otherArgs[start] = transform(array); |
|
return apply(func, this, otherArgs); |
|
}; |
|
} |
|
|
|
/** |
|
* Gets the parent value at `path` of `object`. |
|
* |
|
* @private |
|
* @param {Object} object The object to query. |
|
* @param {Array} path The path to get the parent value of. |
|
* @returns {*} Returns the parent value. |
|
*/ |
|
function parent(object, path) { |
|
return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); |
|
} |
|
|
|
/** |
|
* Reorder `array` according to the specified indexes where the element at |
|
* the first index is assigned as the first element, the element at |
|
* the second index is assigned as the second element, and so on. |
|
* |
|
* @private |
|
* @param {Array} array The array to reorder. |
|
* @param {Array} indexes The arranged array indexes. |
|
* @returns {Array} Returns `array`. |
|
*/ |
|
function reorder(array, indexes) { |
|
var arrLength = array.length, |
|
length = nativeMin(indexes.length, arrLength), |
|
oldArray = copyArray(array); |
|
|
|
while (length--) { |
|
var index = indexes[length]; |
|
array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; |
|
} |
|
return array; |
|
} |
|
|
|
/** |
|
* Sets metadata for `func`. |
|
* |
|
* **Note:** If this function becomes hot, i.e. is invoked a lot in a short |
|
* period of time, it will trip its breaker and transition to an identity |
|
* function to avoid garbage collection pauses in V8. See |
|
* [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) |
|
* for more details. |
|
* |
|
* @private |
|
* @param {Function} func The function to associate metadata with. |
|
* @param {*} data The metadata. |
|
* @returns {Function} Returns `func`. |
|
*/ |
|
var setData = shortOut(baseSetData); |
|
|
|
/** |
|
* Sets the `toString` method of `func` to return `string`. |
|
* |
|
* @private |
|
* @param {Function} func The function to modify. |
|
* @param {Function} string The `toString` result. |
|
* @returns {Function} Returns `func`. |
|
*/ |
|
var setToString = shortOut(baseSetToString); |
|
|
|
/** |
|
* Sets the `toString` method of `wrapper` to mimic the source of `reference` |
|
* with wrapper details in a comment at the top of the source body. |
|
* |
|
* @private |
|
* @param {Function} wrapper The function to modify. |
|
* @param {Function} reference The reference function. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @returns {Function} Returns `wrapper`. |
|
*/ |
|
function setWrapToString(wrapper, reference, bitmask) { |
|
var source = (reference + ''); |
|
return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); |
|
} |
|
|
|
/** |
|
* Creates a function that'll short out and invoke `identity` instead |
|
* of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` |
|
* milliseconds. |
|
* |
|
* @private |
|
* @param {Function} func The function to restrict. |
|
* @returns {Function} Returns the new shortable function. |
|
*/ |
|
function shortOut(func) { |
|
var count = 0, |
|
lastCalled = 0; |
|
|
|
return function() { |
|
var stamp = nativeNow(), |
|
remaining = HOT_SPAN - (stamp - lastCalled); |
|
|
|
lastCalled = stamp; |
|
if (remaining > 0) { |
|
if (++count >= HOT_COUNT) { |
|
return arguments[0]; |
|
} |
|
} else { |
|
count = 0; |
|
} |
|
return func.apply(undefined, arguments); |
|
}; |
|
} |
|
|
|
/** |
|
* Converts `string` to a property path array. |
|
* |
|
* @private |
|
* @param {string} string The string to convert. |
|
* @returns {Array} Returns the property path array. |
|
*/ |
|
var stringToPath = memoizeCapped(function(string) { |
|
var result = []; |
|
if (string.charCodeAt(0) === 46 /* . */) { |
|
result.push(''); |
|
} |
|
string.replace(rePropName, function(match, number, quote, subString) { |
|
result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); |
|
}); |
|
return result; |
|
}); |
|
|
|
/** |
|
* Converts `value` to a string key if it's not a string or symbol. |
|
* |
|
* @private |
|
* @param {*} value The value to inspect. |
|
* @returns {string|symbol} Returns the key. |
|
*/ |
|
function toKey(value) { |
|
if (typeof value == 'string' || isSymbol(value)) { |
|
return value; |
|
} |
|
var result = (value + ''); |
|
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; |
|
} |
|
|
|
/** |
|
* Converts `func` to its source code. |
|
* |
|
* @private |
|
* @param {Function} func The function to convert. |
|
* @returns {string} Returns the source code. |
|
*/ |
|
function toSource(func) { |
|
if (func != null) { |
|
try { |
|
return funcToString.call(func); |
|
} catch (e) {} |
|
try { |
|
return (func + ''); |
|
} catch (e) {} |
|
} |
|
return ''; |
|
} |
|
|
|
/** |
|
* Updates wrapper `details` based on `bitmask` flags. |
|
* |
|
* @private |
|
* @returns {Array} details The details to modify. |
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details. |
|
* @returns {Array} Returns `details`. |
|
*/ |
|
function updateWrapDetails(details, bitmask) { |
|
arrayEach(wrapFlags, function(pair) { |
|
var value = '_.' + pair[0]; |
|
if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { |
|
details.push(value); |
|
} |
|
}); |
|
return details.sort(); |
|
} |
|
|
|
/** |
|
* Creates a clone of `wrapper`. |
|
* |
|
* @private |
|
* @param {Object} wrapper The wrapper to clone. |
|
* @returns {Object} Returns the cloned wrapper. |
|
*/ |
|
function wrapperClone(wrapper) { |
|
if (wrapper instanceof LazyWrapper) { |
|
return wrapper.clone(); |
|
} |
|
var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); |
|
result.__actions__ = copyArray(wrapper.__actions__); |
|
result.__index__ = wrapper.__index__; |
|
result.__values__ = wrapper.__values__; |
|
return result; |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates an array with all falsey values removed. The values `false`, `null`, |
|
* `0`, `""`, `undefined`, and `NaN` are falsey. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to compact. |
|
* @returns {Array} Returns the new array of filtered values. |
|
* @example |
|
* |
|
* _.compact([0, 1, false, 2, '', 3]); |
|
* // => [1, 2, 3] |
|
*/ |
|
function compact(array) { |
|
var index = -1, |
|
length = array == null ? 0 : array.length, |
|
resIndex = 0, |
|
result = []; |
|
|
|
while (++index < length) { |
|
var value = array[index]; |
|
if (value) { |
|
result[resIndex++] = value; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* Creates a new array concatenating `array` with any additional arrays |
|
* and/or values. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Array |
|
* @param {Array} array The array to concatenate. |
|
* @param {...*} [values] The values to concatenate. |
|
* @returns {Array} Returns the new concatenated array. |
|
* @example |
|
* |
|
* var array = [1]; |
|
* var other = _.concat(array, 2, [3], [[4]]); |
|
* |
|
* console.log(other); |
|
* // => [1, 2, 3, [4]] |
|
* |
|
* console.log(array); |
|
* // => [1] |
|
*/ |
|
function concat() { |
|
var length = arguments.length; |
|
if (!length) { |
|
return []; |
|
} |
|
var args = Array(length - 1), |
|
array = arguments[0], |
|
index = length; |
|
|
|
while (index--) { |
|
args[index - 1] = arguments[index]; |
|
} |
|
return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); |
|
} |
|
|
|
/** |
|
* Creates an array of `array` values not included in the other given arrays |
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons. The order and references of result values are |
|
* determined by the first array. |
|
* |
|
* **Note:** Unlike `_.pullAll`, this method returns a new array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @param {...Array} [values] The values to exclude. |
|
* @returns {Array} Returns the new array of filtered values. |
|
* @see _.without, _.xor |
|
* @example |
|
* |
|
* _.difference([2, 1], [2, 3]); |
|
* // => [1] |
|
*/ |
|
var difference = baseRest(function(array, values) { |
|
return isArrayLikeObject(array) |
|
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) |
|
: []; |
|
}); |
|
|
|
/** |
|
* Creates a slice of `array` with `n` elements dropped from the beginning. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.5.0 |
|
* @category Array |
|
* @param {Array} array The array to query. |
|
* @param {number} [n=1] The number of elements to drop. |
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
|
* @returns {Array} Returns the slice of `array`. |
|
* @example |
|
* |
|
* _.drop([1, 2, 3]); |
|
* // => [2, 3] |
|
* |
|
* _.drop([1, 2, 3], 2); |
|
* // => [3] |
|
* |
|
* _.drop([1, 2, 3], 5); |
|
* // => [] |
|
* |
|
* _.drop([1, 2, 3], 0); |
|
* // => [1, 2, 3] |
|
*/ |
|
function drop(array, n, guard) { |
|
var length = array == null ? 0 : array.length; |
|
if (!length) { |
|
return []; |
|
} |
|
n = (guard || n === undefined) ? 1 : toInteger(n); |
|
return baseSlice(array, n < 0 ? 0 : n, length); |
|
} |
|
|
|
/** |
|
* This method is like `_.find` except that it returns the index of the first |
|
* element `predicate` returns truthy for instead of the element itself. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 1.1.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @param {number} [fromIndex=0] The index to search from. |
|
* @returns {number} Returns the index of the found element, else `-1`. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'active': false }, |
|
* { 'user': 'fred', 'active': false }, |
|
* { 'user': 'pebbles', 'active': true } |
|
* ]; |
|
* |
|
* _.findIndex(users, function(o) { return o.user == 'barney'; }); |
|
* // => 0 |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.findIndex(users, { 'user': 'fred', 'active': false }); |
|
* // => 1 |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.findIndex(users, ['active', false]); |
|
* // => 0 |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.findIndex(users, 'active'); |
|
* // => 2 |
|
*/ |
|
function findIndex(array, predicate, fromIndex) { |
|
var length = array == null ? 0 : array.length; |
|
if (!length) { |
|
return -1; |
|
} |
|
var index = fromIndex == null ? 0 : toInteger(fromIndex); |
|
if (index < 0) { |
|
index = nativeMax(length + index, 0); |
|
} |
|
return baseFindIndex(array, baseIteratee(predicate, 3), index); |
|
} |
|
|
|
/** |
|
* This method is like `_.findIndex` except that it iterates over elements |
|
* of `collection` from right to left. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.0.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @param {number} [fromIndex=array.length-1] The index to search from. |
|
* @returns {number} Returns the index of the found element, else `-1`. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'active': true }, |
|
* { 'user': 'fred', 'active': false }, |
|
* { 'user': 'pebbles', 'active': false } |
|
* ]; |
|
* |
|
* _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); |
|
* // => 2 |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.findLastIndex(users, { 'user': 'barney', 'active': true }); |
|
* // => 0 |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.findLastIndex(users, ['active', false]); |
|
* // => 2 |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.findLastIndex(users, 'active'); |
|
* // => 0 |
|
*/ |
|
function findLastIndex(array, predicate, fromIndex) { |
|
var length = array == null ? 0 : array.length; |
|
if (!length) { |
|
return -1; |
|
} |
|
var index = length - 1; |
|
if (fromIndex !== undefined) { |
|
index = toInteger(fromIndex); |
|
index = fromIndex < 0 |
|
? nativeMax(length + index, 0) |
|
: nativeMin(index, length - 1); |
|
} |
|
return baseFindIndex(array, baseIteratee(predicate, 3), index, true); |
|
} |
|
|
|
/** |
|
* Flattens `array` a single level deep. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to flatten. |
|
* @returns {Array} Returns the new flattened array. |
|
* @example |
|
* |
|
* _.flatten([1, [2, [3, [4]], 5]]); |
|
* // => [1, 2, [3, [4]], 5] |
|
*/ |
|
function flatten(array) { |
|
var length = array == null ? 0 : array.length; |
|
return length ? baseFlatten(array, 1) : []; |
|
} |
|
|
|
/** |
|
* Recursively flattens `array`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Array |
|
* @param {Array} array The array to flatten. |
|
* @returns {Array} Returns the new flattened array. |
|
* @example |
|
* |
|
* _.flattenDeep([1, [2, [3, [4]], 5]]); |
|
* // => [1, 2, 3, 4, 5] |
|
*/ |
|
function flattenDeep(array) { |
|
var length = array == null ? 0 : array.length; |
|
return length ? baseFlatten(array, INFINITY) : []; |
|
} |
|
|
|
/** |
|
* Gets the first element of `array`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @alias first |
|
* @category Array |
|
* @param {Array} array The array to query. |
|
* @returns {*} Returns the first element of `array`. |
|
* @example |
|
* |
|
* _.head([1, 2, 3]); |
|
* // => 1 |
|
* |
|
* _.head([]); |
|
* // => undefined |
|
*/ |
|
function head(array) { |
|
return (array && array.length) ? array[0] : undefined; |
|
} |
|
|
|
/** |
|
* Gets the index at which the first occurrence of `value` is found in `array` |
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons. If `fromIndex` is negative, it's used as the |
|
* offset from the end of `array`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @param {*} value The value to search for. |
|
* @param {number} [fromIndex=0] The index to search from. |
|
* @returns {number} Returns the index of the matched value, else `-1`. |
|
* @example |
|
* |
|
* _.indexOf([1, 2, 1, 2], 2); |
|
* // => 1 |
|
* |
|
* // Search from the `fromIndex`. |
|
* _.indexOf([1, 2, 1, 2], 2, 2); |
|
* // => 3 |
|
*/ |
|
function indexOf(array, value, fromIndex) { |
|
var length = array == null ? 0 : array.length; |
|
if (!length) { |
|
return -1; |
|
} |
|
var index = fromIndex == null ? 0 : toInteger(fromIndex); |
|
if (index < 0) { |
|
index = nativeMax(length + index, 0); |
|
} |
|
return baseIndexOf(array, value, index); |
|
} |
|
|
|
/** |
|
* Gets all but the last element of `array`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to query. |
|
* @returns {Array} Returns the slice of `array`. |
|
* @example |
|
* |
|
* _.initial([1, 2, 3]); |
|
* // => [1, 2] |
|
*/ |
|
function initial(array) { |
|
var length = array == null ? 0 : array.length; |
|
return length ? baseSlice(array, 0, -1) : []; |
|
} |
|
|
|
/** |
|
* Creates an array of unique values that are included in all given arrays |
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons. The order and references of result values are |
|
* determined by the first array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {...Array} [arrays] The arrays to inspect. |
|
* @returns {Array} Returns the new array of intersecting values. |
|
* @example |
|
* |
|
* _.intersection([2, 1], [2, 3]); |
|
* // => [2] |
|
*/ |
|
var intersection = baseRest(function(arrays) { |
|
var mapped = arrayMap(arrays, castArrayLikeObject); |
|
return (mapped.length && mapped[0] === arrays[0]) |
|
? baseIntersection(mapped) |
|
: []; |
|
}); |
|
|
|
/** |
|
* Gets the last element of `array`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to query. |
|
* @returns {*} Returns the last element of `array`. |
|
* @example |
|
* |
|
* _.last([1, 2, 3]); |
|
* // => 3 |
|
*/ |
|
function last(array) { |
|
var length = array == null ? 0 : array.length; |
|
return length ? array[length - 1] : undefined; |
|
} |
|
|
|
/** |
|
* Reverses `array` so that the first element becomes the last, the second |
|
* element becomes the second to last, and so on. |
|
* |
|
* **Note:** This method mutates `array` and is based on |
|
* [`Array#reverse`](https://mdn.io/Array/reverse). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Array |
|
* @param {Array} array The array to modify. |
|
* @returns {Array} Returns `array`. |
|
* @example |
|
* |
|
* var array = [1, 2, 3]; |
|
* |
|
* _.reverse(array); |
|
* // => [3, 2, 1] |
|
* |
|
* console.log(array); |
|
* // => [3, 2, 1] |
|
*/ |
|
function reverse(array) { |
|
return array == null ? array : nativeReverse.call(array); |
|
} |
|
|
|
/** |
|
* Creates a slice of `array` from `start` up to, but not including, `end`. |
|
* |
|
* **Note:** This method is used instead of |
|
* [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are |
|
* returned. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Array |
|
* @param {Array} array The array to slice. |
|
* @param {number} [start=0] The start position. |
|
* @param {number} [end=array.length] The end position. |
|
* @returns {Array} Returns the slice of `array`. |
|
*/ |
|
function slice(array, start, end) { |
|
var length = array == null ? 0 : array.length; |
|
if (!length) { |
|
return []; |
|
} |
|
if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { |
|
start = 0; |
|
end = length; |
|
} |
|
else { |
|
start = start == null ? 0 : toInteger(start); |
|
end = end === undefined ? length : toInteger(end); |
|
} |
|
return baseSlice(array, start, end); |
|
} |
|
|
|
/** |
|
* Creates a slice of `array` with `n` elements taken from the beginning. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to query. |
|
* @param {number} [n=1] The number of elements to take. |
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
|
* @returns {Array} Returns the slice of `array`. |
|
* @example |
|
* |
|
* _.take([1, 2, 3]); |
|
* // => [1] |
|
* |
|
* _.take([1, 2, 3], 2); |
|
* // => [1, 2] |
|
* |
|
* _.take([1, 2, 3], 5); |
|
* // => [1, 2, 3] |
|
* |
|
* _.take([1, 2, 3], 0); |
|
* // => [] |
|
*/ |
|
function take(array, n, guard) { |
|
if (!(array && array.length)) { |
|
return []; |
|
} |
|
n = (guard || n === undefined) ? 1 : toInteger(n); |
|
return baseSlice(array, 0, n < 0 ? 0 : n); |
|
} |
|
|
|
/** |
|
* Creates a slice of `array` with `n` elements taken from the end. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Array |
|
* @param {Array} array The array to query. |
|
* @param {number} [n=1] The number of elements to take. |
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
|
* @returns {Array} Returns the slice of `array`. |
|
* @example |
|
* |
|
* _.takeRight([1, 2, 3]); |
|
* // => [3] |
|
* |
|
* _.takeRight([1, 2, 3], 2); |
|
* // => [2, 3] |
|
* |
|
* _.takeRight([1, 2, 3], 5); |
|
* // => [1, 2, 3] |
|
* |
|
* _.takeRight([1, 2, 3], 0); |
|
* // => [] |
|
*/ |
|
function takeRight(array, n, guard) { |
|
var length = array == null ? 0 : array.length; |
|
if (!length) { |
|
return []; |
|
} |
|
n = (guard || n === undefined) ? 1 : toInteger(n); |
|
n = length - n; |
|
return baseSlice(array, n < 0 ? 0 : n, length); |
|
} |
|
|
|
/** |
|
* Creates an array of unique values, in order, from all given arrays using |
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {...Array} [arrays] The arrays to inspect. |
|
* @returns {Array} Returns the new array of combined values. |
|
* @example |
|
* |
|
* _.union([2], [1, 2]); |
|
* // => [2, 1] |
|
*/ |
|
var union = baseRest(function(arrays) { |
|
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); |
|
}); |
|
|
|
/** |
|
* Creates a duplicate-free version of an array, using |
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons, in which only the first occurrence of each element |
|
* is kept. The order of result values is determined by the order they occur |
|
* in the array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @returns {Array} Returns the new duplicate free array. |
|
* @example |
|
* |
|
* _.uniq([2, 1, 2]); |
|
* // => [2, 1] |
|
*/ |
|
function uniq(array) { |
|
return (array && array.length) ? baseUniq(array) : []; |
|
} |
|
|
|
/** |
|
* This method is like `_.uniq` except that it accepts `iteratee` which is |
|
* invoked for each element in `array` to generate the criterion by which |
|
* uniqueness is computed. The order of result values is determined by the |
|
* order they occur in the array. The iteratee is invoked with one argument: |
|
* (value). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element. |
|
* @returns {Array} Returns the new duplicate free array. |
|
* @example |
|
* |
|
* _.uniqBy([2.1, 1.2, 2.3], Math.floor); |
|
* // => [2.1, 1.2] |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); |
|
* // => [{ 'x': 1 }, { 'x': 2 }] |
|
*/ |
|
function uniqBy(array, iteratee) { |
|
return (array && array.length) ? baseUniq(array, baseIteratee(iteratee, 2)) : []; |
|
} |
|
|
|
/** |
|
* This method is like `_.zip` except that it accepts an array of grouped |
|
* elements and creates an array regrouping the elements to their pre-zip |
|
* configuration. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 1.2.0 |
|
* @category Array |
|
* @param {Array} array The array of grouped elements to process. |
|
* @returns {Array} Returns the new array of regrouped elements. |
|
* @example |
|
* |
|
* var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); |
|
* // => [['a', 1, true], ['b', 2, false]] |
|
* |
|
* _.unzip(zipped); |
|
* // => [['a', 'b'], [1, 2], [true, false]] |
|
*/ |
|
function unzip(array) { |
|
if (!(array && array.length)) { |
|
return []; |
|
} |
|
var length = 0; |
|
array = arrayFilter(array, function(group) { |
|
if (isArrayLikeObject(group)) { |
|
length = nativeMax(group.length, length); |
|
return true; |
|
} |
|
}); |
|
return baseTimes(length, function(index) { |
|
return arrayMap(array, baseProperty(index)); |
|
}); |
|
} |
|
|
|
/** |
|
* Creates an array excluding all given values using |
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* for equality comparisons. |
|
* |
|
* **Note:** Unlike `_.pull`, this method returns a new array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {Array} array The array to inspect. |
|
* @param {...*} [values] The values to exclude. |
|
* @returns {Array} Returns the new array of filtered values. |
|
* @see _.difference, _.xor |
|
* @example |
|
* |
|
* _.without([2, 1, 2, 3], 1, 2); |
|
* // => [3] |
|
*/ |
|
var without = baseRest(function(array, values) { |
|
return isArrayLikeObject(array) |
|
? baseDifference(array, values) |
|
: []; |
|
}); |
|
|
|
/** |
|
* Creates an array of grouped elements, the first of which contains the |
|
* first elements of the given arrays, the second of which contains the |
|
* second elements of the given arrays, and so on. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Array |
|
* @param {...Array} [arrays] The arrays to process. |
|
* @returns {Array} Returns the new array of grouped elements. |
|
* @example |
|
* |
|
* _.zip(['a', 'b'], [1, 2], [true, false]); |
|
* // => [['a', 1, true], ['b', 2, false]] |
|
*/ |
|
var zip = baseRest(unzip); |
|
|
|
/** |
|
* This method is like `_.fromPairs` except that it accepts two arrays, |
|
* one of property identifiers and one of corresponding values. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.4.0 |
|
* @category Array |
|
* @param {Array} [props=[]] The property identifiers. |
|
* @param {Array} [values=[]] The property values. |
|
* @returns {Object} Returns the new object. |
|
* @example |
|
* |
|
* _.zipObject(['a', 'b'], [1, 2]); |
|
* // => { 'a': 1, 'b': 2 } |
|
*/ |
|
function zipObject(props, values) { |
|
return baseZipObject(props || [], values || [], assignValue); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a `lodash` wrapper instance that wraps `value` with explicit method |
|
* chain sequences enabled. The result of such sequences must be unwrapped |
|
* with `_#value`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 1.3.0 |
|
* @category Seq |
|
* @param {*} value The value to wrap. |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36 }, |
|
* { 'user': 'fred', 'age': 40 }, |
|
* { 'user': 'pebbles', 'age': 1 } |
|
* ]; |
|
* |
|
* var youngest = _ |
|
* .chain(users) |
|
* .sortBy('age') |
|
* .map(function(o) { |
|
* return o.user + ' is ' + o.age; |
|
* }) |
|
* .head() |
|
* .value(); |
|
* // => 'pebbles is 1' |
|
*/ |
|
function chain(value) { |
|
var result = lodash(value); |
|
result.__chain__ = true; |
|
return result; |
|
} |
|
|
|
/** |
|
* This method invokes `interceptor` and returns `value`. The interceptor |
|
* is invoked with one argument; (value). The purpose of this method is to |
|
* "tap into" a method chain sequence in order to modify intermediate results. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Seq |
|
* @param {*} value The value to provide to `interceptor`. |
|
* @param {Function} interceptor The function to invoke. |
|
* @returns {*} Returns `value`. |
|
* @example |
|
* |
|
* _([1, 2, 3]) |
|
* .tap(function(array) { |
|
* // Mutate input array. |
|
* array.pop(); |
|
* }) |
|
* .reverse() |
|
* .value(); |
|
* // => [2, 1] |
|
*/ |
|
function tap(value, interceptor) { |
|
interceptor(value); |
|
return value; |
|
} |
|
|
|
/** |
|
* This method is like `_.tap` except that it returns the result of `interceptor`. |
|
* The purpose of this method is to "pass thru" values replacing intermediate |
|
* results in a method chain sequence. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Seq |
|
* @param {*} value The value to provide to `interceptor`. |
|
* @param {Function} interceptor The function to invoke. |
|
* @returns {*} Returns the result of `interceptor`. |
|
* @example |
|
* |
|
* _(' abc ') |
|
* .chain() |
|
* .trim() |
|
* .thru(function(value) { |
|
* return [value]; |
|
* }) |
|
* .value(); |
|
* // => ['abc'] |
|
*/ |
|
function thru(value, interceptor) { |
|
return interceptor(value); |
|
} |
|
|
|
/** |
|
* This method is the wrapper version of `_.at`. |
|
* |
|
* @name at |
|
* @memberOf _ |
|
* @since 1.0.0 |
|
* @category Seq |
|
* @param {...(string|string[])} [paths] The property paths to pick. |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; |
|
* |
|
* _(object).at(['a[0].b.c', 'a[1]']).value(); |
|
* // => [3, 4] |
|
*/ |
|
var wrapperAt = flatRest(function(paths) { |
|
var length = paths.length, |
|
start = length ? paths[0] : 0, |
|
value = this.__wrapped__, |
|
interceptor = function(object) { return baseAt(object, paths); }; |
|
|
|
if (length > 1 || this.__actions__.length || |
|
!(value instanceof LazyWrapper) || !isIndex(start)) { |
|
return this.thru(interceptor); |
|
} |
|
value = value.slice(start, +start + (length ? 1 : 0)); |
|
value.__actions__.push({ |
|
'func': thru, |
|
'args': [interceptor], |
|
'thisArg': undefined |
|
}); |
|
return new LodashWrapper(value, this.__chain__).thru(function(array) { |
|
if (length && !array.length) { |
|
array.push(undefined); |
|
} |
|
return array; |
|
}); |
|
}); |
|
|
|
/** |
|
* Creates a `lodash` wrapper instance with explicit method chain sequences enabled. |
|
* |
|
* @name chain |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Seq |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36 }, |
|
* { 'user': 'fred', 'age': 40 } |
|
* ]; |
|
* |
|
* // A sequence without explicit chaining. |
|
* _(users).head(); |
|
* // => { 'user': 'barney', 'age': 36 } |
|
* |
|
* // A sequence with explicit chaining. |
|
* _(users) |
|
* .chain() |
|
* .head() |
|
* .pick('user') |
|
* .value(); |
|
* // => { 'user': 'barney' } |
|
*/ |
|
function wrapperChain() { |
|
return chain(this); |
|
} |
|
|
|
/** |
|
* Executes the chain sequence and returns the wrapped result. |
|
* |
|
* @name commit |
|
* @memberOf _ |
|
* @since 3.2.0 |
|
* @category Seq |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* var array = [1, 2]; |
|
* var wrapped = _(array).push(3); |
|
* |
|
* console.log(array); |
|
* // => [1, 2] |
|
* |
|
* wrapped = wrapped.commit(); |
|
* console.log(array); |
|
* // => [1, 2, 3] |
|
* |
|
* wrapped.last(); |
|
* // => 3 |
|
* |
|
* console.log(array); |
|
* // => [1, 2, 3] |
|
*/ |
|
function wrapperCommit() { |
|
return new LodashWrapper(this.value(), this.__chain__); |
|
} |
|
|
|
/** |
|
* Gets the next value on a wrapped object following the |
|
* [iterator protocol](https://mdn.io/iteration_protocols#iterator). |
|
* |
|
* @name next |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Seq |
|
* @returns {Object} Returns the next iterator value. |
|
* @example |
|
* |
|
* var wrapped = _([1, 2]); |
|
* |
|
* wrapped.next(); |
|
* // => { 'done': false, 'value': 1 } |
|
* |
|
* wrapped.next(); |
|
* // => { 'done': false, 'value': 2 } |
|
* |
|
* wrapped.next(); |
|
* // => { 'done': true, 'value': undefined } |
|
*/ |
|
function wrapperNext() { |
|
if (this.__values__ === undefined) { |
|
this.__values__ = toArray(this.value()); |
|
} |
|
var done = this.__index__ >= this.__values__.length, |
|
value = done ? undefined : this.__values__[this.__index__++]; |
|
|
|
return { 'done': done, 'value': value }; |
|
} |
|
|
|
/** |
|
* Enables the wrapper to be iterable. |
|
* |
|
* @name Symbol.iterator |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Seq |
|
* @returns {Object} Returns the wrapper object. |
|
* @example |
|
* |
|
* var wrapped = _([1, 2]); |
|
* |
|
* wrapped[Symbol.iterator]() === wrapped; |
|
* // => true |
|
* |
|
* Array.from(wrapped); |
|
* // => [1, 2] |
|
*/ |
|
function wrapperToIterator() { |
|
return this; |
|
} |
|
|
|
/** |
|
* Creates a clone of the chain sequence planting `value` as the wrapped value. |
|
* |
|
* @name plant |
|
* @memberOf _ |
|
* @since 3.2.0 |
|
* @category Seq |
|
* @param {*} value The value to plant. |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* function square(n) { |
|
* return n * n; |
|
* } |
|
* |
|
* var wrapped = _([1, 2]).map(square); |
|
* var other = wrapped.plant([3, 4]); |
|
* |
|
* other.value(); |
|
* // => [9, 16] |
|
* |
|
* wrapped.value(); |
|
* // => [1, 4] |
|
*/ |
|
function wrapperPlant(value) { |
|
var result, |
|
parent = this; |
|
|
|
while (parent instanceof baseLodash) { |
|
var clone = wrapperClone(parent); |
|
clone.__index__ = 0; |
|
clone.__values__ = undefined; |
|
if (result) { |
|
previous.__wrapped__ = clone; |
|
} else { |
|
result = clone; |
|
} |
|
var previous = clone; |
|
parent = parent.__wrapped__; |
|
} |
|
previous.__wrapped__ = value; |
|
return result; |
|
} |
|
|
|
/** |
|
* This method is the wrapper version of `_.reverse`. |
|
* |
|
* **Note:** This method mutates the wrapped array. |
|
* |
|
* @name reverse |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Seq |
|
* @returns {Object} Returns the new `lodash` wrapper instance. |
|
* @example |
|
* |
|
* var array = [1, 2, 3]; |
|
* |
|
* _(array).reverse().value() |
|
* // => [3, 2, 1] |
|
* |
|
* console.log(array); |
|
* // => [3, 2, 1] |
|
*/ |
|
function wrapperReverse() { |
|
var value = this.__wrapped__; |
|
if (value instanceof LazyWrapper) { |
|
var wrapped = value; |
|
if (this.__actions__.length) { |
|
wrapped = new LazyWrapper(this); |
|
} |
|
wrapped = wrapped.reverse(); |
|
wrapped.__actions__.push({ |
|
'func': thru, |
|
'args': [reverse], |
|
'thisArg': undefined |
|
}); |
|
return new LodashWrapper(wrapped, this.__chain__); |
|
} |
|
return this.thru(reverse); |
|
} |
|
|
|
/** |
|
* Executes the chain sequence to resolve the unwrapped value. |
|
* |
|
* @name value |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @alias toJSON, valueOf |
|
* @category Seq |
|
* @returns {*} Returns the resolved unwrapped value. |
|
* @example |
|
* |
|
* _([1, 2, 3]).value(); |
|
* // => [1, 2, 3] |
|
*/ |
|
function wrapperValue() { |
|
return baseWrapperValue(this.__wrapped__, this.__actions__); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates an object composed of keys generated from the results of running |
|
* each element of `collection` thru `iteratee`. The corresponding value of |
|
* each key is the number of times the key was returned by `iteratee`. The |
|
* iteratee is invoked with one argument: (value). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.5.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [iteratee=_.identity] The iteratee to transform keys. |
|
* @returns {Object} Returns the composed aggregate object. |
|
* @example |
|
* |
|
* _.countBy([6.1, 4.2, 6.3], Math.floor); |
|
* // => { '4': 1, '6': 2 } |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.countBy(['one', 'two', 'three'], 'length'); |
|
* // => { '3': 2, '5': 1 } |
|
*/ |
|
var countBy = createAggregator(function(result, value, key) { |
|
if (hasOwnProperty.call(result, key)) { |
|
++result[key]; |
|
} else { |
|
baseAssignValue(result, key, 1); |
|
} |
|
}); |
|
|
|
/** |
|
* Checks if `predicate` returns truthy for **all** elements of `collection`. |
|
* Iteration is stopped once `predicate` returns falsey. The predicate is |
|
* invoked with three arguments: (value, index|key, collection). |
|
* |
|
* **Note:** This method returns `true` for |
|
* [empty collections](https://en.wikipedia.org/wiki/Empty_set) because |
|
* [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of |
|
* elements of empty collections. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
|
* @returns {boolean} Returns `true` if all elements pass the predicate check, |
|
* else `false`. |
|
* @example |
|
* |
|
* _.every([true, 1, null, 'yes'], Boolean); |
|
* // => false |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36, 'active': false }, |
|
* { 'user': 'fred', 'age': 40, 'active': false } |
|
* ]; |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.every(users, { 'user': 'barney', 'active': false }); |
|
* // => false |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.every(users, ['active', false]); |
|
* // => true |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.every(users, 'active'); |
|
* // => false |
|
*/ |
|
function every(collection, predicate, guard) { |
|
var func = isArray(collection) ? arrayEvery : baseEvery; |
|
if (guard && isIterateeCall(collection, predicate, guard)) { |
|
predicate = undefined; |
|
} |
|
return func(collection, baseIteratee(predicate, 3)); |
|
} |
|
|
|
/** |
|
* Iterates over elements of `collection`, returning an array of all elements |
|
* `predicate` returns truthy for. The predicate is invoked with three |
|
* arguments: (value, index|key, collection). |
|
* |
|
* **Note:** Unlike `_.remove`, this method returns a new array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @returns {Array} Returns the new filtered array. |
|
* @see _.reject |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36, 'active': true }, |
|
* { 'user': 'fred', 'age': 40, 'active': false } |
|
* ]; |
|
* |
|
* _.filter(users, function(o) { return !o.active; }); |
|
* // => objects for ['fred'] |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.filter(users, { 'age': 36, 'active': true }); |
|
* // => objects for ['barney'] |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.filter(users, ['active', false]); |
|
* // => objects for ['fred'] |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.filter(users, 'active'); |
|
* // => objects for ['barney'] |
|
*/ |
|
function filter(collection, predicate) { |
|
var func = isArray(collection) ? arrayFilter : baseFilter; |
|
return func(collection, baseIteratee(predicate, 3)); |
|
} |
|
|
|
/** |
|
* Iterates over elements of `collection`, returning the first element |
|
* `predicate` returns truthy for. The predicate is invoked with three |
|
* arguments: (value, index|key, collection). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to inspect. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @param {number} [fromIndex=0] The index to search from. |
|
* @returns {*} Returns the matched element, else `undefined`. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36, 'active': true }, |
|
* { 'user': 'fred', 'age': 40, 'active': false }, |
|
* { 'user': 'pebbles', 'age': 1, 'active': true } |
|
* ]; |
|
* |
|
* _.find(users, function(o) { return o.age < 40; }); |
|
* // => object for 'barney' |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.find(users, { 'age': 1, 'active': true }); |
|
* // => object for 'pebbles' |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.find(users, ['active', false]); |
|
* // => object for 'fred' |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.find(users, 'active'); |
|
* // => object for 'barney' |
|
*/ |
|
var find = createFind(findIndex); |
|
|
|
/** |
|
* Iterates over elements of `collection` and invokes `iteratee` for each element. |
|
* The iteratee is invoked with three arguments: (value, index|key, collection). |
|
* Iteratee functions may exit iteration early by explicitly returning `false`. |
|
* |
|
* **Note:** As with other "Collections" methods, objects with a "length" |
|
* property are iterated like arrays. To avoid this behavior use `_.forIn` |
|
* or `_.forOwn` for object iteration. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @alias each |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration. |
|
* @returns {Array|Object} Returns `collection`. |
|
* @see _.forEachRight |
|
* @example |
|
* |
|
* _.forEach([1, 2], function(value) { |
|
* console.log(value); |
|
* }); |
|
* // => Logs `1` then `2`. |
|
* |
|
* _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { |
|
* console.log(key); |
|
* }); |
|
* // => Logs 'a' then 'b' (iteration order is not guaranteed). |
|
*/ |
|
function forEach(collection, iteratee) { |
|
var func = isArray(collection) ? arrayEach : baseEach; |
|
return func(collection, baseIteratee(iteratee, 3)); |
|
} |
|
|
|
/** |
|
* Creates an object composed of keys generated from the results of running |
|
* each element of `collection` thru `iteratee`. The order of grouped values |
|
* is determined by the order they occur in `collection`. The corresponding |
|
* value of each key is an array of elements responsible for generating the |
|
* key. The iteratee is invoked with one argument: (value). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [iteratee=_.identity] The iteratee to transform keys. |
|
* @returns {Object} Returns the composed aggregate object. |
|
* @example |
|
* |
|
* _.groupBy([6.1, 4.2, 6.3], Math.floor); |
|
* // => { '4': [4.2], '6': [6.1, 6.3] } |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.groupBy(['one', 'two', 'three'], 'length'); |
|
* // => { '3': ['one', 'two'], '5': ['three'] } |
|
*/ |
|
var groupBy = createAggregator(function(result, value, key) { |
|
if (hasOwnProperty.call(result, key)) { |
|
result[key].push(value); |
|
} else { |
|
baseAssignValue(result, key, [value]); |
|
} |
|
}); |
|
|
|
/** |
|
* Creates an array of values by running each element in `collection` thru |
|
* `iteratee`. The iteratee is invoked with three arguments: |
|
* (value, index|key, collection). |
|
* |
|
* Many lodash methods are guarded to work as iteratees for methods like |
|
* `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. |
|
* |
|
* The guarded methods are: |
|
* `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, |
|
* `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, |
|
* `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, |
|
* `template`, `trim`, `trimEnd`, `trimStart`, and `words` |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration. |
|
* @returns {Array} Returns the new mapped array. |
|
* @example |
|
* |
|
* function square(n) { |
|
* return n * n; |
|
* } |
|
* |
|
* _.map([4, 8], square); |
|
* // => [16, 64] |
|
* |
|
* _.map({ 'a': 4, 'b': 8 }, square); |
|
* // => [16, 64] (iteration order is not guaranteed) |
|
* |
|
* var users = [ |
|
* { 'user': 'barney' }, |
|
* { 'user': 'fred' } |
|
* ]; |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.map(users, 'user'); |
|
* // => ['barney', 'fred'] |
|
*/ |
|
function map(collection, iteratee) { |
|
var func = isArray(collection) ? arrayMap : baseMap; |
|
return func(collection, baseIteratee(iteratee, 3)); |
|
} |
|
|
|
/** |
|
* Reduces `collection` to a value which is the accumulated result of running |
|
* each element in `collection` thru `iteratee`, where each successive |
|
* invocation is supplied the return value of the previous. If `accumulator` |
|
* is not given, the first element of `collection` is used as the initial |
|
* value. The iteratee is invoked with four arguments: |
|
* (accumulator, value, index|key, collection). |
|
* |
|
* Many lodash methods are guarded to work as iteratees for methods like |
|
* `_.reduce`, `_.reduceRight`, and `_.transform`. |
|
* |
|
* The guarded methods are: |
|
* `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, |
|
* and `sortBy` |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration. |
|
* @param {*} [accumulator] The initial value. |
|
* @returns {*} Returns the accumulated value. |
|
* @see _.reduceRight |
|
* @example |
|
* |
|
* _.reduce([1, 2], function(sum, n) { |
|
* return sum + n; |
|
* }, 0); |
|
* // => 3 |
|
* |
|
* _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { |
|
* (result[value] || (result[value] = [])).push(key); |
|
* return result; |
|
* }, {}); |
|
* // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) |
|
*/ |
|
function reduce(collection, iteratee, accumulator) { |
|
var func = isArray(collection) ? arrayReduce : baseReduce, |
|
initAccum = arguments.length < 3; |
|
|
|
return func(collection, baseIteratee(iteratee, 4), accumulator, initAccum, baseEach); |
|
} |
|
|
|
/** |
|
* The opposite of `_.filter`; this method returns the elements of `collection` |
|
* that `predicate` does **not** return truthy for. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @returns {Array} Returns the new filtered array. |
|
* @see _.filter |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36, 'active': false }, |
|
* { 'user': 'fred', 'age': 40, 'active': true } |
|
* ]; |
|
* |
|
* _.reject(users, function(o) { return !o.active; }); |
|
* // => objects for ['fred'] |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.reject(users, { 'age': 40, 'active': true }); |
|
* // => objects for ['barney'] |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.reject(users, ['active', false]); |
|
* // => objects for ['fred'] |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.reject(users, 'active'); |
|
* // => objects for ['barney'] |
|
*/ |
|
function reject(collection, predicate) { |
|
var func = isArray(collection) ? arrayFilter : baseFilter; |
|
return func(collection, negate(baseIteratee(predicate, 3))); |
|
} |
|
|
|
/** |
|
* Gets the size of `collection` by returning its length for array-like |
|
* values or the number of own enumerable string keyed properties for objects. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object|string} collection The collection to inspect. |
|
* @returns {number} Returns the collection size. |
|
* @example |
|
* |
|
* _.size([1, 2, 3]); |
|
* // => 3 |
|
* |
|
* _.size({ 'a': 1, 'b': 2 }); |
|
* // => 2 |
|
* |
|
* _.size('pebbles'); |
|
* // => 7 |
|
*/ |
|
function size(collection) { |
|
if (collection == null) { |
|
return 0; |
|
} |
|
if (isArrayLike(collection)) { |
|
return isString(collection) ? stringSize(collection) : collection.length; |
|
} |
|
var tag = getTag(collection); |
|
if (tag == mapTag || tag == setTag) { |
|
return collection.size; |
|
} |
|
return baseKeys(collection).length; |
|
} |
|
|
|
/** |
|
* Checks if `predicate` returns truthy for **any** element of `collection`. |
|
* Iteration is stopped once `predicate` returns truthy. The predicate is |
|
* invoked with three arguments: (value, index|key, collection). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
|
* @returns {boolean} Returns `true` if any element passes the predicate check, |
|
* else `false`. |
|
* @example |
|
* |
|
* _.some([null, 0, 'yes', false], Boolean); |
|
* // => true |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'active': true }, |
|
* { 'user': 'fred', 'active': false } |
|
* ]; |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.some(users, { 'user': 'barney', 'active': false }); |
|
* // => false |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.some(users, ['active', false]); |
|
* // => true |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.some(users, 'active'); |
|
* // => true |
|
*/ |
|
function some(collection, predicate, guard) { |
|
var func = isArray(collection) ? arraySome : baseSome; |
|
if (guard && isIterateeCall(collection, predicate, guard)) { |
|
predicate = undefined; |
|
} |
|
return func(collection, baseIteratee(predicate, 3)); |
|
} |
|
|
|
/** |
|
* Creates an array of elements, sorted in ascending order by the results of |
|
* running each element in a collection thru each iteratee. This method |
|
* performs a stable sort, that is, it preserves the original sort order of |
|
* equal elements. The iteratees are invoked with one argument: (value). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Collection |
|
* @param {Array|Object} collection The collection to iterate over. |
|
* @param {...(Function|Function[])} [iteratees=[_.identity]] |
|
* The iteratees to sort by. |
|
* @returns {Array} Returns the new sorted array. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'fred', 'age': 48 }, |
|
* { 'user': 'barney', 'age': 36 }, |
|
* { 'user': 'fred', 'age': 40 }, |
|
* { 'user': 'barney', 'age': 34 } |
|
* ]; |
|
* |
|
* _.sortBy(users, [function(o) { return o.user; }]); |
|
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] |
|
* |
|
* _.sortBy(users, ['user', 'age']); |
|
* // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] |
|
*/ |
|
var sortBy = baseRest(function(collection, iteratees) { |
|
if (collection == null) { |
|
return []; |
|
} |
|
var length = iteratees.length; |
|
if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { |
|
iteratees = []; |
|
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { |
|
iteratees = [iteratees[0]]; |
|
} |
|
return baseOrderBy(collection, baseFlatten(iteratees, 1), []); |
|
}); |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Gets the timestamp of the number of milliseconds that have elapsed since |
|
* the Unix epoch (1 January 1970 00:00:00 UTC). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.4.0 |
|
* @category Date |
|
* @returns {number} Returns the timestamp. |
|
* @example |
|
* |
|
* _.defer(function(stamp) { |
|
* console.log(_.now() - stamp); |
|
* }, _.now()); |
|
* // => Logs the number of milliseconds it took for the deferred invocation. |
|
*/ |
|
var now = function() { |
|
return root.Date.now(); |
|
}; |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a function that invokes `func`, with the `this` binding and arguments |
|
* of the created function, while it's called less than `n` times. Subsequent |
|
* calls to the created function return the result of the last `func` invocation. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Function |
|
* @param {number} n The number of calls at which `func` is no longer invoked. |
|
* @param {Function} func The function to restrict. |
|
* @returns {Function} Returns the new restricted function. |
|
* @example |
|
* |
|
* jQuery(element).on('click', _.before(5, addContactToList)); |
|
* // => Allows adding up to 4 contacts to the list. |
|
*/ |
|
function before(n, func) { |
|
var result; |
|
if (typeof func != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
n = toInteger(n); |
|
return function() { |
|
if (--n > 0) { |
|
result = func.apply(this, arguments); |
|
} |
|
if (n <= 1) { |
|
func = undefined; |
|
} |
|
return result; |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that invokes `func` with the `this` binding of `thisArg` |
|
* and `partials` prepended to the arguments it receives. |
|
* |
|
* The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, |
|
* may be used as a placeholder for partially applied arguments. |
|
* |
|
* **Note:** Unlike native `Function#bind`, this method doesn't set the "length" |
|
* property of bound functions. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to bind. |
|
* @param {*} thisArg The `this` binding of `func`. |
|
* @param {...*} [partials] The arguments to be partially applied. |
|
* @returns {Function} Returns the new bound function. |
|
* @example |
|
* |
|
* function greet(greeting, punctuation) { |
|
* return greeting + ' ' + this.user + punctuation; |
|
* } |
|
* |
|
* var object = { 'user': 'fred' }; |
|
* |
|
* var bound = _.bind(greet, object, 'hi'); |
|
* bound('!'); |
|
* // => 'hi fred!' |
|
* |
|
* // Bound with placeholders. |
|
* var bound = _.bind(greet, object, _, '!'); |
|
* bound('hi'); |
|
* // => 'hi fred!' |
|
*/ |
|
var bind = baseRest(function(func, thisArg, partials) { |
|
var bitmask = WRAP_BIND_FLAG; |
|
if (partials.length) { |
|
var holders = replaceHolders(partials, getHolder(bind)); |
|
bitmask |= WRAP_PARTIAL_FLAG; |
|
} |
|
return createWrap(func, bitmask, thisArg, partials, holders); |
|
}); |
|
|
|
/** |
|
* Creates a debounced function that delays invoking `func` until after `wait` |
|
* milliseconds have elapsed since the last time the debounced function was |
|
* invoked. The debounced function comes with a `cancel` method to cancel |
|
* delayed `func` invocations and a `flush` method to immediately invoke them. |
|
* Provide `options` to indicate whether `func` should be invoked on the |
|
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked |
|
* with the last arguments provided to the debounced function. Subsequent |
|
* calls to the debounced function return the result of the last `func` |
|
* invocation. |
|
* |
|
* **Note:** If `leading` and `trailing` options are `true`, `func` is |
|
* invoked on the trailing edge of the timeout only if the debounced function |
|
* is invoked more than once during the `wait` timeout. |
|
* |
|
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred |
|
* until to the next tick, similar to `setTimeout` with a timeout of `0`. |
|
* |
|
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) |
|
* for details over the differences between `_.debounce` and `_.throttle`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to debounce. |
|
* @param {number} [wait=0] The number of milliseconds to delay. |
|
* @param {Object} [options={}] The options object. |
|
* @param {boolean} [options.leading=false] |
|
* Specify invoking on the leading edge of the timeout. |
|
* @param {number} [options.maxWait] |
|
* The maximum time `func` is allowed to be delayed before it's invoked. |
|
* @param {boolean} [options.trailing=true] |
|
* Specify invoking on the trailing edge of the timeout. |
|
* @returns {Function} Returns the new debounced function. |
|
* @example |
|
* |
|
* // Avoid costly calculations while the window size is in flux. |
|
* jQuery(window).on('resize', _.debounce(calculateLayout, 150)); |
|
* |
|
* // Invoke `sendMail` when clicked, debouncing subsequent calls. |
|
* jQuery(element).on('click', _.debounce(sendMail, 300, { |
|
* 'leading': true, |
|
* 'trailing': false |
|
* })); |
|
* |
|
* // Ensure `batchLog` is invoked once after 1 second of debounced calls. |
|
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); |
|
* var source = new EventSource('/stream'); |
|
* jQuery(source).on('message', debounced); |
|
* |
|
* // Cancel the trailing debounced invocation. |
|
* jQuery(window).on('popstate', debounced.cancel); |
|
*/ |
|
function debounce(func, wait, options) { |
|
var lastArgs, |
|
lastThis, |
|
maxWait, |
|
result, |
|
timerId, |
|
lastCallTime, |
|
lastInvokeTime = 0, |
|
leading = false, |
|
maxing = false, |
|
trailing = true; |
|
|
|
if (typeof func != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
wait = toNumber(wait) || 0; |
|
if (isObject(options)) { |
|
leading = !!options.leading; |
|
maxing = 'maxWait' in options; |
|
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; |
|
trailing = 'trailing' in options ? !!options.trailing : trailing; |
|
} |
|
|
|
function invokeFunc(time) { |
|
var args = lastArgs, |
|
thisArg = lastThis; |
|
|
|
lastArgs = lastThis = undefined; |
|
lastInvokeTime = time; |
|
result = func.apply(thisArg, args); |
|
return result; |
|
} |
|
|
|
function leadingEdge(time) { |
|
// Reset any `maxWait` timer. |
|
lastInvokeTime = time; |
|
// Start the timer for the trailing edge. |
|
timerId = setTimeout(timerExpired, wait); |
|
// Invoke the leading edge. |
|
return leading ? invokeFunc(time) : result; |
|
} |
|
|
|
function remainingWait(time) { |
|
var timeSinceLastCall = time - lastCallTime, |
|
timeSinceLastInvoke = time - lastInvokeTime, |
|
timeWaiting = wait - timeSinceLastCall; |
|
|
|
return maxing |
|
? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) |
|
: timeWaiting; |
|
} |
|
|
|
function shouldInvoke(time) { |
|
var timeSinceLastCall = time - lastCallTime, |
|
timeSinceLastInvoke = time - lastInvokeTime; |
|
|
|
// Either this is the first call, activity has stopped and we're at the |
|
// trailing edge, the system time has gone backwards and we're treating |
|
// it as the trailing edge, or we've hit the `maxWait` limit. |
|
return (lastCallTime === undefined || (timeSinceLastCall >= wait) || |
|
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); |
|
} |
|
|
|
function timerExpired() { |
|
var time = now(); |
|
if (shouldInvoke(time)) { |
|
return trailingEdge(time); |
|
} |
|
// Restart the timer. |
|
timerId = setTimeout(timerExpired, remainingWait(time)); |
|
} |
|
|
|
function trailingEdge(time) { |
|
timerId = undefined; |
|
|
|
// Only invoke if we have `lastArgs` which means `func` has been |
|
// debounced at least once. |
|
if (trailing && lastArgs) { |
|
return invokeFunc(time); |
|
} |
|
lastArgs = lastThis = undefined; |
|
return result; |
|
} |
|
|
|
function cancel() { |
|
if (timerId !== undefined) { |
|
clearTimeout(timerId); |
|
} |
|
lastInvokeTime = 0; |
|
lastArgs = lastCallTime = lastThis = timerId = undefined; |
|
} |
|
|
|
function flush() { |
|
return timerId === undefined ? result : trailingEdge(now()); |
|
} |
|
|
|
function debounced() { |
|
var time = now(), |
|
isInvoking = shouldInvoke(time); |
|
|
|
lastArgs = arguments; |
|
lastThis = this; |
|
lastCallTime = time; |
|
|
|
if (isInvoking) { |
|
if (timerId === undefined) { |
|
return leadingEdge(lastCallTime); |
|
} |
|
if (maxing) { |
|
// Handle invocations in a tight loop. |
|
timerId = setTimeout(timerExpired, wait); |
|
return invokeFunc(lastCallTime); |
|
} |
|
} |
|
if (timerId === undefined) { |
|
timerId = setTimeout(timerExpired, wait); |
|
} |
|
return result; |
|
} |
|
debounced.cancel = cancel; |
|
debounced.flush = flush; |
|
return debounced; |
|
} |
|
|
|
/** |
|
* Defers invoking the `func` until the current call stack has cleared. Any |
|
* additional arguments are provided to `func` when it's invoked. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to defer. |
|
* @param {...*} [args] The arguments to invoke `func` with. |
|
* @returns {number} Returns the timer id. |
|
* @example |
|
* |
|
* _.defer(function(text) { |
|
* console.log(text); |
|
* }, 'deferred'); |
|
* // => Logs 'deferred' after one millisecond. |
|
*/ |
|
var defer = baseRest(function(func, args) { |
|
return baseDelay(func, 1, args); |
|
}); |
|
|
|
/** |
|
* Invokes `func` after `wait` milliseconds. Any additional arguments are |
|
* provided to `func` when it's invoked. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to delay. |
|
* @param {number} wait The number of milliseconds to delay invocation. |
|
* @param {...*} [args] The arguments to invoke `func` with. |
|
* @returns {number} Returns the timer id. |
|
* @example |
|
* |
|
* _.delay(function(text) { |
|
* console.log(text); |
|
* }, 1000, 'later'); |
|
* // => Logs 'later' after one second. |
|
*/ |
|
var delay = baseRest(function(func, wait, args) { |
|
return baseDelay(func, toNumber(wait) || 0, args); |
|
}); |
|
|
|
/** |
|
* Creates a function that memoizes the result of `func`. If `resolver` is |
|
* provided, it determines the cache key for storing the result based on the |
|
* arguments provided to the memoized function. By default, the first argument |
|
* provided to the memoized function is used as the map cache key. The `func` |
|
* is invoked with the `this` binding of the memoized function. |
|
* |
|
* **Note:** The cache is exposed as the `cache` property on the memoized |
|
* function. Its creation may be customized by replacing the `_.memoize.Cache` |
|
* constructor with one whose instances implement the |
|
* [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) |
|
* method interface of `clear`, `delete`, `get`, `has`, and `set`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to have its output memoized. |
|
* @param {Function} [resolver] The function to resolve the cache key. |
|
* @returns {Function} Returns the new memoized function. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': 2 }; |
|
* var other = { 'c': 3, 'd': 4 }; |
|
* |
|
* var values = _.memoize(_.values); |
|
* values(object); |
|
* // => [1, 2] |
|
* |
|
* values(other); |
|
* // => [3, 4] |
|
* |
|
* object.a = 2; |
|
* values(object); |
|
* // => [1, 2] |
|
* |
|
* // Modify the result cache. |
|
* values.cache.set(object, ['a', 'b']); |
|
* values(object); |
|
* // => ['a', 'b'] |
|
* |
|
* // Replace `_.memoize.Cache`. |
|
* _.memoize.Cache = WeakMap; |
|
*/ |
|
function memoize(func, resolver) { |
|
if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
var memoized = function() { |
|
var args = arguments, |
|
key = resolver ? resolver.apply(this, args) : args[0], |
|
cache = memoized.cache; |
|
|
|
if (cache.has(key)) { |
|
return cache.get(key); |
|
} |
|
var result = func.apply(this, args); |
|
memoized.cache = cache.set(key, result) || cache; |
|
return result; |
|
}; |
|
memoized.cache = new (memoize.Cache || MapCache); |
|
return memoized; |
|
} |
|
|
|
// Expose `MapCache`. |
|
memoize.Cache = MapCache; |
|
|
|
/** |
|
* Creates a function that negates the result of the predicate `func`. The |
|
* `func` predicate is invoked with the `this` binding and arguments of the |
|
* created function. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Function |
|
* @param {Function} predicate The predicate to negate. |
|
* @returns {Function} Returns the new negated function. |
|
* @example |
|
* |
|
* function isEven(n) { |
|
* return n % 2 == 0; |
|
* } |
|
* |
|
* _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); |
|
* // => [1, 3, 5] |
|
*/ |
|
function negate(predicate) { |
|
if (typeof predicate != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
return function() { |
|
var args = arguments; |
|
switch (args.length) { |
|
case 0: return !predicate.call(this); |
|
case 1: return !predicate.call(this, args[0]); |
|
case 2: return !predicate.call(this, args[0], args[1]); |
|
case 3: return !predicate.call(this, args[0], args[1], args[2]); |
|
} |
|
return !predicate.apply(this, args); |
|
}; |
|
} |
|
|
|
/** |
|
* Creates a function that is restricted to invoking `func` once. Repeat calls |
|
* to the function return the value of the first invocation. The `func` is |
|
* invoked with the `this` binding and arguments of the created function. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to restrict. |
|
* @returns {Function} Returns the new restricted function. |
|
* @example |
|
* |
|
* var initialize = _.once(createApplication); |
|
* initialize(); |
|
* initialize(); |
|
* // => `createApplication` is invoked once |
|
*/ |
|
function once(func) { |
|
return before(2, func); |
|
} |
|
|
|
/** |
|
* Creates a function that invokes `func` with the `this` binding of the |
|
* created function and arguments from `start` and beyond provided as |
|
* an array. |
|
* |
|
* **Note:** This method is based on the |
|
* [rest parameter](https://mdn.io/rest_parameters). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Function |
|
* @param {Function} func The function to apply a rest parameter to. |
|
* @param {number} [start=func.length-1] The start position of the rest parameter. |
|
* @returns {Function} Returns the new function. |
|
* @example |
|
* |
|
* var say = _.rest(function(what, names) { |
|
* return what + ' ' + _.initial(names).join(', ') + |
|
* (_.size(names) > 1 ? ', & ' : '') + _.last(names); |
|
* }); |
|
* |
|
* say('hello', 'fred', 'barney', 'pebbles'); |
|
* // => 'hello fred, barney, & pebbles' |
|
*/ |
|
function rest(func, start) { |
|
if (typeof func != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
start = start === undefined ? start : toInteger(start); |
|
return baseRest(func, start); |
|
} |
|
|
|
/** |
|
* Creates a throttled function that only invokes `func` at most once per |
|
* every `wait` milliseconds. The throttled function comes with a `cancel` |
|
* method to cancel delayed `func` invocations and a `flush` method to |
|
* immediately invoke them. Provide `options` to indicate whether `func` |
|
* should be invoked on the leading and/or trailing edge of the `wait` |
|
* timeout. The `func` is invoked with the last arguments provided to the |
|
* throttled function. Subsequent calls to the throttled function return the |
|
* result of the last `func` invocation. |
|
* |
|
* **Note:** If `leading` and `trailing` options are `true`, `func` is |
|
* invoked on the trailing edge of the timeout only if the throttled function |
|
* is invoked more than once during the `wait` timeout. |
|
* |
|
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred |
|
* until to the next tick, similar to `setTimeout` with a timeout of `0`. |
|
* |
|
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) |
|
* for details over the differences between `_.throttle` and `_.debounce`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Function |
|
* @param {Function} func The function to throttle. |
|
* @param {number} [wait=0] The number of milliseconds to throttle invocations to. |
|
* @param {Object} [options={}] The options object. |
|
* @param {boolean} [options.leading=true] |
|
* Specify invoking on the leading edge of the timeout. |
|
* @param {boolean} [options.trailing=true] |
|
* Specify invoking on the trailing edge of the timeout. |
|
* @returns {Function} Returns the new throttled function. |
|
* @example |
|
* |
|
* // Avoid excessively updating the position while scrolling. |
|
* jQuery(window).on('scroll', _.throttle(updatePosition, 100)); |
|
* |
|
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. |
|
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); |
|
* jQuery(element).on('click', throttled); |
|
* |
|
* // Cancel the trailing throttled invocation. |
|
* jQuery(window).on('popstate', throttled.cancel); |
|
*/ |
|
function throttle(func, wait, options) { |
|
var leading = true, |
|
trailing = true; |
|
|
|
if (typeof func != 'function') { |
|
throw new TypeError(FUNC_ERROR_TEXT); |
|
} |
|
if (isObject(options)) { |
|
leading = 'leading' in options ? !!options.leading : leading; |
|
trailing = 'trailing' in options ? !!options.trailing : trailing; |
|
} |
|
return debounce(func, wait, { |
|
'leading': leading, |
|
'maxWait': wait, |
|
'trailing': trailing |
|
}); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a shallow clone of `value`. |
|
* |
|
* **Note:** This method is loosely based on the |
|
* [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) |
|
* and supports cloning arrays, array buffers, booleans, date objects, maps, |
|
* numbers, `Object` objects, regexes, sets, strings, symbols, and typed |
|
* arrays. The own enumerable properties of `arguments` objects are cloned |
|
* as plain objects. An empty object is returned for uncloneable values such |
|
* as error objects, functions, DOM nodes, and WeakMaps. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to clone. |
|
* @returns {*} Returns the cloned value. |
|
* @see _.cloneDeep |
|
* @example |
|
* |
|
* var objects = [{ 'a': 1 }, { 'b': 2 }]; |
|
* |
|
* var shallow = _.clone(objects); |
|
* console.log(shallow[0] === objects[0]); |
|
* // => true |
|
*/ |
|
function clone(value) { |
|
return baseClone(value, CLONE_SYMBOLS_FLAG); |
|
} |
|
|
|
/** |
|
* This method is like `_.clone` except that it recursively clones `value`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 1.0.0 |
|
* @category Lang |
|
* @param {*} value The value to recursively clone. |
|
* @returns {*} Returns the deep cloned value. |
|
* @see _.clone |
|
* @example |
|
* |
|
* var objects = [{ 'a': 1 }, { 'b': 2 }]; |
|
* |
|
* var deep = _.cloneDeep(objects); |
|
* console.log(deep[0] === objects[0]); |
|
* // => false |
|
*/ |
|
function cloneDeep(value) { |
|
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); |
|
} |
|
|
|
/** |
|
* Performs a |
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
|
* comparison between two values to determine if they are equivalent. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to compare. |
|
* @param {*} other The other value to compare. |
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`. |
|
* @example |
|
* |
|
* var object = { 'a': 1 }; |
|
* var other = { 'a': 1 }; |
|
* |
|
* _.eq(object, object); |
|
* // => true |
|
* |
|
* _.eq(object, other); |
|
* // => false |
|
* |
|
* _.eq('a', 'a'); |
|
* // => true |
|
* |
|
* _.eq('a', Object('a')); |
|
* // => false |
|
* |
|
* _.eq(NaN, NaN); |
|
* // => true |
|
*/ |
|
function eq(value, other) { |
|
return value === other || (value !== value && other !== other); |
|
} |
|
|
|
/** |
|
* Checks if `value` is likely an `arguments` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is an `arguments` object, |
|
* else `false`. |
|
* @example |
|
* |
|
* _.isArguments(function() { return arguments; }()); |
|
* // => true |
|
* |
|
* _.isArguments([1, 2, 3]); |
|
* // => false |
|
*/ |
|
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { |
|
return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && |
|
!propertyIsEnumerable.call(value, 'callee'); |
|
}; |
|
|
|
/** |
|
* Checks if `value` is classified as an `Array` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is an array, else `false`. |
|
* @example |
|
* |
|
* _.isArray([1, 2, 3]); |
|
* // => true |
|
* |
|
* _.isArray(document.body.children); |
|
* // => false |
|
* |
|
* _.isArray('abc'); |
|
* // => false |
|
* |
|
* _.isArray(_.noop); |
|
* // => false |
|
*/ |
|
var isArray = Array.isArray; |
|
|
|
/** |
|
* Checks if `value` is array-like. A value is considered array-like if it's |
|
* not a function and has a `value.length` that's an integer greater than or |
|
* equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is array-like, else `false`. |
|
* @example |
|
* |
|
* _.isArrayLike([1, 2, 3]); |
|
* // => true |
|
* |
|
* _.isArrayLike(document.body.children); |
|
* // => true |
|
* |
|
* _.isArrayLike('abc'); |
|
* // => true |
|
* |
|
* _.isArrayLike(_.noop); |
|
* // => false |
|
*/ |
|
function isArrayLike(value) { |
|
return value != null && isLength(value.length) && !isFunction(value); |
|
} |
|
|
|
/** |
|
* This method is like `_.isArrayLike` except that it also checks if `value` |
|
* is an object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is an array-like object, |
|
* else `false`. |
|
* @example |
|
* |
|
* _.isArrayLikeObject([1, 2, 3]); |
|
* // => true |
|
* |
|
* _.isArrayLikeObject(document.body.children); |
|
* // => true |
|
* |
|
* _.isArrayLikeObject('abc'); |
|
* // => false |
|
* |
|
* _.isArrayLikeObject(_.noop); |
|
* // => false |
|
*/ |
|
function isArrayLikeObject(value) { |
|
return isObjectLike(value) && isArrayLike(value); |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a boolean primitive or object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a boolean, else `false`. |
|
* @example |
|
* |
|
* _.isBoolean(false); |
|
* // => true |
|
* |
|
* _.isBoolean(null); |
|
* // => false |
|
*/ |
|
function isBoolean(value) { |
|
return value === true || value === false || |
|
(isObjectLike(value) && baseGetTag(value) == boolTag); |
|
} |
|
|
|
/** |
|
* Checks if `value` is a buffer. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.3.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a buffer, else `false`. |
|
* @example |
|
* |
|
* _.isBuffer(new Buffer(2)); |
|
* // => true |
|
* |
|
* _.isBuffer(new Uint8Array(2)); |
|
* // => false |
|
*/ |
|
var isBuffer = nativeIsBuffer || stubFalse; |
|
|
|
/** |
|
* Checks if `value` is classified as a `Date` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a date object, else `false`. |
|
* @example |
|
* |
|
* _.isDate(new Date); |
|
* // => true |
|
* |
|
* _.isDate('Mon April 23 2012'); |
|
* // => false |
|
*/ |
|
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; |
|
|
|
/** |
|
* Checks if `value` is an empty object, collection, map, or set. |
|
* |
|
* Objects are considered empty if they have no own enumerable string keyed |
|
* properties. |
|
* |
|
* Array-like values such as `arguments` objects, arrays, buffers, strings, or |
|
* jQuery-like collections are considered empty if they have a `length` of `0`. |
|
* Similarly, maps and sets are considered empty if they have a `size` of `0`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is empty, else `false`. |
|
* @example |
|
* |
|
* _.isEmpty(null); |
|
* // => true |
|
* |
|
* _.isEmpty(true); |
|
* // => true |
|
* |
|
* _.isEmpty(1); |
|
* // => true |
|
* |
|
* _.isEmpty([1, 2, 3]); |
|
* // => false |
|
* |
|
* _.isEmpty({ 'a': 1 }); |
|
* // => false |
|
*/ |
|
function isEmpty(value) { |
|
if (value == null) { |
|
return true; |
|
} |
|
if (isArrayLike(value) && |
|
(isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || |
|
isBuffer(value) || isTypedArray(value) || isArguments(value))) { |
|
return !value.length; |
|
} |
|
var tag = getTag(value); |
|
if (tag == mapTag || tag == setTag) { |
|
return !value.size; |
|
} |
|
if (isPrototype(value)) { |
|
return !baseKeys(value).length; |
|
} |
|
for (var key in value) { |
|
if (hasOwnProperty.call(value, key)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
/** |
|
* Performs a deep comparison between two values to determine if they are |
|
* equivalent. |
|
* |
|
* **Note:** This method supports comparing arrays, array buffers, booleans, |
|
* date objects, error objects, maps, numbers, `Object` objects, regexes, |
|
* sets, strings, symbols, and typed arrays. `Object` objects are compared |
|
* by their own, not inherited, enumerable properties. Functions and DOM |
|
* nodes are compared by strict equality, i.e. `===`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to compare. |
|
* @param {*} other The other value to compare. |
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`. |
|
* @example |
|
* |
|
* var object = { 'a': 1 }; |
|
* var other = { 'a': 1 }; |
|
* |
|
* _.isEqual(object, other); |
|
* // => true |
|
* |
|
* object === other; |
|
* // => false |
|
*/ |
|
function isEqual(value, other) { |
|
return baseIsEqual(value, other); |
|
} |
|
|
|
/** |
|
* Checks if `value` is a finite primitive number. |
|
* |
|
* **Note:** This method is based on |
|
* [`Number.isFinite`](https://mdn.io/Number/isFinite). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a finite number, else `false`. |
|
* @example |
|
* |
|
* _.isFinite(3); |
|
* // => true |
|
* |
|
* _.isFinite(Number.MIN_VALUE); |
|
* // => true |
|
* |
|
* _.isFinite(Infinity); |
|
* // => false |
|
* |
|
* _.isFinite('3'); |
|
* // => false |
|
*/ |
|
function isFinite(value) { |
|
return typeof value == 'number' && nativeIsFinite(value); |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a `Function` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a function, else `false`. |
|
* @example |
|
* |
|
* _.isFunction(_); |
|
* // => true |
|
* |
|
* _.isFunction(/abc/); |
|
* // => false |
|
*/ |
|
function isFunction(value) { |
|
if (!isObject(value)) { |
|
return false; |
|
} |
|
// The use of `Object#toString` avoids issues with the `typeof` operator |
|
// in Safari 9 which returns 'object' for typed arrays and other constructors. |
|
var tag = baseGetTag(value); |
|
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; |
|
} |
|
|
|
/** |
|
* Checks if `value` is a valid array-like length. |
|
* |
|
* **Note:** This method is loosely based on |
|
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`. |
|
* @example |
|
* |
|
* _.isLength(3); |
|
* // => true |
|
* |
|
* _.isLength(Number.MIN_VALUE); |
|
* // => false |
|
* |
|
* _.isLength(Infinity); |
|
* // => false |
|
* |
|
* _.isLength('3'); |
|
* // => false |
|
*/ |
|
function isLength(value) { |
|
return typeof value == 'number' && |
|
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; |
|
} |
|
|
|
/** |
|
* Checks if `value` is the |
|
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) |
|
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is an object, else `false`. |
|
* @example |
|
* |
|
* _.isObject({}); |
|
* // => true |
|
* |
|
* _.isObject([1, 2, 3]); |
|
* // => true |
|
* |
|
* _.isObject(_.noop); |
|
* // => true |
|
* |
|
* _.isObject(null); |
|
* // => false |
|
*/ |
|
function isObject(value) { |
|
var type = typeof value; |
|
return value != null && (type == 'object' || type == 'function'); |
|
} |
|
|
|
/** |
|
* Checks if `value` is object-like. A value is object-like if it's not `null` |
|
* and has a `typeof` result of "object". |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is object-like, else `false`. |
|
* @example |
|
* |
|
* _.isObjectLike({}); |
|
* // => true |
|
* |
|
* _.isObjectLike([1, 2, 3]); |
|
* // => true |
|
* |
|
* _.isObjectLike(_.noop); |
|
* // => false |
|
* |
|
* _.isObjectLike(null); |
|
* // => false |
|
*/ |
|
function isObjectLike(value) { |
|
return value != null && typeof value == 'object'; |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a `Map` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.3.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a map, else `false`. |
|
* @example |
|
* |
|
* _.isMap(new Map); |
|
* // => true |
|
* |
|
* _.isMap(new WeakMap); |
|
* // => false |
|
*/ |
|
var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; |
|
|
|
/** |
|
* Checks if `value` is `NaN`. |
|
* |
|
* **Note:** This method is based on |
|
* [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as |
|
* global [`isNaN`](https://mdn.io/isNaN) which returns `true` for |
|
* `undefined` and other non-number values. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. |
|
* @example |
|
* |
|
* _.isNaN(NaN); |
|
* // => true |
|
* |
|
* _.isNaN(new Number(NaN)); |
|
* // => true |
|
* |
|
* isNaN(undefined); |
|
* // => true |
|
* |
|
* _.isNaN(undefined); |
|
* // => false |
|
*/ |
|
function isNaN(value) { |
|
// An `NaN` primitive is the only value that is not equal to itself. |
|
// Perform the `toStringTag` check first to avoid errors with some |
|
// ActiveX objects in IE. |
|
return isNumber(value) && value != +value; |
|
} |
|
|
|
/** |
|
* Checks if `value` is `null`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is `null`, else `false`. |
|
* @example |
|
* |
|
* _.isNull(null); |
|
* // => true |
|
* |
|
* _.isNull(void 0); |
|
* // => false |
|
*/ |
|
function isNull(value) { |
|
return value === null; |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a `Number` primitive or object. |
|
* |
|
* **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are |
|
* classified as numbers, use the `_.isFinite` method. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a number, else `false`. |
|
* @example |
|
* |
|
* _.isNumber(3); |
|
* // => true |
|
* |
|
* _.isNumber(Number.MIN_VALUE); |
|
* // => true |
|
* |
|
* _.isNumber(Infinity); |
|
* // => true |
|
* |
|
* _.isNumber('3'); |
|
* // => false |
|
*/ |
|
function isNumber(value) { |
|
return typeof value == 'number' || |
|
(isObjectLike(value) && baseGetTag(value) == numberTag); |
|
} |
|
|
|
/** |
|
* Checks if `value` is a plain object, that is, an object created by the |
|
* `Object` constructor or one with a `[[Prototype]]` of `null`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.8.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`. |
|
* @example |
|
* |
|
* function Foo() { |
|
* this.a = 1; |
|
* } |
|
* |
|
* _.isPlainObject(new Foo); |
|
* // => false |
|
* |
|
* _.isPlainObject([1, 2, 3]); |
|
* // => false |
|
* |
|
* _.isPlainObject({ 'x': 0, 'y': 0 }); |
|
* // => true |
|
* |
|
* _.isPlainObject(Object.create(null)); |
|
* // => true |
|
*/ |
|
function isPlainObject(value) { |
|
if (!isObjectLike(value) || baseGetTag(value) != objectTag) { |
|
return false; |
|
} |
|
var proto = getPrototype(value); |
|
if (proto === null) { |
|
return true; |
|
} |
|
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; |
|
return typeof Ctor == 'function' && Ctor instanceof Ctor && |
|
funcToString.call(Ctor) == objectCtorString; |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a `RegExp` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.1.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`. |
|
* @example |
|
* |
|
* _.isRegExp(/abc/); |
|
* // => true |
|
* |
|
* _.isRegExp('/abc/'); |
|
* // => false |
|
*/ |
|
var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; |
|
|
|
/** |
|
* Checks if `value` is classified as a `Set` object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.3.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a set, else `false`. |
|
* @example |
|
* |
|
* _.isSet(new Set); |
|
* // => true |
|
* |
|
* _.isSet(new WeakSet); |
|
* // => false |
|
*/ |
|
var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; |
|
|
|
/** |
|
* Checks if `value` is classified as a `String` primitive or object. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a string, else `false`. |
|
* @example |
|
* |
|
* _.isString('abc'); |
|
* // => true |
|
* |
|
* _.isString(1); |
|
* // => false |
|
*/ |
|
function isString(value) { |
|
return typeof value == 'string' || |
|
(!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a `Symbol` primitive or object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`. |
|
* @example |
|
* |
|
* _.isSymbol(Symbol.iterator); |
|
* // => true |
|
* |
|
* _.isSymbol('abc'); |
|
* // => false |
|
*/ |
|
function isSymbol(value) { |
|
return typeof value == 'symbol' || |
|
(isObjectLike(value) && baseGetTag(value) == symbolTag); |
|
} |
|
|
|
/** |
|
* Checks if `value` is classified as a typed array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`. |
|
* @example |
|
* |
|
* _.isTypedArray(new Uint8Array); |
|
* // => true |
|
* |
|
* _.isTypedArray([]); |
|
* // => false |
|
*/ |
|
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; |
|
|
|
/** |
|
* Checks if `value` is `undefined`. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Lang |
|
* @param {*} value The value to check. |
|
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. |
|
* @example |
|
* |
|
* _.isUndefined(void 0); |
|
* // => true |
|
* |
|
* _.isUndefined(null); |
|
* // => false |
|
*/ |
|
function isUndefined(value) { |
|
return value === undefined; |
|
} |
|
|
|
/** |
|
* Converts `value` to an array. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Lang |
|
* @param {*} value The value to convert. |
|
* @returns {Array} Returns the converted array. |
|
* @example |
|
* |
|
* _.toArray({ 'a': 1, 'b': 2 }); |
|
* // => [1, 2] |
|
* |
|
* _.toArray('abc'); |
|
* // => ['a', 'b', 'c'] |
|
* |
|
* _.toArray(1); |
|
* // => [] |
|
* |
|
* _.toArray(null); |
|
* // => [] |
|
*/ |
|
function toArray(value) { |
|
if (!value) { |
|
return []; |
|
} |
|
if (isArrayLike(value)) { |
|
return isString(value) ? stringToArray(value) : copyArray(value); |
|
} |
|
if (symIterator && value[symIterator]) { |
|
return iteratorToArray(value[symIterator]()); |
|
} |
|
var tag = getTag(value), |
|
func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); |
|
|
|
return func(value); |
|
} |
|
|
|
/** |
|
* Converts `value` to a finite number. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.12.0 |
|
* @category Lang |
|
* @param {*} value The value to convert. |
|
* @returns {number} Returns the converted number. |
|
* @example |
|
* |
|
* _.toFinite(3.2); |
|
* // => 3.2 |
|
* |
|
* _.toFinite(Number.MIN_VALUE); |
|
* // => 5e-324 |
|
* |
|
* _.toFinite(Infinity); |
|
* // => 1.7976931348623157e+308 |
|
* |
|
* _.toFinite('3.2'); |
|
* // => 3.2 |
|
*/ |
|
function toFinite(value) { |
|
if (!value) { |
|
return value === 0 ? value : 0; |
|
} |
|
value = toNumber(value); |
|
if (value === INFINITY || value === -INFINITY) { |
|
var sign = (value < 0 ? -1 : 1); |
|
return sign * MAX_INTEGER; |
|
} |
|
return value === value ? value : 0; |
|
} |
|
|
|
/** |
|
* Converts `value` to an integer. |
|
* |
|
* **Note:** This method is loosely based on |
|
* [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to convert. |
|
* @returns {number} Returns the converted integer. |
|
* @example |
|
* |
|
* _.toInteger(3.2); |
|
* // => 3 |
|
* |
|
* _.toInteger(Number.MIN_VALUE); |
|
* // => 0 |
|
* |
|
* _.toInteger(Infinity); |
|
* // => 1.7976931348623157e+308 |
|
* |
|
* _.toInteger('3.2'); |
|
* // => 3 |
|
*/ |
|
function toInteger(value) { |
|
var result = toFinite(value), |
|
remainder = result % 1; |
|
|
|
return result === result ? (remainder ? result - remainder : result) : 0; |
|
} |
|
|
|
/** |
|
* Converts `value` to a number. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to process. |
|
* @returns {number} Returns the number. |
|
* @example |
|
* |
|
* _.toNumber(3.2); |
|
* // => 3.2 |
|
* |
|
* _.toNumber(Number.MIN_VALUE); |
|
* // => 5e-324 |
|
* |
|
* _.toNumber(Infinity); |
|
* // => Infinity |
|
* |
|
* _.toNumber('3.2'); |
|
* // => 3.2 |
|
*/ |
|
function toNumber(value) { |
|
if (typeof value == 'number') { |
|
return value; |
|
} |
|
if (isSymbol(value)) { |
|
return NAN; |
|
} |
|
if (isObject(value)) { |
|
var other = typeof value.valueOf == 'function' ? value.valueOf() : value; |
|
value = isObject(other) ? (other + '') : other; |
|
} |
|
if (typeof value != 'string') { |
|
return value === 0 ? value : +value; |
|
} |
|
value = value.replace(reTrim, ''); |
|
var isBinary = reIsBinary.test(value); |
|
return (isBinary || reIsOctal.test(value)) |
|
? freeParseInt(value.slice(2), isBinary ? 2 : 8) |
|
: (reIsBadHex.test(value) ? NAN : +value); |
|
} |
|
|
|
/** |
|
* Converts `value` to a plain object flattening inherited enumerable string |
|
* keyed properties of `value` to own properties of the plain object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Lang |
|
* @param {*} value The value to convert. |
|
* @returns {Object} Returns the converted plain object. |
|
* @example |
|
* |
|
* function Foo() { |
|
* this.b = 2; |
|
* } |
|
* |
|
* Foo.prototype.c = 3; |
|
* |
|
* _.assign({ 'a': 1 }, new Foo); |
|
* // => { 'a': 1, 'b': 2 } |
|
* |
|
* _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); |
|
* // => { 'a': 1, 'b': 2, 'c': 3 } |
|
*/ |
|
function toPlainObject(value) { |
|
return copyObject(value, keysIn(value)); |
|
} |
|
|
|
/** |
|
* Converts `value` to a string. An empty string is returned for `null` |
|
* and `undefined` values. The sign of `-0` is preserved. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Lang |
|
* @param {*} value The value to convert. |
|
* @returns {string} Returns the converted string. |
|
* @example |
|
* |
|
* _.toString(null); |
|
* // => '' |
|
* |
|
* _.toString(-0); |
|
* // => '-0' |
|
* |
|
* _.toString([1, 2, 3]); |
|
* // => '1,2,3' |
|
*/ |
|
function toString(value) { |
|
return value == null ? '' : baseToString(value); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* This method is like `_.assign` except that it iterates over own and |
|
* inherited source properties. |
|
* |
|
* **Note:** This method mutates `object`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @alias extend |
|
* @category Object |
|
* @param {Object} object The destination object. |
|
* @param {...Object} [sources] The source objects. |
|
* @returns {Object} Returns `object`. |
|
* @see _.assign |
|
* @example |
|
* |
|
* function Foo() { |
|
* this.a = 1; |
|
* } |
|
* |
|
* function Bar() { |
|
* this.c = 3; |
|
* } |
|
* |
|
* Foo.prototype.b = 2; |
|
* Bar.prototype.d = 4; |
|
* |
|
* _.assignIn({ 'a': 0 }, new Foo, new Bar); |
|
* // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } |
|
*/ |
|
var assignIn = createAssigner(function(object, source) { |
|
copyObject(source, keysIn(source), object); |
|
}); |
|
|
|
/** |
|
* Creates an object that inherits from the `prototype` object. If a |
|
* `properties` object is given, its own enumerable string keyed properties |
|
* are assigned to the created object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.3.0 |
|
* @category Object |
|
* @param {Object} prototype The object to inherit from. |
|
* @param {Object} [properties] The properties to assign to the object. |
|
* @returns {Object} Returns the new object. |
|
* @example |
|
* |
|
* function Shape() { |
|
* this.x = 0; |
|
* this.y = 0; |
|
* } |
|
* |
|
* function Circle() { |
|
* Shape.call(this); |
|
* } |
|
* |
|
* Circle.prototype = _.create(Shape.prototype, { |
|
* 'constructor': Circle |
|
* }); |
|
* |
|
* var circle = new Circle; |
|
* circle instanceof Circle; |
|
* // => true |
|
* |
|
* circle instanceof Shape; |
|
* // => true |
|
*/ |
|
function create(prototype, properties) { |
|
var result = baseCreate(prototype); |
|
return properties == null ? result : baseAssign(result, properties); |
|
} |
|
|
|
/** |
|
* Assigns own and inherited enumerable string keyed properties of source |
|
* objects to the destination object for all destination properties that |
|
* resolve to `undefined`. Source objects are applied from left to right. |
|
* Once a property is set, additional values of the same property are ignored. |
|
* |
|
* **Note:** This method mutates `object`. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The destination object. |
|
* @param {...Object} [sources] The source objects. |
|
* @returns {Object} Returns `object`. |
|
* @see _.defaultsDeep |
|
* @example |
|
* |
|
* _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); |
|
* // => { 'a': 1, 'b': 2 } |
|
*/ |
|
var defaults = baseRest(function(object, sources) { |
|
object = Object(object); |
|
|
|
var index = -1; |
|
var length = sources.length; |
|
var guard = length > 2 ? sources[2] : undefined; |
|
|
|
if (guard && isIterateeCall(sources[0], sources[1], guard)) { |
|
length = 1; |
|
} |
|
|
|
while (++index < length) { |
|
var source = sources[index]; |
|
var props = keysIn(source); |
|
var propsIndex = -1; |
|
var propsLength = props.length; |
|
|
|
while (++propsIndex < propsLength) { |
|
var key = props[propsIndex]; |
|
var value = object[key]; |
|
|
|
if (value === undefined || |
|
(eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { |
|
object[key] = source[key]; |
|
} |
|
} |
|
} |
|
|
|
return object; |
|
}); |
|
|
|
/** |
|
* This method is like `_.defaults` except that it recursively assigns |
|
* default properties. |
|
* |
|
* **Note:** This method mutates `object`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.10.0 |
|
* @category Object |
|
* @param {Object} object The destination object. |
|
* @param {...Object} [sources] The source objects. |
|
* @returns {Object} Returns `object`. |
|
* @see _.defaults |
|
* @example |
|
* |
|
* _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); |
|
* // => { 'a': { 'b': 2, 'c': 3 } } |
|
*/ |
|
var defaultsDeep = baseRest(function(args) { |
|
args.push(undefined, customDefaultsMerge); |
|
return apply(mergeWith, undefined, args); |
|
}); |
|
|
|
/** |
|
* This method is like `_.find` except that it returns the key of the first |
|
* element `predicate` returns truthy for instead of the element itself. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 1.1.0 |
|
* @category Object |
|
* @param {Object} object The object to inspect. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @returns {string|undefined} Returns the key of the matched element, |
|
* else `undefined`. |
|
* @example |
|
* |
|
* var users = { |
|
* 'barney': { 'age': 36, 'active': true }, |
|
* 'fred': { 'age': 40, 'active': false }, |
|
* 'pebbles': { 'age': 1, 'active': true } |
|
* }; |
|
* |
|
* _.findKey(users, function(o) { return o.age < 40; }); |
|
* // => 'barney' (iteration order is not guaranteed) |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.findKey(users, { 'age': 1, 'active': true }); |
|
* // => 'pebbles' |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.findKey(users, ['active', false]); |
|
* // => 'fred' |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.findKey(users, 'active'); |
|
* // => 'barney' |
|
*/ |
|
function findKey(object, predicate) { |
|
return baseFindKey(object, baseIteratee(predicate, 3), baseForOwn); |
|
} |
|
|
|
/** |
|
* This method is like `_.findKey` except that it iterates over elements of |
|
* a collection in the opposite order. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.0.0 |
|
* @category Object |
|
* @param {Object} object The object to inspect. |
|
* @param {Function} [predicate=_.identity] The function invoked per iteration. |
|
* @returns {string|undefined} Returns the key of the matched element, |
|
* else `undefined`. |
|
* @example |
|
* |
|
* var users = { |
|
* 'barney': { 'age': 36, 'active': true }, |
|
* 'fred': { 'age': 40, 'active': false }, |
|
* 'pebbles': { 'age': 1, 'active': true } |
|
* }; |
|
* |
|
* _.findLastKey(users, function(o) { return o.age < 40; }); |
|
* // => returns 'pebbles' assuming `_.findKey` returns 'barney' |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.findLastKey(users, { 'age': 36, 'active': true }); |
|
* // => 'barney' |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.findLastKey(users, ['active', false]); |
|
* // => 'fred' |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.findLastKey(users, 'active'); |
|
* // => 'pebbles' |
|
*/ |
|
function findLastKey(object, predicate) { |
|
return baseFindKey(object, baseIteratee(predicate, 3), baseForOwnRight); |
|
} |
|
|
|
/** |
|
* Gets the value at `path` of `object`. If the resolved value is |
|
* `undefined`, the `defaultValue` is returned in its place. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.7.0 |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path of the property to get. |
|
* @param {*} [defaultValue] The value returned for `undefined` resolved values. |
|
* @returns {*} Returns the resolved value. |
|
* @example |
|
* |
|
* var object = { 'a': [{ 'b': { 'c': 3 } }] }; |
|
* |
|
* _.get(object, 'a[0].b.c'); |
|
* // => 3 |
|
* |
|
* _.get(object, ['a', '0', 'b', 'c']); |
|
* // => 3 |
|
* |
|
* _.get(object, 'a.b.c', 'default'); |
|
* // => 'default' |
|
*/ |
|
function get(object, path, defaultValue) { |
|
var result = object == null ? undefined : baseGet(object, path); |
|
return result === undefined ? defaultValue : result; |
|
} |
|
|
|
/** |
|
* Checks if `path` is a direct property of `object`. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path to check. |
|
* @returns {boolean} Returns `true` if `path` exists, else `false`. |
|
* @example |
|
* |
|
* var object = { 'a': { 'b': 2 } }; |
|
* var other = _.create({ 'a': _.create({ 'b': 2 }) }); |
|
* |
|
* _.has(object, 'a'); |
|
* // => true |
|
* |
|
* _.has(object, 'a.b'); |
|
* // => true |
|
* |
|
* _.has(object, ['a', 'b']); |
|
* // => true |
|
* |
|
* _.has(other, 'a'); |
|
* // => false |
|
*/ |
|
function has(object, path) { |
|
return object != null && hasPath(object, path, baseHas); |
|
} |
|
|
|
/** |
|
* Checks if `path` is a direct or inherited property of `object`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path to check. |
|
* @returns {boolean} Returns `true` if `path` exists, else `false`. |
|
* @example |
|
* |
|
* var object = _.create({ 'a': _.create({ 'b': 2 }) }); |
|
* |
|
* _.hasIn(object, 'a'); |
|
* // => true |
|
* |
|
* _.hasIn(object, 'a.b'); |
|
* // => true |
|
* |
|
* _.hasIn(object, ['a', 'b']); |
|
* // => true |
|
* |
|
* _.hasIn(object, 'b'); |
|
* // => false |
|
*/ |
|
function hasIn(object, path) { |
|
return object != null && hasPath(object, path, baseHasIn); |
|
} |
|
|
|
/** |
|
* Creates an object composed of the inverted keys and values of `object`. |
|
* If `object` contains duplicate values, subsequent values overwrite |
|
* property assignments of previous values. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.7.0 |
|
* @category Object |
|
* @param {Object} object The object to invert. |
|
* @returns {Object} Returns the new inverted object. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': 2, 'c': 1 }; |
|
* |
|
* _.invert(object); |
|
* // => { '1': 'c', '2': 'b' } |
|
*/ |
|
var invert = createInverter(function(result, value, key) { |
|
if (value != null && |
|
typeof value.toString != 'function') { |
|
value = nativeObjectToString.call(value); |
|
} |
|
|
|
result[value] = key; |
|
}, constant(identity)); |
|
|
|
/** |
|
* This method is like `_.invert` except that the inverted object is generated |
|
* from the results of running each element of `object` thru `iteratee`. The |
|
* corresponding inverted value of each inverted key is an array of keys |
|
* responsible for generating the inverted value. The iteratee is invoked |
|
* with one argument: (value). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.1.0 |
|
* @category Object |
|
* @param {Object} object The object to invert. |
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element. |
|
* @returns {Object} Returns the new inverted object. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': 2, 'c': 1 }; |
|
* |
|
* _.invertBy(object); |
|
* // => { '1': ['a', 'c'], '2': ['b'] } |
|
* |
|
* _.invertBy(object, function(value) { |
|
* return 'group' + value; |
|
* }); |
|
* // => { 'group1': ['a', 'c'], 'group2': ['b'] } |
|
*/ |
|
var invertBy = createInverter(function(result, value, key) { |
|
if (value != null && |
|
typeof value.toString != 'function') { |
|
value = nativeObjectToString.call(value); |
|
} |
|
|
|
if (hasOwnProperty.call(result, value)) { |
|
result[value].push(key); |
|
} else { |
|
result[value] = [key]; |
|
} |
|
}, baseIteratee); |
|
|
|
/** |
|
* Creates an array of the own enumerable property names of `object`. |
|
* |
|
* **Note:** Non-object values are coerced to objects. See the |
|
* [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) |
|
* for more details. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names. |
|
* @example |
|
* |
|
* function Foo() { |
|
* this.a = 1; |
|
* this.b = 2; |
|
* } |
|
* |
|
* Foo.prototype.c = 3; |
|
* |
|
* _.keys(new Foo); |
|
* // => ['a', 'b'] (iteration order is not guaranteed) |
|
* |
|
* _.keys('hi'); |
|
* // => ['0', '1'] |
|
*/ |
|
function keys(object) { |
|
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); |
|
} |
|
|
|
/** |
|
* Creates an array of the own and inherited enumerable property names of `object`. |
|
* |
|
* **Note:** Non-object values are coerced to objects. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property names. |
|
* @example |
|
* |
|
* function Foo() { |
|
* this.a = 1; |
|
* this.b = 2; |
|
* } |
|
* |
|
* Foo.prototype.c = 3; |
|
* |
|
* _.keysIn(new Foo); |
|
* // => ['a', 'b', 'c'] (iteration order is not guaranteed) |
|
*/ |
|
function keysIn(object) { |
|
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); |
|
} |
|
|
|
/** |
|
* This method is like `_.assign` except that it recursively merges own and |
|
* inherited enumerable string keyed properties of source objects into the |
|
* destination object. Source properties that resolve to `undefined` are |
|
* skipped if a destination value exists. Array and plain object properties |
|
* are merged recursively. Other objects and value types are overridden by |
|
* assignment. Source objects are applied from left to right. Subsequent |
|
* sources overwrite property assignments of previous sources. |
|
* |
|
* **Note:** This method mutates `object`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.5.0 |
|
* @category Object |
|
* @param {Object} object The destination object. |
|
* @param {...Object} [sources] The source objects. |
|
* @returns {Object} Returns `object`. |
|
* @example |
|
* |
|
* var object = { |
|
* 'a': [{ 'b': 2 }, { 'd': 4 }] |
|
* }; |
|
* |
|
* var other = { |
|
* 'a': [{ 'c': 3 }, { 'e': 5 }] |
|
* }; |
|
* |
|
* _.merge(object, other); |
|
* // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } |
|
*/ |
|
var merge = createAssigner(function(object, source, srcIndex) { |
|
baseMerge(object, source, srcIndex); |
|
}); |
|
|
|
/** |
|
* This method is like `_.merge` except that it accepts `customizer` which |
|
* is invoked to produce the merged values of the destination and source |
|
* properties. If `customizer` returns `undefined`, merging is handled by the |
|
* method instead. The `customizer` is invoked with six arguments: |
|
* (objValue, srcValue, key, object, source, stack). |
|
* |
|
* **Note:** This method mutates `object`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Object |
|
* @param {Object} object The destination object. |
|
* @param {...Object} sources The source objects. |
|
* @param {Function} customizer The function to customize assigned values. |
|
* @returns {Object} Returns `object`. |
|
* @example |
|
* |
|
* function customizer(objValue, srcValue) { |
|
* if (_.isArray(objValue)) { |
|
* return objValue.concat(srcValue); |
|
* } |
|
* } |
|
* |
|
* var object = { 'a': [1], 'b': [2] }; |
|
* var other = { 'a': [3], 'b': [4] }; |
|
* |
|
* _.mergeWith(object, other, customizer); |
|
* // => { 'a': [1, 3], 'b': [2, 4] } |
|
*/ |
|
var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { |
|
baseMerge(object, source, srcIndex, customizer); |
|
}); |
|
|
|
/** |
|
* The opposite of `_.pick`; this method creates an object composed of the |
|
* own and inherited enumerable property paths of `object` that are not omitted. |
|
* |
|
* **Note:** This method is considerably slower than `_.pick`. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The source object. |
|
* @param {...(string|string[])} [paths] The property paths to omit. |
|
* @returns {Object} Returns the new object. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': '2', 'c': 3 }; |
|
* |
|
* _.omit(object, ['a', 'c']); |
|
* // => { 'b': '2' } |
|
*/ |
|
var omit = flatRest(function(object, paths) { |
|
var result = {}; |
|
if (object == null) { |
|
return result; |
|
} |
|
var isDeep = false; |
|
paths = arrayMap(paths, function(path) { |
|
path = castPath(path, object); |
|
isDeep || (isDeep = path.length > 1); |
|
return path; |
|
}); |
|
copyObject(object, getAllKeysIn(object), result); |
|
if (isDeep) { |
|
result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); |
|
} |
|
var length = paths.length; |
|
while (length--) { |
|
baseUnset(result, paths[length]); |
|
} |
|
return result; |
|
}); |
|
|
|
/** |
|
* The opposite of `_.pickBy`; this method creates an object composed of |
|
* the own and inherited enumerable string keyed properties of `object` that |
|
* `predicate` doesn't return truthy for. The predicate is invoked with two |
|
* arguments: (value, key). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Object |
|
* @param {Object} object The source object. |
|
* @param {Function} [predicate=_.identity] The function invoked per property. |
|
* @returns {Object} Returns the new object. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': '2', 'c': 3 }; |
|
* |
|
* _.omitBy(object, _.isNumber); |
|
* // => { 'b': '2' } |
|
*/ |
|
function omitBy(object, predicate) { |
|
return pickBy(object, negate(baseIteratee(predicate))); |
|
} |
|
|
|
/** |
|
* Creates an object composed of the picked `object` properties. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The source object. |
|
* @param {...(string|string[])} [paths] The property paths to pick. |
|
* @returns {Object} Returns the new object. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': '2', 'c': 3 }; |
|
* |
|
* _.pick(object, ['a', 'c']); |
|
* // => { 'a': 1, 'c': 3 } |
|
*/ |
|
var pick = flatRest(function(object, paths) { |
|
return object == null ? {} : basePick(object, paths); |
|
}); |
|
|
|
/** |
|
* Creates an object composed of the `object` properties `predicate` returns |
|
* truthy for. The predicate is invoked with two arguments: (value, key). |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Object |
|
* @param {Object} object The source object. |
|
* @param {Function} [predicate=_.identity] The function invoked per property. |
|
* @returns {Object} Returns the new object. |
|
* @example |
|
* |
|
* var object = { 'a': 1, 'b': '2', 'c': 3 }; |
|
* |
|
* _.pickBy(object, _.isNumber); |
|
* // => { 'a': 1, 'c': 3 } |
|
*/ |
|
function pickBy(object, predicate) { |
|
if (object == null) { |
|
return {}; |
|
} |
|
var props = arrayMap(getAllKeysIn(object), function(prop) { |
|
return [prop]; |
|
}); |
|
predicate = baseIteratee(predicate); |
|
return basePickBy(object, props, function(value, path) { |
|
return predicate(value, path[0]); |
|
}); |
|
} |
|
|
|
/** |
|
* This method is like `_.get` except that if the resolved value is a |
|
* function it's invoked with the `this` binding of its parent object and |
|
* its result is returned. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @param {Array|string} path The path of the property to resolve. |
|
* @param {*} [defaultValue] The value returned for `undefined` resolved values. |
|
* @returns {*} Returns the resolved value. |
|
* @example |
|
* |
|
* var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; |
|
* |
|
* _.result(object, 'a[0].b.c1'); |
|
* // => 3 |
|
* |
|
* _.result(object, 'a[0].b.c2'); |
|
* // => 4 |
|
* |
|
* _.result(object, 'a[0].b.c3', 'default'); |
|
* // => 'default' |
|
* |
|
* _.result(object, 'a[0].b.c3', _.constant('default')); |
|
* // => 'default' |
|
*/ |
|
function result(object, path, defaultValue) { |
|
path = castPath(path, object); |
|
|
|
var index = -1, |
|
length = path.length; |
|
|
|
// Ensure the loop is entered when path is empty. |
|
if (!length) { |
|
length = 1; |
|
object = undefined; |
|
} |
|
while (++index < length) { |
|
var value = object == null ? undefined : object[toKey(path[index])]; |
|
if (value === undefined) { |
|
index = length; |
|
value = defaultValue; |
|
} |
|
object = isFunction(value) ? value.call(object) : value; |
|
} |
|
return object; |
|
} |
|
|
|
/** |
|
* Sets the value at `path` of `object`. If a portion of `path` doesn't exist, |
|
* it's created. Arrays are created for missing index properties while objects |
|
* are created for all other missing properties. Use `_.setWith` to customize |
|
* `path` creation. |
|
* |
|
* **Note:** This method mutates `object`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.7.0 |
|
* @category Object |
|
* @param {Object} object The object to modify. |
|
* @param {Array|string} path The path of the property to set. |
|
* @param {*} value The value to set. |
|
* @returns {Object} Returns `object`. |
|
* @example |
|
* |
|
* var object = { 'a': [{ 'b': { 'c': 3 } }] }; |
|
* |
|
* _.set(object, 'a[0].b.c', 4); |
|
* console.log(object.a[0].b.c); |
|
* // => 4 |
|
* |
|
* _.set(object, ['x', '0', 'y', 'z'], 5); |
|
* console.log(object.x[0].y.z); |
|
* // => 5 |
|
*/ |
|
function set(object, path, value) { |
|
return object == null ? object : baseSet(object, path, value); |
|
} |
|
|
|
/** |
|
* Creates an array of the own enumerable string keyed property values of `object`. |
|
* |
|
* **Note:** Non-object values are coerced to objects. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Object |
|
* @param {Object} object The object to query. |
|
* @returns {Array} Returns the array of property values. |
|
* @example |
|
* |
|
* function Foo() { |
|
* this.a = 1; |
|
* this.b = 2; |
|
* } |
|
* |
|
* Foo.prototype.c = 3; |
|
* |
|
* _.values(new Foo); |
|
* // => [1, 2] (iteration order is not guaranteed) |
|
* |
|
* _.values('hi'); |
|
* // => ['h', 'i'] |
|
*/ |
|
function values(object) { |
|
return object == null ? [] : baseValues(object, keys(object)); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Clamps `number` within the inclusive `lower` and `upper` bounds. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.0.0 |
|
* @category Number |
|
* @param {number} number The number to clamp. |
|
* @param {number} [lower] The lower bound. |
|
* @param {number} upper The upper bound. |
|
* @returns {number} Returns the clamped number. |
|
* @example |
|
* |
|
* _.clamp(-10, -5, 5); |
|
* // => -5 |
|
* |
|
* _.clamp(10, -5, 5); |
|
* // => 5 |
|
*/ |
|
function clamp(number, lower, upper) { |
|
if (upper === undefined) { |
|
upper = lower; |
|
lower = undefined; |
|
} |
|
if (upper !== undefined) { |
|
upper = toNumber(upper); |
|
upper = upper === upper ? upper : 0; |
|
} |
|
if (lower !== undefined) { |
|
lower = toNumber(lower); |
|
lower = lower === lower ? lower : 0; |
|
} |
|
return baseClamp(toNumber(number), lower, upper); |
|
} |
|
|
|
/** |
|
* Produces a random number between the inclusive `lower` and `upper` bounds. |
|
* If only one argument is provided a number between `0` and the given number |
|
* is returned. If `floating` is `true`, or either `lower` or `upper` are |
|
* floats, a floating-point number is returned instead of an integer. |
|
* |
|
* **Note:** JavaScript follows the IEEE-754 standard for resolving |
|
* floating-point values which can produce unexpected results. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 0.7.0 |
|
* @category Number |
|
* @param {number} [lower=0] The lower bound. |
|
* @param {number} [upper=1] The upper bound. |
|
* @param {boolean} [floating] Specify returning a floating-point number. |
|
* @returns {number} Returns the random number. |
|
* @example |
|
* |
|
* _.random(0, 5); |
|
* // => an integer between 0 and 5 |
|
* |
|
* _.random(5); |
|
* // => also an integer between 0 and 5 |
|
* |
|
* _.random(5, true); |
|
* // => a floating-point number between 0 and 5 |
|
* |
|
* _.random(1.2, 5.2); |
|
* // => a floating-point number between 1.2 and 5.2 |
|
*/ |
|
function random(lower, upper, floating) { |
|
if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { |
|
upper = floating = undefined; |
|
} |
|
if (floating === undefined) { |
|
if (typeof upper == 'boolean') { |
|
floating = upper; |
|
upper = undefined; |
|
} |
|
else if (typeof lower == 'boolean') { |
|
floating = lower; |
|
lower = undefined; |
|
} |
|
} |
|
if (lower === undefined && upper === undefined) { |
|
lower = 0; |
|
upper = 1; |
|
} |
|
else { |
|
lower = toFinite(lower); |
|
if (upper === undefined) { |
|
upper = lower; |
|
lower = 0; |
|
} else { |
|
upper = toFinite(upper); |
|
} |
|
} |
|
if (lower > upper) { |
|
var temp = lower; |
|
lower = upper; |
|
upper = temp; |
|
} |
|
if (floating || lower % 1 || upper % 1) { |
|
var rand = nativeRandom(); |
|
return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); |
|
} |
|
return baseRandom(lower, upper); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Converts the characters "&", "<", ">", '"', and "'" in `string` to their |
|
* corresponding HTML entities. |
|
* |
|
* **Note:** No other characters are escaped. To escape additional |
|
* characters use a third-party library like [_he_](https://mths.be/he). |
|
* |
|
* Though the ">" character is escaped for symmetry, characters like |
|
* ">" and "/" don't need escaping in HTML and have no special meaning |
|
* unless they're part of a tag or unquoted attribute value. See |
|
* [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) |
|
* (under "semi-related fun fact") for more details. |
|
* |
|
* When working with HTML you should always |
|
* [quote attribute values](http://wonko.com/post/html-escaping) to reduce |
|
* XSS vectors. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category String |
|
* @param {string} [string=''] The string to escape. |
|
* @returns {string} Returns the escaped string. |
|
* @example |
|
* |
|
* _.escape('fred, barney, & pebbles'); |
|
* // => 'fred, barney, & pebbles' |
|
*/ |
|
function escape(string) { |
|
string = toString(string); |
|
return (string && reHasUnescapedHtml.test(string)) |
|
? string.replace(reUnescapedHtml, escapeHtmlChar) |
|
: string; |
|
} |
|
|
|
/** |
|
* Removes leading and trailing whitespace or specified characters from `string`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category String |
|
* @param {string} [string=''] The string to trim. |
|
* @param {string} [chars=whitespace] The characters to trim. |
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
|
* @returns {string} Returns the trimmed string. |
|
* @example |
|
* |
|
* _.trim(' abc '); |
|
* // => 'abc' |
|
* |
|
* _.trim('-_-abc-_-', '_-'); |
|
* // => 'abc' |
|
* |
|
* _.map([' foo ', ' bar '], _.trim); |
|
* // => ['foo', 'bar'] |
|
*/ |
|
function trim(string, chars, guard) { |
|
string = toString(string); |
|
if (string && (guard || chars === undefined)) { |
|
return string.replace(reTrim, ''); |
|
} |
|
if (!string || !(chars = baseToString(chars))) { |
|
return string; |
|
} |
|
var strSymbols = stringToArray(string), |
|
chrSymbols = stringToArray(chars), |
|
start = charsStartIndex(strSymbols, chrSymbols), |
|
end = charsEndIndex(strSymbols, chrSymbols) + 1; |
|
|
|
return castSlice(strSymbols, start, end).join(''); |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Creates a function that returns `value`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.4.0 |
|
* @category Util |
|
* @param {*} value The value to return from the new function. |
|
* @returns {Function} Returns the new constant function. |
|
* @example |
|
* |
|
* var objects = _.times(2, _.constant({ 'a': 1 })); |
|
* |
|
* console.log(objects); |
|
* // => [{ 'a': 1 }, { 'a': 1 }] |
|
* |
|
* console.log(objects[0] === objects[1]); |
|
* // => true |
|
*/ |
|
function constant(value) { |
|
return function() { |
|
return value; |
|
}; |
|
} |
|
|
|
/** |
|
* This method returns the first argument it receives. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Util |
|
* @param {*} value Any value. |
|
* @returns {*} Returns `value`. |
|
* @example |
|
* |
|
* var object = { 'a': 1 }; |
|
* |
|
* console.log(_.identity(object) === object); |
|
* // => true |
|
*/ |
|
function identity(value) { |
|
return value; |
|
} |
|
|
|
/** |
|
* Creates a function that invokes `func` with the arguments of the created |
|
* function. If `func` is a property name, the created function returns the |
|
* property value for a given element. If `func` is an array or object, the |
|
* created function returns `true` for elements that contain the equivalent |
|
* source properties, otherwise it returns `false`. |
|
* |
|
* @static |
|
* @since 4.0.0 |
|
* @memberOf _ |
|
* @category Util |
|
* @param {*} [func=_.identity] The value to convert to a callback. |
|
* @returns {Function} Returns the callback. |
|
* @example |
|
* |
|
* var users = [ |
|
* { 'user': 'barney', 'age': 36, 'active': true }, |
|
* { 'user': 'fred', 'age': 40, 'active': false } |
|
* ]; |
|
* |
|
* // The `_.matches` iteratee shorthand. |
|
* _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); |
|
* // => [{ 'user': 'barney', 'age': 36, 'active': true }] |
|
* |
|
* // The `_.matchesProperty` iteratee shorthand. |
|
* _.filter(users, _.iteratee(['user', 'fred'])); |
|
* // => [{ 'user': 'fred', 'age': 40 }] |
|
* |
|
* // The `_.property` iteratee shorthand. |
|
* _.map(users, _.iteratee('user')); |
|
* // => ['barney', 'fred'] |
|
* |
|
* // Create custom iteratee shorthands. |
|
* _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { |
|
* return !_.isRegExp(func) ? iteratee(func) : function(string) { |
|
* return func.test(string); |
|
* }; |
|
* }); |
|
* |
|
* _.filter(['abc', 'def'], /ef/); |
|
* // => ['def'] |
|
*/ |
|
function iteratee(func) { |
|
return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG)); |
|
} |
|
|
|
/** |
|
* Creates a function that performs a partial deep comparison between a given |
|
* object and `source`, returning `true` if the given object has equivalent |
|
* property values, else `false`. |
|
* |
|
* **Note:** The created function is equivalent to `_.isMatch` with `source` |
|
* partially applied. |
|
* |
|
* Partial comparisons will match empty array and empty object `source` |
|
* values against any array or object value, respectively. See `_.isEqual` |
|
* for a list of supported value comparisons. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 3.0.0 |
|
* @category Util |
|
* @param {Object} source The object of property values to match. |
|
* @returns {Function} Returns the new spec function. |
|
* @example |
|
* |
|
* var objects = [ |
|
* { 'a': 1, 'b': 2, 'c': 3 }, |
|
* { 'a': 4, 'b': 5, 'c': 6 } |
|
* ]; |
|
* |
|
* _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); |
|
* // => [{ 'a': 4, 'b': 5, 'c': 6 }] |
|
*/ |
|
function matches(source) { |
|
return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); |
|
} |
|
|
|
/** |
|
* Adds all own enumerable string keyed function properties of a source |
|
* object to the destination object. If `object` is a function, then methods |
|
* are added to its prototype as well. |
|
* |
|
* **Note:** Use `_.runInContext` to create a pristine `lodash` function to |
|
* avoid conflicts caused by modifying the original. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Util |
|
* @param {Function|Object} [object=lodash] The destination object. |
|
* @param {Object} source The object of functions to add. |
|
* @param {Object} [options={}] The options object. |
|
* @param {boolean} [options.chain=true] Specify whether mixins are chainable. |
|
* @returns {Function|Object} Returns `object`. |
|
* @example |
|
* |
|
* function vowels(string) { |
|
* return _.filter(string, function(v) { |
|
* return /[aeiou]/i.test(v); |
|
* }); |
|
* } |
|
* |
|
* _.mixin({ 'vowels': vowels }); |
|
* _.vowels('fred'); |
|
* // => ['e'] |
|
* |
|
* _('fred').vowels().value(); |
|
* // => ['e'] |
|
* |
|
* _.mixin({ 'vowels': vowels }, { 'chain': false }); |
|
* _('fred').vowels(); |
|
* // => ['e'] |
|
*/ |
|
function mixin(object, source, options) { |
|
var props = keys(source), |
|
methodNames = baseFunctions(source, props); |
|
|
|
if (options == null && |
|
!(isObject(source) && (methodNames.length || !props.length))) { |
|
options = source; |
|
source = object; |
|
object = this; |
|
methodNames = baseFunctions(source, keys(source)); |
|
} |
|
var chain = !(isObject(options) && 'chain' in options) || !!options.chain, |
|
isFunc = isFunction(object); |
|
|
|
arrayEach(methodNames, function(methodName) { |
|
var func = source[methodName]; |
|
object[methodName] = func; |
|
if (isFunc) { |
|
object.prototype[methodName] = function() { |
|
var chainAll = this.__chain__; |
|
if (chain || chainAll) { |
|
var result = object(this.__wrapped__), |
|
actions = result.__actions__ = copyArray(this.__actions__); |
|
|
|
actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); |
|
result.__chain__ = chainAll; |
|
return result; |
|
} |
|
return func.apply(object, arrayPush([this.value()], arguments)); |
|
}; |
|
} |
|
}); |
|
|
|
return object; |
|
} |
|
|
|
/** |
|
* Reverts the `_` variable to its previous value and returns a reference to |
|
* the `lodash` function. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Util |
|
* @returns {Function} Returns the `lodash` function. |
|
* @example |
|
* |
|
* var lodash = _.noConflict(); |
|
*/ |
|
function noConflict() { |
|
if (root._ === this) { |
|
root._ = oldDash; |
|
} |
|
return this; |
|
} |
|
|
|
/** |
|
* This method returns `undefined`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.3.0 |
|
* @category Util |
|
* @example |
|
* |
|
* _.times(2, _.noop); |
|
* // => [undefined, undefined] |
|
*/ |
|
function noop() { |
|
// No operation performed. |
|
} |
|
|
|
/** |
|
* Creates a function that returns the value at `path` of a given object. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 2.4.0 |
|
* @category Util |
|
* @param {Array|string} path The path of the property to get. |
|
* @returns {Function} Returns the new accessor function. |
|
* @example |
|
* |
|
* var objects = [ |
|
* { 'a': { 'b': 2 } }, |
|
* { 'a': { 'b': 1 } } |
|
* ]; |
|
* |
|
* _.map(objects, _.property('a.b')); |
|
* // => [2, 1] |
|
* |
|
* _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); |
|
* // => [1, 2] |
|
*/ |
|
function property(path) { |
|
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); |
|
} |
|
|
|
/** |
|
* Creates an array of numbers (positive and/or negative) progressing from |
|
* `start` up to, but not including, `end`. A step of `-1` is used if a negative |
|
* `start` is specified without an `end` or `step`. If `end` is not specified, |
|
* it's set to `start` with `start` then set to `0`. |
|
* |
|
* **Note:** JavaScript follows the IEEE-754 standard for resolving |
|
* floating-point values which can produce unexpected results. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Util |
|
* @param {number} [start=0] The start of the range. |
|
* @param {number} end The end of the range. |
|
* @param {number} [step=1] The value to increment or decrement by. |
|
* @returns {Array} Returns the range of numbers. |
|
* @see _.inRange, _.rangeRight |
|
* @example |
|
* |
|
* _.range(4); |
|
* // => [0, 1, 2, 3] |
|
* |
|
* _.range(-4); |
|
* // => [0, -1, -2, -3] |
|
* |
|
* _.range(1, 5); |
|
* // => [1, 2, 3, 4] |
|
* |
|
* _.range(0, 20, 5); |
|
* // => [0, 5, 10, 15] |
|
* |
|
* _.range(0, -4, -1); |
|
* // => [0, -1, -2, -3] |
|
* |
|
* _.range(1, 4, 0); |
|
* // => [1, 1, 1] |
|
* |
|
* _.range(0); |
|
* // => [] |
|
*/ |
|
var range = createRange(); |
|
|
|
/** |
|
* This method returns a new empty array. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.13.0 |
|
* @category Util |
|
* @returns {Array} Returns the new empty array. |
|
* @example |
|
* |
|
* var arrays = _.times(2, _.stubArray); |
|
* |
|
* console.log(arrays); |
|
* // => [[], []] |
|
* |
|
* console.log(arrays[0] === arrays[1]); |
|
* // => false |
|
*/ |
|
function stubArray() { |
|
return []; |
|
} |
|
|
|
/** |
|
* This method returns `false`. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @since 4.13.0 |
|
* @category Util |
|
* @returns {boolean} Returns `false`. |
|
* @example |
|
* |
|
* _.times(2, _.stubFalse); |
|
* // => [false, false] |
|
*/ |
|
function stubFalse() { |
|
return false; |
|
} |
|
|
|
/** |
|
* Generates a unique ID. If `prefix` is given, the ID is appended to it. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Util |
|
* @param {string} [prefix=''] The value to prefix the ID with. |
|
* @returns {string} Returns the unique ID. |
|
* @example |
|
* |
|
* _.uniqueId('contact_'); |
|
* // => 'contact_104' |
|
* |
|
* _.uniqueId(); |
|
* // => '105' |
|
*/ |
|
function uniqueId(prefix) { |
|
var id = ++idCounter; |
|
return toString(prefix) + id; |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* Computes the maximum value of `array`. If `array` is empty or falsey, |
|
* `undefined` is returned. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Math |
|
* @param {Array} array The array to iterate over. |
|
* @returns {*} Returns the maximum value. |
|
* @example |
|
* |
|
* _.max([4, 2, 8, 6]); |
|
* // => 8 |
|
* |
|
* _.max([]); |
|
* // => undefined |
|
*/ |
|
function max(array) { |
|
return (array && array.length) |
|
? baseExtremum(array, identity, baseGt) |
|
: undefined; |
|
} |
|
|
|
/** |
|
* Computes the minimum value of `array`. If `array` is empty or falsey, |
|
* `undefined` is returned. |
|
* |
|
* @static |
|
* @since 0.1.0 |
|
* @memberOf _ |
|
* @category Math |
|
* @param {Array} array The array to iterate over. |
|
* @returns {*} Returns the minimum value. |
|
* @example |
|
* |
|
* _.min([4, 2, 8, 6]); |
|
* // => 2 |
|
* |
|
* _.min([]); |
|
* // => undefined |
|
*/ |
|
function min(array) { |
|
return (array && array.length) |
|
? baseExtremum(array, identity, baseLt) |
|
: undefined; |
|
} |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
// Add methods that return wrapped values in chain sequences. |
|
lodash.assignIn = assignIn; |
|
lodash.before = before; |
|
lodash.bind = bind; |
|
lodash.chain = chain; |
|
lodash.compact = compact; |
|
lodash.concat = concat; |
|
lodash.countBy = countBy; |
|
lodash.create = create; |
|
lodash.debounce = debounce; |
|
lodash.defaults = defaults; |
|
lodash.defaultsDeep = defaultsDeep; |
|
lodash.defer = defer; |
|
lodash.delay = delay; |
|
lodash.difference = difference; |
|
lodash.drop = drop; |
|
lodash.filter = filter; |
|
lodash.flatten = flatten; |
|
lodash.flattenDeep = flattenDeep; |
|
lodash.groupBy = groupBy; |
|
lodash.initial = initial; |
|
lodash.intersection = intersection; |
|
lodash.invert = invert; |
|
lodash.invertBy = invertBy; |
|
lodash.iteratee = iteratee; |
|
lodash.keys = keys; |
|
lodash.map = map; |
|
lodash.matches = matches; |
|
lodash.merge = merge; |
|
lodash.mixin = mixin; |
|
lodash.negate = negate; |
|
lodash.omit = omit; |
|
lodash.omitBy = omitBy; |
|
lodash.once = once; |
|
lodash.pick = pick; |
|
lodash.range = range; |
|
lodash.reject = reject; |
|
lodash.rest = rest; |
|
lodash.set = set; |
|
lodash.slice = slice; |
|
lodash.sortBy = sortBy; |
|
lodash.take = take; |
|
lodash.takeRight = takeRight; |
|
lodash.tap = tap; |
|
lodash.throttle = throttle; |
|
lodash.thru = thru; |
|
lodash.toArray = toArray; |
|
lodash.union = union; |
|
lodash.uniq = uniq; |
|
lodash.uniqBy = uniqBy; |
|
lodash.unzip = unzip; |
|
lodash.values = values; |
|
lodash.without = without; |
|
lodash.zip = zip; |
|
lodash.zipObject = zipObject; |
|
|
|
// Add aliases. |
|
lodash.extend = assignIn; |
|
|
|
// Add methods to `lodash.prototype`. |
|
mixin(lodash, lodash); |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
// Add methods that return unwrapped values in chain sequences. |
|
lodash.clamp = clamp; |
|
lodash.clone = clone; |
|
lodash.cloneDeep = cloneDeep; |
|
lodash.escape = escape; |
|
lodash.every = every; |
|
lodash.find = find; |
|
lodash.findIndex = findIndex; |
|
lodash.findKey = findKey; |
|
lodash.findLastIndex = findLastIndex; |
|
lodash.findLastKey = findLastKey; |
|
lodash.forEach = forEach; |
|
lodash.get = get; |
|
lodash.has = has; |
|
lodash.head = head; |
|
lodash.identity = identity; |
|
lodash.indexOf = indexOf; |
|
lodash.isArguments = isArguments; |
|
lodash.isArray = isArray; |
|
lodash.isArrayLike = isArrayLike; |
|
lodash.isBoolean = isBoolean; |
|
lodash.isDate = isDate; |
|
lodash.isEmpty = isEmpty; |
|
lodash.isEqual = isEqual; |
|
lodash.isFinite = isFinite; |
|
lodash.isFunction = isFunction; |
|
lodash.isNaN = isNaN; |
|
lodash.isNull = isNull; |
|
lodash.isNumber = isNumber; |
|
lodash.isObject = isObject; |
|
lodash.isPlainObject = isPlainObject; |
|
lodash.isRegExp = isRegExp; |
|
lodash.isString = isString; |
|
lodash.isUndefined = isUndefined; |
|
lodash.last = last; |
|
lodash.max = max; |
|
lodash.min = min; |
|
lodash.noConflict = noConflict; |
|
lodash.noop = noop; |
|
lodash.random = random; |
|
lodash.reduce = reduce; |
|
lodash.result = result; |
|
lodash.size = size; |
|
lodash.some = some; |
|
lodash.trim = trim; |
|
lodash.uniqueId = uniqueId; |
|
|
|
// Add aliases. |
|
lodash.each = forEach; |
|
lodash.first = head; |
|
|
|
mixin(lodash, (function() { |
|
var source = {}; |
|
baseForOwn(lodash, function(func, methodName) { |
|
if (!hasOwnProperty.call(lodash.prototype, methodName)) { |
|
source[methodName] = func; |
|
} |
|
}); |
|
return source; |
|
}()), { 'chain': false }); |
|
|
|
/*------------------------------------------------------------------------*/ |
|
|
|
/** |
|
* The semantic version number. |
|
* |
|
* @static |
|
* @memberOf _ |
|
* @type {string} |
|
*/ |
|
lodash.VERSION = VERSION; |
|
|
|
// Add `LazyWrapper` methods for `_.drop` and `_.take` variants. |
|
arrayEach(['drop', 'take'], function(methodName, index) { |
|
LazyWrapper.prototype[methodName] = function(n) { |
|
n = n === undefined ? 1 : nativeMax(toInteger(n), 0); |
|
|
|
var result = (this.__filtered__ && !index) |
|
? new LazyWrapper(this) |
|
: this.clone(); |
|
|
|
if (result.__filtered__) { |
|
result.__takeCount__ = nativeMin(n, result.__takeCount__); |
|
} else { |
|
result.__views__.push({ |
|
'size': nativeMin(n, MAX_ARRAY_LENGTH), |
|
'type': methodName + (result.__dir__ < 0 ? 'Right' : '') |
|
}); |
|
} |
|
return result; |
|
}; |
|
|
|
LazyWrapper.prototype[methodName + 'Right'] = function(n) { |
|
return this.reverse()[methodName](n).reverse(); |
|
}; |
|
}); |
|
|
|
// Add `LazyWrapper` methods that accept an `iteratee` value. |
|
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { |
|
var type = index + 1, |
|
isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG; |
|
|
|
LazyWrapper.prototype[methodName] = function(iteratee) { |
|
var result = this.clone(); |
|
result.__iteratees__.push({ |
|
'iteratee': getIteratee(iteratee, 3), |
|
'type': type |
|
}); |
|
result.__filtered__ = result.__filtered__ || isFilter; |
|
return result; |
|
}; |
|
}); |
|
|
|
// Add `LazyWrapper` methods for `_.head` and `_.last`. |
|
arrayEach(['head', 'last'], function(methodName, index) { |
|
var takeName = 'take' + (index ? 'Right' : ''); |
|
|
|
LazyWrapper.prototype[methodName] = function() { |
|
return this[takeName](1).value()[0]; |
|
}; |
|
}); |
|
|
|
// Add `LazyWrapper` methods for `_.initial` and `_.tail`. |
|
arrayEach(['initial', 'tail'], function(methodName, index) { |
|
var dropName = 'drop' + (index ? '' : 'Right'); |
|
|
|
LazyWrapper.prototype[methodName] = function() { |
|
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); |
|
}; |
|
}); |
|
|
|
LazyWrapper.prototype.compact = function() { |
|
return this.filter(identity); |
|
}; |
|
|
|
LazyWrapper.prototype.find = function(predicate) { |
|
return this.filter(predicate).head(); |
|
}; |
|
|
|
LazyWrapper.prototype.findLast = function(predicate) { |
|
return this.reverse().find(predicate); |
|
}; |
|
|
|
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) { |
|
if (typeof path == 'function') { |
|
return new LazyWrapper(this); |
|
} |
|
return this.map(function(value) { |
|
return baseInvoke(value, path, args); |
|
}); |
|
}); |
|
|
|
LazyWrapper.prototype.reject = function(predicate) { |
|
return this.filter(negate(getIteratee(predicate))); |
|
}; |
|
|
|
LazyWrapper.prototype.slice = function(start, end) { |
|
start = toInteger(start); |
|
|
|
var result = this; |
|
if (result.__filtered__ && (start > 0 || end < 0)) { |
|
return new LazyWrapper(result); |
|
} |
|
if (start < 0) { |
|
result = result.takeRight(-start); |
|
} else if (start) { |
|
result = result.drop(start); |
|
} |
|
if (end !== undefined) { |
|
end = toInteger(end); |
|
result = end < 0 ? result.dropRight(-end) : result.take(end - start); |
|
} |
|
return result; |
|
}; |
|
|
|
LazyWrapper.prototype.takeRightWhile = function(predicate) { |
|
return this.reverse().takeWhile(predicate).reverse(); |
|
}; |
|
|
|
LazyWrapper.prototype.toArray = function() { |
|
return this.take(MAX_ARRAY_LENGTH); |
|
}; |
|
|
|
// Add `LazyWrapper` methods to `lodash.prototype`. |
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) { |
|
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), |
|
isTaker = /^(?:head|last)$/.test(methodName), |
|
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName], |
|
retUnwrapped = isTaker || /^find/.test(methodName); |
|
|
|
if (!lodashFunc) { |
|
return; |
|
} |
|
lodash.prototype[methodName] = function() { |
|
var value = this.__wrapped__, |
|
args = isTaker ? [1] : arguments, |
|
isLazy = value instanceof LazyWrapper, |
|
iteratee = args[0], |
|
useLazy = isLazy || isArray(value); |
|
|
|
var interceptor = function(value) { |
|
var result = lodashFunc.apply(lodash, arrayPush([value], args)); |
|
return (isTaker && chainAll) ? result[0] : result; |
|
}; |
|
|
|
if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { |
|
// Avoid lazy use if the iteratee has a "length" value other than `1`. |
|
isLazy = useLazy = false; |
|
} |
|
var chainAll = this.__chain__, |
|
isHybrid = !!this.__actions__.length, |
|
isUnwrapped = retUnwrapped && !chainAll, |
|
onlyLazy = isLazy && !isHybrid; |
|
|
|
if (!retUnwrapped && useLazy) { |
|
value = onlyLazy ? value : new LazyWrapper(this); |
|
var result = func.apply(value, args); |
|
result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); |
|
return new LodashWrapper(result, chainAll); |
|
} |
|
if (isUnwrapped && onlyLazy) { |
|
return func.apply(this, args); |
|
} |
|
result = this.thru(interceptor); |
|
return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result; |
|
}; |
|
}); |
|
|
|
// Add `Array` methods to `lodash.prototype`. |
|
arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { |
|
var func = arrayProto[methodName], |
|
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', |
|
retUnwrapped = /^(?:pop|shift)$/.test(methodName); |
|
|
|
lodash.prototype[methodName] = function() { |
|
var args = arguments; |
|
if (retUnwrapped && !this.__chain__) { |
|
var value = this.value(); |
|
return func.apply(isArray(value) ? value : [], args); |
|
} |
|
return this[chainName](function(value) { |
|
return func.apply(isArray(value) ? value : [], args); |
|
}); |
|
}; |
|
}); |
|
|
|
// Map minified method names to their real names. |
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) { |
|
var lodashFunc = lodash[methodName]; |
|
if (lodashFunc) { |
|
var key = (lodashFunc.name + ''), |
|
names = realNames[key] || (realNames[key] = []); |
|
|
|
names.push({ 'name': methodName, 'func': lodashFunc }); |
|
} |
|
}); |
|
|
|
realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{ |
|
'name': 'wrapper', |
|
'func': undefined |
|
}]; |
|
|
|
// Add methods to `LazyWrapper`. |
|
LazyWrapper.prototype.clone = lazyClone; |
|
LazyWrapper.prototype.reverse = lazyReverse; |
|
LazyWrapper.prototype.value = lazyValue; |
|
|
|
// Add lazy aliases. |
|
lodash.prototype.first = lodash.prototype.head; |
|
|
|
if (symIterator) { |
|
lodash.prototype[symIterator] = wrapperToIterator; |
|
} |
|
|
|
/*--------------------------------------------------------------------------*/ |
|
|
|
// Some AMD build optimizers, like r.js, check for condition patterns like: |
|
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { |
|
// Expose Lodash on the global object to prevent errors when Lodash is |
|
// loaded by a script tag in the presence of an AMD loader. |
|
// See http://requirejs.org/docs/errors.html#mismatch for more details. |
|
// Use `_.noConflict` to remove Lodash from the global object. |
|
root._ = lodash; |
|
|
|
// Define as an anonymous module so, through path mapping, it can be |
|
// referenced as the "underscore" module. |
|
define(function() { |
|
return lodash; |
|
}); |
|
} |
|
// Check for `exports` after `define` in case a build optimizer adds it. |
|
else if (freeModule) { |
|
// Export for Node.js. |
|
(freeModule.exports = lodash)._ = lodash; |
|
// Export for CommonJS support. |
|
freeExports._ = lodash; |
|
} |
|
else { |
|
// Export to the global object. |
|
root._ = lodash; |
|
} |
|
}.call(this)); |
|
/** |
|
* 基本函数 |
|
* Create By GUY 2014\11\17 |
|
* |
|
*/ |
|
var _global; |
|
if (typeof window !== "undefined") { |
|
_global = window; |
|
} else if (typeof global !== "undefined") { |
|
_global = global; |
|
} else if (typeof self !== "undefined") { |
|
_global = self; |
|
} else { |
|
_global = this; |
|
} |
|
if (!_global.BI) { |
|
_global.BI = {}; |
|
} |
|
|
|
!(function (undefined) { |
|
var traverse = function (func, context) { |
|
return function (value, key, obj) { |
|
return func.call(context, key, value, obj); |
|
}; |
|
}; |
|
var _apply = function (name) { |
|
return function () { |
|
return _[name].apply(_, arguments); |
|
}; |
|
}; |
|
var _applyFunc = function (name) { |
|
return function () { |
|
var args = Array.prototype.slice.call(arguments, 0); |
|
args[1] = _.isFunction(args[1]) ? traverse(args[1], args[2]) : args[1]; |
|
return _[name].apply(_, args); |
|
}; |
|
}; |
|
|
|
// Utility |
|
_.extend(BI, { |
|
assert: function (v, is) { |
|
if (this.isFunction(is)) { |
|
if (!is(v)) { |
|
throw new Error(v + " error"); |
|
} else { |
|
return true; |
|
} |
|
} |
|
if (!this.isArray(is)) { |
|
is = [is]; |
|
} |
|
if (!this.deepContains(is, v)) { |
|
throw new Error(v + " error"); |
|
} |
|
}, |
|
|
|
warn: function (message) { |
|
console.warn(message); |
|
}, |
|
|
|
UUID: function () { |
|
var f = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"]; |
|
var str = ""; |
|
for (var i = 0; i < 16; i++) { |
|
var r = parseInt(f.length * Math.random(), 10); |
|
str += f[r]; |
|
} |
|
return str; |
|
}, |
|
|
|
isWidget: function (widget) { |
|
return widget instanceof BI.Widget || (BI.View && widget instanceof BI.View); |
|
}, |
|
|
|
createWidgets: function (items, options, context) { |
|
if (!BI.isArray(items)) { |
|
throw new Error("cannot create Widgets"); |
|
} |
|
if (BI.isWidget(options)) { |
|
context = options; |
|
options = {}; |
|
} else { |
|
options || (options = {}); |
|
} |
|
return BI.map(BI.flatten(items), function (i, item) { |
|
return BI.createWidget(item, BI.deepClone(options)); |
|
}); |
|
}, |
|
|
|
createItems: function (data, innerAttr, outerAttr) { |
|
innerAttr = BI.isArray(innerAttr) ? innerAttr : BI.makeArray(BI.flatten(data).length, innerAttr || {}); |
|
outerAttr = BI.isArray(outerAttr) ? outerAttr : BI.makeArray(BI.flatten(data).length, outerAttr || {}); |
|
return BI.map(data, function (i, item) { |
|
if (BI.isArray(item)) { |
|
return BI.createItems(item, innerAttr, outerAttr); |
|
} |
|
if (item instanceof BI.Widget) { |
|
return BI.extend({}, innerAttr.shift(), outerAttr.shift(), { |
|
type: null, |
|
el: item |
|
}); |
|
} |
|
if (innerAttr[0] instanceof BI.Widget) { |
|
outerAttr.shift(); |
|
return BI.extend({}, item, { |
|
el: innerAttr.shift() |
|
}); |
|
} |
|
if (item.el instanceof BI.Widget || (BI.View && item.el instanceof BI.View)) { |
|
innerAttr.shift(); |
|
return BI.extend({}, outerAttr.shift(), {type: null}, item); |
|
} |
|
if (item.el) { |
|
return BI.extend({}, outerAttr.shift(), item, { |
|
el: BI.extend({}, innerAttr.shift(), item.el) |
|
}); |
|
} |
|
return BI.extend({}, outerAttr.shift(), { |
|
el: BI.extend({}, innerAttr.shift(), item) |
|
}); |
|
}); |
|
}, |
|
|
|
// 用容器包装items |
|
packageItems: function (items, layouts) { |
|
for (var i = layouts.length - 1; i >= 0; i--) { |
|
items = BI.map(items, function (k, it) { |
|
return BI.extend({}, layouts[i], { |
|
items: [ |
|
BI.extend({}, layouts[i].el, { |
|
el: it |
|
}) |
|
] |
|
}); |
|
}); |
|
} |
|
return items; |
|
}, |
|
|
|
formatEL: function (obj) { |
|
if (obj && !obj.type && obj.el) { |
|
return obj; |
|
} |
|
return { |
|
el: obj |
|
}; |
|
}, |
|
|
|
// 剥开EL |
|
stripEL: function (obj) { |
|
return obj.type && obj || obj.el || obj; |
|
}, |
|
|
|
trans2Element: function (widgets) { |
|
return BI.map(widgets, function (i, wi) { |
|
return wi.element; |
|
}); |
|
} |
|
}); |
|
|
|
// 集合相关方法 |
|
_.each(["where", "findWhere", "invoke", "pluck", "shuffle", "sample", "toArray", "size"], function (name) { |
|
BI[name] = _apply(name); |
|
}); |
|
_.each(["get", "set", "each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min", |
|
"sortBy", "groupBy", "indexBy", "countBy", "partition", "clamp"], function (name) { |
|
if (name === "any") { |
|
BI[name] = _applyFunc("some"); |
|
} else { |
|
BI[name] = _applyFunc(name); |
|
} |
|
}); |
|
_.extend(BI, { |
|
// 数数 |
|
count: function (from, to, predicate) { |
|
var t; |
|
if (predicate) { |
|
for (t = from; t < to; t++) { |
|
predicate(t); |
|
} |
|
} |
|
return to - from; |
|
}, |
|
|
|
// 倒数 |
|
inverse: function (from, to, predicate) { |
|
return BI.count(to, from, predicate); |
|
}, |
|
|
|
firstKey: function (obj) { |
|
var res = undefined; |
|
BI.any(obj, function (key, value) { |
|
res = key; |
|
return true; |
|
}); |
|
return res; |
|
}, |
|
|
|
lastKey: function (obj) { |
|
var res = undefined; |
|
BI.each(obj, function (key, value) { |
|
res = key; |
|
return true; |
|
}); |
|
return res; |
|
}, |
|
|
|
firstObject: function (obj) { |
|
var res = undefined; |
|
BI.any(obj, function (key, value) { |
|
res = value; |
|
return true; |
|
}); |
|
return res; |
|
}, |
|
|
|
lastObject: function (obj) { |
|
var res = undefined; |
|
BI.each(obj, function (key, value) { |
|
res = value; |
|
return true; |
|
}); |
|
return res; |
|
}, |
|
|
|
concat: function (obj1, obj2) { |
|
if (BI.isKey(obj1)) { |
|
return BI.map([].slice.apply(arguments), function (idx, v) { |
|
return v; |
|
}).join(""); |
|
} |
|
if (BI.isArray(obj1)) { |
|
return _.concat.apply([], arguments); |
|
} |
|
if (BI.isObject(obj1)) { |
|
return _.extend.apply({}, arguments); |
|
} |
|
}, |
|
|
|
backEach: function (obj, predicate, context) { |
|
predicate = BI.iteratee(predicate, context); |
|
for (var index = obj.length - 1; index >= 0; index--) { |
|
predicate(index, obj[index], obj); |
|
} |
|
return false; |
|
}, |
|
|
|
backAny: function (obj, predicate, context) { |
|
predicate = BI.iteratee(predicate, context); |
|
for (var index = obj.length - 1; index >= 0; index--) { |
|
if (predicate(index, obj[index], obj)) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
}, |
|
|
|
backEvery: function (obj, predicate, context) { |
|
predicate = BI.iteratee(predicate, context); |
|
for (var index = obj.length - 1; index >= 0; index--) { |
|
if (!predicate(index, obj[index], obj)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
}, |
|
|
|
backFindKey: function (obj, predicate, context) { |
|
predicate = BI.iteratee(predicate, context); |
|
var keys = _.keys(obj), key; |
|
for (var i = keys.length - 1; i >= 0; i--) { |
|
key = keys[i]; |
|
if (predicate(obj[key], key, obj)) { |
|
return key; |
|
} |
|
} |
|
}, |
|
|
|
backFind: function (obj, predicate, context) { |
|
var key; |
|
if (BI.isArray(obj)) { |
|
key = BI.findLastIndex(obj, predicate, context); |
|
} else { |
|
key = BI.backFindKey(obj, predicate, context); |
|
} |
|
if (key !== void 0 && key !== -1) { |
|
return obj[key]; |
|
} |
|
}, |
|
|
|
remove: function (obj, target, context) { |
|
var isFunction = BI.isFunction(target); |
|
target = isFunction || BI.isArray(target) ? target : [target]; |
|
var i; |
|
if (BI.isArray(obj)) { |
|
for (i = 0; i < obj.length; i++) { |
|
if ((isFunction && target.apply(context, [i, obj[i]]) === true) || (!isFunction && BI.contains(target, obj[i]))) { |
|
obj.splice(i--, 1); |
|
} |
|
} |
|
} else { |
|
BI.each(obj, function (i, v) { |
|
if ((isFunction && target.apply(context, [i, obj[i]]) === true) || (!isFunction && BI.contains(target, obj[i]))) { |
|
delete obj[i]; |
|
} |
|
}); |
|
} |
|
}, |
|
|
|
removeAt: function (obj, index) { |
|
index = BI.isArray(index) ? index : [index]; |
|
var isArray = BI.isArray(obj), i; |
|
for (i = 0; i < index.length; i++) { |
|
if (isArray) { |
|
obj[index[i]] = "$deleteIndex"; |
|
} else { |
|
delete obj[index[i]]; |
|
} |
|
} |
|
if (isArray) { |
|
BI.remove(obj, "$deleteIndex"); |
|
} |
|
}, |
|
|
|
string2Array: function (str) { |
|
return str.split("&-&"); |
|
}, |
|
|
|
array2String: function (array) { |
|
return array.join("&-&"); |
|
}, |
|
|
|
abc2Int: function (str) { |
|
var idx = 0, start = "A", str = str.toUpperCase(); |
|
for (var i = 0, len = str.length; i < len; ++i) { |
|
idx = str.charAt(i).charCodeAt(0) - start.charCodeAt(0) + 26 * idx + 1; |
|
if (idx > (2147483646 - str.charAt(i).charCodeAt(0) + start.charCodeAt(0)) / 26) { |
|
return 0; |
|
} |
|
} |
|
return idx; |
|
}, |
|
|
|
int2Abc: function (num) { |
|
var DIGITS = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; |
|
var idx = num, str = ""; |
|
if (num === 0) { |
|
return ""; |
|
} |
|
while (idx !== 0) { |
|
var t = idx % 26; |
|
if (t === 0) { |
|
t = 26; |
|
} |
|
str = DIGITS[t - 1] + str; |
|
idx = (idx - t) / 26; |
|
} |
|
return str; |
|
} |
|
}); |
|
|
|
// 数组相关的方法 |
|
_.each(["first", "initial", "last", "rest", "compact", "flatten", "without", "union", "intersection", |
|
"difference", "zip", "unzip", "object", "indexOf", "lastIndexOf", "sortedIndex", "range", "take", "takeRight", "uniqBy"], function (name) { |
|
BI[name] = _apply(name); |
|
}); |
|
_.each(["findIndex", "findLastIndex"], function (name) { |
|
BI[name] = _applyFunc(name); |
|
}); |
|
_.extend(BI, { |
|
// 构建一个长度为length的数组 |
|
makeArray: function (length, value) { |
|
var res = []; |
|
for (var i = 0; i < length; i++) { |
|
if (BI.isNull(value)) { |
|
res.push(i); |
|
} else { |
|
res.push(BI.deepClone(value)); |
|
} |
|
} |
|
return res; |
|
}, |
|
|
|
makeObject: function (array, value) { |
|
var map = {}; |
|
for (var i = 0; i < array.length; i++) { |
|
if (BI.isNull(value)) { |
|
map[array[i]] = array[i]; |
|
} else { |
|
map[array[i]] = BI.deepClone(value); |
|
} |
|
} |
|
return map; |
|
}, |
|
|
|
makeArrayByArray: function (array, value) { |
|
var res = []; |
|
if (!array) { |
|
return res; |
|
} |
|
for (var i = 0, len = array.length; i < len; i++) { |
|
if (BI.isArray(array[i])) { |
|
res.push(arguments.callee(array[i], value)); |
|
} else { |
|
res.push(BI.deepClone(value)); |
|
} |
|
} |
|
return res; |
|
}, |
|
|
|
uniq: function (array, isSorted, iteratee, context) { |
|
if (array == null) { |
|
return []; |
|
} |
|
if (!_.isBoolean(isSorted)) { |
|
context = iteratee; |
|
iteratee = isSorted; |
|
isSorted = false; |
|
} |
|
iteratee && (iteratee = traverse(iteratee, context)); |
|
return _.uniq.call(_, array, isSorted, iteratee, context); |
|
} |
|
}); |
|
|
|
// 对象相关方法 |
|
_.each(["keys", "allKeys", "values", "pairs", "invert", "create", "functions", "extend", "extendOwn", |
|
"defaults", "clone", "property", "propertyOf", "matcher", "isEqual", "isMatch", "isEmpty", |
|
"isElement", "isNumber", "isString", "isArray", "isObject", "isPlainObject", "isArguments", "isFunction", "isFinite", |
|
"isBoolean", "isDate", "isRegExp", "isError", "isNaN", "isUndefined", "zipObject", "cloneDeep"], function (name) { |
|
BI[name] = _apply(name); |
|
}); |
|
_.each(["mapObject", "findKey", "pick", "omit", "tap"], function (name) { |
|
BI[name] = _applyFunc(name); |
|
}); |
|
_.extend(BI, { |
|
|
|
inherit: function (sb, sp, overrides) { |
|
if (typeof sp === "object") { |
|
overrides = sp; |
|
sp = sb; |
|
sb = function () { |
|
return sp.apply(this, arguments); |
|
}; |
|
} |
|
var F = function () { |
|
}, spp = sp.prototype; |
|
F.prototype = spp; |
|
sb.prototype = new F(); |
|
sb.superclass = spp; |
|
_.extend(sb.prototype, overrides, { |
|
superclass: sp |
|
}); |
|
return sb; |
|
}, |
|
|
|
init: function () { |
|
// 先把准备环境准备好 |
|
while (BI.prepares && BI.prepares.length > 0) { |
|
BI.prepares.shift()(); |
|
} |
|
BI.initialized = true; |
|
}, |
|
|
|
has: function (obj, keys) { |
|
if (BI.isArray(keys)) { |
|
if (keys.length === 0) { |
|
return false; |
|
} |
|
return BI.every(keys, function (i, key) { |
|
return _.has(obj, key); |
|
}); |
|
} |
|
return _.has.apply(_, arguments); |
|
}, |
|
|
|
freeze: function (value) { |
|
// 在ES5中,如果这个方法的参数不是一个对象(一个原始值),那么它会导致 TypeError |
|
// 在ES2015中,非对象参数将被视为要被冻结的普通对象,并被简单地返回 |
|
if (Object.freeze && BI.isObject(value)) { |
|
return Object.freeze(value); |
|
} |
|
return value; |
|
}, |
|
|
|
// 数字和字符串可以作为key |
|
isKey: function (key) { |
|
return BI.isNumber(key) || (BI.isString(key) && key.length > 0); |
|
}, |
|
|
|
// 忽略大小写的等于 |
|
isCapitalEqual: function (a, b) { |
|
a = BI.isNull(a) ? a : ("" + a).toLowerCase(); |
|
b = BI.isNull(b) ? b : ("" + b).toLowerCase(); |
|
return BI.isEqual(a, b); |
|
}, |
|
|
|
isWidthOrHeight: function (w) { |
|
if (typeof w === "number") { |
|
return w >= 0; |
|
} else if (typeof w === "string") { |
|
return /^\d{1,3}%$/.exec(w) || w == "auto" || /^\d+px$/.exec(w); |
|
} |
|
}, |
|
|
|
isNotNull: function (obj) { |
|
return !BI.isNull(obj); |
|
}, |
|
|
|
isNull: function (obj) { |
|
return typeof obj === "undefined" || obj === null; |
|
}, |
|
|
|
isEmptyArray: function (arr) { |
|
return BI.isArray(arr) && BI.isEmpty(arr); |
|
}, |
|
|
|
isNotEmptyArray: function (arr) { |
|
return BI.isArray(arr) && !BI.isEmpty(arr); |
|
}, |
|
|
|
isEmptyObject: function (obj) { |
|
return BI.isEqual(obj, {}); |
|
}, |
|
|
|
isNotEmptyObject: function (obj) { |
|
return BI.isPlainObject(obj) && !BI.isEmptyObject(obj); |
|
}, |
|
|
|
isEmptyString: function (obj) { |
|
return BI.isString(obj) && obj.length === 0; |
|
}, |
|
|
|
isNotEmptyString: function (obj) { |
|
return BI.isString(obj) && !BI.isEmptyString(obj); |
|
}, |
|
|
|
isWindow: function (obj) { |
|
return obj != null && obj == obj.window; |
|
} |
|
}); |
|
|
|
// deep方法 |
|
_.extend(BI, { |
|
deepClone: _.cloneDeep, |
|
deepExtend: _.merge, |
|
|
|
isDeepMatch: function (object, attrs) { |
|
var keys = BI.keys(attrs), length = keys.length; |
|
if (object == null) { |
|
return !length; |
|
} |
|
var obj = Object(object); |
|
for (var i = 0; i < length; i++) { |
|
var key = keys[i]; |
|
if (!BI.isEqual(attrs[key], obj[key]) || !(key in obj)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
}, |
|
|
|
contains: function (obj, target, fromIndex) { |
|
if (!_.isArrayLike(obj)) obj = _.values(obj); |
|
return _.indexOf(obj, target, typeof fromIndex === "number" && fromIndex) >= 0; |
|
}, |
|
|
|
deepContains: function (obj, copy) { |
|
if (BI.isObject(copy)) { |
|
return BI.any(obj, function (i, v) { |
|
if (BI.isEqual(v, copy)) { |
|
return true; |
|
} |
|
}); |
|
} |
|
return BI.contains(obj, copy); |
|
}, |
|
|
|
deepIndexOf: function (obj, target) { |
|
for (var i = 0; i < obj.length; i++) { |
|
if (BI.isEqual(target, obj[i])) { |
|
return i; |
|
} |
|
} |
|
return -1; |
|
}, |
|
|
|
deepRemove: function (obj, target) { |
|
var done = false; |
|
var i; |
|
if (BI.isArray(obj)) { |
|
for (i = 0; i < obj.length; i++) { |
|
if (BI.isEqual(target, obj[i])) { |
|
obj.splice(i--, 1); |
|
done = true; |
|
} |
|
} |
|
} else { |
|
BI.each(obj, function (i, v) { |
|
if (BI.isEqual(target, obj[i])) { |
|
delete obj[i]; |
|
done = true; |
|
} |
|
}); |
|
} |
|
return done; |
|
}, |
|
|
|
deepWithout: function (obj, target) { |
|
if (BI.isArray(obj)) { |
|
var result = []; |
|
for (var i = 0; i < obj.length; i++) { |
|
if (!BI.isEqual(target, obj[i])) { |
|
result.push(obj[i]); |
|
} |
|
} |
|
return result; |
|
} |
|
var result = {}; |
|
BI.each(obj, function (i, v) { |
|
if (!BI.isEqual(target, obj[i])) { |
|
result[i] = v; |
|
} |
|
}); |
|
return result; |
|
|
|
}, |
|
|
|
deepUnique: function (array) { |
|
var result = []; |
|
BI.each(array, function (i, item) { |
|
if (!BI.deepContains(result, item)) { |
|
result.push(item); |
|
} |
|
}); |
|
return result; |
|
}, |
|
|
|
// 比较两个对象得出不一样的key值 |
|
deepDiff: function (object, other) { |
|
object || (object = {}); |
|
other || (other = {}); |
|
var result = []; |
|
var used = []; |
|
for (var b in object) { |
|
if (this.has(object, b)) { |
|
if (!this.isEqual(object[b], other[b])) { |
|
result.push(b); |
|
} |
|
used.push(b); |
|
} |
|
} |
|
for (var b in other) { |
|
if (this.has(other, b) && !BI.contains(used, b)) { |
|
result.push(b); |
|
} |
|
} |
|
return result; |
|
} |
|
}); |
|
|
|
// 通用方法 |
|
_.each(["uniqueId", "result", "chain", "iteratee", "escape", "unescape"], function (name) { |
|
BI[name] = function () { |
|
return _[name].apply(_, arguments); |
|
}; |
|
}); |
|
|
|
// 事件相关方法 |
|
_.each(["bind", "once", "partial", "debounce", "throttle", "delay", "defer", "wrap"], function (name) { |
|
BI[name] = function () { |
|
return _[name].apply(_, arguments); |
|
}; |
|
}); |
|
|
|
_.extend(BI, { |
|
nextTick: (function () { |
|
var callbacks = []; |
|
var pending = false; |
|
var timerFunc = void 0; |
|
|
|
function nextTickHandler() { |
|
pending = false; |
|
var copies = callbacks.slice(0); |
|
callbacks.length = 0; |
|
for (var i = 0; i < copies.length; i++) { |
|
copies[i](); |
|
} |
|
} |
|
|
|
if (typeof Promise !== "undefined") { |
|
var p = Promise.resolve(); |
|
timerFunc = function timerFunc() { |
|
p.then(nextTickHandler); |
|
}; |
|
} else if (typeof MutationObserver !== "undefined") { |
|
var counter = 1; |
|
var observer = new MutationObserver(nextTickHandler); |
|
var textNode = document.createTextNode(String(counter)); |
|
observer.observe(textNode, { |
|
characterData: true |
|
}); |
|
timerFunc = function timerFunc() { |
|
counter = (counter + 1) % 2; |
|
textNode.data = String(counter); |
|
}; |
|
} else if (typeof setImmediate !== "undefined") { |
|
timerFunc = function timerFunc() { |
|
setImmediate(nextTickHandler); |
|
}; |
|
} else { |
|
// Fallback to setTimeout. |
|
timerFunc = function timerFunc() { |
|
setTimeout(nextTickHandler, 0); |
|
}; |
|
} |
|
|
|
return function queueNextTick(cb) { |
|
var _resolve = void 0; |
|
var args = [].slice.call(arguments, 1); |
|
callbacks.push(function () { |
|
if (cb) { |
|
try { |
|
cb.apply(null, args); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
} else if (_resolve) { |
|
_resolve.apply(null, args); |
|
} |
|
}); |
|
if (!pending) { |
|
pending = true; |
|
timerFunc(); |
|
} |
|
// $flow-disable-line |
|
if (!cb && typeof Promise !== 'undefined') { |
|
return new Promise(function (resolve, reject) { |
|
_resolve = resolve; |
|
}); |
|
} |
|
}; |
|
})() |
|
}); |
|
|
|
// 数字相关方法 |
|
_.each(["random"], function (name) { |
|
BI[name] = _apply(name); |
|
}); |
|
_.extend(BI, { |
|
getTime: function () { |
|
if (_global.performance && _global.performance.now) { |
|
return _global.performance.now(); |
|
} |
|
if (_global.performance && _global.performance.webkitNow) { |
|
return _global.performance.webkitNow(); |
|
} |
|
if (Date.now) { |
|
return Date.now(); |
|
} |
|
return BI.getDate().getTime(); |
|
|
|
|
|
}, |
|
|
|
parseInt: function (number) { |
|
var radix = 10; |
|
if (/^0x/g.test(number)) { |
|
radix = 16; |
|
} |
|
try { |
|
return parseInt(number, radix); |
|
} catch (e) { |
|
throw new Error(number + "parse int error"); |
|
return NaN; |
|
} |
|
}, |
|
|
|
parseSafeInt: function (value) { |
|
var MAX_SAFE_INTEGER = 9007199254740991; |
|
return value |
|
? this.clamp(this.parseInt(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) |
|
: (value === 0 ? value : 0); |
|
}, |
|
|
|
parseFloat: function (number) { |
|
try { |
|
return parseFloat(number); |
|
} catch (e) { |
|
throw new Error(number + "parse float error"); |
|
return NaN; |
|
} |
|
}, |
|
|
|
isNaturalNumber: function (number) { |
|
if (/^\d+$/.test(number)) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
|
|
isPositiveInteger: function (number) { |
|
if (/^\+?[1-9][0-9]*$/.test(number)) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
|
|
isNegativeInteger: function (number) { |
|
if (/^\-[1-9][0-9]*$/.test(number)) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
|
|
isInteger: function (number) { |
|
if (/^\-?\d+$/.test(number)) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
|
|
isNumeric: function (number) { |
|
return !isNaN(parseFloat(number)) && isFinite(number); |
|
}, |
|
|
|
isFloat: function (number) { |
|
if (/^([+-]?)\\d*\\.\\d+$/.test(number)) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
|
|
isOdd: function (number) { |
|
if (!BI.isInteger(number)) { |
|
return false; |
|
} |
|
return (number & 1) === 1; |
|
}, |
|
|
|
isEven: function (number) { |
|
if (!BI.isInteger(number)) { |
|
return false; |
|
} |
|
return (number & 1) === 0; |
|
}, |
|
|
|
sum: function (array, iteratee, context) { |
|
var sum = 0; |
|
BI.each(array, function (i, item) { |
|
if (iteratee) { |
|
sum += Number(iteratee.apply(context, [i, item])); |
|
} else { |
|
sum += Number(item); |
|
} |
|
}); |
|
return sum; |
|
}, |
|
|
|
average: function (array, iteratee, context) { |
|
var sum = BI.sum(array, iteratee, context); |
|
return sum / array.length; |
|
} |
|
}); |
|
|
|
// 字符串相关方法 |
|
_.extend(BI, { |
|
trim: function () { |
|
return _.trim.apply(_, arguments); |
|
}, |
|
|
|
toUpperCase: function (string) { |
|
return (string + "").toLocaleUpperCase(); |
|
}, |
|
|
|
toLowerCase: function (string) { |
|
return (string + "").toLocaleLowerCase(); |
|
}, |
|
|
|
isEndWithBlank: function (string) { |
|
return /(\s|\u00A0)$/.test(string); |
|
}, |
|
|
|
isLiteral: function (exp) { |
|
var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/; |
|
return literalValueRE.test(exp); |
|
}, |
|
|
|
stripQuotes: function (str) { |
|
var a = str.charCodeAt(0); |
|
var b = str.charCodeAt(str.length - 1); |
|
return a === b && (a === 0x22 || a === 0x27) |
|
? str.slice(1, -1) |
|
: str; |
|
}, |
|
|
|
// background-color => backgroundColor |
|
camelize: function (str) { |
|
return str.replace(/-(.)/g, function (_, character) { |
|
return character.toUpperCase(); |
|
}); |
|
}, |
|
|
|
// backgroundColor => background-color |
|
hyphenate: function (str) { |
|
return str.replace(/([A-Z])/g, "-$1").toLowerCase(); |
|
}, |
|
|
|
isNotEmptyString: function (str) { |
|
return BI.isString(str) && !BI.isEmpty(str); |
|
}, |
|
|
|
isEmptyString: function (str) { |
|
return BI.isString(str) && BI.isEmpty(str); |
|
}, |
|
|
|
/** |
|
* 通用加密方法 |
|
*/ |
|
encrypt: function (type, text, key) { |
|
switch (type) { |
|
case BI.CRYPT_TYPE.AES: |
|
default: |
|
return BI.aesEncrypt(text, key); |
|
} |
|
}, |
|
|
|
/** |
|
* 通用解密方法 |
|
* @param type 解密方式 |
|
* @param text 文本 |
|
* @param key 种子 |
|
* @return {*} |
|
*/ |
|
decrypt: function (type, text, key) { |
|
switch (type) { |
|
case BI.CRYPT_TYPE.AES: |
|
default: |
|
return BI.aesDecrypt(text, key); |
|
} |
|
}, |
|
|
|
/** |
|
* 对字符串中的'和\做编码处理 |
|
* @static |
|
* @param {String} string 要做编码处理的字符串 |
|
* @return {String} 编码后的字符串 |
|
*/ |
|
escape: function (string) { |
|
return string.replace(/('|\\)/g, "\\$1"); |
|
}, |
|
|
|
/** |
|
* 让字符串通过指定字符做补齐的函数 |
|
* |
|
* var s = BI.leftPad('123', 5, '0');//s的值为:'00123' |
|
* |
|
* @static |
|
* @param {String} val 原始值 |
|
* @param {Number} size 总共需要的位数 |
|
* @param {String} ch 用于补齐的字符 |
|
* @return {String} 补齐后的字符串 |
|
*/ |
|
leftPad: function (val, size, ch) { |
|
var result = String(val); |
|
if (!ch) { |
|
ch = " "; |
|
} |
|
while (result.length < size) { |
|
result = ch + result; |
|
} |
|
return result.toString(); |
|
}, |
|
|
|
/** |
|
* 对字符串做替换的函数 |
|
* |
|
* var cls = 'my-class', text = 'Some text'; |
|
* var res = BI.format('<div class="{0}>{1}</div>"', cls, text); |
|
* //res的值为:'<div class="my-class">Some text</div>'; |
|
* |
|
* @static |
|
* @param {String} format 要做替换的字符串,替换字符串1,替换字符串2... |
|
* @return {String} 做了替换后的字符串 |
|
*/ |
|
format: function (format) { |
|
var args = Array.prototype.slice.call(arguments, 1); |
|
return format.replace(/\{(\d+)\}/g, function (m, i) { |
|
return args[i]; |
|
}); |
|
} |
|
}); |
|
|
|
// 日期相关方法 |
|
_.extend(BI, { |
|
/** |
|
* 是否是闰年 |
|
* @param year |
|
* @returns {boolean} |
|
*/ |
|
isLeapYear: function (year) { |
|
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; |
|
}, |
|
|
|
/** |
|
* 检测是否在有效期 |
|
* |
|
* @param YY 年 |
|
* @param MM 月 |
|
* @param DD 日 |
|
* @param minDate '1900-01-01' |
|
* @param maxDate '2099-12-31' |
|
* @returns {Array} 若无效返回无效状态 |
|
*/ |
|
checkDateVoid: function (YY, MM, DD, minDate, maxDate) { |
|
var back = []; |
|
YY = YY | 0; |
|
MM = MM | 0; |
|
DD = DD | 0; |
|
minDate = BI.isString(minDate) ? minDate.match(/\d+/g) : minDate; |
|
maxDate = BI.isString(maxDate) ? maxDate.match(/\d+/g) : maxDate; |
|
if (YY < minDate[0]) { |
|
back = ["y"]; |
|
} else if (YY > maxDate[0]) { |
|
back = ["y", 1]; |
|
} else if (YY >= minDate[0] && YY <= maxDate[0]) { |
|
if (YY == minDate[0]) { |
|
if (MM < minDate[1]) { |
|
back = ["m"]; |
|
} else if (MM == minDate[1]) { |
|
if (DD < minDate[2]) { |
|
back = ["d"]; |
|
} |
|
} |
|
} |
|
if (YY == maxDate[0]) { |
|
if (MM > maxDate[1]) { |
|
back = ["m", 1]; |
|
} else if (MM == maxDate[1]) { |
|
if (DD > maxDate[2]) { |
|
back = ["d", 1]; |
|
} |
|
} |
|
} |
|
} |
|
return back; |
|
}, |
|
|
|
checkDateLegal: function (str) { |
|
var ar = str.match(/\d+/g); |
|
var YY = ar[0] | 0, MM = ar[1] | 0, DD = ar[2] | 0; |
|
if (ar.length <= 1) { |
|
return true; |
|
} |
|
if (ar.length <= 2) { |
|
return MM >= 1 && MM <= 12; |
|
} |
|
var MD = BI.Date._MD.slice(0); |
|
MD[1] = BI.isLeapYear(YY) ? 29 : 28; |
|
return MM >= 1 && MM <= 12 && DD <= MD[MM - 1]; |
|
}, |
|
|
|
parseDateTime: function (str, fmt) { |
|
var today = BI.getDate(); |
|
var y = 0; |
|
var m = 0; |
|
var d = 1; |
|
// wei : 对于fmt为‘YYYYMM’或者‘YYYYMMdd’的格式,str的值为类似'201111'的形式,因为年月之间没有分隔符,所以正则表达式分割无效,导致bug7376。 |
|
var a = str.split(/\W+/); |
|
if (fmt.toLowerCase() == "%y%x" || fmt.toLowerCase() == "%y%x%d") { |
|
var yearlength = 4; |
|
var otherlength = 2; |
|
a[0] = str.substring(0, yearlength); |
|
a[1] = str.substring(yearlength, yearlength + otherlength); |
|
a[2] = str.substring(yearlength + otherlength, yearlength + otherlength * 2); |
|
} |
|
var b = fmt.match(/%./g); |
|
var i = 0, j = 0; |
|
var hr = 0; |
|
var min = 0; |
|
var sec = 0; |
|
for (i = 0; i < a.length; ++i) { |
|
switch (b[i]) { |
|
case "%d": |
|
case "%e": |
|
d = parseInt(a[i], 10); |
|
break; |
|
|
|
case "%X": |
|
m = parseInt(a[i], 10) - 1; |
|
break; |
|
case "%x": |
|
m = parseInt(a[i], 10) - 1; |
|
break; |
|
|
|
case "%Y": |
|
case "%y": |
|
y = parseInt(a[i], 10); |
|
(y < 100) && (y += (y > 29) ? 1900 : 2000); |
|
break; |
|
|
|
case "%b": |
|
case "%B": |
|
for (j = 0; j < 12; ++j) { |
|
if (BI.Date._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { |
|
m = j; |
|
break; |
|
} |
|
} |
|
break; |
|
|
|
case "%H": |
|
case "%I": |
|
case "%k": |
|
case "%l": |
|
hr = parseInt(a[i], 10); |
|
break; |
|
|
|
case "%P": |
|
case "%p": |
|
if (/pm/i.test(a[i]) && hr < 12) { |
|
hr += 12; |
|
} else if (/am/i.test(a[i]) && hr >= 12) { |
|
hr -= 12; |
|
} |
|
break; |
|
|
|
case "%M": |
|
min = parseInt(a[i], 10); |
|
case "%S": |
|
sec = parseInt(a[i], 10); |
|
break; |
|
} |
|
} |
|
// if (!a[i]) { |
|
// continue; |
|
// } |
|
if (isNaN(y)) { |
|
y = today.getFullYear(); |
|
} |
|
if (isNaN(m)) { |
|
m = today.getMonth(); |
|
} |
|
if (isNaN(d)) { |
|
d = today.getDate(); |
|
} |
|
if (isNaN(hr)) { |
|
hr = today.getHours(); |
|
} |
|
if (isNaN(min)) { |
|
min = today.getMinutes(); |
|
} |
|
if (isNaN(sec)) { |
|
sec = today.getSeconds(); |
|
} |
|
if (y != 0) { |
|
return BI.getDate(y, m, d, hr, min, sec); |
|
} |
|
y = 0; |
|
m = -1; |
|
d = 0; |
|
for (i = 0; i < a.length; ++i) { |
|
if (a[i].search(/[a-zA-Z]+/) != -1) { |
|
var t = -1; |
|
for (j = 0; j < 12; ++j) { |
|
if (BI.Date._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { |
|
t = j; |
|
break; |
|
} |
|
} |
|
if (t != -1) { |
|
if (m != -1) { |
|
d = m + 1; |
|
} |
|
m = t; |
|
} |
|
} else if (parseInt(a[i], 10) <= 12 && m == -1) { |
|
m = a[i] - 1; |
|
} else if (parseInt(a[i], 10) > 31 && y == 0) { |
|
y = parseInt(a[i], 10); |
|
(y < 100) && (y += (y > 29) ? 1900 : 2000); |
|
} else if (d == 0) { |
|
d = a[i]; |
|
} |
|
} |
|
if (y == 0) { |
|
y = today.getFullYear(); |
|
} |
|
if (m != -1 && d != 0) { |
|
return BI.getDate(y, m, d, hr, min, sec); |
|
} |
|
return today; |
|
}, |
|
|
|
getDate: function () { |
|
var length = arguments.length; |
|
var args = arguments; |
|
var dt; |
|
switch (length) { |
|
// new Date() |
|
case 0: |
|
dt = new Date(); |
|
break; |
|
// new Date(long) |
|
case 1: |
|
dt = new Date(args[0]); |
|
break; |
|
// new Date(year, month) |
|
case 2: |
|
dt = new Date(args[0], args[1]); |
|
break; |
|
// new Date(year, month, day) |
|
case 3: |
|
dt = new Date(args[0], args[1], args[2]); |
|
break; |
|
// new Date(year, month, day, hour) |
|
case 4: |
|
dt = new Date(args[0], args[1], args[2], args[3]); |
|
break; |
|
// new Date(year, month, day, hour, minute) |
|
case 5: |
|
dt = new Date(args[0], args[1], args[2], args[3], args[4]); |
|
break; |
|
// new Date(year, month, day, hour, minute, second) |
|
case 6: |
|
dt = new Date(args[0], args[1], args[2], args[3], args[4], args[5]); |
|
break; |
|
// new Date(year, month, day, hour, minute, second, millisecond) |
|
case 7: |
|
dt = new Date(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); |
|
break; |
|
default: |
|
dt = new Date(); |
|
break; |
|
} |
|
if (BI.isNotNull(BI.timeZone) && (arguments.length === 0 || (arguments.length === 1 && BI.isNumber(arguments[0])))) { |
|
var localTime = dt.getTime(); |
|
// BI-33791 1901年以前的东8区标准是GMT+0805, 统一无论是什么时间,都以整的0800这样的为基准 |
|
var localOffset = dt.getTimezoneOffset() * 60000; // 获得当地时间偏移的毫秒数 |
|
var utc = localTime + localOffset; // utc即GMT时间标准时区 |
|
return new Date(utc + BI.timeZone);// + Pool.timeZone.offset); |
|
} |
|
return dt; |
|
|
|
}, |
|
|
|
getTime: function () { |
|
var length = arguments.length; |
|
var args = arguments; |
|
var dt; |
|
switch (length) { |
|
// new Date() |
|
case 0: |
|
dt = new Date(); |
|
break; |
|
// new Date(long) |
|
case 1: |
|
dt = new Date(args[0]); |
|
break; |
|
// new Date(year, month) |
|
case 2: |
|
dt = new Date(args[0], args[1]); |
|
break; |
|
// new Date(year, month, day) |
|
case 3: |
|
dt = new Date(args[0], args[1], args[2]); |
|
break; |
|
// new Date(year, month, day, hour) |
|
case 4: |
|
dt = new Date(args[0], args[1], args[2], args[3]); |
|
break; |
|
// new Date(year, month, day, hour, minute) |
|
case 5: |
|
dt = new Date(args[0], args[1], args[2], args[3], args[4]); |
|
break; |
|
// new Date(year, month, day, hour, minute, second) |
|
case 6: |
|
dt = new Date(args[0], args[1], args[2], args[3], args[4], args[5]); |
|
break; |
|
// new Date(year, month, day, hour, minute, second, millisecond) |
|
case 7: |
|
dt = new Date(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); |
|
break; |
|
default: |
|
dt = new Date(); |
|
break; |
|
} |
|
if (BI.isNotNull(BI.timeZone)) { |
|
// BI-33791 1901年以前的东8区标准是GMT+0805, 统一无论是什么时间,都以整的0800这样的为基准 |
|
return dt.getTime() - BI.timeZone - new Date().getTimezoneOffset() * 60000; |
|
} |
|
return dt.getTime(); |
|
|
|
} |
|
}); |
|
})(); |
|
!(function () { |
|
function extend () { |
|
var target = arguments[0] || {}, length = arguments.length, i = 1, options, name, src, copy; |
|
for (; i < length; i++) { |
|
// Only deal with non-null/undefined values |
|
if ((options = arguments[i]) != null) { |
|
// Extend the base object |
|
for (name in options) { |
|
src = target[name]; |
|
copy = options[name]; |
|
|
|
// Prevent never-ending loop |
|
if (target === copy) { |
|
continue; |
|
} |
|
|
|
if (copy !== undefined) { |
|
target[name] = copy; |
|
} |
|
} |
|
} |
|
} |
|
return target; |
|
} |
|
|
|
/** |
|
* 客户端观察者,主要处理事件的添加、删除、执行等 |
|
* @class BI.OB |
|
* @abstract |
|
*/ |
|
BI.OB = function (config) { |
|
this._constructor(config); |
|
}; |
|
_.extend(BI.OB.prototype, { |
|
props: {}, |
|
init: null, |
|
destroyed: null, |
|
|
|
_constructor: function (config) { |
|
this._initProps(config); |
|
this._init(); |
|
this._initRef(); |
|
}, |
|
|
|
_defaultConfig: function (config) { |
|
return {}; |
|
}, |
|
|
|
_initProps: function (config) { |
|
var props = this.props; |
|
if (BI.isFunction(this.props)) { |
|
props = this.props(config); |
|
} |
|
this.options = extend(this._defaultConfig(config), props, config); |
|
}, |
|
|
|
_init: function () { |
|
this._initListeners(); |
|
this.init && this.init(); |
|
}, |
|
|
|
_initListeners: function () { |
|
var self = this; |
|
if (this.options.listeners != null) { |
|
_.each(this.options.listeners, function (lis) { |
|
(lis.target ? lis.target : self)[lis.once ? "once" : "on"] |
|
(lis.eventName, _.bind(lis.action, self)); |
|
}); |
|
delete this.options.listeners; |
|
} |
|
}, |
|
|
|
// 获得一个当前对象的引用 |
|
_initRef: function () { |
|
if (this.options.ref) { |
|
this.options.ref.call(this, this); |
|
} |
|
}, |
|
|
|
//释放当前对象 |
|
_purgeRef: function () { |
|
if (this.options.ref) { |
|
this.options.ref.call(null); |
|
this.options.ref = null; |
|
} |
|
}, |
|
|
|
_getEvents: function () { |
|
if (!_.isArray(this.events)) { |
|
this.events = []; |
|
} |
|
return this.events; |
|
}, |
|
|
|
/** |
|
* 给观察者绑定一个事件 |
|
* @param {String} eventName 事件的名字 |
|
* @param {Function} fn 事件对应的执行函数 |
|
*/ |
|
on: function (eventName, fn) { |
|
eventName = eventName.toLowerCase(); |
|
var fns = this._getEvents()[eventName]; |
|
if (!_.isArray(fns)) { |
|
fns = []; |
|
this._getEvents()[eventName] = fns; |
|
} |
|
fns.push(fn); |
|
}, |
|
|
|
/** |
|
* 给观察者绑定一个只执行一次的事件 |
|
* @param {String} eventName 事件的名字 |
|
* @param {Function} fn 事件对应的执行函数 |
|
*/ |
|
once: function (eventName, fn) { |
|
var proxy = function () { |
|
fn.apply(this, arguments); |
|
this.un(eventName, proxy); |
|
}; |
|
this.on(eventName, proxy); |
|
}, |
|
/** |
|
* 解除观察者绑定的指定事件 |
|
* @param {String} eventName 要解除绑定事件的名字 |
|
* @param {Function} fn 事件对应的执行函数,该参数是可选的,没有该参数时,将解除绑定所有同名字的事件 |
|
*/ |
|
un: function (eventName, fn) { |
|
eventName = eventName.toLowerCase(); |
|
|
|
/* alex:如果fn是null,就是把eventName上面所有方法都un掉*/ |
|
if (fn == null) { |
|
delete this._getEvents()[eventName]; |
|
} else { |
|
var fns = this._getEvents()[eventName]; |
|
if (_.isArray(fns)) { |
|
var newFns = []; |
|
_.each(fns, function (ifn) { |
|
if (ifn != fn) { |
|
newFns.push(ifn); |
|
} |
|
}); |
|
this._getEvents()[eventName] = newFns; |
|
} |
|
} |
|
}, |
|
/** |
|
* 清除观察者的所有事件绑定 |
|
*/ |
|
purgeListeners: function () { |
|
/* alex:清空events*/ |
|
this.events = []; |
|
}, |
|
/** |
|
* 触发绑定过的事件 |
|
* |
|
* @param {String} eventName 要触发的事件的名字 |
|
* @returns {Boolean} 如果事件函数返回false,则返回false并中断其他同名事件的执行,否则执行所有的同名事件并返回true |
|
*/ |
|
fireEvent: function () { |
|
var eventName = arguments[0].toLowerCase(); |
|
var fns = this._getEvents()[eventName]; |
|
if (BI.isArray(fns)) { |
|
if (BI.isArguments(arguments[1])) { |
|
for (var i = 0; i < fns.length; i++) { |
|
if (fns[i].apply(this, arguments[1]) === false) { |
|
return false; |
|
} |
|
} |
|
} else { |
|
var args = Array.prototype.slice.call(arguments, 1); |
|
for (var i = 0; i < fns.length; i++) { |
|
if (fns[i].apply(this, args) === false) { |
|
return false; |
|
} |
|
} |
|
} |
|
} |
|
return true; |
|
}, |
|
|
|
destroy: function () { |
|
this.destroyed && this.destroyed(); |
|
this._purgeRef(); |
|
this.purgeListeners(); |
|
} |
|
}); |
|
})();/** |
|
* Widget超类 |
|
* @class BI.Widget |
|
* @extends BI.OB |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
*/ |
|
|
|
!(function () { |
|
BI.Widget = BI.inherit(BI.OB, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Widget.superclass._defaultConfig.apply(this), { |
|
root: false, |
|
tagName: "div", |
|
attributes: null, |
|
data: null, |
|
|
|
tag: null, |
|
disabled: false, |
|
invisible: false, |
|
invalid: false, |
|
baseCls: "", |
|
extraCls: "", |
|
cls: "", |
|
css: null |
|
}); |
|
}, |
|
|
|
// 覆盖父类的_constructor方法,widget不走ob的生命周期 |
|
_constructor: function () { |
|
}, |
|
|
|
beforeInit: null, |
|
|
|
// 生命周期函数 |
|
beforeCreate: null, |
|
|
|
created: null, |
|
|
|
render: null, |
|
|
|
beforeMount: null, |
|
|
|
mounted: null, |
|
|
|
shouldUpdate: null, |
|
|
|
update: function () { |
|
}, |
|
|
|
beforeDestroy: null, |
|
|
|
destroyed: null, |
|
|
|
_init: function () { |
|
BI.Widget.superclass._init.apply(this, arguments); |
|
this._initRoot(); |
|
this._initElementWidth(); |
|
this._initElementHeight(); |
|
this._initVisual(); |
|
this._initState(); |
|
this._initRender(); |
|
}, |
|
|
|
_initRender: function () { |
|
if (this.beforeInit) { |
|
this.__asking = true; |
|
this.beforeInit(BI.bind(this._render, this)); |
|
if (this.__asking === true) { |
|
this.__async = true; |
|
} |
|
} else { |
|
this._render(); |
|
} |
|
}, |
|
|
|
_render: function () { |
|
this.__asking = false; |
|
this.beforeCreate && this.beforeCreate(); |
|
this._initElement(); |
|
this._initEffects(); |
|
this.created && this.created(); |
|
}, |
|
|
|
/** |
|
* 初始化根节点 |
|
* @private |
|
*/ |
|
_initRoot: function () { |
|
var o = this.options; |
|
this.widgetName = o.widgetName || BI.uniqueId("widget"); |
|
this._isRoot = o.root; |
|
if (BI.isWidget(o.element)) { |
|
if (o.element instanceof BI.Widget) { |
|
this._parent = o.element; |
|
this._parent.addWidget(this.widgetName, this); |
|
} else { |
|
this._isRoot = true; |
|
} |
|
this.element = this.options.element.element; |
|
} else if (o.element) { |
|
// if (o.root !== true) { |
|
// throw new Error("root is a required property"); |
|
// } |
|
this.element = BI.Widget._renderEngine.createElement(this); |
|
this._isRoot = true; |
|
} else { |
|
this.element = BI.Widget._renderEngine.createElement(this); |
|
} |
|
this.element._isWidget = true; |
|
if (o._baseCls || o.baseCls || o.extraCls || o.cls) { |
|
this.element.addClass((o._baseCls || "") + " " + (o.baseCls || "") + " " + (o.extraCls || "") + " " + (o.cls || "")); |
|
} |
|
if (o.attributes) { |
|
this.element.attr(o.attributes); |
|
} |
|
if (o.data) { |
|
this.element.data(o.data); |
|
} |
|
if (o.css) { |
|
this.element.css(o.css); |
|
} |
|
this._children = {}; |
|
}, |
|
|
|
_initElementWidth: function () { |
|
var o = this.options; |
|
if (BI.isWidthOrHeight(o.width)) { |
|
this.element.css("width", o.width); |
|
} |
|
}, |
|
|
|
_initElementHeight: function () { |
|
var o = this.options; |
|
if (BI.isWidthOrHeight(o.height)) { |
|
this.element.css("height", o.height); |
|
} |
|
}, |
|
|
|
_initVisual: function () { |
|
var o = this.options; |
|
if (o.invisible) { |
|
// 用display属性做显示和隐藏,否则jquery会在显示时将display设为block会覆盖掉display:flex属性 |
|
this.element.css("display", "none"); |
|
} |
|
}, |
|
|
|
_initEffects: function () { |
|
var o = this.options; |
|
if (o.disabled || o.invalid) { |
|
if (this.options.disabled) { |
|
this.setEnable(false); |
|
} |
|
if (this.options.invalid) { |
|
this.setValid(false); |
|
} |
|
} |
|
}, |
|
|
|
_initState: function () { |
|
this._isMounted = false; |
|
}, |
|
|
|
_initElement: function () { |
|
var self = this; |
|
var els = this.render && this.render(); |
|
if (BI.isPlainObject(els)) { |
|
els = [els]; |
|
} |
|
if (BI.isArray(els)) { |
|
BI.each(els, function (i, el) { |
|
BI.createWidget(el, { |
|
element: self |
|
}); |
|
}); |
|
} |
|
// if (this._isRoot === true || !(this instanceof BI.Layout)) { |
|
this._mount(); |
|
// } |
|
}, |
|
|
|
_setParent: function (parent) { |
|
this._parent = parent; |
|
}, |
|
|
|
/** |
|
* |
|
* @param force 是否强制挂载子节点 |
|
* @param deep 子节点是否也是按照当前force处理 |
|
* @param lifeHook 生命周期钩子触不触发,默认触发 |
|
* @param predicate 递归每个widget的回调 |
|
* @returns {boolean} |
|
* @private |
|
*/ |
|
_mount: function (force, deep, lifeHook, predicate) { |
|
var self = this; |
|
if (!force && (this._isMounted || !this.isVisible() || this.__asking === true || !(this._isRoot === true || (this._parent && this._parent._isMounted === true)))) { |
|
return false; |
|
} |
|
lifeHook !== false && this.beforeMount && this.beforeMount(); |
|
this._isMounted = true; |
|
this._mountChildren && this._mountChildren(); |
|
BI.each(this._children, function (i, widget) { |
|
!self.isEnabled() && widget._setEnable(false); |
|
!self.isValid() && widget._setValid(false); |
|
widget._mount && widget._mount(deep ? force : false, deep, lifeHook, predicate); |
|
}); |
|
lifeHook !== false && this.mounted && this.mounted(); |
|
this.fireEvent(BI.Events.MOUNT); |
|
predicate && predicate(this); |
|
return true; |
|
}, |
|
|
|
_mountChildren: null, |
|
|
|
isMounted: function () { |
|
return this._isMounted; |
|
}, |
|
|
|
setWidth: function (w) { |
|
this.options.width = w; |
|
this._initElementWidth(); |
|
}, |
|
|
|
setHeight: function (h) { |
|
this.options.height = h; |
|
this._initElementHeight(); |
|
}, |
|
|
|
_setEnable: function (enable) { |
|
if (enable === true) { |
|
this.options.disabled = false; |
|
} else if (enable === false) { |
|
this.options.disabled = true; |
|
} |
|
// 递归将所有子组件使能 |
|
BI.each(this._children, function (i, child) { |
|
!child._manualSetEnable && child._setEnable && child._setEnable(enable); |
|
}); |
|
}, |
|
|
|
_setValid: function (valid) { |
|
if (valid === true) { |
|
this.options.invalid = false; |
|
} else if (valid === false) { |
|
this.options.invalid = true; |
|
} |
|
// 递归将所有子组件使有效 |
|
BI.each(this._children, function (i, child) { |
|
!child._manualSetValid && child._setValid && child._setValid(valid); |
|
}); |
|
}, |
|
|
|
_setVisible: function (visible) { |
|
if (visible === true) { |
|
this.options.invisible = false; |
|
} else if (visible === false) { |
|
this.options.invisible = true; |
|
} |
|
}, |
|
|
|
setEnable: function (enable) { |
|
this._manualSetEnable = true; |
|
this._setEnable(enable); |
|
if (enable === true) { |
|
this.element.removeClass("base-disabled disabled"); |
|
} else if (enable === false) { |
|
this.element.addClass("base-disabled disabled"); |
|
} |
|
}, |
|
|
|
setVisible: function (visible) { |
|
this._setVisible(visible); |
|
if (visible === true) { |
|
// 用this.element.show()会把display属性改成block |
|
this.element.css("display", ""); |
|
this._mount(); |
|
} else if (visible === false) { |
|
this.element.css("display", "none"); |
|
} |
|
this.fireEvent(BI.Events.VIEW, visible); |
|
}, |
|
|
|
setValid: function (valid) { |
|
this._manualSetValid = true; |
|
this._setValid(valid); |
|
if (valid === true) { |
|
this.element.removeClass("base-invalid invalid"); |
|
} else if (valid === false) { |
|
this.element.addClass("base-invalid invalid"); |
|
} |
|
}, |
|
|
|
doBehavior: function () { |
|
var args = arguments; |
|
// 递归将所有子组件使有效 |
|
BI.each(this._children, function (i, child) { |
|
child.doBehavior && child.doBehavior.apply(child, args); |
|
}); |
|
}, |
|
|
|
getWidth: function () { |
|
return this.options.width; |
|
}, |
|
|
|
getHeight: function () { |
|
return this.options.height; |
|
}, |
|
|
|
isValid: function () { |
|
return !this.options.invalid; |
|
}, |
|
|
|
addWidget: function (name, widget) { |
|
var self = this; |
|
if (name instanceof BI.Widget) { |
|
widget = name; |
|
name = widget.getName(); |
|
} |
|
if (BI.isKey(name)) { |
|
name = name + ""; |
|
} |
|
name = name || widget.getName() || BI.uniqueId("widget"); |
|
if (this._children[name]) { |
|
throw new Error("name has already been existed"); |
|
} |
|
widget._setParent && widget._setParent(this); |
|
widget.on(BI.Events.DESTROY, function () { |
|
BI.remove(self._children, this); |
|
}); |
|
return (this._children[name] = widget); |
|
}, |
|
|
|
getWidgetByName: function (name) { |
|
if (!BI.isKey(name) || name === this.getName()) { |
|
return this; |
|
} |
|
name = name + ""; |
|
var widget = void 0, other = {}; |
|
BI.any(this._children, function (i, wi) { |
|
if (i === name) { |
|
widget = wi; |
|
return true; |
|
} |
|
other[i] = wi; |
|
}); |
|
if (!widget) { |
|
BI.any(other, function (i, wi) { |
|
return (widget = wi.getWidgetByName(i)); |
|
}); |
|
} |
|
return widget; |
|
}, |
|
|
|
removeWidget: function (nameOrWidget) { |
|
var self = this; |
|
if (BI.isWidget(nameOrWidget)) { |
|
BI.remove(this._children, nameOrWidget); |
|
} else { |
|
delete this._children[nameOrWidget]; |
|
} |
|
}, |
|
|
|
hasWidget: function (name) { |
|
return this._children[name] != null; |
|
}, |
|
|
|
getName: function () { |
|
return this.widgetName; |
|
}, |
|
|
|
setTag: function (tag) { |
|
this.options.tag = tag; |
|
}, |
|
|
|
getTag: function () { |
|
return this.options.tag; |
|
}, |
|
|
|
attr: function (key, value) { |
|
var self = this; |
|
if (BI.isPlainObject(key)) { |
|
BI.each(key, function (k, v) { |
|
self.attr(k, v); |
|
}); |
|
return; |
|
} |
|
if (BI.isNotNull(value)) { |
|
return this.options[key] = value; |
|
} |
|
return this.options[key]; |
|
}, |
|
|
|
css: function (name, value) { |
|
return this.element.css(name, value); |
|
}, |
|
|
|
getText: function () { |
|
|
|
}, |
|
|
|
setText: function (text) { |
|
|
|
}, |
|
|
|
getValue: function () { |
|
|
|
}, |
|
|
|
setValue: function (value) { |
|
|
|
}, |
|
|
|
isEnabled: function () { |
|
return !this.options.disabled; |
|
}, |
|
|
|
isVisible: function () { |
|
return !this.options.invisible; |
|
}, |
|
|
|
disable: function () { |
|
this.setEnable(false); |
|
}, |
|
|
|
enable: function () { |
|
this.setEnable(true); |
|
}, |
|
|
|
valid: function () { |
|
this.setValid(true); |
|
}, |
|
|
|
invalid: function () { |
|
this.setValid(false); |
|
}, |
|
|
|
invisible: function () { |
|
this.setVisible(false); |
|
}, |
|
|
|
visible: function () { |
|
this.setVisible(true); |
|
}, |
|
|
|
__d: function () { |
|
this.beforeDestroy && this.beforeDestroy(); |
|
this.beforeDestroy = null; |
|
BI.each(this._children, function (i, widget) { |
|
widget && widget._unMount && widget._unMount(); |
|
}); |
|
this._children = {}; |
|
this._parent = null; |
|
this._isMounted = false; |
|
this.destroyed && this.destroyed(); |
|
this.destroyed = null; |
|
}, |
|
|
|
_unMount: function () { |
|
this.__d(); |
|
this.fireEvent(BI.Events.UNMOUNT); |
|
this.purgeListeners(); |
|
}, |
|
|
|
isolate: function () { |
|
if (this._parent) { |
|
this._parent.removeWidget(this); |
|
} |
|
BI.DOM.hang([this]); |
|
}, |
|
|
|
empty: function () { |
|
BI.each(this._children, function (i, widget) { |
|
widget && widget._unMount && widget._unMount(); |
|
}); |
|
this._children = {}; |
|
this.element.empty(); |
|
}, |
|
|
|
_destroy: function () { |
|
this.__d(); |
|
this.element.destroy(); |
|
this.purgeListeners(); |
|
}, |
|
|
|
destroy: function () { |
|
this.__d(); |
|
this.element.destroy(); |
|
this.fireEvent(BI.Events.DESTROY); |
|
this._purgeRef(); |
|
this.purgeListeners(); |
|
} |
|
}); |
|
BI.Widget.registerRenderEngine = function (engine) { |
|
BI.Widget._renderEngine = engine; |
|
}; |
|
BI.Widget.registerRenderEngine({ |
|
createElement: function (widget) { |
|
if (BI.isWidget(widget)) { |
|
var o = widget.options; |
|
if (o.element) { |
|
return BI.$(o.element); |
|
} |
|
return BI.$(document.createElement(o.tagName)); |
|
} |
|
return BI.$(widget); |
|
}, |
|
createFragment: function () { |
|
return document.createDocumentFragment(); |
|
} |
|
}); |
|
|
|
BI.mount = function (widget, container, predicate, hydrate) { |
|
if (hydrate === true) { |
|
// 将widget的element元素都挂载好,并建立相互关系 |
|
widget.element.data("__widgets", [widget]); |
|
var res = widget._mount(true, false, false, function (w) { |
|
BI.each(w._children, function (i, child) { |
|
var ws = child.element.data("__widgets"); |
|
if (!ws) { |
|
ws = []; |
|
} |
|
ws.push(child); |
|
child.element.data("__widgets", ws); |
|
}); |
|
predicate && predicate.apply(this, arguments); |
|
}); |
|
// 将新的dom树属性(事件等)patch到已存在的dom上 |
|
var c = BI.Widget._renderEngine.createElement; |
|
BI.DOM.patchProps(widget.element, c(c(container).children()[0])); |
|
|
|
var triggerLifeHook = function (w) { |
|
w.beforeMount && w.beforeMount(); |
|
w.mounted && w.mounted(); |
|
BI.each(w._children, function (i, child) { |
|
triggerLifeHook(child); |
|
}); |
|
}; |
|
// 最后触发组件树生命周期函数 |
|
triggerLifeHook(widget); |
|
return res; |
|
} |
|
if (container) { |
|
BI.Widget._renderEngine.createElement(container).append(widget.element); |
|
} |
|
return widget._mount(true, false, false, predicate); |
|
}; |
|
})();(function () { |
|
var kv = {}; |
|
BI.shortcut = BI.component = function (xtype, cls) { |
|
if (kv[xtype] != null) { |
|
_global.console && console.error("shortcut:[" + xtype + "] has been registed"); |
|
} |
|
kv[xtype] = cls; |
|
}; |
|
|
|
// 根据配置属性生成widget |
|
var createWidget = function (config) { |
|
var cls = kv[config.type]; |
|
|
|
var widget = new cls(); |
|
|
|
widget._initProps(config); |
|
widget._init(); |
|
widget._initRef(); |
|
|
|
return widget; |
|
}; |
|
|
|
BI.createWidget = function (item, options, context) { |
|
// 先把准备环境准备好 |
|
BI.init(); |
|
var el, w; |
|
item || (item = {}); |
|
if (BI.isWidget(options)) { |
|
context = options; |
|
options = {}; |
|
} else { |
|
options || (options = {}); |
|
} |
|
if (BI.isEmpty(item) && BI.isEmpty(options)) { |
|
return BI.createWidget({ |
|
type: "bi.layout" |
|
}); |
|
} |
|
if (BI.isWidget(item)) { |
|
return item; |
|
} |
|
if (item.type || options.type) { |
|
el = BI.extend({}, options, item); |
|
w = BI.Plugin.getWidget(el.type, el); |
|
w.listeners = (w.listeners || []).concat([{ |
|
eventName: BI.Events.MOUNT, |
|
action: function () { |
|
BI.Plugin.getObject(el.type, this); |
|
} |
|
}]); |
|
return w.type === el.type ? createWidget(w) : BI.createWidget(BI.extend({}, item, {type: w.type}, options)); |
|
} |
|
if (item.el && (item.el.type || options.type)) { |
|
el = BI.extend({}, options, item.el); |
|
w = BI.Plugin.getWidget(el.type, el); |
|
w.listeners = (w.listeners || []).concat([{ |
|
eventName: BI.Events.MOUNT, |
|
action: function () { |
|
BI.Plugin.getObject(el.type, this); |
|
} |
|
}]); |
|
return w.type === el.type ? createWidget(w) : BI.createWidget(BI.extend({}, item, {type: w.type}, options)); |
|
} |
|
if (BI.isWidget(item.el)) { |
|
return item.el; |
|
} |
|
throw new Error("无法根据item创建组件"); |
|
}; |
|
|
|
BI.createElement = function () { |
|
var widget = BI.createWidget.apply(this, arguments); |
|
return widget.element; |
|
}; |
|
|
|
})();!(function () { |
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
/** |
|
* CryptoJS core components. |
|
*/ |
|
BI.CRYPT_TYPE = BI.CRYPT_TYPE || {}; |
|
BI.CRYPT_TYPE.AES = "aes"; |
|
|
|
var CryptoJS = CryptoJS || (function (Math, undefined) { |
|
/** |
|
* CryptoJS namespace. |
|
*/ |
|
var C = {}; |
|
|
|
/** |
|
* Library namespace. |
|
*/ |
|
var C_lib = C.lib = {}; |
|
|
|
/** |
|
* Base object for prototypal inheritance. |
|
*/ |
|
var Base = C_lib.Base = (function () { |
|
function F () { |
|
} |
|
|
|
return { |
|
/** |
|
* Creates a new object that inherits from this object. |
|
* |
|
* @param {Object} overrides Properties to copy into the new object. |
|
* |
|
* @return {Object} The new object. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var MyType = CryptoJS.lib.Base.extend({ |
|
* field: 'value', |
|
* |
|
* method: function () { |
|
* } |
|
* }); |
|
*/ |
|
extend: function (overrides) { |
|
// Spawn |
|
F.prototype = this; |
|
var subtype = new F(); |
|
|
|
// Augment |
|
if (overrides) { |
|
subtype.mixIn(overrides); |
|
} |
|
|
|
// Create default initializer |
|
if (!subtype.hasOwnProperty('init')) { |
|
subtype.init = function () { |
|
subtype.$super.init.apply(this, arguments); |
|
}; |
|
} |
|
|
|
// Initializer's prototype is the subtype object |
|
subtype.init.prototype = subtype; |
|
|
|
// Reference supertype |
|
subtype.$super = this; |
|
|
|
return subtype; |
|
}, |
|
|
|
/** |
|
* Extends this object and runs the init method. |
|
* Arguments to create() will be passed to init(). |
|
* |
|
* @return {Object} The new object. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var instance = MyType.create(); |
|
*/ |
|
create: function () { |
|
var instance = this.extend(); |
|
instance.init.apply(instance, arguments); |
|
|
|
return instance; |
|
}, |
|
|
|
/** |
|
* Initializes a newly created object. |
|
* Override this method to add some logic when your objects are created. |
|
* |
|
* @example |
|
* |
|
* var MyType = CryptoJS.lib.Base.extend({ |
|
* init: function () { |
|
* // ... |
|
* } |
|
* }); |
|
*/ |
|
init: function () { |
|
}, |
|
|
|
/** |
|
* Copies properties into this object. |
|
* |
|
* @param {Object} properties The properties to mix in. |
|
* |
|
* @example |
|
* |
|
* MyType.mixIn({ |
|
* field: 'value' |
|
* }); |
|
*/ |
|
mixIn: function (properties) { |
|
for (var propertyName in properties) { |
|
if (properties.hasOwnProperty(propertyName)) { |
|
this[propertyName] = properties[propertyName]; |
|
} |
|
} |
|
|
|
// IE won't copy toString using the loop above |
|
if (properties.hasOwnProperty('toString')) { |
|
this.toString = properties.toString; |
|
} |
|
}, |
|
|
|
/** |
|
* Creates a copy of this object. |
|
* |
|
* @return {Object} The clone. |
|
* |
|
* @example |
|
* |
|
* var clone = instance.clone(); |
|
*/ |
|
clone: function () { |
|
return this.init.prototype.extend(this); |
|
} |
|
}; |
|
}()); |
|
|
|
/** |
|
* An array of 32-bit words. |
|
* |
|
* @property {Array} words The array of 32-bit words. |
|
* @property {number} sigBytes The number of significant bytes in this word array. |
|
*/ |
|
var WordArray = C_lib.WordArray = Base.extend({ |
|
/** |
|
* Initializes a newly created word array. |
|
* |
|
* @param {Array} words (Optional) An array of 32-bit words. |
|
* @param {number} sigBytes (Optional) The number of significant bytes in the words. |
|
* |
|
* @example |
|
* |
|
* var wordArray = CryptoJS.lib.WordArray.create(); |
|
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); |
|
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); |
|
*/ |
|
init: function (words, sigBytes) { |
|
words = this.words = words || []; |
|
|
|
if (sigBytes != undefined) { |
|
this.sigBytes = sigBytes; |
|
} else { |
|
this.sigBytes = words.length * 4; |
|
} |
|
}, |
|
|
|
/** |
|
* Converts this word array to a string. |
|
* |
|
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex |
|
* |
|
* @return {string} The stringified word array. |
|
* |
|
* @example |
|
* |
|
* var string = wordArray + ''; |
|
* var string = wordArray.toString(); |
|
* var string = wordArray.toString(CryptoJS.enc.Utf8); |
|
*/ |
|
toString: function (encoder) { |
|
return (encoder || Hex).stringify(this); |
|
}, |
|
|
|
/** |
|
* Concatenates a word array to this word array. |
|
* |
|
* @param {WordArray} wordArray The word array to append. |
|
* |
|
* @return {WordArray} This word array. |
|
* |
|
* @example |
|
* |
|
* wordArray1.concat(wordArray2); |
|
*/ |
|
concat: function (wordArray) { |
|
// Shortcuts |
|
var thisWords = this.words; |
|
var thatWords = wordArray.words; |
|
var thisSigBytes = this.sigBytes; |
|
var thatSigBytes = wordArray.sigBytes; |
|
|
|
// Clamp excess bits |
|
this.clamp(); |
|
|
|
// Concat |
|
if (thisSigBytes % 4) { |
|
// Copy one byte at a time |
|
for (var i = 0; i < thatSigBytes; i++) { |
|
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; |
|
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); |
|
} |
|
} else if (thatWords.length > 0xffff) { |
|
// Copy one word at a time |
|
for (var i = 0; i < thatSigBytes; i += 4) { |
|
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; |
|
} |
|
} else { |
|
// Copy all words at once |
|
thisWords.push.apply(thisWords, thatWords); |
|
} |
|
this.sigBytes += thatSigBytes; |
|
|
|
// Chainable |
|
return this; |
|
}, |
|
|
|
/** |
|
* Removes insignificant bits. |
|
* |
|
* @example |
|
* |
|
* wordArray.clamp(); |
|
*/ |
|
clamp: function () { |
|
// Shortcuts |
|
var words = this.words; |
|
var sigBytes = this.sigBytes; |
|
|
|
// Clamp |
|
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); |
|
words.length = Math.ceil(sigBytes / 4); |
|
}, |
|
|
|
/** |
|
* Creates a copy of this word array. |
|
* |
|
* @return {WordArray} The clone. |
|
* |
|
* @example |
|
* |
|
* var clone = wordArray.clone(); |
|
*/ |
|
clone: function () { |
|
var clone = Base.clone.call(this); |
|
clone.words = this.words.slice(0); |
|
|
|
return clone; |
|
}, |
|
|
|
/** |
|
* Creates a word array filled with random bytes. |
|
* |
|
* @param {number} nBytes The number of random bytes to generate. |
|
* |
|
* @return {WordArray} The random word array. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var wordArray = CryptoJS.lib.WordArray.random(16); |
|
*/ |
|
random: function (nBytes) { |
|
var words = []; |
|
for (var i = 0; i < nBytes; i += 4) { |
|
words.push((Math.random() * 0x100000000) | 0); |
|
} |
|
|
|
return new WordArray.init(words, nBytes); |
|
} |
|
}); |
|
|
|
/** |
|
* Encoder namespace. |
|
*/ |
|
var C_enc = C.enc = {}; |
|
|
|
/** |
|
* Hex encoding strategy. |
|
*/ |
|
var Hex = C_enc.Hex = { |
|
/** |
|
* Converts a word array to a hex string. |
|
* |
|
* @param {WordArray} wordArray The word array. |
|
* |
|
* @return {string} The hex string. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var hexString = CryptoJS.enc.Hex.stringify(wordArray); |
|
*/ |
|
stringify: function (wordArray) { |
|
// Shortcuts |
|
var words = wordArray.words; |
|
var sigBytes = wordArray.sigBytes; |
|
|
|
// Convert |
|
var hexChars = []; |
|
for (var i = 0; i < sigBytes; i++) { |
|
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; |
|
hexChars.push((bite >>> 4).toString(16)); |
|
hexChars.push((bite & 0x0f).toString(16)); |
|
} |
|
|
|
return hexChars.join(''); |
|
}, |
|
|
|
/** |
|
* Converts a hex string to a word array. |
|
* |
|
* @param {string} hexStr The hex string. |
|
* |
|
* @return {WordArray} The word array. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var wordArray = CryptoJS.enc.Hex.parse(hexString); |
|
*/ |
|
parse: function (hexStr) { |
|
// Shortcut |
|
var hexStrLength = hexStr.length; |
|
|
|
// Convert |
|
var words = []; |
|
for (var i = 0; i < hexStrLength; i += 2) { |
|
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); |
|
} |
|
|
|
return new WordArray.init(words, hexStrLength / 2); |
|
} |
|
}; |
|
|
|
/** |
|
* Latin1 encoding strategy. |
|
*/ |
|
var Latin1 = C_enc.Latin1 = { |
|
/** |
|
* Converts a word array to a Latin1 string. |
|
* |
|
* @param {WordArray} wordArray The word array. |
|
* |
|
* @return {string} The Latin1 string. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); |
|
*/ |
|
stringify: function (wordArray) { |
|
// Shortcuts |
|
var words = wordArray.words; |
|
var sigBytes = wordArray.sigBytes; |
|
|
|
// Convert |
|
var latin1Chars = []; |
|
for (var i = 0; i < sigBytes; i++) { |
|
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; |
|
latin1Chars.push(String.fromCharCode(bite)); |
|
} |
|
|
|
return latin1Chars.join(''); |
|
}, |
|
|
|
/** |
|
* Converts a Latin1 string to a word array. |
|
* |
|
* @param {string} latin1Str The Latin1 string. |
|
* |
|
* @return {WordArray} The word array. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String); |
|
*/ |
|
parse: function (latin1Str) { |
|
// Shortcut |
|
var latin1StrLength = latin1Str.length; |
|
|
|
// Convert |
|
var words = []; |
|
for (var i = 0; i < latin1StrLength; i++) { |
|
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); |
|
} |
|
|
|
return new WordArray.init(words, latin1StrLength); |
|
} |
|
}; |
|
|
|
/** |
|
* UTF-8 encoding strategy. |
|
*/ |
|
var Utf8 = C_enc.Utf8 = { |
|
/** |
|
* Converts a word array to a UTF-8 string. |
|
* |
|
* @param {WordArray} wordArray The word array. |
|
* |
|
* @return {string} The UTF-8 string. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); |
|
*/ |
|
stringify: function (wordArray) { |
|
try { |
|
return decodeURIComponent(escape(Latin1.stringify(wordArray))); |
|
} catch (e) { |
|
throw new Error('Malformed UTF-8 data'); |
|
} |
|
}, |
|
|
|
/** |
|
* Converts a UTF-8 string to a word array. |
|
* |
|
* @param {string} utf8Str The UTF-8 string. |
|
* |
|
* @return {WordArray} The word array. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String); |
|
*/ |
|
parse: function (utf8Str) { |
|
return Latin1.parse(unescape(encodeURIComponent(utf8Str))); |
|
} |
|
}; |
|
|
|
/** |
|
* Abstract buffered block algorithm template. |
|
* |
|
* The property blockSize must be implemented in a concrete subtype. |
|
* |
|
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 |
|
*/ |
|
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ |
|
/** |
|
* Resets this block algorithm's data buffer to its initial state. |
|
* |
|
* @example |
|
* |
|
* bufferedBlockAlgorithm.reset(); |
|
*/ |
|
reset: function () { |
|
// Initial values |
|
this._data = new WordArray.init(); |
|
this._nDataBytes = 0; |
|
}, |
|
|
|
/** |
|
* Adds new data to this block algorithm's buffer. |
|
* |
|
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. |
|
* |
|
* @example |
|
* |
|
* bufferedBlockAlgorithm._append('data'); |
|
* bufferedBlockAlgorithm._append(wordArray); |
|
*/ |
|
_append: function (data) { |
|
// Convert string to WordArray, else assume WordArray already |
|
if (typeof data == 'string') { |
|
data = Utf8.parse(data); |
|
} |
|
|
|
// Append |
|
this._data.concat(data); |
|
this._nDataBytes += data.sigBytes; |
|
}, |
|
|
|
/** |
|
* Processes available data blocks. |
|
* |
|
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. |
|
* |
|
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed. |
|
* |
|
* @return {WordArray} The processed data. |
|
* |
|
* @example |
|
* |
|
* var processedData = bufferedBlockAlgorithm._process(); |
|
* var processedData = bufferedBlockAlgorithm._process(!!'flush'); |
|
*/ |
|
_process: function (doFlush) { |
|
// Shortcuts |
|
var data = this._data; |
|
var dataWords = data.words; |
|
var dataSigBytes = data.sigBytes; |
|
var blockSize = this.blockSize; |
|
var blockSizeBytes = blockSize * 4; |
|
|
|
// Count blocks ready |
|
var nBlocksReady = dataSigBytes / blockSizeBytes; |
|
if (doFlush) { |
|
// Round up to include partial blocks |
|
nBlocksReady = Math.ceil(nBlocksReady); |
|
} else { |
|
// Round down to include only full blocks, |
|
// less the number of blocks that must remain in the buffer |
|
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); |
|
} |
|
|
|
// Count words ready |
|
var nWordsReady = nBlocksReady * blockSize; |
|
|
|
// Count bytes ready |
|
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); |
|
|
|
// Process blocks |
|
if (nWordsReady) { |
|
for (var offset = 0; offset < nWordsReady; offset += blockSize) { |
|
// Perform concrete-algorithm logic |
|
this._doProcessBlock(dataWords, offset); |
|
} |
|
|
|
// Remove processed words |
|
var processedWords = dataWords.splice(0, nWordsReady); |
|
data.sigBytes -= nBytesReady; |
|
} |
|
|
|
// Return processed words |
|
return new WordArray.init(processedWords, nBytesReady); |
|
}, |
|
|
|
/** |
|
* Creates a copy of this object. |
|
* |
|
* @return {Object} The clone. |
|
* |
|
* @example |
|
* |
|
* var clone = bufferedBlockAlgorithm.clone(); |
|
*/ |
|
clone: function () { |
|
var clone = Base.clone.call(this); |
|
clone._data = this._data.clone(); |
|
|
|
return clone; |
|
}, |
|
|
|
_minBufferSize: 0 |
|
}); |
|
|
|
/** |
|
* Abstract hasher template. |
|
* |
|
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) |
|
*/ |
|
var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ |
|
/** |
|
* Configuration options. |
|
*/ |
|
cfg: Base.extend(), |
|
|
|
/** |
|
* Initializes a newly created hasher. |
|
* |
|
* @param {Object} cfg (Optional) The configuration options to use for this hash computation. |
|
* |
|
* @example |
|
* |
|
* var hasher = CryptoJS.algo.SHA256.create(); |
|
*/ |
|
init: function (cfg) { |
|
// Apply config defaults |
|
this.cfg = this.cfg.extend(cfg); |
|
|
|
// Set initial values |
|
this.reset(); |
|
}, |
|
|
|
/** |
|
* Resets this hasher to its initial state. |
|
* |
|
* @example |
|
* |
|
* hasher.reset(); |
|
*/ |
|
reset: function () { |
|
// Reset data buffer |
|
BufferedBlockAlgorithm.reset.call(this); |
|
|
|
// Perform concrete-hasher logic |
|
this._doReset(); |
|
}, |
|
|
|
/** |
|
* Updates this hasher with a message. |
|
* |
|
* @param {WordArray|string} messageUpdate The message to append. |
|
* |
|
* @return {Hasher} This hasher. |
|
* |
|
* @example |
|
* |
|
* hasher.update('message'); |
|
* hasher.update(wordArray); |
|
*/ |
|
update: function (messageUpdate) { |
|
// Append |
|
this._append(messageUpdate); |
|
|
|
// Update the hash |
|
this._process(); |
|
|
|
// Chainable |
|
return this; |
|
}, |
|
|
|
/** |
|
* Finalizes the hash computation. |
|
* Note that the finalize operation is effectively a destructive, read-once operation. |
|
* |
|
* @param {WordArray|string} messageUpdate (Optional) A final message update. |
|
* |
|
* @return {WordArray} The hash. |
|
* |
|
* @example |
|
* |
|
* var hash = hasher.finalize(); |
|
* var hash = hasher.finalize('message'); |
|
* var hash = hasher.finalize(wordArray); |
|
*/ |
|
finalize: function (messageUpdate) { |
|
// Final message update |
|
if (messageUpdate) { |
|
this._append(messageUpdate); |
|
} |
|
|
|
// Perform concrete-hasher logic |
|
var hash = this._doFinalize(); |
|
|
|
return hash; |
|
}, |
|
|
|
blockSize: 512 / 32, |
|
|
|
/** |
|
* Creates a shortcut function to a hasher's object interface. |
|
* |
|
* @param {Hasher} hasher The hasher to create a helper for. |
|
* |
|
* @return {Function} The shortcut function. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); |
|
*/ |
|
_createHelper: function (hasher) { |
|
return function (message, cfg) { |
|
return new hasher.init(cfg).finalize(message); |
|
}; |
|
}, |
|
|
|
/** |
|
* Creates a shortcut function to the HMAC's object interface. |
|
* |
|
* @param {Hasher} hasher The hasher to use in this HMAC helper. |
|
* |
|
* @return {Function} The shortcut function. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); |
|
*/ |
|
_createHmacHelper: function (hasher) { |
|
return function (message, key) { |
|
return new C_algo.HMAC.init(hasher, key).finalize(message); |
|
}; |
|
} |
|
}); |
|
|
|
/** |
|
* Algorithm namespace. |
|
*/ |
|
var C_algo = C.algo = {}; |
|
|
|
return C; |
|
}(Math)); |
|
|
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
(function () { |
|
// Shortcuts |
|
var C = CryptoJS; |
|
var C_lib = C.lib; |
|
var WordArray = C_lib.WordArray; |
|
var C_enc = C.enc; |
|
|
|
/** |
|
* Base64 encoding strategy. |
|
*/ |
|
var Base64 = C_enc.Base64 = { |
|
/** |
|
* Converts a word array to a Base64 string. |
|
* |
|
* @param {WordArray} wordArray The word array. |
|
* |
|
* @return {string} The Base64 string. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var base64String = CryptoJS.enc.Base64.stringify(wordArray); |
|
*/ |
|
stringify: function (wordArray) { |
|
// Shortcuts |
|
var words = wordArray.words; |
|
var sigBytes = wordArray.sigBytes; |
|
var map = this._map; |
|
|
|
// Clamp excess bits |
|
wordArray.clamp(); |
|
|
|
// Convert |
|
var base64Chars = []; |
|
for (var i = 0; i < sigBytes; i += 3) { |
|
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; |
|
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; |
|
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; |
|
|
|
var triplet = (byte1 << 16) | (byte2 << 8) | byte3; |
|
|
|
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { |
|
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); |
|
} |
|
} |
|
|
|
// Add padding |
|
var paddingChar = map.charAt(64); |
|
if (paddingChar) { |
|
while (base64Chars.length % 4) { |
|
base64Chars.push(paddingChar); |
|
} |
|
} |
|
|
|
return base64Chars.join(''); |
|
}, |
|
|
|
/** |
|
* Converts a Base64 string to a word array. |
|
* |
|
* @param {string} base64Str The Base64 string. |
|
* |
|
* @return {WordArray} The word array. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var wordArray = CryptoJS.enc.Base64.parse(base64String); |
|
*/ |
|
parse: function (base64Str) { |
|
// Shortcuts |
|
var base64StrLength = base64Str.length; |
|
var map = this._map; |
|
|
|
// Ignore padding |
|
var paddingChar = map.charAt(64); |
|
if (paddingChar) { |
|
var paddingIndex = base64Str.indexOf(paddingChar); |
|
if (paddingIndex != -1) { |
|
base64StrLength = paddingIndex; |
|
} |
|
} |
|
|
|
// Convert |
|
var words = []; |
|
var nBytes = 0; |
|
for (var i = 0; i < base64StrLength; i++) { |
|
if (i % 4) { |
|
var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2); |
|
var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2); |
|
words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8); |
|
nBytes++; |
|
} |
|
} |
|
|
|
return WordArray.create(words, nBytes); |
|
}, |
|
|
|
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' |
|
}; |
|
}()); |
|
|
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
(function (Math) { |
|
// Shortcuts |
|
var C = CryptoJS; |
|
var C_lib = C.lib; |
|
var WordArray = C_lib.WordArray; |
|
var Hasher = C_lib.Hasher; |
|
var C_algo = C.algo; |
|
|
|
// Constants table |
|
var T = []; |
|
|
|
// Compute constants |
|
(function () { |
|
for (var i = 0; i < 64; i++) { |
|
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; |
|
} |
|
}()); |
|
|
|
/** |
|
* MD5 hash algorithm. |
|
*/ |
|
var MD5 = C_algo.MD5 = Hasher.extend({ |
|
_doReset: function () { |
|
this._hash = new WordArray.init([ |
|
0x67452301, 0xefcdab89, |
|
0x98badcfe, 0x10325476 |
|
]); |
|
}, |
|
|
|
_doProcessBlock: function (M, offset) { |
|
// Swap endian |
|
for (var i = 0; i < 16; i++) { |
|
// Shortcuts |
|
var offset_i = offset + i; |
|
var M_offset_i = M[offset_i]; |
|
|
|
M[offset_i] = ( |
|
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | |
|
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) |
|
); |
|
} |
|
|
|
// Shortcuts |
|
var H = this._hash.words; |
|
|
|
var M_offset_0 = M[offset + 0]; |
|
var M_offset_1 = M[offset + 1]; |
|
var M_offset_2 = M[offset + 2]; |
|
var M_offset_3 = M[offset + 3]; |
|
var M_offset_4 = M[offset + 4]; |
|
var M_offset_5 = M[offset + 5]; |
|
var M_offset_6 = M[offset + 6]; |
|
var M_offset_7 = M[offset + 7]; |
|
var M_offset_8 = M[offset + 8]; |
|
var M_offset_9 = M[offset + 9]; |
|
var M_offset_10 = M[offset + 10]; |
|
var M_offset_11 = M[offset + 11]; |
|
var M_offset_12 = M[offset + 12]; |
|
var M_offset_13 = M[offset + 13]; |
|
var M_offset_14 = M[offset + 14]; |
|
var M_offset_15 = M[offset + 15]; |
|
|
|
// Working varialbes |
|
var a = H[0]; |
|
var b = H[1]; |
|
var c = H[2]; |
|
var d = H[3]; |
|
|
|
// Computation |
|
a = FF(a, b, c, d, M_offset_0, 7, T[0]); |
|
d = FF(d, a, b, c, M_offset_1, 12, T[1]); |
|
c = FF(c, d, a, b, M_offset_2, 17, T[2]); |
|
b = FF(b, c, d, a, M_offset_3, 22, T[3]); |
|
a = FF(a, b, c, d, M_offset_4, 7, T[4]); |
|
d = FF(d, a, b, c, M_offset_5, 12, T[5]); |
|
c = FF(c, d, a, b, M_offset_6, 17, T[6]); |
|
b = FF(b, c, d, a, M_offset_7, 22, T[7]); |
|
a = FF(a, b, c, d, M_offset_8, 7, T[8]); |
|
d = FF(d, a, b, c, M_offset_9, 12, T[9]); |
|
c = FF(c, d, a, b, M_offset_10, 17, T[10]); |
|
b = FF(b, c, d, a, M_offset_11, 22, T[11]); |
|
a = FF(a, b, c, d, M_offset_12, 7, T[12]); |
|
d = FF(d, a, b, c, M_offset_13, 12, T[13]); |
|
c = FF(c, d, a, b, M_offset_14, 17, T[14]); |
|
b = FF(b, c, d, a, M_offset_15, 22, T[15]); |
|
|
|
a = GG(a, b, c, d, M_offset_1, 5, T[16]); |
|
d = GG(d, a, b, c, M_offset_6, 9, T[17]); |
|
c = GG(c, d, a, b, M_offset_11, 14, T[18]); |
|
b = GG(b, c, d, a, M_offset_0, 20, T[19]); |
|
a = GG(a, b, c, d, M_offset_5, 5, T[20]); |
|
d = GG(d, a, b, c, M_offset_10, 9, T[21]); |
|
c = GG(c, d, a, b, M_offset_15, 14, T[22]); |
|
b = GG(b, c, d, a, M_offset_4, 20, T[23]); |
|
a = GG(a, b, c, d, M_offset_9, 5, T[24]); |
|
d = GG(d, a, b, c, M_offset_14, 9, T[25]); |
|
c = GG(c, d, a, b, M_offset_3, 14, T[26]); |
|
b = GG(b, c, d, a, M_offset_8, 20, T[27]); |
|
a = GG(a, b, c, d, M_offset_13, 5, T[28]); |
|
d = GG(d, a, b, c, M_offset_2, 9, T[29]); |
|
c = GG(c, d, a, b, M_offset_7, 14, T[30]); |
|
b = GG(b, c, d, a, M_offset_12, 20, T[31]); |
|
|
|
a = HH(a, b, c, d, M_offset_5, 4, T[32]); |
|
d = HH(d, a, b, c, M_offset_8, 11, T[33]); |
|
c = HH(c, d, a, b, M_offset_11, 16, T[34]); |
|
b = HH(b, c, d, a, M_offset_14, 23, T[35]); |
|
a = HH(a, b, c, d, M_offset_1, 4, T[36]); |
|
d = HH(d, a, b, c, M_offset_4, 11, T[37]); |
|
c = HH(c, d, a, b, M_offset_7, 16, T[38]); |
|
b = HH(b, c, d, a, M_offset_10, 23, T[39]); |
|
a = HH(a, b, c, d, M_offset_13, 4, T[40]); |
|
d = HH(d, a, b, c, M_offset_0, 11, T[41]); |
|
c = HH(c, d, a, b, M_offset_3, 16, T[42]); |
|
b = HH(b, c, d, a, M_offset_6, 23, T[43]); |
|
a = HH(a, b, c, d, M_offset_9, 4, T[44]); |
|
d = HH(d, a, b, c, M_offset_12, 11, T[45]); |
|
c = HH(c, d, a, b, M_offset_15, 16, T[46]); |
|
b = HH(b, c, d, a, M_offset_2, 23, T[47]); |
|
|
|
a = II(a, b, c, d, M_offset_0, 6, T[48]); |
|
d = II(d, a, b, c, M_offset_7, 10, T[49]); |
|
c = II(c, d, a, b, M_offset_14, 15, T[50]); |
|
b = II(b, c, d, a, M_offset_5, 21, T[51]); |
|
a = II(a, b, c, d, M_offset_12, 6, T[52]); |
|
d = II(d, a, b, c, M_offset_3, 10, T[53]); |
|
c = II(c, d, a, b, M_offset_10, 15, T[54]); |
|
b = II(b, c, d, a, M_offset_1, 21, T[55]); |
|
a = II(a, b, c, d, M_offset_8, 6, T[56]); |
|
d = II(d, a, b, c, M_offset_15, 10, T[57]); |
|
c = II(c, d, a, b, M_offset_6, 15, T[58]); |
|
b = II(b, c, d, a, M_offset_13, 21, T[59]); |
|
a = II(a, b, c, d, M_offset_4, 6, T[60]); |
|
d = II(d, a, b, c, M_offset_11, 10, T[61]); |
|
c = II(c, d, a, b, M_offset_2, 15, T[62]); |
|
b = II(b, c, d, a, M_offset_9, 21, T[63]); |
|
|
|
// Intermediate hash value |
|
H[0] = (H[0] + a) | 0; |
|
H[1] = (H[1] + b) | 0; |
|
H[2] = (H[2] + c) | 0; |
|
H[3] = (H[3] + d) | 0; |
|
}, |
|
|
|
_doFinalize: function () { |
|
// Shortcuts |
|
var data = this._data; |
|
var dataWords = data.words; |
|
|
|
var nBitsTotal = this._nDataBytes * 8; |
|
var nBitsLeft = data.sigBytes * 8; |
|
|
|
// Add padding |
|
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); |
|
|
|
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); |
|
var nBitsTotalL = nBitsTotal; |
|
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( |
|
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | |
|
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) |
|
); |
|
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( |
|
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | |
|
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) |
|
); |
|
|
|
data.sigBytes = (dataWords.length + 1) * 4; |
|
|
|
// Hash final blocks |
|
this._process(); |
|
|
|
// Shortcuts |
|
var hash = this._hash; |
|
var H = hash.words; |
|
|
|
// Swap endian |
|
for (var i = 0; i < 4; i++) { |
|
// Shortcut |
|
var H_i = H[i]; |
|
|
|
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | |
|
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); |
|
} |
|
|
|
// Return final computed hash |
|
return hash; |
|
}, |
|
|
|
clone: function () { |
|
var clone = Hasher.clone.call(this); |
|
clone._hash = this._hash.clone(); |
|
|
|
return clone; |
|
} |
|
}); |
|
|
|
function FF (a, b, c, d, x, s, t) { |
|
var n = a + ((b & c) | (~b & d)) + x + t; |
|
return ((n << s) | (n >>> (32 - s))) + b; |
|
} |
|
|
|
function GG (a, b, c, d, x, s, t) { |
|
var n = a + ((b & d) | (c & ~d)) + x + t; |
|
return ((n << s) | (n >>> (32 - s))) + b; |
|
} |
|
|
|
function HH (a, b, c, d, x, s, t) { |
|
var n = a + (b ^ c ^ d) + x + t; |
|
return ((n << s) | (n >>> (32 - s))) + b; |
|
} |
|
|
|
function II (a, b, c, d, x, s, t) { |
|
var n = a + (c ^ (b | ~d)) + x + t; |
|
return ((n << s) | (n >>> (32 - s))) + b; |
|
} |
|
|
|
/** |
|
* Shortcut function to the hasher's object interface. |
|
* |
|
* @param {WordArray|string} message The message to hash. |
|
* |
|
* @return {WordArray} The hash. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var hash = CryptoJS.MD5('message'); |
|
* var hash = CryptoJS.MD5(wordArray); |
|
*/ |
|
C.MD5 = Hasher._createHelper(MD5); |
|
|
|
/** |
|
* Shortcut function to the HMAC's object interface. |
|
* |
|
* @param {WordArray|string} message The message to hash. |
|
* @param {WordArray|string} key The secret key. |
|
* |
|
* @return {WordArray} The HMAC. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var hmac = CryptoJS.HmacMD5(message, key); |
|
*/ |
|
C.HmacMD5 = Hasher._createHmacHelper(MD5); |
|
}(Math)); |
|
|
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
(function () { |
|
// Shortcuts |
|
var C = CryptoJS; |
|
var C_lib = C.lib; |
|
var Base = C_lib.Base; |
|
var WordArray = C_lib.WordArray; |
|
var C_algo = C.algo; |
|
var MD5 = C_algo.MD5; |
|
|
|
/** |
|
* This key derivation function is meant to conform with EVP_BytesToKey. |
|
* www.openssl.org/docs/crypto/EVP_BytesToKey.html |
|
*/ |
|
var EvpKDF = C_algo.EvpKDF = Base.extend({ |
|
/** |
|
* Configuration options. |
|
* |
|
* @property {number} keySize The key size in words to generate. Default: 4 (128 bits) |
|
* @property {Hasher} hasher The hash algorithm to use. Default: MD5 |
|
* @property {number} iterations The number of iterations to perform. Default: 1 |
|
*/ |
|
cfg: Base.extend({ |
|
keySize: 128 / 32, |
|
hasher: MD5, |
|
iterations: 1 |
|
}), |
|
|
|
/** |
|
* Initializes a newly created key derivation function. |
|
* |
|
* @param {Object} cfg (Optional) The configuration options to use for the derivation. |
|
* |
|
* @example |
|
* |
|
* var kdf = CryptoJS.algo.EvpKDF.create(); |
|
* var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); |
|
* var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); |
|
*/ |
|
init: function (cfg) { |
|
this.cfg = this.cfg.extend(cfg); |
|
}, |
|
|
|
/** |
|
* Derives a key from a password. |
|
* |
|
* @param {WordArray|string} password The password. |
|
* @param {WordArray|string} salt A salt. |
|
* |
|
* @return {WordArray} The derived key. |
|
* |
|
* @example |
|
* |
|
* var key = kdf.compute(password, salt); |
|
*/ |
|
compute: function (password, salt) { |
|
// Shortcut |
|
var cfg = this.cfg; |
|
|
|
// Init hasher |
|
var hasher = cfg.hasher.create(); |
|
|
|
// Initial values |
|
var derivedKey = WordArray.create(); |
|
|
|
// Shortcuts |
|
var derivedKeyWords = derivedKey.words; |
|
var keySize = cfg.keySize; |
|
var iterations = cfg.iterations; |
|
|
|
// Generate key |
|
while (derivedKeyWords.length < keySize) { |
|
if (block) { |
|
hasher.update(block); |
|
} |
|
var block = hasher.update(password).finalize(salt); |
|
hasher.reset(); |
|
|
|
// Iterations |
|
for (var i = 1; i < iterations; i++) { |
|
block = hasher.finalize(block); |
|
hasher.reset(); |
|
} |
|
|
|
derivedKey.concat(block); |
|
} |
|
derivedKey.sigBytes = keySize * 4; |
|
|
|
return derivedKey; |
|
} |
|
}); |
|
|
|
/** |
|
* Derives a key from a password. |
|
* |
|
* @param {WordArray|string} password The password. |
|
* @param {WordArray|string} salt A salt. |
|
* @param {Object} cfg (Optional) The configuration options to use for this computation. |
|
* |
|
* @return {WordArray} The derived key. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var key = CryptoJS.EvpKDF(password, salt); |
|
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); |
|
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); |
|
*/ |
|
C.EvpKDF = function (password, salt, cfg) { |
|
return EvpKDF.create(cfg).compute(password, salt); |
|
}; |
|
}()); |
|
|
|
|
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
/** |
|
* Cipher core components. |
|
*/ |
|
CryptoJS.lib.Cipher || (function (undefined) { |
|
// Shortcuts |
|
var C = CryptoJS; |
|
var C_lib = C.lib; |
|
var Base = C_lib.Base; |
|
var WordArray = C_lib.WordArray; |
|
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; |
|
var C_enc = C.enc; |
|
var Utf8 = C_enc.Utf8; |
|
var Base64 = C_enc.Base64; |
|
var C_algo = C.algo; |
|
var EvpKDF = C_algo.EvpKDF; |
|
|
|
/** |
|
* Abstract base cipher template. |
|
* |
|
* @property {number} keySize This cipher's key size. Default: 4 (128 bits) |
|
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) |
|
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode. |
|
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode. |
|
*/ |
|
var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ |
|
/** |
|
* Configuration options. |
|
* |
|
* @property {WordArray} iv The IV to use for this operation. |
|
*/ |
|
cfg: Base.extend(), |
|
|
|
/** |
|
* Creates this cipher in encryption mode. |
|
* |
|
* @param {WordArray} key The key. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @return {Cipher} A cipher instance. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); |
|
*/ |
|
createEncryptor: function (key, cfg) { |
|
return this.create(this._ENC_XFORM_MODE, key, cfg); |
|
}, |
|
|
|
/** |
|
* Creates this cipher in decryption mode. |
|
* |
|
* @param {WordArray} key The key. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @return {Cipher} A cipher instance. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); |
|
*/ |
|
createDecryptor: function (key, cfg) { |
|
return this.create(this._DEC_XFORM_MODE, key, cfg); |
|
}, |
|
|
|
/** |
|
* Initializes a newly created cipher. |
|
* |
|
* @param {number} xformMode Either the encryption or decryption transormation mode constant. |
|
* @param {WordArray} key The key. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @example |
|
* |
|
* var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); |
|
*/ |
|
init: function (xformMode, key, cfg) { |
|
// Apply config defaults |
|
this.cfg = this.cfg.extend(cfg); |
|
|
|
// Store transform mode and key |
|
this._xformMode = xformMode; |
|
this._key = key; |
|
|
|
// Set initial values |
|
this.reset(); |
|
}, |
|
|
|
/** |
|
* Resets this cipher to its initial state. |
|
* |
|
* @example |
|
* |
|
* cipher.reset(); |
|
*/ |
|
reset: function () { |
|
// Reset data buffer |
|
BufferedBlockAlgorithm.reset.call(this); |
|
|
|
// Perform concrete-cipher logic |
|
this._doReset(); |
|
}, |
|
|
|
/** |
|
* Adds data to be encrypted or decrypted. |
|
* |
|
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt. |
|
* |
|
* @return {WordArray} The data after processing. |
|
* |
|
* @example |
|
* |
|
* var encrypted = cipher.process('data'); |
|
* var encrypted = cipher.process(wordArray); |
|
*/ |
|
process: function (dataUpdate) { |
|
// Append |
|
this._append(dataUpdate); |
|
|
|
// Process available blocks |
|
return this._process(); |
|
}, |
|
|
|
/** |
|
* Finalizes the encryption or decryption process. |
|
* Note that the finalize operation is effectively a destructive, read-once operation. |
|
* |
|
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. |
|
* |
|
* @return {WordArray} The data after final processing. |
|
* |
|
* @example |
|
* |
|
* var encrypted = cipher.finalize(); |
|
* var encrypted = cipher.finalize('data'); |
|
* var encrypted = cipher.finalize(wordArray); |
|
*/ |
|
finalize: function (dataUpdate) { |
|
// Final data update |
|
if (dataUpdate) { |
|
this._append(dataUpdate); |
|
} |
|
|
|
// Perform concrete-cipher logic |
|
var finalProcessedData = this._doFinalize(); |
|
|
|
return finalProcessedData; |
|
}, |
|
|
|
keySize: 128 / 32, |
|
|
|
ivSize: 128 / 32, |
|
|
|
_ENC_XFORM_MODE: 1, |
|
|
|
_DEC_XFORM_MODE: 2, |
|
|
|
/** |
|
* Creates shortcut functions to a cipher's object interface. |
|
* |
|
* @param {Cipher} cipher The cipher to create a helper for. |
|
* |
|
* @return {Object} An object with encrypt and decrypt shortcut functions. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); |
|
*/ |
|
_createHelper: (function () { |
|
function selectCipherStrategy (key) { |
|
if (typeof key == 'string') { |
|
return PasswordBasedCipher; |
|
} else { |
|
return SerializableCipher; |
|
} |
|
} |
|
|
|
return function (cipher) { |
|
return { |
|
encrypt: function (message, key, cfg) { |
|
return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); |
|
}, |
|
|
|
decrypt: function (ciphertext, key, cfg) { |
|
return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); |
|
} |
|
}; |
|
}; |
|
}()) |
|
}); |
|
|
|
/** |
|
* Abstract base stream cipher template. |
|
* |
|
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) |
|
*/ |
|
var StreamCipher = C_lib.StreamCipher = Cipher.extend({ |
|
_doFinalize: function () { |
|
// Process partial blocks |
|
var finalProcessedBlocks = this._process(!!'flush'); |
|
|
|
return finalProcessedBlocks; |
|
}, |
|
|
|
blockSize: 1 |
|
}); |
|
|
|
/** |
|
* Mode namespace. |
|
*/ |
|
var C_mode = C.mode = {}; |
|
|
|
/** |
|
* Abstract base block cipher mode template. |
|
*/ |
|
var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ |
|
/** |
|
* Creates this mode for encryption. |
|
* |
|
* @param {Cipher} cipher A block cipher instance. |
|
* @param {Array} iv The IV words. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); |
|
*/ |
|
createEncryptor: function (cipher, iv) { |
|
return this.Encryptor.create(cipher, iv); |
|
}, |
|
|
|
/** |
|
* Creates this mode for decryption. |
|
* |
|
* @param {Cipher} cipher A block cipher instance. |
|
* @param {Array} iv The IV words. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); |
|
*/ |
|
createDecryptor: function (cipher, iv) { |
|
return this.Decryptor.create(cipher, iv); |
|
}, |
|
|
|
/** |
|
* Initializes a newly created mode. |
|
* |
|
* @param {Cipher} cipher A block cipher instance. |
|
* @param {Array} iv The IV words. |
|
* |
|
* @example |
|
* |
|
* var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); |
|
*/ |
|
init: function (cipher, iv) { |
|
this._cipher = cipher; |
|
this._iv = iv; |
|
} |
|
}); |
|
|
|
/** |
|
* Cipher Block Chaining mode. |
|
*/ |
|
var CBC = C_mode.CBC = (function () { |
|
/** |
|
* Abstract base CBC mode. |
|
*/ |
|
var CBC = BlockCipherMode.extend(); |
|
|
|
/** |
|
* CBC encryptor. |
|
*/ |
|
CBC.Encryptor = CBC.extend({ |
|
/** |
|
* Processes the data block at offset. |
|
* |
|
* @param {Array} words The data words to operate on. |
|
* @param {number} offset The offset where the block starts. |
|
* |
|
* @example |
|
* |
|
* mode.processBlock(data.words, offset); |
|
*/ |
|
processBlock: function (words, offset) { |
|
// Shortcuts |
|
var cipher = this._cipher; |
|
var blockSize = cipher.blockSize; |
|
|
|
// XOR and encrypt |
|
xorBlock.call(this, words, offset, blockSize); |
|
cipher.encryptBlock(words, offset); |
|
|
|
// Remember this block to use with next block |
|
this._prevBlock = words.slice(offset, offset + blockSize); |
|
} |
|
}); |
|
|
|
/** |
|
* CBC decryptor. |
|
*/ |
|
CBC.Decryptor = CBC.extend({ |
|
/** |
|
* Processes the data block at offset. |
|
* |
|
* @param {Array} words The data words to operate on. |
|
* @param {number} offset The offset where the block starts. |
|
* |
|
* @example |
|
* |
|
* mode.processBlock(data.words, offset); |
|
*/ |
|
processBlock: function (words, offset) { |
|
// Shortcuts |
|
var cipher = this._cipher; |
|
var blockSize = cipher.blockSize; |
|
|
|
// Remember this block to use with next block |
|
var thisBlock = words.slice(offset, offset + blockSize); |
|
|
|
// Decrypt and XOR |
|
cipher.decryptBlock(words, offset); |
|
xorBlock.call(this, words, offset, blockSize); |
|
|
|
// This block becomes the previous block |
|
this._prevBlock = thisBlock; |
|
} |
|
}); |
|
|
|
function xorBlock (words, offset, blockSize) { |
|
// Shortcut |
|
var iv = this._iv; |
|
|
|
// Choose mixing block |
|
if (iv) { |
|
var block = iv; |
|
|
|
// Remove IV for subsequent blocks |
|
this._iv = undefined; |
|
} else { |
|
var block = this._prevBlock; |
|
} |
|
|
|
// XOR blocks |
|
for (var i = 0; i < blockSize; i++) { |
|
words[offset + i] ^= block[i]; |
|
} |
|
} |
|
|
|
return CBC; |
|
}()); |
|
|
|
/** |
|
* Padding namespace. |
|
*/ |
|
var C_pad = C.pad = {}; |
|
|
|
/** |
|
* PKCS #5/7 padding strategy. |
|
*/ |
|
var Pkcs7 = C_pad.Pkcs7 = { |
|
/** |
|
* Pads data using the algorithm defined in PKCS #5/7. |
|
* |
|
* @param {WordArray} data The data to pad. |
|
* @param {number} blockSize The multiple that the data should be padded to. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* CryptoJS.pad.Pkcs7.pad(wordArray, 4); |
|
*/ |
|
pad: function (data, blockSize) { |
|
// Shortcut |
|
var blockSizeBytes = blockSize * 4; |
|
|
|
// Count padding bytes |
|
var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; |
|
|
|
// Create padding word |
|
var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; |
|
|
|
// Create padding |
|
var paddingWords = []; |
|
for (var i = 0; i < nPaddingBytes; i += 4) { |
|
paddingWords.push(paddingWord); |
|
} |
|
var padding = WordArray.create(paddingWords, nPaddingBytes); |
|
|
|
// Add padding |
|
data.concat(padding); |
|
}, |
|
|
|
/** |
|
* Unpads data that had been padded using the algorithm defined in PKCS #5/7. |
|
* |
|
* @param {WordArray} data The data to unpad. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* CryptoJS.pad.Pkcs7.unpad(wordArray); |
|
*/ |
|
unpad: function (data) { |
|
// Get number of padding bytes from last byte |
|
var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; |
|
|
|
// Remove padding |
|
data.sigBytes -= nPaddingBytes; |
|
} |
|
}; |
|
|
|
/** |
|
* Abstract base block cipher template. |
|
* |
|
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) |
|
*/ |
|
var BlockCipher = C_lib.BlockCipher = Cipher.extend({ |
|
/** |
|
* Configuration options. |
|
* |
|
* @property {Mode} mode The block mode to use. Default: CBC |
|
* @property {Padding} padding The padding strategy to use. Default: Pkcs7 |
|
*/ |
|
cfg: Cipher.cfg.extend({ |
|
mode: CBC, |
|
padding: Pkcs7 |
|
}), |
|
|
|
reset: function () { |
|
// Reset cipher |
|
Cipher.reset.call(this); |
|
|
|
// Shortcuts |
|
var cfg = this.cfg; |
|
var iv = cfg.iv; |
|
var mode = cfg.mode; |
|
|
|
// Reset block mode |
|
if (this._xformMode == this._ENC_XFORM_MODE) { |
|
var modeCreator = mode.createEncryptor; |
|
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { |
|
var modeCreator = mode.createDecryptor; |
|
|
|
// Keep at least one block in the buffer for unpadding |
|
this._minBufferSize = 1; |
|
} |
|
this._mode = modeCreator.call(mode, this, iv && iv.words); |
|
}, |
|
|
|
_doProcessBlock: function (words, offset) { |
|
this._mode.processBlock(words, offset); |
|
}, |
|
|
|
_doFinalize: function () { |
|
// Shortcut |
|
var padding = this.cfg.padding; |
|
|
|
// Finalize |
|
if (this._xformMode == this._ENC_XFORM_MODE) { |
|
// Pad data |
|
padding.pad(this._data, this.blockSize); |
|
|
|
// Process final blocks |
|
var finalProcessedBlocks = this._process(!!'flush'); |
|
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { |
|
// Process final blocks |
|
var finalProcessedBlocks = this._process(!!'flush'); |
|
|
|
// Unpad data |
|
padding.unpad(finalProcessedBlocks); |
|
} |
|
|
|
return finalProcessedBlocks; |
|
}, |
|
|
|
blockSize: 128 / 32 |
|
}); |
|
|
|
/** |
|
* A collection of cipher parameters. |
|
* |
|
* @property {WordArray} ciphertext The raw ciphertext. |
|
* @property {WordArray} key The key to this ciphertext. |
|
* @property {WordArray} iv The IV used in the ciphering operation. |
|
* @property {WordArray} salt The salt used with a key derivation function. |
|
* @property {Cipher} algorithm The cipher algorithm. |
|
* @property {Mode} mode The block mode used in the ciphering operation. |
|
* @property {Padding} padding The padding scheme used in the ciphering operation. |
|
* @property {number} blockSize The block size of the cipher. |
|
* @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. |
|
*/ |
|
var CipherParams = C_lib.CipherParams = Base.extend({ |
|
/** |
|
* Initializes a newly created cipher params object. |
|
* |
|
* @param {Object} cipherParams An object with any of the possible cipher parameters. |
|
* |
|
* @example |
|
* |
|
* var cipherParams = CryptoJS.lib.CipherParams.create({ |
|
* ciphertext: ciphertextWordArray, |
|
* key: keyWordArray, |
|
* iv: ivWordArray, |
|
* salt: saltWordArray, |
|
* algorithm: CryptoJS.algo.AES, |
|
* mode: CryptoJS.mode.CBC, |
|
* padding: CryptoJS.pad.PKCS7, |
|
* blockSize: 4, |
|
* formatter: CryptoJS.format.OpenSSL |
|
* }); |
|
*/ |
|
init: function (cipherParams) { |
|
this.mixIn(cipherParams); |
|
}, |
|
|
|
/** |
|
* Converts this cipher params object to a string. |
|
* |
|
* @param {Format} formatter (Optional) The formatting strategy to use. |
|
* |
|
* @return {string} The stringified cipher params. |
|
* |
|
* @throws Error If neither the formatter nor the default formatter is set. |
|
* |
|
* @example |
|
* |
|
* var string = cipherParams + ''; |
|
* var string = cipherParams.toString(); |
|
* var string = cipherParams.toString(CryptoJS.format.OpenSSL); |
|
*/ |
|
toString: function (formatter) { |
|
return (formatter || this.formatter).stringify(this); |
|
} |
|
}); |
|
|
|
/** |
|
* Format namespace. |
|
*/ |
|
var C_format = C.format = {}; |
|
|
|
/** |
|
* OpenSSL formatting strategy. |
|
*/ |
|
var OpenSSLFormatter = C_format.OpenSSL = { |
|
/** |
|
* Converts a cipher params object to an OpenSSL-compatible string. |
|
* |
|
* @param {CipherParams} cipherParams The cipher params object. |
|
* |
|
* @return {string} The OpenSSL-compatible string. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); |
|
*/ |
|
stringify: function (cipherParams) { |
|
// Shortcuts |
|
var ciphertext = cipherParams.ciphertext; |
|
var salt = cipherParams.salt; |
|
|
|
// Format |
|
if (salt) { |
|
var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); |
|
} else { |
|
var wordArray = ciphertext; |
|
} |
|
|
|
return wordArray.toString(Base64); |
|
}, |
|
|
|
/** |
|
* Converts an OpenSSL-compatible string to a cipher params object. |
|
* |
|
* @param {string} openSSLStr The OpenSSL-compatible string. |
|
* |
|
* @return {CipherParams} The cipher params object. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); |
|
*/ |
|
parse: function (openSSLStr) { |
|
// Parse base64 |
|
var ciphertext = Base64.parse(openSSLStr); |
|
|
|
// Shortcut |
|
var ciphertextWords = ciphertext.words; |
|
|
|
// Test for salt |
|
if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { |
|
// Extract salt |
|
var salt = WordArray.create(ciphertextWords.slice(2, 4)); |
|
|
|
// Remove salt from ciphertext |
|
ciphertextWords.splice(0, 4); |
|
ciphertext.sigBytes -= 16; |
|
} |
|
|
|
return CipherParams.create({ciphertext: ciphertext, salt: salt}); |
|
} |
|
}; |
|
|
|
/** |
|
* A cipher wrapper that returns ciphertext as a serializable cipher params object. |
|
*/ |
|
var SerializableCipher = C_lib.SerializableCipher = Base.extend({ |
|
/** |
|
* Configuration options. |
|
* |
|
* @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL |
|
*/ |
|
cfg: Base.extend({ |
|
format: OpenSSLFormatter |
|
}), |
|
|
|
/** |
|
* Encrypts a message. |
|
* |
|
* @param {Cipher} cipher The cipher algorithm to use. |
|
* @param {WordArray|string} message The message to encrypt. |
|
* @param {WordArray} key The key. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @return {CipherParams} A cipher params object. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); |
|
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); |
|
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); |
|
*/ |
|
encrypt: function (cipher, message, key, cfg) { |
|
// Apply config defaults |
|
cfg = this.cfg.extend(cfg); |
|
|
|
// Encrypt |
|
var encryptor = cipher.createEncryptor(key, cfg); |
|
var ciphertext = encryptor.finalize(message); |
|
|
|
// Shortcut |
|
var cipherCfg = encryptor.cfg; |
|
|
|
// Create and return serializable cipher params |
|
return CipherParams.create({ |
|
ciphertext: ciphertext, |
|
key: key, |
|
iv: cipherCfg.iv, |
|
algorithm: cipher, |
|
mode: cipherCfg.mode, |
|
padding: cipherCfg.padding, |
|
blockSize: cipher.blockSize, |
|
formatter: cfg.format |
|
}); |
|
}, |
|
|
|
/** |
|
* Decrypts serialized ciphertext. |
|
* |
|
* @param {Cipher} cipher The cipher algorithm to use. |
|
* @param {CipherParams|string} ciphertext The ciphertext to decrypt. |
|
* @param {WordArray} key The key. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @return {WordArray} The plaintext. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); |
|
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); |
|
*/ |
|
decrypt: function (cipher, ciphertext, key, cfg) { |
|
// Apply config defaults |
|
cfg = this.cfg.extend(cfg); |
|
|
|
// Convert string to CipherParams |
|
ciphertext = this._parse(ciphertext, cfg.format); |
|
|
|
// Decrypt |
|
var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); |
|
|
|
return plaintext; |
|
}, |
|
|
|
/** |
|
* Converts serialized ciphertext to CipherParams, |
|
* else assumed CipherParams already and returns ciphertext unchanged. |
|
* |
|
* @param {CipherParams|string} ciphertext The ciphertext. |
|
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. |
|
* |
|
* @return {CipherParams} The unserialized ciphertext. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); |
|
*/ |
|
_parse: function (ciphertext, format) { |
|
if (typeof ciphertext == 'string') { |
|
return format.parse(ciphertext, this); |
|
} else { |
|
return ciphertext; |
|
} |
|
} |
|
}); |
|
|
|
/** |
|
* Key derivation function namespace. |
|
*/ |
|
var C_kdf = C.kdf = {}; |
|
|
|
/** |
|
* OpenSSL key derivation function. |
|
*/ |
|
var OpenSSLKdf = C_kdf.OpenSSL = { |
|
/** |
|
* Derives a key and IV from a password. |
|
* |
|
* @param {string} password The password to derive from. |
|
* @param {number} keySize The size in words of the key to generate. |
|
* @param {number} ivSize The size in words of the IV to generate. |
|
* @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. |
|
* |
|
* @return {CipherParams} A cipher params object with the key, IV, and salt. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); |
|
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); |
|
*/ |
|
execute: function (password, keySize, ivSize, salt) { |
|
// Generate random salt |
|
if (!salt) { |
|
salt = WordArray.random(64 / 8); |
|
} |
|
|
|
// Derive key and IV |
|
var key = EvpKDF.create({keySize: keySize + ivSize}).compute(password, salt); |
|
|
|
// Separate key and IV |
|
var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); |
|
key.sigBytes = keySize * 4; |
|
|
|
// Return params |
|
return CipherParams.create({key: key, iv: iv, salt: salt}); |
|
} |
|
}; |
|
|
|
/** |
|
* A serializable cipher wrapper that derives the key from a password, |
|
* and returns ciphertext as a serializable cipher params object. |
|
*/ |
|
var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ |
|
/** |
|
* Configuration options. |
|
* |
|
* @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL |
|
*/ |
|
cfg: SerializableCipher.cfg.extend({ |
|
kdf: OpenSSLKdf |
|
}), |
|
|
|
/** |
|
* Encrypts a message using a password. |
|
* |
|
* @param {Cipher} cipher The cipher algorithm to use. |
|
* @param {WordArray|string} message The message to encrypt. |
|
* @param {string} password The password. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @return {CipherParams} A cipher params object. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); |
|
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); |
|
*/ |
|
encrypt: function (cipher, message, password, cfg) { |
|
// Apply config defaults |
|
cfg = this.cfg.extend(cfg); |
|
|
|
// Derive key and other params |
|
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize); |
|
|
|
// Add IV to config |
|
cfg.iv = derivedParams.iv; |
|
|
|
// Encrypt |
|
var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); |
|
|
|
// Mix in derived params |
|
ciphertext.mixIn(derivedParams); |
|
|
|
return ciphertext; |
|
}, |
|
|
|
/** |
|
* Decrypts serialized ciphertext using a password. |
|
* |
|
* @param {Cipher} cipher The cipher algorithm to use. |
|
* @param {CipherParams|string} ciphertext The ciphertext to decrypt. |
|
* @param {string} password The password. |
|
* @param {Object} cfg (Optional) The configuration options to use for this operation. |
|
* |
|
* @return {WordArray} The plaintext. |
|
* |
|
* @static |
|
* |
|
* @example |
|
* |
|
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); |
|
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); |
|
*/ |
|
decrypt: function (cipher, ciphertext, password, cfg) { |
|
// Apply config defaults |
|
cfg = this.cfg.extend(cfg); |
|
|
|
// Convert string to CipherParams |
|
ciphertext = this._parse(ciphertext, cfg.format); |
|
|
|
// Derive key and other params |
|
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt); |
|
|
|
// Add IV to config |
|
cfg.iv = derivedParams.iv; |
|
|
|
// Decrypt |
|
var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); |
|
|
|
return plaintext; |
|
} |
|
}); |
|
}()); |
|
|
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
/** |
|
* Electronic Codebook block mode. |
|
*/ |
|
CryptoJS.mode.ECB = (function () { |
|
var ECB = CryptoJS.lib.BlockCipherMode.extend(); |
|
|
|
ECB.Encryptor = ECB.extend({ |
|
processBlock: function (words, offset) { |
|
this._cipher.encryptBlock(words, offset); |
|
} |
|
}); |
|
|
|
ECB.Decryptor = ECB.extend({ |
|
processBlock: function (words, offset) { |
|
this._cipher.decryptBlock(words, offset); |
|
} |
|
}); |
|
|
|
return ECB; |
|
}()); |
|
|
|
|
|
/* |
|
CryptoJS v3.1.2 |
|
code.google.com/p/crypto-js |
|
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|
code.google.com/p/crypto-js/wiki/License |
|
*/ |
|
(function () { |
|
// Shortcuts |
|
var C = CryptoJS; |
|
var C_lib = C.lib; |
|
var BlockCipher = C_lib.BlockCipher; |
|
var C_algo = C.algo; |
|
|
|
// Lookup tables |
|
var SBOX = []; |
|
var INV_SBOX = []; |
|
var SUB_MIX_0 = []; |
|
var SUB_MIX_1 = []; |
|
var SUB_MIX_2 = []; |
|
var SUB_MIX_3 = []; |
|
var INV_SUB_MIX_0 = []; |
|
var INV_SUB_MIX_1 = []; |
|
var INV_SUB_MIX_2 = []; |
|
var INV_SUB_MIX_3 = []; |
|
|
|
// Compute lookup tables |
|
(function () { |
|
// Compute double table |
|
var d = []; |
|
for (var i = 0; i < 256; i++) { |
|
if (i < 128) { |
|
d[i] = i << 1; |
|
} else { |
|
d[i] = (i << 1) ^ 0x11b; |
|
} |
|
} |
|
|
|
// Walk GF(2^8) |
|
var x = 0; |
|
var xi = 0; |
|
for (var i = 0; i < 256; i++) { |
|
// Compute sbox |
|
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); |
|
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; |
|
SBOX[x] = sx; |
|
INV_SBOX[sx] = x; |
|
|
|
// Compute multiplication |
|
var x2 = d[x]; |
|
var x4 = d[x2]; |
|
var x8 = d[x4]; |
|
|
|
// Compute sub bytes, mix columns tables |
|
var t = (d[sx] * 0x101) ^ (sx * 0x1010100); |
|
SUB_MIX_0[x] = (t << 24) | (t >>> 8); |
|
SUB_MIX_1[x] = (t << 16) | (t >>> 16); |
|
SUB_MIX_2[x] = (t << 8) | (t >>> 24); |
|
SUB_MIX_3[x] = t; |
|
|
|
// Compute inv sub bytes, inv mix columns tables |
|
var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); |
|
INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); |
|
INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); |
|
INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); |
|
INV_SUB_MIX_3[sx] = t; |
|
|
|
// Compute next counter |
|
if (!x) { |
|
x = xi = 1; |
|
} else { |
|
x = x2 ^ d[d[d[x8 ^ x2]]]; |
|
xi ^= d[d[xi]]; |
|
} |
|
} |
|
}()); |
|
|
|
// Precomputed Rcon lookup |
|
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; |
|
|
|
/** |
|
* AES block cipher algorithm. |
|
*/ |
|
var AES = C_algo.AES = BlockCipher.extend({ |
|
_doReset: function () { |
|
// Shortcuts |
|
var key = this._key; |
|
var keyWords = key.words; |
|
var keySize = key.sigBytes / 4; |
|
|
|
// Compute number of rounds |
|
var nRounds = this._nRounds = keySize + 6; |
|
|
|
// Compute number of key schedule rows |
|
var ksRows = (nRounds + 1) * 4; |
|
|
|
// Compute key schedule |
|
var keySchedule = this._keySchedule = []; |
|
for (var ksRow = 0; ksRow < ksRows; ksRow++) { |
|
if (ksRow < keySize) { |
|
keySchedule[ksRow] = keyWords[ksRow]; |
|
} else { |
|
var t = keySchedule[ksRow - 1]; |
|
|
|
if (!(ksRow % keySize)) { |
|
// Rot word |
|
t = (t << 8) | (t >>> 24); |
|
|
|
// Sub word |
|
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; |
|
|
|
// Mix Rcon |
|
t ^= RCON[(ksRow / keySize) | 0] << 24; |
|
} else if (keySize > 6 && ksRow % keySize == 4) { |
|
// Sub word |
|
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; |
|
} |
|
|
|
keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; |
|
} |
|
} |
|
|
|
// Compute inv key schedule |
|
var invKeySchedule = this._invKeySchedule = []; |
|
for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { |
|
var ksRow = ksRows - invKsRow; |
|
|
|
if (invKsRow % 4) { |
|
var t = keySchedule[ksRow]; |
|
} else { |
|
var t = keySchedule[ksRow - 4]; |
|
} |
|
|
|
if (invKsRow < 4 || ksRow <= 4) { |
|
invKeySchedule[invKsRow] = t; |
|
} else { |
|
invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ |
|
INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; |
|
} |
|
} |
|
}, |
|
|
|
encryptBlock: function (M, offset) { |
|
this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); |
|
}, |
|
|
|
decryptBlock: function (M, offset) { |
|
// Swap 2nd and 4th rows |
|
var t = M[offset + 1]; |
|
M[offset + 1] = M[offset + 3]; |
|
M[offset + 3] = t; |
|
|
|
this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); |
|
|
|
// Inv swap 2nd and 4th rows |
|
var t = M[offset + 1]; |
|
M[offset + 1] = M[offset + 3]; |
|
M[offset + 3] = t; |
|
}, |
|
|
|
_doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { |
|
// Shortcut |
|
var nRounds = this._nRounds; |
|
|
|
// Get input, add round key |
|
var s0 = M[offset] ^ keySchedule[0]; |
|
var s1 = M[offset + 1] ^ keySchedule[1]; |
|
var s2 = M[offset + 2] ^ keySchedule[2]; |
|
var s3 = M[offset + 3] ^ keySchedule[3]; |
|
|
|
// Key schedule row counter |
|
var ksRow = 4; |
|
|
|
// Rounds |
|
for (var round = 1; round < nRounds; round++) { |
|
// Shift rows, sub bytes, mix columns, add round key |
|
var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; |
|
var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; |
|
var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; |
|
var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; |
|
|
|
// Update state |
|
s0 = t0; |
|
s1 = t1; |
|
s2 = t2; |
|
s3 = t3; |
|
} |
|
|
|
// Shift rows, sub bytes, add round key |
|
var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; |
|
var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; |
|
var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; |
|
var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; |
|
|
|
// Set output |
|
M[offset] = t0; |
|
M[offset + 1] = t1; |
|
M[offset + 2] = t2; |
|
M[offset + 3] = t3; |
|
}, |
|
|
|
keySize: 256 / 32 |
|
}); |
|
|
|
/** |
|
* Shortcut functions to the cipher's object interface. |
|
* |
|
* @example |
|
* |
|
* var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); |
|
* var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); |
|
*/ |
|
C.AES = BlockCipher._createHelper(AES); |
|
}()); |
|
|
|
|
|
_.extend(BI, { |
|
/** |
|
* aes加密方法 |
|
* aes-128-ecb |
|
* |
|
* @example |
|
* |
|
* var ciphertext = BI.aesEncrypt(text, key); |
|
*/ |
|
aesEncrypt: function (text, key) { |
|
key = CryptoJS.enc.Utf8.parse(key); |
|
var cipher = CryptoJS.AES.encrypt(text, key, { |
|
mode: CryptoJS.mode.ECB, |
|
padding: CryptoJS.pad.Pkcs7 |
|
}); |
|
|
|
var base64Cipher = cipher.ciphertext.toString(CryptoJS.enc.Base64); |
|
return base64Cipher; |
|
}, |
|
|
|
/** |
|
* aes解密方法 |
|
* @param {String} text |
|
* @param {String} key |
|
*/ |
|
aesDecrypt: function (text, key) { |
|
key = CryptoJS.enc.Utf8.parse(key); |
|
var decipher = CryptoJS.AES.decrypt(text, key, { |
|
mode: CryptoJS.mode.ECB, |
|
padding: CryptoJS.pad.Pkcs7 |
|
}); |
|
|
|
return CryptoJS.enc.Utf8.stringify(decipher); |
|
} |
|
}); |
|
}());!(function () { |
|
function aspect (type) { |
|
return function (target, methodName, advice) { |
|
var exist = target[methodName], |
|
dispatcher; |
|
|
|
if (!exist || exist.target != target) { |
|
dispatcher = target[methodName] = function () { |
|
// before methods |
|
var beforeArr = dispatcher.before; |
|
var args = arguments, next; |
|
for (var l = beforeArr.length; l--;) { |
|
next = beforeArr[l].advice.apply(this, args); |
|
if (next === false) { |
|
return false; |
|
} |
|
args = next || args; |
|
} |
|
// target method |
|
var rs = dispatcher.method.apply(this, args); |
|
// after methods |
|
var afterArr = dispatcher.after; |
|
for (var i = 0, ii = afterArr.length; i < ii; i++) { |
|
next = afterArr[i].advice.call(this, rs, args); |
|
if (rs === false) { |
|
return false; |
|
} |
|
args = next || args; |
|
} |
|
return rs; |
|
}; |
|
|
|
dispatcher.before = []; |
|
dispatcher.after = []; |
|
|
|
if (exist) { |
|
dispatcher.method = exist; |
|
} |
|
dispatcher.target = target; |
|
} |
|
|
|
var aspectArr = (dispatcher || exist)[type]; |
|
var obj = { |
|
advice: advice, |
|
_index: aspectArr.length, |
|
remove: function () { |
|
aspectArr.splice(this._index, 1); |
|
} |
|
}; |
|
aspectArr.push(obj); |
|
|
|
return obj; |
|
}; |
|
} |
|
|
|
BI.aspect = { |
|
before: aspect("before"), |
|
after: aspect("after") |
|
}; |
|
|
|
return BI.aspect; |
|
|
|
})(); |
|
!(function () { |
|
|
|
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; |
|
|
|
|
|
// private method for UTF-8 encoding |
|
var _utf8_encode = function (string) { |
|
string = string.replace(/\r\n/g, "\n"); |
|
var utftext = ""; |
|
|
|
for (var n = 0; n < string.length; n++) { |
|
|
|
var c = string.charCodeAt(n); |
|
|
|
if (c < 128) { |
|
utftext += String.fromCharCode(c); |
|
} else if ((c > 127) && (c < 2048)) { |
|
utftext += String.fromCharCode((c >> 6) | 192); |
|
utftext += String.fromCharCode((c & 63) | 128); |
|
} else { |
|
utftext += String.fromCharCode((c >> 12) | 224); |
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128); |
|
utftext += String.fromCharCode((c & 63) | 128); |
|
} |
|
|
|
} |
|
|
|
return utftext; |
|
}; |
|
|
|
// private method for UTF-8 decoding |
|
var _utf8_decode = function (utftext) { |
|
var string = ""; |
|
var i = 0; |
|
var c = 0, c3 = 0, c2 = 0; |
|
|
|
while (i < utftext.length) { |
|
|
|
c = utftext.charCodeAt(i); |
|
|
|
if (c < 128) { |
|
string += String.fromCharCode(c); |
|
i++; |
|
} else if ((c > 191) && (c < 224)) { |
|
c2 = utftext.charCodeAt(i + 1); |
|
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); |
|
i += 2; |
|
} else { |
|
c2 = utftext.charCodeAt(i + 1); |
|
c3 = utftext.charCodeAt(i + 2); |
|
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); |
|
i += 3; |
|
} |
|
|
|
} |
|
return string; |
|
}; |
|
|
|
_.extend(BI, { |
|
|
|
encode: function (input) { |
|
var output = ""; |
|
var chr1, chr2, chr3, enc1, enc2, enc3, enc4; |
|
var i = 0; |
|
|
|
input = _utf8_encode(input); |
|
|
|
while (i < input.length) { |
|
|
|
chr1 = input.charCodeAt(i++); |
|
chr2 = input.charCodeAt(i++); |
|
chr3 = input.charCodeAt(i++); |
|
|
|
enc1 = chr1 >> 2; |
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); |
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); |
|
enc4 = chr3 & 63; |
|
|
|
if (isNaN(chr2)) { |
|
enc3 = enc4 = 64; |
|
} else if (isNaN(chr3)) { |
|
enc4 = 64; |
|
} |
|
|
|
output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4); |
|
|
|
} |
|
|
|
return output; |
|
}, |
|
|
|
// public method for decoding |
|
decode: function (input) { |
|
var output = ""; |
|
var chr1, chr2, chr3; |
|
var enc1, enc2, enc3, enc4; |
|
var i = 0; |
|
|
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); |
|
|
|
while (i < input.length) { |
|
|
|
enc1 = _keyStr.indexOf(input.charAt(i++)); |
|
enc2 = _keyStr.indexOf(input.charAt(i++)); |
|
enc3 = _keyStr.indexOf(input.charAt(i++)); |
|
enc4 = _keyStr.indexOf(input.charAt(i++)); |
|
|
|
chr1 = (enc1 << 2) | (enc2 >> 4); |
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); |
|
chr3 = ((enc3 & 3) << 6) | enc4; |
|
|
|
output = output + String.fromCharCode(chr1); |
|
|
|
if (enc3 != 64) { |
|
output = output + String.fromCharCode(chr2); |
|
} |
|
if (enc4 != 64) { |
|
output = output + String.fromCharCode(chr3); |
|
} |
|
|
|
} |
|
|
|
output = _utf8_decode(output); |
|
|
|
return output; |
|
|
|
} |
|
}); |
|
})(); |
|
BI.Cache = { |
|
_prefix: "bi", |
|
setUsername: function (username) { |
|
localStorage.setItem(BI.Cache._prefix + ".username", (username + "" || "").toUpperCase()); |
|
}, |
|
getUsername: function () { |
|
return localStorage.getItem(BI.Cache._prefix + ".username") || ""; |
|
}, |
|
_getKeyPrefix: function () { |
|
return BI.Cache.getUsername() + "." + BI.Cache._prefix + "."; |
|
}, |
|
_generateKey: function (key) { |
|
return BI.Cache._getKeyPrefix() + (key || ""); |
|
}, |
|
getItem: function (key) { |
|
return localStorage.getItem(BI.Cache._generateKey(key)); |
|
}, |
|
setItem: function (key, value) { |
|
localStorage.setItem(BI.Cache._generateKey(key), value); |
|
}, |
|
removeItem: function (key) { |
|
localStorage.removeItem(BI.Cache._generateKey(key)); |
|
}, |
|
clear: function () { |
|
for (var i = localStorage.length; i >= 0; i--) { |
|
var key = localStorage.key(i); |
|
if (key) { |
|
if (key.indexOf(BI.Cache._getKeyPrefix()) === 0) { |
|
localStorage.removeItem(key); |
|
} |
|
} |
|
} |
|
}, |
|
keys: function () { |
|
var result = []; |
|
for (var i = localStorage.length; i >= 0; i--) { |
|
var key = localStorage.key(i); |
|
if (key) { |
|
var prefix = BI.Cache._getKeyPrefix(); |
|
if (key.indexOf(prefix) === 0) { |
|
result[result.length] = key.substring(prefix.length); |
|
} |
|
} |
|
} |
|
return result; |
|
}, |
|
|
|
addCookie: function (name, value, path, expiresHours) { |
|
var cookieString = name + "=" + escape(value); |
|
// 判断是否设置过期时间 |
|
if (expiresHours && expiresHours > 0) { |
|
var date = new Date(); |
|
// expires是标准GMT格式时间,应该使用时间戳作为起始时间 |
|
date.setTime(date.getTime() + expiresHours * 3600 * 1000); |
|
cookieString = cookieString + "; expires=" + date.toUTCString(); |
|
} |
|
if (path) { |
|
cookieString = cookieString + "; path=" + path; |
|
} |
|
document.cookie = cookieString; |
|
}, |
|
getCookie: function (name) { |
|
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); |
|
if (arr = document.cookie.match(reg)) {return unescape(arr[2]);} |
|
return null; |
|
}, |
|
deleteCookie: function (name, path) { |
|
var date = new Date(); |
|
date.setTime(date.getTime() - 10000); |
|
var cookieString = name + "=v; expires=" + date.toUTCString(); |
|
if (path) { |
|
cookieString = cookieString + "; path=" + path; |
|
} |
|
document.cookie = cookieString; |
|
} |
|
};BI.CellSizeAndPositionManager = function (cellCount, cellSizeGetter, estimatedCellSize) { |
|
this._cellSizeGetter = cellSizeGetter; |
|
this._cellCount = cellCount; |
|
this._estimatedCellSize = estimatedCellSize; |
|
this._cellSizeAndPositionData = {}; |
|
this._lastMeasuredIndex = -1; |
|
}; |
|
|
|
BI.CellSizeAndPositionManager.prototype = { |
|
constructor: BI.CellSizeAndPositionManager, |
|
configure: function (cellCount, estimatedCellSize) { |
|
this._cellCount = cellCount; |
|
this._estimatedCellSize = estimatedCellSize; |
|
}, |
|
|
|
getCellCount: function () { |
|
return this._cellCount; |
|
}, |
|
|
|
getEstimatedCellSize: function () { |
|
return this._estimatedCellSize; |
|
}, |
|
|
|
getLastMeasuredIndex: function () { |
|
return this._lastMeasuredIndex; |
|
}, |
|
|
|
getSizeAndPositionOfCell: function (index) { |
|
if (index < 0 || index >= this._cellCount) { |
|
return; |
|
} |
|
if (index > this._lastMeasuredIndex) { |
|
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); |
|
var offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size; |
|
|
|
for (var i = this._lastMeasuredIndex + 1; i <= index; i++) { |
|
var size = this._cellSizeGetter(i); |
|
|
|
if (size == null || isNaN(size)) { |
|
continue; |
|
} |
|
|
|
this._cellSizeAndPositionData[i] = { |
|
offset: offset, |
|
size: size |
|
}; |
|
|
|
offset += size; |
|
} |
|
|
|
this._lastMeasuredIndex = index; |
|
} |
|
return this._cellSizeAndPositionData[index]; |
|
}, |
|
|
|
getSizeAndPositionOfLastMeasuredCell: function () { |
|
return this._lastMeasuredIndex >= 0 |
|
? this._cellSizeAndPositionData[this._lastMeasuredIndex] |
|
: { |
|
offset: 0, |
|
size: 0 |
|
}; |
|
}, |
|
|
|
getTotalSize: function () { |
|
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); |
|
return lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size + (this._cellCount - this._lastMeasuredIndex - 1) * this._estimatedCellSize; |
|
}, |
|
|
|
getUpdatedOffsetForIndex: function (align, containerSize, currentOffset, targetIndex) { |
|
var datum = this.getSizeAndPositionOfCell(targetIndex); |
|
var maxOffset = datum.offset; |
|
var minOffset = maxOffset - containerSize + datum.size; |
|
|
|
var idealOffset; |
|
|
|
switch (align) { |
|
case "start": |
|
idealOffset = maxOffset; |
|
break; |
|
case "end": |
|
idealOffset = minOffset; |
|
break; |
|
case "center": |
|
idealOffset = maxOffset - ((containerSize - datum.size) / 2); |
|
break; |
|
default: |
|
idealOffset = Math.max(minOffset, Math.min(maxOffset, currentOffset)); |
|
break; |
|
} |
|
|
|
var totalSize = this.getTotalSize(); |
|
|
|
return Math.max(0, Math.min(totalSize - containerSize, idealOffset)); |
|
}, |
|
|
|
getVisibleCellRange: function (containerSize, offset) { |
|
var totalSize = this.getTotalSize(); |
|
|
|
if (totalSize === 0) { |
|
return {}; |
|
} |
|
|
|
var maxOffset = offset + containerSize; |
|
var start = this._findNearestCell(offset); |
|
|
|
var datum = this.getSizeAndPositionOfCell(start); |
|
offset = datum.offset + datum.size; |
|
|
|
var stop = start; |
|
|
|
while (offset < maxOffset && stop < this._cellCount - 1) { |
|
stop++; |
|
offset += this.getSizeAndPositionOfCell(stop).size; |
|
} |
|
|
|
return { |
|
start: start, |
|
stop: stop |
|
}; |
|
}, |
|
|
|
resetCell: function (index) { |
|
this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1); |
|
}, |
|
|
|
_binarySearch: function (high, low, offset) { |
|
var middle; |
|
var currentOffset; |
|
|
|
while (low <= high) { |
|
middle = low + Math.floor((high - low) / 2); |
|
currentOffset = this.getSizeAndPositionOfCell(middle).offset; |
|
|
|
if (currentOffset === offset) { |
|
return middle; |
|
} else if (currentOffset < offset) { |
|
low = middle + 1; |
|
} else if (currentOffset > offset) { |
|
high = middle - 1; |
|
} |
|
} |
|
|
|
if (low > 0) { |
|
return low - 1; |
|
} |
|
}, |
|
|
|
_exponentialSearch: function (index, offset) { |
|
var interval = 1; |
|
|
|
while (index < this._cellCount && this.getSizeAndPositionOfCell(index).offset < offset) { |
|
index += interval; |
|
interval *= 2; |
|
} |
|
|
|
return this._binarySearch(Math.min(index, this._cellCount - 1), Math.floor(index / 2), offset); |
|
}, |
|
|
|
_findNearestCell: function (offset) { |
|
if (isNaN(offset)) { |
|
return; |
|
} |
|
|
|
offset = Math.max(0, offset); |
|
|
|
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell(); |
|
var lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex); |
|
|
|
if (lastMeasuredCellSizeAndPosition.offset >= offset) { |
|
return this._binarySearch(lastMeasuredIndex, 0, offset); |
|
} |
|
return this._exponentialSearch(lastMeasuredIndex, offset); |
|
|
|
} |
|
}; |
|
|
|
BI.ScalingCellSizeAndPositionManager = function (cellCount, cellSizeGetter, estimatedCellSize, maxScrollSize) { |
|
this._cellSizeAndPositionManager = new BI.CellSizeAndPositionManager(cellCount, cellSizeGetter, estimatedCellSize); |
|
this._maxScrollSize = maxScrollSize || 10000000; |
|
}; |
|
|
|
BI.ScalingCellSizeAndPositionManager.prototype = { |
|
constructor: BI.ScalingCellSizeAndPositionManager, |
|
|
|
configure: function () { |
|
this._cellSizeAndPositionManager.configure.apply(this._cellSizeAndPositionManager, arguments); |
|
}, |
|
|
|
getCellCount: function () { |
|
return this._cellSizeAndPositionManager.getCellCount(); |
|
}, |
|
|
|
getEstimatedCellSize: function () { |
|
return this._cellSizeAndPositionManager.getEstimatedCellSize(); |
|
}, |
|
|
|
getLastMeasuredIndex: function () { |
|
return this._cellSizeAndPositionManager.getLastMeasuredIndex(); |
|
}, |
|
|
|
getOffsetAdjustment: function (containerSize, offset) { |
|
var totalSize = this._cellSizeAndPositionManager.getTotalSize(); |
|
var safeTotalSize = this.getTotalSize(); |
|
var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize); |
|
|
|
return Math.round(offsetPercentage * (safeTotalSize - totalSize)); |
|
}, |
|
|
|
getSizeAndPositionOfCell: function (index) { |
|
return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index); |
|
}, |
|
|
|
getSizeAndPositionOfLastMeasuredCell: function () { |
|
return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell(); |
|
}, |
|
|
|
getTotalSize: function () { |
|
return Math.min(this._maxScrollSize, this._cellSizeAndPositionManager.getTotalSize()); |
|
}, |
|
|
|
getUpdatedOffsetForIndex: function (align, containerSize, currentOffset, targetIndex) { |
|
currentOffset = this._safeOffsetToOffset(containerSize, currentOffset); |
|
|
|
var offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex(align, containerSize, currentOffset, targetIndex); |
|
|
|
return this._offsetToSafeOffset(containerSize, offset); |
|
}, |
|
|
|
getVisibleCellRange: function (containerSize, offset) { |
|
offset = this._safeOffsetToOffset(containerSize, offset); |
|
|
|
return this._cellSizeAndPositionManager.getVisibleCellRange(containerSize, offset); |
|
}, |
|
|
|
resetCell: function (index) { |
|
this._cellSizeAndPositionManager.resetCell(index); |
|
}, |
|
|
|
_getOffsetPercentage: function (containerSize, offset, totalSize) { |
|
return totalSize <= containerSize |
|
? 0 |
|
: offset / (totalSize - containerSize); |
|
}, |
|
|
|
_offsetToSafeOffset: function (containerSize, offset) { |
|
var totalSize = this._cellSizeAndPositionManager.getTotalSize(); |
|
var safeTotalSize = this.getTotalSize(); |
|
|
|
if (totalSize === safeTotalSize) { |
|
return offset; |
|
} |
|
var offsetPercentage = this._getOffsetPercentage(containerSize, offset, totalSize); |
|
|
|
return Math.round(offsetPercentage * (safeTotalSize - containerSize)); |
|
|
|
}, |
|
|
|
_safeOffsetToOffset: function (containerSize, offset) { |
|
var totalSize = this._cellSizeAndPositionManager.getTotalSize(); |
|
var safeTotalSize = this.getTotalSize(); |
|
|
|
if (totalSize === safeTotalSize) { |
|
return offset; |
|
} |
|
var offsetPercentage = this._getOffsetPercentage(containerSize, offset, safeTotalSize); |
|
|
|
return Math.round(offsetPercentage * (totalSize - containerSize)); |
|
|
|
} |
|
};/** |
|
* 汉字拼音索引 |
|
*/ |
|
|
|
!(function () { |
|
var _ChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGHGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY"; |
|
|
|
// 此处收录了375个多音字,数据来自于http://www.51windows.net/pages/pinyin.asp |
|
var oMultiDiff = { |
|
19969: "DZ", |
|
19975: "WM", |
|
19988: "QJ", |
|
20048: "YL", |
|
20056: "SC", |
|
20060: "NM", |
|
20094: "QG", |
|
20127: "QJ", |
|
20167: "QC", |
|
20193: "YG", |
|
20250: "KH", |
|
20256: "ZC", |
|
20282: "SC", |
|
20285: "QJG", |
|
20291: "TD", |
|
20314: "YD", |
|
20315: "BF", |
|
20340: "NE", |
|
20375: "TD", |
|
20389: "YJ", |
|
20391: "CZ", |
|
20415: "PB", |
|
20446: "YS", |
|
20447: "SQ", |
|
20504: "TC", |
|
20608: "KG", |
|
20854: "QJ", |
|
20857: "ZC", |
|
20911: "PF", |
|
20985: "AW", |
|
21032: "PB", |
|
21048: "XQ", |
|
21049: "SC", |
|
21089: "YS", |
|
21119: "JC", |
|
21242: "SB", |
|
21273: "SC", |
|
21305: "YP", |
|
21306: "QO", |
|
21330: "ZC", |
|
21333: "SDC", |
|
21345: "QK", |
|
21378: "CA", |
|
21397: "SC", |
|
21414: "XS", |
|
21442: "SC", |
|
21477: "JG", |
|
21480: "TD", |
|
21484: "ZS", |
|
21494: "YX", |
|
21505: "YX", |
|
21512: "HG", |
|
21523: "XH", |
|
21537: "PB", |
|
21542: "PF", |
|
21549: "KH", |
|
21571: "E", |
|
21574: "DA", |
|
21588: "TD", |
|
21589: "O", |
|
21618: "ZC", |
|
21621: "KHA", |
|
21632: "ZJ", |
|
21654: "KG", |
|
21679: "LKG", |
|
21683: "KH", |
|
21710: "A", |
|
21719: "YH", |
|
21734: "WOE", |
|
21769: "A", |
|
21780: "WN", |
|
21804: "XH", |
|
21834: "A", |
|
21899: "ZD", |
|
21903: "RN", |
|
21908: "WO", |
|
21939: "ZC", |
|
21956: "SA", |
|
21964: "YA", |
|
21970: "TD", |
|
22003: "A", |
|
22031: "JG", |
|
22040: "XS", |
|
22060: "ZC", |
|
22066: "ZC", |
|
22079: "MH", |
|
22129: "XJ", |
|
22179: "XA", |
|
22237: "NJ", |
|
22244: "TD", |
|
22280: "JQ", |
|
22300: "YH", |
|
22313: "XW", |
|
22331: "YQ", |
|
22343: "YJ", |
|
22351: "PH", |
|
22395: "DC", |
|
22412: "TD", |
|
22484: "PB", |
|
22500: "PB", |
|
22534: "ZD", |
|
22549: "DH", |
|
22561: "PB", |
|
22612: "TD", |
|
22771: "KQ", |
|
22831: "HB", |
|
22841: "JG", |
|
22855: "QJ", |
|
22865: "XQ", |
|
23013: "ML", |
|
23081: "WM", |
|
23487: "SX", |
|
23558: "QJ", |
|
23561: "YW", |
|
23586: "YW", |
|
23614: "YW", |
|
23615: "SN", |
|
23631: "PB", |
|
23646: "ZS", |
|
23663: "ZT", |
|
23673: "YG", |
|
23762: "TD", |
|
23769: "ZS", |
|
23780: "QJ", |
|
23884: "QK", |
|
24055: "XH", |
|
24113: "DC", |
|
24162: "ZC", |
|
24191: "GA", |
|
24273: "QJ", |
|
24324: "NL", |
|
24377: "TD", |
|
24378: "QJ", |
|
24439: "PF", |
|
24554: "ZS", |
|
24683: "TD", |
|
24694: "WE", |
|
24733: "LK", |
|
24925: "TN", |
|
25094: "ZG", |
|
25100: "XQ", |
|
25103: "XH", |
|
25153: "PB", |
|
25170: "PB", |
|
25179: "KG", |
|
25203: "PB", |
|
25240: "ZS", |
|
25282: "FB", |
|
25303: "NA", |
|
25324: "KG", |
|
25341: "ZY", |
|
25373: "WZ", |
|
25375: "XJ", |
|
25384: "A", |
|
25457: "A", |
|
25528: "SD", |
|
25530: "SC", |
|
25552: "TD", |
|
25774: "ZC", |
|
25874: "ZC", |
|
26044: "YW", |
|
26080: "WM", |
|
26292: "PB", |
|
26333: "PB", |
|
26355: "ZY", |
|
26366: "CZ", |
|
26397: "ZC", |
|
26399: "QJ", |
|
26415: "ZS", |
|
26451: "SB", |
|
26526: "ZC", |
|
26552: "JG", |
|
26561: "TD", |
|
26588: "JG", |
|
26597: "CZ", |
|
26629: "ZS", |
|
26638: "YL", |
|
26646: "XQ", |
|
26653: "KG", |
|
26657: "XJ", |
|
26727: "HG", |
|
26894: "ZC", |
|
26937: "ZS", |
|
26946: "ZC", |
|
26999: "KJ", |
|
27099: "KJ", |
|
27449: "YQ", |
|
27481: "XS", |
|
27542: "ZS", |
|
27663: "ZS", |
|
27748: "TS", |
|
27784: "SC", |
|
27788: "ZD", |
|
27795: "TD", |
|
27812: "O", |
|
27850: "PB", |
|
27852: "MB", |
|
27895: "SL", |
|
27898: "PL", |
|
27973: "QJ", |
|
27981: "KH", |
|
27986: "HX", |
|
27994: "XJ", |
|
28044: "YC", |
|
28065: "WG", |
|
28177: "SM", |
|
28267: "QJ", |
|
28291: "KH", |
|
28337: "ZQ", |
|
28463: "TL", |
|
28548: "DC", |
|
28601: "TD", |
|
28689: "PB", |
|
28805: "JG", |
|
28820: "QG", |
|
28846: "PB", |
|
28952: "TD", |
|
28975: "ZC", |
|
29100: "A", |
|
29325: "QJ", |
|
29575: "SL", |
|
29602: "FB", |
|
30010: "TD", |
|
30044: "CX", |
|
30058: "PF", |
|
30091: "YSP", |
|
30111: "YN", |
|
30229: "XJ", |
|
30427: "SC", |
|
30465: "SX", |
|
30631: "YQ", |
|
30655: "QJ", |
|
30684: "QJG", |
|
30707: "SD", |
|
30729: "XH", |
|
30796: "LG", |
|
30917: "PB", |
|
31074: "NM", |
|
31085: "JZ", |
|
31109: "SC", |
|
31181: "ZC", |
|
31192: "MLB", |
|
31293: "JQ", |
|
31400: "YX", |
|
31584: "YJ", |
|
31896: "ZN", |
|
31909: "ZY", |
|
31995: "XJ", |
|
32321: "PF", |
|
32327: "ZY", |
|
32418: "HG", |
|
32420: "XQ", |
|
32421: "HG", |
|
32438: "LG", |
|
32473: "GJ", |
|
32488: "TD", |
|
32521: "QJ", |
|
32527: "PB", |
|
32562: "ZSQ", |
|
32564: "JZ", |
|
32735: "ZD", |
|
32793: "PB", |
|
33071: "PF", |
|
33098: "XL", |
|
33100: "YA", |
|
33152: "PB", |
|
33261: "CX", |
|
33324: "BP", |
|
33333: "TD", |
|
33406: "YA", |
|
33426: "WM", |
|
33432: "PB", |
|
33445: "JG", |
|
33486: "ZN", |
|
33493: "TS", |
|
33507: "QJ", |
|
33540: "QJ", |
|
33544: "ZC", |
|
33564: "XQ", |
|
33617: "YT", |
|
33632: "QJ", |
|
33636: "XH", |
|
33637: "YX", |
|
33694: "WG", |
|
33705: "PF", |
|
33728: "YW", |
|
33882: "SR", |
|
34067: "WM", |
|
34074: "YW", |
|
34121: "QJ", |
|
34255: "ZC", |
|
34259: "XL", |
|
34425: "JH", |
|
34430: "XH", |
|
34485: "KH", |
|
34503: "YS", |
|
34532: "HG", |
|
34552: "XS", |
|
34558: "YE", |
|
34593: "ZL", |
|
34660: "YQ", |
|
34892: "XH", |
|
34928: "SC", |
|
34999: "QJ", |
|
35048: "PB", |
|
35059: "SC", |
|
35098: "ZC", |
|
35203: "TQ", |
|
35265: "JX", |
|
35299: "JX", |
|
35782: "SZ", |
|
35828: "YS", |
|
35830: "E", |
|
35843: "TD", |
|
35895: "YG", |
|
35977: "MH", |
|
36158: "JG", |
|
36228: "QJ", |
|
36426: "XQ", |
|
36466: "DC", |
|
36710: "JC", |
|
36711: "ZYG", |
|
36767: "PB", |
|
36866: "SK", |
|
36951: "YW", |
|
37034: "YX", |
|
37063: "XH", |
|
37218: "ZC", |
|
37325: "ZC", |
|
38063: "PB", |
|
38079: "TD", |
|
38085: "QY", |
|
38107: "DC", |
|
38116: "TD", |
|
38123: "YD", |
|
38224: "HG", |
|
38241: "XTC", |
|
38271: "ZC", |
|
38415: "YE", |
|
38426: "KH", |
|
38461: "YD", |
|
38463: "AE", |
|
38466: "PB", |
|
38477: "XJ", |
|
38518: "YT", |
|
38551: "WK", |
|
38585: "ZC", |
|
38704: "XS", |
|
38739: "LJ", |
|
38761: "GJ", |
|
38808: "SQ", |
|
39048: "JG", |
|
39049: "XJ", |
|
39052: "HG", |
|
39076: "CZ", |
|
39271: "XT", |
|
39534: "TD", |
|
39552: "TD", |
|
39584: "PB", |
|
39647: "SB", |
|
39730: "LG", |
|
39748: "TPB", |
|
40109: "ZQ", |
|
40479: "ND", |
|
40516: "HG", |
|
40536: "HG", |
|
40583: "QJ", |
|
40765: "YQ", |
|
40784: "QJ", |
|
40840: "YK", |
|
40863: "QJG" |
|
}; |
|
|
|
var _checkPYCh = function (ch) { |
|
var uni = ch.charCodeAt(0); |
|
// 如果不在汉字处理范围之内,返回原字符,也可以调用自己的处理函数 |
|
if (uni > 40869 || uni < 19968) {return ch;} // dealWithOthers(ch); |
|
return (oMultiDiff[uni] ? oMultiDiff[uni] : (_ChineseFirstPY.charAt(uni - 19968))); |
|
}; |
|
|
|
var _mkPYRslt = function (arr, options) { |
|
var ignoreMulti = options.ignoreMulti; |
|
var splitChar = options.splitChar; |
|
var arrRslt = [""], k, multiLen = 0; |
|
for (var i = 0, len = arr.length; i < len; i++) { |
|
var str = arr[i]; |
|
var strlen = str.length; |
|
// 多音字过多的情况下,指数增长会造成浏览器卡死,超过20完全卡死,18勉强能用,考虑到不同性能最好是16或者14 |
|
// 超过14个多音字之后,后面的都用第一个拼音 |
|
if (strlen == 1 || multiLen > 14 || ignoreMulti) { |
|
var tmpStr = str.substring(0, 1); |
|
for (k = 0; k < arrRslt.length; k++) { |
|
arrRslt[k] += tmpStr; |
|
} |
|
} else { |
|
var tmpArr = arrRslt.slice(0); |
|
arrRslt = []; |
|
multiLen ++; |
|
for (k = 0; k < strlen; k++) { |
|
// 复制一个相同的arrRslt |
|
var tmp = tmpArr.slice(0); |
|
// 把当前字符str[k]添加到每个元素末尾 |
|
for (var j = 0; j < tmp.length; j++) { |
|
tmp[j] += str.charAt(k); |
|
} |
|
// 把复制并修改后的数组连接到arrRslt上 |
|
arrRslt = arrRslt.concat(tmp); |
|
} |
|
} |
|
} |
|
// BI-56386 这边直接将所有多音字组合拼接是有风险的,因为丢失了每一组的起始索引信息, 外部使用indexOf等方法会造成错位 |
|
// 一旦错位就可能认为不符合条件, 但实际上还是有可能符合条件的,故此处以一个无法搜索的不可见字符作为连接 |
|
return arrRslt.join(splitChar || "").toLowerCase(); |
|
}; |
|
|
|
_.extend(BI, { |
|
makeFirstPY: function (str, options) { |
|
options = options || {}; |
|
if (typeof (str) !== "string") {return "" + str;} |
|
var arrResult = []; // 保存中间结果的数组 |
|
for (var i = 0, len = str.length; i < len; i++) { |
|
// 获得unicode码 |
|
var ch = str.charAt(i); |
|
// 检查该unicode码是否在处理范围之内,在则返回该码对映汉字的拼音首字母,不在则调用其它函数处理 |
|
arrResult.push(_checkPYCh(ch)); |
|
} |
|
// 处理arrResult,返回所有可能的拼音首字母串数组 |
|
return _mkPYRslt(arrResult, options); |
|
} |
|
}); |
|
})(); |
|
(function () { |
|
function defaultComparator (a, b) { |
|
return a < b; |
|
} |
|
|
|
BI.Heap = function (items, comparator) { |
|
this._items = items || []; |
|
this._size = this._items.length; |
|
this._comparator = comparator || defaultComparator; |
|
this._heapify(); |
|
}; |
|
|
|
BI.Heap.prototype = { |
|
constructor: BI.Heap, |
|
empty: function () { |
|
return this._size === 0; |
|
}, |
|
|
|
pop: function () { |
|
if (this._size === 0) { |
|
return; |
|
} |
|
|
|
var elt = this._items[0]; |
|
|
|
var lastElt = this._items.pop(); |
|
this._size--; |
|
|
|
if (this._size > 0) { |
|
this._items[0] = lastElt; |
|
this._sinkDown(0); |
|
} |
|
|
|
return elt; |
|
}, |
|
|
|
push: function (item) { |
|
this._items[this._size++] = item; |
|
this._bubbleUp(this._size - 1); |
|
}, |
|
|
|
size: function () { |
|
return this._size; |
|
}, |
|
|
|
peek: function () { |
|
if (this._size === 0) { |
|
return; |
|
} |
|
|
|
return this._items[0]; |
|
}, |
|
|
|
_heapify: function () { |
|
for (var index = Math.floor((this._size + 1) / 2); index >= 0; index--) { |
|
this._sinkDown(index); |
|
} |
|
}, |
|
|
|
_bubbleUp: function (index) { |
|
var elt = this._items[index]; |
|
while (index > 0) { |
|
var parentIndex = Math.floor((index + 1) / 2) - 1; |
|
var parentElt = this._items[parentIndex]; |
|
|
|
// if parentElt < elt, stop |
|
if (this._comparator(parentElt, elt)) { |
|
return; |
|
} |
|
|
|
// swap |
|
this._items[parentIndex] = elt; |
|
this._items[index] = parentElt; |
|
index = parentIndex; |
|
} |
|
}, |
|
|
|
_sinkDown: function (index) { |
|
var elt = this._items[index]; |
|
|
|
while (true) { |
|
var leftChildIndex = 2 * (index + 1) - 1; |
|
var rightChildIndex = 2 * (index + 1); |
|
var swapIndex = -1; |
|
|
|
if (leftChildIndex < this._size) { |
|
var leftChild = this._items[leftChildIndex]; |
|
if (this._comparator(leftChild, elt)) { |
|
swapIndex = leftChildIndex; |
|
} |
|
} |
|
|
|
if (rightChildIndex < this._size) { |
|
var rightChild = this._items[rightChildIndex]; |
|
if (this._comparator(rightChild, elt)) { |
|
if (swapIndex === -1 || |
|
this._comparator(rightChild, this._items[swapIndex])) { |
|
swapIndex = rightChildIndex; |
|
} |
|
} |
|
} |
|
|
|
// if we don't have a swap, stop |
|
if (swapIndex === -1) { |
|
return; |
|
} |
|
|
|
this._items[index] = this._items[swapIndex]; |
|
this._items[swapIndex] = elt; |
|
index = swapIndex; |
|
} |
|
} |
|
}; |
|
})(); |
|
|
|
!(function () { |
|
BI.LinkHashMap = function () { |
|
this.array = []; |
|
this.map = {}; |
|
}; |
|
BI.LinkHashMap.prototype = { |
|
constructor: BI.LinkHashMap, |
|
has: function (key) { |
|
if (key in this.map) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
|
|
add: function (key, value) { |
|
if (typeof key === "undefined") { |
|
return; |
|
} |
|
if (key in this.map) { |
|
this.map[key] = value; |
|
} else { |
|
this.array.push(key); |
|
this.map[key] = value; |
|
} |
|
}, |
|
|
|
remove: function (key) { |
|
if (key in this.map) { |
|
delete this.map[key]; |
|
for (var i = 0; i < this.array.length; i++) { |
|
if (this.array[i] == key) { |
|
this.array.splice(i, 1); |
|
break; |
|
} |
|
} |
|
} |
|
}, |
|
|
|
size: function () { |
|
return this.array.length; |
|
}, |
|
|
|
each: function (fn, scope) { |
|
var scope = scope || window; |
|
var fn = fn || null; |
|
if (fn == null || typeof (fn) !== "function") { |
|
return; |
|
} |
|
for (var i = 0; i < this.array.length; i++) { |
|
var key = this.array[i]; |
|
var value = this.map[key]; |
|
var re = fn.call(scope, key, value, i, this.array, this.map); |
|
if (re == false) { |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
get: function (key) { |
|
return this.map[key]; |
|
}, |
|
|
|
toArray: function () { |
|
var array = []; |
|
this.each(function (key, value) { |
|
array.push(value); |
|
}); |
|
return array; |
|
} |
|
}; |
|
})(); |
|
!(function () { |
|
BI.LRU = function (limit) { |
|
this.size = 0; |
|
this.limit = limit; |
|
this.head = this.tail = undefined; |
|
this._keymap = {}; |
|
}; |
|
|
|
var p = BI.LRU.prototype; |
|
|
|
p.put = function (key, value) { |
|
var removed; |
|
if (this.size === this.limit) { |
|
removed = this.shift(); |
|
} |
|
|
|
var entry = this.get(key, true); |
|
if (!entry) { |
|
entry = { |
|
key: key |
|
}; |
|
this._keymap[key] = entry; |
|
if (this.tail) { |
|
this.tail.newer = entry; |
|
entry.older = this.tail; |
|
} else { |
|
this.head = entry; |
|
} |
|
this.tail = entry; |
|
this.size++; |
|
} |
|
entry.value = value; |
|
|
|
return removed; |
|
}; |
|
|
|
p.shift = function () { |
|
var entry = this.head; |
|
if (entry) { |
|
this.head = this.head.newer; |
|
this.head.older = undefined; |
|
entry.newer = entry.older = undefined; |
|
this._keymap[entry.key] = undefined; |
|
this.size--; |
|
} |
|
return entry; |
|
}; |
|
|
|
|
|
p.get = function (key, returnEntry) { |
|
var entry = this._keymap[key]; |
|
if (entry === undefined) return; |
|
if (entry === this.tail) { |
|
return returnEntry |
|
? entry |
|
: entry.value; |
|
} |
|
// HEAD--------------TAIL |
|
// <.older .newer> |
|
// <--- add direction -- |
|
// A B C <D> E |
|
if (entry.newer) { |
|
if (entry === this.head) { |
|
this.head = entry.newer; |
|
} |
|
entry.newer.older = entry.older; // C <-- E. |
|
} |
|
if (entry.older) { |
|
entry.older.newer = entry.newer; // C. --> E |
|
} |
|
entry.newer = undefined; // D --x |
|
entry.older = this.tail; // D. --> E |
|
if (this.tail) { |
|
this.tail.newer = entry; // E. <-- D |
|
} |
|
this.tail = entry; |
|
return returnEntry |
|
? entry |
|
: entry.value; |
|
}; |
|
|
|
p.has = function (key) { |
|
return this._keymap[key] != null; |
|
}; |
|
})();// 线段树 |
|
(function () { |
|
var parent = function (node) { |
|
return Math.floor(node / 2); |
|
}; |
|
|
|
var Int32Array = _global.Int32Array || function (size) { |
|
var xs = []; |
|
for (var i = size - 1; i >= 0; --i) { |
|
xs[i] = 0; |
|
} |
|
return xs; |
|
}; |
|
|
|
var ceilLog2 = function (x) { |
|
var y = 1; |
|
while (y < x) { |
|
y *= 2; |
|
} |
|
return y; |
|
}; |
|
|
|
BI.PrefixIntervalTree = function (xs) { |
|
this._size = xs.length; |
|
this._half = ceilLog2(this._size); |
|
// _heap是一个_size两倍以上的堆 |
|
this._heap = new Int32Array(2 * this._half); |
|
|
|
var i; |
|
// 初始化 >= _size 的堆空间, 即叶子节点 |
|
for (i = 0; i < this._size; ++i) { |
|
this._heap[this._half + i] = xs[i]; |
|
} |
|
// 初始化 < _size 的堆空间, 即非叶子节点,根节点包含整个区间 |
|
for (i = this._half - 1; i > 0; --i) { |
|
this._heap[i] = this._heap[2 * i] + this._heap[2 * i + 1]; |
|
} |
|
}; |
|
|
|
BI.PrefixIntervalTree.prototype = { |
|
constructor: BI.PrefixIntervalTree, |
|
// 往_half之后的空间set值,需要更新其所有祖先节点的值 |
|
set: function (index, value) { |
|
var node = this._half + index; |
|
this._heap[node] = value; |
|
|
|
node = parent(node); |
|
for (; node !== 0; node = parent(node)) { |
|
this._heap[node] = |
|
this._heap[2 * node] + this._heap[2 * node + 1]; |
|
} |
|
}, |
|
|
|
get: function (index) { |
|
var node = this._half + index; |
|
return this._heap[node]; |
|
}, |
|
|
|
getSize: function () { |
|
return this._size; |
|
}, |
|
|
|
/** |
|
* get(0) + get(1) + ... + get(end - 1). |
|
*/ |
|
sumUntil: function (end) { |
|
if (end === 0) { |
|
return 0; |
|
} |
|
|
|
var node = this._half + end - 1; |
|
var sum = this._heap[node]; |
|
for (; node !== 1; node = parent(node)) { |
|
if (node % 2 === 1) { |
|
sum += this._heap[node - 1]; |
|
} |
|
} |
|
|
|
return sum; |
|
}, |
|
|
|
/** |
|
* get(0) + get(1) + ... + get(inclusiveEnd). |
|
*/ |
|
sumTo: function (inclusiveEnd) { |
|
return this.sumUntil(inclusiveEnd + 1); |
|
}, |
|
|
|
/** |
|
* sum get(begin) + get(begin + 1) + ... + get(end - 1). |
|
*/ |
|
sum: function (begin, end) { |
|
return this.sumUntil(end) - this.sumUntil(begin); |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or |
|
* -1 if no such i exists. |
|
*/ |
|
greatestLowerBound: function (t) { |
|
if (t < 0) { |
|
return -1; |
|
} |
|
|
|
var node = 1; |
|
if (this._heap[node] <= t) { |
|
return this._size; |
|
} |
|
|
|
while (node < this._half) { |
|
var leftSum = this._heap[2 * node]; |
|
if (t < leftSum) { |
|
node = 2 * node; |
|
} else { |
|
node = 2 * node + 1; |
|
t -= leftSum; |
|
} |
|
} |
|
|
|
return node - this._half; |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or |
|
* -1 if no such i exists. |
|
*/ |
|
greatestStrictLowerBound: function (t) { |
|
if (t <= 0) { |
|
return -1; |
|
} |
|
|
|
var node = 1; |
|
if (this._heap[node] < t) { |
|
return this._size; |
|
} |
|
|
|
while (node < this._half) { |
|
var leftSum = this._heap[2 * node]; |
|
if (t <= leftSum) { |
|
node = 2 * node; |
|
} else { |
|
node = 2 * node + 1; |
|
t -= leftSum; |
|
} |
|
} |
|
|
|
return node - this._half; |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or |
|
* size + 1 if no such i exists. |
|
*/ |
|
leastUpperBound: function (t) { |
|
return this.greatestStrictLowerBound(t) + 1; |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or |
|
* size + 1 if no such i exists. |
|
*/ |
|
leastStrictUpperBound: function (t) { |
|
return this.greatestLowerBound(t) + 1; |
|
} |
|
}; |
|
|
|
BI.PrefixIntervalTree.uniform = function (size, initialValue) { |
|
var xs = []; |
|
for (var i = size - 1; i >= 0; --i) { |
|
xs[i] = initialValue; |
|
} |
|
|
|
return new BI.PrefixIntervalTree(xs); |
|
}; |
|
|
|
BI.PrefixIntervalTree.empty = function (size) { |
|
return BI.PrefixIntervalTree.uniform(size, 0); |
|
}; |
|
|
|
})(); |
|
|
|
!(function () { |
|
BI.Queue = function (capacity) { |
|
this.capacity = capacity; |
|
this.array = []; |
|
}; |
|
BI.Queue.prototype = { |
|
constructor: BI.Queue, |
|
|
|
contains: function (v) { |
|
return BI.contains(this.array, v); |
|
}, |
|
|
|
indexOf: function (v) { |
|
return BI.contains(this.array, v); |
|
}, |
|
|
|
getElementByIndex: function (index) { |
|
return this.array[index]; |
|
}, |
|
|
|
push: function (v) { |
|
this.array.push(v); |
|
if (this.capacity && this.array.length > this.capacity) { |
|
this.array.shift(); |
|
} |
|
}, |
|
|
|
pop: function () { |
|
this.array.pop(); |
|
}, |
|
|
|
shift: function () { |
|
this.array.shift(); |
|
}, |
|
|
|
unshift: function (v) { |
|
this.array.unshift(v); |
|
if (this.capacity && this.array.length > this.capacity) { |
|
this.array.pop(); |
|
} |
|
}, |
|
|
|
remove: function (v) { |
|
BI.remove(this.array, v); |
|
}, |
|
|
|
splice: function () { |
|
this.array.splice.apply(this.array, arguments); |
|
}, |
|
|
|
slice: function () { |
|
this.array.slice.apply(this.array, arguments); |
|
}, |
|
|
|
size: function () { |
|
return this.array.length; |
|
}, |
|
|
|
each: function (fn, scope) { |
|
var scope = scope || window; |
|
var fn = fn || null; |
|
if (fn == null || typeof (fn) !== "function") { |
|
return; |
|
} |
|
for (var i = 0; i < this.array.length; i++) { |
|
var re = fn.call(scope, i, this.array[i], this.array); |
|
if (re == false) { |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
toArray: function () { |
|
return this.array; |
|
}, |
|
|
|
fromArray: function (array) { |
|
var self = this; |
|
BI.each(array, function (i, v) { |
|
self.push(v); |
|
}); |
|
}, |
|
|
|
clear: function () { |
|
this.array.length = 0; |
|
} |
|
}; |
|
})();!(function () { |
|
var Section = function (height, width, x, y) { |
|
this.height = height; |
|
this.width = width; |
|
this.x = x; |
|
this.y = y; |
|
|
|
this._indexMap = {}; |
|
this._indices = []; |
|
}; |
|
|
|
Section.prototype = { |
|
constructor: Section, |
|
addCellIndex: function (index) { |
|
if (!this._indexMap[index]) { |
|
this._indexMap[index] = true; |
|
this._indices.push(index); |
|
} |
|
}, |
|
|
|
getCellIndices: function () { |
|
return this._indices; |
|
} |
|
}; |
|
|
|
var SECTION_SIZE = 100; |
|
BI.SectionManager = function (sectionSize) { |
|
this._sectionSize = sectionSize || SECTION_SIZE; |
|
this._cellMetadata = []; |
|
this._sections = {}; |
|
}; |
|
|
|
BI.SectionManager.prototype = { |
|
constructor: BI.SectionManager, |
|
getCellIndices: function (height, width, x, y) { |
|
var indices = {}; |
|
|
|
BI.each(this.getSections(height, width, x, y), function (i, section) { |
|
BI.each(section.getCellIndices(), function (j, index) { |
|
indices[index] = index; |
|
}); |
|
}); |
|
|
|
return BI.map(BI.keys(indices), function (i, index) { |
|
return indices[index]; |
|
}); |
|
}, |
|
|
|
getCellMetadata: function (index) { |
|
return this._cellMetadata[index]; |
|
}, |
|
|
|
getSections: function (height, width, x, y) { |
|
var sectionXStart = Math.floor(x / this._sectionSize); |
|
var sectionXStop = Math.floor((x + width - 1) / this._sectionSize); |
|
var sectionYStart = Math.floor(y / this._sectionSize); |
|
var sectionYStop = Math.floor((y + height - 1) / this._sectionSize); |
|
|
|
var sections = []; |
|
|
|
for (var sectionX = sectionXStart; sectionX <= sectionXStop; sectionX++) { |
|
for (var sectionY = sectionYStart; sectionY <= sectionYStop; sectionY++) { |
|
var key = sectionX + "." + sectionY; |
|
|
|
if (!this._sections[key]) { |
|
this._sections[key] = new Section(this._sectionSize, this._sectionSize, sectionX * this._sectionSize, sectionY * this._sectionSize); |
|
} |
|
|
|
sections.push(this._sections[key]); |
|
} |
|
} |
|
|
|
return sections; |
|
}, |
|
|
|
getTotalSectionCount: function () { |
|
return BI.size(this._sections); |
|
}, |
|
|
|
registerCell: function (cellMetadatum, index) { |
|
this._cellMetadata[index] = cellMetadatum; |
|
|
|
BI.each(this.getSections(cellMetadatum.height, cellMetadatum.width, cellMetadatum.x, cellMetadatum.y), function (i, section) { |
|
section.addCellIndex(index); |
|
}); |
|
} |
|
}; |
|
})();(function () { |
|
BI.Tree = function () { |
|
this.root = new BI.Node(BI.UUID()); |
|
}; |
|
|
|
BI.Tree.prototype = { |
|
constructor: BI.Tree, |
|
addNode: function (node, newNode, index) { |
|
if (BI.isNull(newNode)) { |
|
this.root.addChild(node, index); |
|
} else if (BI.isNull(node)) { |
|
this.root.addChild(newNode, index); |
|
} else { |
|
node.addChild(newNode, index); |
|
} |
|
}, |
|
|
|
isRoot: function (node) { |
|
return node === this.root; |
|
}, |
|
|
|
getRoot: function () { |
|
return this.root; |
|
}, |
|
|
|
clear: function () { |
|
this.root.clear(); |
|
}, |
|
|
|
initTree: function (nodes) { |
|
var self = this; |
|
this.clear(); |
|
var queue = []; |
|
BI.each(nodes, function (i, node) { |
|
var n = new BI.Node(node); |
|
n.set("data", node); |
|
self.addNode(n); |
|
queue.push(n); |
|
}); |
|
while (!BI.isEmpty(queue)) { |
|
var parent = queue.shift(); |
|
var node = parent.get("data"); |
|
BI.each(node.children, function (i, child) { |
|
var n = new BI.Node(child); |
|
n.set("data", child); |
|
queue.push(n); |
|
self.addNode(parent, n); |
|
}); |
|
} |
|
}, |
|
|
|
_toJSON: function (node) { |
|
var self = this; |
|
var children = []; |
|
BI.each(node.getChildren(), function (i, child) { |
|
children.push(self._toJSON(child)); |
|
}); |
|
return BI.extend({ |
|
id: node.id |
|
}, BI.deepClone(node.get("data")), (children.length > 0 ? { |
|
children: children |
|
} : {})); |
|
}, |
|
|
|
toJSON: function (node) { |
|
var self = this, result = []; |
|
BI.each((node || this.root).getChildren(), function (i, child) { |
|
result.push(self._toJSON(child)); |
|
}); |
|
return result; |
|
}, |
|
|
|
_toJSONWithNode: function (node) { |
|
var self = this; |
|
var children = []; |
|
BI.each(node.getChildren(), function (i, child) { |
|
children.push(self._toJSONWithNode(child)); |
|
}); |
|
return BI.extend({ |
|
id: node.id |
|
}, BI.deepClone(node.get("data")), { |
|
node: node |
|
}, (children.length > 0 ? { |
|
children: children |
|
} : {})); |
|
}, |
|
|
|
toJSONWithNode: function (node) { |
|
var self = this, result = []; |
|
BI.each((node || this.root).getChildren(), function (i, child) { |
|
result.push(self._toJSONWithNode(child)); |
|
}); |
|
return result; |
|
}, |
|
|
|
search: function (root, target, param) { |
|
if (!(root instanceof BI.Node)) { |
|
return arguments.callee.apply(this, [this.root, root, target]); |
|
} |
|
var self = this, next = null; |
|
|
|
if (BI.isNull(target)) { |
|
return null; |
|
} |
|
if (BI.isEqual(root[param || "id"], target)) { |
|
return root; |
|
} |
|
BI.any(root.getChildren(), function (i, child) { |
|
next = self.search(child, target, param); |
|
if (null !== next) { |
|
return true; |
|
} |
|
}); |
|
return next; |
|
}, |
|
|
|
_traverse: function (node, callback) { |
|
var queue = []; |
|
queue.push(node); |
|
while (!BI.isEmpty(queue)) { |
|
var temp = queue.shift(); |
|
var b = callback && callback(temp); |
|
if (b === false) { |
|
break; |
|
} |
|
if (b === true) { |
|
continue; |
|
} |
|
if (temp != null) { |
|
queue = queue.concat(temp.getChildren()); |
|
} |
|
} |
|
}, |
|
|
|
traverse: function (callback) { |
|
this._traverse(this.root, callback); |
|
}, |
|
|
|
_recursion: function (node, route, callback) { |
|
var self = this; |
|
return BI.every(node.getChildren(), function (i, child) { |
|
var next = BI.clone(route); |
|
next.push(child.id); |
|
var b = callback && callback(child, next); |
|
if (b === false) { |
|
return false; |
|
} |
|
if (b === true) { |
|
return true; |
|
} |
|
return self._recursion(child, next, callback); |
|
}); |
|
}, |
|
|
|
recursion: function (callback) { |
|
this._recursion(this.root, [], callback); |
|
}, |
|
|
|
inOrderTraverse: function (callback) { |
|
this._inOrderTraverse(this.root, callback); |
|
}, |
|
|
|
// 中序遍历(递归) |
|
_inOrderTraverse: function (node, callback) { |
|
if (node != null) { |
|
this._inOrderTraverse(node.getLeft()); |
|
callback && callback(node); |
|
this._inOrderTraverse(node.getRight()); |
|
} |
|
}, |
|
|
|
// 中序遍历(非递归) |
|
nrInOrderTraverse: function (callback) { |
|
|
|
var stack = []; |
|
var node = this.root; |
|
while (node != null || !BI.isEmpty(stack)) { |
|
while (node != null) { |
|
stack.push(node); |
|
node = node.getLeft(); |
|
} |
|
node = stack.pop(); |
|
callback && callback(node); |
|
node = node.getRight(); |
|
} |
|
}, |
|
|
|
preOrderTraverse: function (callback) { |
|
this._preOrderTraverse(this.root, callback); |
|
}, |
|
|
|
// 先序遍历(递归) |
|
_preOrderTraverse: function (node, callback) { |
|
if (node != null) { |
|
callback && callback(node); |
|
this._preOrderTraverse(node.getLeft()); |
|
this._preOrderTraverse(node.getRight()); |
|
} |
|
}, |
|
|
|
// 先序遍历(非递归) |
|
nrPreOrderTraverse: function (callback) { |
|
|
|
var stack = []; |
|
var node = this.root; |
|
|
|
while (node != null || !BI.isEmpty(stack)) { |
|
|
|
while (node != null) { |
|
callback && callback(node); |
|
stack.push(node); |
|
node = node.getLeft(); |
|
} |
|
node = stack.pop(); |
|
node = node.getRight(); |
|
} |
|
}, |
|
|
|
postOrderTraverse: function (callback) { |
|
this._postOrderTraverse(this.root, callback); |
|
}, |
|
|
|
// 后序遍历(递归) |
|
_postOrderTraverse: function (node, callback) { |
|
if (node != null) { |
|
this._postOrderTraverse(node.getLeft()); |
|
this._postOrderTraverse(node.getRight()); |
|
callback && callback(node); |
|
} |
|
}, |
|
|
|
// 后续遍历(非递归) |
|
nrPostOrderTraverse: function (callback) { |
|
|
|
var stack = []; |
|
var node = this.root; |
|
var preNode = null;// 表示最近一次访问的节点 |
|
|
|
while (node != null || !BI.isEmpty(stack)) { |
|
|
|
while (node != null) { |
|
stack.push(node); |
|
node = node.getLeft(); |
|
} |
|
|
|
node = BI.last(stack); |
|
|
|
if (node.getRight() == null || node.getRight() == preNode) { |
|
callback && callback(node); |
|
node = stack.pop(); |
|
preNode = node; |
|
node = null; |
|
} else { |
|
node = node.getRight(); |
|
} |
|
} |
|
} |
|
}; |
|
|
|
BI.Node = function (id) { |
|
if (BI.isObject(id)) { |
|
BI.extend(this, id); |
|
} else { |
|
this.id = id; |
|
} |
|
this.clear.apply(this, arguments); |
|
}; |
|
|
|
BI.Node.prototype = { |
|
constructor: BI.Node, |
|
|
|
set: function (key, value) { |
|
if (BI.isObject(key)) { |
|
BI.extend(this, key); |
|
return; |
|
} |
|
this[key] = value; |
|
}, |
|
|
|
get: function (key) { |
|
return this[key]; |
|
}, |
|
|
|
isLeaf: function () { |
|
return BI.isEmpty(this.children); |
|
}, |
|
|
|
getChildren: function () { |
|
return this.children; |
|
}, |
|
|
|
getChildrenLength: function () { |
|
return this.children.length; |
|
}, |
|
|
|
getFirstChild: function () { |
|
return BI.first(this.children); |
|
}, |
|
|
|
getLastChild: function () { |
|
return BI.last(this.children); |
|
}, |
|
|
|
setLeft: function (left) { |
|
this.left = left; |
|
}, |
|
|
|
getLeft: function () { |
|
return this.left; |
|
}, |
|
|
|
setRight: function (right) { |
|
this.right = right; |
|
}, |
|
|
|
getRight: function () { |
|
return this.right; |
|
}, |
|
|
|
setParent: function (parent) { |
|
this.parent = parent; |
|
}, |
|
|
|
getParent: function () { |
|
return this.parent; |
|
}, |
|
|
|
getChild: function (index) { |
|
return this.children[index]; |
|
}, |
|
|
|
getChildIndex: function (id) { |
|
return BI.findIndex(this.children, function (i, ch) { |
|
return ch.get("id") === id; |
|
}); |
|
}, |
|
|
|
removeChild: function (id) { |
|
this.removeChildByIndex(this.getChildIndex(id)); |
|
}, |
|
|
|
removeChildByIndex: function (index) { |
|
var before = this.getChild(index - 1); |
|
var behind = this.getChild(index + 1); |
|
if (before != null) { |
|
before.setRight(behind || null); |
|
} |
|
if (behind != null) { |
|
behind.setLeft(before || null); |
|
} |
|
this.children.splice(index, 1); |
|
}, |
|
|
|
removeAllChilds: function () { |
|
this.children = []; |
|
}, |
|
|
|
addChild: function (child, index) { |
|
var cur = null; |
|
if (BI.isUndefined(index)) { |
|
cur = this.children.length - 1; |
|
} else { |
|
cur = index - 1; |
|
} |
|
child.setParent(this); |
|
if (cur >= 0) { |
|
this.getChild(cur) && this.getChild(cur).setRight(child); |
|
child.setLeft(this.getChild(cur)); |
|
} |
|
if (BI.isUndefined(index)) { |
|
this.children.push(child); |
|
} else { |
|
this.children.splice(index, 0, child); |
|
} |
|
}, |
|
|
|
equals: function (obj) { |
|
return this === obj || this.id === obj.id; |
|
}, |
|
|
|
clear: function () { |
|
this.parent = null; |
|
this.left = null; |
|
this.right = null; |
|
this.children = []; |
|
} |
|
}; |
|
|
|
BI.extend(BI.Tree, { |
|
transformToArrayFormat: function (nodes, pId) { |
|
if (!nodes) return []; |
|
var r = []; |
|
if (BI.isArray(nodes)) { |
|
for (var i = 0, l = nodes.length; i < l; i++) { |
|
var node = BI.clone(nodes[i]); |
|
node.pId = node.pId == null ? pId : node.pId; |
|
delete node.children; |
|
r.push(node); |
|
if (nodes[i]["children"]) { |
|
r = r.concat(BI.Tree.transformToArrayFormat(nodes[i]["children"], node.id)); |
|
} |
|
} |
|
} else { |
|
var newNodes = BI.clone(nodes); |
|
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId; |
|
delete newNodes.children; |
|
r.push(newNodes); |
|
if (nodes["children"]) { |
|
r = r.concat(BI.Tree.transformToArrayFormat(nodes["children"], newNodes.id)); |
|
} |
|
} |
|
return r; |
|
}, |
|
|
|
arrayFormat: function (nodes, pId) { |
|
if (!nodes) { |
|
return []; |
|
} |
|
var r = []; |
|
if (BI.isArray(nodes)) { |
|
for (var i = 0, l = nodes.length; i < l; i++) { |
|
var node = nodes[i]; |
|
node.pId = node.pId == null ? pId : node.pId; |
|
r.push(node); |
|
if (nodes[i]["children"]) { |
|
r = r.concat(BI.Tree.arrayFormat(nodes[i]["children"], node.id)); |
|
} |
|
} |
|
} else { |
|
var newNodes = nodes; |
|
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId; |
|
r.push(newNodes); |
|
if (nodes["children"]) { |
|
r = r.concat(BI.Tree.arrayFormat(nodes["children"], newNodes.id)); |
|
} |
|
} |
|
return r; |
|
}, |
|
|
|
transformToTreeFormat: function (sNodes) { |
|
var i, l; |
|
if (!sNodes) { |
|
return []; |
|
} |
|
|
|
if (BI.isArray(sNodes)) { |
|
var r = []; |
|
var tmpMap = {}; |
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
if (BI.isNull(sNodes[i].id)) { |
|
return sNodes; |
|
} |
|
tmpMap[sNodes[i].id] = BI.clone(sNodes[i]); |
|
} |
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) { |
|
if (!tmpMap[sNodes[i].pId].children) { |
|
tmpMap[sNodes[i].pId].children = []; |
|
} |
|
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]); |
|
} else { |
|
r.push(tmpMap[sNodes[i].id]); |
|
} |
|
delete tmpMap[sNodes[i].id].pId; |
|
} |
|
return r; |
|
} |
|
return [sNodes]; |
|
|
|
}, |
|
|
|
treeFormat: function (sNodes) { |
|
var i, l; |
|
if (!sNodes) { |
|
return []; |
|
} |
|
|
|
if (BI.isArray(sNodes)) { |
|
var r = []; |
|
var tmpMap = {}; |
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
if (BI.isNull(sNodes[i].id)) { |
|
return sNodes; |
|
} |
|
tmpMap[sNodes[i].id] = sNodes[i]; |
|
} |
|
for (i = 0, l = sNodes.length; i < l; i++) { |
|
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) { |
|
if (!tmpMap[sNodes[i].pId].children) { |
|
tmpMap[sNodes[i].pId].children = []; |
|
} |
|
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]); |
|
} else { |
|
r.push(tmpMap[sNodes[i].id]); |
|
} |
|
} |
|
return r; |
|
} |
|
return [sNodes]; |
|
|
|
}, |
|
|
|
traversal: function (array, callback) { |
|
if (BI.isNull(array)) { |
|
return; |
|
} |
|
var self = this; |
|
BI.some(array, function (i, item) { |
|
if (callback(i, item) === false) { |
|
return true; |
|
} |
|
self.traversal(item.children, callback); |
|
}); |
|
} |
|
}); |
|
})();// 向量操作 |
|
BI.Vector = function (x, y) { |
|
this.x = x; |
|
this.y = y; |
|
}; |
|
BI.Vector.prototype = { |
|
constructor: BI.Vector, |
|
cross: function (v) { |
|
return (this.x * v.y - this.y * v.x); |
|
}, |
|
length: function (v) { |
|
return (Math.sqrt(this.x * v.x + this.y * v.y)); |
|
} |
|
}; |
|
BI.Region = function (x, y, w, h) { |
|
this.x = x; |
|
this.y = y; |
|
this.w = w; |
|
this.h = h; |
|
}; |
|
BI.Region.prototype = { |
|
constructor: BI.Region, |
|
// 判断两个区域是否相交,若相交,则要么顶点互相包含,要么矩形边界(或对角线)相交 |
|
isIntersects: function (obj) { |
|
if (this.isPointInside(obj.x, obj.y) || |
|
this.isPointInside(obj.x + obj.w, obj.y) || |
|
this.isPointInside(obj.x, obj.y + obj.h) || |
|
this.isPointInside(obj.x + obj.w, obj.y + obj.h)) { |
|
return true; |
|
} else if (obj.isPointInside(this.x, this.y) || |
|
obj.isPointInside(this.x + this.w, this.y) || |
|
obj.isPointInside(this.x, this.y + this.h) || |
|
obj.isPointInside(this.x + this.w, this.y + this.h)) { |
|
return true; |
|
} else if (obj.x != null && obj.y != null)// 判断矩形对角线相交 |v1 X v2||v1 X v3| < 0 |
|
{ |
|
var vector1 = new BI.Vector(this.w, this.h);// 矩形对角线向量 |
|
var vector2 = new BI.Vector(obj.x - this.x, obj.y - this.y); |
|
var vector3 = new BI.Vector(vector2.x + obj.w, vector2.y + obj.h); |
|
if ((vector1.cross(vector2) * vector1.cross(vector3)) < 0) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
}, |
|
// 判断一个点是否在这个区域内部 |
|
isPointInside: function (x, y) { |
|
if (this.x == null || this.y == null) { |
|
return false; |
|
} |
|
if (x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h) { |
|
return true; |
|
} |
|
return false; |
|
}, |
|
// 返回区域的重心,因为是矩形所以返回中点 |
|
getPosition: function () { |
|
var pos = []; |
|
pos.push(this.x + this.w / 2); |
|
pos.push(this.y + this.h / 2); |
|
return pos; |
|
} |
|
};BI.BehaviorFactory = { |
|
createBehavior: function (key, options) { |
|
var behavior; |
|
switch (key) { |
|
case "highlight": |
|
behavior = BI.HighlightBehavior; |
|
break; |
|
case "redmark": |
|
behavior = BI.RedMarkBehavior; |
|
break; |
|
} |
|
return new behavior(options); |
|
} |
|
}; |
|
|
|
/** |
|
* guy |
|
* 行为控件 |
|
* @class BI.Behavior |
|
* @extends BI.OB |
|
*/ |
|
BI.Behavior = BI.inherit(BI.OB, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Behavior.superclass._defaultConfig.apply(this, arguments), { |
|
rule: function () {return true;} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Behavior.superclass._init.apply(this, arguments); |
|
|
|
}, |
|
|
|
doBehavior: function () { |
|
|
|
} |
|
});/** |
|
* 布局容器类 |
|
* @class BI.Layout |
|
* @extends BI.Widget |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Boolean} [options.scrollable=false] 子组件超出容器边界之后是否会出现滚动条 |
|
* @cfg {Boolean} [options.scrollx=false] 子组件超出容器边界之后是否会出现横向滚动条 |
|
* @cfg {Boolean} [options.scrolly=false] 子组件超出容器边界之后是否会出现纵向滚动条 |
|
*/ |
|
BI.Layout = BI.inherit(BI.Widget, { |
|
props: function () { |
|
return { |
|
scrollable: null, // true, false, null |
|
scrollx: false, // true, false |
|
scrolly: false, // true, false |
|
items: [] |
|
}; |
|
}, |
|
|
|
render: function () { |
|
this._init4Margin(); |
|
this._init4Scroll(); |
|
}, |
|
|
|
_init4Margin: function () { |
|
if (this.options.top) { |
|
this.element.css("top", this.options.top); |
|
} |
|
if (this.options.left) { |
|
this.element.css("left", this.options.left); |
|
} |
|
if (this.options.bottom) { |
|
this.element.css("bottom", this.options.bottom); |
|
} |
|
if (this.options.right) { |
|
this.element.css("right", this.options.right); |
|
} |
|
}, |
|
|
|
_init4Scroll: function () { |
|
switch (this.options.scrollable) { |
|
case true: |
|
this.element.css("overflow", "auto"); |
|
break; |
|
case false: |
|
this.element.css("overflow", "hidden"); |
|
break; |
|
default : |
|
break; |
|
} |
|
if (this.options.scrollx) { |
|
this.element.css({ |
|
"overflow-x": "auto", |
|
"overflow-y": "hidden" |
|
}); |
|
} |
|
if (this.options.scrolly) { |
|
this.element.css({ |
|
"overflow-x": "hidden", |
|
"overflow-y": "auto" |
|
}); |
|
} |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.element.append(frag); |
|
}, |
|
|
|
_mountChildren: function () { |
|
var self = this; |
|
var frag = BI.Widget._renderEngine.createFragment(); |
|
var hasChild = false; |
|
BI.each(this._children, function (i, widget) { |
|
if (widget.element !== self.element) { |
|
frag.appendChild(widget.element[0]); |
|
hasChild = true; |
|
} |
|
}); |
|
if (hasChild === true) { |
|
this.appendFragment(frag); |
|
} |
|
}, |
|
|
|
_getChildName: function (index) { |
|
return index + ""; |
|
}, |
|
|
|
_addElement: function (i, item, context) { |
|
var self = this, w; |
|
if (!this.hasWidget(this._getChildName(i))) { |
|
w = BI.createWidget(item, context); |
|
w.on(BI.Events.DESTROY, function () { |
|
BI.each(self._children, function (name, child) { |
|
if (child === w) { |
|
BI.remove(self._children, child); |
|
self.removeItemAt(name | 0); |
|
} |
|
}); |
|
}); |
|
this.addWidget(this._getChildName(i), w); |
|
} else { |
|
w = this.getWidgetByName(this._getChildName(i)); |
|
} |
|
return w; |
|
}, |
|
|
|
_getOptions: function (item) { |
|
if (item instanceof BI.Widget) { |
|
item = item.options; |
|
} |
|
item = BI.stripEL(item); |
|
if (item instanceof BI.Widget) { |
|
item = item.options; |
|
} |
|
return item; |
|
}, |
|
|
|
_compare: function (item1, item2) { |
|
var self = this; |
|
return eq(item1, item2); |
|
|
|
// 不比较函数 |
|
function eq (a, b, aStack, bStack) { |
|
if (a === b) { |
|
return a !== 0 || 1 / a === 1 / b; |
|
} |
|
if (a == null || b == null) { |
|
return a === b; |
|
} |
|
var className = Object.prototype.toString.call(a); |
|
switch (className) { |
|
case "[object RegExp]": |
|
case "[object String]": |
|
return "" + a === "" + b; |
|
case "[object Number]": |
|
if (+a !== +a) { |
|
return +b !== +b; |
|
} |
|
return +a === 0 ? 1 / +a === 1 / b : +a === +b; |
|
case "[object Date]": |
|
case "[object Boolean]": |
|
return +a === +b; |
|
} |
|
|
|
var areArrays = className === "[object Array]"; |
|
if (!areArrays) { |
|
if (BI.isFunction(a) && BI.isFunction(b)) { |
|
return true; |
|
} |
|
a = self._getOptions(a); |
|
b = self._getOptions(b); |
|
} |
|
|
|
aStack = aStack || []; |
|
bStack = bStack || []; |
|
var length = aStack.length; |
|
while (length--) { |
|
if (aStack[length] === a) { |
|
return bStack[length] === b; |
|
} |
|
} |
|
|
|
aStack.push(a); |
|
bStack.push(b); |
|
|
|
if (areArrays) { |
|
length = a.length; |
|
if (length !== b.length) { |
|
return false; |
|
} |
|
while (length--) { |
|
if (!eq(a[length], b[length], aStack, bStack)) { |
|
return false; |
|
} |
|
} |
|
} else { |
|
var keys = _.keys(a), key; |
|
length = keys.length; |
|
if (_.keys(b).length !== length) { |
|
return false; |
|
} |
|
while (length--) { |
|
key = keys[length]; |
|
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) { |
|
return false; |
|
} |
|
} |
|
} |
|
aStack.pop(); |
|
bStack.pop(); |
|
return true; |
|
} |
|
}, |
|
|
|
_getWrapper: function () { |
|
return this.element; |
|
}, |
|
|
|
_addItemAt: function (index, item) { |
|
for (var i = this.options.items.length; i > index; i--) { |
|
this._children[this._getChildName(i)] = this._children[this._getChildName(i - 1)]; |
|
} |
|
delete this._children[this._getChildName(index)]; |
|
this.options.items.splice(index, 0, item); |
|
}, |
|
|
|
_removeItemAt: function (index) { |
|
for (var i = index; i < this.options.items.length - 1; i++) { |
|
this._children[this._getChildName(i)] = this._children[this._getChildName(i + 1)]; |
|
} |
|
delete this._children[this._getChildName(this.options.items.length - 1)]; |
|
this.options.items.splice(index, 1); |
|
}, |
|
|
|
/** |
|
* 添加一个子组件到容器中 |
|
* @param {JSON/BI.Widget} item 子组件 |
|
*/ |
|
addItem: function (item) { |
|
return this.addItemAt(this.options.items.length, item); |
|
}, |
|
|
|
prependItem: function (item) { |
|
return this.addItemAt(0, item); |
|
}, |
|
|
|
addItemAt: function (index, item) { |
|
if (index < 0 || index > this.options.items.length) { |
|
return; |
|
} |
|
this._addItemAt(index, item); |
|
var w = this._addElement(index, item); |
|
if (index > 0) { |
|
this._children[this._getChildName(index - 1)].element.after(w.element); |
|
} else { |
|
w.element.prependTo(this._getWrapper()); |
|
} |
|
w._mount(); |
|
return w; |
|
}, |
|
|
|
removeItemAt: function (indexes) { |
|
indexes = BI.isArray(indexes) ? indexes : [indexes]; |
|
var deleted = []; |
|
var newItems = [], newChildren = {}; |
|
for (var i = 0, len = this.options.items.length; i < len; i++) { |
|
var child = this._children[this._getChildName(i)]; |
|
if (BI.contains(indexes, i)) { |
|
child && deleted.push(child); |
|
} else { |
|
newChildren[this._getChildName(newItems.length)] = child; |
|
newItems.push(this.options.items[i]); |
|
} |
|
} |
|
this.options.items = newItems; |
|
this._children = newChildren; |
|
BI.each(deleted, function (i, c) { |
|
c._destroy(); |
|
}); |
|
}, |
|
|
|
shouldUpdateItem: function (index, item) { |
|
if (index < 0 || index > this.options.items.length - 1) { |
|
return false; |
|
} |
|
var child = this._children[this._getChildName(index)]; |
|
if (!child.shouldUpdate) { |
|
return null; |
|
} |
|
return child.shouldUpdate(this._getOptions(item)) === true; |
|
}, |
|
|
|
updateItemAt: function (index, item) { |
|
if (index < 0 || index > this.options.items.length - 1) { |
|
return; |
|
} |
|
|
|
var child = this._children[this._getChildName(index)]; |
|
var updated; |
|
if (updated = child.update(this._getOptions(item))) { |
|
return updated; |
|
} |
|
var del = this._children[this._getChildName(index)]; |
|
delete this._children[this._getChildName(index)]; |
|
this.options.items.splice(index, 1); |
|
var w = this._addElement(index, item); |
|
this.options.items.splice(index, 0, item); |
|
this._children[this._getChildName(index)] = w; |
|
if (index > 0) { |
|
this._children[this._getChildName(index - 1)].element.after(w.element); |
|
} else { |
|
w.element.prependTo(this._getWrapper()); |
|
} |
|
del._destroy(); |
|
w._mount(); |
|
}, |
|
|
|
addItems: function (items, context) { |
|
var self = this, o = this.options; |
|
var fragment = BI.Widget._renderEngine.createFragment(); |
|
var added = []; |
|
BI.each(items, function (i, item) { |
|
var w = self._addElement(o.items.length, item, context); |
|
self._children[self._getChildName(o.items.length)] = w; |
|
o.items.push(item); |
|
added.push(w); |
|
fragment.appendChild(w.element[0]); |
|
}); |
|
if (this._isMounted) { |
|
this._getWrapper().append(fragment); |
|
BI.each(added, function (i, w) { |
|
w._mount(); |
|
}); |
|
} |
|
}, |
|
|
|
prependItems: function (items, context) { |
|
var self = this; |
|
items = items || []; |
|
var fragment = BI.Widget._renderEngine.createFragment(); |
|
var added = []; |
|
for (var i = items.length - 1; i >= 0; i--) { |
|
this._addItemAt(0, items[i]); |
|
var w = this._addElement(0, items[i], context); |
|
self._children[self._getChildName(0)] = w; |
|
this.options.items.unshift(items[i]); |
|
added.push(w); |
|
fragment.appendChild(w.element[0]); |
|
} |
|
if (this._isMounted) { |
|
this._getWrapper().prepend(fragment); |
|
BI.each(added, function (i, w) { |
|
w._mount(); |
|
}); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
var self = this, value = [], child; |
|
BI.each(this.options.items, function (i) { |
|
if (child = self._children[self._getChildName(i)]) { |
|
var v = child.getValue(); |
|
v = BI.isArray(v) ? v : [v]; |
|
value = value.concat(v); |
|
} |
|
}); |
|
return value; |
|
}, |
|
|
|
setValue: function (v) { |
|
var self = this, child; |
|
BI.each(this.options.items, function (i) { |
|
if (child = self._children[self._getChildName(i)]) { |
|
child.setValue(v); |
|
} |
|
}); |
|
}, |
|
|
|
setText: function (v) { |
|
var self = this, child; |
|
BI.each(this.options.items, function (i) { |
|
if (child = self._children[self._getChildName(i)]) { |
|
child.setText(v); |
|
} |
|
}); |
|
}, |
|
|
|
patchItem: function (oldVnode, vnode, index) { |
|
var shouldUpdate = this.shouldUpdateItem(index, vnode); |
|
if (shouldUpdate === true || (shouldUpdate === null && !this._compare(oldVnode, vnode))) { |
|
return this.updateItemAt(index, vnode); |
|
} |
|
}, |
|
|
|
updateChildren: function (oldCh, newCh) { |
|
var self = this; |
|
var oldStartIdx = 0, newStartIdx = 0; |
|
var oldEndIdx = oldCh.length - 1; |
|
var oldStartVnode = oldCh[0]; |
|
var oldEndVnode = oldCh[oldEndIdx]; |
|
var newEndIdx = newCh.length - 1; |
|
var newStartVnode = newCh[0]; |
|
var newEndVnode = newCh[newEndIdx]; |
|
var before; |
|
var updated; |
|
var children = {}; |
|
BI.each(oldCh, function (i, child) { |
|
child = self._getOptions(child); |
|
var key = child.key == null ? i : child.key; |
|
if (BI.isKey(key)) { |
|
children[key] = self._children[self._getChildName(i)]; |
|
} |
|
}); |
|
|
|
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { |
|
if (BI.isNull(oldStartVnode)) { |
|
oldStartVnode = oldCh[++oldStartIdx]; |
|
} else if (BI.isNull(oldEndVnode)) { |
|
oldEndVnode = oldCh[--oldEndIdx]; |
|
} else if (sameVnode(oldStartVnode, newStartVnode, oldStartIdx, newStartIdx)) { |
|
updated = this.patchItem(oldStartVnode, newStartVnode, oldStartIdx) || updated; |
|
children[oldStartVnode.key == null ? this._getChildName(oldStartIdx) : oldStartVnode.key] = this._children[this._getChildName(oldStartIdx)]; |
|
oldStartVnode = oldCh[++oldStartIdx]; |
|
newStartVnode = newCh[++newStartIdx]; |
|
} else if (sameVnode(oldEndVnode, newEndVnode, oldEndIdx, newEndIdx)) { |
|
updated = this.patchItem(oldEndVnode, newEndVnode, oldEndIdx) || updated; |
|
children[oldEndVnode.key == null ? this._getChildName(oldEndIdx) : oldEndVnode.key] = this._children[this._getChildName(oldEndIdx)]; |
|
oldEndVnode = oldCh[--oldEndIdx]; |
|
newEndVnode = newCh[--newEndIdx]; |
|
} else if (sameVnode(oldStartVnode, newEndVnode)) { |
|
updated = this.patchItem(oldStartVnode, newEndVnode, oldStartIdx) || updated; |
|
children[oldStartVnode.key == null ? this._getChildName(oldStartIdx) : oldStartVnode.key] = this._children[this._getChildName(oldStartIdx)]; |
|
insertBefore(oldStartVnode, oldEndVnode, true); |
|
oldStartVnode = oldCh[++oldStartIdx]; |
|
newEndVnode = newCh[--newEndIdx]; |
|
} else if (sameVnode(oldEndVnode, newStartVnode)) { |
|
updated = this.patchItem(oldEndVnode, newStartVnode, oldEndIdx) || updated; |
|
children[oldEndVnode.key == null ? this._getChildName(oldEndIdx) : oldEndVnode.key] = this._children[this._getChildName(oldEndIdx)]; |
|
insertBefore(oldEndVnode, oldStartVnode); |
|
oldEndVnode = oldCh[--oldEndIdx]; |
|
newStartVnode = newCh[++newStartIdx]; |
|
} else { |
|
var sameOldVnode = findOldVnode(oldCh, newStartVnode, oldStartIdx, oldEndIdx); |
|
if (BI.isNull(sameOldVnode)) { // 不存在就把新的放到左边 |
|
var node = addNode(newStartVnode); |
|
insertBefore(node, oldStartVnode); |
|
newStartVnode = newCh[++newStartIdx]; |
|
} else { // 如果新节点在就旧节点区间中存在就复用一下 |
|
BI.each(oldCh, function (index, child) { |
|
if (child && sameVnode(child, newStartVnode)) { |
|
updated = self.patchItem(sameOldVnode, newStartVnode, index) || updated; |
|
children[sameOldVnode.key == null ? self._getChildName(index) : sameOldVnode.key] = self._children[self._getChildName(index)]; |
|
oldCh[index] = undefined; |
|
insertBefore(sameOldVnode, oldStartVnode); |
|
} |
|
}); |
|
newStartVnode = newCh[++newStartIdx]; |
|
} |
|
} |
|
} |
|
if (oldStartIdx > oldEndIdx) { |
|
before = BI.isNull(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1]; |
|
addVnodes(before, newCh, newStartIdx, newEndIdx); |
|
} else if (newStartIdx > newEndIdx) { |
|
removeVnodes(oldCh, oldStartIdx, oldEndIdx); |
|
} |
|
|
|
this._children = {}; |
|
BI.each(newCh, function (i, child) { |
|
var node = self._getOptions(child); |
|
var key = node.key == null ? self._getChildName(i) : node.key; |
|
children[key]._mount(); |
|
self._children[self._getChildName(i)] = children[key]; |
|
}); |
|
|
|
function sameVnode (vnode1, vnode2, oldIndex, newIndex) { |
|
vnode1 = self._getOptions(vnode1); |
|
vnode2 = self._getOptions(vnode2); |
|
if (BI.isKey(vnode1.key)) { |
|
return vnode1.key === vnode2.key; |
|
} |
|
if (oldIndex >= 0) { |
|
return oldIndex === newIndex; |
|
} |
|
} |
|
|
|
function addNode (vnode, index) { |
|
var opt = self._getOptions(vnode); |
|
var key = opt.key == null ? self._getChildName(index) : opt.key; |
|
return children[key] = self._addElement(key, vnode); |
|
} |
|
|
|
function addVnodes (before, vnodes, startIdx, endIdx) { |
|
for (; startIdx <= endIdx; ++startIdx) { |
|
var node = addNode(vnodes[startIdx], startIdx); |
|
insertBefore(node, before, false, startIdx); |
|
} |
|
} |
|
|
|
function removeVnodes (vnodes, startIdx, endIdx) { |
|
for (; startIdx <= endIdx; ++startIdx) { |
|
var ch = vnodes[startIdx]; |
|
if (BI.isNotNull(ch)) { |
|
var node = self._getOptions(ch); |
|
var key = node.key == null ? self._getChildName(startIdx) : node.key; |
|
delete self._children[self._getChildName(key)]; |
|
children[key]._destroy(); |
|
} |
|
} |
|
} |
|
|
|
function insertBefore (insert, before, isNext, index) { |
|
insert = self._getOptions(insert); |
|
before = before && self._getOptions(before); |
|
var insertKey = BI.isKey(insert.key) ? insert.key : self._getChildName(index); |
|
if (before && children[before.key]) { |
|
var beforeKey = BI.isKey(before.key) ? before.key : self._getChildName(index); |
|
var next; |
|
if (isNext) { |
|
next = children[beforeKey].element.next(); |
|
} else { |
|
next = children[beforeKey].element; |
|
} |
|
if (next.length > 0) { |
|
next.before(children[insertKey].element); |
|
} else { |
|
self._getWrapper().append(children[insertKey].element); |
|
} |
|
} else { |
|
self._getWrapper().append(children[insertKey].element); |
|
} |
|
} |
|
|
|
function findOldVnode (vnodes, vNode, beginIdx, endIdx) { |
|
var i, found; |
|
for (i = beginIdx; i <= endIdx; ++i) { |
|
if (vnodes[i] && sameVnode(vnodes[i], vNode)) { |
|
found = vnodes[i]; |
|
} |
|
} |
|
return found; |
|
} |
|
|
|
return updated; |
|
}, |
|
|
|
update: function (opt) { |
|
var o = this.options; |
|
var items = opt.items || []; |
|
var updated = this.updateChildren(o.items, items); |
|
this.options.items = items; |
|
return updated; |
|
// var updated, i, len; |
|
// for (i = 0, len = Math.min(o.items.length, items.length); i < len; i++) { |
|
// if (!this._compare(o.items[i], items[i])) { |
|
// updated = this.updateItemAt(i, items[i]) || updated; |
|
// } |
|
// } |
|
// if (o.items.length > items.length) { |
|
// var deleted = []; |
|
// for (i = items.length; i < o.items.length; i++) { |
|
// deleted.push(this._children[this._getChildName(i)]); |
|
// delete this._children[this._getChildName(i)]; |
|
// } |
|
// o.items.splice(items.length); |
|
// BI.each(deleted, function (i, w) { |
|
// w._destroy(); |
|
// }) |
|
// } else if (items.length > o.items.length) { |
|
// for (i = o.items.length; i < items.length; i++) { |
|
// this.addItemAt(i, items[i]); |
|
// } |
|
// } |
|
// return updated; |
|
}, |
|
|
|
stroke: function (items) { |
|
var self = this; |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
self._addElement(i, item); |
|
} |
|
}); |
|
}, |
|
|
|
removeWidget: function (nameOrWidget) { |
|
var removeIndex; |
|
if (BI.isWidget(nameOrWidget)) { |
|
BI.each(this._children, function (name, child) { |
|
if (child === nameOrWidget) { |
|
removeIndex = name; |
|
} |
|
}); |
|
} else { |
|
removeIndex = nameOrWidget; |
|
} |
|
if (removeIndex) { |
|
this._removeItemAt(removeIndex | 0); |
|
} |
|
}, |
|
|
|
empty: function () { |
|
BI.Layout.superclass.empty.apply(this, arguments); |
|
this.options.items = []; |
|
}, |
|
|
|
destroy: function () { |
|
BI.Layout.superclass.destroy.apply(this, arguments); |
|
this.options.items = []; |
|
}, |
|
|
|
populate: function (items) { |
|
var self = this, o = this.options; |
|
items = items || []; |
|
if (this._isMounted) { |
|
this.update({items: items}); |
|
return; |
|
} |
|
this.options.items = items; |
|
this.stroke(items); |
|
}, |
|
|
|
resize: function () { |
|
|
|
} |
|
}); |
|
BI.shortcut("bi.layout", BI.Layout); |
|
BI.Plugin = BI.Plugin || {}; |
|
!(function () { |
|
var _WidgetsPlugin = {}; |
|
var _ObjectPlugin = {}; |
|
var _ConfigPlugin = {}; |
|
var _GlobalWidgetConfigFn, _GlobalObjectConfigFn; |
|
BI.extend(BI.Plugin, { |
|
|
|
getWidget: function (type, options) { |
|
if (_GlobalWidgetConfigFn) { |
|
_GlobalWidgetConfigFn(type, options); |
|
} |
|
var res; |
|
if (_ConfigPlugin[type]) { |
|
for (var i = _ConfigPlugin[type].length - 1; i >= 0; i--) { |
|
if (res = _ConfigPlugin[type][i](options)) { |
|
options = res; |
|
} |
|
} |
|
} |
|
// Deprecated |
|
if (_WidgetsPlugin[type]) { |
|
for (var i = _WidgetsPlugin[type].length - 1; i >= 0; i--) { |
|
if (res = _WidgetsPlugin[type][i](options)) { |
|
return res; |
|
} |
|
} |
|
} |
|
return options; |
|
}, |
|
|
|
config: function (widgetConfigFn, objectConfigFn) { |
|
_GlobalWidgetConfigFn = widgetConfigFn; |
|
_GlobalObjectConfigFn = objectConfigFn; |
|
}, |
|
|
|
configWidget: function (type, fn) { |
|
if (!_ConfigPlugin[type]) { |
|
_ConfigPlugin[type] = []; |
|
} |
|
_ConfigPlugin[type].push(fn); |
|
}, |
|
|
|
registerWidget: function (type, fn) { |
|
if (!_WidgetsPlugin[type]) { |
|
_WidgetsPlugin[type] = []; |
|
} |
|
if (_WidgetsPlugin[type].length > 0) { |
|
console.log("组件已经注册过了!"); |
|
} |
|
_WidgetsPlugin[type].push(fn); |
|
}, |
|
|
|
relieveWidget: function (type) { |
|
delete _WidgetsPlugin[type]; |
|
}, |
|
|
|
getObject: function (type, object) { |
|
if (_GlobalObjectConfigFn) { |
|
_GlobalObjectConfigFn(type, object); |
|
} |
|
if (_ObjectPlugin[type]) { |
|
var res; |
|
for (var i = 0, len = _ObjectPlugin[type].length; i < len; i++) { |
|
if (res = _ObjectPlugin[type][i](object)) { |
|
object = res; |
|
}; |
|
} |
|
} |
|
return res || object; |
|
}, |
|
|
|
registerObject: function (type, fn) { |
|
if (!_ObjectPlugin[type]) { |
|
_ObjectPlugin[type] = []; |
|
} |
|
if (_ObjectPlugin[type].length > 0) { |
|
console.log("对象已经注册过了!"); |
|
} |
|
_ObjectPlugin[type].push(fn); |
|
}, |
|
|
|
relieveObject: function (type) { |
|
delete _ObjectPlugin[type]; |
|
} |
|
}); |
|
})();/** |
|
* guy |
|
* 由一个元素切换到另一个元素的行为 |
|
* @class BI.Action |
|
* @extends BI.OB |
|
* @abstract |
|
*/ |
|
BI.Action = BI.inherit(BI.OB, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Action.superclass._defaultConfig.apply(this, arguments), { |
|
src: null, |
|
tar: null |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Action.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
actionPerformed: function (src, tar, callback) { |
|
|
|
}, |
|
|
|
actionBack: function (tar, src, callback) { |
|
|
|
} |
|
}); |
|
|
|
BI.ActionFactory = { |
|
createAction: function (key, options) { |
|
var action; |
|
switch (key) { |
|
case "show": |
|
action = BI.ShowAction; |
|
break; |
|
} |
|
return new action(options); |
|
} |
|
};/** |
|
* guy |
|
* 由一个元素切换到另一个元素的行为 |
|
* @class BI.ShowAction |
|
* @extends BI.Action |
|
*/ |
|
BI.ShowAction = BI.inherit(BI.Action, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ShowAction.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ShowAction.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
actionPerformed: function (src, tar, callback) { |
|
tar = tar || this.options.tar; |
|
tar.setVisible(true); |
|
callback && callback(); |
|
}, |
|
|
|
actionBack: function (tar, src, callback) { |
|
tar = tar || this.options.tar; |
|
tar.setVisible(false); |
|
callback && callback(); |
|
} |
|
});(function () { |
|
var _global; |
|
if (typeof window !== "undefined") { |
|
_global = window; |
|
} else if (typeof global !== "undefined") { |
|
_global = global; |
|
} else if (typeof self !== "undefined") { |
|
_global = self; |
|
} else { |
|
_global = this; |
|
} |
|
if (!_global.BI) { |
|
_global.BI = {}; |
|
} |
|
|
|
function isEmpty (value) { |
|
// 判断是否为空值 |
|
var result = value === "" || value === null || value === undefined; |
|
return result; |
|
} |
|
|
|
// 判断是否是无效的日期 |
|
function isInvalidDate (date) { |
|
return date == "Invalid Date" || date == "NaN"; |
|
} |
|
|
|
/** |
|
* CHART-1400 |
|
* 使用数值计算的方式来获取任意数值的科学技术表示值。 |
|
* 科学计数格式 |
|
*/ |
|
function _eFormat (text, fmt) { |
|
text = +text; |
|
|
|
return eFormat(text, fmt); |
|
|
|
/** |
|
* 科学计数格式具体计算过程 |
|
* @param num |
|
* @param format {String}有两种形式, |
|
* 1、"0.00E00"这样的字符串表示正常的科学计数表示,只不过规定了数值精确到百分位, |
|
* 而数量级的绝对值如果是10以下的时候在前面补零。 |
|
* 2、 "##0.0E0"这样的字符串则规定用科学计数法表示之后的数值的整数部分是三位,精确到十分位, |
|
* 数量级没有规定,因为没见过实数里有用科学计数法表示之后E的后面会小于一位的情况(0无所谓)。 |
|
* @returns {*} |
|
*/ |
|
function eFormat (num, format) { |
|
var neg = num < 0 ? (num *= -1, "-") : "", |
|
magnitudeNeg = ""; |
|
|
|
var funcName = num > 0 && num < 1 ? "floor" : "ceil"; // -0.9999->-1 |
|
// 数量级 |
|
var magnitude = Math[funcName](Math.log(num) / Math.log(10)); |
|
|
|
if (!isFinite(magnitude)) { |
|
return format.replace(/#/ig, "").replace(/\.e/ig, "E"); |
|
} |
|
|
|
num = num / Math.pow(10, magnitude); |
|
|
|
// 让num转化成[1, 10)区间上的数 |
|
if (num > 0 && num < 1) { |
|
num *= 10; |
|
magnitude -= 1; |
|
} |
|
|
|
// 计算出format中需要显示的整数部分的位数,然后更新这个数值,也更新数量级 |
|
var integerLen = getInteger(magnitude, format); |
|
integerLen > 1 && (magnitude -= integerLen - 1, num *= Math.pow(10, integerLen - 1)); |
|
|
|
magnitude < 0 && (magnitudeNeg = "-", magnitude *= -1); |
|
|
|
// 获取科学计数法精确到的位数 |
|
var precision = getPrecision(format); |
|
// 判断num经过四舍五入之后是否有进位 |
|
var isValueCarry = isValueCarried(num); |
|
|
|
num *= Math.pow(10, precision); |
|
num = Math.round(num); |
|
// 如果出现进位的情况,将num除以10 |
|
isValueCarry && (num /= 10, magnitude += magnitudeNeg === "-" ? -1 : 1); |
|
num /= Math.pow(10, precision); |
|
|
|
// 小数部分保留precision位 |
|
num = num.toFixed(precision); |
|
// 格式化指数的部分 |
|
magnitude = formatExponential(format, magnitude, magnitudeNeg); |
|
|
|
return neg + num + "E" + magnitude; |
|
} |
|
|
|
// 获取format格式规定的数量级的形式 |
|
function formatExponential (format, num, magnitudeNeg) { |
|
num += ""; |
|
if (!/e/ig.test(format)) { |
|
return num; |
|
} |
|
format = format.split(/e/ig)[1]; |
|
|
|
while (num.length < format.length) { |
|
num = "0" + num; |
|
} |
|
|
|
// 如果magnitudeNeg是一个"-",而且num正好全是0,那么就别显示负号了 |
|
var isAllZero = true; |
|
for (var i = 0, len = num.length; i < len; i++) { |
|
if (!isAllZero) { |
|
continue; |
|
} |
|
isAllZero = num.charAt(i) === "0"; |
|
} |
|
magnitudeNeg = isAllZero ? "" : magnitudeNeg; |
|
|
|
return magnitudeNeg + num; |
|
} |
|
|
|
// 获取format规定的科学计数法精确到的位数 |
|
function getPrecision (format) { |
|
if (!/e/ig.test(format)) { |
|
return 0; |
|
} |
|
var arr = format.split(/e/ig)[0].split("."); |
|
|
|
return arr.length > 1 ? arr[1].length : 0; |
|
} |
|
|
|
// 获取数值科学计数法表示之后整数的位数 |
|
// 这边我们还需要考虑#和0的问题 |
|
function getInteger (magnitude, format) { |
|
if (!/e/ig.test(format)) { |
|
return 0; |
|
} |
|
// return format.split(/e/ig)[0].split(".")[0].length; |
|
|
|
var formatLeft = format.split(/e/ig)[0].split(".")[0], i, f, len = formatLeft.length; |
|
var valueLeftLen = 0; |
|
|
|
for (i = 0; i < len; i++) { |
|
f = formatLeft.charAt(i); |
|
// "#"所在的位置到末尾长度小于等于值的整数部分长度,那么这个#才可以占位 |
|
if (f == 0 || (f == "#" && (len - i <= magnitude + 1))) { |
|
valueLeftLen++; |
|
} |
|
} |
|
|
|
return valueLeftLen; |
|
} |
|
|
|
// 判断num通过round函数之后是否有进位 |
|
function isValueCarried (num) { |
|
var roundNum = Math.round(num); |
|
num = (num + "").split(".")[0]; |
|
roundNum = (roundNum + "").split(".")[0]; |
|
return num.length !== roundNum.length; |
|
} |
|
} |
|
|
|
//'#.##'之类的格式处理 1.324e-18 这种的科学数字 |
|
function _dealNumberPrecision (text, fright) { |
|
if (/[eE]/.test(text)) { |
|
var precision = 0, i = 0, ch; |
|
|
|
if (/[%‰]$/.test(fright)) { |
|
precision = /[%]$/.test(fright) ? 2 : 3; |
|
} |
|
|
|
for (var len = fright.length; i < len; i++) { |
|
if ((ch = fright.charAt(i)) == "0" || ch == "#") { |
|
precision++; |
|
} |
|
} |
|
return Number(text).toFixed(precision); |
|
} |
|
|
|
return text; |
|
} |
|
|
|
/** |
|
* 数字格式 |
|
*/ |
|
function _numberFormat (text, format) { |
|
var text = text + ""; |
|
|
|
//在调用数字格式的时候如果text里没有任何数字则不处理 |
|
if (!(/[0-9]/.test(text)) || !format) { |
|
return text; |
|
} |
|
|
|
// 数字格式,区分正负数 |
|
var numMod = format.indexOf(";"); |
|
if (numMod > -1) { |
|
if (text >= 0) { |
|
return _numberFormat(text + "", format.substring(0, numMod)); |
|
} |
|
return _numberFormat((-text) + "", format.substr(numMod + 1)); |
|
|
|
} else { |
|
// 兼容格式处理负数的情况(copy:fr-jquery.format.js) |
|
if (+text < 0 && format.charAt(0) !== "-") { |
|
return _numberFormat((-text) + "", "-" + format); |
|
} |
|
} |
|
|
|
var fp = format.split("."), fleft = fp[0] || "", fright = fp[1] || ""; |
|
text = _dealNumberPrecision(text, fright); |
|
var tp = text.split("."), tleft = tp[0] || "", tright = tp[1] || ""; |
|
|
|
// 百分比,千分比的小数点移位处理 |
|
if (/[%‰]$/.test(format)) { |
|
var paddingZero = /[%]$/.test(format) ? "00" : "000"; |
|
tright += paddingZero; |
|
tleft += tright.substr(0, paddingZero.length); |
|
tleft = tleft.replace(/^0+/gi, ""); |
|
tright = tright.substr(paddingZero.length).replace(/0+$/gi, ""); |
|
} |
|
var right = _dealWithRight(tright, fright); |
|
if (right.leftPlus) { |
|
// 小数点后有进位 |
|
tleft = parseInt(tleft) + 1 + ""; |
|
|
|
tleft = isNaN(tleft) ? "1" : tleft; |
|
} |
|
right = right.num; |
|
var left = _dealWithLeft(tleft, fleft); |
|
if (!(/[0-9]/.test(left))) { |
|
left = left + "0"; |
|
} |
|
if (!(/[0-9]/.test(right))) { |
|
return left + right; |
|
} else { |
|
return left + "." + right; |
|
} |
|
} |
|
|
|
/** |
|
* 处理小数点右边小数部分 |
|
* @param tright 右边内容 |
|
* @param fright 右边格式 |
|
* @returns {JSON} 返回处理结果和整数部分是否需要进位 |
|
* @private |
|
*/ |
|
function _dealWithRight (tright, fright) { |
|
var right = "", j = 0, i = 0; |
|
for (var len = fright.length; i < len; i++) { |
|
var ch = fright.charAt(i); |
|
var c = tright.charAt(j); |
|
switch (ch) { |
|
case "0": |
|
if (isEmpty(c)) { |
|
c = "0"; |
|
} |
|
right += c; |
|
j++; |
|
break; |
|
case "#": |
|
right += c; |
|
j++; |
|
break; |
|
default : |
|
right += ch; |
|
break; |
|
} |
|
} |
|
var rll = tright.substr(j); |
|
var result = {}; |
|
if (!isEmpty(rll) && rll.charAt(0) > 4) { |
|
// 有多余字符,需要四舍五入 |
|
result.leftPlus = true; |
|
var numReg = right.match(/^[0-9]+/); |
|
if (numReg) { |
|
var num = numReg[0]; |
|
var orilen = num.length; |
|
var newnum = parseInt(num) + 1 + ""; |
|
// 进位到整数部分 |
|
if (newnum.length > orilen) { |
|
newnum = newnum.substr(1); |
|
} else { |
|
newnum = BI.leftPad(newnum, orilen, "0"); |
|
result.leftPlus = false; |
|
} |
|
right = right.replace(/^[0-9]+/, newnum); |
|
} |
|
} |
|
result.num = right; |
|
return result; |
|
} |
|
|
|
/** |
|
* 处理小数点左边整数部分 |
|
* @param tleft 左边内容 |
|
* @param fleft 左边格式 |
|
* @returns {string} 返回处理结果 |
|
* @private |
|
*/ |
|
function _dealWithLeft (tleft, fleft) { |
|
var left = ""; |
|
var j = tleft.length - 1; |
|
var combo = -1, last = -1; |
|
var i = fleft.length - 1; |
|
for (; i >= 0; i--) { |
|
var ch = fleft.charAt(i); |
|
var c = tleft.charAt(j); |
|
switch (ch) { |
|
case "0": |
|
if (isEmpty(c)) { |
|
c = "0"; |
|
} |
|
last = -1; |
|
left = c + left; |
|
j--; |
|
break; |
|
case "#": |
|
last = i; |
|
left = c + left; |
|
j--; |
|
break; |
|
case ",": |
|
if (!isEmpty(c)) { |
|
// 计算一个,分隔区间的长度 |
|
var com = fleft.match(/,[#0]+/); |
|
if (com) { |
|
combo = com[0].length - 1; |
|
} |
|
left = "," + left; |
|
} |
|
break; |
|
default : |
|
left = ch + left; |
|
break; |
|
} |
|
} |
|
if (last > -1) { |
|
// 处理剩余字符 |
|
var tll = tleft.substr(0, j + 1); |
|
left = left.substr(0, last) + tll + left.substr(last); |
|
} |
|
if (combo > 0) { |
|
// 处理,分隔区间 |
|
var res = left.match(/[0-9]+,/); |
|
if (res) { |
|
res = res[0]; |
|
var newstr = "", n = res.length - 1 - combo; |
|
for (; n >= 0; n = n - combo) { |
|
newstr = res.substr(n, combo) + "," + newstr; |
|
} |
|
var lres = res.substr(0, n + combo); |
|
if (!isEmpty(lres)) { |
|
newstr = lres + "," + newstr; |
|
} |
|
} |
|
left = left.replace(/[0-9]+,/, newstr); |
|
} |
|
return left; |
|
} |
|
|
|
|
|
BI.cjkEncode = function (text) { |
|
// alex:如果非字符串,返回其本身(cjkEncode(234) 返回 ""是不对的) |
|
if (typeof text !== "string") { |
|
return text; |
|
} |
|
|
|
var newText = ""; |
|
for (var i = 0; i < text.length; i++) { |
|
var code = text.charCodeAt(i); |
|
if (code >= 128 || code === 91 || code === 93) {// 91 is "[", 93 is "]". |
|
newText += "[" + code.toString(16) + "]"; |
|
} else { |
|
newText += text.charAt(i); |
|
} |
|
} |
|
|
|
return newText; |
|
}; |
|
|
|
/** |
|
* 将cjkEncode处理过的字符串转化为原始字符串 |
|
* |
|
* @static |
|
* @param text 需要做解码的字符串 |
|
* @return {String} 解码后的字符串 |
|
*/ |
|
BI.cjkDecode = function (text) { |
|
if (text == null) { |
|
return ""; |
|
} |
|
// 查找没有 "[", 直接返回. kunsnat:数字的时候, 不支持indexOf方法, 也是直接返回. |
|
if (!isNaN(text) || text.indexOf("[") == -1) { |
|
return text; |
|
} |
|
|
|
var newText = ""; |
|
for (var i = 0; i < text.length; i++) { |
|
var ch = text.charAt(i); |
|
if (ch == "[") { |
|
var rightIdx = text.indexOf("]", i + 1); |
|
if (rightIdx > i + 1) { |
|
var subText = text.substring(i + 1, rightIdx); |
|
// james:主要是考虑[CDATA[]]这样的值的出现 |
|
if (subText.length > 0) { |
|
ch = String.fromCharCode(eval("0x" + subText)); |
|
} |
|
|
|
i = rightIdx; |
|
} |
|
} |
|
|
|
newText += ch; |
|
} |
|
|
|
return newText; |
|
}; |
|
|
|
// replace the html special tags |
|
var SPECIAL_TAGS = { |
|
"&": "&", |
|
"\"": """, |
|
"<": "<", |
|
">": ">", |
|
" ": " " |
|
}; |
|
BI.htmlEncode = function (text) { |
|
return BI.isNull(text) ? "" : BI.replaceAll(text + "", "&|\"|<|>|\\s", function (v) { |
|
return SPECIAL_TAGS[v] ? SPECIAL_TAGS[v] : " "; |
|
}); |
|
}; |
|
// html decode |
|
BI.htmlDecode = function (text) { |
|
return BI.isNull(text) ? "" : BI.replaceAll(text + "", "&|"|<|>| ", function (v) { |
|
switch (v) { |
|
case "&": |
|
return "&"; |
|
case """: |
|
return "\""; |
|
case "<": |
|
return "<"; |
|
case ">": |
|
return ">"; |
|
case " ": |
|
default: |
|
return " "; |
|
} |
|
}); |
|
}; |
|
|
|
BI.cjkEncodeDO = function (o) { |
|
if (BI.isPlainObject(o)) { |
|
var result = {}; |
|
_.each(o, function (v, k) { |
|
if (!(typeof v === "string")) { |
|
v = BI.jsonEncode(v); |
|
} |
|
// wei:bug 43338,如果key是中文,cjkencode后o的长度就加了1,ie9以下版本死循环,所以新建对象result。 |
|
k = BI.cjkEncode(k); |
|
result[k] = BI.cjkEncode(v); |
|
}); |
|
return result; |
|
} |
|
return o; |
|
}; |
|
|
|
BI.jsonEncode = function (o) { |
|
// james:这个Encode是抄的EXT的 |
|
var useHasOwn = !!{}.hasOwnProperty; |
|
|
|
// crashes Safari in some instances |
|
// var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/; |
|
|
|
var m = { |
|
"\b": "\\b", |
|
"\t": "\\t", |
|
"\n": "\\n", |
|
"\f": "\\f", |
|
"\r": "\\r", |
|
"\"": "\\\"", |
|
"\\": "\\\\" |
|
}; |
|
|
|
var encodeString = function (s) { |
|
if (/["\\\x00-\x1f]/.test(s)) { |
|
return "\"" + s.replace(/([\x00-\x1f\\"])/g, function (a, b) { |
|
var c = m[b]; |
|
if (c) { |
|
return c; |
|
} |
|
c = b.charCodeAt(); |
|
return "\\u00" + |
|
Math.floor(c / 16).toString(16) + |
|
(c % 16).toString(16); |
|
}) + "\""; |
|
} |
|
return "\"" + s + "\""; |
|
}; |
|
|
|
var encodeArray = function (o) { |
|
var a = ["["], b, i, l = o.length, v; |
|
for (i = 0; i < l; i += 1) { |
|
v = o[i]; |
|
switch (typeof v) { |
|
case "undefined": |
|
case "function": |
|
case "unknown": |
|
break; |
|
default: |
|
if (b) { |
|
a.push(","); |
|
} |
|
a.push(v === null ? "null" : BI.jsonEncode(v)); |
|
b = true; |
|
} |
|
} |
|
a.push("]"); |
|
return a.join(""); |
|
}; |
|
|
|
if (typeof o === "undefined" || o === null) { |
|
return "null"; |
|
} else if (BI.isArray(o)) { |
|
return encodeArray(o); |
|
} else if (o instanceof Date) { |
|
/* |
|
* alex:原来只是把年月日时分秒简单地拼成一个String,无法decode |
|
* 现在这么处理就可以decode了,但是JS.jsonDecode和Java.JSONObject也要跟着改一下 |
|
*/ |
|
return BI.jsonEncode({ |
|
__time__: o.getTime() |
|
}); |
|
} else if (typeof o === "string") { |
|
return encodeString(o); |
|
} else if (typeof o === "number") { |
|
return isFinite(o) ? String(o) : "null"; |
|
} else if (typeof o === "boolean") { |
|
return String(o); |
|
} else if (BI.isFunction(o)) { |
|
return String(o); |
|
} |
|
var a = ["{"], b, i, v; |
|
for (i in o) { |
|
if (!useHasOwn || o.hasOwnProperty(i)) { |
|
v = o[i]; |
|
switch (typeof v) { |
|
case "undefined": |
|
case "unknown": |
|
break; |
|
default: |
|
if (b) { |
|
a.push(","); |
|
} |
|
a.push(BI.jsonEncode(i), ":", |
|
v === null ? "null" : BI.jsonEncode(v)); |
|
b = true; |
|
} |
|
} |
|
} |
|
a.push("}"); |
|
return a.join(""); |
|
|
|
}; |
|
|
|
BI.jsonDecode = function (text) { |
|
|
|
try { |
|
// 注意0啊 |
|
// var jo = $.parseJSON(text) || {}; |
|
var jo = BI.$ ? BI.$.parseJSON(text) : _global.JSON.parse(text); |
|
if (jo == null) { |
|
jo = {}; |
|
} |
|
} catch (e) { |
|
/* |
|
* richie:浏览器只支持标准的JSON字符串转换,而jQuery会默认调用浏览器的window.JSON.parse()函数进行解析 |
|
* 比如:var str = "{'a':'b'}",这种形式的字符串转换为JSON就会抛异常 |
|
*/ |
|
try { |
|
jo = new Function("return " + text)() || {}; |
|
} catch (e) { |
|
// do nothing |
|
} |
|
if (jo == null) { |
|
jo = []; |
|
} |
|
} |
|
if (!_hasDateInJson(text)) { |
|
return jo; |
|
} |
|
|
|
function _hasDateInJson (json) { |
|
if (!json || typeof json !== "string") { |
|
return false; |
|
} |
|
return json.indexOf("__time__") != -1; |
|
} |
|
|
|
return (function (o) { |
|
if (typeof o === "string") { |
|
return o; |
|
} |
|
if (o && o.__time__ != null) { |
|
return new Date(o.__time__); |
|
} |
|
for (var a in o) { |
|
if (o[a] == o || typeof o[a] === "object" || _.isFunction(o[a])) { |
|
break; |
|
} |
|
o[a] = arguments.callee(o[a]); |
|
} |
|
|
|
return o; |
|
})(jo); |
|
}; |
|
|
|
/** |
|
* 获取编码后的url |
|
* @param urlTemplate url模板 |
|
* @param param 参数 |
|
* @returns {*|String} |
|
* @example |
|
* BI.getEncodeURL("design/{tableName}/{fieldName}",{tableName: "A", fieldName: "a"}) // design/A/a |
|
*/ |
|
BI.getEncodeURL = function (urlTemplate, param) { |
|
return urlTemplate.replaceAll("\\{(.*?)\\}", function (ori, str) { |
|
return BI.encodeURIComponent(BI.isObject(param) ? param[str] : param); |
|
}); |
|
}; |
|
|
|
BI.encodeURIComponent = function (url) { |
|
BI.specialCharsMap = BI.specialCharsMap || {}; |
|
url = url || ""; |
|
url = BI.replaceAll(url + "", BI.keys(BI.specialCharsMap || []).join("|"), function (str) { |
|
switch (str) { |
|
case "\\": |
|
return BI.specialCharsMap["\\\\"] || str; |
|
default: |
|
return BI.specialCharsMap[str] || str; |
|
} |
|
}); |
|
return _global.encodeURIComponent(url); |
|
}; |
|
|
|
BI.decodeURIComponent = function (url) { |
|
var reserveSpecialCharsMap = {}; |
|
BI.each(BI.specialCharsMap, function (initialChar, encodeChar) { |
|
reserveSpecialCharsMap[encodeChar] = initialChar === "\\\\" ? "\\" : initialChar; |
|
}); |
|
url = url || ""; |
|
url = BI.replaceAll(url + "", BI.keys(reserveSpecialCharsMap || []).join("|"), function (str) { |
|
return reserveSpecialCharsMap[str] || str; |
|
}); |
|
return _global.decodeURIComponent(url); |
|
}; |
|
|
|
BI.contentFormat = function (cv, fmt) { |
|
if (isEmpty(cv)) { |
|
// 原值为空,返回空字符 |
|
return ""; |
|
} |
|
var text = cv.toString(); |
|
if (isEmpty(fmt)) { |
|
// 格式为空,返回原字符 |
|
return text; |
|
} |
|
if (fmt.match(/^T/)) { |
|
// T - 文本格式 |
|
return text; |
|
} else if (fmt.match(/^D/)) { |
|
// D - 日期(时间)格式 |
|
if (!(cv instanceof Date)) { |
|
if (typeof cv === "number") { |
|
// 毫秒数类型 |
|
cv = new Date(cv); |
|
} else { |
|
//字符串类型转化为date类型 |
|
cv = new Date(Date.parse(("" + cv).replace(/-|\./g, "/"))); |
|
} |
|
} |
|
if (!isInvalidDate(cv) && !BI.isNull(cv)) { |
|
var needTrim = fmt.match(/^DT/); |
|
text = BI.date2Str(cv, fmt.substring(needTrim ? 2 : 1)); |
|
} |
|
} else if (fmt.match(/E/)) { |
|
// 科学计数格式 |
|
text = _eFormat(text, fmt); |
|
} else { |
|
// 数字格式 |
|
text = _numberFormat(text, fmt); |
|
} |
|
// ¤ - 货币格式 |
|
text = text.replace(/¤/g, "¥"); |
|
return text; |
|
}; |
|
|
|
/** |
|
* 将Java提供的日期格式字符串装换为JS识别的日期格式字符串 |
|
* @class FR.parseFmt |
|
* @param fmt 日期格式 |
|
* @returns {String} |
|
*/ |
|
BI.parseFmt = function (fmt) { |
|
if (!fmt) { |
|
return ""; |
|
} |
|
//日期 |
|
fmt = String(fmt) |
|
//年 |
|
.replace(/y{4,}/g, "%Y")//yyyy的时候替换为Y |
|
.replace(/y{2}/g, "%y")//yy的时候替换为y |
|
//月 |
|
.replace(/M{4,}/g, "%b")//MMMM的时候替换为b,八 |
|
.replace(/M{3}/g, "%B")//MMM的时候替换为M,八月 |
|
.replace(/M{2}/g, "%X")//MM的时候替换为X,08 |
|
.replace(/M{1}/g, "%x")//M的时候替换为x,8 |
|
.replace(/a{1}/g, "%p"); |
|
//天 |
|
if (new RegExp("d{2,}", "g").test(fmt)) { |
|
fmt = fmt.replace(/d{2,}/g, "%d");//dd的时候替换为d |
|
} else { |
|
fmt = fmt.replace(/d{1}/g, "%e");//d的时候替换为j |
|
} |
|
//时 |
|
if (new RegExp("h{2,}", "g").test(fmt)) {//12小时制 |
|
fmt = fmt.replace(/h{2,}/g, "%I"); |
|
} else { |
|
fmt = fmt.replace(/h{1}/g, "%I"); |
|
} |
|
if (new RegExp("H{2,}", "g").test(fmt)) {//24小时制 |
|
fmt = fmt.replace(/H{2,}/g, "%H"); |
|
} else { |
|
fmt = fmt.replace(/H{1}/g, "%H"); |
|
} |
|
fmt = fmt.replace(/m{2,}/g, "%M")//分 |
|
//秒 |
|
.replace(/s{2,}/g, "%S"); |
|
|
|
return fmt; |
|
}; |
|
|
|
/** |
|
* 把字符串按照对应的格式转化成日期对象 |
|
* |
|
* @example |
|
* var result = BI.str2Date('2013-12-12', 'yyyy-MM-dd');//Thu Dec 12 2013 00:00:00 GMT+0800 |
|
* |
|
* @class BI.str2Date |
|
* @param str 字符串 |
|
* @param format 日期格式 |
|
* @returns {*} |
|
*/ |
|
BI.str2Date = function (str, format) { |
|
if (typeof str != "string" || typeof format != "string") { |
|
return null; |
|
} |
|
var fmt = BI.parseFmt(format); |
|
return BI.parseDateTime(str, fmt); |
|
}; |
|
|
|
/** |
|
* 把日期对象按照指定格式转化成字符串 |
|
* |
|
* @example |
|
* var date = new Date('Thu Dec 12 2013 00:00:00 GMT+0800'); |
|
* var result = BI.date2Str(date, 'yyyy-MM-dd');//2013-12-12 |
|
* |
|
* @class BI.date2Str |
|
* @param date 日期 |
|
* @param format 日期格式 |
|
* @returns {String} |
|
*/ |
|
BI.date2Str = function (date, format) { |
|
if (!date) { |
|
return ""; |
|
} |
|
// O(len(format)) |
|
var len = format.length, result = ""; |
|
if (len > 0) { |
|
var flagch = format.charAt(0), start = 0, str = flagch; |
|
for (var i = 1; i < len; i++) { |
|
var ch = format.charAt(i); |
|
if (flagch !== ch) { |
|
result += compileJFmt({ |
|
char: flagch, |
|
str: str, |
|
len: i - start |
|
}, date); |
|
flagch = ch; |
|
start = i; |
|
str = flagch; |
|
} else { |
|
str += ch; |
|
} |
|
} |
|
result += compileJFmt({ |
|
char: flagch, |
|
str: str, |
|
len: len - start |
|
}, date); |
|
} |
|
return result; |
|
|
|
function compileJFmt (jfmt, date) { |
|
var str = jfmt.str, len = jfmt.len, ch = jfmt["char"]; |
|
switch (ch) { |
|
case "E": // 星期 |
|
str = BI.Date._DN[date.getDay()]; |
|
break; |
|
case "y": // 年 |
|
if (len <= 3) { |
|
str = (date.getFullYear() + "").slice(2, 4); |
|
} else { |
|
str = date.getFullYear(); |
|
} |
|
break; |
|
case "M": // 月 |
|
if (len > 2) { |
|
str = BI.Date._MN[date.getMonth()]; |
|
} else if (len < 2) { |
|
str = date.getMonth() + 1; |
|
} else { |
|
str = BI.leftPad(date.getMonth() + 1 + "", 2, "0"); |
|
} |
|
break; |
|
case "d": // 日 |
|
if (len > 1) { |
|
str = BI.leftPad(date.getDate() + "", 2, "0"); |
|
} else { |
|
str = date.getDate(); |
|
} |
|
break; |
|
case "h": // 时(12) |
|
var hour = date.getHours() % 12; |
|
if (hour === 0) { |
|
hour = 12; |
|
} |
|
if (len > 1) { |
|
str = BI.leftPad(hour + "", 2, "0"); |
|
} else { |
|
str = hour; |
|
} |
|
break; |
|
case "H": // 时(24) |
|
if (len > 1) { |
|
str = BI.leftPad(date.getHours() + "", 2, "0"); |
|
} else { |
|
str = date.getHours(); |
|
} |
|
break; |
|
case "m": |
|
if (len > 1) { |
|
str = BI.leftPad(date.getMinutes() + "", 2, "0"); |
|
} else { |
|
str = date.getMinutes(); |
|
} |
|
break; |
|
case "s": |
|
if (len > 1) { |
|
str = BI.leftPad(date.getSeconds() + "", 2, "0"); |
|
} else { |
|
str = date.getSeconds(); |
|
} |
|
break; |
|
case "a": |
|
str = date.getHours() < 12 ? "am" : "pm"; |
|
break; |
|
case "z": |
|
str = BI.getTimezone(date); |
|
break; |
|
default: |
|
str = jfmt.str; |
|
break; |
|
} |
|
return str; |
|
} |
|
}; |
|
|
|
BI.object2Number = function (value) { |
|
if (value == null) { |
|
return 0; |
|
} |
|
if (typeof value === "number") { |
|
return value; |
|
} |
|
var str = value + ""; |
|
if (str.indexOf(".") === -1) { |
|
return parseInt(str); |
|
} |
|
return parseFloat(str); |
|
}; |
|
|
|
BI.object2Date = function (obj) { |
|
if (obj == null) { |
|
return new Date(); |
|
} |
|
if (obj instanceof Date) { |
|
return obj; |
|
} else if (typeof obj === "number") { |
|
return new Date(obj); |
|
} |
|
var str = obj + ""; |
|
str = str.replace(/-/g, "/"); |
|
var dt = new Date(str); |
|
if (!isInvalidDate(dt)) { |
|
return dt; |
|
} |
|
|
|
return new Date(); |
|
|
|
}; |
|
|
|
BI.object2Time = function (obj) { |
|
if (obj == null) { |
|
return new Date(); |
|
} |
|
if (obj instanceof Date) { |
|
return obj; |
|
} |
|
var str = obj + ""; |
|
str = str.replace(/-/g, "/"); |
|
var dt = new Date(str); |
|
if (!isInvalidDate(dt)) { |
|
return dt; |
|
} |
|
if (str.indexOf("/") === -1 && str.indexOf(":") !== -1) { |
|
dt = new Date("1970/01/01 " + str); |
|
if (!isInvalidDate(dt)) { |
|
return dt; |
|
} |
|
} |
|
dt = BI.parseDateTime(str, "HH:mm:ss"); |
|
if (!isInvalidDate(dt)) { |
|
return dt; |
|
} |
|
return new Date(); |
|
|
|
}; |
|
})(); |
|
/** |
|
* guy |
|
* |
|
* @class BI.HighlightBehavior |
|
* @extends BI.Behavior |
|
*/ |
|
BI.HighlightBehavior = BI.inherit(BI.Behavior, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.HighlightBehavior.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_init: function () { |
|
BI.HighlightBehavior.superclass._init.apply(this, arguments); |
|
|
|
}, |
|
|
|
doBehavior: function (items) { |
|
var args = Array.prototype.slice.call(arguments, 1), |
|
o = this.options; |
|
BI.each(items, function (i, item) { |
|
if (item instanceof BI.Single) { |
|
var rule = o.rule(item.getValue(), item); |
|
|
|
function doBe (run) { |
|
if (run === true) { |
|
item.doHighLight && item.doHighLight.apply(item, args); |
|
} else { |
|
item.unHighLight && item.unHighLight.apply(item, args); |
|
} |
|
} |
|
|
|
if (BI.isFunction(rule)) { |
|
rule(doBe); |
|
} else { |
|
doBe(rule); |
|
} |
|
} else { |
|
item.doBehavior && item.doBehavior.apply(item, args); |
|
} |
|
}); |
|
} |
|
});/** |
|
* guy |
|
* 标红行为 |
|
* @class BI.RedMarkBehavior |
|
* @extends BI.Behavior |
|
*/ |
|
BI.RedMarkBehavior = BI.inherit(BI.Behavior, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.RedMarkBehavior.superclass._defaultConfig.apply(this, arguments), { |
|
|
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.RedMarkBehavior.superclass._init.apply(this, arguments); |
|
|
|
}, |
|
|
|
doBehavior: function (items) { |
|
var args = Array.prototype.slice.call(arguments, 1), |
|
o = this.options; |
|
BI.each(items, function (i, item) { |
|
if(item instanceof BI.Single) { |
|
if (o.rule(item.getValue(), item)) { |
|
item.doRedMark && item.doRedMark.apply(item, args); |
|
} else { |
|
item.doRedMark && item.unRedMark.apply(item, args); |
|
} |
|
} else { |
|
item.doBehavior && item.doBehavior.apply(item, args); |
|
} |
|
}); |
|
} |
|
});/** |
|
* guy |
|
* 控制器 |
|
* Controller层超类 |
|
* @class BI.Controller |
|
* @extends BI.OB |
|
* @abstract |
|
*/ |
|
BI.Controller = BI.inherit(BI.OB, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Controller.superclass._defaultConfig.apply(this, arguments), { |
|
|
|
}); |
|
}, |
|
_init: function () { |
|
BI.Controller.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
destroy: function () { |
|
|
|
} |
|
}); |
|
BI.Controller.EVENT_CHANGE = "__EVENT_CHANGE__";/** |
|
* 广播 |
|
* |
|
* Created by GUY on 2015/12/23. |
|
* @class |
|
*/ |
|
BI.BroadcastController = BI.inherit(BI.Controller, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.BroadcastController.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_init: function () { |
|
BI.BroadcastController.superclass._init.apply(this, arguments); |
|
this._broadcasts = {}; |
|
}, |
|
|
|
on: function (name, fn) { |
|
var self = this; |
|
if (!this._broadcasts[name]) { |
|
this._broadcasts[name] = []; |
|
} |
|
this._broadcasts[name].push(fn); |
|
return function () { |
|
self.remove(name, fn); |
|
}; |
|
}, |
|
|
|
send: function (name) { |
|
var args = [].slice.call(arguments, 1); |
|
BI.each(this._broadcasts[name], function (i, fn) { |
|
fn.apply(null, args); |
|
}); |
|
}, |
|
|
|
remove: function (name, fn) { |
|
var self = this; |
|
if (fn) { |
|
BI.remove(this._broadcasts[name], function (idx) { |
|
return self._broadcasts[name].indexOf(fn) === idx; |
|
}); |
|
this._broadcasts[name].remove(fn); |
|
if (this._broadcasts[name].length === 0) { |
|
delete this._broadcasts[name]; |
|
} |
|
} else { |
|
delete this._broadcasts[name]; |
|
} |
|
return this; |
|
} |
|
});/** |
|
* 气泡图控制器 |
|
* 控制气泡图的显示方向 |
|
* |
|
* Created by GUY on 2015/8/21. |
|
* @class |
|
*/ |
|
BI.BubblesController = BI.inherit(BI.Controller, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.BubblesController.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_const: { |
|
bubbleHeight: 18 |
|
}, |
|
|
|
_init: function () { |
|
BI.BubblesController.superclass._init.apply(this, arguments); |
|
var self = this; |
|
this.bubblesManager = {}; |
|
this.storeBubbles = {}; |
|
BI.Resizers.add("bubbleController" + BI.uniqueId(), function () { |
|
BI.each(self.bubblesManager, function (name) { |
|
self.remove(name); |
|
}); |
|
self.bubblesManager = {}; |
|
self.storeBubbles = {}; |
|
}); |
|
}, |
|
|
|
_createBubble: function (direct, text, level, height) { |
|
return BI.createWidget({ |
|
type: "bi.bubble", |
|
text: text, |
|
level: level, |
|
height: height || 18, |
|
direction: direct |
|
}); |
|
}, |
|
|
|
_getOffsetLeft: function (name, context, offsetStyle) { |
|
var left = 0; |
|
if ("center" === offsetStyle) { |
|
left = context.element.offset().left + (context.element.bounds().width - this.get(name).element.bounds().width) / 2; |
|
if (left < 0) { |
|
left = 0; |
|
} |
|
return left; |
|
} |
|
if ("right" === offsetStyle) { |
|
left = context.element.offset().left + context.element.bounds().width - this.get(name).element.bounds().width; |
|
if (left < 0) { |
|
left = 0; |
|
} |
|
return left; |
|
} |
|
return context.element.offset().left; |
|
}, |
|
|
|
_getOffsetTop: function (name, context, offsetStyle) { |
|
var top = 0; |
|
if ("center" === offsetStyle) { |
|
top = context.element.offset().top + (context.element.bounds().height - this.get(name).element.bounds().height) / 2; |
|
if (top < 0) { |
|
top = 0; |
|
} |
|
return top; |
|
} else if ("right" === offsetStyle) { |
|
top = context.element.offset().top + context.element.bounds().height - this.get(name).element.bounds().height; |
|
if (top < 0) { |
|
top = 0; |
|
} |
|
return top; |
|
} |
|
return context.element.offset().top; |
|
}, |
|
|
|
_getLeftPosition: function (name, context, offsetStyle) { |
|
var position = BI.DOM.getLeftPosition(context, this.get(name)); |
|
position.top = this._getOffsetTop(name, context, offsetStyle); |
|
return position; |
|
}, |
|
|
|
_getBottomPosition: function (name, context, offsetStyle) { |
|
var position = BI.DOM.getBottomPosition(context, this.get(name)); |
|
position.left = this._getOffsetLeft(name, context, offsetStyle); |
|
return position; |
|
}, |
|
|
|
_getTopPosition: function (name, context, offsetStyle) { |
|
var position = BI.DOM.getTopPosition(context, this.get(name)); |
|
position.left = this._getOffsetLeft(name, context, offsetStyle); |
|
return position; |
|
}, |
|
|
|
_getRightPosition: function (name, context, offsetStyle) { |
|
var position = BI.DOM.getRightPosition(context, this.get(name)); |
|
position.top = this._getOffsetTop(name, context, offsetStyle); |
|
return position; |
|
}, |
|
|
|
/** |
|
* |
|
* @param name |
|
* @param text |
|
* @param context |
|
* @param offsetStyle center, left, right三种类型, 默认left |
|
* @returns {BI.BubblesController} |
|
*/ |
|
show: function (name, text, context, opt) { |
|
opt || (opt = {}); |
|
var container = opt.container || context; |
|
var offsetStyle = opt.offsetStyle || {}; |
|
var level = opt.level || "error"; |
|
var adjustYOffset = opt.adjustYOffset || 0; |
|
var adjustXOffset = opt.adjustXOffset || 0; |
|
if (!this.storeBubbles[name]) { |
|
this.storeBubbles[name] = {}; |
|
} |
|
if (!this.storeBubbles[name]["top"]) { |
|
this.storeBubbles[name]["top"] = this._createBubble("top", text, level); |
|
} |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: container, |
|
items: [{ |
|
el: this.storeBubbles[name]["top"] |
|
}] |
|
}); |
|
this.set(name, this.storeBubbles[name]["top"]); |
|
var position = this._getTopPosition(name, context, offsetStyle); |
|
this.get(name).element.css({left: position.left + adjustXOffset, top: position.top - adjustYOffset}); |
|
this.get(name).invisible(); |
|
if (!BI.DOM.isTopSpaceEnough(context, this.get(name), adjustYOffset)) { |
|
if (!this.storeBubbles[name]["left"]) { |
|
this.storeBubbles[name]["left"] = this._createBubble("left", text, level, 30); |
|
} |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: container, |
|
items: [{ |
|
el: this.storeBubbles[name]["left"] |
|
}] |
|
}); |
|
this.set(name, this.storeBubbles[name]["left"]); |
|
var position = this._getLeftPosition(name, context, offsetStyle); |
|
this.get(name).element.css({left: position.left - adjustXOffset, top: position.top - adjustYOffset}); |
|
this.get(name).invisible(); |
|
if (!BI.DOM.isLeftSpaceEnough(context, this.get(name), adjustXOffset)) { |
|
if (!this.storeBubbles[name]["right"]) { |
|
this.storeBubbles[name]["right"] = this._createBubble("right", text, level, 30); |
|
} |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: container, |
|
items: [{ |
|
el: this.storeBubbles[name]["right"] |
|
}] |
|
}); |
|
this.set(name, this.storeBubbles[name]["right"]); |
|
var position = this._getRightPosition(name, context, offsetStyle); |
|
this.get(name).element.css({left: position.left + adjustXOffset, top: position.top - adjustYOffset}); |
|
this.get(name).invisible(); |
|
if (!BI.DOM.isRightSpaceEnough(context, this.get(name), adjustXOffset)) { |
|
if (!this.storeBubbles[name]["bottom"]) { |
|
this.storeBubbles[name]["bottom"] = this._createBubble("bottom", text, level); |
|
} |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: container, |
|
items: [{ |
|
el: this.storeBubbles[name]["bottom"] |
|
}] |
|
}); |
|
this.set(name, this.storeBubbles[name]["bottom"]); |
|
var position = this._getBottomPosition(name, context, offsetStyle); |
|
this.get(name).element.css({left: position.left + adjustXOffset, top: position.top + adjustYOffset}); |
|
this.get(name).invisible(); |
|
} |
|
} |
|
} |
|
this.get(name).setText(text); |
|
this.get(name).visible(); |
|
return this; |
|
}, |
|
|
|
hide: function (name) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
this.get(name).invisible(); |
|
return this; |
|
}, |
|
|
|
add: function (name, bubble) { |
|
if (this.has(name)) { |
|
return this; |
|
} |
|
this.set(name, bubble); |
|
return this; |
|
}, |
|
|
|
get: function (name) { |
|
return this.bubblesManager[name]; |
|
}, |
|
|
|
set: function (name, bubble) { |
|
this.bubblesManager[name] = bubble; |
|
}, |
|
|
|
has: function (name) { |
|
return this.bubblesManager[name] != null; |
|
}, |
|
|
|
remove: function (name) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
BI.each(this.storeBubbles[name], function (dir, bubble) { |
|
bubble.destroy(); |
|
}); |
|
delete this.storeBubbles[name]; |
|
delete this.bubblesManager[name]; |
|
return this; |
|
} |
|
});/** |
|
* 弹出层面板控制器, z-index在10w层级 |
|
* |
|
* Created by GUY on 2015/6/24. |
|
* @class |
|
*/ |
|
BI.LayerController = BI.inherit(BI.Controller, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.LayerController.superclass._defaultConfig.apply(this, arguments), { |
|
render: "body" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.LayerController.superclass._init.apply(this, arguments); |
|
this.layerManager = {}; |
|
this.layouts = {}; |
|
this.zindex = BI.zIndex_layer; |
|
BI.Resizers.add("layerController" + BI.uniqueId(), BI.bind(this._resize, this)); |
|
}, |
|
|
|
_resize: function () { |
|
BI.each(this.layouts, function (i, layer) { |
|
if (layer.element.is(":visible")) { |
|
layer.element.trigger("__resize__"); |
|
} |
|
}); |
|
}, |
|
|
|
make: function (name, container, op, context) { |
|
if (BI.isWidget(container)) { |
|
op = op || {}; |
|
op.container = container; |
|
} else { |
|
context = op; |
|
op = container; |
|
} |
|
return this.create(name, null, op, context); |
|
}, |
|
|
|
create: function (name, from, op, context) { |
|
if (this.has(name)) { |
|
return this.get(name); |
|
} |
|
op || (op = {}); |
|
var offset = op.offset || {}; |
|
var w = from; |
|
if (BI.isWidget(from)) { |
|
w = from.element; |
|
} |
|
if (BI.isNotEmptyString(w)) { |
|
w = BI.Widget._renderEngine.createElement(w); |
|
} |
|
if (this.has(name)) { |
|
return this.get(name); |
|
} |
|
var widget = BI.createWidget((op.render || {}), BI.extend({ |
|
type: "bi.layout" |
|
}, op), context); |
|
var layout = BI.createWidget({ |
|
type: "bi.absolute", |
|
invisible: true, |
|
items: [{ |
|
el: widget, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}, context); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: op.container || this.options.render, |
|
items: [{ |
|
el: layout, |
|
left: offset.left || 0, |
|
right: offset.right || 0, |
|
top: offset.top || 0, |
|
bottom: offset.bottom || 0 |
|
}] |
|
}); |
|
if (w) { |
|
layout.element.addClass("bi-popup-view"); |
|
layout.element.css({ |
|
left: w.offset().left + (offset.left || 0), |
|
top: w.offset().top + (offset.top || 0), |
|
width: offset.width || (w.outerWidth() - (offset.left || 0) - (offset.right || 0)) || "", |
|
height: offset.height || (w.outerHeight() - (offset.top || 0) - (offset.bottom || 0)) || "" |
|
}); |
|
layout.element.on("__resize__", function () { |
|
w.is(":visible") && |
|
layout.element.css({ |
|
left: w.offset().left + (offset.left || 0), |
|
top: w.offset().top + (offset.top || 0), |
|
width: offset.width || (w.outerWidth() - (offset.left || 0) - (offset.right || 0)) || "", |
|
height: offset.height || (w.outerHeight() - (offset.top || 0) - (offset.bottom || 0)) || "" |
|
}); |
|
}); |
|
} |
|
this.add(name, widget, layout); |
|
return widget; |
|
}, |
|
|
|
hide: function (name, callback) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
this._getLayout(name).invisible(); |
|
this._getLayout(name).element.hide(0, callback); |
|
return this; |
|
}, |
|
|
|
show: function (name, callback) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
this._getLayout(name).visible(); |
|
this._getLayout(name).element.css("z-index", this.zindex++).show(0, callback).trigger("__resize__"); |
|
return this; |
|
}, |
|
|
|
isVisible: function (name) { |
|
return this.has(name) && this._getLayout(name).isVisible(); |
|
}, |
|
|
|
add: function (name, layer, layout) { |
|
if (this.has(name)) { |
|
throw new Error("name is already exist"); |
|
} |
|
layout.setVisible(false); |
|
this.layerManager[name] = layer; |
|
this.layouts[name] = layout; |
|
layout.element.css("z-index", this.zindex++); |
|
return this; |
|
}, |
|
|
|
_getLayout: function (name) { |
|
return this.layouts[name]; |
|
}, |
|
|
|
get: function (name) { |
|
return this.layerManager[name]; |
|
}, |
|
|
|
has: function (name) { |
|
return this.layerManager[name] != null; |
|
}, |
|
|
|
remove: function (name) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
this.layerManager[name].destroy(); |
|
this.layouts[name].destroy(); |
|
delete this.layerManager[name]; |
|
delete this.layouts[name]; |
|
return this; |
|
}, |
|
|
|
removeAll: function () { |
|
var self = this; |
|
BI.each(BI.keys(this.layerManager), function (index, name) { |
|
self.layerManager[name].destroy(); |
|
self.layouts[name].destroy(); |
|
}); |
|
this.layerManager = {}; |
|
this.layouts = {}; |
|
return this; |
|
} |
|
});/** |
|
* 遮罩面板, z-index在1亿层级 |
|
* |
|
* Created by GUY on 2015/6/24. |
|
* @class |
|
*/ |
|
BI.MaskersController = BI.inherit(BI.LayerController, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MaskersController.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MaskersController.superclass._init.apply(this, arguments); |
|
this.zindex = BI.zIndex_masker; |
|
} |
|
});/** |
|
* guy |
|
* popover弹出层控制器, z-index在100w层级 |
|
* @class BI.popoverController |
|
* @extends BI.Controller |
|
*/ |
|
BI.PopoverController = BI.inherit(BI.Controller, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.PopoverController.superclass._defaultConfig.apply(this, arguments), { |
|
modal: true, // 模态窗口 |
|
render: "body" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.PopoverController.superclass._init.apply(this, arguments); |
|
this.modal = this.options.modal; |
|
this.floatManager = {}; |
|
this.floatLayer = {}; |
|
this.floatContainer = {}; |
|
this.floatOpened = {}; |
|
this.zindex = BI.zIndex_popover; |
|
this.zindexMap = {}; |
|
}, |
|
|
|
_check: function (name) { |
|
return BI.isNotNull(this.floatManager[name]); |
|
}, |
|
|
|
create: function (name, options, context) { |
|
if (this._check(name)) { |
|
return this; |
|
} |
|
var popover = BI.createWidget(options || {}, { |
|
type: "bi.popover" |
|
}, context); |
|
this.add(name, popover, options, context); |
|
return this; |
|
}, |
|
|
|
add: function (name, popover, options, context) { |
|
var self = this; |
|
options || (options = {}); |
|
if (this._check(name)) { |
|
return this; |
|
} |
|
this.floatContainer[name] = BI.createWidget({ |
|
type: "bi.absolute", |
|
cls: "bi-popup-view", |
|
items: [{ |
|
el: (this.floatLayer[name] = BI.createWidget({ |
|
type: "bi.absolute", |
|
items: [popover] |
|
}, context)), |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.floatManager[name] = popover; |
|
(function (key) { |
|
popover.on(BI.Popover.EVENT_CLOSE, function () { |
|
self.close(key); |
|
}); |
|
})(name); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: options.container || this.options.render, |
|
items: [{ |
|
el: this.floatContainer[name], |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
return this; |
|
}, |
|
|
|
open: function (name) { |
|
if (!this._check(name)) { |
|
return this; |
|
} |
|
if (!this.floatOpened[name]) { |
|
this.floatOpened[name] = true; |
|
var container = this.floatContainer[name]; |
|
container.element.css("zIndex", this.zindex++); |
|
this.modal && container.element.__hasZIndexMask__(this.zindexMap[name]) && container.element.__releaseZIndexMask__(this.zindexMap[name]); |
|
this.zindexMap[name] = this.zindex; |
|
this.modal && container.element.__buildZIndexMask__(this.zindex++); |
|
this.get(name).setZindex(this.zindex++); |
|
this.floatContainer[name].visible(); |
|
var popover = this.get(name); |
|
popover.show && popover.show(); |
|
var W = BI.Widget._renderEngine.createElement(this.options.render).width(), H = BI.Widget._renderEngine.createElement(this.options.render).height(); |
|
var w = popover.element.width(), h = popover.element.height(); |
|
var left = (W - w) / 2, top = (H - h) / 2; |
|
if (left < 0) { |
|
left = 0; |
|
} |
|
if (top < 0) { |
|
top = 0; |
|
} |
|
popover.element.css({ |
|
left: left + "px", |
|
top: top + "px" |
|
}); |
|
} |
|
return this; |
|
}, |
|
|
|
close: function (name) { |
|
if (!this._check(name)) { |
|
return this; |
|
} |
|
if (this.floatOpened[name]) { |
|
delete this.floatOpened[name]; |
|
this.floatContainer[name].invisible(); |
|
this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]); |
|
} |
|
return this; |
|
}, |
|
|
|
get: function (name) { |
|
return this.floatManager[name]; |
|
}, |
|
|
|
remove: function (name) { |
|
if (!this._check(name)) { |
|
return this; |
|
} |
|
this.floatContainer[name].destroy(); |
|
this.modal && this.floatContainer[name].element.__releaseZIndexMask__(this.zindexMap[name]); |
|
delete this.floatManager[name]; |
|
delete this.floatLayer[name]; |
|
delete this.zindexMap[name]; |
|
delete this.floatContainer[name]; |
|
delete this.floatOpened[name]; |
|
return this; |
|
}, |
|
|
|
removeAll: function () { |
|
var self = this; |
|
BI.each(this.floatContainer, function (name, container) { |
|
container.destroy(); |
|
self.modal && self.floatContainer[name].element.__releaseZIndexMask__(self.zindexMap[name]); |
|
}); |
|
this.floatManager = {}; |
|
this.floatLayer = {}; |
|
this.floatContainer = {}; |
|
this.floatOpened = {}; |
|
this.zindexMap = {}; |
|
return this; |
|
} |
|
});/** |
|
* window.resize 控制器 |
|
* |
|
* Created by GUY on 2015/6/24. |
|
* @class |
|
*/ |
|
BI.ResizeController = BI.inherit(BI.Controller, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ResizeController.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ResizeController.superclass._init.apply(this, arguments); |
|
var self = this; |
|
this.resizerManger = {}; |
|
var fn = BI.debounce(function (ev) { |
|
// if (BI.isWindow(ev.target)) { |
|
self._resize(ev); |
|
// } |
|
}, 30); |
|
BI.Widget._renderEngine.createElement(_global).resize(fn); |
|
}, |
|
|
|
_resize: function (ev) { |
|
BI.each(this.resizerManger, function (key, resizer) { |
|
if (resizer instanceof BI.$) { |
|
if (resizer.is(":visible")) { |
|
resizer.trigger("__resize__"); |
|
} |
|
return; |
|
} |
|
if (resizer instanceof BI.Layout) { |
|
resizer.resize(); |
|
return; |
|
} |
|
if (BI.isFunction(resizer)) { |
|
resizer(ev); |
|
return; |
|
} |
|
}); |
|
}, |
|
|
|
add: function (name, resizer) { |
|
var self = this; |
|
if (this.has(name)) { |
|
return this; |
|
} |
|
this.resizerManger[name] = resizer; |
|
return function () { |
|
self.remove(name); |
|
}; |
|
}, |
|
|
|
get: function (name) { |
|
return this.resizerManger[name]; |
|
}, |
|
|
|
has: function (name) { |
|
return this.resizerManger[name] != null; |
|
}, |
|
|
|
remove: function (name) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
delete this.resizerManger[name]; |
|
return this; |
|
} |
|
});/** |
|
* tooltip控制器 |
|
* 控制tooltip的显示, 且页面中只有一个tooltip显示 |
|
* |
|
* Created by GUY on 2015/9/8. |
|
* @class BI.TooltipsController |
|
* @extends BI.Controller |
|
*/ |
|
BI.TooltipsController = BI.inherit(BI.Controller, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TooltipsController.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_const: { |
|
height: 18 |
|
}, |
|
|
|
_init: function () { |
|
BI.TooltipsController.superclass._init.apply(this, arguments); |
|
this.tooltipsManager = {}; |
|
this.showingTips = {};// 存储正在显示的tooltip |
|
}, |
|
|
|
_createTooltip: function (text, level) { |
|
return BI.createWidget({ |
|
type: "bi.tooltip", |
|
text: text, |
|
level: level, |
|
stopEvent: true |
|
}); |
|
}, |
|
|
|
hide: function (name, callback) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
delete this.showingTips[name]; |
|
this.get(name).element.hide(0, callback); |
|
this.get(name).invisible(); |
|
return this; |
|
}, |
|
|
|
create: function (name, text, level, context) { |
|
if (!this.has(name)) { |
|
var tooltip = this._createTooltip(text, level); |
|
this.add(name, tooltip); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: context || "body", |
|
items: [{ |
|
el: tooltip |
|
}] |
|
}); |
|
tooltip.invisible(); |
|
} |
|
return this.get(name); |
|
}, |
|
|
|
// opt: {container: '', belowMouse: false} |
|
show: function (e, name, text, level, context, opt) { |
|
opt || (opt = {}); |
|
var self = this; |
|
BI.each(this.showingTips, function (i, tip) { |
|
self.hide(i); |
|
}); |
|
this.showingTips = {}; |
|
if (!this.has(name)) { |
|
this.create(name, text, level, opt.container || "body"); |
|
} |
|
if (!opt.belowMouse) { |
|
var offset = context.element.offset(); |
|
var bounds = context.element.bounds(); |
|
if (bounds.height === 0 || bounds.width === 0) { |
|
return; |
|
} |
|
var top = offset.top + bounds.height + 5; |
|
} |
|
var tooltip = this.get(name); |
|
tooltip.setText(text); |
|
tooltip.element.css({ |
|
left: "0px", |
|
top: "0px" |
|
}); |
|
tooltip.visible(); |
|
tooltip.element.height(tooltip.element[0].scrollHeight); |
|
this.showingTips[name] = true; |
|
// scale影响要计算在内 |
|
// var scale = context.element.offset().left / context.element.get(0).getBoundingClientRect().left; |
|
// var x = (e.pageX || e.clientX) * scale + 15, y = (e.pageY || e.clientY) * scale + 15; |
|
var x = (e.pageX || e.clientX) + 15, y = (e.pageY || e.clientY) + 15; |
|
if (x + tooltip.element.outerWidth() > BI.Widget._renderEngine.createElement("body").outerWidth()) { |
|
x -= tooltip.element.outerWidth() + 15; |
|
} |
|
var bodyHeight = BI.Widget._renderEngine.createElement("body").outerHeight(); |
|
if (y + tooltip.element.outerHeight() > bodyHeight || top + tooltip.element.outerHeight() > bodyHeight) { |
|
y -= tooltip.element.outerHeight() + 15; |
|
!opt.belowMouse && (y = Math.min(y, offset.top - tooltip.element.outerHeight() - 5)); |
|
} else { |
|
!opt.belowMouse && (y = Math.max(y, top)); |
|
} |
|
tooltip.element.css({ |
|
left: x < 0 ? 0 : x + "px", |
|
top: y < 0 ? 0 : y + "px" |
|
}); |
|
tooltip.element.hover(function () { |
|
self.remove(name); |
|
context.element.trigger("mouseleave.title" + context.getName()); |
|
}); |
|
return this; |
|
}, |
|
|
|
add: function (name, bubble) { |
|
if (this.has(name)) { |
|
return this; |
|
} |
|
this.set(name, bubble); |
|
return this; |
|
}, |
|
|
|
get: function (name) { |
|
return this.tooltipsManager[name]; |
|
}, |
|
|
|
set: function (name, bubble) { |
|
this.tooltipsManager[name] = bubble; |
|
}, |
|
|
|
has: function (name) { |
|
return this.tooltipsManager[name] != null; |
|
}, |
|
|
|
remove: function (name) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
this.tooltipsManager[name].destroy(); |
|
delete this.tooltipsManager[name]; |
|
return this; |
|
} |
|
});/** |
|
* 事件集合 |
|
* @class BI.Events |
|
*/ |
|
_.extend(BI, { |
|
Events: { |
|
|
|
/** |
|
* @static |
|
* @property keydown事件 |
|
*/ |
|
KEYDOWN: "_KEYDOWN", |
|
|
|
/** |
|
* @static |
|
* @property 回撤事件 |
|
*/ |
|
BACKSPACE: "_BACKSPACE", |
|
|
|
/** |
|
* @static |
|
* @property 空格事件 |
|
*/ |
|
SPACE: "_SPACE", |
|
|
|
/** |
|
* @static |
|
* @property 回车事件 |
|
*/ |
|
ENTER: "_ENTER", |
|
|
|
/** |
|
* @static |
|
* @property 确定事件 |
|
*/ |
|
CONFIRM: "_CONFIRM", |
|
|
|
/** |
|
* @static |
|
* @property 错误事件 |
|
*/ |
|
ERROR: "_ERROR", |
|
|
|
/** |
|
* @static |
|
* @property 暂停事件 |
|
*/ |
|
PAUSE: "_PAUSE", |
|
|
|
/** |
|
* @static |
|
* @property destroy事件 |
|
*/ |
|
DESTROY: "_DESTROY", |
|
|
|
/** |
|
* @static |
|
* @property 挂载事件 |
|
*/ |
|
MOUNT: "_MOUNT", |
|
|
|
/** |
|
* @static |
|
* @property 取消挂载事件 |
|
*/ |
|
UNMOUNT: "_UNMOUNT", |
|
|
|
/** |
|
* @static |
|
* @property 清除选择 |
|
*/ |
|
CLEAR: "_CLEAR", |
|
|
|
/** |
|
* @static |
|
* @property 添加数据 |
|
*/ |
|
ADD: "_ADD", |
|
|
|
/** |
|
* @static |
|
* @property 正在编辑状态事件 |
|
*/ |
|
EDITING: "_EDITING", |
|
|
|
/** |
|
* @static |
|
* @property 空状态事件 |
|
*/ |
|
EMPTY: "_EMPTY", |
|
|
|
/** |
|
* @static |
|
* @property 显示隐藏事件 |
|
*/ |
|
VIEW: "_VIEW", |
|
|
|
/** |
|
* @static |
|
* @property 窗体改变大小 |
|
*/ |
|
RESIZE: "_RESIZE", |
|
|
|
/** |
|
* @static |
|
* @property 编辑前事件 |
|
*/ |
|
BEFOREEDIT: "_BEFOREEDIT", |
|
|
|
/** |
|
* @static |
|
* @property 编辑后事件 |
|
*/ |
|
AFTEREDIT: "_AFTEREDIT", |
|
|
|
/** |
|
* @static |
|
* @property 开始编辑事件 |
|
*/ |
|
STARTEDIT: "_STARTEDIT", |
|
|
|
/** |
|
* @static |
|
* @property 停止编辑事件 |
|
*/ |
|
STOPEDIT: "_STOPEDIT", |
|
|
|
/** |
|
* @static |
|
* @property 值改变事件 |
|
*/ |
|
CHANGE: "_CHANGE", |
|
|
|
/** |
|
* @static |
|
* @property 下拉弹出菜单事件 |
|
*/ |
|
EXPAND: "_EXPAND", |
|
|
|
/** |
|
* @static |
|
* @property 关闭下拉菜单事件 |
|
*/ |
|
COLLAPSE: "_COLLAPSE", |
|
|
|
/** |
|
* @static |
|
* @property 回调事件 |
|
*/ |
|
CALLBACK: "_CALLBACK", |
|
|
|
/** |
|
* @static |
|
* @property 点击事件 |
|
*/ |
|
CLICK: "_CLICK", |
|
|
|
/** |
|
* @static |
|
* @property 状态改变事件,一般是用在复选按钮和单选按钮 |
|
*/ |
|
STATECHANGE: "_STATECHANGE", |
|
|
|
/** |
|
* @static |
|
* @property 状态改变前事件 |
|
*/ |
|
BEFORESTATECHANGE: "_BEFORESTATECHANGE", |
|
|
|
|
|
/** |
|
* @static |
|
* @property 初始化事件 |
|
*/ |
|
INIT: "_INIT", |
|
|
|
/** |
|
* @static |
|
* @property 初始化后事件 |
|
*/ |
|
AFTERINIT: "_AFTERINIT", |
|
|
|
/** |
|
* @static |
|
* @property 滚动条滚动事件 |
|
*/ |
|
SCROLL: "_SCROLL", |
|
|
|
|
|
/** |
|
* @static |
|
* @property 开始加载事件 |
|
*/ |
|
STARTLOAD: "_STARTLOAD", |
|
|
|
/** |
|
* @static |
|
* @property 加载后事件 |
|
*/ |
|
AFTERLOAD: "_AFTERLOAD", |
|
|
|
|
|
/** |
|
* @static |
|
* @property 提交前事件 |
|
*/ |
|
BS: "beforesubmit", |
|
|
|
/** |
|
* @static |
|
* @property 提交后事件 |
|
*/ |
|
AS: "aftersubmit", |
|
|
|
/** |
|
* @static |
|
* @property 提交完成事件 |
|
*/ |
|
SC: "submitcomplete", |
|
|
|
/** |
|
* @static |
|
* @property 提交失败事件 |
|
*/ |
|
SF: "submitfailure", |
|
|
|
/** |
|
* @static |
|
* @property 提交成功事件 |
|
*/ |
|
SS: "submitsuccess", |
|
|
|
/** |
|
* @static |
|
* @property 校验提交前事件 |
|
*/ |
|
BVW: "beforeverifywrite", |
|
|
|
/** |
|
* @static |
|
* @property 校验提交后事件 |
|
*/ |
|
AVW: "afterverifywrite", |
|
|
|
/** |
|
* @static |
|
* @property 校验后事件 |
|
*/ |
|
AV: "afterverify", |
|
|
|
/** |
|
* @static |
|
* @property 填报前事件 |
|
*/ |
|
BW: "beforewrite", |
|
|
|
/** |
|
* @static |
|
* @property 填报后事件 |
|
*/ |
|
AW: "afterwrite", |
|
|
|
/** |
|
* @static |
|
* @property 填报成功事件 |
|
*/ |
|
WS: "writesuccess", |
|
|
|
/** |
|
* @static |
|
* @property 填报失败事件 |
|
*/ |
|
WF: "writefailure", |
|
|
|
/** |
|
* @static |
|
* @property 添加行前事件 |
|
*/ |
|
BA: "beforeappend", |
|
|
|
/** |
|
* @static |
|
* @property 添加行后事件 |
|
*/ |
|
AA: "afterappend", |
|
|
|
/** |
|
* @static |
|
* @property 删除行前事件 |
|
*/ |
|
BD: "beforedelete", |
|
|
|
/** |
|
* @static |
|
* @property 删除行后事件 |
|
*/ |
|
AD: "beforedelete", |
|
|
|
/** |
|
* @static |
|
* @property 未提交离开事件 |
|
*/ |
|
UC: "unloadcheck", |
|
|
|
|
|
/** |
|
* @static |
|
* @property PDF导出前事件 |
|
*/ |
|
BTOPDF: "beforetopdf", |
|
|
|
/** |
|
* @static |
|
* @property PDF导出后事件 |
|
*/ |
|
ATOPDF: "aftertopdf", |
|
|
|
/** |
|
* @static |
|
* @property Excel导出前事件 |
|
*/ |
|
BTOEXCEL: "beforetoexcel", |
|
|
|
/** |
|
* @static |
|
* @property Excel导出后事件 |
|
*/ |
|
ATOEXCEL: "aftertoexcel", |
|
|
|
/** |
|
* @static |
|
* @property Word导出前事件 |
|
*/ |
|
BTOWORD: "beforetoword", |
|
|
|
/** |
|
* @static |
|
* @property Word导出后事件 |
|
*/ |
|
ATOWORD: "aftertoword", |
|
|
|
/** |
|
* @static |
|
* @property 图片导出前事件 |
|
*/ |
|
BTOIMAGE: "beforetoimage", |
|
|
|
/** |
|
* @static |
|
* @property 图片导出后事件 |
|
*/ |
|
ATOIMAGE: "aftertoimage", |
|
|
|
/** |
|
* @static |
|
* @property HTML导出前事件 |
|
*/ |
|
BTOHTML: "beforetohtml", |
|
|
|
/** |
|
* @static |
|
* @property HTML导出后事件 |
|
*/ |
|
ATOHTML: "aftertohtml", |
|
|
|
/** |
|
* @static |
|
* @property Excel导入前事件 |
|
*/ |
|
BIMEXCEL: "beforeimportexcel", |
|
|
|
/** |
|
* @static |
|
* @property Excel导出后事件 |
|
*/ |
|
AIMEXCEL: "afterimportexcel", |
|
|
|
/** |
|
* @static |
|
* @property PDF打印前事件 |
|
*/ |
|
BPDFPRINT: "beforepdfprint", |
|
|
|
/** |
|
* @static |
|
* @property PDF打印后事件 |
|
*/ |
|
APDFPRINT: "afterpdfprint", |
|
|
|
/** |
|
* @static |
|
* @property Flash打印前事件 |
|
*/ |
|
BFLASHPRINT: "beforeflashprint", |
|
|
|
/** |
|
* @static |
|
* @property Flash打印后事件 |
|
*/ |
|
AFLASHPRINT: "afterflashprint", |
|
|
|
/** |
|
* @static |
|
* @property Applet打印前事件 |
|
*/ |
|
BAPPLETPRINT: "beforeappletprint", |
|
|
|
/** |
|
* @static |
|
* @property Applet打印后事件 |
|
*/ |
|
AAPPLETPRINT: "afterappletprint", |
|
|
|
/** |
|
* @static |
|
* @property 服务器打印前事件 |
|
*/ |
|
BSEVERPRINT: "beforeserverprint", |
|
|
|
/** |
|
* @static |
|
* @property 服务器打印后事件 |
|
*/ |
|
ASERVERPRINT: "afterserverprint", |
|
|
|
/** |
|
* @static |
|
* @property 邮件发送前事件 |
|
*/ |
|
BEMAIL: "beforeemail", |
|
|
|
/** |
|
* @static |
|
* @property 邮件发送后事件 |
|
*/ |
|
AEMAIL: "afteremail" |
|
} |
|
});/** |
|
* 对数组对象的扩展 |
|
* @class Array |
|
*/ |
|
_.extend(BI, { |
|
|
|
pushArray: function (sArray, array) { |
|
for (var i = 0; i < array.length; i++) { |
|
sArray.push(array[i]); |
|
} |
|
}, |
|
pushDistinct: function (sArray, obj) { |
|
if (!BI.contains(sArray, obj)) { |
|
sArray.push(obj); |
|
} |
|
}, |
|
pushDistinctArray: function (sArray, array) { |
|
for (var i = 0, len = array.length; i < len; i++) { |
|
BI.pushDistinct(sArray, array[i]); |
|
} |
|
} |
|
}); |
|
BI.prepares.push(function () { |
|
BI.Date = BI.Date || {}; |
|
// 牵扯到国际化这些常量在页面加载后再生效 |
|
// full day names |
|
BI.Date._DN = [BI.i18nText("BI-Basic_Sunday"), |
|
BI.i18nText("BI-Basic_Monday"), |
|
BI.i18nText("BI-Basic_Tuesday"), |
|
BI.i18nText("BI-Basic_Wednesday"), |
|
BI.i18nText("BI-Basic_Thursday"), |
|
BI.i18nText("BI-Basic_Friday"), |
|
BI.i18nText("BI-Basic_Saturday"), |
|
BI.i18nText("BI-Basic_Sunday")]; |
|
|
|
// short day names |
|
BI.Date._SDN = [BI.i18nText("BI-Basic_Simple_Sunday"), |
|
BI.i18nText("BI-Basic_Simple_Monday"), |
|
BI.i18nText("BI-Basic_Simple_Tuesday"), |
|
BI.i18nText("BI-Basic_Simple_Wednesday"), |
|
BI.i18nText("BI-Basic_Simple_Thursday"), |
|
BI.i18nText("BI-Basic_Simple_Friday"), |
|
BI.i18nText("BI-Basic_Simple_Saturday"), |
|
BI.i18nText("BI-Basic_Simple_Sunday")]; |
|
|
|
// Monday first, etc. |
|
BI.Date._FD = 1; |
|
|
|
// full month namesdat |
|
BI.Date._MN = [ |
|
BI.i18nText("BI-Basic_January"), |
|
BI.i18nText("BI-Basic_February"), |
|
BI.i18nText("BI-Basic_March"), |
|
BI.i18nText("BI-Basic_April"), |
|
BI.i18nText("BI-Basic_May"), |
|
BI.i18nText("BI-Basic_June"), |
|
BI.i18nText("BI-Basic_July"), |
|
BI.i18nText("BI-Basic_August"), |
|
BI.i18nText("BI-Basic_September"), |
|
BI.i18nText("BI-Basic_October"), |
|
BI.i18nText("BI-Basic_November"), |
|
BI.i18nText("BI-Basic_December")]; |
|
|
|
// short month names |
|
BI.Date._SMN = [0, |
|
1, |
|
2, |
|
3, |
|
4, |
|
5, |
|
6, |
|
7, |
|
8, |
|
9, |
|
10, |
|
11]; |
|
|
|
BI.Date._QN = ["", BI.i18nText("BI-Quarter_1"), |
|
BI.i18nText("BI-Quarter_2"), |
|
BI.i18nText("BI-Quarter_3"), |
|
BI.i18nText("BI-Quarter_4")]; |
|
|
|
/** Adds the number of days array to the Date object. */ |
|
BI.Date._MD = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |
|
|
|
// 实际上无论周几作为一周的第一天,周初周末都是在-6-0间做偏移,用一个数组就可以 |
|
BI.Date._OFFSET = [0, -1, -2, -3, -4, -5, -6]; |
|
});/** Constants used for time computations */ |
|
BI.Date = BI.Date || {}; |
|
BI.Date.SECOND = 1000; |
|
BI.Date.MINUTE = 60 * BI.Date.SECOND; |
|
BI.Date.HOUR = 60 * BI.Date.MINUTE; |
|
BI.Date.DAY = 24 * BI.Date.HOUR; |
|
BI.Date.WEEK = 7 * BI.Date.DAY; |
|
|
|
_.extend(BI, { |
|
/** |
|
* 获取时区 |
|
* @returns {String} |
|
*/ |
|
getTimezone: function (date) { |
|
return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, ""); |
|
}, |
|
|
|
/** Returns the number of days in the current month */ |
|
getMonthDays: function (date, month) { |
|
var year = date.getFullYear(); |
|
if (typeof month === "undefined") { |
|
month = date.getMonth(); |
|
} |
|
if (((0 == (year % 4)) && ((0 != (year % 100)) || (0 == (year % 400)))) && month == 1) { |
|
return 29; |
|
} |
|
return BI.Date._MD[month]; |
|
|
|
}, |
|
|
|
/** |
|
* 获取每月的最后一天 |
|
* @returns {Date} |
|
*/ |
|
getLastDateOfMonth: function (date) { |
|
return BI.getDate(date.getFullYear(), date.getMonth(), BI.getMonthDays(date)); |
|
}, |
|
|
|
/** Returns the number of day in the year. */ |
|
getDayOfYear: function (date) { |
|
var now = BI.getDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); |
|
var then = BI.getDate(date.getFullYear(), 0, 0, 0, 0, 0); |
|
var time = now - then; |
|
return Math.floor(time / BI.Date.DAY); |
|
}, |
|
|
|
/** Returns the number of the week in year, as defined in ISO 8601. */ |
|
getWeekNumber: function (date) { |
|
var d = BI.getDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); |
|
var week = d.getDay(); |
|
var startOfWeek = BI.StartOfWeek % 7; |
|
var middleDay = (startOfWeek + 3) % 7; |
|
middleDay = middleDay || 7; |
|
// 偏移到周周首之前需要多少天 |
|
var offsetWeekStartCount = week < startOfWeek ? (7 + week - startOfWeek) : (week - startOfWeek); |
|
var offsetWeekMiddleCount = middleDay < startOfWeek ? (7 + middleDay - startOfWeek) : (middleDay - startOfWeek); |
|
d.setDate(d.getDate() - offsetWeekStartCount + offsetWeekMiddleCount); |
|
var ms = d.valueOf(); |
|
d.setMonth(0); |
|
d.setDate(1); |
|
return Math.floor((ms - d.valueOf()) / (7 * 864e5)) + 1; |
|
}, |
|
|
|
getQuarter: function (date) { |
|
return Math.floor(date.getMonth() / 3) + 1; |
|
}, |
|
|
|
// 离当前时间多少天的时间 |
|
getOffsetDate: function (date, offset) { |
|
return BI.getDate(BI.getTime(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()) + offset * 864e5); |
|
}, |
|
|
|
getOffsetQuarter: function (date, n) { |
|
var dt = BI.getDate(BI.getTime(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds())); |
|
var day = dt.getDate(); |
|
var monthDay = BI.getMonthDays(BI.getDate(dt.getFullYear(), dt.getMonth() + BI.parseInt(n) * 3, 1)); |
|
if (day > monthDay) { |
|
day = monthDay; |
|
} |
|
dt.setDate(day); |
|
dt.setMonth(dt.getMonth() + parseInt(n) * 3); |
|
return dt; |
|
}, |
|
|
|
// 得到本季度的起始月份 |
|
getQuarterStartMonth: function (date) { |
|
var quarterStartMonth = 0; |
|
var nowMonth = date.getMonth(); |
|
if (nowMonth < 3) { |
|
quarterStartMonth = 0; |
|
} |
|
if (2 < nowMonth && nowMonth < 6) { |
|
quarterStartMonth = 3; |
|
} |
|
if (5 < nowMonth && nowMonth < 9) { |
|
quarterStartMonth = 6; |
|
} |
|
if (nowMonth > 8) { |
|
quarterStartMonth = 9; |
|
} |
|
return quarterStartMonth; |
|
}, |
|
// 获得本季度的起始日期 |
|
getQuarterStartDate: function (date) { |
|
return BI.getDate(date.getFullYear(), BI.getQuarterStartMonth(date), 1); |
|
}, |
|
// 得到本季度的结束日期 |
|
getQuarterEndDate: function (date) { |
|
var quarterEndMonth = BI.getQuarterStartMonth(date) + 2; |
|
return BI.getDate(date.getFullYear(), quarterEndMonth, BI.getMonthDays(date, quarterEndMonth)); |
|
}, |
|
|
|
// 指定日期n个月之前或之后的日期 |
|
getOffsetMonth: function (date, n) { |
|
var dt = BI.getDate(BI.getTime(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds())); |
|
var day = dt.getDate(); |
|
var monthDay = BI.getMonthDays(BI.getDate(dt.getFullYear(), dt.getMonth() + parseInt(n), 1)); |
|
if (day > monthDay) { |
|
day = monthDay; |
|
} |
|
dt.setDate(day); |
|
dt.setMonth(dt.getMonth() + parseInt(n)); |
|
return dt; |
|
}, |
|
|
|
// 获得本周的起始日期 |
|
getWeekStartDate: function (date) { |
|
var w = date.getDay(); |
|
var startOfWeek = BI.StartOfWeek % 7; |
|
return BI.getOffsetDate(date, BI.Date._OFFSET[w < startOfWeek ? (7 + w - startOfWeek) : (w - startOfWeek)]); |
|
}, |
|
// 得到本周的结束日期 |
|
getWeekEndDate: function (date) { |
|
var w = date.getDay(); |
|
var startOfWeek = BI.StartOfWeek % 7; |
|
return BI.getOffsetDate(date, BI.Date._OFFSET[w < startOfWeek ? (7 + w - startOfWeek) : (w - startOfWeek)] + 6); |
|
}, |
|
|
|
// 格式化打印日期 |
|
print: function (date, str) { |
|
var m = date.getMonth(); |
|
var d = date.getDate(); |
|
var y = date.getFullYear(); |
|
var yWith4number = y + ""; |
|
while (yWith4number.length < 4) { |
|
yWith4number = "0" + yWith4number; |
|
} |
|
var wn = BI.getWeekNumber(date); |
|
var qr = BI.getQuarter(date); |
|
var w = date.getDay(); |
|
var s = {}; |
|
var hr = date.getHours(); |
|
var pm = (hr >= 12); |
|
var ir = (pm) ? (hr - 12) : hr; |
|
var dy = BI.getDayOfYear(date); |
|
if (ir == 0) { |
|
ir = 12; |
|
} |
|
var min = date.getMinutes(); |
|
var sec = date.getSeconds(); |
|
s["%a"] = BI.Date._SDN[w]; // abbreviated weekday name [FIXME: I18N] |
|
s["%A"] = BI.Date._DN[w]; // full weekday name |
|
s["%b"] = BI.Date._SMN[m]; // abbreviated month name [FIXME: I18N] |
|
s["%B"] = BI.Date._MN[m]; // full month name |
|
// FIXME: %c : preferred date and time representation for the current locale |
|
s["%C"] = 1 + Math.floor(y / 100); // the century number |
|
s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) |
|
s["%e"] = d; // the day of the month (range 1 to 31) |
|
// FIXME: %D : american date style: %m/%d/%y |
|
// FIXME: %E, %F, %G, %g, %h (man strftime) |
|
s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) |
|
s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) |
|
s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) |
|
s["%k"] = hr + ""; // hour, range 0 to 23 (24h format) |
|
s["%l"] = ir + ""; // hour, range 1 to 12 (12h format) |
|
s["%X"] = (m < 9) ? ("0" + (1 + m)) : (1 + m); // month, range 01 to 12 |
|
s["%x"] = m + 1; // month, range 1 to 12 |
|
s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 |
|
s["%n"] = "\n"; // a newline character |
|
s["%p"] = pm ? "PM" : "AM"; |
|
s["%P"] = pm ? "pm" : "am"; |
|
// FIXME: %r : the time in am/pm notation %I:%M:%S %p |
|
// FIXME: %R : the time in 24-hour notation %H:%M |
|
s["%s"] = Math.floor(date.getTime() / 1000); |
|
s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 |
|
s["%t"] = "\t"; // a tab character |
|
// FIXME: %T : the time in 24-hour notation (%H:%M:%S) |
|
s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; |
|
s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) |
|
s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) |
|
// FIXME: %x : preferred date representation for the current locale without the time |
|
// FIXME: %X : preferred time representation for the current locale without the date |
|
s["%y"] = yWith4number.substr(2, 2); // year without the century (range 00 to 99) |
|
s["%Y"] = yWith4number; // year with the century |
|
s["%%"] = "%"; // a literal '%' character |
|
s["%Q"] = qr; |
|
|
|
var re = /%./g; |
|
BI.isKhtml = BI.isKhtml || function () { |
|
if(!_global.navigator) { |
|
return false; |
|
} |
|
return /Konqueror|Safari|KHTML/i.test(navigator.userAgent); |
|
}; |
|
|
|
// 包含年周的格式化,ISO8601标准周的计数会影响年 |
|
if ((str.indexOf("%Y") !== -1 || str.indexOf("%y") !== -1) && (str.indexOf("%W") !== -1 || str.indexOf("%U") !== -1 || str.indexOf("%V") !== -1)) { |
|
switch (wn) { |
|
// 如果周数是1,但是当前却在12月,表示此周数为下一年的 |
|
case 1: |
|
if (m === 11) { |
|
s["%y"] = parseInt(s["%y"]) + 1; |
|
s["%Y"] = parseInt(s["%Y"]) + 1; |
|
} |
|
break; |
|
// 如果周数是53,但是当前却在1月,表示此周数为上一年的 |
|
case 53: |
|
if (m === 0) { |
|
s["%y"] = parseInt(s["%y"]) - 1; |
|
s["%Y"] = parseInt(s["%Y"]) - 1; |
|
} |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
if (!BI.isKhtml()) { |
|
return str.replace(re, function (par) { |
|
return s[par] || par; |
|
}); |
|
} |
|
var a = str.match(re); |
|
for (var i = 0; i < a.length; i++) { |
|
var tmp = s[a[i]]; |
|
if (tmp) { |
|
re = new RegExp(a[i], "g"); |
|
str = str.replace(re, tmp); |
|
} |
|
} |
|
|
|
return str; |
|
} |
|
}); |
|
/** |
|
* 基本的函数 |
|
* Created by GUY on 2015/6/24. |
|
*/ |
|
BI.Func = {}; |
|
_.extend(BI.Func, { |
|
/** |
|
* 创建唯一的名字 |
|
* @param array |
|
* @param name |
|
* @returns {*} |
|
*/ |
|
createDistinctName: function (array, name) { |
|
var src = name, idx = 1; |
|
name = name || ""; |
|
while (true) { |
|
if (BI.every(array, function (i, item) { |
|
return BI.isKey(item) ? item !== name : item.name !== name; |
|
})) { |
|
break; |
|
} |
|
name = src + (idx++); |
|
} |
|
return name; |
|
}, |
|
|
|
/** |
|
* 获取字符宽度 |
|
* @param str |
|
* @return {number} |
|
*/ |
|
getGBWidth: function (str) { |
|
str = str + ""; |
|
str = str.replace(/[^\x00-\xff]/g, "xx"); |
|
return Math.ceil(str.length / 2); |
|
}, |
|
|
|
/** |
|
* 获取搜索结果 |
|
* @param items |
|
* @param keyword |
|
* @param param 搜索哪个属性 |
|
*/ |
|
getSearchResult: function (items, keyword, param) { |
|
var isArray = BI.isArray(items); |
|
items = isArray ? BI.flatten(items) : items; |
|
param || (param = "text"); |
|
if (!BI.isKey(keyword)) { |
|
return { |
|
find: BI.deepClone(items), |
|
match: isArray ? [] : {} |
|
}; |
|
} |
|
var t, text, py; |
|
keyword = BI.toUpperCase(keyword); |
|
var matched = isArray ? [] : {}, find = isArray ? [] : {}; |
|
BI.each(items, function (i, item) { |
|
// 兼容item为null的处理 |
|
if (BI.isNull(item)) { |
|
return; |
|
} |
|
item = BI.deepClone(item); |
|
t = BI.stripEL(item); |
|
text = BI.find([t[param], t.text, t.value, t.name, t], function (index, val) { |
|
return BI.isNotNull(val); |
|
}); |
|
|
|
if (BI.isNull(text) || BI.isObject(text)) return; |
|
|
|
py = BI.makeFirstPY(text, { |
|
splitChar: "\u200b" |
|
}); |
|
text = BI.toUpperCase(text); |
|
py = BI.toUpperCase(py); |
|
var pidx; |
|
if (text.indexOf(keyword) > -1) { |
|
if (text === keyword) { |
|
isArray ? matched.push(item) : (matched[i] = item); |
|
} else { |
|
isArray ? find.push(item) : (find[i] = item); |
|
} |
|
// BI-56386 这边两个pid / text.length是为了防止截取的首字符串不是完整的,但光这样做还不够,即时错位了,也不能说明就不符合条件 |
|
} else if (pidx = py.indexOf(keyword), (pidx > -1)) { |
|
if (text === keyword || keyword.length === text.length) { |
|
isArray ? matched.push(item) : (matched[i] = item); |
|
} else { |
|
isArray ? find.push(item) : (find[i] = item); |
|
} |
|
} |
|
}); |
|
return { |
|
match: matched, |
|
find: find |
|
}; |
|
} |
|
}); |
|
|
|
_.extend(BI, { |
|
beforeFunc: function (sFunc, func) { |
|
var __self = sFunc; |
|
return function () { |
|
if (func.apply(sFunc, arguments) === false) { |
|
return false; |
|
} |
|
return __self.apply(sFunc, arguments); |
|
}; |
|
}, |
|
|
|
afterFunc: function (sFunc, func) { |
|
var __self = sFunc; |
|
return function () { |
|
var ret = __self.apply(sFunc, arguments); |
|
if (ret === false) { |
|
return false; |
|
} |
|
func.apply(sFunc, arguments); |
|
return ret; |
|
}; |
|
} |
|
});_.extend(BI, { |
|
// 给Number类型增加一个add方法,调用起来更加方便。 |
|
add: function (num, arg) { |
|
return accAdd(arg, num); |
|
|
|
/** |
|
** 加法函数,用来得到精确的加法结果 |
|
** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。 |
|
** 调用:accAdd(arg1,arg2) |
|
** 返回值:arg1加上arg2的精确结果 |
|
**/ |
|
function accAdd (arg1, arg2) { |
|
var r1, r2, m, c; |
|
try { |
|
r1 = arg1.toString().split(".")[1].length; |
|
} catch (e) { |
|
r1 = 0; |
|
} |
|
try { |
|
r2 = arg2.toString().split(".")[1].length; |
|
} catch (e) { |
|
r2 = 0; |
|
} |
|
c = Math.abs(r1 - r2); |
|
m = Math.pow(10, Math.max(r1, r2)); |
|
if (c > 0) { |
|
var cm = Math.pow(10, c); |
|
if (r1 > r2) { |
|
arg1 = Number(arg1.toString().replace(".", "")); |
|
arg2 = Number(arg2.toString().replace(".", "")) * cm; |
|
} else { |
|
arg1 = Number(arg1.toString().replace(".", "")) * cm; |
|
arg2 = Number(arg2.toString().replace(".", "")); |
|
} |
|
} else { |
|
arg1 = Number(arg1.toString().replace(".", "")); |
|
arg2 = Number(arg2.toString().replace(".", "")); |
|
} |
|
return (arg1 + arg2) / m; |
|
} |
|
}, |
|
|
|
// 给Number类型增加一个sub方法,调用起来更加方便。 |
|
sub: function (num, arg) { |
|
return accSub(num, arg); |
|
|
|
/** |
|
** 减法函数,用来得到精确的减法结果 |
|
** 说明:javascript的减法结果会有误差,在两个浮点数相减的时候会比较明显。这个函数返回较为精确的减法结果。 |
|
** 调用:accSub(arg1,arg2) |
|
** 返回值:arg1加上arg2的精确结果 |
|
**/ |
|
function accSub (arg1, arg2) { |
|
var r1, r2, m, n; |
|
try { |
|
r1 = arg1.toString().split(".")[1].length; |
|
} catch (e) { |
|
r1 = 0; |
|
} |
|
try { |
|
r2 = arg2.toString().split(".")[1].length; |
|
} catch (e) { |
|
r2 = 0; |
|
} |
|
m = Math.pow(10, Math.max(r1, r2)); // last modify by deeka //动态控制精度长度 |
|
n = (r1 >= r2) ? r1 : r2; |
|
return ((arg1 * m - arg2 * m) / m).toFixed(n); |
|
} |
|
}, |
|
|
|
// 给Number类型增加一个mul方法,调用起来更加方便。 |
|
mul: function (num, arg) { |
|
return accMul(arg, num); |
|
|
|
/** |
|
** 乘法函数,用来得到精确的乘法结果 |
|
** 说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。 |
|
** 调用:accMul(arg1,arg2) |
|
** 返回值:arg1乘以 arg2的精确结果 |
|
**/ |
|
function accMul (arg1, arg2) { |
|
var m = 0, s1 = arg1.toString(), s2 = arg2.toString(); |
|
try { |
|
m += s1.split(".")[1].length; |
|
} catch (e) { |
|
} |
|
try { |
|
m += s2.split(".")[1].length; |
|
} catch (e) { |
|
} |
|
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m); |
|
} |
|
}, |
|
|
|
// 给Number类型增加一个div方法,调用起来更加方便。 |
|
div: function (num, arg) { |
|
return accDivide(num, arg); |
|
|
|
/** |
|
* Return digits length of a number |
|
* @param {*number} num Input number |
|
*/ |
|
function digitLength (num) { |
|
// Get digit length of e |
|
var eSplit = num.toString().split(/[eE]/); |
|
var len = (eSplit[0].split(".")[1] || "").length - (+(eSplit[1] || 0)); |
|
return len > 0 ? len : 0; |
|
} |
|
/** |
|
* 把小数转成整数,支持科学计数法。如果是小数则放大成整数 |
|
* @param {*number} num 输入数 |
|
*/ |
|
function float2Fixed (num) { |
|
if (num.toString().indexOf("e") === -1) { |
|
return Number(num.toString().replace(".", "")); |
|
} |
|
var dLen = digitLength(num); |
|
return dLen > 0 ? num * Math.pow(10, dLen) : num; |
|
} |
|
|
|
/** |
|
* 精确乘法 |
|
*/ |
|
function times (num1, num2) { |
|
var others = []; |
|
for (var _i = 2; _i < arguments.length; _i++) { |
|
others[_i - 2] = arguments[_i]; |
|
} |
|
if (others.length > 0) { |
|
return times.apply(void 0, [times(num1, num2), others[0]].concat(others.slice(1))); |
|
} |
|
var num1Changed = float2Fixed(num1); |
|
var num2Changed = float2Fixed(num2); |
|
var baseNum = digitLength(num1) + digitLength(num2); |
|
var leftValue = num1Changed * num2Changed; |
|
return leftValue / Math.pow(10, baseNum); |
|
} |
|
|
|
/** |
|
* 精确除法 |
|
*/ |
|
function accDivide (num1, num2) { |
|
var others = []; |
|
for (var _i = 2; _i < arguments.length; _i++) { |
|
others[_i - 2] = arguments[_i]; |
|
} |
|
if (others.length > 0) { |
|
return accDivide.apply(void 0, [accDivide(num1, num2), others[0]].concat(others.slice(1))); |
|
} |
|
var num1Changed = float2Fixed(num1); |
|
var num2Changed = float2Fixed(num2); |
|
return times((num1Changed / num2Changed), Math.pow(10, digitLength(num2) - digitLength(num1))); |
|
} |
|
} |
|
|
|
});/** |
|
* 对字符串对象的扩展 |
|
* @class String |
|
*/ |
|
_.extend(BI, { |
|
|
|
/** |
|
* 判断字符串是否已指定的字符串开始 |
|
* @param str source字符串 |
|
* @param {String} startTag 指定的开始字符串 |
|
* @return {Boolean} 如果字符串以指定字符串开始则返回true,否则返回false |
|
*/ |
|
startWith: function (str, startTag) { |
|
str = str || ""; |
|
if (startTag == null || startTag == "" || str.length === 0 || startTag.length > str.length) { |
|
return false; |
|
} |
|
return str.substr(0, startTag.length) == startTag; |
|
}, |
|
/** |
|
* 判断字符串是否以指定的字符串结束 |
|
* @param str source字符串 |
|
* @param {String} endTag 指定的字符串 |
|
* @return {Boolean} 如果字符串以指定字符串结束则返回true,否则返回false |
|
*/ |
|
endWith: function (str, endTag) { |
|
if (endTag == null || endTag == "" || str.length === 0 || endTag.length > str.length) { |
|
return false; |
|
} |
|
return str.substring(str.length - endTag.length) == endTag; |
|
}, |
|
|
|
/** |
|
* 获取url中指定名字的参数 |
|
* @param str source字符串 |
|
* @param {String} name 参数的名字 |
|
* @return {String} 参数的值 |
|
*/ |
|
getQuery: function (str, name) { |
|
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); |
|
var r = str.substr(str.indexOf("?") + 1).match(reg); |
|
if (r) { |
|
return unescape(r[2]); |
|
} |
|
return null; |
|
}, |
|
|
|
/** |
|
* 给url加上给定的参数 |
|
* @param str source字符串 |
|
* @param {Object} paras 参数对象,是一个键值对对象 |
|
* @return {String} 添加了给定参数的url |
|
*/ |
|
appendQuery: function (str, paras) { |
|
if (!paras) { |
|
return str; |
|
} |
|
var src = str; |
|
// 没有问号说明还没有参数 |
|
if (src.indexOf("?") === -1) { |
|
src += "?"; |
|
} |
|
// 如果以问号结尾,说明没有其他参数 |
|
if (BI.endWith(src, "?") !== false) { |
|
} else { |
|
src += "&"; |
|
} |
|
_.each(paras, function (value, name) { |
|
if (typeof(name) === "string") { |
|
src += name + "=" + value + "&"; |
|
} |
|
}); |
|
src = src.substr(0, src.length - 1); |
|
return src; |
|
}, |
|
/** |
|
* 将所有符合第一个字符串所表示的字符串替换成为第二个字符串 |
|
* @param str source字符串 |
|
* @param {String} s1 要替换的字符串的正则表达式 |
|
* @param {String} s2 替换的结果字符串 |
|
* @returns {String} 替换后的字符串 |
|
*/ |
|
replaceAll: function (str, s1, s2) { |
|
return str.replace(new RegExp(s1, "gm"), s2); |
|
}, |
|
/** |
|
* 总是让字符串以指定的字符开头 |
|
* @param str source字符串 |
|
* @param {String} start 指定的字符 |
|
* @returns {String} 以指定字符开头的字符串 |
|
*/ |
|
perfectStart: function (str, start) { |
|
if (BI.startWith(str, start)) { |
|
return str; |
|
} |
|
return start + str; |
|
|
|
}, |
|
|
|
/** |
|
* 获取字符串中某字符串的所有项位置数组 |
|
* @param str source字符串 |
|
* @param {String} sub 子字符串 |
|
* @return {Number[]} 子字符串在父字符串中出现的所有位置组成的数组 |
|
*/ |
|
allIndexOf: function (str, sub) { |
|
if (typeof sub !== "string") { |
|
return []; |
|
} |
|
var location = []; |
|
var offset = 0; |
|
while (str.length > 0) { |
|
var loc = str.indexOf(sub); |
|
if (loc === -1) { |
|
break; |
|
} |
|
location.push(offset + loc); |
|
str = str.substring(loc + sub.length, str.length); |
|
offset += loc + sub.length; |
|
} |
|
return location; |
|
} |
|
});!(function () { |
|
var i18nStore = {}; |
|
_.extend(BI, { |
|
addI18n: function (i18n) { |
|
BI.extend(i18nStore, i18n); |
|
}, |
|
i18nText: function (key) { |
|
var localeText = i18nStore[key] || (BI.i18n && BI.i18n[key]) || ""; |
|
if (!localeText) { |
|
localeText = key; |
|
} |
|
var len = arguments.length; |
|
if (len > 1) { |
|
if (localeText.indexOf("{R1}") > -1) { |
|
for (var i = 1; i < len; i++) { |
|
var key = "{R" + i + "}"; |
|
localeText = BI.replaceAll(localeText, key, arguments[i] + ""); |
|
} |
|
} else { |
|
var args = Array.prototype.slice.call(arguments); |
|
var count = 1; |
|
return BI.replaceAll(localeText, "\\{\\s*\\}", function () { |
|
return args[count++] + ""; |
|
}); |
|
} |
|
} |
|
return localeText; |
|
} |
|
}); |
|
})();(function () { |
|
var moduleInjection = {}; |
|
BI.module = function (xtype, cls) { |
|
if (moduleInjection[xtype] != null) { |
|
_global.console && console.error("module:[" + xtype + "] has been registed"); |
|
} |
|
moduleInjection[xtype] = cls; |
|
}; |
|
|
|
var constantInjection = {}; |
|
BI.constant = function (xtype, cls) { |
|
if (constantInjection[xtype] != null) { |
|
_global.console && console.error("constant:[" + xtype + "] has been registed"); |
|
} |
|
constantInjection[xtype] = cls; |
|
}; |
|
|
|
var modelInjection = {}; |
|
BI.model = function (xtype, cls) { |
|
if (modelInjection[xtype] != null) { |
|
_global.console && console.error("model:[" + xtype + "] has been registed"); |
|
} |
|
modelInjection[xtype] = cls; |
|
}; |
|
|
|
var storeInjection = {}; |
|
BI.store = function (xtype, cls) { |
|
if (storeInjection[xtype] != null) { |
|
_global.console && console.error("store:[" + xtype + "] has been registed"); |
|
} |
|
storeInjection[xtype] = cls; |
|
}; |
|
|
|
var serviceInjection = {}; |
|
BI.service = function (xtype, cls) { |
|
if (serviceInjection[xtype] != null) { |
|
_global.console && console.error("service:[" + xtype + "] has been registed"); |
|
} |
|
serviceInjection[xtype] = cls; |
|
}; |
|
|
|
var providerInjection = {}; |
|
BI.provider = function (xtype, cls) { |
|
if (providerInjection[xtype] != null) { |
|
_global.console && console.error("provider:[" + xtype + "] has been registed"); |
|
} |
|
providerInjection[xtype] = cls; |
|
}; |
|
|
|
var configFunctions = {}; |
|
BI.config = function (type, configFn) { |
|
if (BI.initialized) { |
|
if (constantInjection[type]) { |
|
return (constantInjection[type] = configFn(constantInjection[type])); |
|
} |
|
if (providerInjection[type]) { |
|
if (!providers[type]) { |
|
providers[type] = new providerInjection[type](); |
|
} |
|
return configFn(providers[type]); |
|
} |
|
return BI.Plugin.configWidget(type, configFn); |
|
} |
|
if (!configFunctions[type]) { |
|
configFunctions[type] = []; |
|
BI.prepares.push(function () { |
|
var queue = configFunctions[type]; |
|
for (var i = 0; i < queue.length; i++) { |
|
if (constantInjection[type]) { |
|
constantInjection[type] = queue[i](constantInjection[type]); |
|
continue; |
|
} |
|
if (providerInjection[type]) { |
|
if (!providers[type]) { |
|
providers[type] = new providerInjection[type](); |
|
} |
|
queue[i](providers[type]); |
|
continue; |
|
} |
|
BI.Plugin.configWidget(type, queue[i]); |
|
} |
|
configFunctions[type] = null; |
|
}); |
|
} |
|
configFunctions[type].push(configFn); |
|
}; |
|
|
|
var actions = {}; |
|
var globalAction = []; |
|
BI.action = function (type, actionFn) { |
|
if (BI.isFunction(type)) { |
|
globalAction.push(type); |
|
return function () { |
|
BI.remove(globalAction, function (idx) { |
|
return globalAction.indexOf(actionFn) === idx; |
|
}); |
|
}; |
|
} |
|
if (!actions[type]) { |
|
actions[type] = []; |
|
} |
|
actions[type].push(actionFn); |
|
return function () { |
|
BI.remove(actions[type], function (idx) { |
|
return actions[type].indexOf(actionFn) === idx; |
|
}); |
|
if (actions[type].length === 0) { |
|
delete actions[type]; |
|
} |
|
}; |
|
}; |
|
|
|
var points = {}; |
|
BI.point = function (type, action, pointFn, after) { |
|
if (!points[type]) { |
|
points[type] = {}; |
|
} |
|
if (!points[type][action]) { |
|
points[type][action] = {}; |
|
} |
|
if (!points[type][action][after ? "after" : "before"]) { |
|
points[type][action][after ? "after" : "before"] = []; |
|
} |
|
points[type][action][after ? "after" : "before"].push(pointFn); |
|
}; |
|
|
|
BI.Modules = { |
|
getModule: function (type) { |
|
if (!moduleInjection[type]) { |
|
_global.console && console.error("module:[" + type + "] does not exists"); |
|
return false; |
|
} |
|
return moduleInjection[type]; |
|
}, |
|
getAllModules: function () { |
|
return moduleInjection; |
|
} |
|
}; |
|
|
|
BI.Constants = { |
|
getConstant: function (type) { |
|
return constantInjection[type]; |
|
} |
|
}; |
|
|
|
var callPoint = function (inst, types) { |
|
types = BI.isArray(types) ? types : [types]; |
|
BI.each(types, function (idx, type) { |
|
if (points[type]) { |
|
for (var action in points[type]) { |
|
var bfns = points[type][action].before; |
|
if (bfns) { |
|
BI.aspect.before(inst, action, function (bfns) { |
|
return function () { |
|
for (var i = 0, len = bfns.length; i < len; i++) { |
|
try { |
|
bfns[i].apply(inst, arguments); |
|
} catch (e) { |
|
_global.console && console.error(e); |
|
} |
|
} |
|
}; |
|
}(bfns)); |
|
} |
|
var afns = points[type][action].after; |
|
if (afns) { |
|
BI.aspect.after(inst, action, function (afns) { |
|
return function () { |
|
for (var i = 0, len = afns.length; i < len; i++) { |
|
try { |
|
afns[i].apply(inst, arguments); |
|
} catch (e) { |
|
_global.console && console.error(e); |
|
} |
|
} |
|
}; |
|
}(afns)); |
|
} |
|
} |
|
} |
|
}); |
|
}; |
|
|
|
BI.Models = { |
|
getModel: function (type, config) { |
|
var inst = new modelInjection[type](config); |
|
inst._constructor && inst._constructor(config); |
|
inst.mixins && callPoint(inst, inst.mixins); |
|
callPoint(inst, type); |
|
return inst; |
|
} |
|
}; |
|
|
|
var stores = {}; |
|
|
|
BI.Stores = { |
|
getStore: function (type, config) { |
|
if (stores[type]) { |
|
return stores[type]; |
|
} |
|
var inst = stores[type] = new storeInjection[type](config); |
|
inst._constructor && inst._constructor(config); |
|
callPoint(inst, type); |
|
return inst; |
|
} |
|
}; |
|
|
|
var services = {}; |
|
|
|
BI.Services = { |
|
getService: function (type, config) { |
|
if (services[type]) { |
|
return services[type]; |
|
} |
|
services[type] = new serviceInjection[type](config); |
|
callPoint(services[type], type); |
|
return services[type]; |
|
} |
|
}; |
|
|
|
var providers = {}, |
|
providerInstance = {}; |
|
|
|
BI.Providers = { |
|
getProvider: function (type, config) { |
|
if (!providers[type]) { |
|
providers[type] = new providerInjection[type](); |
|
} |
|
if (!providerInstance[type]) { |
|
providerInstance[type] = new (providers[type].$get())(config); |
|
} |
|
return providerInstance[type]; |
|
} |
|
}; |
|
|
|
BI.Actions = { |
|
runAction: function (type, event, config) { |
|
BI.each(actions[type], function (i, act) { |
|
try { |
|
act(event, config); |
|
} catch (e) { |
|
_global.console && console.error(e); |
|
} |
|
}); |
|
}, |
|
runGlobalAction: function () { |
|
var args = [].slice.call(arguments); |
|
BI.each(globalAction, function (i, act) { |
|
try { |
|
act.apply(null, args); |
|
} catch (e) { |
|
_global.console && console.error(e); |
|
} |
|
}); |
|
} |
|
}; |
|
|
|
BI.getContext = function (type, config) { |
|
if (constantInjection[type]) { |
|
return BI.Constants.getConstant(type); |
|
} |
|
if (modelInjection[type]) { |
|
return BI.Models.getModel(type, config); |
|
} |
|
if (storeInjection[type]) { |
|
return BI.Stores.getStore(type, config); |
|
} |
|
if (serviceInjection[type]) { |
|
return BI.Services.getService(type, config); |
|
} |
|
if (providerInjection[type]) { |
|
return BI.Providers.getProvider(type, config); |
|
} |
|
}; |
|
})();/** |
|
* guy |
|
* 检测某个Widget的EventChange事件然后去show某个card |
|
* @type {*|void|Object} |
|
* @class BI.ShowListener |
|
* @extends BI.OB |
|
*/ |
|
BI.ShowListener = BI.inherit(BI.OB, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ShowListener.superclass._defaultConfig.apply(this, arguments), { |
|
eventObj: BI.createWidget(), |
|
cardLayout: null, |
|
cardNameCreator: function (v) { |
|
return v; |
|
}, |
|
cardCreator: BI.emptyFn, |
|
afterCardCreated: BI.emptyFn, |
|
afterCardShow: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ShowListener.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (o.eventObj) { |
|
o.eventObj.on(BI.Controller.EVENT_CHANGE, function (type, v, ob) { |
|
if (type === BI.Events.CLICK) { |
|
v = v || o.eventObj.getValue(); |
|
v = BI.isArray(v) ? (v.length > 1 ? v.toString() : v[0]) : v; |
|
if (BI.isNull(v)) { |
|
throw new Error("value cannot be null"); |
|
} |
|
var cardName = o.cardNameCreator(v); |
|
if (!o.cardLayout.isCardExisted(cardName)) { |
|
var card = o.cardCreator(cardName); |
|
o.cardLayout.addCardByName(cardName, card); |
|
o.afterCardCreated(cardName); |
|
} |
|
o.cardLayout.showCardByName(cardName); |
|
BI.nextTick(function () { |
|
o.afterCardShow(cardName); |
|
self.fireEvent(BI.ShowListener.EVENT_CHANGE, cardName); |
|
}); |
|
} |
|
}); |
|
} |
|
} |
|
}); |
|
BI.ShowListener.EVENT_CHANGE = "EVENT_CHANGE";/** |
|
* style加载管理器 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class |
|
*/ |
|
BI.StyleLoaderManager = BI.inherit(BI.OB, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.StyleLoaderManager.superclass._defaultConfig.apply(this, arguments), {}); |
|
}, |
|
|
|
_init: function () { |
|
BI.StyleLoaderManager.superclass._init.apply(this, arguments); |
|
this.stylesManager = {}; |
|
}, |
|
|
|
loadStyle: function (name, styleString) { |
|
if(!_global.document) { |
|
return; |
|
} |
|
var d = document, styles = d.createElement("style"); |
|
d.getElementsByTagName("head")[0].appendChild(styles); |
|
styles.setAttribute("type", "text/css"); |
|
if (styles.styleSheet) { |
|
styles.styleSheet.cssText = styleString; |
|
} else { |
|
styles.appendChild(document.createTextNode(styleString)); |
|
} |
|
this.stylesManager[name] = styles; |
|
|
|
return this; |
|
}, |
|
|
|
get: function (name) { |
|
return this.stylesManager[name]; |
|
}, |
|
|
|
has: function (name) { |
|
return this.stylesManager[name] != null; |
|
}, |
|
|
|
removeStyle: function (name) { |
|
if (!this.has(name)) { |
|
return this; |
|
} |
|
this.stylesManager[name].parentNode.removeChild(this.stylesManager[name]); |
|
delete this.stylesManager[name]; |
|
return this; |
|
} |
|
});/** |
|
* @class BI.Logic |
|
* @extends BI.OB |
|
*/ |
|
BI.Logic = BI.inherit(BI.OB, { |
|
createLogic: function () { |
|
return this.options || {}; |
|
} |
|
}); |
|
|
|
BI.LogicFactory = { |
|
Type: { |
|
Vertical: "vertical", |
|
Horizontal: "horizontal", |
|
Table: "table", |
|
HorizontalFill: "horizontal_fill" |
|
}, |
|
createLogic: function (key, options) { |
|
var logic; |
|
switch (key) { |
|
case BI.LogicFactory.Type.Vertical: |
|
logic = BI.VerticalLayoutLogic; |
|
break; |
|
case BI.LogicFactory.Type.Horizontal: |
|
logic = BI.HorizontalLayoutLogic; |
|
break; |
|
case BI.LogicFactory.Type.Table: |
|
logic = BI.TableLayoutLogic; |
|
break; |
|
case BI.LogicFactory.Type.HorizontalFill: |
|
logic = BI.HorizontalFillLayoutLogic; |
|
break; |
|
default : |
|
logic = BI.Logic; |
|
break; |
|
} |
|
return new logic(options).createLogic(); |
|
}, |
|
|
|
createLogicTypeByDirection: function (direction) { |
|
switch (direction) { |
|
case BI.Direction.Top: |
|
case BI.Direction.Bottom: |
|
case BI.Direction.Custom: |
|
return BI.LogicFactory.Type.Vertical; |
|
break; |
|
case BI.Direction.Left: |
|
case BI.Direction.Right: |
|
return BI.LogicFactory.Type.Horizontal; |
|
} |
|
}, |
|
|
|
createLogicItemsByDirection: function (direction) { |
|
var layout; |
|
var items = Array.prototype.slice.call(arguments, 1); |
|
items = BI.map(items, function (i, item) { |
|
if (BI.isWidget(item)) { |
|
return { |
|
el: item, |
|
width: item.options.width, |
|
height: item.options.height |
|
}; |
|
} |
|
return item; |
|
}); |
|
switch (direction) { |
|
case BI.Direction.Bottom: |
|
layout = BI.LogicFactory.Type.Vertical; |
|
items.reverse(); |
|
break; |
|
case BI.Direction.Right: |
|
layout = BI.LogicFactory.Type.Horizontal; |
|
items.reverse(); |
|
break; |
|
case BI.Direction.Custom: |
|
items = items.slice(1); |
|
break; |
|
} |
|
return items; |
|
} |
|
};/** |
|
* guy |
|
* 上下布局逻辑 |
|
* 上下布局的时候要考虑到是动态布局还是静态布局 |
|
* |
|
* @class BI.VerticalLayoutLogic |
|
* @extends BI.Logic |
|
*/ |
|
BI.VerticalLayoutLogic = BI.inherit(BI.Logic, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.VerticalLayoutLogic.superclass._defaultConfig.apply(this, arguments), { |
|
dynamic: false, |
|
scrollable: null, |
|
scrolly: false, |
|
scrollx: false, |
|
items: [], |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
createLogic: function () { |
|
var layout, o = this.options; |
|
if (o.dynamic) { |
|
layout = "bi.vertical"; |
|
} else { |
|
layout = "bi.vtape"; |
|
} |
|
return { |
|
type: layout, |
|
scrollable: o.scrollable, |
|
scrolly: o.scrolly, |
|
scrollx: o.scrollx, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
_init: function () { |
|
BI.VerticalLayoutLogic.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
|
|
|
|
/** |
|
* guy |
|
* 左右布局逻辑 |
|
* 左右布局的时候要考虑到是动态布局还是静态布局 |
|
* |
|
* @class BI.HorizontalLayoutLogic |
|
* @extends BI.Logic |
|
*/ |
|
BI.HorizontalLayoutLogic = BI.inherit(BI.Logic, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.HorizontalLayoutLogic.superclass._defaultConfig.apply(this, arguments), { |
|
dynamic: false, |
|
scrollable: null, |
|
scrolly: false, |
|
scrollx: false, |
|
items: [], |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
createLogic: function () { |
|
var layout, o = this.options; |
|
if (o.dynamic) { |
|
layout = "bi.vertical_adapt"; |
|
} else { |
|
layout = "bi.htape"; |
|
} |
|
return { |
|
type: layout, |
|
scrollable: o.scrollable, |
|
scrolly: o.scrolly, |
|
scrollx: o.scrollx, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
_init: function () { |
|
BI.HorizontalLayoutLogic.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
|
|
/** |
|
* guy |
|
* 表格布局逻辑 |
|
* 表格布局的时候要考虑到是动态布局还是静态布局 |
|
* |
|
* @class BI.TableLayoutLogic |
|
* @extends BI.OB |
|
*/ |
|
BI.TableLayoutLogic = BI.inherit(BI.Logic, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TableLayoutLogic.superclass._defaultConfig.apply(this, arguments), { |
|
dynamic: false, |
|
scrollable: null, |
|
scrolly: false, |
|
scrollx: false, |
|
columns: 0, |
|
rows: 0, |
|
columnSize: [], |
|
rowSize: [], |
|
hgap: 0, |
|
vgap: 0, |
|
items: [] |
|
}); |
|
}, |
|
|
|
createLogic: function () { |
|
var layout, o = this.options; |
|
if (o.dynamic) { |
|
layout = "bi.table"; |
|
} else { |
|
layout = "bi.window"; |
|
} |
|
return { |
|
type: layout, |
|
scrollable: o.scrollable, |
|
scrolly: o.scrolly, |
|
scrollx: o.scrollx, |
|
columns: o.columns, |
|
rows: o.rows, |
|
columnSize: o.columnSize, |
|
rowSize: o.rowSize, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
_init: function () { |
|
BI.TableLayoutLogic.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
|
|
/** |
|
* guy |
|
* 左右充满布局逻辑 |
|
* |
|
* @class BI.HorizontalFillLayoutLogic |
|
* @extends BI.Logic |
|
*/ |
|
BI.HorizontalFillLayoutLogic = BI.inherit(BI.Logic, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.HorizontalFillLayoutLogic.superclass._defaultConfig.apply(this, arguments), { |
|
dynamic: false, |
|
scrollable: null, |
|
scrolly: false, |
|
scrollx: false, |
|
items: [], |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
createLogic: function () { |
|
var layout, o = this.options; |
|
var columnSize = []; |
|
BI.each(o.items, function (i, item) { |
|
columnSize.push(item.width || 0); |
|
}); |
|
if (o.dynamic) { |
|
layout = "bi.horizontal_adapt"; |
|
} else { |
|
layout = "bi.htape"; |
|
} |
|
return { |
|
type: layout, |
|
columnSize: columnSize, |
|
scrollable: o.scrollable, |
|
scrolly: o.scrolly, |
|
scrollx: o.scrollx, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
_init: function () { |
|
BI.HorizontalFillLayoutLogic.superclass._init.apply(this, arguments); |
|
} |
|
});if (!Number.prototype.toFixed || (0.00008).toFixed(3) !== "0.000" || |
|
(0.9).toFixed(0) === "0" || (1.255).toFixed(2) !== "1.25" || |
|
(1000000000000000128).toFixed(0) !== "1000000000000000128") { |
|
(function () { |
|
var base, size, data, i; |
|
base = 1e7; |
|
size = 6; |
|
data = [0, 0, 0, 0, 0, 0]; |
|
function multiply (n, c) { |
|
var i = -1; |
|
while (++i < size) { |
|
c += n * data[i]; |
|
data[i] = c % base; |
|
c = Math.floor(c / base); |
|
} |
|
} |
|
|
|
function divide (n) { |
|
var i = size, c = 0; |
|
while (--i >= 0) { |
|
c += data[i]; |
|
data[i] = Math.floor(c / n); |
|
c = (c % n) * base; |
|
} |
|
} |
|
|
|
function toString () { |
|
var i = size; |
|
var s = ""; |
|
while (--i >= 0) { |
|
if (s !== "" || i === 0 || data[i] !== 0) { |
|
var t = String(data[i]); |
|
if (s === "") { |
|
s = t; |
|
} else { |
|
s += "0000000".slice(0, 7 - t.length) + t; |
|
} |
|
} |
|
} |
|
return s; |
|
} |
|
|
|
function pow (x, n, acc) { |
|
return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) |
|
: pow(x * x, n / 2, acc))); |
|
} |
|
|
|
function log (x) { |
|
var n = 0; |
|
while (x >= 4096) { |
|
n += 12; |
|
x /= 4096; |
|
} |
|
while (x >= 2) { |
|
n += 1; |
|
x /= 2; |
|
} |
|
return n; |
|
} |
|
|
|
Number.prototype.toFixed = function (fractionDigits) { |
|
var f, x, s, m, e, z, j, k; |
|
f = Number(fractionDigits); |
|
f = f !== f ? 0 : Math.floor(f); |
|
|
|
if (f < 0 || f > 20) { |
|
throw new RangeError("Number.toFixed called with invalid number of decimals"); |
|
} |
|
|
|
x = Number(this); |
|
|
|
if (x !== x) { |
|
return "NaN"; |
|
} |
|
|
|
if (x <= -1e21 || x > 1e21) { |
|
return String(x); |
|
} |
|
|
|
s = ""; |
|
|
|
if (x < 0) { |
|
s = "-"; |
|
x = -x; |
|
} |
|
|
|
m = "0"; |
|
|
|
if (x > 1e-21) { |
|
// 1e-21<x<1e21 |
|
// -70<log2(x)<70 |
|
e = log(x * pow(2, 69, 1)) - 69; |
|
z = (e < 0 ? x * pow(2, -e, 1) : x / pow(2, e, 1)); |
|
z *= 0x10000000000000;// Math.pow(2,52); |
|
e = 52 - e; |
|
|
|
// -18<e<122 |
|
// x=z/2^e |
|
if (e > 0) { |
|
multiply(0, z); |
|
j = f; |
|
|
|
while (j >= 7) { |
|
multiply(1e7, 0); |
|
j -= 7; |
|
} |
|
|
|
multiply(pow(10, j, 1), 0); |
|
j = e - 1; |
|
|
|
while (j >= 23) { |
|
divide(1 << 23); |
|
j -= 23; |
|
} |
|
divide(1 << j); |
|
multiply(1, 1); |
|
divide(2); |
|
m = toString(); |
|
} else { |
|
multiply(0, z); |
|
multiply(1 << (-e), 0); |
|
m = toString() + "0.00000000000000000000".slice(2, 2 + f); |
|
} |
|
} |
|
|
|
if (f > 0) { |
|
k = m.length; |
|
|
|
if (k <= f) { |
|
m = s + "0.0000000000000000000".slice(0, f - k + 2) + m; |
|
} else { |
|
m = s + m.slice(0, k - f) + "." + m.slice(k - f); |
|
} |
|
} else { |
|
m = s + m; |
|
} |
|
|
|
return m; |
|
}; |
|
|
|
})(); |
|
}!(function () { |
|
var cancelAnimationFrame = |
|
_global.cancelAnimationFrame || |
|
_global.webkitCancelAnimationFrame || |
|
_global.mozCancelAnimationFrame || |
|
_global.oCancelAnimationFrame || |
|
_global.msCancelAnimationFrame || |
|
_global.clearTimeout; |
|
|
|
var requestAnimationFrame = _global.requestAnimationFrame || _global.webkitRequestAnimationFrame || _global.mozRequestAnimationFrame || _global.oRequestAnimationFrame || _global.msRequestAnimationFrame || _global.setTimeout; |
|
|
|
|
|
BI.MouseMoveTracker = function (onMove, onMoveEnd, domNode) { |
|
this._isDragging = false; |
|
this._animationFrameID = null; |
|
this._domNode = domNode; |
|
this._onMove = onMove; |
|
this._onMoveEnd = onMoveEnd; |
|
|
|
this._onMouseMove = BI.bind(this._onMouseMove, this); |
|
this._onMouseUp = BI.bind(this._onMouseUp, this); |
|
this._didMouseMove = BI.bind(this._didMouseMove, this); |
|
}; |
|
BI.MouseMoveTracker.prototype = { |
|
constructor: BI.MouseMoveTracker, |
|
captureMouseMoves: function (/* object*/ event) { |
|
if (!this._eventMoveToken && !this._eventUpToken) { |
|
this._eventMoveToken = BI.EventListener.listen( |
|
this._domNode, |
|
"mousemove", |
|
this._onMouseMove |
|
); |
|
this._eventUpToken = BI.EventListener.listen( |
|
this._domNode, |
|
"mouseup", |
|
this._onMouseUp |
|
); |
|
} |
|
|
|
if (!this._isDragging) { |
|
this._deltaX = 0; |
|
this._deltaY = 0; |
|
this._isDragging = true; |
|
this._x = event.clientX; |
|
this._y = event.clientY; |
|
} |
|
event.preventDefault ? event.preventDefault() : (event.returnValue = false); |
|
}, |
|
|
|
releaseMouseMoves: function () { |
|
if (this._eventMoveToken && this._eventUpToken) { |
|
this._eventMoveToken.remove(); |
|
this._eventMoveToken = null; |
|
this._eventUpToken.remove(); |
|
this._eventUpToken = null; |
|
} |
|
|
|
if (this._animationFrameID !== null) { |
|
cancelAnimationFrame(this._animationFrameID); |
|
this._animationFrameID = null; |
|
} |
|
|
|
if (this._isDragging) { |
|
this._isDragging = false; |
|
this._x = null; |
|
this._y = null; |
|
} |
|
}, |
|
|
|
isDragging: function () /* boolean*/ { |
|
return this._isDragging; |
|
}, |
|
|
|
_onMouseMove: function (/* object*/ event) { |
|
var x = event.clientX; |
|
var y = event.clientY; |
|
|
|
this._deltaX += (x - this._x); |
|
this._deltaY += (y - this._y); |
|
|
|
if (this._animationFrameID === null) { |
|
// The mouse may move faster then the animation frame does. |
|
// Use `requestAnimationFrame` to avoid over-updating. |
|
this._animationFrameID = |
|
requestAnimationFrame(this._didMouseMove); |
|
} |
|
|
|
this._x = x; |
|
this._y = y; |
|
event.preventDefault ? event.preventDefault() : (event.returnValue = false); |
|
}, |
|
|
|
_didMouseMove: function () { |
|
this._animationFrameID = null; |
|
this._onMove(this._deltaX, this._deltaY); |
|
this._deltaX = 0; |
|
this._deltaY = 0; |
|
}, |
|
|
|
_onMouseUp: function () { |
|
if (this._animationFrameID) { |
|
this._didMouseMove(); |
|
} |
|
this._onMoveEnd(); |
|
} |
|
}; |
|
})();!(function () { |
|
var PIXEL_STEP = 10; |
|
var LINE_HEIGHT = 40; |
|
var PAGE_HEIGHT = 800; |
|
var requestAnimationFrame = _global.requestAnimationFrame || _global.webkitRequestAnimationFrame || _global.mozRequestAnimationFrame || _global.oRequestAnimationFrame || _global.msRequestAnimationFrame || _global.setTimeout; |
|
|
|
function normalizeWheel (/* object*/event) /* object*/ { |
|
var sX = 0, |
|
sY = 0, |
|
// spinX, spinY |
|
pX = 0, |
|
pY = 0; // pixelX, pixelY |
|
|
|
// Legacy |
|
if ("detail" in event) { |
|
sY = event.detail; |
|
} |
|
if ("wheelDelta" in event) { |
|
sY = -event.wheelDelta / 120; |
|
} |
|
if ("wheelDeltaY" in event) { |
|
sY = -event.wheelDeltaY / 120; |
|
} |
|
if ("wheelDeltaX" in event) { |
|
sX = -event.wheelDeltaX / 120; |
|
} |
|
|
|
// side scrolling on FF with DOMMouseScroll |
|
if ("axis" in event && event.axis === event.HORIZONTAL_AXIS) { |
|
sX = sY; |
|
sY = 0; |
|
} |
|
|
|
pX = sX * PIXEL_STEP; |
|
pY = sY * PIXEL_STEP; |
|
|
|
if ("deltaY" in event) { |
|
pY = event.deltaY; |
|
} |
|
if ("deltaX" in event) { |
|
pX = event.deltaX; |
|
} |
|
|
|
if ((pX || pY) && event.deltaMode) { |
|
if (event.deltaMode === 1) { |
|
// delta in LINE units |
|
pX *= LINE_HEIGHT; |
|
pY *= LINE_HEIGHT; |
|
} else { |
|
// delta in PAGE units |
|
pX *= PAGE_HEIGHT; |
|
pY *= PAGE_HEIGHT; |
|
} |
|
} |
|
|
|
// Fall-back if spin cannot be determined |
|
if (pX && !sX) { |
|
sX = pX < 1 ? -1 : 1; |
|
} |
|
if (pY && !sY) { |
|
sY = pY < 1 ? -1 : 1; |
|
} |
|
|
|
return { |
|
spinX: sX, |
|
spinY: sY, |
|
pixelX: pX, |
|
pixelY: pY |
|
}; |
|
} |
|
|
|
BI.WheelHandler = function (onWheel, handleScrollX, handleScrollY, stopPropagation) { |
|
this._animationFrameID = null; |
|
this._deltaX = 0; |
|
this._deltaY = 0; |
|
this._didWheel = BI.bind(this._didWheel, this); |
|
if (typeof handleScrollX !== "function") { |
|
handleScrollX = handleScrollX ? |
|
function () { |
|
return true; |
|
} : |
|
function () { |
|
return false; |
|
}; |
|
} |
|
|
|
if (typeof handleScrollY !== "function") { |
|
handleScrollY = handleScrollY ? |
|
function () { |
|
return true; |
|
} : |
|
function () { |
|
return false; |
|
}; |
|
} |
|
|
|
if (typeof stopPropagation !== "function") { |
|
stopPropagation = stopPropagation ? |
|
function () { |
|
return true; |
|
} : |
|
function () { |
|
return false; |
|
}; |
|
} |
|
|
|
this._handleScrollX = handleScrollX; |
|
this._handleScrollY = handleScrollY; |
|
this._stopPropagation = stopPropagation; |
|
this._onWheelCallback = onWheel; |
|
this.onWheel = BI.bind(this.onWheel, this); |
|
}; |
|
BI.WheelHandler.prototype = { |
|
constructor: BI.WheelHandler, |
|
onWheel: function (/* object*/ event) { |
|
var normalizedEvent = normalizeWheel(event); |
|
var deltaX = this._deltaX + normalizedEvent.pixelX; |
|
var deltaY = this._deltaY + normalizedEvent.pixelY; |
|
var handleScrollX = this._handleScrollX(deltaX, deltaY); |
|
var handleScrollY = this._handleScrollY(deltaY, deltaX); |
|
if (!handleScrollX && !handleScrollY) { |
|
return; |
|
} |
|
|
|
this._deltaX += handleScrollX ? normalizedEvent.pixelX : 0; |
|
this._deltaY += handleScrollY ? normalizedEvent.pixelY : 0; |
|
event.preventDefault ? event.preventDefault() : (event.returnValue = false); |
|
|
|
var changed; |
|
if (this._deltaX !== 0 || this._deltaY !== 0) { |
|
if (this._stopPropagation()) { |
|
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true); |
|
} |
|
changed = true; |
|
} |
|
|
|
if (changed === true && this._animationFrameID === null) { |
|
this._animationFrameID = requestAnimationFrame(this._didWheel); |
|
} |
|
}, |
|
|
|
_didWheel: function () { |
|
this._animationFrameID = null; |
|
this._onWheelCallback(this._deltaX, this._deltaY); |
|
this._deltaX = 0; |
|
this._deltaY = 0; |
|
} |
|
}; |
|
})();/** |
|
* 常量 |
|
*/ |
|
|
|
_.extend(BI, { |
|
MAX: 0xfffffffffffffff, |
|
MIN: -0xfffffffffffffff, |
|
EVENT_RESPONSE_TIME: 200, |
|
zIndex_layer: 1e5, |
|
zIndex_popover: 1e6, |
|
zIndex_popup: 1e7, |
|
zIndex_masker: 1e8, |
|
zIndex_tip: 1e9, |
|
emptyStr: "", |
|
emptyFn: function () { |
|
}, |
|
empty: null, |
|
Key: { |
|
48: "0", |
|
49: "1", |
|
50: "2", |
|
51: "3", |
|
52: "4", |
|
53: "5", |
|
54: "6", |
|
55: "7", |
|
56: "8", |
|
57: "9", |
|
65: "a", |
|
66: "b", |
|
67: "c", |
|
68: "d", |
|
69: "e", |
|
70: "f", |
|
71: "g", |
|
72: "h", |
|
73: "i", |
|
74: "j", |
|
75: "k", |
|
76: "l", |
|
77: "m", |
|
78: "n", |
|
79: "o", |
|
80: "p", |
|
81: "q", |
|
82: "r", |
|
83: "s", |
|
84: "t", |
|
85: "u", |
|
86: "v", |
|
87: "w", |
|
88: "x", |
|
89: "y", |
|
90: "z", |
|
96: "0", |
|
97: "1", |
|
98: "2", |
|
99: "3", |
|
100: "4", |
|
101: "5", |
|
102: "6", |
|
103: "7", |
|
104: "8", |
|
105: "9", |
|
106: "*", |
|
107: "+", |
|
109: "-", |
|
110: ".", |
|
111: "/" |
|
}, |
|
KeyCode: { |
|
BACKSPACE: 8, |
|
COMMA: 188, |
|
DELETE: 46, |
|
DOWN: 40, |
|
END: 35, |
|
ENTER: 13, |
|
ESCAPE: 27, |
|
HOME: 36, |
|
LEFT: 37, |
|
NUMPAD_ADD: 107, |
|
NUMPAD_DECIMAL: 110, |
|
NUMPAD_DIVIDE: 111, |
|
NUMPAD_ENTER: 108, |
|
NUMPAD_MULTIPLY: 106, |
|
NUMPAD_SUBTRACT: 109, |
|
PAGE_DOWN: 34, |
|
PAGE_UP: 33, |
|
PERIOD: 190, |
|
RIGHT: 39, |
|
SPACE: 32, |
|
TAB: 9, |
|
UP: 38 |
|
}, |
|
Status: { |
|
SUCCESS: 1, |
|
WRONG: 2, |
|
START: 3, |
|
END: 4, |
|
WAITING: 5, |
|
READY: 6, |
|
RUNNING: 7, |
|
OUTOFBOUNDS: 8, |
|
NULL: -1 |
|
}, |
|
Direction: { |
|
Top: "top", |
|
Bottom: "bottom", |
|
Left: "left", |
|
Right: "right", |
|
Custom: "custom" |
|
}, |
|
Axis: { |
|
Vertical: "vertical", |
|
Horizontal: "horizontal" |
|
}, |
|
Selection: { |
|
Default: -2, |
|
None: -1, |
|
Single: 0, |
|
Multi: 1, |
|
All: 2 |
|
}, |
|
HorizontalAlign: { |
|
Left: "left", |
|
Right: "right", |
|
Center: "center", |
|
Stretch: "stretch" |
|
}, |
|
VerticalAlign: { |
|
Middle: "middle", |
|
Top: "top", |
|
Bottom: "bottom", |
|
Stretch: "stretch" |
|
}, |
|
StartOfWeek: 1 |
|
});BI.version = "2.0";/** |
|
* absolute实现的居中布局 |
|
* @class BI.AbsoluteCenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.AbsoluteCenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.AbsoluteCenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-absolute-center-layout", |
|
hgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
vgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.AbsoluteCenterLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.AbsoluteCenterLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "absolute", |
|
left: o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0), |
|
right: o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0), |
|
top: o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0), |
|
bottom: o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0), |
|
margin: "auto" |
|
}); |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("absolute_center_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.AbsoluteCenterLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.absolute_center_adapt", BI.AbsoluteCenterLayout);/** |
|
* absolute实现的居中布局 |
|
* @class BI.AbsoluteHorizontalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.AbsoluteHorizontalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.AbsoluteHorizontalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-absolute-horizontal-layout", |
|
hgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
vgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.AbsoluteHorizontalLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.AbsoluteHorizontalLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "absolute", |
|
left: o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0), |
|
right: o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0), |
|
margin: "auto" |
|
}); |
|
if (o.vgap + o.tgap + (item.vgap || 0) + (item.tgap || 0) !== 0) { |
|
w.element.css("top", o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0)); |
|
} |
|
if (o.vgap + o.bgap + (item.vgap || 0) + (item.bgap || 0) !== 0) { |
|
w.element.css("bottom", o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0)); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("absolute_horizontal_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.AbsoluteHorizontalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.absolute_horizontal_adapt", BI.AbsoluteHorizontalLayout);/** |
|
* absolute实现的居中布局 |
|
* @class BI.AbsoluteVerticalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.AbsoluteVerticalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.AbsoluteVerticalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-absolute-vertical-layout", |
|
hgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
vgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.AbsoluteVerticalLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.AbsoluteVerticalLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "absolute", |
|
left: item.lgap, |
|
right: item.rgap, |
|
top: o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0), |
|
bottom: o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0), |
|
margin: "auto" |
|
}); |
|
if (o.hgap + o.lgap + (item.hgap || 0) + (item.lgap || 0) !== 0) { |
|
w.element.css("left", o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0)); |
|
} |
|
if (o.hgap + o.rgap + (item.hgap || 0) + (item.rgap || 0) !== 0) { |
|
w.element.css("right", o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0)); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("absolute_vertical_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.AbsoluteVerticalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.absolute_vertical_adapt", BI.AbsoluteVerticalLayout);/** |
|
* 自适应水平和垂直方向都居中容器 |
|
* @class BI.CenterAdaptLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.CenterAdaptLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.CenterAdaptLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-center-adapt-layout", |
|
horizontalAlign: BI.HorizontalAlign.Center, |
|
columnSize: [], |
|
scrollx: false, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var o = this.options, self = this; |
|
BI.CenterAdaptLayout.superclass.render.apply(this, arguments); |
|
return { |
|
type: "bi.horizontal", |
|
verticalAlign: BI.VerticalAlign.Middle, |
|
horizontalAlign: o.horizontalAlign, |
|
columnSize: o.columnSize, |
|
scrollx: o.scrollx, |
|
items: o.items, |
|
ref: function (_ref) { |
|
self.layout = _ref; |
|
}, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("center_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
this.layout.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.center_adapt", BI.CenterAdaptLayout);/** |
|
* 水平方向居中容器 |
|
* @class BI.HorizontalAdaptLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.HorizontalAdaptLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.HorizontalAdaptLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-horizontal-adapt-layout", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
horizontalAlign: BI.HorizontalAlign.Center, |
|
columnSize: [], |
|
scrollx: false, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
BI.HorizontalAdaptLayout.superclass.render.apply(this, arguments); |
|
return { |
|
type: "bi.horizontal", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
horizontalAlign: o.horizontalAlign, |
|
columnSize: o.columnSize, |
|
items: o.items, |
|
scrollx: o.scrollx, |
|
ref: function (_ref) { |
|
self.layout = _ref; |
|
}, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("horizontal_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
this.layout.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.horizontal_adapt", BI.HorizontalAdaptLayout);/** |
|
* 左右分离,垂直方向居中容器 |
|
* items:{ |
|
left: [{el:{type:"bi.button"}}], |
|
right:[{el:{type:"bi.button"}}] |
|
} |
|
* @class BI.LeftRightVerticalAdaptLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.LeftRightVerticalAdaptLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.LeftRightVerticalAdaptLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-left-right-vertical-adapt-layout", |
|
items: {}, |
|
llgap: 0, |
|
lrgap: 0, |
|
lhgap: 0, |
|
rlgap: 0, |
|
rrgap: 0, |
|
rhgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var o = this.options, self = this; |
|
BI.LeftRightVerticalAdaptLayout.superclass.render.apply(this, arguments); |
|
var layoutArray = []; |
|
if ("left" in o.items) { |
|
layoutArray.push({ |
|
type: "bi.left", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical_adapt", |
|
height: "100%", |
|
items: o.items.left, |
|
hgap: o.lhgap, |
|
lgap: o.llgap, |
|
rgap: o.lrgap |
|
} |
|
}] |
|
}); |
|
} |
|
if ("right" in o.items) { |
|
layoutArray.push({ |
|
type: "bi.right", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical_adapt", |
|
height: "100%", |
|
items: o.items.right, |
|
textAlign: "right", |
|
hgap: o.rhgap, |
|
lgap: o.rlgap, |
|
rgap: o.rrgap |
|
} |
|
}] |
|
}); |
|
} |
|
return layoutArray; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("left_right_vertical_adapt布局不需要resize"); |
|
}, |
|
|
|
addItem: function () { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.LeftRightVerticalAdaptLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.left_right_vertical_adapt", BI.LeftRightVerticalAdaptLayout); |
|
|
|
|
|
BI.LeftVerticalAdaptLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.LeftRightVerticalAdaptLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-left-vertical-adapt-layout", |
|
items: [], |
|
lgap: 0, |
|
rgap: 0, |
|
hgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var o = this.options, self = this; |
|
BI.LeftVerticalAdaptLayout.superclass.render.apply(this, arguments); |
|
return { |
|
type: "bi.left", |
|
ref: function (_ref) { |
|
self.layout = _ref; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.vertical_adapt", |
|
height: "100%", |
|
items: o.items, |
|
lgap: o.lgap, |
|
hgap: o.hgap, |
|
rgap: o.rgap |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("left_vertical_adapt布局不需要resize"); |
|
}, |
|
|
|
addItem: function () { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
populate: function (items) { |
|
this.layout.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.left_vertical_adapt", BI.LeftVerticalAdaptLayout); |
|
|
|
BI.RightVerticalAdaptLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.RightVerticalAdaptLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-right-vertical-adapt-layout", |
|
items: [], |
|
lgap: 0, |
|
rgap: 0, |
|
hgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var o = this.options, self = this; |
|
BI.RightVerticalAdaptLayout.superclass.render.apply(this, arguments); |
|
return { |
|
type: "bi.right", |
|
ref: function (_ref) { |
|
self.layout = _ref; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.vertical_adapt", |
|
height: "100%", |
|
textAlign: "right", |
|
items: o.items, |
|
lgap: o.lgap, |
|
hgap: o.hgap, |
|
rgap: o.rgap |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
|
|
}, |
|
|
|
addItem: function () { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
populate: function (items) { |
|
this.layout.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.right_vertical_adapt", BI.RightVerticalAdaptLayout);/** |
|
* 使用display:table和display:table-cell实现的horizontal布局 |
|
* @class BI.TableAdaptLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.TableAdaptLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.TableAdaptLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-table-center-adapt-layout", |
|
columnSize: [], |
|
verticalAlign: BI.VerticalAlign.Top, |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
scrollx: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var o = this.options; |
|
BI.TableAdaptLayout.superclass.render.apply(this, arguments); |
|
this.$table = BI.Widget._renderEngine.createElement("<div>").css({ |
|
position: "relative", |
|
display: "table", |
|
height: o.verticalAlign === BI.VerticalAlign.Middle ? "100%" : "auto", |
|
width: o.horizontalAlign === BI.HorizontalAlign.Center ? "100%" : "auto", |
|
"white-space": "nowrap" |
|
}); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
|
|
var o = this.options; |
|
var td; |
|
var width = o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i]; |
|
if (!this.hasWidget(this._getChildName(i))) { |
|
var w = BI.createWidget(item); |
|
w.element.css({position: "relative", top: "0", left: "0", margin: "0px auto"}); |
|
td = BI.createWidget({ |
|
type: "bi.default", |
|
width: width, |
|
items: [w] |
|
}); |
|
this.addWidget(this._getChildName(i), td); |
|
} else { |
|
td = this.getWidgetByName(this._getChildName(i)); |
|
td.element.width(width); |
|
} |
|
// 对于表现为td的元素设置最大宽度,有几点需要注意 |
|
// 1、由于直接对td设置最大宽度是在规范中未定义的, 所以要使用类似td:firstChild来迂回实现 |
|
// 2、不能给多个td设置最大宽度,这样只会平分宽度 |
|
// 3、多百分比宽度就算了 |
|
td.element.css({"max-width": o.columnSize[i] <= 1 ? width : width + "px"}); |
|
if (i === 0) { |
|
td.element.addClass("first-element"); |
|
} |
|
td.element.css({ |
|
position: "relative", |
|
display: "table-cell", |
|
"vertical-align": o.verticalAlign, |
|
margin: "0", |
|
padding: "0", |
|
height: "100%" |
|
}); |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return td; |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.$table.append(frag); |
|
this.element.append(this.$table); |
|
}, |
|
|
|
resize: function () { |
|
// console.log("center_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.TableAdaptLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.table_adapt", BI.TableAdaptLayout);/** |
|
* 垂直方向居中容器 |
|
* @class BI.VerticalAdaptLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.VerticalAdaptLayout = BI.inherit(BI.Layout, { |
|
props: { |
|
baseCls: "bi-vertical-adapt-layout", |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
columnSize: [], |
|
scrollx: false, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
BI.VerticalAdaptLayout.superclass.render.apply(this, arguments); |
|
return { |
|
type: "bi.horizontal", |
|
verticalAlign: BI.VerticalAlign.Middle, |
|
horizontalAlign: o.horizontalAlign, |
|
columnSize: o.columnSize, |
|
items: o.items, |
|
scrollx: o.scrollx, |
|
ref: function (_ref) { |
|
self.layout = _ref; |
|
}, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("vertical_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
this.layout.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.vertical_adapt", BI.VerticalAdaptLayout);/** |
|
* 水平方向居中自适应容器 |
|
* @class BI.HorizontalAutoLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.HorizontalAutoLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.HorizontalAutoLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-horizon-auto-layout", |
|
hgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
vgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.HorizontalAutoLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.HorizontalAutoLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
margin: "0px auto" |
|
}); |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": (i === 0 ? o.vgap : 0) + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("horizontal_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.HorizontalAutoLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.horizontal_auto", BI.HorizontalAutoLayout);/** |
|
* 浮动的水平居中布局 |
|
*/ |
|
BI.FloatHorizontalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FloatHorizontalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-float-horizontal-adapt-layout", |
|
items: [], |
|
hgap: 0, |
|
vgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
lgap: 0, |
|
rgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FloatHorizontalLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
// console.log("float_horizontal_adapt布局不需要resize"); |
|
}, |
|
|
|
mounted: function () { |
|
var self = this; |
|
var width = this.left.element.width(), |
|
height = this.left.element.height(); |
|
this.left.element.width(width).height(height).css("float", "none"); |
|
BI.remove(this._children, function (i, wi) { |
|
if (wi === self.container) { |
|
delete self._children[i]; |
|
} |
|
}); |
|
BI.createWidget({ |
|
type: "bi.horizontal_auto", |
|
element: this, |
|
items: [this.left] |
|
}); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var self = this, o = this.options; |
|
this.left = BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [item], |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap |
|
}); |
|
|
|
this.container = BI.createWidget({ |
|
type: "bi.left", |
|
element: this, |
|
items: [this.left] |
|
}); |
|
|
|
return this.left; |
|
}, |
|
|
|
populate: function (items) { |
|
BI.HorizontalAutoLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.horizontal_float", BI.FloatHorizontalLayout);/** |
|
* 内联布局 |
|
* @class BI.InlineCenterAdaptLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Number} [hgap=0] 水平间隙 |
|
* @cfg {Number} [vgap=0] 垂直间隙 |
|
*/ |
|
BI.InlineCenterAdaptLayout = BI.inherit(BI.Layout, { |
|
|
|
props: function () { |
|
return BI.extend(BI.InlineLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-inline-center-adapt-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.InlineCenterAdaptLayout.superclass.render.apply(this, arguments); |
|
this.element.css({ |
|
whiteSpace: "nowrap", |
|
textAlign: "center" |
|
}); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item, length) { |
|
var o = this.options; |
|
var w = BI.InlineVerticalAdaptLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"vertical-align": "middle" |
|
}); |
|
w.element.addClass("inline-center-adapt-item"); |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
addItem: function (item) { |
|
throw new Error("不能添加元素"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var self = this; |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
self._addElement(i, item, items.length); |
|
} |
|
}); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.InlineCenterAdaptLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.inline_center_adapt", BI.InlineCenterAdaptLayout);/** |
|
* 内联布局 |
|
* @class BI.InlineVerticalAdaptLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Number} [hgap=0] 水平间隙 |
|
* @cfg {Number} [vgap=0] 垂直间隙 |
|
*/ |
|
BI.InlineVerticalAdaptLayout = BI.inherit(BI.Layout, { |
|
|
|
props: function () { |
|
return BI.extend(BI.InlineLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-inline-vertical-adapt-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
textAlign: "left" |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.InlineVerticalAdaptLayout.superclass.render.apply(this, arguments); |
|
var o = this.options; |
|
this.element.css({ |
|
whiteSpace: "nowrap", |
|
textAlign: o.textAlign |
|
}); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.InlineVerticalAdaptLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"vertical-align": "middle" |
|
}); |
|
w.element.addClass("inline-vertical-adapt-item"); |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.InlineVerticalAdaptLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.inline_vertical_adapt", BI.InlineVerticalAdaptLayout);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexCenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexCenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexCenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-center-adapt-layout", |
|
hgap: 0, |
|
vgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FlexCenterLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FlexCenterLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"flex-shrink": "0", |
|
"margin-left": (i === 0 ? o.hgap : 0) + "px", |
|
"margin-right": o.hgap + "px", |
|
"margin-top": o.vgap + "px", |
|
"margin-bottom": o.vgap + "px" |
|
}); |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_center_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FlexCenterLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_center_adapt", BI.FlexCenterLayout);/** |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexHorizontalCenter |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexHorizontalCenter = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexHorizontalCenter.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-horizontal-center-adapt-layout", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
rowSize: [], |
|
scrolly: false, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.flex_vertical", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
horizontalAlign: BI.HorizontalAlign.Center, |
|
verticalAlign: o.verticalAlign, |
|
rowSize: o.rowSize, |
|
scrollx: o.scrollx, |
|
scrolly: o.scrolly, |
|
scrollable: o.scrollable, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_vertical_center_adapt布局不需要resize"); |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate(items); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_horizontal_adapt", BI.FlexHorizontalCenter); |
|
BI.shortcut("bi.flex_horizontal_center_adapt", BI.FlexHorizontalCenter);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexHorizontalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexHorizontalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexHorizontalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-horizontal-layout", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
horizontalAlign: BI.HorizontalAlign.Left,// 如果只有一个子元素且想让该子元素横向撑满,设置成Stretch |
|
columnSize: [], |
|
scrollx: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FlexHorizontalLayout.superclass.render.apply(this, arguments); |
|
var o = this.options; |
|
this.element.addClass("v-" + o.verticalAlign).addClass("h-" + o.horizontalAlign); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FlexHorizontalLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"flex-shrink": "0" |
|
}); |
|
if (o.columnSize[i] > 0) { |
|
w.element.width(o.columnSize[i]); |
|
} |
|
if (o.columnSize[i] === "fill") { |
|
w.element.css("flex", "1"); |
|
} |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_horizontal布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FlexHorizontalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_horizontal", BI.FlexHorizontalLayout);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexVerticalCenter |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexVerticalCenter = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexVerticalCenter.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-vertical-center-adapt-layout", |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
columnSize: [], |
|
scrollx: false, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.flex_horizontal", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
verticalAlign: BI.VerticalAlign.Middle, |
|
horizontalAlign: o.horizontalAlign, |
|
columnSize: o.columnSize, |
|
scrollx: o.scrollx, |
|
scrolly: o.scrolly, |
|
scrollable: o.scrollable, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
hgap: o.hgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_vertical_center_adapt布局不需要resize"); |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate(items); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_vertical_adapt", BI.FlexVerticalCenter); |
|
BI.shortcut("bi.flex_vertical_center_adapt", BI.FlexVerticalCenter);/** |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexVerticalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexVerticalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexVerticalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-vertical-layout", |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
verticalAlign: BI.VerticalAlign.Top, |
|
rowSize: [], |
|
scrolly: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FlexVerticalLayout.superclass.render.apply(this, arguments); |
|
var o = this.options; |
|
this.element.addClass("h-" + o.horizontalAlign).addClass("v-" + o.verticalAlign); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var w = BI.FlexVerticalLayout.superclass._addElement.apply(this, arguments); |
|
var o = this.options; |
|
w.element.css({ |
|
position: "relative", |
|
"flex-shrink": "0" |
|
}); |
|
if (o.rowSize[i] > 0) { |
|
w.element.height(o.rowSize[i]); |
|
} |
|
if (o.rowSize[i] === "fill") { |
|
w.element.css("flex", "1"); |
|
} |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": (i === 0 ? o.vgap : 0) + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_vertical布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FlexVerticalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_vertical", BI.FlexVerticalLayout);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexWrapperCenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexWrapperCenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexWrapperCenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-scrollable-center-adapt-layout clearfix", |
|
scrollable: true |
|
}); |
|
}, |
|
render: function () { |
|
BI.FlexWrapperCenterLayout.superclass.render.apply(this, arguments); |
|
this.$wrapper = BI.Widget._renderEngine.createElement("<div>").addClass("flex-scrollable-center-adapt-layout-wrapper"); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FlexWrapperCenterLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"margin-left": (i === 0 ? o.hgap : 0) + "px", |
|
"margin-right": o.hgap + "px", |
|
"margin-top": o.vgap + "px", |
|
"margin-bottom": o.vgap + "px" |
|
}); |
|
return w; |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.$wrapper.append(frag); |
|
this.element.append(this.$wrapper); |
|
}, |
|
|
|
_getWrapper: function () { |
|
return this.$wrapper; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_center_adapt布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FlexWrapperCenterLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_scrollable_center_adapt", BI.FlexWrapperCenterLayout);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexVerticalCenter |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexWrapperHorizontalCenter = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexWrapperHorizontalCenter.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-scrollable-vertical-center-adapt-layout clearfix", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
rowSize: [], |
|
scrollable: true, |
|
scrolly: false, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.flex_scrollable_vertical", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
horizontalAlign: BI.HorizontalAlign.Center, |
|
verticalAlign: o.verticalAlign, |
|
rowSize: o.rowSize, |
|
scrollx: o.scrollx, |
|
scrolly: o.scrolly, |
|
scrollable: o.scrollable, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate(items); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_scrollable_horizontal_adapt", BI.FlexWrapperHorizontalCenter); |
|
BI.shortcut("bi.flex_scrollable_horizontal_center_adapt", BI.FlexWrapperHorizontalCenter);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexHorizontalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexWrapperHorizontalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexWrapperHorizontalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-scrollable-horizontal-layout clearfix", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
columnSize: [], |
|
scrollable: null, |
|
scrollx: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FlexWrapperHorizontalLayout.superclass.render.apply(this, arguments); |
|
var o = this.options; |
|
this.$wrapper = BI.Widget._renderEngine.createElement("<div>").addClass("flex-scrollable-horizontal-layout-wrapper v-" + o.verticalAlign).addClass("h-" + o.horizontalAlign); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FlexWrapperHorizontalLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"flex-shrink": "0" |
|
}); |
|
if (o.columnSize[i] > 0) { |
|
w.element.width(o.columnSize[i]); |
|
} |
|
if (o.columnSize[i] === "fill") { |
|
w.element.css("flex", "1"); |
|
} |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.$wrapper.append(frag); |
|
this.element.append(this.$wrapper); |
|
}, |
|
|
|
_getWrapper: function () { |
|
return this.$wrapper; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_wrapper_horizontal布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FlexWrapperHorizontalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_scrollable_horizontal", BI.FlexWrapperHorizontalLayout);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexVerticalCenter |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexWrapperVerticalCenter = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexWrapperVerticalCenter.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-scrollable-vertical-center-adapt-layout clearfix", |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
columnSize: [], |
|
scrollx: false, |
|
scrollable: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.flex_scrollable_horizontal", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
verticalAlign: BI.VerticalAlign.Middle, |
|
horizontalAlign: o.horizontalAlign, |
|
columnSize: o.columnSize, |
|
scrollx: o.scrollx, |
|
scrolly: o.scrolly, |
|
scrollable: o.scrollable, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
items: o.items |
|
}; |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate(items); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_scrollable_vertical_adapt", BI.FlexWrapperVerticalCenter); |
|
BI.shortcut("bi.flex_scrollable_vertical_center_adapt", BI.FlexWrapperVerticalCenter);/** |
|
*自适应水平和垂直方向都居中容器 |
|
* Created by GUY on 2016/12/2. |
|
* |
|
* @class BI.FlexWrapperVerticalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FlexWrapperVerticalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FlexWrapperVerticalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-flex-scrollable-vertical-layout clearfix", |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
verticalAlign: BI.VerticalAlign.Top, |
|
rowSize: [], |
|
scrollable: null, |
|
scrolly: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FlexWrapperVerticalLayout.superclass.render.apply(this, arguments); |
|
var o = this.options; |
|
this.$wrapper = BI.Widget._renderEngine.createElement("<div>").addClass("flex-scrollable-vertical-layout-wrapper h-" + o.horizontalAlign).addClass("v-" + o.verticalAlign); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FlexWrapperVerticalLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative", |
|
"flex-shrink": "0" |
|
}); |
|
if (o.rowSize[i] > 0) { |
|
w.element.height(o.rowSize[i]); |
|
} |
|
if (o.rowSize[i] === "fill") { |
|
w.element.css("flex", "1"); |
|
} |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": (i === 0 ? o.vgap : 0) + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.$wrapper.append(frag); |
|
this.element.append(this.$wrapper); |
|
}, |
|
|
|
_getWrapper: function () { |
|
return this.$wrapper; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("flex_wrapper_vertical布局不需要resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FlexWrapperVerticalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.flex_scrollable_vertical", BI.FlexWrapperVerticalLayout);/** |
|
* 固定子组件上下左右的布局容器 |
|
* @class BI.AbsoluteLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.AbsoluteLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.AbsoluteLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-absolute-layout", |
|
hgap: null, |
|
vgap: null, |
|
lgap: null, |
|
rgap: null, |
|
tgap: null, |
|
bgap: null |
|
}); |
|
}, |
|
render: function () { |
|
BI.AbsoluteLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.AbsoluteLayout.superclass._addElement.apply(this, arguments); |
|
var left = 0, right = 0, top = 0, bottom = 0; |
|
if (BI.isNotNull(item.left)) { |
|
w.element.css({left: item.left}); |
|
left += item.left; |
|
} |
|
if (BI.isNotNull(item.right)) { |
|
w.element.css({right: item.right}); |
|
right += item.right; |
|
} |
|
if (BI.isNotNull(item.top)) { |
|
w.element.css({top: item.top}); |
|
top += item.top; |
|
} |
|
if (BI.isNotNull(item.bottom)) { |
|
w.element.css({bottom: item.bottom}); |
|
bottom += item.bottom; |
|
} |
|
|
|
if (BI.isNotNull(o.hgap)) { |
|
left += o.hgap; |
|
w.element.css({left: left}); |
|
right += o.hgap; |
|
w.element.css({right: right}); |
|
} |
|
if (BI.isNotNull(o.vgap)) { |
|
top += o.vgap; |
|
w.element.css({top: top}); |
|
bottom += o.vgap; |
|
w.element.css({bottom: bottom}); |
|
} |
|
|
|
if (BI.isNotNull(o.lgap)) { |
|
left += o.lgap; |
|
w.element.css({left: left}); |
|
} |
|
if (BI.isNotNull(o.rgap)) { |
|
right += o.rgap; |
|
w.element.css({right: right}); |
|
} |
|
if (BI.isNotNull(o.tgap)) { |
|
top += o.tgap; |
|
w.element.css({top: top}); |
|
} |
|
if (BI.isNotNull(o.bgap)) { |
|
bottom += o.bgap; |
|
w.element.css({bottom: bottom}); |
|
} |
|
|
|
|
|
if (BI.isNotNull(item.width)) { |
|
w.element.css({width: item.width}); |
|
} |
|
if (BI.isNotNull(item.height)) { |
|
w.element.css({height: item.height}); |
|
} |
|
w.element.css({position: "absolute"}); |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
stroke: function (items) { |
|
this.options.items = items || []; |
|
var self = this; |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
if (!BI.isWidget(item) && !item.el) { |
|
throw new Error("el must be exist"); |
|
} |
|
self._addElement(i, item); |
|
} |
|
}); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.AbsoluteLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.absolute", BI.AbsoluteLayout);BI.AdaptiveLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.AdaptiveLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-adaptive-layout", |
|
hgap: null, |
|
vgap: null, |
|
lgap: null, |
|
rgap: null, |
|
tgap: null, |
|
bgap: null |
|
}); |
|
}, |
|
render: function () { |
|
BI.AdaptiveLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.AdaptiveLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({position: "relative"}); |
|
var left = 0, right = 0, top = 0, bottom = 0; |
|
if (BI.isNotNull(item.left)) { |
|
w.element.css({ |
|
left: item.left |
|
}); |
|
} |
|
if (BI.isNotNull(item.right)) { |
|
w.element.css({ |
|
right: item.right |
|
}); |
|
} |
|
if (BI.isNotNull(item.top)) { |
|
w.element.css({ |
|
top: item.top |
|
}); |
|
} |
|
if (BI.isNotNull(item.bottom)) { |
|
w.element.css({ |
|
bottom: item.bottom |
|
}); |
|
} |
|
|
|
if (BI.isNotNull(o.hgap)) { |
|
left += o.hgap; |
|
w.element.css({"margin-left": left}); |
|
right += o.hgap; |
|
w.element.css({"margin-right": right}); |
|
} |
|
if (BI.isNotNull(o.vgap)) { |
|
top += o.vgap; |
|
w.element.css({"margin-top": top}); |
|
bottom += o.vgap; |
|
w.element.css({"margin-bottom": bottom}); |
|
} |
|
|
|
if (BI.isNotNull(o.lgap)) { |
|
left += o.lgap; |
|
w.element.css({"margin-left": left}); |
|
} |
|
if (BI.isNotNull(o.rgap)) { |
|
right += o.rgap; |
|
w.element.css({"margin-right": right}); |
|
} |
|
if (BI.isNotNull(o.tgap)) { |
|
top += o.tgap; |
|
w.element.css({"margin-top": top}); |
|
} |
|
if (BI.isNotNull(o.bgap)) { |
|
bottom += o.bgap; |
|
w.element.css({"margin-bottom": bottom}); |
|
} |
|
|
|
if (BI.isNotNull(item.width)) { |
|
w.element.css({width: item.width}); |
|
} |
|
if (BI.isNotNull(item.height)) { |
|
w.element.css({height: item.height}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.AbsoluteLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.adaptive", BI.AdaptiveLayout);/** |
|
* 上下的高度固定/左右的宽度固定,中间的高度/宽度自适应 |
|
* |
|
* @class BI.BorderLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.BorderLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.BorderLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-border-layout", |
|
items: {} |
|
}); |
|
}, |
|
render: function () { |
|
BI.BorderLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
stroke: function (regions) { |
|
var item; |
|
var top = 0; |
|
var bottom = 0; |
|
var left = 0; |
|
var right = 0; |
|
if ("north" in regions) { |
|
item = regions["north"]; |
|
if (item != null) { |
|
if (item.el) { |
|
if (!this.hasWidget(this.getName() + "north")) { |
|
var w = BI.createWidget(item); |
|
this.addWidget(this.getName() + "north", w); |
|
} |
|
this.getWidgetByName(this.getName() + "north").element.height(item.height) |
|
.css({ |
|
position: "absolute", |
|
top: (item.top || 0), |
|
left: (item.left || 0), |
|
right: (item.right || 0), |
|
bottom: "initial" |
|
}); |
|
} |
|
top = (item.height || 0) + (item.top || 0) + (item.bottom || 0); |
|
} |
|
} |
|
if ("south" in regions) { |
|
item = regions["south"]; |
|
if (item != null) { |
|
if (item.el) { |
|
if (!this.hasWidget(this.getName() + "south")) { |
|
var w = BI.createWidget(item); |
|
this.addWidget(this.getName() + "south", w); |
|
} |
|
this.getWidgetByName(this.getName() + "south").element.height(item.height) |
|
.css({ |
|
position: "absolute", |
|
bottom: (item.bottom || 0), |
|
left: (item.left || 0), |
|
right: (item.right || 0), |
|
top: "initial" |
|
}); |
|
} |
|
bottom = (item.height || 0) + (item.top || 0) + (item.bottom || 0); |
|
} |
|
} |
|
if ("west" in regions) { |
|
item = regions["west"]; |
|
if (item != null) { |
|
if (item.el) { |
|
if (!this.hasWidget(this.getName() + "west")) { |
|
var w = BI.createWidget(item); |
|
this.addWidget(this.getName() + "west", w); |
|
} |
|
this.getWidgetByName(this.getName() + "west").element.width(item.width) |
|
.css({ |
|
position: "absolute", |
|
left: (item.left || 0), |
|
top: top, |
|
bottom: bottom, |
|
right: "initial" |
|
}); |
|
} |
|
left = (item.width || 0) + (item.left || 0) + (item.right || 0); |
|
} |
|
} |
|
if ("east" in regions) { |
|
item = regions["east"]; |
|
if (item != null) { |
|
if (item.el) { |
|
if (!this.hasWidget(this.getName() + "east")) { |
|
var w = BI.createWidget(item); |
|
this.addWidget(this.getName() + "east", w); |
|
} |
|
this.getWidgetByName(this.getName() + "east").element.width(item.width) |
|
.css({ |
|
position: "absolute", |
|
right: (item.right || 0), |
|
top: top, |
|
bottom: bottom, |
|
left: "initial" |
|
}); |
|
} |
|
right = (item.width || 0) + (item.left || 0) + (item.right || 0); |
|
} |
|
} |
|
if ("center" in regions) { |
|
item = regions["center"]; |
|
if (item != null) { |
|
if (!this.hasWidget(this.getName() + "center")) { |
|
var w = BI.createWidget(item); |
|
this.addWidget(this.getName() + "center", w); |
|
} |
|
this.getWidgetByName(this.getName() + "center").element |
|
.css({position: "absolute", top: top, bottom: bottom, left: left, right: right}); |
|
} |
|
} |
|
}, |
|
|
|
update: function (opt) { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.BorderLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.border", BI.BorderLayout);/** |
|
* 卡片布局,可以做到当前只显示一个组件,其他的都隐藏 |
|
* @class BI.CardLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {String} options.defaultShowName 默认展示的子组件名 |
|
*/ |
|
BI.CardLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.CardLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-card-layout", |
|
items: [] |
|
}); |
|
}, |
|
render: function () { |
|
BI.CardLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
// console.log("default布局不需要resize"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var self = this, o = this.options; |
|
this.showIndex = void 0; |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
if (!self.hasWidget(item.cardName)) { |
|
var w = BI.createWidget(item); |
|
w.on(BI.Events.DESTROY, function () { |
|
var index = BI.findIndex(o.items, function (i, tItem) { |
|
return tItem.cardName == item.cardName; |
|
}); |
|
if (index > -1) { |
|
o.items.splice(index, 1); |
|
} |
|
}); |
|
self.addWidget(item.cardName, w); |
|
} else { |
|
var w = self.getWidgetByName(item.cardName); |
|
} |
|
w.element.css({position: "absolute", top: "0", right: "0", bottom: "0", left: "0"}); |
|
w.setVisible(false); |
|
} |
|
}); |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
empty: function () { |
|
BI.CardLayout.superclass.empty.apply(this, arguments); |
|
this.options.items = []; |
|
}, |
|
|
|
populate: function (items) { |
|
BI.CardLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
this.options.defaultShowName && this.showCardByName(this.options.defaultShowName); |
|
}, |
|
|
|
isCardExisted: function (cardName) { |
|
return BI.some(this.options.items, function (i, item) { |
|
return item.cardName == cardName && item.el; |
|
}); |
|
}, |
|
|
|
getCardByName: function (cardName) { |
|
if (!this.isCardExisted(cardName)) { |
|
throw new Error("cardName is not exist"); |
|
} |
|
return this._children[cardName]; |
|
}, |
|
|
|
_deleteCardByName: function (cardName) { |
|
delete this._children[cardName]; |
|
var index = BI.findIndex(this.options.items, function (i, item) { |
|
return item.cardName == cardName; |
|
}); |
|
if (index > -1) { |
|
this.options.items.splice(index, 1); |
|
} |
|
}, |
|
|
|
deleteCardByName: function (cardName) { |
|
if (!this.isCardExisted(cardName)) { |
|
throw new Error("cardName is not exist"); |
|
} |
|
|
|
var child = this._children[cardName]; |
|
this._deleteCardByName(cardName); |
|
child && child._destroy(); |
|
}, |
|
|
|
addCardByName: function (cardName, cardItem) { |
|
if (this.isCardExisted(cardName)) { |
|
throw new Error("cardName is already exist"); |
|
} |
|
var widget = BI.createWidget(cardItem, this); |
|
widget.element.css({ |
|
position: "relative", |
|
top: "0", |
|
left: "0", |
|
width: "100%", |
|
height: "100%" |
|
}).appendTo(this.element); |
|
widget.invisible(); |
|
this.addWidget(cardName, widget); |
|
this.options.items.push({el: cardItem, cardName: cardName}); |
|
return widget; |
|
}, |
|
|
|
showCardByName: function (name, action, callback) { |
|
var self = this; |
|
// name不存在的时候全部隐藏 |
|
var exist = this.isCardExisted(name); |
|
if (this.showIndex != null) { |
|
this.lastShowIndex = this.showIndex; |
|
} |
|
this.showIndex = name; |
|
var flag = false; |
|
BI.each(this.options.items, function (i, item) { |
|
var el = self._children[item.cardName]; |
|
if (el) { |
|
if (name != item.cardName) { |
|
// 动画效果只有在全部都隐藏的时候才有意义,且只要执行一次动画操作就够了 |
|
!flag && !exist && (BI.Action && action instanceof BI.Action) ? (action.actionBack(el), flag = true) : el.invisible(); |
|
} else { |
|
(BI.Action && action instanceof BI.Action) ? action.actionPerformed(void 0, el, callback) : (el.visible(), callback && callback()); |
|
} |
|
} |
|
}); |
|
}, |
|
|
|
showLastCard: function () { |
|
var self = this; |
|
this.showIndex = this.lastShowIndex; |
|
BI.each(this.options.items, function (i, item) { |
|
self._children[item.cardName].setVisible(self.showIndex == i); |
|
}); |
|
}, |
|
|
|
setDefaultShowName: function (name) { |
|
this.options.defaultShowName = name; |
|
return this; |
|
}, |
|
|
|
getDefaultShowName: function () { |
|
return this.options.defaultShowName; |
|
}, |
|
|
|
getAllCardNames: function () { |
|
return BI.map(this.options.items, function (i, item) { |
|
return item.cardName; |
|
}); |
|
}, |
|
|
|
getShowingCard: function () { |
|
if (!BI.isKey(this.showIndex)) { |
|
return void 0; |
|
} |
|
return this.getWidgetByName(this.showIndex); |
|
}, |
|
|
|
deleteAllCard: function () { |
|
var self = this; |
|
BI.each(this.getAllCardNames(), function (i, name) { |
|
self.deleteCardByName(name); |
|
}); |
|
}, |
|
|
|
hideAllCard: function () { |
|
var self = this; |
|
BI.each(this.options.items, function (i, item) { |
|
self._children[item.cardName].invisible(); |
|
}); |
|
}, |
|
|
|
isAllCardHide: function () { |
|
var self = this; |
|
var flag = true; |
|
BI.some(this.options.items, function (i, item) { |
|
if (self._children[item.cardName].isVisible()) { |
|
flag = false; |
|
return false; |
|
} |
|
}); |
|
return flag; |
|
}, |
|
|
|
removeWidget: function (nameOrWidget) { |
|
var removeName; |
|
if (BI.isWidget(nameOrWidget)) { |
|
BI.each(this._children, function (name, child) { |
|
if (child === nameOrWidget) { |
|
removeName = name; |
|
} |
|
}); |
|
} else { |
|
removeName = nameOrWidget; |
|
} |
|
if (removeName) { |
|
this._deleteCardByName(removeName); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.card", BI.CardLayout);/** |
|
* 默认的布局方式 |
|
* |
|
* @class BI.DefaultLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.DefaultLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.DefaultLayout.superclass.props.apply(this, arguments), { |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
items: [] |
|
}); |
|
}, |
|
render: function () { |
|
BI.DefaultLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.DefaultLayout.superclass._addElement.apply(this, arguments); |
|
if (o.vgap + o.tgap + (item.tgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + (item.lgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("default布局不需要resize") |
|
}, |
|
|
|
populate: function (items) { |
|
BI.DefaultLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.default", BI.DefaultLayout);/** |
|
* 分隔容器的控件,按照宽度和高度所占比平分整个容器 |
|
* |
|
* @class BI.DivisionLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.DivisionLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.DivisionLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-division-layout", |
|
columns: null, |
|
rows: null, |
|
items: [] |
|
// [ |
|
// { |
|
// column: 0, |
|
// row: 0, |
|
// width: 0.25, |
|
// height: 0.33, |
|
// el: {type: 'bi.button', text: 'button1'} |
|
// }, |
|
// { |
|
// column: 1, |
|
// row: 1, |
|
// width: 0.25, |
|
// height: 0.33, |
|
// el: {type: 'bi.button', text: 'button2'} |
|
// }, |
|
// { |
|
// column: 3, |
|
// row: 2, |
|
// width: 0.25, |
|
// height: 0.33, |
|
// el: {type: 'bi.button', text: 'button3'} |
|
// } |
|
// ] |
|
}); |
|
}, |
|
render: function () { |
|
BI.DivisionLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.opitons.items); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var o = this.options; |
|
var rows = o.rows || o.items.length, columns = o.columns || ((o.items[0] && o.items[0].length) | 0); |
|
var map = BI.makeArray(rows), widths = {}, heights = {}; |
|
|
|
function firstElement (item, row, col) { |
|
if (row === 0) { |
|
item.addClass("first-row"); |
|
} |
|
if (col === 0) { |
|
item.addClass("first-col"); |
|
} |
|
item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row"); |
|
item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col"); |
|
item.addClass("center-element"); |
|
} |
|
|
|
function firstObject (item, row, col) { |
|
var cls = ""; |
|
if (row === 0) { |
|
cls += " first-row"; |
|
} |
|
if (col === 0) { |
|
cls += " first-col"; |
|
} |
|
BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row"); |
|
BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col"); |
|
item.cls = (item.cls || "") + cls + " center-element"; |
|
} |
|
|
|
function first (item, row, col) { |
|
if (item instanceof BI.Widget) { |
|
firstElement(item.element, row, col); |
|
} else if (item.el instanceof BI.Widget) { |
|
firstElement(item.el.element, row, col); |
|
} else if (item.el) { |
|
firstObject(item.el, row, col); |
|
} else { |
|
firstObject(item, row, col); |
|
} |
|
} |
|
|
|
BI.each(map, function (i) { |
|
map[i] = BI.makeArray(columns); |
|
}); |
|
BI.each(items, function (i, item) { |
|
if (BI.isArray(item)) { |
|
BI.each(item, function (j, el) { |
|
widths[i] = (widths[i] || 0) + item.width; |
|
heights[j] = (heights[j] || 0) + item.height; |
|
map[i][j] = el; |
|
}); |
|
return; |
|
} |
|
widths[item.row] = (widths[item.row] || 0) + item.width; |
|
heights[item.column] = (heights[item.column] || 0) + item.height; |
|
map[item.row][item.column] = item; |
|
}); |
|
for (var i = 0; i < rows; i++) { |
|
var totalW = 0; |
|
for (var j = 0; j < columns; j++) { |
|
if (!map[i][j]) { |
|
throw new Error("item be required"); |
|
} |
|
if (!this.hasWidget(this.getName() + i + "_" + j)) { |
|
var w = BI.createWidget(map[i][j]); |
|
this.addWidget(this.getName() + i + "_" + j, w); |
|
} else { |
|
w = this.getWidgetByName(this.getName() + i + "_" + j); |
|
} |
|
var left = totalW * 100 / widths[i]; |
|
w.element.css({position: "absolute", left: left + "%"}); |
|
if (j > 0) { |
|
var lastW = this.getWidgetByName(this.getName() + i + "_" + (j - 1)); |
|
lastW.element.css({right: (100 - left) + "%"}); |
|
} |
|
if (j == o.columns - 1) { |
|
w.element.css({right: "0%"}); |
|
} |
|
first(w, i, j); |
|
totalW += map[i][j].width; |
|
} |
|
} |
|
for (var j = 0; j < o.columns; j++) { |
|
var totalH = 0; |
|
for (var i = 0; i < o.rows; i++) { |
|
var w = this.getWidgetByName(this.getName() + i + "_" + j); |
|
var top = totalH * 100 / heights[j]; |
|
w.element.css({top: top + "%"}); |
|
if (i > 0) { |
|
var lastW = this.getWidgetByName(this.getName() + (i - 1) + "_" + j); |
|
lastW.element.css({bottom: (100 - top) + "%"}); |
|
} |
|
if (i == o.rows - 1) { |
|
w.element.css({bottom: "0%"}); |
|
} |
|
totalH += map[i][j].height; |
|
} |
|
} |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.DivisionLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.division", BI.DivisionLayout);/** |
|
* 靠左对齐的自由浮动布局 |
|
* @class BI.FloatLeftLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Number} [hgap=0] 水平间隙 |
|
* @cfg {Number} [vgap=0] 垂直间隙 |
|
*/ |
|
BI.FloatLeftLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FloatLeftLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-float-left-layout clearfix", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FloatLeftLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FloatLeftLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({position: "relative", float: "left"}); |
|
if (BI.isNotNull(item.left)) { |
|
w.element.css({left: item.left}); |
|
} |
|
if (BI.isNotNull(item.right)) { |
|
w.element.css({right: item.right}); |
|
} |
|
if (BI.isNotNull(item.top)) { |
|
w.element.css({top: item.top}); |
|
} |
|
if (BI.isNotNull(item.bottom)) { |
|
w.element.css({bottom: item.bottom}); |
|
} |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FloatLeftLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.left", BI.FloatLeftLayout); |
|
|
|
/** |
|
* 靠右对齐的自由浮动布局 |
|
* @class BI.FloatRightLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Number} [hgap=0] 水平间隙 |
|
* @cfg {Number} [vgap=0] 垂直间隙 |
|
*/ |
|
BI.FloatRightLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FloatRightLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-float-right-layout clearfix", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FloatRightLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.FloatRightLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({position: "relative", float: "right"}); |
|
if (BI.isNotNull(item.left)) { |
|
w.element.css({left: item.left}); |
|
} |
|
if (BI.isNotNull(item.right)) { |
|
w.element.css({right: item.right}); |
|
} |
|
if (BI.isNotNull(item.top)) { |
|
w.element.css({top: item.top}); |
|
} |
|
if (BI.isNotNull(item.bottom)) { |
|
w.element.css({bottom: item.bottom}); |
|
} |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": (i === 0 ? o.hgap : 0) + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.FloatRightLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.right", BI.FloatRightLayout);/** |
|
* 上下的高度固定/左右的宽度固定,中间的高度/宽度自适应 |
|
* |
|
* @class BI.BorderLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.GridLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.GridLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-grid-layout", |
|
columns: null, |
|
rows: null, |
|
items: [] |
|
/* [ |
|
{ |
|
column: 0, |
|
row: 0, |
|
el: {type: 'bi.button', text: 'button1'} |
|
}, |
|
{ |
|
column: 1, |
|
row: 1, |
|
el: {type: 'bi.button', text: 'button2'} |
|
}, |
|
{ |
|
column: 3, |
|
row: 2, |
|
el: {type: 'bi.button', text: 'button3'} |
|
} |
|
]*/ |
|
}); |
|
}, |
|
render: function () { |
|
BI.GridLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
// console.log("grid布局不需要resize") |
|
}, |
|
|
|
addItem: function () { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var self = this, o = this.options; |
|
var rows = o.rows || o.items.length, columns = o.columns || ((o.items[0] && o.items[0].length) | 0); |
|
var width = 100 / columns, height = 100 / rows; |
|
var els = []; |
|
for (var i = 0; i < rows; i++) { |
|
els[i] = []; |
|
} |
|
|
|
function firstElement (item, row, col) { |
|
if (row === 0) { |
|
item.addClass("first-row"); |
|
} |
|
if (col === 0) { |
|
item.addClass("first-col"); |
|
} |
|
item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row"); |
|
item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col"); |
|
item.addClass("center-element"); |
|
} |
|
|
|
function firstObject (item, row, col) { |
|
var cls = ""; |
|
if (row === 0) { |
|
cls += " first-row"; |
|
} |
|
if (col === 0) { |
|
cls += " first-col"; |
|
} |
|
BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row"); |
|
BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col"); |
|
item.cls = (item.cls || "") + cls + " center-element"; |
|
} |
|
|
|
function first (item, row, col) { |
|
if (item instanceof BI.Widget) { |
|
firstElement(item.element, row, col); |
|
} else if (item.el instanceof BI.Widget) { |
|
firstElement(item.el.element, row, col); |
|
} else if (item.el) { |
|
firstObject(item.el, row, col); |
|
} else { |
|
firstObject(item, row, col); |
|
} |
|
} |
|
|
|
BI.each(items, function (i, item) { |
|
if (BI.isArray(item)) { |
|
BI.each(item, function (j, el) { |
|
els[i][j] = BI.createWidget(el); |
|
}); |
|
return; |
|
} |
|
els[item.row][item.column] = BI.createWidget(item); |
|
}); |
|
for (var i = 0; i < rows; i++) { |
|
for (var j = 0; j < columns; j++) { |
|
if (!els[i][j]) { |
|
els[i][j] = BI.createWidget({ |
|
type: "bi.layout" |
|
}); |
|
} |
|
first(els[i][j], i, j); |
|
els[i][j].element.css({ |
|
position: "absolute", |
|
top: height * i + "%", |
|
left: width * j + "%", |
|
right: (100 - (width * (j + 1))) + "%", |
|
bottom: (100 - (height * (i + 1))) + "%" |
|
}); |
|
this.addWidget(els[i][j]); |
|
} |
|
} |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.GridLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.grid", BI.GridLayout);/** |
|
* 水平布局 |
|
* @class BI.HorizontalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.HorizontalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.HorizontalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-horizontal-layout", |
|
verticalAlign: BI.VerticalAlign.Top, |
|
horizontalAlign: BI.HorizontalAlign.Left, |
|
columnSize: [], |
|
scrollx: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
var o = this.options; |
|
BI.HorizontalLayout.superclass.render.apply(this, arguments); |
|
this.$table = BI.Widget._renderEngine.createElement("<table>").attr({cellspacing: 0, cellpadding: 0}).css({ |
|
position: "relative", |
|
"white-space": "nowrap", |
|
height: o.verticalAlign === BI.VerticalAlign.Middle ? "100%" : "auto", |
|
width: (o.horizontalAlign === BI.HorizontalAlign.Center || o.horizontalAlign === BI.HorizontalAlign.Stretch) ? "100%" : "auto", |
|
"border-spacing": "0px", |
|
border: "none", |
|
"border-collapse": "separate" |
|
}); |
|
this.$tr = BI.Widget._renderEngine.createElement("<tr>"); |
|
this.$tr.appendTo(this.$table); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var td; |
|
var width = o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i]; |
|
if (!this.hasWidget(this._getChildName(i))) { |
|
var w = BI.createWidget(item); |
|
w.element.css({position: "relative", margin: "0px auto"}); |
|
td = BI.createWidget({ |
|
type: "bi.default", |
|
tagName: "td", |
|
attributes: { |
|
width: width |
|
}, |
|
items: [w] |
|
}); |
|
this.addWidget(this._getChildName(i), td); |
|
} else { |
|
td = this.getWidgetByName(this._getChildName(i)); |
|
td.element.attr("width", width); |
|
} |
|
// 对于表现为td的元素设置最大宽度,有几点需要注意 |
|
// 1、由于直接对td设置最大宽度是在规范中未定义的, 所以要使用类似td:firstChild来迂回实现 |
|
// 2、不能给多个td设置最大宽度,这样只会平分宽度 |
|
// 3、多百分比宽度就算了 |
|
td.element.css({"max-width": o.columnSize[i] <= 1 ? width : width + "px"}); |
|
if (i === 0) { |
|
td.element.addClass("first-element"); |
|
} |
|
td.element.css({ |
|
position: "relative", |
|
"vertical-align": o.verticalAlign, |
|
margin: "0", |
|
padding: "0", |
|
border: "none" |
|
}); |
|
|
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return td; |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.$tr.append(frag); |
|
this.element.append(this.$table); |
|
}, |
|
|
|
resize: function () { |
|
// console.log("horizontal layout do not need to resize"); |
|
}, |
|
|
|
_getWrapper: function () { |
|
return this.$tr; |
|
}, |
|
|
|
populate: function (items) { |
|
BI.HorizontalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.horizontal", BI.HorizontalLayout); |
|
|
|
/** |
|
* 水平布局 |
|
* @class BI.HorizontalCellLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.HorizontalCellLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.HorizontalCellLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-horizontal-cell-layout", |
|
scrollable: true, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.HorizontalCellLayout.superclass.render.apply(this, arguments); |
|
this.element.css({display: "table", "vertical-align": "top"}); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.HorizontalCellLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({position: "relative", display: "table-cell", "vertical-align": "middle"}); |
|
if (o.hgap + o.lgap > 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap > 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + "px" |
|
}); |
|
} |
|
if (o.vgap + o.tgap > 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap > 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("horizontal do not need to resize"); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.HorizontalCellLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.horizontal_cell", BI.HorizontalCellLayout);/** |
|
* 内联布局 |
|
* @class BI.InlineLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Number} [hgap=0] 水平间隙 |
|
* @cfg {Number} [vgap=0] 垂直间隙 |
|
*/ |
|
BI.InlineLayout = BI.inherit(BI.Layout, { |
|
|
|
props: function () { |
|
return BI.extend(BI.InlineLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-inline-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.InlineLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.InlineLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({"position": "relative", display: "inline-block", "*display": "inline", "*zoom": 1}); |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": (i === 0 ? o.hgap : 0) + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.InlineLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.inline", BI.InlineLayout);/** |
|
* 靠左对齐的自由浮动布局 |
|
* @class BI.LatticeLayout |
|
* @extends BI.Layout |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {Number} [hgap=0] 水平间隙 |
|
* @cfg {Number} [vgap=0] 垂直间隙 |
|
*/ |
|
BI.LatticeLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.LatticeLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-lattice-layout clearfix" |
|
// columnSize: [0.2, 0.2, 0.6], |
|
}); |
|
}, |
|
render: function () { |
|
BI.LatticeLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.LatticeLayout.superclass._addElement.apply(this, arguments); |
|
if (o.columnSize && o.columnSize[i]) { |
|
var width = o.columnSize[i] / BI.sum(o.columnSize) * 100 + "%"; |
|
} else { |
|
var width = 1 / this.options.items.length * 100 + "%"; |
|
} |
|
w.element.css({position: "relative", float: "left", width: width}); |
|
return w; |
|
}, |
|
|
|
addItem: function (item) { |
|
var w = BI.LatticeLayout.superclass.addItem.apply(this, arguments); |
|
this.resize(); |
|
return w; |
|
}, |
|
|
|
addItemAt: function (item) { |
|
var w = BI.LatticeLayout.superclass.addItemAt.apply(this, arguments); |
|
this.resize(); |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.LatticeLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.lattice", BI.LatticeLayout);/** |
|
* 上下的高度固定/左右的宽度固定,中间的高度/宽度自适应 |
|
* |
|
* @class BI.TableLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.TableLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.TableLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-table-layout", |
|
scrolly: true, |
|
columnSize: [200, 200, "fill"], |
|
rowSize: 30, // or [30,30,30] |
|
hgap: 0, |
|
vgap: 0, |
|
items: [[ |
|
{ |
|
el: {text: "label1"} |
|
}, |
|
{ |
|
el: {text: "label2"} |
|
}, |
|
{ |
|
el: {text: "label3"} |
|
} |
|
]] |
|
}); |
|
}, |
|
render: function () { |
|
BI.TableLayout.superclass.render.apply(this, arguments); |
|
this.rows = 0; |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (idx, arr) { |
|
var o = this.options; |
|
var abs = [], left = 0, right = 0, i, j; |
|
|
|
function firstElement (item, row, col) { |
|
if (row === 0) { |
|
item.addClass("first-row"); |
|
} |
|
if (col === 0) { |
|
item.addClass("first-col"); |
|
} |
|
item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row"); |
|
item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col"); |
|
item.addClass("center-element"); |
|
} |
|
|
|
function firstObject (item, row, col) { |
|
var cls = ""; |
|
if (row === 0) { |
|
cls += " first-row"; |
|
} |
|
if (col === 0) { |
|
cls += " first-col"; |
|
} |
|
BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row"); |
|
BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col"); |
|
item.cls = (item.cls || "") + cls + " center-element"; |
|
} |
|
|
|
function first (item, row, col) { |
|
if (item instanceof BI.Widget) { |
|
firstElement(item.element, row, col); |
|
} else if (item.el instanceof BI.Widget) { |
|
firstElement(item.el.element, row, col); |
|
} else if (item.el) { |
|
firstObject(item.el, row, col); |
|
} else { |
|
firstObject(item, row, col); |
|
} |
|
} |
|
|
|
for (i = 0; i < arr.length; i++) { |
|
if (BI.isNumber(o.columnSize[i])) { |
|
first(arr[i], this.rows, i); |
|
abs.push(BI.extend({ |
|
top: 0, |
|
bottom: 0, |
|
left: o.columnSize[i] <= 1 ? left * 100 + "%" : left, |
|
width: o.columnSize[i] <= 1 ? o.columnSize[i] * 100 + "%" : o.columnSize[i] |
|
}, arr[i])); |
|
left += o.columnSize[i] + (o.columnSize[i] < 1 ? 0 : o.hgap); |
|
} else { |
|
break; |
|
} |
|
} |
|
for (j = arr.length - 1; j > i; j--) { |
|
if (BI.isNumber(o.columnSize[j])) { |
|
first(arr[j], this.rows, j); |
|
abs.push(BI.extend({ |
|
top: 0, |
|
bottom: 0, |
|
right: o.columnSize[j] <= 1 ? right * 100 + "%" : right, |
|
width: o.columnSize[j] <= 1 ? o.columnSize[j] * 100 + "%" : o.columnSize[j] |
|
}, arr[j])); |
|
right += o.columnSize[j] + (o.columnSize[j] < 1 ? 0 : o.hgap); |
|
} else { |
|
throw new Error("item with fill can only be one"); |
|
} |
|
} |
|
if (i >= 0 && i < arr.length) { |
|
first(arr[i], this.rows, i); |
|
abs.push(BI.extend({ |
|
top: 0, |
|
bottom: 0, |
|
left: left <= 1 ? left * 100 + "%" : left, |
|
right: right <= 1 ? right * 100 + "%" : right |
|
}, arr[i])); |
|
} |
|
var w = BI.createWidget({ |
|
type: "bi.absolute", |
|
height: BI.isArray(o.rowSize) ? o.rowSize[this.rows] : o.rowSize, |
|
items: abs |
|
}); |
|
if (this.rows > 0) { |
|
this.getWidgetByName(this.getName() + (this.rows - 1)).element.css({ |
|
"margin-bottom": o.vgap |
|
}); |
|
} |
|
w.element.css({ |
|
position: "relative" |
|
}); |
|
this.addWidget(this.getName() + (this.rows++), w); |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("table布局不需要resize"); |
|
}, |
|
|
|
addItem: function (arr) { |
|
if (!BI.isArray(arr)) { |
|
throw new Error("item must be array"); |
|
} |
|
return BI.TableLayout.superclass.addItem.apply(this, arguments); |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.TableLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.table", BI.TableLayout);/** |
|
* 水平tape布局 |
|
* @class BI.HTapeLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.HTapeLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.HTapeLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-h-tape-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
items: [ |
|
{ |
|
width: 100, |
|
el: {type: "bi.button", text: "button1"} |
|
}, |
|
{ |
|
width: "fill", |
|
el: {type: "bi.button", text: "button2"} |
|
}, |
|
{ |
|
width: 200, |
|
el: {type: "bi.button", text: "button3"} |
|
} |
|
] |
|
}); |
|
}, |
|
render: function () { |
|
BI.HTapeLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var self = this, o = this.options; |
|
items = BI.compact(items); |
|
BI.each(items, function (i, item) { |
|
if (!self.hasWidget(self.getName() + i + "")) { |
|
var w = BI.createWidget(item); |
|
self.addWidget(self.getName() + i + "", w); |
|
} else { |
|
w = self.getWidgetByName(self.getName() + i + ""); |
|
} |
|
w.element.css({position: "absolute", top: (item.vgap || 0) + (item.tgap || 0) + o.vgap + o.tgap + "px", bottom: (item.bgap || 0) + (item.vgap || 0) + o.vgap + o.bgap + "px"}); |
|
}); |
|
|
|
var left = {}, right = {}; |
|
left[0] = 0; |
|
right[items.length - 1] = 0; |
|
|
|
BI.any(items, function (i, item) { |
|
var w = self.getWidgetByName(self.getName() + i + ""); |
|
if (BI.isNull(left[i])) { |
|
left[i] = left[i - 1] + items[i - 1].width + (items[i - 1].lgap || 0) + 2 * (items[i - 1].hgap || 0) + o.hgap + o.lgap + o.rgap; |
|
} |
|
if (item.width < 1 && item.width >= 0) { |
|
w.element.css({left: left[i] * 100 + "%", width: item.width * 100 + "%"}); |
|
} else { |
|
w.element.css({ |
|
left: left[i] + (item.lgap || 0) + (item.hgap || 0) + o.hgap + o.lgap + "px", |
|
width: BI.isNumber(item.width) ? item.width : "" |
|
}); |
|
} |
|
if (!BI.isNumber(item.width)) { |
|
return true; |
|
} |
|
}); |
|
BI.backAny(items, function (i, item) { |
|
var w = self.getWidgetByName(self.getName() + i + ""); |
|
if (BI.isNull(right[i])) { |
|
right[i] = right[i + 1] + items[i + 1].width + (items[i + 1].rgap || 0) + 2 * (items[i + 1].hgap || 0) + o.hgap + o.lgap + o.rgap; |
|
} |
|
if (item.width < 1 && item.width >= 0) { |
|
w.element.css({right: right[i] * 100 + "%", width: item.width * 100 + "%"}); |
|
} else { |
|
w.element.css({ |
|
right: right[i] + (item.rgap || 0) + (item.hgap || 0) + o.hgap + o.rgap + "px", |
|
width: BI.isNumber(item.width) ? item.width : "" |
|
}); |
|
} |
|
if (!BI.isNumber(item.width)) { |
|
return true; |
|
} |
|
}); |
|
}, |
|
|
|
update: function () { |
|
var updated; |
|
BI.each(this._children, function (i, child) { |
|
updated = child.update() || updated; |
|
}); |
|
return updated; |
|
}, |
|
|
|
populate: function (items) { |
|
BI.HTapeLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.htape", BI.HTapeLayout); |
|
|
|
/** |
|
* 垂直tape布局 |
|
* @class BI.VTapeLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.VTapeLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.VTapeLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-v-tape-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
items: [ |
|
{ |
|
height: 100, |
|
el: {type: "bi.button", text: "button1"} |
|
}, |
|
{ |
|
height: "fill", |
|
el: {type: "bi.button", text: "button2"} |
|
}, |
|
{ |
|
height: 200, |
|
el: {type: "bi.button", text: "button3"} |
|
} |
|
] |
|
}); |
|
}, |
|
render: function () { |
|
BI.VTapeLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var self = this, o = this.options; |
|
items = BI.compact(items); |
|
BI.each(items, function (i, item) { |
|
if (!self.hasWidget(self.getName() + i + "")) { |
|
var w = BI.createWidget(item); |
|
self.addWidget(self.getName() + i + "", w); |
|
} else { |
|
w = self.getWidgetByName(self.getName() + i + ""); |
|
} |
|
w.element.css({position: "absolute", left: (item.lgap || 0) + (item.hgap || 0) + o.hgap + o.lgap + "px", right: + (item.hgap || 0) + (item.rgap || 0) + o.hgap + o.rgap + "px"}); |
|
}); |
|
|
|
var top = {}, bottom = {}; |
|
top[0] = 0; |
|
bottom[items.length - 1] = 0; |
|
|
|
BI.any(items, function (i, item) { |
|
var w = self.getWidgetByName(self.getName() + i + ""); |
|
if (BI.isNull(top[i])) { |
|
top[i] = top[i - 1] + items[i - 1].height + (items[i - 1].tgap || 0) + 2 * (items[i - 1].vgap || 0) + o.vgap + o.tgap + o.bgap; |
|
} |
|
if (item.height < 1 && item.height >= 0) { |
|
w.element.css({top: top[i] * 100 + "%", height: item.height * 100 + "%"}); |
|
} else { |
|
w.element.css({ |
|
top: top[i] + (item.vgap || 0) + (item.tgap || 0) + o.vgap + o.tgap + "px", |
|
height: BI.isNumber(item.height) ? item.height : "" |
|
}); |
|
} |
|
if (!BI.isNumber(item.height)) { |
|
return true; |
|
} |
|
}); |
|
BI.backAny(items, function (i, item) { |
|
var w = self.getWidgetByName(self.getName() + i + ""); |
|
if (BI.isNull(bottom[i])) { |
|
bottom[i] = bottom[i + 1] + items[i + 1].height + (items[i + 1].bgap || 0) + 2 * (items[i + 1].vgap || 0) + o.vgap + o.tgap + o.bgap; |
|
} |
|
if (item.height < 1 && item.height >= 0) { |
|
w.element.css({bottom: bottom[i] * 100 + "%", height: item.height * 100 + "%"}); |
|
} else { |
|
w.element.css({ |
|
bottom: bottom[i] + (item.vgap || 0) + (item.bgap || 0) + o.vgap + o.bgap + "px", |
|
height: BI.isNumber(item.height) ? item.height : "" |
|
}); |
|
} |
|
if (!BI.isNumber(item.height)) { |
|
return true; |
|
} |
|
}); |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.VTapeLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.vtape", BI.VTapeLayout);/** |
|
* td布局 |
|
* @class BI.TdLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.TdLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.TdLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-td-layout", |
|
columnSize: [200, 200, 200], |
|
hgap: 0, |
|
vgap: 0, |
|
items: [[ |
|
{ |
|
el: {text: "label1"} |
|
}, |
|
{ |
|
el: {text: "label2"} |
|
}, |
|
{ |
|
el: {text: "label3"} |
|
} |
|
]] |
|
}); |
|
}, |
|
render: function () { |
|
BI.TdLayout.superclass.render.apply(this, arguments); |
|
this.$table = BI.Widget._renderEngine.createElement("<table>").attr({cellspacing: 0, cellpadding: 0}).css({ |
|
position: "relative", |
|
width: "100%", |
|
height: "100%", |
|
"border-spacing": "0px", |
|
border: "none", |
|
"border-collapse": "separate" |
|
}); |
|
this.rows = 0; |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (idx, arr) { |
|
var o = this.options; |
|
|
|
function firstElement (item, row, col) { |
|
if (row === 0) { |
|
item.addClass("first-row"); |
|
} |
|
if (col === 0) { |
|
item.addClass("first-col"); |
|
} |
|
item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row"); |
|
item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col"); |
|
item.addClass("center-element"); |
|
} |
|
|
|
function firstObject (item, row, col) { |
|
var cls = ""; |
|
if (row === 0) { |
|
cls += " first-row"; |
|
} |
|
if (col === 0) { |
|
cls += " first-col"; |
|
} |
|
BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row"); |
|
BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col"); |
|
item.cls = (item.cls || "") + cls + " center-element"; |
|
} |
|
|
|
function first (item, row, col) { |
|
if (item instanceof BI.Widget) { |
|
firstElement(item.element, row, col); |
|
} else if (item.el instanceof BI.Widget) { |
|
firstElement(item.el.element, row, col); |
|
} else if (item.el) { |
|
firstObject(item.el, row, col); |
|
} else { |
|
firstObject(item, row, col); |
|
} |
|
} |
|
|
|
var tr = BI.createWidget({ |
|
type: "bi.default", |
|
tagName: "tr" |
|
}); |
|
|
|
for (var i = 0; i < arr.length; i++) { |
|
var w = BI.createWidget(arr[i]); |
|
w.element.css({position: "relative", top: "0", left: "0", margin: "0px auto"}); |
|
if (arr[i].lgap) { |
|
w.element.css({"margin-left": arr[i].lgap + "px"}); |
|
} |
|
if (arr[i].rgap) { |
|
w.element.css({"margin-right": arr[i].rgap + "px"}); |
|
} |
|
if (arr[i].tgap) { |
|
w.element.css({"margin-top": arr[i].tgap + "px"}); |
|
} |
|
if (arr[i].bgap) { |
|
w.element.css({"margin-bottom": arr[i].bgap + "px"}); |
|
} |
|
first(w, this.rows++, i); |
|
var td = BI.createWidget({ |
|
type: "bi.default", |
|
attributes: { |
|
width: o.columnSize[i] <= 1 ? (o.columnSize[i] * 100 + "%") : o.columnSize[i] |
|
}, |
|
tagName: "td", |
|
items: [w] |
|
}); |
|
td.element.css({ |
|
position: "relative", |
|
"vertical-align": "middle", |
|
margin: "0", |
|
padding: "0", |
|
border: "none" |
|
}); |
|
tr.addItem(td); |
|
} |
|
this.addWidget(this.getName() + idx, tr); |
|
return tr; |
|
}, |
|
|
|
appendFragment: function (frag) { |
|
this.$table.append(frag); |
|
this.element.append(this.$table); |
|
}, |
|
|
|
resize: function () { |
|
// console.log("td布局不需要resize"); |
|
}, |
|
|
|
addItem: function (arr) { |
|
if (!BI.isArray(arr)) { |
|
throw new Error("item must be array"); |
|
} |
|
return BI.TdLayout.superclass.addItem.apply(this, arguments); |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.TdLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.td", BI.TdLayout);/** |
|
* 垂直布局 |
|
* @class BI.VerticalLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.VerticalLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.VerticalLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-vertical-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
scrolly: true |
|
}); |
|
}, |
|
render: function () { |
|
BI.VerticalLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
_addElement: function (i, item) { |
|
var o = this.options; |
|
var w = BI.VerticalLayout.superclass._addElement.apply(this, arguments); |
|
w.element.css({ |
|
position: "relative" |
|
}); |
|
if (o.vgap + o.tgap + (item.tgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-top": (i === 0 ? o.vgap : 0) + o.tgap + (item.tgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
if (o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-left": o.hgap + o.lgap + (item.lgap || 0) + (item.hgap || 0) +"px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-right": o.hgap + o.rgap + (item.rgap || 0) + (item.hgap || 0) + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) !== 0) { |
|
w.element.css({ |
|
"margin-bottom": o.vgap + o.bgap + (item.bgap || 0) + (item.vgap || 0) + "px" |
|
}); |
|
} |
|
return w; |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.VerticalLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.vertical", BI.VerticalLayout);/** |
|
* |
|
* @class BI.WindowLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.WindowLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.WindowLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-window-layout", |
|
columns: 3, |
|
rows: 2, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
columnSize: [100, "fill", 200], |
|
rowSize: [100, "fill"], |
|
items: [[ |
|
{ |
|
el: {type: "bi.button", text: "button1"} |
|
}, |
|
{ |
|
el: {type: "bi.button", text: "button2"} |
|
}, |
|
{ |
|
el: {type: "bi.button", text: "button3"} |
|
} |
|
]] |
|
}); |
|
}, |
|
render: function () { |
|
BI.WindowLayout.superclass.render.apply(this, arguments); |
|
this.populate(this.options.items); |
|
}, |
|
|
|
resize: function () { |
|
this.stroke(this.options.items); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
stroke: function (items) { |
|
var o = this.options; |
|
if (BI.isNumber(o.rowSize)) { |
|
o.rowSize = BI.makeArray(o.items.length, 1 / o.items.length); |
|
} |
|
if (BI.isNumber(o.columnSize)) { |
|
o.columnSize = BI.makeArray(o.items[0].length, 1 / o.items[0].length); |
|
} |
|
function firstElement (item, row, col) { |
|
if (row === 0) { |
|
item.addClass("first-row"); |
|
} |
|
if (col === 0) { |
|
item.addClass("first-col"); |
|
} |
|
item.addClass(BI.isOdd(row + 1) ? "odd-row" : "even-row"); |
|
item.addClass(BI.isOdd(col + 1) ? "odd-col" : "even-col"); |
|
item.addClass("center-element"); |
|
} |
|
|
|
function firstObject (item, row, col) { |
|
var cls = ""; |
|
if (row === 0) { |
|
cls += " first-row"; |
|
} |
|
if (col === 0) { |
|
cls += " first-col"; |
|
} |
|
BI.isOdd(row + 1) ? (cls += " odd-row") : (cls += " even-row"); |
|
BI.isOdd(col + 1) ? (cls += " odd-col") : (cls += " even-col"); |
|
item.cls = (item.cls || "") + cls + " center-element"; |
|
} |
|
|
|
function first (item, row, col) { |
|
if (item instanceof BI.Widget) { |
|
firstElement(item.element, row, col); |
|
} else if (item.el instanceof BI.Widget) { |
|
firstElement(item.el.element, row, col); |
|
} else if (item.el) { |
|
firstObject(item.el, row, col); |
|
} else { |
|
firstObject(item, row, col); |
|
} |
|
} |
|
|
|
for (var i = 0; i < o.rows; i++) { |
|
for (var j = 0; j < o.columns; j++) { |
|
if (!o.items[i][j]) { |
|
throw new Error("item be required"); |
|
} |
|
if (!this.hasWidget(this.getName() + i + "_" + j)) { |
|
var w = BI.createWidget(o.items[i][j]); |
|
w.element.css({position: "absolute"}); |
|
this.addWidget(this.getName() + i + "_" + j, w); |
|
} |
|
} |
|
} |
|
var left = {}, right = {}, top = {}, bottom = {}; |
|
left[0] = 0; |
|
top[0] = 0; |
|
right[o.columns - 1] = 0; |
|
bottom[o.rows - 1] = 0; |
|
// 从上到下 |
|
for (var i = 0; i < o.rows; i++) { |
|
for (var j = 0; j < o.columns; j++) { |
|
var wi = this.getWidgetByName(this.getName() + i + "_" + j); |
|
if (BI.isNull(top[i])) { |
|
top[i] = top[i - 1] + (o.rowSize[i - 1] < 1 ? o.rowSize[i - 1] : o.rowSize[i - 1] + o.vgap + o.bgap); |
|
} |
|
var t = top[i] <= 1 ? top[i] * 100 + "%" : top[i] + o.vgap + o.tgap + "px", h = ""; |
|
if (BI.isNumber(o.rowSize[i])) { |
|
h = o.rowSize[i] <= 1 ? o.rowSize[i] * 100 + "%" : o.rowSize[i] + "px"; |
|
} |
|
wi.element.css({top: t, height: h}); |
|
first(wi, i, j); |
|
} |
|
if (!BI.isNumber(o.rowSize[i])) { |
|
break; |
|
} |
|
} |
|
// 从下到上 |
|
for (var i = o.rows - 1; i >= 0; i--) { |
|
for (var j = 0; j < o.columns; j++) { |
|
var wi = this.getWidgetByName(this.getName() + i + "_" + j); |
|
if (BI.isNull(bottom[i])) { |
|
bottom[i] = bottom[i + 1] + (o.rowSize[i + 1] < 1 ? o.rowSize[i + 1] : o.rowSize[i + 1] + o.vgap + o.tgap); |
|
} |
|
var b = bottom[i] <= 1 ? bottom[i] * 100 + "%" : bottom[i] + o.vgap + o.bgap + "px", h = ""; |
|
if (BI.isNumber(o.rowSize[i])) { |
|
h = o.rowSize[i] <= 1 ? o.rowSize[i] * 100 + "%" : o.rowSize[i] + "px"; |
|
} |
|
wi.element.css({bottom: b, height: h}); |
|
first(wi, i, j); |
|
} |
|
if (!BI.isNumber(o.rowSize[i])) { |
|
break; |
|
} |
|
} |
|
// 从左到右 |
|
for (var j = 0; j < o.columns; j++) { |
|
for (var i = 0; i < o.rows; i++) { |
|
var wi = this.getWidgetByName(this.getName() + i + "_" + j); |
|
if (BI.isNull(left[j])) { |
|
left[j] = left[j - 1] + (o.columnSize[j - 1] < 1 ? o.columnSize[j - 1] : o.columnSize[j - 1] + o.hgap + o.rgap); |
|
} |
|
var l = left[j] <= 1 ? left[j] * 100 + "%" : left[j] + o.hgap + o.lgap + "px", w = ""; |
|
if (BI.isNumber(o.columnSize[j])) { |
|
w = o.columnSize[j] <= 1 ? o.columnSize[j] * 100 + "%" : o.columnSize[j] + "px"; |
|
} |
|
wi.element.css({left: l, width: w}); |
|
first(wi, i, j); |
|
} |
|
if (!BI.isNumber(o.columnSize[j])) { |
|
break; |
|
} |
|
} |
|
// 从右到左 |
|
for (var j = o.columns - 1; j >= 0; j--) { |
|
for (var i = 0; i < o.rows; i++) { |
|
var wi = this.getWidgetByName(this.getName() + i + "_" + j); |
|
if (BI.isNull(right[j])) { |
|
right[j] = right[j + 1] + (o.columnSize[j + 1] < 1 ? o.columnSize[j + 1] : o.columnSize[j + 1] + o.hgap + o.lgap); |
|
} |
|
var r = right[j] <= 1 ? right[j] * 100 + "%" : right[j] + o.hgap + o.rgap + "px", w = ""; |
|
if (BI.isNumber(o.columnSize[j])) { |
|
w = o.columnSize[j] <= 1 ? o.columnSize[j] * 100 + "%" : o.columnSize[j] + "px"; |
|
} |
|
wi.element.css({right: r, width: w}); |
|
first(wi, i, j); |
|
} |
|
if (!BI.isNumber(o.columnSize[j])) { |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
update: function () { |
|
}, |
|
|
|
populate: function (items) { |
|
BI.WindowLayout.superclass.populate.apply(this, arguments); |
|
this._mount(); |
|
} |
|
}); |
|
BI.shortcut("bi.window", BI.WindowLayout);/** |
|
* 水平和垂直方向都居中容器, 非自适应,用于宽度高度固定的面板 |
|
* @class BI.CenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.CenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.CenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-center-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.CenterLayout.superclass.render.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var list = [], items = o.items; |
|
BI.each(items, function (i) { |
|
list.push({ |
|
column: i, |
|
row: 0, |
|
el: BI.createWidget({ |
|
type: "bi.default", |
|
cls: "center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "") |
|
}) |
|
}); |
|
}); |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
var w = BI.createWidget(item); |
|
w.element.css({ |
|
position: "absolute", |
|
left: o.hgap + o.lgap, |
|
right: o.hgap + o.rgap, |
|
top: o.vgap + o.tgap, |
|
bottom: o.vgap + o.bgap, |
|
width: "auto", |
|
height: "auto" |
|
}); |
|
list[i].el.addItem(w); |
|
} |
|
}); |
|
return { |
|
type: "bi.grid", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
columns: list.length, |
|
rows: 1, |
|
items: list |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("center布局不需要resize"); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate.apply(this.wrapper, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.center", BI.CenterLayout);/** |
|
* 浮动布局实现的居中容器 |
|
* @class BI.FloatCenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.FloatCenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.FloatCenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-float-center-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.FloatCenterLayout.superclass.render.apply(this, arguments); |
|
var self = this, o = this.options, items = o.items; |
|
var list = [], width = 100 / items.length; |
|
BI.each(items, function (i) { |
|
var widget = BI.createWidget({ |
|
type: "bi.default" |
|
}); |
|
widget.element.addClass("center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "")).css({ |
|
width: width + "%", |
|
height: "100%" |
|
}); |
|
list.push({ |
|
el: widget |
|
}); |
|
}); |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
var w = BI.createWidget(item); |
|
w.element.css({ |
|
position: "absolute", |
|
left: o.hgap + o.lgap, |
|
right: o.hgap + o.rgap, |
|
top: o.vgap + o.tgap, |
|
bottom: o.vgap + o.bgap, |
|
width: "auto", |
|
height: "auto" |
|
}); |
|
list[i].el.addItem(w); |
|
} |
|
}); |
|
return { |
|
type: "bi.left", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
items: list |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("floatcenter布局不需要resize"); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate.apply(this.wrapper, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.float_center", BI.FloatCenterLayout);/** |
|
* 水平和垂直方向都居中容器, 非自适应,用于宽度高度固定的面板 |
|
* @class BI.HorizontalCenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.HorizontalCenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.HorizontalCenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-horizontal-center-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
render: function () { |
|
BI.HorizontalCenterLayout.superclass.render.apply(this, arguments); |
|
var self = this, o = this.options, items = o.items; |
|
var list = []; |
|
BI.each(items, function (i) { |
|
list.push({ |
|
column: i, |
|
row: 0, |
|
el: BI.createWidget({ |
|
type: "bi.default", |
|
cls: "center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "") |
|
}) |
|
}); |
|
}); |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
var w = BI.createWidget(item); |
|
w.element.css({ |
|
position: "absolute", |
|
left: o.hgap + o.lgap, |
|
right: o.hgap + o.rgap, |
|
top: o.vgap + o.tgap, |
|
bottom: o.vgap + o.bgap, |
|
width: "auto" |
|
}); |
|
list[i].el.addItem(w); |
|
} |
|
}); |
|
return { |
|
type: "bi.grid", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
columns: list.length, |
|
rows: 1, |
|
items: list |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("horizontal_center布局不需要resize"); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate.apply(this.wrapper, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.horizontal_center", BI.HorizontalCenterLayout);/** |
|
* 垂直方向都居中容器, 非自适应,用于高度不固定的面板 |
|
* @class BI.VerticalCenterLayout |
|
* @extends BI.Layout |
|
*/ |
|
BI.VerticalCenterLayout = BI.inherit(BI.Layout, { |
|
props: function () { |
|
return BI.extend(BI.VerticalCenterLayout.superclass.props.apply(this, arguments), { |
|
baseCls: "bi-vertical-center-layout", |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0 |
|
}); |
|
}, |
|
|
|
render: function () { |
|
BI.VerticalCenterLayout.superclass.render.apply(this, arguments); |
|
var self = this, o = this.options, items = o.items; |
|
var list = []; |
|
BI.each(items, function (i) { |
|
list.push({ |
|
column: 0, |
|
row: i, |
|
el: BI.createWidget({ |
|
type: "bi.default", |
|
cls: "center-element " + (i === 0 ? "first-element " : "") + (i === items.length - 1 ? "last-element" : "") |
|
}) |
|
}); |
|
}); |
|
BI.each(items, function (i, item) { |
|
if (item) { |
|
var w = BI.createWidget(item); |
|
w.element.css({ |
|
position: "absolute", |
|
left: o.hgap + o.lgap, |
|
right: o.hgap + o.rgap, |
|
top: o.vgap + o.tgap, |
|
bottom: o.vgap + o.bgap, |
|
height: "auto" |
|
}); |
|
list[i].el.addItem(w); |
|
} |
|
}); |
|
return { |
|
type: "bi.grid", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
columns: 1, |
|
rows: list.length, |
|
items: list |
|
}; |
|
}, |
|
|
|
resize: function () { |
|
// console.log("vertical_center布局不需要resize"); |
|
}, |
|
|
|
addItem: function (item) { |
|
// do nothing |
|
throw new Error("cannot be added"); |
|
}, |
|
|
|
update: function (opt) { |
|
return this.wrapper.update(opt); |
|
}, |
|
|
|
populate: function (items) { |
|
this.wrapper.populate.apply(this.wrapper, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.vertical_center", BI.VerticalCenterLayout);/** |
|
* 缓冲池 |
|
* @type {{Buffer: {}}} |
|
*/ |
|
|
|
(function () { |
|
var Buffer = {}; |
|
var MODE = false;// 设置缓存模式为关闭 |
|
|
|
BI.BufferPool = { |
|
put: function (name, cache) { |
|
if (BI.isNotNull(Buffer[name])) { |
|
throw new Error("Buffer Pool has the key already!"); |
|
} |
|
Buffer[name] = cache; |
|
}, |
|
|
|
get: function (name) { |
|
return Buffer[name]; |
|
} |
|
}; |
|
})();/** |
|
* 共享池 |
|
* @type {{Shared: {}}} |
|
*/ |
|
|
|
(function () { |
|
var _Shared = {}; |
|
BI.SharingPool = { |
|
_Shared: _Shared, |
|
put: function (name, shared) { |
|
_Shared[name] = shared; |
|
}, |
|
|
|
cat: function () { |
|
var args = Array.prototype.slice.call(arguments, 0), |
|
copy = _Shared; |
|
for (var i = 0; i < args.length; i++) { |
|
copy = copy && copy[args[i]]; |
|
} |
|
return copy; |
|
}, |
|
|
|
get: function () { |
|
return BI.deepClone(this.cat.apply(this, arguments)); |
|
}, |
|
|
|
remove: function (key) { |
|
delete _Shared[key]; |
|
} |
|
}; |
|
})();BI.Req = { |
|
|
|
}; |
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } |
|
|
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : factory(global.Fix = global.Fix || {}); |
|
})(this, function (exports) { |
|
'use strict'; |
|
|
|
function noop(a, b, c) {} |
|
|
|
function isNative(Ctor) { |
|
return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); |
|
} |
|
|
|
var rhashcode = /\d\.\d{4}/; |
|
|
|
//生成UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript |
|
function makeHashCode(prefix) { |
|
/* istanbul ignore next*/ |
|
prefix = prefix || 'bi'; |
|
/* istanbul ignore next*/ |
|
return String(Math.random() + Math.random()).replace(rhashcode, prefix); |
|
} |
|
|
|
var hasProto = '__proto__' in {}; |
|
|
|
var isIE = function isIE() { |
|
if (typeof navigator === "undefined") { |
|
return false; |
|
} |
|
return (/(msie|trident)/i.test(navigator.userAgent.toLowerCase()) |
|
); |
|
}; |
|
|
|
var getIEVersion = function getIEVersion() { |
|
var version = 0; |
|
if (typeof navigator === "undefined") { |
|
return false; |
|
} |
|
var agent = navigator.userAgent.toLowerCase(); |
|
var v1 = agent.match(/(?:msie\s([\w.]+))/); |
|
var v2 = agent.match(/(?:trident.*rv:([\w.]+))/); |
|
if (v1 && v2 && v1[1] && v2[1]) { |
|
version = Math.max(v1[1] * 1, v2[1] * 1); |
|
} else if (v1 && v1[1]) { |
|
version = v1[1] * 1; |
|
} else if (v2 && v2[1]) { |
|
version = v2[1] * 1; |
|
} else { |
|
version = 0; |
|
} |
|
return version; |
|
}; |
|
var isIE9Below = isIE() && getIEVersion() < 9; |
|
|
|
var _toString = Object.prototype.toString; |
|
|
|
function isPlainObject(obj) { |
|
return _toString.call(obj) === '[object Object]'; |
|
} |
|
|
|
function isConfigurable(obj, key) { |
|
var configurable = true; |
|
var property = Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(obj, key); |
|
if (property && property.configurable === false) { |
|
configurable = false; |
|
} |
|
return configurable; |
|
} |
|
|
|
function isExtensible(obj) { |
|
if (Object.isExtensible) { |
|
return Object.isExtensible(obj); |
|
} |
|
var name = ''; |
|
while (obj.hasOwnProperty(name)) { |
|
name += '?'; |
|
} |
|
obj[name] = true; |
|
var returnValue = obj.hasOwnProperty(name); |
|
delete obj[name]; |
|
return returnValue; |
|
} |
|
|
|
function remove(arr, item) { |
|
if (arr && arr.length) { |
|
var _index = arr.indexOf(item); |
|
if (_index > -1) { |
|
return arr.splice(_index, 1); |
|
} |
|
} |
|
} |
|
|
|
var bailRE = /[^\w.$]/; |
|
|
|
function parsePath(path) { |
|
if (bailRE.test(path)) { |
|
return; |
|
} |
|
var segments = path.split('.'); |
|
return function (obj) { |
|
for (var i = 0; i < segments.length; i++) { |
|
if (!obj) return; |
|
obj = obj[segments[i]]; |
|
} |
|
return obj; |
|
}; |
|
} |
|
|
|
var nextTick = function () { |
|
var callbacks = []; |
|
var pending = false; |
|
var timerFunc = void 0; |
|
|
|
function nextTickHandler() { |
|
pending = false; |
|
var copies = callbacks.slice(0); |
|
callbacks.length = 0; |
|
for (var i = 0; i < copies.length; i++) { |
|
copies[i](); |
|
} |
|
} |
|
|
|
// An asynchronous deferring mechanism. |
|
// In pre 2.4, we used to use microtasks (Promise/MutationObserver) |
|
// but microtasks actually has too high a priority and fires in between |
|
// supposedly sequential events (e.g. #4521, #6690) or even between |
|
// bubbling of the same event (#6566). Technically setImmediate should be |
|
// the ideal choice, but it's not available everywhere; and the only polyfill |
|
// that consistently queues the callback after all DOM events triggered in the |
|
// same loop is by using MessageChannel. |
|
/* istanbul ignore if */ |
|
if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { |
|
timerFunc = function timerFunc() { |
|
setImmediate(nextTickHandler); |
|
}; |
|
} else if (typeof MessageChannel !== 'undefined' && (isNative(MessageChannel) || |
|
// PhantomJS |
|
MessageChannel.toString() === '[object MessageChannelConstructor]')) { |
|
var channel = new MessageChannel(); |
|
var port = channel.port2; |
|
channel.port1.onmessage = nextTickHandler; |
|
timerFunc = function timerFunc() { |
|
port.postMessage(1); |
|
}; |
|
} else |
|
/* istanbul ignore next */ |
|
if (typeof Promise !== 'undefined' && isNative(Promise)) { |
|
// use microtask in non-DOM environments, e.g. Weex |
|
var p = Promise.resolve(); |
|
timerFunc = function timerFunc() { |
|
p.then(nextTickHandler); |
|
}; |
|
} else { |
|
// fallback to setTimeout |
|
timerFunc = function timerFunc() { |
|
setTimeout(nextTickHandler, 0); |
|
}; |
|
} |
|
|
|
return function queueNextTick(cb, ctx) { |
|
var _resolve = void 0; |
|
callbacks.push(function () { |
|
if (cb) { |
|
try { |
|
cb.call(ctx); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
} else if (_resolve) { |
|
_resolve(ctx); |
|
} |
|
}); |
|
if (!pending) { |
|
pending = true; |
|
timerFunc(); |
|
} |
|
// $flow-disable-line |
|
if (!cb && typeof Promise !== 'undefined') { |
|
return new Promise(function (resolve, reject) { |
|
_resolve = resolve; |
|
}); |
|
} |
|
}; |
|
}(); |
|
|
|
var falsy; |
|
var $$skipArray = { |
|
__ob__: falsy, |
|
$accessors: falsy, |
|
$vbthis: falsy, |
|
$vbsetter: falsy |
|
}; |
|
|
|
var uid = 0; |
|
|
|
/** |
|
* A dep is an observable that can have multiple |
|
* directives subscribing to it. |
|
*/ |
|
|
|
var Dep = function () { |
|
function Dep() { |
|
_classCallCheck(this, Dep); |
|
|
|
this.id = uid++; |
|
this.subs = []; |
|
} |
|
|
|
Dep.prototype.addSub = function addSub(sub) { |
|
this.subs.push(sub); |
|
}; |
|
|
|
Dep.prototype.removeSub = function removeSub(sub) { |
|
remove(this.subs, sub); |
|
}; |
|
|
|
Dep.prototype.depend = function depend() { |
|
if (Dep.target) { |
|
Dep.target.addDep(this); |
|
} |
|
}; |
|
|
|
Dep.prototype.notify = function notify(options) { |
|
// stabilize the subscriber list first |
|
var subs = this.subs.slice(); |
|
for (var i = 0, l = subs.length; i < l; i++) { |
|
subs[i].update(options); |
|
} |
|
}; |
|
|
|
return Dep; |
|
}(); |
|
|
|
// the current target watcher being evaluated. |
|
// this is globally unique because there could be only one |
|
// watcher being evaluated at any time. |
|
|
|
|
|
Dep.target = null; |
|
var targetStack = []; |
|
|
|
function pushTarget(_target) { |
|
if (Dep.target) targetStack.push(Dep.target); |
|
Dep.target = _target; |
|
} |
|
|
|
function popTarget() { |
|
Dep.target = targetStack.pop(); |
|
} |
|
|
|
var arrayProto = Array.prototype; |
|
var arrayMethods = []; |
|
_.each(['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'], function (method) { |
|
var original = arrayProto[method]; |
|
arrayMethods[method] = function mutator() { |
|
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { |
|
args[_key] = arguments[_key]; |
|
} |
|
|
|
var ob = this.__ob__; |
|
var inserted = void 0; |
|
switch (method) { |
|
case 'push': |
|
case 'unshift': |
|
inserted = args; |
|
break; |
|
case 'splice': |
|
inserted = args.slice(2); |
|
break; |
|
} |
|
if (inserted) inserted = ob.observeArray(inserted); |
|
switch (method) { |
|
case 'push': |
|
case 'unshift': |
|
args = inserted; |
|
break; |
|
case 'splice': |
|
args = [args[0], args[1]].concat(inserted ? inserted : []); |
|
break; |
|
} |
|
var result = original.apply(this, args); |
|
notify(ob.parent, ob.parentKey, ob.dep, true); |
|
return result; |
|
}; |
|
}); |
|
|
|
//如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8 |
|
//标准浏览器使用__defineGetter__, __defineSetter__实现 |
|
var canHideProperty = true; |
|
try { |
|
Object.defineProperty({}, '_', { |
|
value: 'x' |
|
}); |
|
delete $$skipArray.$vbsetter; |
|
delete $$skipArray.$vbthis; |
|
} catch (e) { |
|
/* istanbul ignore next*/ |
|
canHideProperty = false; |
|
} |
|
|
|
var createViewModel = Object.defineProperties; |
|
var defineProperty = void 0; |
|
|
|
var timeBucket = new Date() - 0; |
|
/* istanbul ignore if*/ |
|
if (!canHideProperty) { |
|
if ('__defineGetter__' in {}) { |
|
defineProperty = function defineProperty(obj, prop, desc) { |
|
if ('value' in desc) { |
|
obj[prop] = desc.value; |
|
} |
|
if ('get' in desc) { |
|
obj.__defineGetter__(prop, desc.get); |
|
} |
|
if ('set' in desc) { |
|
obj.__defineSetter__(prop, desc.set); |
|
} |
|
return obj; |
|
}; |
|
createViewModel = function createViewModel(obj, descs) { |
|
for (var prop in descs) { |
|
if (descs.hasOwnProperty(prop)) { |
|
defineProperty(obj, prop, descs[prop]); |
|
} |
|
} |
|
return obj; |
|
}; |
|
} |
|
/* istanbul ignore if*/ |
|
if (isIE9Below) { |
|
var VBClassPool = {}; |
|
window.execScript([// jshint ignore:line |
|
'Function parseVB(code)', '\tExecuteGlobal(code)', 'End Function' //转换一段文本为VB代码 |
|
].join('\n'), 'VBScript'); |
|
|
|
var VBMediator = function VBMediator(instance, accessors, name, value) { |
|
// jshint ignore:line |
|
var accessor = accessors[name]; |
|
if (arguments.length === 4) { |
|
accessor.set.call(instance, value); |
|
} else { |
|
return accessor.get.call(instance); |
|
} |
|
}; |
|
createViewModel = function createViewModel(name, accessors, properties) { |
|
// jshint ignore:line |
|
var buffer = []; |
|
buffer.push('\tPrivate [$vbsetter]', '\tPublic [$accessors]', '\tPublic Default Function [$vbthis](ac' + timeBucket + ', s' + timeBucket + ')', '\t\tSet [$accessors] = ac' + timeBucket + ': set [$vbsetter] = s' + timeBucket, '\t\tSet [$vbthis] = Me', //链式调用 |
|
'\tEnd Function'); |
|
//添加普通属性,因为VBScript对象不能像JS那样随意增删属性,必须在这里预先定义好 |
|
var uniq = { |
|
$vbthis: true, |
|
$vbsetter: true, |
|
$accessors: true |
|
}; |
|
for (name in $$skipArray) { |
|
if (!uniq[name]) { |
|
buffer.push('\tPublic [' + name + ']'); |
|
uniq[name] = true; |
|
} |
|
} |
|
//添加访问器属性 |
|
for (name in accessors) { |
|
if (uniq[name]) { |
|
continue; |
|
} |
|
uniq[name] = true; |
|
buffer.push( |
|
//由于不知对方会传入什么,因此set, let都用上 |
|
'\tPublic Property Let [' + name + '](val' + timeBucket + ')', //setter |
|
'\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Set [' + name + '](val' + timeBucket + ')', //setter |
|
'\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Get [' + name + ']', //getter |
|
'\tOn Error Resume Next', //必须优先使用set语句,否则它会误将数组当字符串返回 |
|
'\t\tSet[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tIf Err.Number <> 0 Then', '\t\t[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tEnd If', '\tOn Error Goto 0', '\tEnd Property'); |
|
} |
|
|
|
for (name in properties) { |
|
if (!uniq[name]) { |
|
uniq[name] = true; |
|
buffer.push('\tPublic [' + name + ']'); |
|
} |
|
} |
|
|
|
buffer.push('\tPublic [hasOwnProperty]'); |
|
buffer.push('End Class'); |
|
var body = buffer.join('\r\n'); |
|
var className = VBClassPool[body]; |
|
if (!className) { |
|
className = makeHashCode('VBClass'); |
|
window.parseVB('Class ' + className + body); |
|
window.parseVB(['Function ' + className + 'Factory(acc, vbm)', //创建实例并传入两个关键的参数 |
|
'\tDim o', '\tSet o = (New ' + className + ')(acc, vbm)', '\tSet ' + className + 'Factory = o', 'End Function'].join('\r\n')); |
|
VBClassPool[body] = className; |
|
} |
|
var ret = window[className + 'Factory'](accessors, VBMediator); //得到其产品 |
|
return ret; //得到其产品 |
|
}; |
|
} |
|
} |
|
|
|
var createViewModel$1 = createViewModel; |
|
|
|
var arrayKeys = _.keys(arrayMethods); |
|
|
|
var observerState = { |
|
shouldConvert: true |
|
}; |
|
|
|
function def(obj, key, val, enumerable) { |
|
Object.defineProperty(obj, key, { |
|
value: val, |
|
enumerable: !!enumerable, |
|
writable: true, |
|
configurable: true |
|
}); |
|
} |
|
|
|
/** |
|
* Observer class that are attached to each observed |
|
* object. Once attached, the observer converts target |
|
* object's property keys into getter/setters that |
|
* collect dependencies and dispatches updates. |
|
*/ |
|
|
|
var Observer = function () { |
|
function Observer(value) { |
|
_classCallCheck(this, Observer); |
|
|
|
this.value = value; |
|
this.dep = new Dep(); |
|
this.vmCount = 0; |
|
if (_.isArray(value)) { |
|
var augment = hasProto ? protoAugment : copyAugment; |
|
augment(value, arrayMethods, arrayKeys); |
|
this.model = this.observeArray(value); |
|
} else { |
|
this.model = this.walk(value); |
|
} |
|
if (isIE9Below) { |
|
this.model['__ob__'] = this; |
|
} else { |
|
def(this.model, "__ob__", this); |
|
} |
|
} |
|
|
|
Observer.prototype.walk = function walk(obj) { |
|
return defineReactive(obj, this); |
|
}; |
|
|
|
Observer.prototype.observeArray = function observeArray(items) { |
|
for (var i = 0, l = items.length; i < l; i++) { |
|
var ob = observe(items[i], this, i); |
|
items[i] = ob ? ob.model : items[i]; |
|
} |
|
return items; |
|
}; |
|
|
|
return Observer; |
|
}(); |
|
|
|
function protoAugment(target, src, keys) { |
|
/* eslint-disable no-proto */ |
|
target.__proto__ = src; |
|
/* eslint-enable no-proto */ |
|
} |
|
|
|
/* istanbul ignore next */ |
|
function copyAugment(target, src, keys) { |
|
for (var i = 0, l = keys.length; i < l; i++) { |
|
var key = keys[i]; |
|
target[key] = src[key]; |
|
} |
|
} |
|
|
|
function observe(value, parentObserver, parentKey) { |
|
if (!_.isObject(value)) { |
|
return; |
|
} |
|
var ob = void 0; |
|
if (value.__ob__ instanceof Observer) { |
|
ob = value.__ob__; |
|
} else if (observerState.shouldConvert && isExtensible(value) && (_.isArray(value) || isPlainObject(value))) { |
|
ob = new Observer(value); |
|
} |
|
if (ob) { |
|
ob.parent = parentObserver || ob.parent; |
|
ob.parentKey = parentKey; |
|
} |
|
return ob; |
|
} |
|
|
|
function notify(observer, key, dep, refresh) { |
|
dep.notify({ observer: observer, key: key, refresh: refresh }); |
|
if (observer) { |
|
//触发a.*绑定的依赖 |
|
_.each(observer._deps, function (dep) { |
|
dep.notify({ observer: observer, key: key }); |
|
}); |
|
//触发a.**绑定的依赖 |
|
var parent = observer, |
|
root = observer, |
|
route = key || ""; |
|
while (parent) { |
|
_.each(parent._scopeDeps, function (dep) { |
|
dep.notify({ observer: observer, key: key }); |
|
}); |
|
if (parent.parentKey != null) { |
|
route = parent.parentKey + '.' + route; |
|
} |
|
root = parent; |
|
parent = parent.parent; |
|
} |
|
for (var _key2 in root._globalDeps) { |
|
var reg = new RegExp(_key2); |
|
if (reg.test(route)) { |
|
root._globalDeps[_key2].notify({ observer: observer, key: _key2 }); |
|
} |
|
} |
|
} |
|
} |
|
|
|
function defineReactive(obj, observer, shallow) { |
|
var props = {}; |
|
var model = void 0; |
|
// if (typeof Proxy === 'function') { |
|
// const deps = {}, childObs = {}, cache = {} |
|
// _.each(obj, function (val, key) { |
|
// if (key in $$skipArray) { |
|
// return |
|
// } |
|
// cache[key] = val |
|
// const dep = deps[key] = (observer && observer['__dep' + key]) || new Dep() |
|
// observer && (observer['__dep' + key] = dep) |
|
// childObs[key] = !shallow && observe(val, observer, key) |
|
// }) |
|
// return model = new Proxy(props, { |
|
// has: function (target, key) { |
|
// return key in obj; |
|
// }, |
|
// get: function (target, key) { |
|
// if (key in $$skipArray) { |
|
// return target[key] |
|
// } |
|
// const value = cache[key] |
|
// if (Dep.target) { |
|
// deps[key].depend() |
|
// if (childObs[key]) { |
|
// childObs[key].dep.depend() |
|
// if (_.isArray(value)) { |
|
// dependArray(value) |
|
// } |
|
// } |
|
// } |
|
// return value |
|
// }, |
|
// set: function (target, key, newVal) { |
|
// if (key in $$skipArray) { |
|
// return target[key] = newVal |
|
// } |
|
// const value = cache[key], dep = deps[key] |
|
// if (newVal === value || (newVal !== newVal && value !== value)) { |
|
// return newVal |
|
// } |
|
// cache[key] = newVal |
|
// childObs[key] = !shallow && observe(newVal, observer, key) |
|
// obj[key] = childObs[key] ? childObs[key].model : newVal |
|
// notify(model, key, dep) |
|
// return obj[key] |
|
// } |
|
// }) |
|
// } |
|
_.each(obj, function (val, key) { |
|
if (key in $$skipArray) { |
|
return; |
|
} |
|
var configurable = isConfigurable(obj, key); |
|
var dep = observer && observer['__dep' + key] || new Dep(); |
|
observer && (observer['__dep' + key] = dep); |
|
var childOb = configurable && !shallow && observe(val, observer, key); |
|
props[key] = { |
|
enumerable: true, |
|
configurable: true, |
|
get: function reactiveGetter() { |
|
var value = childOb ? childOb.model : val; |
|
if (Dep.target) { |
|
dep.depend(); |
|
if (childOb) { |
|
childOb.dep.depend(); |
|
if (_.isArray(value)) { |
|
dependArray(value); |
|
} |
|
} |
|
} |
|
return value; |
|
}, |
|
set: function reactiveSetter(newVal) { |
|
var value = childOb ? childOb.model : val; |
|
if (newVal === value || newVal !== newVal && value !== value) { |
|
return; |
|
} |
|
val = newVal; |
|
childOb = configurable && !shallow && observe(newVal, observer, key); |
|
if (childOb && value && value.__ob__) { |
|
childOb._scopeDeps = value.__ob__._scopeDeps; |
|
childOb._deps = value.__ob__._deps; |
|
} |
|
obj[key] = childOb ? childOb.model : newVal; |
|
notify(model.__ob__, key, dep); |
|
} |
|
}; |
|
}); |
|
return model = createViewModel$1(obj, props); |
|
} |
|
|
|
/** |
|
* Set a property on an object. Adds the new property and |
|
* triggers change notification if the property doesn't |
|
* already exist. |
|
*/ |
|
function set(target, key, val) { |
|
if (_.isArray(target)) { |
|
target.length = Math.max(target.length, key); |
|
target.splice(key, 1, val); |
|
return val; |
|
} |
|
if (_.has(target, key)) { |
|
target[key] = val; |
|
return val; |
|
} |
|
var ob = target.__ob__; |
|
if (!ob) { |
|
target[key] = val; |
|
return val; |
|
} |
|
ob.value[key] = val; |
|
target = defineReactive(ob.value, ob); |
|
notify(ob, key, ob.dep); |
|
return target; |
|
} |
|
|
|
/** |
|
* Delete a property and trigger change if necessary. |
|
*/ |
|
function del(target, key) { |
|
if (_.isArray(target)) { |
|
target.splice(key, 1); |
|
return; |
|
} |
|
var ob = target.__ob__; |
|
if (!_.has(target, key)) { |
|
return; |
|
} |
|
if (!ob) { |
|
delete target[key]; |
|
return target; |
|
} |
|
delete ob.value[key]; |
|
target = defineReactive(ob.value, ob); |
|
notify(ob, key, ob.dep); |
|
return target; |
|
} |
|
|
|
/** |
|
* Collect dependencies on array elements when the array is touched, since |
|
* we cannot intercept array element access like property getters. |
|
*/ |
|
function dependArray(value) { |
|
for (var e, i = 0, l = value.length; i < l; i++) { |
|
e = value[i]; |
|
e && e.__ob__ && e.__ob__.dep.depend(); |
|
if (_.isArray(e)) { |
|
dependArray(e); |
|
} |
|
} |
|
} |
|
|
|
var queue = []; |
|
var activatedChildren = []; |
|
var has = {}; |
|
var waiting = false; |
|
var flushing = false; |
|
var index = 0; |
|
|
|
function resetSchedulerState() { |
|
index = queue.length = activatedChildren.length = 0; |
|
has = {}; |
|
waiting = flushing = false; |
|
} |
|
|
|
function flushSchedulerQueue() { |
|
flushing = true; |
|
var watcher = void 0, |
|
id = void 0, |
|
options = void 0; |
|
|
|
// Sort queue before flush. |
|
// This ensures that: |
|
// 1. Components are updated from parent to child. (because parent is always |
|
// created before the child) |
|
// 2. A component's user watchers are run before its render watcher (because |
|
// user watchers are created before the render watcher) |
|
// 3. If a component is destroyed during a parent component's watcher run, |
|
// its watchers can be skipped. |
|
queue.sort(function (a, b) { |
|
return a.id - b.id; |
|
}); |
|
|
|
// do not cache length because more watchers might be pushed |
|
// as we run existing watchers |
|
for (index = 0; index < queue.length; index++) { |
|
watcher = queue[index].watcher; |
|
options = queue[index].options; |
|
id = watcher.id; |
|
has[id] = null; |
|
watcher.run(options); |
|
} |
|
|
|
resetSchedulerState(); |
|
} |
|
|
|
function queueWatcher(watcher, options) { |
|
var id = watcher.id; |
|
if (has[id] == null) { |
|
has[id] = true; |
|
if (!flushing) { |
|
queue.push({ watcher: watcher, options: options }); |
|
} else { |
|
// if already flushing, splice the watcher based on its id |
|
// if already past its id, it will be run next immediately. |
|
var i = queue.length - 1; |
|
while (i > index && queue[i].watcher.id > watcher.id) { |
|
i--; |
|
} |
|
queue.splice(i + 1, 0, { watcher: watcher, options: options }); |
|
} |
|
// queue the flush |
|
if (!waiting) { |
|
waiting = true; |
|
nextTick(flushSchedulerQueue); |
|
} |
|
} |
|
} |
|
|
|
var uid$1 = 0; |
|
|
|
var Watcher = function () { |
|
function Watcher(vm, expOrFn, cb, options) { |
|
_classCallCheck(this, Watcher); |
|
|
|
this.vm = vm; |
|
// vm._watchers || (vm._watchers = []) |
|
// vm._watchers.push(this) |
|
// options |
|
if (options) { |
|
this.deep = !!options.deep; |
|
this.user = !!options.user; |
|
this.lazy = !!options.lazy; |
|
this.sync = !!options.sync; |
|
} else { |
|
this.deep = this.user = this.lazy = this.sync = false; |
|
} |
|
this.cb = cb; |
|
this.id = ++uid$1; // uid for batching |
|
this.active = true; |
|
this.dirty = this.lazy; // for lazy watchers |
|
this.deps = []; |
|
this.newDeps = []; |
|
this.depIds = new Set(); |
|
this.newDepIds = new Set(); |
|
this.expression = ''; |
|
// parse expression for getter |
|
if (typeof expOrFn === 'function') { |
|
this.getter = expOrFn; |
|
} else { |
|
this.getter = parsePath(expOrFn); |
|
if (!this.getter) { |
|
this.getter = function () {}; |
|
} |
|
} |
|
this.value = this.lazy ? undefined : this.get(); |
|
} |
|
|
|
Watcher.prototype.get = function get() { |
|
pushTarget(this); |
|
var value = void 0; |
|
var vm = this.vm; |
|
try { |
|
value = this.getter.call(vm, vm); |
|
} catch (e) { |
|
// if (this.user) { |
|
// } else { |
|
// console.error(e) |
|
// } |
|
} finally { |
|
// "touch" every property so they are all tracked as |
|
// dependencies for deep watching |
|
if (this.deep) { |
|
traverse(value); |
|
} |
|
popTarget(); |
|
this.cleanupDeps(); |
|
} |
|
return value; |
|
}; |
|
|
|
Watcher.prototype.addDep = function addDep(dep) { |
|
var id = dep.id; |
|
if (!this.newDepIds.has(id)) { |
|
this.newDepIds.add(id); |
|
this.newDeps.push(dep); |
|
if (!this.depIds.has(id)) { |
|
dep.addSub(this); |
|
} |
|
} |
|
}; |
|
|
|
Watcher.prototype.cleanupDeps = function cleanupDeps() { |
|
var i = this.deps.length; |
|
while (i--) { |
|
var dep = this.deps[i]; |
|
if (!this.newDepIds.has(dep.id)) { |
|
dep.removeSub(this); |
|
} |
|
} |
|
var tmp = this.depIds; |
|
this.depIds = this.newDepIds; |
|
this.newDepIds = tmp; |
|
this.newDepIds.clear(); |
|
tmp = this.deps; |
|
this.deps = this.newDeps; |
|
this.newDeps = tmp; |
|
this.newDeps.length = 0; |
|
}; |
|
|
|
Watcher.prototype.update = function update(options) { |
|
/* istanbul ignore else */ |
|
if (this.lazy) { |
|
this.dirty = true; |
|
} else if (this.sync) { |
|
this.run(options); |
|
} else { |
|
queueWatcher(this, options); |
|
} |
|
}; |
|
|
|
Watcher.prototype.run = function run(options) { |
|
if (this.active) { |
|
var value = this.get(); |
|
if (value !== this.value || |
|
// Deep watchers and watchers on Object/Arrays should fire even |
|
// when the value is the same, because the value may |
|
// have mutated. |
|
options && options.refresh || this.deep) { |
|
// set new value |
|
var oldValue = this.value; |
|
this.value = value; |
|
if (this.user) { |
|
try { |
|
this.cb.call(this.vm, value, oldValue, options); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
} else { |
|
try { |
|
this.cb.call(this.vm, value, oldValue, options); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
|
|
Watcher.prototype.evaluate = function evaluate() { |
|
this.value = this.get(); |
|
this.dirty = false; |
|
}; |
|
|
|
Watcher.prototype.depend = function depend() { |
|
var i = this.deps.length; |
|
while (i--) { |
|
this.deps[i].depend(); |
|
} |
|
}; |
|
|
|
Watcher.prototype.teardown = function teardown() { |
|
if (this.active) { |
|
// remove self from vm's watcher list |
|
// this is a somewhat expensive operation so we skip it |
|
// if the vm is being destroyed. |
|
remove(this.vm._watchers, this); |
|
var i = this.deps.length; |
|
while (i--) { |
|
this.deps[i].removeSub(this); |
|
} |
|
this.active = false; |
|
} |
|
}; |
|
|
|
return Watcher; |
|
}(); |
|
|
|
var seenObjects = new Set(); |
|
|
|
function traverse(val) { |
|
seenObjects.clear(); |
|
_traverse(val, seenObjects); |
|
} |
|
|
|
function _traverse(val, seen) { |
|
var i = void 0, |
|
keys = void 0; |
|
var isA = _.isArray(val); |
|
if (!isA && !_.isObject(val)) { |
|
return; |
|
} |
|
if (val.__ob__) { |
|
var depId = val.__ob__.dep.id; |
|
if (seen.has(depId)) { |
|
return; |
|
} |
|
seen.add(depId); |
|
} |
|
if (isA) { |
|
i = val.length; |
|
while (i--) { |
|
_traverse(val[i], seen); |
|
} |
|
} else { |
|
keys = _.keys(val); |
|
i = keys.length; |
|
while (i--) { |
|
_traverse(val[keys[i]], seen); |
|
} |
|
} |
|
} |
|
|
|
var falsy$1; |
|
var operators = { |
|
'||': falsy$1, |
|
'&&': falsy$1, |
|
'(': falsy$1, |
|
')': falsy$1 |
|
}; |
|
|
|
function runBinaryFunction(binarys) { |
|
var expr = ''; |
|
for (var i = 0, len = binarys.length; i < len; i++) { |
|
if (_.isBoolean(binarys[i]) || _.has(operators, binarys[i])) { |
|
expr += binarys[i]; |
|
} else { |
|
expr += 'false'; |
|
} |
|
} |
|
return new Function('return ' + expr)(); |
|
} |
|
|
|
function routeToRegExp(route) { |
|
route = route.replace(/\*./g, '[a-zA-Z0-9_]+.'); |
|
return '^' + route + '$'; |
|
} |
|
|
|
function watch(model, expOrFn, cb, options) { |
|
if (isPlainObject(cb)) { |
|
options = cb; |
|
cb = cb.handler; |
|
} |
|
if (typeof cb === 'string') { |
|
cb = model[cb]; |
|
} |
|
options = options || {}; |
|
options.user = true; |
|
var exps = void 0; |
|
if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && !/\*/.test(expOrFn)) { |
|
var watcher = new Watcher(model, expOrFn, cb, options); |
|
if (options.immediate) { |
|
cb(watcher.value); |
|
} |
|
return function unwatchFn() { |
|
watcher.teardown(); |
|
}; |
|
} |
|
var watchers = []; |
|
var fns = exps.slice(); |
|
var complete = false, |
|
running = false; |
|
var callback = function callback(index, newValue, oldValue, attrs) { |
|
if (complete === true) { |
|
return; |
|
} |
|
fns[index] = true; |
|
if (runBinaryFunction(fns)) { |
|
complete = true; |
|
cb(newValue, oldValue, attrs); |
|
} |
|
if (options && options.sync) { |
|
complete = false; |
|
running = false; |
|
fns = exps.slice(); |
|
} else { |
|
if (!running) { |
|
running = true; |
|
nextTick(function () { |
|
complete = false; |
|
running = false; |
|
fns = exps.slice(); |
|
}); |
|
} |
|
} |
|
}; |
|
_.each(exps, function (exp, i) { |
|
if (_.has(operators, exp)) { |
|
return; |
|
} |
|
//a.**或a.*形式 |
|
if (/^[1-9a-zA-Z.]+(\*\*$|\*$)/.test(exp) || exp === "**") { |
|
var isGlobal = /\*\*$/.test(exp); |
|
if (isGlobal) { |
|
//a.**的形式 |
|
exp = exp.replace(".**", ""); |
|
} else { |
|
//a.*的形式 |
|
exp = exp.replace(".*", ""); |
|
} |
|
var getter = exp === "**" ? function (m) { |
|
return m; |
|
} : parsePath(exp); |
|
var v = getter.call(model, model); |
|
var dep = new Dep(); |
|
if (isGlobal) { |
|
(v.__ob__._scopeDeps || (v.__ob__._scopeDeps = [])).push(dep); |
|
} else { |
|
(v.__ob__._deps || (v.__ob__._deps = [])).push(dep); |
|
} |
|
var w = new Watcher(model, function () { |
|
dep.depend(); |
|
return NaN; |
|
}, function (newValue, oldValue, attrs) { |
|
callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); |
|
}, options); |
|
watchers.push(function unwatchFn() { |
|
w.teardown(); |
|
v.__ob__._scopeDeps && remove(v.__ob__._scopeDeps, dep); |
|
v.__ob__._deps && remove(v.__ob__._deps, dep); |
|
}); |
|
return; |
|
} |
|
if (/\*\*$|\*$/.test(exp)) { |
|
throw new Error('not support'); |
|
} |
|
//其他含有*的情况,如*.a,*.*.a,a.*.a |
|
if (/\*/.test(exp)) { |
|
var currentModel = model; |
|
//先获取到能获取到的对象 |
|
var paths = exp.split("."); |
|
for (var _i = 0, len = paths.length; _i < len; _i++) { |
|
if (paths[_i] === "*") { |
|
break; |
|
} |
|
currentModel = model[paths[_i]]; |
|
} |
|
exp = exp.substr(exp.indexOf("*")); |
|
//补全路径 |
|
var parent = currentModel.__ob__.parent, |
|
root = currentModel.__ob__; |
|
while (parent) { |
|
exp = '*.' + exp; |
|
root = parent; |
|
parent = parent.parent; |
|
} |
|
var regStr = routeToRegExp(exp); |
|
var _dep = new Dep(); |
|
root._globalDeps || (root._globalDeps = {}); |
|
root._globalDeps[regStr] = _dep; |
|
|
|
var _w = new Watcher(currentModel, function () { |
|
_dep.depend(); |
|
return NaN; |
|
}, function (newValue, oldValue, attrs) { |
|
callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); |
|
}, options); |
|
watchers.push(function unwatchFn() { |
|
_w.teardown(); |
|
root._globalDeps && delete root._globalDeps[regStr]; |
|
}); |
|
return; |
|
} |
|
var watcher = new Watcher(model, exp, function (newValue, oldValue, attrs) { |
|
callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); |
|
}, options); |
|
watchers.push(function unwatchFn() { |
|
watcher.teardown(); |
|
}); |
|
}); |
|
return watchers; |
|
} |
|
|
|
var mixinInjection = {}; |
|
|
|
function getMixins(type) { |
|
return mixinInjection[type]; |
|
} |
|
|
|
function mixin(xtype, cls) { |
|
mixinInjection[xtype] = _.cloneDeep(cls); |
|
} |
|
|
|
var computedWatcherOptions = { lazy: true }; |
|
|
|
function initState(vm, state) { |
|
if (state) { |
|
vm.$$state = observe(state).model; |
|
} |
|
} |
|
|
|
function initComputed(vm, computed) { |
|
var watchers = vm._computedWatchers = {}; |
|
|
|
defineComputed(vm, computed); |
|
|
|
for (var key in computed) { |
|
var userDef = computed[key], |
|
context = vm.$$model ? vm.model : vm; |
|
var getter = typeof userDef === "function" ? _.bind(userDef, context) : _.bind(userDef.get, context); |
|
|
|
watchers[key] = new Watcher(vm.$$computed, getter || noop, noop, computedWatcherOptions); |
|
} |
|
} |
|
|
|
function defineComputed(vm, computed) { |
|
var props = {}; |
|
// if (typeof Proxy === 'function') { |
|
// return vm.$$computed = new Proxy(props, { |
|
// has: function (target, key) { |
|
// return computed && key in computed |
|
// }, |
|
// get: function (target, key) { |
|
// return createComputedGetter(vm, key)() |
|
// } |
|
// }) |
|
// } |
|
var shouldCache = true; |
|
for (var key in computed) { |
|
if (!(key in vm)) { |
|
var sharedPropertyDefinition = { |
|
enumerable: true, |
|
configurable: true, |
|
get: noop, |
|
set: noop |
|
}; |
|
var userDef = computed[key]; |
|
if (typeof userDef === "function") { |
|
sharedPropertyDefinition.get = createComputedGetter(vm, key); |
|
sharedPropertyDefinition.set = noop; |
|
} else { |
|
sharedPropertyDefinition.get = userDef.get ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : userDef.get : noop; |
|
sharedPropertyDefinition.set = userDef.set ? userDef.set : noop; |
|
} |
|
|
|
props[key] = sharedPropertyDefinition; |
|
} |
|
} |
|
vm.$$computed = createViewModel$1({}, props); |
|
} |
|
|
|
function createComputedGetter(vm, key) { |
|
return function computedGetter() { |
|
var watcher = vm._computedWatchers && vm._computedWatchers[key]; |
|
if (watcher) { |
|
if (watcher.dirty) { |
|
watcher.evaluate(); |
|
} |
|
if (Dep.target) { |
|
watcher.depend(); |
|
} |
|
return watcher.value; |
|
} |
|
}; |
|
} |
|
|
|
function initWatch(vm, watch$$1) { |
|
vm._watchers || (vm._watchers = []); |
|
for (var key in watch$$1) { |
|
var handler = watch$$1[key]; |
|
if (_.isArray(handler)) { |
|
for (var i = 0; i < handler.length; i++) { |
|
vm._watchers.push(createWatcher(vm, key, handler[i])); |
|
} |
|
} else { |
|
vm._watchers.push(createWatcher(vm, key, handler)); |
|
} |
|
} |
|
} |
|
|
|
function createWatcher(vm, keyOrFn, cb, options) { |
|
if (isPlainObject(cb)) { |
|
options = cb; |
|
cb = cb.handler; |
|
} |
|
if (typeof cb === 'string') { |
|
cb = vm[cb]; |
|
} |
|
return watch(vm.model, keyOrFn, _.bind(cb, vm.$$model ? vm.model : vm), options); |
|
} |
|
|
|
function initMethods(vm, methods) { |
|
for (var key in methods) { |
|
vm[key] = methods[key] == null ? noop : _.bind(methods[key], vm.$$model ? vm.model : vm); |
|
} |
|
} |
|
|
|
function initMixins(vm, mixins) { |
|
mixins = mixins || []; |
|
|
|
_.each(mixins.reverse(), function (mixinType) { |
|
var mixin$$1 = getMixins(mixinType); |
|
|
|
for (var key in mixin$$1) { |
|
if (typeof mixin$$1[key] !== "function") continue; |
|
|
|
if (_.has(vm, key)) continue; |
|
|
|
vm[key] = _.bind(mixin$$1[key], vm.$$model ? vm.model : vm); |
|
} |
|
}); |
|
} |
|
|
|
function defineProps(vm, keys) { |
|
var props = {}; |
|
// if (typeof Proxy === 'function') { |
|
// return vm.model = new Proxy(props, { |
|
// has: function (target, key) { |
|
// return keys.indexOf(key) > -1; |
|
// }, |
|
// get: function (target, key) { |
|
// if (key in $$skipArray) { |
|
// return props[key] |
|
// } |
|
// if (vm.$$computed && key in vm.$$computed) { |
|
// return vm.$$computed[key] |
|
// } |
|
// if (vm.$$state && key in vm.$$state) { |
|
// return vm.$$state[key] |
|
// } |
|
// return vm.$$model[key] |
|
// }, |
|
// set: function (target, key, val) { |
|
// if (key in $$skipArray) { |
|
// return props[key] = val |
|
// } |
|
// if (vm.$$state && key in vm.$$state) { |
|
// return vm.$$state[key] = val |
|
// } |
|
// if (vm.$$model && key in vm.$$model) { |
|
// return vm.$$model[key] = val |
|
// } |
|
// } |
|
// }) |
|
// } |
|
|
|
var _loop = function _loop(i, len) { |
|
var key = keys[i]; |
|
if (!(key in $$skipArray)) { |
|
props[key] = { |
|
enumerable: true, |
|
configurable: true, |
|
get: function get() { |
|
if (vm.$$computed && key in vm.$$computed) { |
|
return vm.$$computed[key]; |
|
} |
|
if (vm.$$state && key in vm.$$state) { |
|
return vm.$$state[key]; |
|
} |
|
if (vm.$$model && key in vm.$$model) { |
|
return vm.$$model[key]; |
|
} |
|
var p = vm._parent; |
|
while (p) { |
|
if (p.$$context && key in p.$$context) { |
|
return p.$$context[key]; |
|
} |
|
p = p._parent; |
|
} |
|
}, |
|
set: function set(val) { |
|
if (vm.$$state && key in vm.$$state) { |
|
return vm.$$state[key] = val; |
|
} |
|
if (vm.$$model && key in vm.$$model) { |
|
return vm.$$model[key] = val; |
|
} |
|
var p = vm._parent; |
|
while (p) { |
|
if (p.$$context && key in p.$$context) { |
|
return p.$$context[key] = val; |
|
} |
|
p = p._parent; |
|
} |
|
} |
|
}; |
|
} |
|
}; |
|
|
|
for (var i = 0, len = keys.length; i < len; i++) { |
|
_loop(i, len); |
|
} |
|
vm.model = createViewModel$1({}, props); |
|
} |
|
|
|
function defineContext(vm, keys) { |
|
var props = {}; |
|
|
|
var _loop2 = function _loop2(i, len) { |
|
var key = keys[i]; |
|
if (!(key in $$skipArray)) { |
|
props[key] = { |
|
enumerable: true, |
|
configurable: true, |
|
get: function get() { |
|
return vm.model[key]; |
|
}, |
|
set: function set(val) { |
|
return vm.model[key] = val; |
|
} |
|
}; |
|
} |
|
}; |
|
|
|
for (var i = 0, len = keys.length; i < len; i++) { |
|
_loop2(i, len); |
|
} |
|
vm.$$context = createViewModel$1({}, props); |
|
} |
|
|
|
var Model = function () { |
|
function Model() { |
|
_classCallCheck(this, Model); |
|
} |
|
|
|
Model.prototype._constructor = function _constructor(model) { |
|
if (model instanceof Observer || model instanceof Model) { |
|
model = model.model; |
|
} |
|
if (model && model.__ob__) { |
|
this.$$model = model; |
|
} else { |
|
this.options = model || {}; |
|
} |
|
this._parent = Model.target; |
|
var state = _.isFunction(this.state) ? this.state() : this.state; |
|
var computed = this.computed; |
|
var context = this.context; |
|
var childContext = this.childContext; |
|
var watch$$1 = this.watch; |
|
var actions = this.actions; |
|
var keys = _.keys(this.$$model).concat(_.keys(state)).concat(_.keys(computed)).concat(context || []); |
|
var mixins = this.mixins; |
|
defineProps(this, keys); |
|
childContext && defineContext(this, childContext); |
|
this.$$model && (this.model.__ob__ = this.$$model.__ob__); |
|
initMixins(this, mixins); |
|
this.init(); |
|
initState(this, state); |
|
initComputed(this, computed); |
|
initWatch(this, watch$$1); |
|
initMethods(this, actions); |
|
this.created && this.created(); |
|
if (this.$$model) { |
|
return this.model; |
|
} |
|
}; |
|
|
|
Model.prototype._init = function _init() {}; |
|
|
|
Model.prototype.init = function init() { |
|
this._init(); |
|
}; |
|
|
|
Model.prototype.destroy = function destroy() { |
|
for (var _key3 in this._computedWatchers) { |
|
this._computedWatchers[_key3].teardown(); |
|
} |
|
_.each(this._watchers, function (unwatches) { |
|
unwatches = _.isArray(unwatches) ? unwatches : [unwatches]; |
|
_.each(unwatches, function (unwatch) { |
|
unwatch(); |
|
}); |
|
}); |
|
this._watchers && (this._watchers = []); |
|
this.destroyed && this.destroyed(); |
|
this.$$model = null; |
|
this.$$computed = null; |
|
this.$$state = null; |
|
}; |
|
|
|
return Model; |
|
}(); |
|
|
|
function toJSON(model) { |
|
var result = void 0; |
|
if (_.isArray(model)) { |
|
result = []; |
|
for (var i = 0, len = model.length; i < len; i++) { |
|
result[i] = toJSON(model[i]); |
|
} |
|
} else if (model && isPlainObject(model)) { |
|
result = {}; |
|
for (var _key4 in model) { |
|
if (!_.has($$skipArray, _key4)) { |
|
result[_key4] = toJSON(model[_key4]); |
|
} |
|
} |
|
} else { |
|
result = model; |
|
} |
|
return result; |
|
} |
|
|
|
function define(model) { |
|
return new Observer(model).model; |
|
} |
|
var version = '2.0'; |
|
|
|
exports.define = define; |
|
exports.version = version; |
|
exports.$$skipArray = $$skipArray; |
|
exports.mixin = mixin; |
|
exports.Model = Model; |
|
exports.observerState = observerState; |
|
exports.Observer = Observer; |
|
exports.observe = observe; |
|
exports.notify = notify; |
|
exports.defineReactive = defineReactive; |
|
exports.set = set; |
|
exports.del = del; |
|
exports.Watcher = Watcher; |
|
exports.pushTarget = pushTarget; |
|
exports.popTarget = popTarget; |
|
exports.watch = watch; |
|
exports.toJSON = toJSON; |
|
|
|
exports.__esModule = true; |
|
});/** |
|
* 当没有元素时有提示信息的view |
|
* |
|
* Created by GUY on 2015/9/8. |
|
* @class BI.Pane |
|
* @extends BI.Widget |
|
* @abstract |
|
*/ |
|
BI.Pane = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.Pane.superclass._defaultConfig.apply(this, arguments), { |
|
_baseCls: "bi-pane", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
overlap: true, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_assertTip: function () { |
|
var o = this.options; |
|
if (!this._tipText) { |
|
this._tipText = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "bi-tips", |
|
text: o.tipText, |
|
height: 25 |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute_center_adapt", |
|
element: this, |
|
items: [this._tipText] |
|
}); |
|
} |
|
}, |
|
|
|
loading: function () { |
|
var self = this, o = this.options; |
|
var isIE = BI.isIE(); |
|
var loadingAnimation = BI.createWidget({ |
|
type: "bi.horizontal", |
|
cls: "bi-loading-widget" + (isIE ? " wave-loading hack" : ""), |
|
height: 30, |
|
width: 30, |
|
hgap: 5, |
|
vgap: 2.5, |
|
items: isIE ? [] : [{ |
|
type: "bi.layout", |
|
cls: "animate-rect rect1", |
|
height: 25, |
|
width: 3 |
|
}, { |
|
type: "bi.layout", |
|
cls: "animate-rect rect2", |
|
height: 25, |
|
width: 3 |
|
}, { |
|
type: "bi.layout", |
|
cls: "animate-rect rect3", |
|
height: 25, |
|
width: 3 |
|
}] |
|
}); |
|
// pane在同步方式下由items决定tipText的显示与否 |
|
// loading的异步情况下由loaded后对面板的populate的时机决定 |
|
this.setTipVisible(false); |
|
if (o.overlap === true) { |
|
if (!BI.Layers.has(this.getName())) { |
|
BI.createWidget({ |
|
type: "bi.absolute_center_adapt", |
|
cls: "loading-container", |
|
items: [{ |
|
el: loadingAnimation |
|
}], |
|
element: BI.Layers.make(this.getName(), this) |
|
}); |
|
} |
|
BI.Layers.show(self.getName()); |
|
} else if (BI.isNull(this._loading)) { |
|
this._loading = loadingAnimation; |
|
this._loading.element.css("zIndex", 1); |
|
BI.createWidget({ |
|
type: "bi.absolute_center_adapt", |
|
element: this, |
|
cls: "loading-container", |
|
items: [{ |
|
el: this._loading, |
|
left: 0, |
|
right: 0, |
|
top: 0 |
|
}] |
|
}); |
|
} |
|
this.element.addClass("loading-status"); |
|
}, |
|
|
|
loaded: function () { |
|
var self = this, o = this.options; |
|
BI.Layers.remove(self.getName()); |
|
this._loading && this._loading.destroy(); |
|
this._loading && (this._loading = null); |
|
o.onLoaded(); |
|
self.fireEvent(BI.Pane.EVENT_LOADED); |
|
this.element.removeClass("loading-status"); |
|
}, |
|
|
|
check: function () { |
|
this.setTipVisible(BI.isEmpty(this.options.items)); |
|
}, |
|
|
|
setTipVisible: function (b) { |
|
if (b === true) { |
|
this._assertTip(); |
|
this._tipText.setVisible(true); |
|
} else { |
|
this._tipText && this._tipText.setVisible(false); |
|
} |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items || []; |
|
this.check(); |
|
}, |
|
|
|
empty: function () { |
|
|
|
} |
|
}); |
|
BI.Pane.EVENT_LOADED = "EVENT_LOADED";/** |
|
* guy |
|
* 这仅仅只是一个超类, 所有简单控件的基类 |
|
* 1、类的控制, |
|
* 2、title的控制 |
|
* 3、文字超过边界显示3个点 |
|
* 4、cursor默认pointor |
|
* @class BI.Single |
|
* @extends BI.Widget |
|
* @abstract |
|
*/ |
|
BI.Single = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.Single.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-single", |
|
readonly: false, |
|
title: null, |
|
warningTitle: null, |
|
tipType: null, // success或warning |
|
value: null, |
|
belowMouse: false // title是否跟随鼠标 |
|
}); |
|
}, |
|
|
|
_showToolTip: function (e, opt) { |
|
opt || (opt = {}); |
|
var self = this, o = this.options; |
|
var type = this.getTipType() || (this.isEnabled() ? "success" : "warning"); |
|
var title = type === "success" ? this.getTitle() : (this.getWarningTitle() || this.getTitle()); |
|
if (BI.isKey(title)) { |
|
BI.Tooltips.show(e, this.getName(), title, type, this, opt); |
|
if (o.action) { |
|
BI.Actions.runAction(o.action, "hover", o, this); |
|
} |
|
BI.Actions.runGlobalAction("hover", o, this); |
|
} |
|
}, |
|
|
|
_hideTooltip: function () { |
|
var self = this; |
|
var tooltip = BI.Tooltips.get(this.getName()); |
|
if (BI.isNotNull(tooltip)) { |
|
tooltip.element.fadeOut(200, function () { |
|
BI.Tooltips.remove(self.getName()); |
|
}); |
|
} |
|
}, |
|
|
|
_init: function () { |
|
BI.Single.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isKey(o.title) || BI.isKey(o.warningTitle) |
|
|| BI.isFunction(o.title) || BI.isFunction(o.warningTitle)) { |
|
this.enableHover({ |
|
belowMouse: o.belowMouse, |
|
container: o.container |
|
}); |
|
} |
|
}, |
|
|
|
_clearTimeOut: function () { |
|
if (BI.isNotNull(this.showTimeout)) { |
|
clearTimeout(this.showTimeout); |
|
this.showTimeout = null; |
|
} |
|
if (BI.isNotNull(this.hideTimeout)) { |
|
clearTimeout(this.hideTimeout); |
|
this.hideTimeout = null; |
|
} |
|
}, |
|
|
|
enableHover: function (opt) { |
|
opt || (opt = {}); |
|
var self = this; |
|
if (!this._hoverBinded) { |
|
this.element.on("mouseenter.title" + this.getName(), function (e) { |
|
self._e = e; |
|
if (self.getTipType() === "warning" || (BI.isKey(self.getWarningTitle()) && !self.isEnabled())) { |
|
self.showTimeout = BI.delay(function () { |
|
if (BI.isNotNull(self.showTimeout)) { |
|
self._showToolTip(self._e || e, opt); |
|
} |
|
}, 200); |
|
} else if (self.getTipType() === "success" || self.isEnabled()) { |
|
self.showTimeout = BI.delay(function () { |
|
if (BI.isNotNull(self.showTimeout)) { |
|
self._showToolTip(self._e || e, opt); |
|
} |
|
}, 500); |
|
} |
|
}); |
|
this.element.on("mousemove.title" + this.getName(), function (e) { |
|
self._e = e; |
|
if (BI.isNotNull(self.showTimeout)) { |
|
clearTimeout(self.showTimeout); |
|
self.showTimeout = null; |
|
} |
|
if(BI.isNull(self.hideTimeout)) { |
|
self.hideTimeout = BI.delay(function () { |
|
if (BI.isNotNull(self.hideTimeout)) { |
|
self._hideTooltip(); |
|
} |
|
}, 500); |
|
} |
|
|
|
self.showTimeout = BI.delay(function () { |
|
// DEC-5321 IE下如果回调已经进入事件队列,clearTimeout将不会起作用 |
|
if (BI.isNotNull(self.showTimeout)) { |
|
if (BI.isNotNull(self.hideTimeout)) { |
|
clearTimeout(self.hideTimeout); |
|
self.hideTimeout = null; |
|
} |
|
// CHART-10611 在拖拽的情况下, 鼠标拖拽着元素离开了拖拽元素的容器,但是子元素在dom结构上仍然属于容器 |
|
// 这样会认为鼠标仍然在容器中, 500ms内放开的话,会在容器之外显示鼠标停留处显示容器的title |
|
if (self.element.__isMouseInBounds__(self._e || e)) { |
|
self._showToolTip(self._e || e, opt); |
|
} |
|
} |
|
}, 500); |
|
|
|
}); |
|
this.element.on("mouseleave.title" + this.getName(), function (e) { |
|
self._e = null; |
|
self._clearTimeOut(); |
|
self._hideTooltip(); |
|
}); |
|
this._hoverBinded = true; |
|
} |
|
}, |
|
|
|
disabledHover: function () { |
|
// 取消hover事件 |
|
this._clearTimeOut(); |
|
this._hideTooltip(); |
|
this.element.unbind("mouseenter.title" + this.getName()) |
|
.unbind("mousemove.title" + this.getName()) |
|
.unbind("mouseleave.title" + this.getName()); |
|
this._hoverBinded = false; |
|
}, |
|
|
|
populate: function (items) { |
|
this.items = items || []; |
|
}, |
|
|
|
// opt: {container: '', belowMouse: false} |
|
setTitle: function (title, opt) { |
|
this.options.title = title; |
|
if (BI.isKey(title) || BI.isFunction(title)) { |
|
this.enableHover(opt); |
|
} else { |
|
this.disabledHover(); |
|
} |
|
}, |
|
|
|
setWarningTitle: function (title, opt) { |
|
this.options.warningTitle = title; |
|
if (BI.isKey(title) || BI.isFunction(title)) { |
|
this.enableHover(opt); |
|
} else { |
|
this.disabledHover(); |
|
} |
|
}, |
|
|
|
getTipType: function () { |
|
return this.options.tipType; |
|
}, |
|
|
|
isReadOnly: function () { |
|
return !!this.options.readonly; |
|
}, |
|
|
|
getTitle: function () { |
|
var title = this.options.title; |
|
if(BI.isFunction(title)) { |
|
return title(); |
|
} |
|
return title; |
|
}, |
|
|
|
getWarningTitle: function () { |
|
var title = this.options.warningTitle; |
|
if(BI.isFunction(title)) { |
|
return title(); |
|
} |
|
return title; |
|
}, |
|
|
|
setValue: function (val) { |
|
if (!this.options.readonly) { |
|
this.options.value = val; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.options.value; |
|
}, |
|
|
|
_unMount: function () { |
|
BI.Single.superclass._unMount.apply(this, arguments); |
|
if(BI.isNotNull(this.showTimeout)) { |
|
clearTimeout(this.showTimeout); |
|
this.showTimeout = null; |
|
} |
|
BI.Tooltips.remove(this.getName()); |
|
} |
|
});/** |
|
* guy 表示一行数据,通过position来定位位置的数据 |
|
* @class BI.Text |
|
* @extends BI.Single |
|
*/ |
|
BI.Text = BI.inherit(BI.Single, { |
|
|
|
props: { |
|
baseCls: "bi-text", |
|
textAlign: "left", |
|
whiteSpace: "normal", |
|
lineHeight: null, |
|
handler: null, // 如果传入handler,表示处理文字的点击事件,不是区域的 |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
text: "", |
|
py: "", |
|
highLight: false |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
if (o.hgap + o.lgap > 0) { |
|
this.element.css({ |
|
"padding-left": o.hgap + o.lgap + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap > 0) { |
|
this.element.css({ |
|
"padding-right": o.hgap + o.rgap + "px" |
|
}); |
|
} |
|
if (o.vgap + o.tgap > 0) { |
|
this.element.css({ |
|
"padding-top": o.vgap + o.tgap + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap > 0) { |
|
this.element.css({ |
|
"padding-bottom": o.vgap + o.bgap + "px" |
|
}); |
|
} |
|
if (BI.isNumber(o.height)) { |
|
this.element.css({lineHeight: o.height + "px"}); |
|
} |
|
if (BI.isNumber(o.lineHeight)) { |
|
this.element.css({lineHeight: o.lineHeight + "px"}); |
|
} |
|
if (BI.isWidthOrHeight(o.maxWidth)) { |
|
this.element.css({maxWidth: o.maxWidth}); |
|
} |
|
this.element.css({ |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
textOverflow: o.whiteSpace === "nowrap" ? "ellipsis" : "", |
|
overflow: o.whiteSpace === "nowrap" ? "" : (BI.isWidthOrHeight(o.height) ? "auto" : "") |
|
}); |
|
if (o.handler) { |
|
this.text = BI.createWidget({ |
|
type: "bi.layout", |
|
tagName: "span" |
|
}); |
|
this.text.element.click(function () { |
|
o.handler(self.getValue()); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.default", |
|
element: this, |
|
items: [this.text] |
|
}); |
|
} else { |
|
this.text = this; |
|
} |
|
|
|
var text = this._getShowText(); |
|
if (BI.isKey(text)) { |
|
this.setText(text); |
|
} else if (BI.isKey(o.value)) { |
|
this.setText(o.value); |
|
} |
|
if (BI.isKey(o.keyword)) { |
|
this.doRedMark(o.keyword); |
|
} |
|
if (o.highLight) { |
|
this.doHighLight(); |
|
} |
|
}, |
|
|
|
_getShowText: function () { |
|
var o = this.options; |
|
return BI.isFunction(o.text) ? o.text() : o.text; |
|
}, |
|
|
|
|
|
doRedMark: function (keyword) { |
|
var o = this.options; |
|
// render之后做的doredmark,这个时候虽然标红了,但是之后text mounted执行的时候并没有keyword |
|
o.keyword = keyword; |
|
this.text.element.__textKeywordMarked__(this._getShowText() || o.value, keyword, o.py); |
|
}, |
|
|
|
unRedMark: function () { |
|
var o = this.options; |
|
o.keyword = ""; |
|
this.text.element.__textKeywordMarked__(this._getShowText() || o.value, "", o.py); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.element.addClass("bi-high-light"); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.element.removeClass("bi-high-light"); |
|
}, |
|
|
|
setValue: function (text) { |
|
BI.Text.superclass.setValue.apply(this, arguments); |
|
if (!this.isReadOnly()) { |
|
this.setText(text); |
|
} |
|
}, |
|
|
|
setStyle: function (css) { |
|
this.text.element.css(css); |
|
}, |
|
|
|
setText: function (text) { |
|
BI.Text.superclass.setText.apply(this, arguments); |
|
// 为textContext赋值为undefined时在ie和edge下会真的显示undefined |
|
this.options.text = BI.isNotNull(text) ? text : ""; |
|
if (BI.isIE9Below()) { |
|
this.text.element.html(BI.htmlEncode(this._getShowText())); |
|
return; |
|
} |
|
if (/\s/.test(text)) { |
|
this.text.element[0].innerHTML = BI.htmlEncode(this._getShowText()); |
|
} else { |
|
// textContent性能更好,并且原生防xss |
|
this.text.element[0].textContent = this._getShowText(); |
|
} |
|
BI.isKey(this.options.keyword) && this.doRedMark(this.options.keyword); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.text", BI.Text); |
|
/** |
|
* guy |
|
* @class BI.BasicButton |
|
* @extends BI.Single |
|
* |
|
* 一般的button父级 |
|
*/ |
|
BI.BasicButton = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.BasicButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-basic-button" + (conf.invalid ? "" : " cursor-pointer") + ((BI.isIE() && BI.getIEVersion() < 10) ? " hack" : ""), |
|
value: "", |
|
text: "", |
|
stopEvent: false, |
|
stopPropagation: false, |
|
selected: false, |
|
once: false, // 点击一次选中有效,再点无效 |
|
forceSelected: false, // 点击即选中, 选中了就不会被取消,与once的区别是forceSelected不影响事件的触发 |
|
forceNotSelected: false, // 无论怎么点击都不会被选中 |
|
disableSelected: false, // 使能选中 |
|
|
|
shadow: false, |
|
isShadowShowingOnSelected: false, // 选中状态下是否显示阴影 |
|
trigger: null, |
|
handler: BI.emptyFn, |
|
bubble: null |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BasicButton.superclass._init.apply(this, arguments); |
|
var opts = this.options; |
|
if (opts.selected === true) { |
|
BI.nextTick(BI.bind(function () { |
|
this.setSelected(opts.selected); |
|
}, this)); |
|
} |
|
BI.nextTick(BI.bind(this.bindEvent, this)); |
|
|
|
if (opts.shadow) { |
|
this._createShadow(); |
|
} |
|
if (opts.level) { |
|
this.element.addClass("button-" + opts.level); |
|
} |
|
}, |
|
|
|
_createShadow: function () { |
|
var self = this, o = this.options; |
|
|
|
var assertMask = function () { |
|
if (!self.$mask) { |
|
self.$mask = BI.createWidget(BI.isObject(o.shadow) ? o.shadow : {}, { |
|
type: "bi.layout", |
|
cls: "bi-button-mask" |
|
}); |
|
self.$mask.invisible(); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: self, |
|
items: [{ |
|
el: self.$mask, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
} |
|
}; |
|
|
|
this.element.mouseup(function () { |
|
if (!self._hover && !o.isShadowShowingOnSelected) { |
|
assertMask(); |
|
self.$mask.invisible(); |
|
} |
|
}); |
|
this.element.on("mouseenter." + this.getName(), function (e) { |
|
if (self.element.__isMouseInBounds__(e)) { |
|
if (self.isEnabled() && !self._hover && (o.isShadowShowingOnSelected || !self.isSelected())) { |
|
assertMask(); |
|
self.$mask.visible(); |
|
} |
|
} |
|
}); |
|
this.element.on("mousemove." + this.getName(), function (e) { |
|
if (!self.element.__isMouseInBounds__(e)) { |
|
if (self.isEnabled() && !self._hover) { |
|
assertMask(); |
|
self.$mask.invisible(); |
|
} |
|
} |
|
}); |
|
this.element.on("mouseleave." + this.getName(), function () { |
|
if (self.isEnabled() && !self._hover) { |
|
assertMask(); |
|
self.$mask.invisible(); |
|
} |
|
}); |
|
}, |
|
|
|
bindEvent: function () { |
|
var self = this; |
|
var o = this.options, hand = this.handle(); |
|
if (!hand) { |
|
return; |
|
} |
|
hand = hand.element; |
|
var triggerArr = (o.trigger || "").split(","); |
|
BI.each(triggerArr, function (idx, trigger) { |
|
switch (trigger) { |
|
case "mouseup": |
|
var mouseDown = false; |
|
hand.mousedown(function () { |
|
mouseDown = true; |
|
}); |
|
hand.mouseup(function (e) { |
|
if (mouseDown === true) { |
|
clk(e); |
|
} |
|
mouseDown = false; |
|
ev(e); |
|
}); |
|
break; |
|
case "mousedown": |
|
var mouseDown = false; |
|
var selected = false; |
|
hand.mousedown(function (e) { |
|
// if (e.button === 0) { |
|
BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) { |
|
// if (e.button === 0) { |
|
if (BI.DOM.isExist(self) && !hand.__isMouseInBounds__(e) && mouseDown === true && !selected) { |
|
// self.setSelected(!self.isSelected()); |
|
self._trigger(); |
|
} |
|
mouseDown = false; |
|
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName()); |
|
// } |
|
}); |
|
if (mouseDown === true) { |
|
return; |
|
} |
|
if (self.isSelected()) { |
|
selected = true; |
|
} else { |
|
clk(e); |
|
} |
|
mouseDown = true; |
|
ev(e); |
|
// } |
|
}); |
|
hand.mouseup(function (e) { |
|
// if (e.button === 0) { |
|
if (BI.DOM.isExist(self) && mouseDown === true && selected === true) { |
|
clk(e); |
|
} |
|
mouseDown = false; |
|
selected = false; |
|
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName()); |
|
// } |
|
}); |
|
break; |
|
case "dblclick": |
|
hand.dblclick(clk); |
|
break; |
|
case "lclick": |
|
var mouseDown = false; |
|
var interval; |
|
hand.mousedown(function (e) { |
|
BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) { |
|
interval && clearInterval(interval); |
|
interval = null; |
|
mouseDown = false; |
|
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName()); |
|
}); |
|
if (mouseDown === true) { |
|
return; |
|
} |
|
if (!self.isEnabled() || (self.isOnce() && self.isSelected())) { |
|
return; |
|
} |
|
interval = setInterval(function () { |
|
if (self.isEnabled()) { |
|
self.doClick(); |
|
} |
|
}, 180); |
|
mouseDown = true; |
|
ev(e); |
|
}); |
|
break; |
|
default: |
|
if (o.stopEvent || o.stopPropagation) { |
|
hand.mousedown(function (e) { |
|
ev(e); |
|
}); |
|
} |
|
hand.click(clk); |
|
break; |
|
} |
|
}); |
|
|
|
// 之后的300ms点击无效 |
|
var onClick = BI.debounce(this._doClick, BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
|
|
function ev (e) { |
|
if (o.stopEvent) { |
|
e.stopEvent(); |
|
} |
|
if (o.stopPropagation) { |
|
e.stopPropagation(); |
|
} |
|
} |
|
|
|
function clk (e) { |
|
ev(e); |
|
if (!self.isEnabled() || (self.isOnce() && self.isSelected())) { |
|
return; |
|
} |
|
if (BI.isKey(o.bubble) || BI.isFunction(o.bubble)) { |
|
if (BI.isNull(self.combo)) { |
|
var popup; |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: self, |
|
items: [{ |
|
el: { |
|
type: "bi.bubble_combo", |
|
trigger: "", |
|
// bubble的提示不需要一直存在在界面上 |
|
destroyWhenHide: true, |
|
ref: function () { |
|
self.combo = this; |
|
}, |
|
el: { |
|
type: "bi.layout", |
|
height: "100%" |
|
}, |
|
popup: { |
|
type: "bi.text_bubble_bar_popup_view", |
|
text: getBubble(), |
|
ref: function () { |
|
popup = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON, |
|
action: function (v) { |
|
self.combo.hideView(); |
|
if (v) { |
|
onClick.apply(self, arguments); |
|
} |
|
} |
|
}] |
|
}, |
|
listeners: [{ |
|
eventName: BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
popup.populate(getBubble()); |
|
} |
|
}] |
|
}, |
|
left: 0, |
|
right: 0, |
|
bottom: 0, |
|
top: 0 |
|
}] |
|
}); |
|
} |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
return; |
|
} |
|
onClick.apply(self, arguments); |
|
} |
|
|
|
function getBubble () { |
|
var bubble = self.options.bubble; |
|
if (BI.isFunction(bubble)) { |
|
return bubble(); |
|
} |
|
return bubble; |
|
} |
|
}, |
|
|
|
_trigger: function (e) { |
|
var o = this.options; |
|
if (!this.isEnabled()) { |
|
return; |
|
} |
|
if (!this.isDisableSelected()) { |
|
this.isForceSelected() ? this.setSelected(true) : |
|
(this.isForceNotSelected() ? this.setSelected(false) : |
|
this.setSelected(!this.isSelected())); |
|
} |
|
if (this.isValid()) { |
|
o.handler.call(this, this.getValue(), this, e); |
|
var v = this.getValue(); |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, v, this, e); |
|
this.fireEvent(BI.BasicButton.EVENT_CHANGE, v, this); |
|
if (o.action) { |
|
BI.Actions.runAction(o.action, "click", o, this); |
|
} |
|
BI.Actions.runGlobalAction("click", o, this); |
|
} |
|
}, |
|
|
|
_doClick: function (e) { |
|
if (this.isValid()) { |
|
this.beforeClick(e); |
|
} |
|
this._trigger(e); |
|
if (this.isValid()) { |
|
this.doClick(e); |
|
} |
|
}, |
|
|
|
beforeClick: function () { |
|
|
|
}, |
|
|
|
doClick: function () { |
|
|
|
}, |
|
|
|
handle: function () { |
|
return this; |
|
}, |
|
|
|
hover: function () { |
|
this._hover = true; |
|
this.handle().element.addClass("hover"); |
|
if (this.options.shadow) { |
|
this.$mask && this.$mask.setVisible(true); |
|
} |
|
}, |
|
|
|
dishover: function () { |
|
this._hover = false; |
|
this.handle().element.removeClass("hover"); |
|
if (this.options.shadow) { |
|
this.$mask && this.$mask.setVisible(false); |
|
} |
|
}, |
|
|
|
setSelected: function (b) { |
|
var o = this.options; |
|
o.selected = b; |
|
if (b) { |
|
this.handle().element.addClass("active"); |
|
} else { |
|
this.handle().element.removeClass("active"); |
|
} |
|
if (o.shadow && !o.isShadowShowingOnSelected) { |
|
this.$mask && this.$mask.setVisible(false); |
|
} |
|
}, |
|
|
|
isSelected: function () { |
|
return this.options.selected; |
|
}, |
|
|
|
isOnce: function () { |
|
return this.options.once; |
|
}, |
|
|
|
isForceSelected: function () { |
|
return this.options.forceSelected; |
|
}, |
|
|
|
isForceNotSelected: function () { |
|
return this.options.forceNotSelected; |
|
}, |
|
|
|
isDisableSelected: function () { |
|
return this.options.disableSelected; |
|
}, |
|
|
|
setText: function (text) { |
|
this.options.text = text; |
|
}, |
|
|
|
getText: function () { |
|
return this.options.text; |
|
}, |
|
|
|
_setEnable: function (enable) { |
|
BI.BasicButton.superclass._setEnable.apply(this, arguments); |
|
if (enable === true) { |
|
this.element.removeClass("base-disabled disabled"); |
|
} else if (enable === false) { |
|
this.element.addClass("base-disabled disabled"); |
|
} |
|
if (!enable) { |
|
if (this.options.shadow) { |
|
this.$mask && this.$mask.setVisible(false); |
|
} |
|
} |
|
}, |
|
|
|
empty: function () { |
|
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + this.getName()); |
|
BI.BasicButton.superclass.empty.apply(this, arguments); |
|
}, |
|
|
|
destroy: function () { |
|
BI.BasicButton.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.BasicButton.EVENT_CHANGE = "BasicButton.EVENT_CHANGE";/** |
|
* 表示一个可以展开的节点, 不仅有选中状态而且有展开状态 |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.NodeButton |
|
* @extends BI.BasicButton |
|
* @abstract |
|
*/ |
|
BI.NodeButton = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.NodeButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend( conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-node", |
|
open: false |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.NodeButton.superclass._init.apply(this, arguments); |
|
var self = this; |
|
BI.nextTick(function () { |
|
self.setOpened(self.isOpened()); |
|
}); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
this.setOpened(!this.isOpened()); |
|
}, |
|
|
|
isOnce: function () { |
|
return false; |
|
}, |
|
|
|
isOpened: function () { |
|
return !!this.options.open; |
|
}, |
|
|
|
setOpened: function (b) { |
|
this.options.open = !!b; |
|
}, |
|
|
|
triggerCollapse: function () { |
|
if(this.isOpened()) { |
|
this.setOpened(false); |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
triggerExpand: function () { |
|
if(!this.isOpened()) { |
|
this.setOpened(true); |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, this.getValue(), this); |
|
} |
|
} |
|
});/** |
|
* guy |
|
* tip提示 |
|
* zIndex在10亿级别 |
|
* @class BI.Tip |
|
* @extends BI.Single |
|
* @abstract |
|
*/ |
|
BI.Tip = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Tip.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-tip", |
|
zIndex: BI.zIndex_tip |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Tip.superclass._init.apply(this, arguments); |
|
this.element.css({zIndex: this.options.zIndex}); |
|
} |
|
});/** |
|
* Created by GUY on 2015/6/26. |
|
* @class BI.ButtonGroup |
|
* @extends BI.Widget |
|
*/ |
|
|
|
BI.ButtonGroup = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ButtonGroup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-button-group", |
|
behaviors: {}, |
|
items: [], |
|
value: "", |
|
chooseType: BI.Selection.Single, |
|
layouts: [{ |
|
type: "bi.center", |
|
hgap: 0, |
|
vgap: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ButtonGroup.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
var behaviors = {}; |
|
BI.each(o.behaviors, function (key, rule) { |
|
behaviors[key] = BI.BehaviorFactory.createBehavior(key, { |
|
rule: rule |
|
}); |
|
}); |
|
this.behaviors = behaviors; |
|
this.populate(o.items); |
|
if(BI.isKey(o.value) || BI.isNotEmptyArray(o.value)){ |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_createBtns: function (items) { |
|
var o = this.options; |
|
return BI.createWidgets(BI.createItems(items, { |
|
type: "bi.text_button" |
|
})); |
|
}, |
|
|
|
_btnsCreator: function (items) { |
|
var self = this, args = Array.prototype.slice.call(arguments), o = this.options; |
|
var buttons = this._createBtns(items); |
|
args[0] = buttons; |
|
|
|
BI.each(this.behaviors, function (i, behavior) { |
|
behavior.doBehavior.apply(behavior, args); |
|
}); |
|
BI.each(buttons, function (i, btn) { |
|
btn.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (type === BI.Events.CLICK) { |
|
switch (o.chooseType) { |
|
case BI.ButtonGroup.CHOOSE_TYPE_SINGLE: |
|
self.setValue(btn.getValue()); |
|
break; |
|
case BI.ButtonGroup.CHOOSE_TYPE_NONE: |
|
self.setValue([]); |
|
break; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.fireEvent(BI.ButtonGroup.EVENT_CHANGE, value, obj); |
|
} else { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}); |
|
btn.on(BI.Events.DESTROY, function () { |
|
BI.remove(self.buttons, btn); |
|
}); |
|
}); |
|
|
|
return buttons; |
|
}, |
|
|
|
_packageBtns: function (btns) { |
|
var o = this.options; |
|
for (var i = o.layouts.length - 1; i > 0; i--) { |
|
btns = BI.map(btns, function (k, it) { |
|
return BI.extend({}, o.layouts[i], { |
|
items: [ |
|
BI.extend({}, o.layouts[i].el, { |
|
el: it |
|
}) |
|
] |
|
}); |
|
}); |
|
} |
|
return btns; |
|
}, |
|
|
|
_packageSimpleItems: function (btns) { |
|
var o = this.options; |
|
return BI.map(o.items, function (i, item) { |
|
if (BI.stripEL(item) === item) { |
|
return btns[i]; |
|
} |
|
return BI.extend({}, item, { |
|
el: btns[i] |
|
}); |
|
}); |
|
}, |
|
|
|
_packageItems: function (items, packBtns) { |
|
return BI.createItems(BI.makeArrayByArray(items, {}), BI.clone(packBtns)); |
|
}, |
|
|
|
_packageLayout: function (items) { |
|
var o = this.options, layout = BI.deepClone(o.layouts[0]); |
|
|
|
var lay = BI.formatEL(layout).el; |
|
while (lay && lay.items && !BI.isEmpty(lay.items)) { |
|
lay = BI.formatEL(lay.items[0]).el; |
|
} |
|
lay.items = items; |
|
return layout; |
|
}, |
|
|
|
// 如果是一个简单的layout |
|
_isSimpleLayout: function () { |
|
var o = this.options; |
|
return o.layouts.length === 1 && !BI.isArray(o.items[0]); |
|
}, |
|
|
|
doBehavior: function () { |
|
var args = Array.prototype.slice.call(arguments); |
|
args.unshift(this.buttons); |
|
BI.each(this.behaviors, function (i, behavior) { |
|
behavior.doBehavior.apply(behavior, args); |
|
}); |
|
}, |
|
|
|
prependItems: function (items) { |
|
var o = this.options; |
|
var btns = this._btnsCreator.apply(this, arguments); |
|
this.buttons = BI.concat(btns, this.buttons); |
|
|
|
if (this._isSimpleLayout() && this.layouts && this.layouts.prependItems) { |
|
this.layouts.prependItems(btns); |
|
return; |
|
} |
|
|
|
items = this._packageItems(items, this._packageBtns(btns)); |
|
this.layouts.prependItems(this._packageLayout(items).items); |
|
}, |
|
|
|
addItems: function (items) { |
|
var o = this.options; |
|
var btns = this._btnsCreator.apply(this, arguments); |
|
this.buttons = BI.concat(this.buttons, btns); |
|
|
|
// 如果是一个简单的layout |
|
if (this._isSimpleLayout() && this.layouts && this.layouts.addItems) { |
|
this.layouts.addItems(btns); |
|
return; |
|
} |
|
|
|
items = this._packageItems(items, this._packageBtns(btns)); |
|
this.layouts.addItems(this._packageLayout(items).items); |
|
}, |
|
|
|
removeItemAt: function (indexes) { |
|
BI.removeAt(this.buttons, indexes); |
|
this.layouts.removeItemAt(indexes); |
|
}, |
|
|
|
removeItems: function (values) { |
|
values = BI.isArray(values) ? values : [values]; |
|
var deleted = []; |
|
BI.each(this.buttons, function (i, button) { |
|
if (BI.deepContains(values, button.getValue())) { |
|
deleted.push(i); |
|
} |
|
}); |
|
BI.removeAt(this.buttons, deleted); |
|
this.layouts.removeItemAt(deleted); |
|
}, |
|
|
|
populate: function (items) { |
|
items = items || []; |
|
this.empty(); |
|
this.options.items = items; |
|
|
|
this.buttons = this._btnsCreator.apply(this, arguments); |
|
if (this._isSimpleLayout()) { |
|
items = this._packageSimpleItems(this.buttons); |
|
} else { |
|
items = this._packageItems(items, this._packageBtns(this.buttons)); |
|
} |
|
|
|
this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items))); |
|
}, |
|
|
|
setNotSelectedValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttons, function (i, item) { |
|
if (BI.deepContains(v, item.getValue())) { |
|
item.setSelected && item.setSelected(false); |
|
} else { |
|
item.setSelected && item.setSelected(true); |
|
} |
|
}); |
|
}, |
|
|
|
setEnabledValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttons, function (i, item) { |
|
if (BI.deepContains(v, item.getValue())) { |
|
item.setEnable(true); |
|
} else { |
|
item.setEnable(false); |
|
} |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttons, function (i, item) { |
|
if (BI.deepContains(v, item.getValue())) { |
|
item.setSelected && item.setSelected(true); |
|
} else { |
|
item.setSelected && item.setSelected(false); |
|
} |
|
}); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
var v = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && !(item.isSelected && item.isSelected())) { |
|
v.push(item.getValue()); |
|
} |
|
}); |
|
return v; |
|
}, |
|
|
|
getValue: function () { |
|
var v = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && item.isSelected && item.isSelected()) { |
|
v.push(item.getValue()); |
|
} |
|
}); |
|
return v; |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.buttons; |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.buttons; |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
var btns = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isSelected && item.isSelected()) { |
|
btns.push(item); |
|
} |
|
}); |
|
return btns; |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
var btns = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isSelected && !item.isSelected()) { |
|
btns.push(item); |
|
} |
|
}); |
|
return btns; |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
var index = -1; |
|
BI.any(this.buttons, function (i, item) { |
|
if (item.isEnabled() && item.getValue() === value) { |
|
index = i; |
|
return true; |
|
} |
|
}); |
|
return index; |
|
}, |
|
|
|
getNodeById: function (id) { |
|
var node; |
|
BI.any(this.buttons, function (i, item) { |
|
if (item.isEnabled() && item.options.id === id) { |
|
node = item; |
|
return true; |
|
} |
|
}); |
|
return node; |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
var node; |
|
BI.any(this.buttons, function (i, item) { |
|
if (item.isEnabled() && item.getValue() === value) { |
|
node = item; |
|
return true; |
|
} |
|
}); |
|
return node; |
|
}, |
|
|
|
empty: function () { |
|
BI.ButtonGroup.superclass.empty.apply(this, arguments); |
|
this.options.items = []; |
|
}, |
|
|
|
destroy: function () { |
|
BI.ButtonGroup.superclass.destroy.apply(this, arguments); |
|
this.options.items = []; |
|
} |
|
}); |
|
BI.extend(BI.ButtonGroup, { |
|
CHOOSE_TYPE_SINGLE: BI.Selection.Single, |
|
CHOOSE_TYPE_MULTI: BI.Selection.Multi, |
|
CHOOSE_TYPE_ALL: BI.Selection.All, |
|
CHOOSE_TYPE_NONE: BI.Selection.None, |
|
CHOOSE_TYPE_DEFAULT: BI.Selection.Default |
|
}); |
|
BI.ButtonGroup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.button_group", BI.ButtonGroup);/** |
|
* Created by GUY on 2015/8/10. |
|
* @class BI.ButtonTree |
|
* @extends BI.ButtonGroup |
|
*/ |
|
|
|
BI.ButtonTree = BI.inherit(BI.ButtonGroup, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ButtonTree.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-button-tree" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ButtonTree.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
setNotSelectedValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttons, function (i, item) { |
|
if (!BI.isFunction(item.setSelected)) { |
|
item.setNotSelectedValue(v); |
|
return; |
|
} |
|
if (BI.deepContains(v, item.getValue())) { |
|
item.setSelected(false); |
|
} else { |
|
item.setSelected(true); |
|
} |
|
}); |
|
}, |
|
|
|
setEnabledValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttons, function (i, item) { |
|
if (BI.isFunction(item.setEnabledValue)) { |
|
item.setEnabledValue(v); |
|
return; |
|
} |
|
if (BI.deepContains(v, item.getValue())) { |
|
item.setEnable(true); |
|
} else { |
|
item.setEnable(false); |
|
} |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttons, function (i, item) { |
|
if (!BI.isFunction(item.setSelected)) { |
|
item.setValue(v); |
|
return; |
|
} |
|
if (BI.deepContains(v, item.getValue())) { |
|
item.setSelected(true); |
|
} else { |
|
item.setSelected(false); |
|
} |
|
}); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
var v = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && !BI.isFunction(item.setSelected)) { |
|
v = BI.concat(v, item.getNotSelectedValue()); |
|
return; |
|
} |
|
if (item.isEnabled() && item.isSelected && !item.isSelected()) { |
|
v.push(item.getValue()); |
|
} |
|
}); |
|
return v; |
|
}, |
|
|
|
getValue: function () { |
|
var v = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && !BI.isFunction(item.setSelected)) { |
|
v = BI.concat(v, item.getValue()); |
|
return; |
|
} |
|
if (item.isEnabled() && item.isSelected && item.isSelected()) { |
|
v.push(item.getValue()); |
|
} |
|
}); |
|
return v; |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
var btns = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && !BI.isFunction(item.setSelected)) { |
|
btns = btns.concat(item.getSelectedButtons()); |
|
return; |
|
} |
|
if (item.isSelected && item.isSelected()) { |
|
btns.push(item); |
|
} |
|
}); |
|
return btns; |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
var btns = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && !BI.isFunction(item.setSelected)) { |
|
btns = btns.concat(item.getNotSelectedButtons()); |
|
return; |
|
} |
|
if (item.isSelected && !item.isSelected()) { |
|
btns.push(item); |
|
} |
|
}); |
|
return btns; |
|
}, |
|
|
|
// 获取所有的叶子节点 |
|
getAllLeaves: function () { |
|
var leaves = []; |
|
BI.each(this.buttons, function (i, item) { |
|
if (item.isEnabled() && !BI.isFunction(item.setSelected)) { |
|
leaves = leaves.concat(item.getAllLeaves()); |
|
return; |
|
} |
|
if (item.isEnabled()) { |
|
leaves.push(item); |
|
} |
|
}); |
|
return leaves; |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
var index = -1; |
|
BI.any(this.buttons, function (i, item) { |
|
var vs = item.getValue(); |
|
if (item.isEnabled() && (vs === value || BI.contains(vs, value))) { |
|
index = i; |
|
return true; |
|
} |
|
}); |
|
return index; |
|
}, |
|
|
|
getNodeById: function (id) { |
|
var node; |
|
BI.any(this.buttons, function (i, item) { |
|
if (item.isEnabled()) { |
|
if (item.attr("id") === id) { |
|
node = item; |
|
return true; |
|
} else if (BI.isFunction(item.getNodeById)) { |
|
if (node = item.getNodeById(id)) { |
|
return true; |
|
} |
|
} |
|
} |
|
}); |
|
return node; |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
var node; |
|
BI.any(this.buttons, function (i, item) { |
|
if (item.isEnabled()) { |
|
if (BI.isFunction(item.getNodeByValue)) { |
|
if (node = item.getNodeByValue(value)) { |
|
return true; |
|
} |
|
} else if (item.attr("value") === value) { |
|
node = item; |
|
return true; |
|
} |
|
} |
|
}); |
|
return node; |
|
} |
|
}); |
|
BI.ButtonTree.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.button_tree", BI.ButtonTree);BI.prepares.push(function () { |
|
BI.Resizers = new BI.ResizeController(); |
|
BI.Layers = new BI.LayerController(); |
|
BI.Maskers = new BI.MaskersController(); |
|
BI.Bubbles = new BI.BubblesController(); |
|
BI.Tooltips = new BI.TooltipsController(); |
|
BI.Popovers = new BI.PopoverController(); |
|
BI.Broadcasts = new BI.BroadcastController(); |
|
BI.StyleLoaders = new BI.StyleLoaderManager(); |
|
}); |
|
/** |
|
* CollectionView |
|
* |
|
* Created by GUY on 2016/1/15. |
|
* @class BI.CollectionView |
|
* @extends BI.Widget |
|
*/ |
|
BI.CollectionView = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.CollectionView.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-collection", |
|
// width: 400, //必设 |
|
// height: 300, //必设 |
|
overflowX: true, |
|
overflowY: true, |
|
cellSizeAndPositionGetter: BI.emptyFn, |
|
horizontalOverscanSize: 0, |
|
verticalOverscanSize: 0, |
|
scrollLeft: 0, |
|
scrollTop: 0, |
|
items: [] |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.CollectionView.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.renderedCells = []; |
|
this.renderedKeys = []; |
|
this.renderRange = {}; |
|
this._scrollLock = false; |
|
this._debounceRelease = BI.debounce(function () { |
|
self._scrollLock = false; |
|
}, 1000 / 60); |
|
this.container = BI.createWidget({ |
|
type: "bi.absolute" |
|
}); |
|
this.element.scroll(function () { |
|
if (self._scrollLock === true) { |
|
return; |
|
} |
|
o.scrollLeft = self.element.scrollLeft(); |
|
o.scrollTop = self.element.scrollTop(); |
|
self._calculateChildrenToRender(); |
|
self.fireEvent(BI.CollectionView.EVENT_SCROLL, { |
|
scrollLeft: o.scrollLeft, |
|
scrollTop: o.scrollTop |
|
}); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
scrollable: o.overflowX === true && o.overflowY === true, |
|
scrolly: o.overflowX === false && o.overflowY === true, |
|
scrollx: o.overflowX === true && o.overflowY === false, |
|
items: [this.container] |
|
}); |
|
if (o.items.length > 0) { |
|
this._calculateSizeAndPositionData(); |
|
this._populate(); |
|
} |
|
}, |
|
|
|
mounted: function () { |
|
var o = this.options; |
|
if (o.scrollLeft !== 0 || o.scrollTop !== 0) { |
|
this.element.scrollTop(o.scrollTop); |
|
this.element.scrollLeft(o.scrollLeft); |
|
} |
|
}, |
|
|
|
_calculateSizeAndPositionData: function () { |
|
var o = this.options; |
|
var cellMetadata = []; |
|
var sectionManager = new BI.SectionManager(); |
|
var height = 0; |
|
var width = 0; |
|
|
|
for (var index = 0, len = o.items.length; index < len; index++) { |
|
var cellMetadatum = o.cellSizeAndPositionGetter(index); |
|
|
|
if (cellMetadatum.height == null || isNaN(cellMetadatum.height) || |
|
cellMetadatum.width == null || isNaN(cellMetadatum.width) || |
|
cellMetadatum.x == null || isNaN(cellMetadatum.x) || |
|
cellMetadatum.y == null || isNaN(cellMetadatum.y)) { |
|
throw Error(); |
|
} |
|
|
|
height = Math.max(height, cellMetadatum.y + cellMetadatum.height); |
|
width = Math.max(width, cellMetadatum.x + cellMetadatum.width); |
|
|
|
cellMetadatum.index = index; |
|
cellMetadata[index] = cellMetadatum; |
|
sectionManager.registerCell(cellMetadatum, index); |
|
} |
|
|
|
this._cellMetadata = cellMetadata; |
|
this._sectionManager = sectionManager; |
|
this._height = height; |
|
this._width = width; |
|
}, |
|
|
|
_cellRenderers: function (height, width, x, y) { |
|
this._lastRenderedCellIndices = this._sectionManager.getCellIndices(height, width, x, y); |
|
return this._cellGroupRenderer(); |
|
}, |
|
|
|
_cellGroupRenderer: function () { |
|
var self = this, o = this.options; |
|
var rendered = []; |
|
BI.each(this._lastRenderedCellIndices, function (i, index) { |
|
var cellMetadata = self._sectionManager.getCellMetadata(index); |
|
rendered.push(cellMetadata); |
|
}); |
|
return rendered; |
|
}, |
|
|
|
_calculateChildrenToRender: function () { |
|
var self = this, o = this.options; |
|
var scrollLeft = BI.clamp(o.scrollLeft, 0, this._getMaxScrollLeft()); |
|
var scrollTop = BI.clamp(o.scrollTop, 0, this._getMaxScrollTop()); |
|
var left = Math.max(0, scrollLeft - o.horizontalOverscanSize); |
|
var top = Math.max(0, scrollTop - o.verticalOverscanSize); |
|
var right = Math.min(this._width, scrollLeft + o.width + o.horizontalOverscanSize); |
|
var bottom = Math.min(this._height, scrollTop + o.height + o.verticalOverscanSize); |
|
if (right > 0 && bottom > 0) { |
|
// 如果滚动的区间并没有超出渲染的范围 |
|
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) { |
|
return; |
|
} |
|
var childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top); |
|
var renderedCells = [], renderedKeys = {}, renderedWidgets = {}; |
|
// 存储所有的left和top |
|
var lefts = {}, tops = {}; |
|
for (var i = 0, len = childrenToDisplay.length; i < len; i++) { |
|
var datum = childrenToDisplay[i]; |
|
lefts[datum.x] = datum.x; |
|
lefts[datum.x + datum.width] = datum.x + datum.width; |
|
tops[datum.y] = datum.y; |
|
tops[datum.y + datum.height] = datum.y + datum.height; |
|
} |
|
lefts = BI.toArray(lefts); |
|
tops = BI.toArray(tops); |
|
var leftMap = BI.invert(lefts); |
|
var topMap = BI.invert(tops); |
|
// 存储上下左右四个边界 |
|
var leftBorder = {}, rightBorder = {}, topBorder = {}, bottomBorder = {}; |
|
var assertMinBorder = function (border, offset) { |
|
if (border[offset] == null) { |
|
border[offset] = Number.MAX_VALUE; |
|
} |
|
}; |
|
var assertMaxBorder = function (border, offset) { |
|
if (border[offset] == null) { |
|
border[offset] = 0; |
|
} |
|
}; |
|
for (var i = 0, len = childrenToDisplay.length; i < len; i++) { |
|
var datum = childrenToDisplay[i]; |
|
var index = this.renderedKeys[datum.index] && this.renderedKeys[datum.index][1]; |
|
var child; |
|
if (index >= 0) { |
|
if (datum.width !== this.renderedCells[index]._width) { |
|
this.renderedCells[index]._width = datum.width; |
|
this.renderedCells[index].el.setWidth(datum.width); |
|
} |
|
if (datum.height !== this.renderedCells[index]._height) { |
|
this.renderedCells[index]._height = datum.height; |
|
this.renderedCells[index].el.setHeight(datum.height); |
|
} |
|
if (this.renderedCells[index]._left !== datum.x) { |
|
this.renderedCells[index].el.element.css("left", datum.x + "px"); |
|
} |
|
if (this.renderedCells[index]._top !== datum.y) { |
|
this.renderedCells[index].el.element.css("top", datum.y + "px"); |
|
} |
|
renderedCells.push(child = this.renderedCells[index]); |
|
} else { |
|
child = BI.createWidget(BI.extend({ |
|
type: "bi.label", |
|
width: datum.width, |
|
height: datum.height |
|
}, o.items[datum.index], { |
|
cls: (o.items[datum.index].cls || "") + " container-cell" + (datum.y === 0 ? " first-row" : "") + (datum.x === 0 ? " first-col" : ""), |
|
_left: datum.x, |
|
_top: datum.y |
|
})); |
|
renderedCells.push({ |
|
el: child, |
|
left: datum.x, |
|
top: datum.y, |
|
_left: datum.x, |
|
_top: datum.y, |
|
_width: datum.width, |
|
_height: datum.height |
|
}); |
|
} |
|
var startTopIndex = topMap[datum.y] | 0; |
|
var endTopIndex = topMap[datum.y + datum.height] | 0; |
|
for (var k = startTopIndex; k <= endTopIndex; k++) { |
|
var t = tops[k]; |
|
assertMinBorder(leftBorder, t); |
|
assertMaxBorder(rightBorder, t); |
|
leftBorder[t] = Math.min(leftBorder[t], datum.x); |
|
rightBorder[t] = Math.max(rightBorder[t], datum.x + datum.width); |
|
} |
|
var startLeftIndex = leftMap[datum.x] | 0; |
|
var endLeftIndex = leftMap[datum.x + datum.width] | 0; |
|
for (var k = startLeftIndex; k <= endLeftIndex; k++) { |
|
var l = lefts[k]; |
|
assertMinBorder(topBorder, l); |
|
assertMaxBorder(bottomBorder, l); |
|
topBorder[l] = Math.min(topBorder[l], datum.y); |
|
bottomBorder[l] = Math.max(bottomBorder[l], datum.y + datum.height); |
|
} |
|
|
|
renderedKeys[datum.index] = [datum.index, i]; |
|
renderedWidgets[i] = child; |
|
} |
|
// 已存在的, 需要添加的和需要删除的 |
|
var existSet = {}, addSet = {}, deleteArray = []; |
|
BI.each(renderedKeys, function (i, key) { |
|
if (self.renderedKeys[i]) { |
|
existSet[i] = key; |
|
} else { |
|
addSet[i] = key; |
|
} |
|
}); |
|
BI.each(this.renderedKeys, function (i, key) { |
|
if (existSet[i]) { |
|
return; |
|
} |
|
if (addSet[i]) { |
|
return; |
|
} |
|
deleteArray.push(key[1]); |
|
}); |
|
BI.each(deleteArray, function (i, index) { |
|
// 性能优化,不调用destroy方法防止触发destroy事件 |
|
self.renderedCells[index].el._destroy(); |
|
}); |
|
var addedItems = []; |
|
BI.each(addSet, function (index, key) { |
|
addedItems.push(renderedCells[key[1]]); |
|
}); |
|
this.container.addItems(addedItems); |
|
// 拦截父子级关系 |
|
this.container._children = renderedWidgets; |
|
this.container.attr("items", renderedCells); |
|
this.renderedCells = renderedCells; |
|
this.renderedKeys = renderedKeys; |
|
|
|
// Todo 左右比较特殊 |
|
var minX = BI.min(leftBorder); |
|
var maxX = BI.max(rightBorder); |
|
|
|
var minY = BI.max(topBorder); |
|
var maxY = BI.min(bottomBorder); |
|
|
|
this.renderRange = {minX: minX, minY: minY, maxX: maxX, maxY: maxY}; |
|
} |
|
}, |
|
|
|
_getMaxScrollLeft: function () { |
|
return Math.max(0, this._width - this.options.width + (this.options.overflowX ? BI.DOM.getScrollWidth() : 0)); |
|
}, |
|
|
|
_getMaxScrollTop: function () { |
|
return Math.max(0, this._height - this.options.height + (this.options.overflowY ? BI.DOM.getScrollWidth() : 0)); |
|
}, |
|
|
|
_populate: function (items) { |
|
var o = this.options; |
|
this._reRange(); |
|
if (items && items !== this.options.items) { |
|
this.options.items = items; |
|
this._calculateSizeAndPositionData(); |
|
} |
|
if (o.items.length > 0) { |
|
this.container.setWidth(this._width); |
|
this.container.setHeight(this._height); |
|
|
|
this._calculateChildrenToRender(); |
|
// 元素未挂载时不能设置scrollTop |
|
try { |
|
this.element.scrollTop(o.scrollTop); |
|
this.element.scrollLeft(o.scrollLeft); |
|
} catch (e) { |
|
} |
|
} |
|
}, |
|
|
|
setScrollLeft: function (scrollLeft) { |
|
if (this.options.scrollLeft === scrollLeft) { |
|
return; |
|
} |
|
this._scrollLock = true; |
|
this.options.scrollLeft = BI.clamp(scrollLeft || 0, 0, this._getMaxScrollLeft()); |
|
this._debounceRelease(); |
|
this._calculateChildrenToRender(); |
|
this.element.scrollLeft(this.options.scrollLeft); |
|
}, |
|
|
|
setScrollTop: function (scrollTop) { |
|
if (this.options.scrollTop === scrollTop) { |
|
return; |
|
} |
|
this._scrollLock = true; |
|
this.options.scrollTop = BI.clamp(scrollTop || 0, 0, this._getMaxScrollTop()); |
|
this._debounceRelease(); |
|
this._calculateChildrenToRender(); |
|
this.element.scrollTop(this.options.scrollTop); |
|
}, |
|
|
|
setOverflowX: function (b) { |
|
var self = this; |
|
if (this.options.overflowX !== !!b) { |
|
this.options.overflowX = !!b; |
|
BI.nextTick(function () { |
|
self.element.css({overflowX: b ? "auto" : "hidden"}); |
|
}); |
|
} |
|
}, |
|
|
|
setOverflowY: function (b) { |
|
var self = this; |
|
if (this.options.overflowY !== !!b) { |
|
this.options.overflowY = !!b; |
|
BI.nextTick(function () { |
|
self.element.css({overflowY: b ? "auto" : "hidden"}); |
|
}); |
|
} |
|
}, |
|
|
|
getScrollLeft: function () { |
|
return this.options.scrollLeft; |
|
}, |
|
|
|
getScrollTop: function () { |
|
return this.options.scrollTop; |
|
}, |
|
|
|
getMaxScrollLeft: function () { |
|
return this._getMaxScrollLeft(); |
|
}, |
|
|
|
getMaxScrollTop: function () { |
|
return this._getMaxScrollTop(); |
|
}, |
|
|
|
// 重新计算children |
|
_reRange: function () { |
|
this.renderRange = {}; |
|
}, |
|
|
|
_clearChildren: function () { |
|
this.container._children = {}; |
|
this.container.attr("items", []); |
|
}, |
|
|
|
restore: function () { |
|
BI.each(this.renderedCells, function (i, cell) { |
|
cell.el._destroy(); |
|
}); |
|
this._clearChildren(); |
|
this.renderedCells = []; |
|
this.renderedKeys = []; |
|
this.renderRange = {}; |
|
this._scrollLock = false; |
|
}, |
|
|
|
populate: function (items) { |
|
if (items && items !== this.options.items) { |
|
this.restore(); |
|
} |
|
this._populate(items); |
|
} |
|
}); |
|
BI.CollectionView.EVENT_SCROLL = "EVENT_SCROLL"; |
|
BI.shortcut("bi.collection_view", BI.CollectionView);/** |
|
* @class BI.Combo |
|
* @extends BI.Widget |
|
*/ |
|
BI.Combo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.Combo.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-combo", |
|
trigger: "click", |
|
toggle: true, |
|
direction: "bottom", // top||bottom||left||right||top,left||top,right||bottom,left||bottom,right||right,innerRight||right,innerLeft||innerRight||innerLeft |
|
logic: { |
|
dynamic: true |
|
}, |
|
container: null, // popupview放置的容器,默认为this.element |
|
isDefaultInit: false, |
|
destroyWhenHide: false, |
|
isNeedAdjustHeight: true, // 是否需要高度调整 |
|
isNeedAdjustWidth: true, |
|
stopEvent: false, |
|
stopPropagation: false, |
|
adjustLength: 0, // 调整的距离 |
|
adjustXOffset: 0, |
|
adjustYOffset: 0, |
|
hideChecker: BI.emptyFn, |
|
offsetStyle: "left", // left,right,center |
|
el: {}, |
|
popup: {}, |
|
comboClass: "bi-combo-popup", |
|
hoverClass: "bi-combo-hover" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Combo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this._initCombo(); |
|
this._initPullDownAction(); |
|
this.combo.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (self.isEnabled() && self.isValid()) { |
|
if (type === BI.Events.EXPAND) { |
|
self._popupView(); |
|
} |
|
if (type === BI.Events.COLLAPSE) { |
|
self._hideView(); |
|
} |
|
if (type === BI.Events.EXPAND) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.fireEvent(BI.Combo.EVENT_EXPAND); |
|
} |
|
if (type === BI.Events.COLLAPSE) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.isViewVisible() && self.fireEvent(BI.Combo.EVENT_COLLAPSE); |
|
} |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.Combo.EVENT_TRIGGER_CHANGE, obj); |
|
} |
|
} |
|
}); |
|
|
|
self.element.on("mouseenter." + self.getName(), function (e) { |
|
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) { |
|
self.element.addClass(o.hoverClass); |
|
} |
|
}); |
|
self.element.on("mouseleave." + self.getName(), function (e) { |
|
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) { |
|
self.element.removeClass(o.hoverClass); |
|
} |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("vertical", BI.extend(o.logic, { |
|
items: [ |
|
{ el: this.combo } |
|
] |
|
})))); |
|
o.isDefaultInit && (this._assertPopupView()); |
|
BI.Resizers.add(this.getName(), BI.bind(function () { |
|
if (this.isViewVisible()) { |
|
this._hideView(); |
|
} |
|
}, this)); |
|
}, |
|
|
|
_toggle: function () { |
|
this._assertPopupViewRender(); |
|
if (this.popupView.isVisible()) { |
|
this._hideView(); |
|
} else { |
|
if (this.isEnabled()) { |
|
this._popupView(); |
|
} |
|
} |
|
}, |
|
|
|
_initPullDownAction: function () { |
|
var self = this, o = this.options; |
|
var evs = (this.options.trigger || "").split(","); |
|
var st = function (e) { |
|
if (o.stopEvent) { |
|
e.stopEvent(); |
|
} |
|
if (o.stopPropagation) { |
|
e.stopPropagation(); |
|
} |
|
}; |
|
|
|
var enterPopup = false; |
|
|
|
function hide () { |
|
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid() && o.toggle === true) { |
|
self._hideView(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.combo); |
|
self.fireEvent(BI.Combo.EVENT_COLLAPSE); |
|
} |
|
self.popupView && self.popupView.element.off("mouseenter." + self.getName()).off("mouseleave." + self.getName()); |
|
enterPopup = false; |
|
} |
|
|
|
BI.each(evs, function (i, ev) { |
|
switch (ev) { |
|
case "hover": |
|
self.element.on("mouseenter." + self.getName(), function (e) { |
|
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) { |
|
self._popupView(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.combo); |
|
self.fireEvent(BI.Combo.EVENT_EXPAND); |
|
} |
|
}); |
|
self.element.on("mouseleave." + self.getName(), function (e) { |
|
if (self.popupView) { |
|
self.popupView.element.on("mouseenter." + self.getName(), function (e) { |
|
enterPopup = true; |
|
self.popupView.element.on("mouseleave." + self.getName(), function (e) { |
|
hide(); |
|
}); |
|
self.popupView.element.off("mouseenter." + self.getName()); |
|
}); |
|
BI.defer(function () { |
|
if (!enterPopup) { |
|
hide(); |
|
} |
|
}, 50); |
|
} |
|
}); |
|
break; |
|
case "click": |
|
var debounce = BI.debounce(function (e) { |
|
if (self.combo.element.__isMouseInBounds__(e)) { |
|
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) { |
|
// if (!o.toggle && self.isViewVisible()) { |
|
// return; |
|
// } |
|
o.toggle ? self._toggle() : self._popupView(); |
|
if (self.isViewVisible()) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.combo); |
|
self.fireEvent(BI.Combo.EVENT_EXPAND); |
|
} else { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.combo); |
|
self.fireEvent(BI.Combo.EVENT_COLLAPSE); |
|
} |
|
} |
|
} |
|
}, BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
self.element.off(ev + "." + self.getName()).on(ev + "." + self.getName(), function (e) { |
|
debounce(e); |
|
st(e); |
|
}); |
|
break; |
|
case "click-hover": |
|
var debounce = BI.debounce(function (e) { |
|
if (self.combo.element.__isMouseInBounds__(e)) { |
|
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) { |
|
// if (self.isViewVisible()) { |
|
// return; |
|
// } |
|
self._popupView(); |
|
if (self.isViewVisible()) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.combo); |
|
self.fireEvent(BI.Combo.EVENT_EXPAND); |
|
} |
|
} |
|
} |
|
}, BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
self.element.off("click." + self.getName()).on("click." + self.getName(), function (e) { |
|
debounce(e); |
|
st(e); |
|
}); |
|
self.element.on("mouseleave." + self.getName(), function (e) { |
|
if (self.popupView) { |
|
self.popupView.element.on("mouseenter." + self.getName(), function (e) { |
|
enterPopup = true; |
|
self.popupView.element.on("mouseleave." + self.getName(), function (e) { |
|
hide(); |
|
}); |
|
self.popupView.element.off("mouseenter." + self.getName()); |
|
}); |
|
BI.defer(function () { |
|
if (!enterPopup) { |
|
hide(); |
|
} |
|
}, 50); |
|
} |
|
}); |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
_initCombo: function () { |
|
this.combo = BI.createWidget(this.options.el, { |
|
value: this.options.value |
|
}); |
|
}, |
|
|
|
_assertPopupView: function () { |
|
var self = this, o = this.options; |
|
if (this.popupView == null) { |
|
this.popupView = BI.createWidget(this.options.popup, { |
|
type: "bi.popup_view", |
|
value: o.value |
|
}, this); |
|
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (type === BI.Events.CLICK) { |
|
self.combo.setValue(self.getValue()); |
|
self.fireEvent(BI.Combo.EVENT_CHANGE, value, obj); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.popupView.setVisible(false); |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.Combo.EVENT_AFTER_INIT); |
|
}); |
|
} |
|
}, |
|
|
|
_assertPopupViewRender: function () { |
|
this._assertPopupView(); |
|
if (!this._rendered) { |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this.options.container || this, |
|
items: [ |
|
{el: this.popupView} |
|
] |
|
}); |
|
this._rendered = true; |
|
} |
|
}, |
|
|
|
_hideIf: function (e) { |
|
// if (this.element.__isMouseInBounds__(e) || (this.popupView && this.popupView.element.__isMouseInBounds__(e))) { |
|
// return; |
|
// } |
|
// BI-10290 公式combo双击公式内容会收起 |
|
if ((this.element.find(e.target).length > 0) |
|
|| (this.popupView && this.popupView.element.find(e.target).length > 0) |
|
|| e.target.className === "CodeMirror-cursor" || BI.Widget._renderEngine.createElement(e.target).closest(".CodeMirror-hints").length > 0) {// BI-9887 CodeMirror的公式弹框需要特殊处理下 |
|
var directions = this.options.direction.split(","); |
|
if (BI.contains(directions, "innerLeft") || BI.contains(directions, "innerRight")) { |
|
// popup可以出现的trigger内部的combo,滚动时不需要消失,而是调整位置 |
|
this.adjustWidth(); |
|
this.adjustHeight(); |
|
} |
|
return; |
|
} |
|
var isHide = this.options.hideChecker.apply(this, [e]); |
|
if (isHide === false) { |
|
return; |
|
} |
|
this._hideView(); |
|
}, |
|
|
|
_hideView: function () { |
|
this.fireEvent(BI.Combo.EVENT_BEFORE_HIDEVIEW); |
|
if (this.options.destroyWhenHide === true) { |
|
this.popupView && this.popupView.destroy(); |
|
this.popupView = null; |
|
this._rendered = false; |
|
} else { |
|
this.popupView && this.popupView.invisible(); |
|
} |
|
this.element.removeClass(this.options.comboClass); |
|
|
|
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName()); |
|
this.fireEvent(BI.Combo.EVENT_AFTER_HIDEVIEW); |
|
}, |
|
|
|
_popupView: function (e) { |
|
this._assertPopupViewRender(); |
|
this.fireEvent(BI.Combo.EVENT_BEFORE_POPUPVIEW); |
|
|
|
this.popupView.visible(); |
|
this.adjustWidth(e); |
|
this.adjustHeight(e); |
|
|
|
this.element.addClass(this.options.comboClass); |
|
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName()); |
|
BI.Widget._renderEngine.createElement(document).bind("mousedown." + this.getName(), BI.bind(this._hideIf, this)).bind("mousewheel." + this.getName(), BI.bind(this._hideIf, this)); |
|
this.fireEvent(BI.Combo.EVENT_AFTER_POPUPVIEW); |
|
}, |
|
|
|
adjustWidth: function (e) { |
|
var o = this.options; |
|
if (!this.popupView) { |
|
return; |
|
} |
|
if (o.isNeedAdjustWidth === true) { |
|
this.resetListWidth(""); |
|
var width = this.popupView.element.outerWidth(); |
|
var maxW = this.element.outerWidth() || o.width; |
|
if (width > maxW + 80) { |
|
maxW = maxW + 80; |
|
} else if (width > maxW) { |
|
maxW = width; |
|
} |
|
this.resetListWidth(maxW < 100 ? 100 : maxW); |
|
} |
|
}, |
|
|
|
adjustHeight: function (e) { |
|
var o = this.options, p = {}; |
|
if (!this.popupView) { |
|
return; |
|
} |
|
var isVisible = this.popupView.isVisible(); |
|
this.popupView.visible(); |
|
var combo = BI.isNotNull(e) ? { |
|
element: { |
|
offset: function () { |
|
return { |
|
left: e.pageX, |
|
top: e.pageY |
|
}; |
|
}, |
|
bounds: function () { |
|
// offset为其相对于父定位元素的偏移 |
|
return { |
|
x: e.offsetX, |
|
y: e.offsetY, |
|
width: 0, |
|
height: 24 |
|
}; |
|
}, |
|
outerWidth: function () { |
|
return 0; |
|
}, |
|
outerHeight: function () { |
|
return 24; |
|
} |
|
} |
|
} : this.combo; |
|
switch (o.direction) { |
|
case "bottom": |
|
case "bottom,right": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["bottom", "top", "right", "left"], o.offsetStyle); |
|
break; |
|
case "top": |
|
case "top,right": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["top", "bottom", "right", "left"], o.offsetStyle); |
|
break; |
|
case "left": |
|
case "left,bottom": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "bottom", "top"], o.offsetStyle); |
|
break; |
|
case "right": |
|
case "right,bottom": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "bottom", "top"], o.offsetStyle); |
|
break; |
|
case "top,left": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["top", "bottom", "left", "right"], o.offsetStyle); |
|
break; |
|
case "bottom,left": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["bottom", "top", "left", "right"], o.offsetStyle); |
|
break; |
|
case "left,top": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "top", "bottom"], o.offsetStyle); |
|
break; |
|
case "right,top": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "top", "bottom"], o.offsetStyle); |
|
break; |
|
case "right,innerRight": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerRight", "innerLeft", "bottom", "top"], o.offsetStyle); |
|
break; |
|
case "right,innerLeft": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerLeft", "innerRight", "bottom", "top"], o.offsetStyle); |
|
break; |
|
case "innerRight": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["innerRight", "innerLeft", "right", "left", "bottom", "top"], o.offsetStyle); |
|
break; |
|
case "innerLeft": |
|
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["innerLeft", "innerRight", "left", "right", "bottom", "top"], o.offsetStyle); |
|
break; |
|
case "top,custom": |
|
case "custom,top": |
|
p = BI.DOM.getTopAdaptPosition(combo, this.popupView, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight); |
|
break; |
|
case "custom,bottom": |
|
case "bottom,custom": |
|
p = BI.DOM.getBottomAdaptPosition(combo, this.popupView, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight); |
|
break; |
|
case "left,custom": |
|
case "custom,left": |
|
p = BI.DOM.getLeftAdaptPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength); |
|
delete p.top; |
|
delete p.adaptHeight; |
|
break; |
|
case "custom,right": |
|
case "right,custom": |
|
p = BI.DOM.getRightAdaptPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength); |
|
delete p.top; |
|
delete p.adaptHeight; |
|
break; |
|
} |
|
|
|
if ("adaptHeight" in p) { |
|
this.resetListHeight(p["adaptHeight"]); |
|
} |
|
if ("left" in p) { |
|
this.popupView.element.css({ |
|
left: p.left |
|
}); |
|
} |
|
if ("top" in p) { |
|
this.popupView.element.css({ |
|
top: p.top |
|
}); |
|
} |
|
this.position = p; |
|
this.popupView.setVisible(isVisible); |
|
}, |
|
|
|
resetListHeight: function (h) { |
|
this._assertPopupView(); |
|
this.popupView.resetHeight && this.popupView.resetHeight(h); |
|
}, |
|
|
|
resetListWidth: function (w) { |
|
this._assertPopupView(); |
|
this.popupView.resetWidth && this.popupView.resetWidth(w); |
|
}, |
|
|
|
populate: function (items) { |
|
this._assertPopupView(); |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
this.combo.populate.apply(this.combo, arguments); |
|
}, |
|
|
|
_setEnable: function (arg) { |
|
BI.Combo.superclass._setEnable.apply(this, arguments); |
|
if (arg === true) { |
|
this.element.removeClass("base-disabled disabled"); |
|
} else if (arg === false) { |
|
this.element.addClass("base-disabled disabled"); |
|
} |
|
!arg && this.element.removeClass(this.options.hoverClass); |
|
!arg && this.isViewVisible() && this._hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
if (BI.isNull(this.popupView)) { |
|
this.options.popup.value = v; |
|
} else { |
|
this.popupView.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
if (BI.isNull(this.popupView)) { |
|
return this.options.popup.value; |
|
} else { |
|
return this.popupView.getValue(); |
|
} |
|
}, |
|
|
|
isViewVisible: function () { |
|
return this.isEnabled() && this.combo.isEnabled() && !!this.popupView && this.popupView.isVisible(); |
|
}, |
|
|
|
showView: function (e) { |
|
// 减少popup 调整宽高的次数 |
|
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) { |
|
this._popupView(e); |
|
} |
|
}, |
|
|
|
hideView: function () { |
|
this._hideView(); |
|
}, |
|
|
|
getView: function () { |
|
return this.popupView; |
|
}, |
|
|
|
getPopupPosition: function () { |
|
return this.position; |
|
}, |
|
|
|
toggle: function () { |
|
this._toggle(); |
|
}, |
|
|
|
destroyed: function () { |
|
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()) |
|
.unbind("mousewheel." + this.getName()) |
|
.unbind("mouseenter." + this.getName()) |
|
.unbind("mousemove." + this.getName()) |
|
.unbind("mouseleave." + this.getName()); |
|
BI.Resizers.remove(this.getName()); |
|
this.popupView && this.popupView._destroy(); |
|
} |
|
}); |
|
BI.Combo.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE"; |
|
BI.Combo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.Combo.EVENT_EXPAND = "EVENT_EXPAND"; |
|
BI.Combo.EVENT_COLLAPSE = "EVENT_COLLAPSE"; |
|
BI.Combo.EVENT_AFTER_INIT = "EVENT_AFTER_INIT"; |
|
|
|
|
|
BI.Combo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.Combo.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW"; |
|
BI.Combo.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW"; |
|
BI.Combo.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW"; |
|
|
|
BI.shortcut("bi.combo", BI.Combo);/** |
|
* |
|
* 某个可以展开的节点 |
|
* |
|
* Created by GUY on 2015/9/10. |
|
* @class BI.Expander |
|
* @extends BI.Widget |
|
*/ |
|
BI.Expander = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Expander.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-expander", |
|
trigger: "click", |
|
toggle: true, |
|
// direction: "bottom", //top,bottom四个方向 |
|
isDefaultInit: false, // 是否默认初始化子节点 |
|
el: {}, |
|
popup: {}, |
|
expanderClass: "bi-expander-popup", |
|
hoverClass: "bi-expander-hover" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Expander.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this._expanded = !!o.el.open; |
|
this._initExpander(); |
|
this._initPullDownAction(); |
|
this.expander.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (self.isEnabled() && self.isValid()) { |
|
if (type === BI.Events.EXPAND) { |
|
self._popupView(); |
|
} |
|
if (type === BI.Events.COLLAPSE) { |
|
self._hideView(); |
|
} |
|
if (type === BI.Events.EXPAND) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.fireEvent(BI.Expander.EVENT_EXPAND); |
|
} |
|
if (type === BI.Events.COLLAPSE) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.isViewVisible() && self.fireEvent(BI.Expander.EVENT_COLLAPSE); |
|
} |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.Expander.EVENT_TRIGGER_CHANGE, value, obj); |
|
} |
|
} |
|
}); |
|
|
|
this.element.hover(function () { |
|
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) { |
|
self.element.addClass(o.hoverClass); |
|
} |
|
}, function () { |
|
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) { |
|
self.element.removeClass(o.hoverClass); |
|
} |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [ |
|
{el: this.expander} |
|
] |
|
}); |
|
o.isDefaultInit && this._assertPopupView(); |
|
if (this.expander.isOpened() === true) { |
|
this._popupView(); |
|
} |
|
}, |
|
|
|
_toggle: function () { |
|
this._assertPopupViewRender(); |
|
if (this.popupView.isVisible()) { |
|
this._hideView(); |
|
} else { |
|
if (this.isEnabled()) { |
|
this._popupView(); |
|
} |
|
} |
|
}, |
|
|
|
_initPullDownAction: function () { |
|
var self = this, o = this.options; |
|
var evs = this.options.trigger.split(","); |
|
BI.each(evs, function (i, e) { |
|
switch (e) { |
|
case "hover": |
|
self.element[e](function (e) { |
|
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) { |
|
self._popupView(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.expander); |
|
self.fireEvent(BI.Expander.EVENT_EXPAND); |
|
} |
|
}, function () { |
|
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid() && o.toggle) { |
|
self._hideView(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.expander); |
|
self.fireEvent(BI.Expander.EVENT_COLLAPSE); |
|
} |
|
}); |
|
break; |
|
case "click": |
|
if (e) { |
|
self.element.off(e + "." + self.getName()).on(e + "." + self.getName(), BI.debounce(function (e) { |
|
if (self.expander.element.__isMouseInBounds__(e)) { |
|
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) { |
|
o.toggle ? self._toggle() : self._popupView(); |
|
if (self.isExpanded()) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.expander); |
|
self.fireEvent(BI.Expander.EVENT_EXPAND); |
|
} else { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.expander); |
|
self.fireEvent(BI.Expander.EVENT_COLLAPSE); |
|
} |
|
} |
|
} |
|
}, BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
})); |
|
} |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
_initExpander: function () { |
|
this.expander = BI.createWidget(this.options.el); |
|
}, |
|
|
|
_assertPopupView: function () { |
|
var self = this, o = this.options; |
|
if (this.popupView == null) { |
|
this.popupView = BI.createWidget(this.options.popup, { |
|
type: "bi.button_group", |
|
cls: "expander-popup", |
|
layouts: [{ |
|
type: "bi.vertical", |
|
hgap: 0, |
|
vgap: 0 |
|
}], |
|
value: o.value |
|
}, this); |
|
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
// self.setValue(self.getValue()); |
|
self.fireEvent(BI.Expander.EVENT_CHANGE, value, obj); |
|
} |
|
}); |
|
this.popupView.setVisible(this.isExpanded()); |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.Expander.EVENT_AFTER_INIT); |
|
}); |
|
} |
|
}, |
|
|
|
_assertPopupViewRender: function () { |
|
this._assertPopupView(); |
|
if (!this._rendered) { |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [ |
|
{el: this.popupView} |
|
] |
|
}); |
|
this._rendered = true; |
|
} |
|
}, |
|
|
|
_hideView: function () { |
|
this.fireEvent(BI.Expander.EVENT_BEFORE_HIDEVIEW); |
|
this._expanded = false; |
|
this.expander.setOpened(false); |
|
this.popupView && this.popupView.invisible(); |
|
this.element.removeClass(this.options.expanderClass); |
|
|
|
this.fireEvent(BI.Expander.EVENT_AFTER_HIDEVIEW); |
|
}, |
|
|
|
_popupView: function () { |
|
this._assertPopupViewRender(); |
|
this.fireEvent(BI.Expander.EVENT_BEFORE_POPUPVIEW); |
|
this._expanded = true; |
|
this.expander.setOpened(true); |
|
this.popupView.visible(); |
|
this.element.addClass(this.options.expanderClass); |
|
this.fireEvent(BI.Expander.EVENT_AFTER_POPUPVIEW); |
|
}, |
|
|
|
populate: function (items) { |
|
// this._assertPopupView(); |
|
this.popupView && this.popupView.populate.apply(this.popupView, arguments); |
|
this.expander.populate.apply(this.expander, arguments); |
|
}, |
|
|
|
_setEnable: function (arg) { |
|
BI.Expander.superclass._setEnable.apply(this, arguments); |
|
!arg && this.element.removeClass(this.options.hoverClass); |
|
!arg && this.isViewVisible() && this._hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.expander.setValue(v); |
|
if (BI.isNull(this.popupView)) { |
|
this.options.popup.value = v; |
|
} else { |
|
this.popupView.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
if (BI.isNull(this.popupView)) { |
|
return this.options.popup.value; |
|
} else { |
|
return this.popupView.getValue(); |
|
} |
|
}, |
|
|
|
isViewVisible: function () { |
|
return this.isEnabled() && this.expander.isEnabled() && !!this.popupView && this.popupView.isVisible(); |
|
}, |
|
|
|
isExpanded: function () { |
|
return this._expanded; |
|
}, |
|
|
|
showView: function () { |
|
if (this.isEnabled() && this.expander.isEnabled()) { |
|
this._popupView(); |
|
} |
|
}, |
|
|
|
hideView: function () { |
|
this._hideView(); |
|
}, |
|
|
|
getView: function () { |
|
return this.popupView; |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.popupView && this.popupView.getAllLeaves(); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
if (this.expander.options.id === id) { |
|
return this.expander; |
|
} |
|
return this.popupView && this.popupView.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
if (this.expander.getValue() === value) { |
|
return this.expander; |
|
} |
|
return this.popupView && this.popupView.getNodeByValue(value); |
|
}, |
|
|
|
destroy: function () { |
|
BI.Expander.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.Expander.EVENT_EXPAND = "EVENT_EXPAND"; |
|
BI.Expander.EVENT_COLLAPSE = "EVENT_COLLAPSE"; |
|
BI.Expander.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE"; |
|
BI.Expander.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.Expander.EVENT_AFTER_INIT = "EVENT_AFTER_INIT"; |
|
|
|
|
|
BI.Expander.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.Expander.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW"; |
|
BI.Expander.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW"; |
|
BI.Expander.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW"; |
|
|
|
BI.shortcut("bi.expander", BI.Expander);/** |
|
* Created by GUY on 2015/8/10. |
|
*/ |
|
|
|
BI.ComboGroup = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ComboGroup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-combo-group bi-list-item", |
|
|
|
// 以下这些属性对每一个combo都是公用的 |
|
trigger: "click,hover", |
|
direction: "right", |
|
adjustLength: 0, |
|
isDefaultInit: false, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
|
|
el: {type: "bi.text_button", text: "", value: ""}, |
|
children: [], |
|
|
|
popup: { |
|
el: { |
|
type: "bi.button_tree", |
|
chooseType: 0, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ComboGroup.superclass._init.apply(this, arguments); |
|
this._populate(this.options.el); |
|
}, |
|
|
|
_populate: function (item) { |
|
var self = this, o = this.options; |
|
var children = o.children; |
|
if (BI.isEmpty(children)) { |
|
throw new Error("ComboGroup构造错误"); |
|
} |
|
BI.each(children, function (i, ch) { |
|
var son = BI.formatEL(ch).el.children; |
|
ch = BI.formatEL(ch).el; |
|
if (!BI.isEmpty(son)) { |
|
ch.el = BI.clone(ch); |
|
ch.children = son; |
|
ch.type = "bi.combo_group"; |
|
ch.action = o.action; |
|
ch.height = o.height; |
|
ch.direction = o.direction; |
|
ch.isDefaultInit = o.isDefaultInit; |
|
ch.isNeedAdjustHeight = o.isNeedAdjustHeight; |
|
ch.isNeedAdjustWidth = o.isNeedAdjustWidth; |
|
ch.adjustLength = o.adjustLength; |
|
ch.popup = o.popup; |
|
} |
|
}); |
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
element: this, |
|
container: o.container, |
|
height: o.height, |
|
trigger: o.trigger, |
|
direction: o.direction, |
|
isDefaultInit: o.isDefaultInit, |
|
isNeedAdjustWidth: o.isNeedAdjustWidth, |
|
isNeedAdjustHeight: o.isNeedAdjustHeight, |
|
adjustLength: o.adjustLength, |
|
el: item, |
|
popup: BI.extend({}, o.popup, { |
|
el: BI.extend({ |
|
items: children |
|
}, o.popup.el) |
|
}) |
|
}); |
|
this.combo.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.ComboGroup.EVENT_CHANGE, obj); |
|
} |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return this.combo.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
} |
|
}); |
|
BI.ComboGroup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.combo_group", BI.ComboGroup);BI.VirtualGroup = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.VirtualGroup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-virtual-group", |
|
items: [], |
|
layouts: [{ |
|
type: "bi.center", |
|
hgap: 0, |
|
vgap: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var o = this.options; |
|
this.populate(o.items); |
|
if (BI.isKey(o.value)) { |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_packageBtns: function (items) { |
|
var o = this.options; |
|
var map = this.buttonMap = {}; |
|
for (var i = o.layouts.length - 1; i > 0; i--) { |
|
items = BI.map(items, function (k, it) { |
|
var el = BI.stripEL(it); |
|
return BI.extend({}, o.layouts[i], { |
|
items: [ |
|
BI.extend({}, o.layouts[i].el, { |
|
el: BI.extend({ |
|
ref: function (_ref) { |
|
if (BI.isKey(map[el.value])) { |
|
map[el.value] = _ref; |
|
} |
|
} |
|
}, el) |
|
}) |
|
] |
|
}); |
|
}); |
|
} |
|
return items; |
|
}, |
|
|
|
_packageLayout: function (items) { |
|
var o = this.options, layout = BI.deepClone(o.layouts[0]); |
|
|
|
var lay = BI.formatEL(layout).el; |
|
while (lay && lay.items && !BI.isEmpty(lay.items)) { |
|
lay = BI.formatEL(lay.items[0]).el; |
|
} |
|
lay.items = items; |
|
return layout; |
|
}, |
|
|
|
addItems: function (items) { |
|
this.layouts.addItems(items); |
|
}, |
|
|
|
prependItems: function (items) { |
|
this.layouts.prependItems(items); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
BI.each(this.buttonMap, function (key, item) { |
|
if (item) { |
|
if (v.deepContains(key)) { |
|
item.setSelected && item.setSelected(true); |
|
} else { |
|
item.setSelected && item.setSelected(false); |
|
} |
|
} |
|
}); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
var v = []; |
|
BI.each(this.buttonMap, function (i, item) { |
|
if (item) { |
|
if (item.isEnabled() && !(item.isSelected && item.isSelected())) { |
|
v.push(item.getValue()); |
|
} |
|
} |
|
}); |
|
return v; |
|
}, |
|
|
|
getValue: function () { |
|
var v = []; |
|
BI.each(this.buttonMap, function (i, item) { |
|
if (item) { |
|
if (item.isEnabled() && item.isSelected && item.isSelected()) { |
|
v.push(item.getValue()); |
|
} |
|
} |
|
}); |
|
return v; |
|
}, |
|
|
|
populate: function (items) { |
|
var self = this; |
|
items = items || []; |
|
this.options.items = items; |
|
items = this._packageBtns(items); |
|
if (!this.layouts) { |
|
this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items))); |
|
} else { |
|
this.layouts.populate(items); |
|
} |
|
} |
|
}); |
|
BI.VirtualGroup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.virtual_group", BI.VirtualGroup);/** |
|
* 加载控件 |
|
* |
|
* Created by GUY on 2015/8/31. |
|
* @class BI.Loader |
|
* @extends BI.Widget |
|
*/ |
|
BI.Loader = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Loader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-loader", |
|
|
|
direction: "top", |
|
isDefaultInit: true, // 是否默认初始化数据 |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
|
|
// 下面是button_group的属性 |
|
el: { |
|
type: "bi.button_group" |
|
}, |
|
|
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn, |
|
|
|
// 下面是分页信息 |
|
count: false, |
|
prev: false, |
|
next: {}, |
|
hasPrev: BI.emptyFn, |
|
hasNext: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_prevLoad: function () { |
|
var self = this, o = this.options; |
|
this.prev.setLoading(); |
|
o.itemsCreator.apply(this, [{times: --this.times}, function () { |
|
self.prev.setLoaded(); |
|
self.prependItems.apply(self, arguments); |
|
}]); |
|
}, |
|
|
|
_nextLoad: function () { |
|
var self = this, o = this.options; |
|
this.next.setLoading(); |
|
o.itemsCreator.apply(this, [{times: ++this.times}, function () { |
|
self.next.setLoaded(); |
|
self.addItems.apply(self, arguments); |
|
}]); |
|
}, |
|
|
|
_init: function () { |
|
BI.Loader.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (o.itemsCreator === false) { |
|
o.prev = false; |
|
o.next = false; |
|
} |
|
if (o.prev !== false) { |
|
this.prev = BI.createWidget(BI.extend({ |
|
type: "bi.loading_bar" |
|
}, o.prev)); |
|
this.prev.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self._prevLoad(); |
|
} |
|
}); |
|
} |
|
|
|
this.button_group = BI.createWidget(o.el, { |
|
type: "bi.button_group", |
|
chooseType: 0, |
|
items: o.items, |
|
behaviors: {}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
value: o.value |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.Loader.EVENT_CHANGE, obj); |
|
} |
|
}); |
|
|
|
if (o.next !== false) { |
|
this.next = BI.createWidget(BI.extend({ |
|
type: "bi.loading_bar" |
|
}, o.next)); |
|
this.next.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self._nextLoad(); |
|
} |
|
}); |
|
} |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({ |
|
scrolly: true |
|
}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.prev, this.button_group, this.next) |
|
})))); |
|
|
|
o.isDefaultInit && BI.isEmpty(o.items) && BI.nextTick(BI.bind(function () { |
|
o.isDefaultInit && BI.isEmpty(o.items) && this._populate(); |
|
}, this)); |
|
if (BI.isNotEmptyArray(o.items)) { |
|
this._populate(o.items); |
|
} |
|
}, |
|
|
|
hasPrev: function () { |
|
var o = this.options; |
|
if (BI.isNumber(o.count)) { |
|
return this.count < o.count; |
|
} |
|
return !!o.hasPrev.apply(this, [{ |
|
times: this.times, |
|
count: this.count |
|
}]); |
|
}, |
|
|
|
hasNext: function () { |
|
var o = this.options; |
|
if (BI.isNumber(o.count)) { |
|
return this.count < o.count; |
|
} |
|
return !!o.hasNext.apply(this, [{ |
|
times: this.times, |
|
count: this.count |
|
}]); |
|
}, |
|
|
|
prependItems: function (items) { |
|
this.count += items.length; |
|
if (this.next !== false) { |
|
if (this.hasPrev()) { |
|
this.options.items = this.options.items.concat(items); |
|
this.prev.setLoaded(); |
|
} else { |
|
this.prev.setEnd(); |
|
} |
|
} |
|
this.button_group.prependItems.apply(this.button_group, arguments); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.count += items.length; |
|
if (BI.isObject(this.next)) { |
|
if (this.hasNext()) { |
|
this.options.items = this.options.items.concat(items); |
|
this.next.setLoaded(); |
|
} else { |
|
this.next.setEnd(); |
|
} |
|
} |
|
this.button_group.addItems.apply(this.button_group, arguments); |
|
}, |
|
|
|
|
|
_populate: function (items) { |
|
var self = this, o = this.options; |
|
if (arguments.length === 0 && (BI.isFunction(o.itemsCreator))) { |
|
o.itemsCreator.apply(this, [{times: 1}, function () { |
|
if (arguments.length === 0) { |
|
throw new Error("arguments can not be null!!!"); |
|
} |
|
self.populate.apply(self, arguments); |
|
o.onLoaded(); |
|
}]); |
|
return false; |
|
} |
|
this.options.items = items; |
|
this.times = 1; |
|
this.count = 0; |
|
this.count += items.length; |
|
if (BI.isObject(this.next)) { |
|
if (this.hasNext()) { |
|
this.next.setLoaded(); |
|
} else { |
|
this.next.invisible(); |
|
} |
|
} |
|
if (BI.isObject(this.prev)) { |
|
if (this.hasPrev()) { |
|
this.prev.setLoaded(); |
|
} else { |
|
this.prev.invisible(); |
|
} |
|
} |
|
return true; |
|
}, |
|
|
|
populate: function () { |
|
this._populate.apply(this, arguments) && this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.button_group.setNotSelectedValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.button_group.getNotSelectedValue(); |
|
}, |
|
|
|
setValue: function () { |
|
this.button_group.setValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.button_group.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.button_group.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.button_group.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.button_group.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.button_group.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.button_group.getNodeByValue(value); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
BI.each([this.prev, this.next], function (i, ob) { |
|
ob && ob.setVisible(false); |
|
}); |
|
}, |
|
|
|
destroy: function () { |
|
BI.Loader.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.Loader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.loader", BI.Loader);/** |
|
* Created by GUY on 2015/6/26. |
|
*/ |
|
|
|
BI.Navigation = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Navigation.superclass._defaultConfig.apply(this, arguments), { |
|
direction: "bottom", // top, bottom, left, right, custom |
|
logic: { |
|
dynamic: false |
|
}, |
|
single: false, |
|
showIndex: false, |
|
tab: false, |
|
cardCreator: function (v) { |
|
return BI.createWidget(); |
|
}, |
|
|
|
afterCardCreated: BI.emptyFn, |
|
afterCardShow: BI.emptyFn |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
this.tab = BI.createWidget(this.options.tab, {type: "bi.button_group"}); |
|
this.cardMap = {}; |
|
this.showIndex = 0; |
|
this.layout = BI.createWidget({ |
|
type: "bi.card" |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tab, this.layout) |
|
})))); |
|
|
|
|
|
new BI.ShowListener({ |
|
eventObj: this.tab, |
|
cardLayout: this.layout, |
|
cardNameCreator: function (v) { |
|
return self.showIndex + v; |
|
}, |
|
cardCreator: function (v) { |
|
var card = o.cardCreator(v); |
|
self.cardMap[v] = card; |
|
return card; |
|
}, |
|
afterCardCreated: BI.bind(this.afterCardCreated, this), |
|
afterCardShow: BI.bind(this.afterCardShow, this) |
|
}); |
|
}, |
|
|
|
mounted: function () { |
|
var o = this.options; |
|
if (o.showIndex !== false) { |
|
this.setSelect(o.showIndex); |
|
} |
|
}, |
|
|
|
_deleteOtherCards: function (currCardName) { |
|
var self = this, o = this.options; |
|
if (o.single === true) { |
|
BI.each(this.cardMap, function (name, card) { |
|
if (name !== (currCardName + "")) { |
|
self.layout.deleteCardByName(name); |
|
delete self.cardMap[name]; |
|
} |
|
}); |
|
} |
|
}, |
|
|
|
afterCardCreated: function (v) { |
|
var self = this; |
|
this.cardMap[v].on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.Navigation.EVENT_CHANGE, obj); |
|
} |
|
}); |
|
this.options.afterCardCreated.apply(this, arguments); |
|
}, |
|
|
|
afterCardShow: function (v) { |
|
this.showIndex = v; |
|
this._deleteOtherCards(v); |
|
this.options.afterCardShow.apply(this, arguments); |
|
}, |
|
|
|
populate: function () { |
|
var card = this.layout.getShowingCard(); |
|
if (card) { |
|
return card.populate.apply(card, arguments); |
|
} |
|
}, |
|
|
|
_assertCard: function (v) { |
|
if (!this.layout.isCardExisted(v)) { |
|
var card = this.options.cardCreator(v); |
|
this.cardMap[v] = card; |
|
this.layout.addCardByName(v, card); |
|
this.afterCardCreated(v); |
|
} |
|
}, |
|
|
|
setSelect: function (v) { |
|
this._assertCard(v); |
|
this.layout.showCardByName(v); |
|
this._deleteOtherCards(v); |
|
if (this.showIndex !== v) { |
|
this.showIndex = v; |
|
BI.nextTick(BI.bind(this.afterCardShow, this, v)); |
|
} |
|
}, |
|
|
|
getSelect: function () { |
|
return this.showIndex; |
|
}, |
|
|
|
getSelectedCard: function () { |
|
if (BI.isKey(this.showIndex)) { |
|
return this.cardMap[this.showIndex]; |
|
} |
|
}, |
|
|
|
/** |
|
* @override |
|
*/ |
|
setValue: function (v) { |
|
var card = this.layout.getShowingCard(); |
|
if (card) { |
|
card.setValue(v); |
|
} |
|
}, |
|
|
|
/** |
|
* @override |
|
*/ |
|
getValue: function () { |
|
var card = this.layout.getShowingCard(); |
|
if (card) { |
|
return card.getValue(); |
|
} |
|
}, |
|
|
|
empty: function () { |
|
this.layout.deleteAllCard(); |
|
this.cardMap = {}; |
|
}, |
|
|
|
destroy: function () { |
|
BI.Navigation.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.Navigation.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.navigation", BI.Navigation);/** |
|
* 搜索逻辑控件 |
|
* |
|
* Created by GUY on 2015/9/28. |
|
* @class BI.Searcher |
|
* @extends BI.Widget |
|
*/ |
|
|
|
BI.Searcher = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Searcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-searcher", |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
vgap: 0, |
|
hgap: 0, |
|
|
|
isDefaultInit: false, |
|
isAutoSearch: true, // 是否自动搜索 |
|
isAutoSync: true, // 是否自动同步数据, 即是否保持搜索面板和adapter面板状态值的统一 |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
|
|
// isAutoSearch为false时启用 |
|
onSearch: function (op, callback) { |
|
callback([]); |
|
}, |
|
|
|
el: { |
|
type: "bi.search_editor" |
|
}, |
|
|
|
popup: { |
|
type: "bi.searcher_view" |
|
}, |
|
|
|
adapter: null, |
|
masker: { // masker层 |
|
offset: {} |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Searcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.search_editor" |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
vgap: o.vgap, |
|
hgap: o.hgap, |
|
items: [this.editor] |
|
}); |
|
o.isDefaultInit && (this._assertPopupView()); |
|
|
|
var search = BI.debounce(BI.bind(this._search, this), BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
switch (type) { |
|
case BI.Events.STARTEDIT: |
|
self._startSearch(); |
|
break; |
|
case BI.Events.EMPTY: |
|
self._stopSearch(); |
|
break; |
|
case BI.Events.CHANGE: |
|
search(); |
|
break; |
|
case BI.Events.PAUSE: |
|
self._pauseSearch(); |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
_assertPopupView: function () { |
|
var self = this, o = this.options; |
|
if ((o.masker && !BI.Maskers.has(this.getName())) || (o.masker === false && !this.popupView)) { |
|
this.popupView = BI.createWidget(o.popup, { |
|
type: "bi.searcher_view", |
|
chooseType: o.chooseType |
|
}); |
|
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
if (o.isAutoSync) { |
|
var values = o.adapter && o.adapter.getValue(); |
|
if (!obj.isSelected()) { |
|
o.adapter && o.adapter.setValue(BI.deepWithout(values, obj.getValue())); |
|
} else { |
|
switch (o.chooseType) { |
|
case BI.ButtonGroup.CHOOSE_TYPE_SINGLE: |
|
o.adapter && o.adapter.setValue([obj.getValue()]); |
|
break; |
|
case BI.ButtonGroup.CHOOSE_TYPE_MULTI: |
|
values.push(obj.getValue()); |
|
o.adapter && o.adapter.setValue(values); |
|
break; |
|
} |
|
} |
|
} |
|
self.fireEvent(BI.Searcher.EVENT_CHANGE, value, obj); |
|
} |
|
}); |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.Searcher.EVENT_AFTER_INIT); |
|
}); |
|
} |
|
if (o.masker && !BI.Maskers.has(this.getName())) { |
|
BI.Maskers.create(this.getName(), o.adapter, BI.extend({ |
|
container: this, |
|
render: this.popupView |
|
}, o.masker), this); |
|
} |
|
}, |
|
|
|
_startSearch: function () { |
|
this._assertPopupView(); |
|
this._stop = false; |
|
this._isSearching = true; |
|
this.fireEvent(BI.Searcher.EVENT_START); |
|
this.popupView.startSearch && this.popupView.startSearch(); |
|
// 搜索前先清空dom |
|
// BI.Maskers.get(this.getName()).empty(); |
|
BI.nextTick(function (name) { |
|
BI.Maskers.show(name); |
|
}, this.getName()); |
|
}, |
|
|
|
_pauseSearch: function () { |
|
var o = this.options, name = this.getName(); |
|
this._stop = true; |
|
BI.nextTick(function (name) { |
|
BI.Maskers.hide(name); |
|
}, this.getName()); |
|
if (this._isSearching === true) { |
|
this.popupView && this.popupView.pauseSearch && this.popupView.pauseSearch(); |
|
this.fireEvent(BI.Searcher.EVENT_PAUSE); |
|
} |
|
this._isSearching = false; |
|
}, |
|
|
|
_stopSearch: function () { |
|
var o = this.options, name = this.getName(); |
|
this._stop = true; |
|
BI.Maskers.hide(name); |
|
if (this._isSearching === true) { |
|
this.popupView && this.popupView.stopSearch && this.popupView.stopSearch(); |
|
this.fireEvent(BI.Searcher.EVENT_STOP); |
|
} |
|
this._isSearching = false; |
|
}, |
|
|
|
_search: function () { |
|
var self = this, o = this.options, keyword = this._getLastSearchKeyword(); |
|
if (keyword === "" || this._stop) { |
|
return; |
|
} |
|
if (o.isAutoSearch) { |
|
var items = (o.adapter && ((o.adapter.getItems && o.adapter.getItems()) || o.adapter.attr("items"))) || []; |
|
var finding = BI.Func.getSearchResult(items, keyword); |
|
var match = finding.match, find = finding.find; |
|
this.popupView.populate(find, match, keyword); |
|
o.isAutoSync && o.adapter && o.adapter.getValue && this.popupView.setValue(o.adapter.getValue()); |
|
self.fireEvent(BI.Searcher.EVENT_SEARCHING); |
|
return; |
|
} |
|
this.popupView.loading && this.popupView.loading(); |
|
o.onSearch({ |
|
times: 1, |
|
keyword: keyword, |
|
selectedValues: o.adapter && o.adapter.getValue() |
|
}, function (searchResult, matchResult) { |
|
if (!self._stop) { |
|
var args = [].slice.call(arguments); |
|
if (args.length > 0) { |
|
args.push(keyword); |
|
} |
|
BI.Maskers.show(self.getName()); |
|
self.popupView.populate.apply(self.popupView, args); |
|
o.isAutoSync && o.adapter && o.adapter.getValue && self.popupView.setValue(o.adapter.getValue()); |
|
self.popupView.loaded && self.popupView.loaded(); |
|
self.fireEvent(BI.Searcher.EVENT_SEARCHING); |
|
} |
|
}); |
|
}, |
|
|
|
_getLastSearchKeyword: function () { |
|
if (this.isValid()) { |
|
var res = this.editor.getValue().match(/[\S]+/g); |
|
return BI.isNull(res) ? "" : res[res.length - 1]; |
|
} |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.options.adapter = adapter; |
|
BI.Maskers.remove(this.getName()); |
|
}, |
|
|
|
doSearch: function () { |
|
if (this.isSearching()) { |
|
this._search(); |
|
} |
|
}, |
|
|
|
stopSearch: function () { |
|
this._stopSearch();// 先停止搜索,然后再去设置editor为空 |
|
// important:停止搜索必须退出编辑状态,这里必须加上try(input框不显示时blur会抛异常) |
|
try { |
|
this.editor.blur(); |
|
} catch (e) { |
|
if (!this.editor.blur) { |
|
throw new Error("editor没有实现blur方法"); |
|
} |
|
} finally { |
|
this.editor.setValue(""); |
|
} |
|
}, |
|
|
|
isSearching: function () { |
|
return this._isSearching; |
|
}, |
|
|
|
isViewVisible: function () { |
|
return this.editor.isEnabled() && BI.Maskers.isVisible(this.getName()); |
|
}, |
|
|
|
getView: function () { |
|
return this.popupView; |
|
}, |
|
|
|
hasMatched: function () { |
|
this._assertPopupView(); |
|
return this.popupView.hasMatched(); |
|
}, |
|
|
|
adjustHeight: function () { |
|
if (BI.Maskers.has(this.getName()) && BI.Maskers.get(this.getName()).isVisible()) { |
|
BI.Maskers.show(this.getName()); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.isViewVisible() && BI.Maskers.show(this.getName()); |
|
}, |
|
|
|
setValue: function (v) { |
|
if (BI.isNull(this.popupView)) { |
|
this.options.popup.value = v; |
|
} else { |
|
this.popupView.setValue(v); |
|
} |
|
}, |
|
|
|
getKeyword: function () { |
|
return this._getLastSearchKeyword(); |
|
}, |
|
|
|
getKeywords: function () { |
|
return this.editor.getKeywords(); |
|
}, |
|
|
|
getValue: function () { |
|
var o = this.options; |
|
if (o.isAutoSync && o.adapter && o.adapter.getValue) { |
|
return o.adapter.getValue(); |
|
} |
|
if (this.isSearching()) { |
|
return this.popupView.getValue(); |
|
} else if (o.adapter && o.adapter.getValue) { |
|
return o.adapter.getValue(); |
|
} |
|
if (BI.isNull(this.popupView)) { |
|
return o.popup.value; |
|
} |
|
return this.popupView.getValue(); |
|
|
|
}, |
|
|
|
populate: function (result, searchResult, keyword) { |
|
var o = this.options; |
|
this._assertPopupView(); |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
if (o.isAutoSync && o.adapter && o.adapter.getValue) { |
|
this.popupView.setValue(o.adapter.getValue()); |
|
} |
|
}, |
|
|
|
empty: function () { |
|
this.popupView && this.popupView.empty(); |
|
}, |
|
|
|
destroyed: function () { |
|
BI.Maskers.remove(this.getName()); |
|
} |
|
}); |
|
BI.Searcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.Searcher.EVENT_START = "EVENT_START"; |
|
BI.Searcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.Searcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.Searcher.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.Searcher.EVENT_AFTER_INIT = "EVENT_AFTER_INIT"; |
|
|
|
BI.shortcut("bi.searcher", BI.Searcher);/** |
|
* |
|
* 切换显示或隐藏面板 |
|
* |
|
* Created by GUY on 2015/11/2. |
|
* @class BI.Switcher |
|
* @extends BI.Widget |
|
*/ |
|
BI.Switcher = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Switcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-switcher", |
|
direction: BI.Direction.Top, |
|
trigger: "click", |
|
toggle: true, |
|
el: {}, |
|
popup: {}, |
|
adapter: null, |
|
masker: {}, |
|
switcherClass: "bi-switcher-popup", |
|
hoverClass: "bi-switcher-hover" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Switcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this._initSwitcher(); |
|
this._initPullDownAction(); |
|
this.switcher.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (self.isEnabled() && self.isValid()) { |
|
if (type === BI.Events.EXPAND) { |
|
self._popupView(); |
|
} |
|
if (type === BI.Events.COLLAPSE) { |
|
self._hideView(); |
|
} |
|
if (type === BI.Events.EXPAND) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.fireEvent(BI.Switcher.EVENT_EXPAND); |
|
} |
|
if (type === BI.Events.COLLAPSE) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.isViewVisible() && self.fireEvent(BI.Switcher.EVENT_COLLAPSE); |
|
} |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.Switcher.EVENT_TRIGGER_CHANGE, value, obj); |
|
} |
|
} |
|
}); |
|
|
|
this.element.hover(function () { |
|
if (self.isEnabled() && self.switcher.isEnabled()) { |
|
self.element.addClass(o.hoverClass); |
|
} |
|
}, function () { |
|
if (self.isEnabled() && self.switcher.isEnabled()) { |
|
self.element.removeClass(o.hoverClass); |
|
} |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [ |
|
{el: this.switcher} |
|
] |
|
}); |
|
o.isDefaultInit && (this._assertPopupView()); |
|
}, |
|
|
|
_toggle: function () { |
|
this._assertPopupView(); |
|
if (this.isExpanded()) { |
|
this._hideView(); |
|
} else { |
|
if (this.isEnabled()) { |
|
this._popupView(); |
|
} |
|
} |
|
}, |
|
|
|
_initPullDownAction: function () { |
|
var self = this, o = this.options; |
|
var evs = this.options.trigger.split(","); |
|
BI.each(evs, function (i, e) { |
|
switch (e) { |
|
case "hover": |
|
self.element[e](function (e) { |
|
if (self.isEnabled() && self.switcher.isEnabled()) { |
|
self._popupView(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.switcher); |
|
self.fireEvent(BI.Switcher.EVENT_EXPAND); |
|
} |
|
}, function () { |
|
if (self.isEnabled() && self.switcher.isEnabled() && o.toggle) { |
|
self._hideView(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.switcher); |
|
self.fireEvent(BI.Switcher.EVENT_COLLAPSE); |
|
} |
|
}); |
|
break; |
|
default : |
|
if (e) { |
|
self.element.off(e + "." + self.getName()).on(e + "." + self.getName(), BI.debounce(function (e) { |
|
if (self.switcher.element.__isMouseInBounds__(e)) { |
|
if (self.isEnabled() && self.switcher.isEnabled()) { |
|
o.toggle ? self._toggle() : self._popupView(); |
|
if (self.isExpanded()) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.switcher); |
|
self.fireEvent(BI.Switcher.EVENT_EXPAND); |
|
} else { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.switcher); |
|
self.fireEvent(BI.Switcher.EVENT_COLLAPSE); |
|
} |
|
} |
|
} |
|
}, BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
})); |
|
} |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
_initSwitcher: function () { |
|
this.switcher = BI.createWidget(this.options.el, { |
|
value: this.options.value |
|
}); |
|
}, |
|
|
|
_assertPopupView: function () { |
|
var self = this, o = this.options; |
|
if (!this._created) { |
|
this.popupView = BI.createWidget(o.popup, { |
|
type: "bi.button_group", |
|
element: o.adapter && BI.Maskers.create(this.getName(), o.adapter, BI.extend({container: this}, o.masker)), |
|
cls: "switcher-popup", |
|
layouts: [{ |
|
type: "bi.vertical", |
|
hgap: 0, |
|
vgap: 0 |
|
}], |
|
value: o.value |
|
}, this); |
|
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.Switcher.EVENT_CHANGE, value, obj); |
|
} |
|
}); |
|
if (o.direction !== BI.Direction.Custom && !o.adapter) { |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [ |
|
{el: this.popupView} |
|
] |
|
}); |
|
} |
|
this._created = true; |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.Switcher.EVENT_AFTER_INIT); |
|
}); |
|
} |
|
}, |
|
|
|
_hideView: function () { |
|
this.fireEvent(BI.Switcher.EVENT_BEFORE_HIDEVIEW); |
|
var self = this, o = this.options; |
|
o.adapter ? BI.Maskers.hide(self.getName()) : (self.popupView && self.popupView.setVisible(false)); |
|
BI.nextTick(function () { |
|
o.adapter ? BI.Maskers.hide(self.getName()) : (self.popupView && self.popupView.setVisible(false)); |
|
self.element.removeClass(o.switcherClass); |
|
self.fireEvent(BI.Switcher.EVENT_AFTER_HIDEVIEW); |
|
}); |
|
}, |
|
|
|
_popupView: function () { |
|
var self = this, o = this.options; |
|
this._assertPopupView(); |
|
this.fireEvent(BI.Switcher.EVENT_BEFORE_POPUPVIEW); |
|
o.adapter ? BI.Maskers.show(this.getName()) : self.popupView.setVisible(true); |
|
BI.nextTick(function (name) { |
|
o.adapter ? BI.Maskers.show(name) : self.popupView.setVisible(true); |
|
self.element.addClass(o.switcherClass); |
|
self.fireEvent(BI.Switcher.EVENT_AFTER_POPUPVIEW); |
|
}, this.getName()); |
|
}, |
|
|
|
populate: function (items) { |
|
this._assertPopupView(); |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
this.switcher.populate.apply(this.switcher, arguments); |
|
}, |
|
|
|
_setEnable: function (arg) { |
|
BI.Switcher.superclass._setEnable.apply(this, arguments); |
|
!arg && this.isViewVisible() && this._hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.switcher.setValue(v); |
|
if (BI.isNull(this.popupView)) { |
|
this.options.popup.value = v; |
|
} else { |
|
this.popupView.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
if (BI.isNull(this.popupView)) { |
|
return this.options.popup.value; |
|
} else { |
|
return this.popupView.getValue(); |
|
} |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.options.adapter = adapter; |
|
BI.Maskers.remove(this.getName()); |
|
}, |
|
|
|
isViewVisible: function () { |
|
return this.isEnabled() && this.switcher.isEnabled() && |
|
(this.options.adapter ? BI.Maskers.isVisible(this.getName()) : (this.popupView && this.popupView.isVisible())); |
|
}, |
|
|
|
isExpanded: function () { |
|
return this.isViewVisible(); |
|
}, |
|
|
|
showView: function () { |
|
if (this.isEnabled() && this.switcher.isEnabled()) { |
|
this._popupView(); |
|
} |
|
}, |
|
|
|
hideView: function () { |
|
this._hideView(); |
|
}, |
|
|
|
getView: function () { |
|
return this.popupView; |
|
}, |
|
|
|
adjustView: function () { |
|
this.isViewVisible() && BI.Maskers.show(this.getName()); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.popupView && this.popupView.getAllLeaves(); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
if (this.switcher.attr("id") === id) { |
|
return this.switcher; |
|
} |
|
return this.popupView && this.popupView.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
if (this.switcher.getValue() === value) { |
|
return this.switcher; |
|
} |
|
return this.popupView && this.popupView.getNodeByValue(value); |
|
}, |
|
|
|
empty: function () { |
|
this.popupView && this.popupView.empty(); |
|
} |
|
}); |
|
BI.Switcher.EVENT_EXPAND = "EVENT_EXPAND"; |
|
BI.Switcher.EVENT_COLLAPSE = "EVENT_COLLAPSE"; |
|
BI.Switcher.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE"; |
|
BI.Switcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.Switcher.EVENT_AFTER_INIT = "EVENT_AFTER_INIT"; |
|
|
|
|
|
BI.Switcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.Switcher.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW"; |
|
BI.Switcher.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW"; |
|
BI.Switcher.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW"; |
|
|
|
BI.shortcut("bi.switcher", BI.Switcher);/** |
|
* Created by GUY on 2015/6/26. |
|
*/ |
|
|
|
BI.Tab = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Tab.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-tab", |
|
direction: "top", // top, bottom, left, right, custom |
|
single: false, // 是不是单页面 |
|
logic: { |
|
dynamic: false |
|
}, |
|
showIndex: false, |
|
tab: false, |
|
cardCreator: function (v) { |
|
return BI.createWidget(); |
|
} |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
if (BI.isObject(o.tab)) { |
|
this.tab = BI.createWidget(this.options.tab, {type: "bi.button_group"}); |
|
this.tab.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
} |
|
this.cardMap = {}; |
|
this.layout = BI.createWidget({ |
|
type: "bi.card" |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tab, this.layout) |
|
})))); |
|
|
|
var listener = new BI.ShowListener({ |
|
eventObj: this.tab, |
|
cardLayout: this.layout, |
|
cardCreator: function (v) { |
|
var card = o.cardCreator.apply(self, arguments); |
|
self.cardMap[v] = card; |
|
return card; |
|
}, |
|
afterCardShow: function (v) { |
|
self._deleteOtherCards(v); |
|
self.curr = v; |
|
} |
|
}); |
|
listener.on(BI.ShowListener.EVENT_CHANGE, function (value) { |
|
self.fireEvent(BI.Tab.EVENT_CHANGE, value, self); |
|
}); |
|
}, |
|
|
|
_deleteOtherCards: function (currCardName) { |
|
var self = this, o = this.options; |
|
if (o.single === true) { |
|
BI.each(this.cardMap, function (name, card) { |
|
if (name !== (currCardName + "")) { |
|
self.layout.deleteCardByName(name); |
|
delete self.cardMap[name]; |
|
} |
|
}); |
|
} |
|
}, |
|
|
|
_assertCard: function (v) { |
|
if (!this.layout.isCardExisted(v)) { |
|
var card = this.options.cardCreator(v); |
|
this.cardMap[v] = card; |
|
this.layout.addCardByName(v, card); |
|
} |
|
}, |
|
|
|
mounted: function () { |
|
var o = this.options; |
|
if (o.showIndex !== false) { |
|
this.setSelect(o.showIndex); |
|
} |
|
}, |
|
|
|
setSelect: function (v) { |
|
this.tab && this.tab.setValue(v); |
|
this._assertCard(v); |
|
this.layout.showCardByName(v); |
|
this._deleteOtherCards(v); |
|
if (this.curr !== v) { |
|
this.curr = v; |
|
} |
|
}, |
|
|
|
removeTab: function (cardname) { |
|
var self = this, o = this.options; |
|
BI.any(this.cardMap, function (name, card) { |
|
if (BI.isEqual(name, (cardname + ""))) { |
|
self.layout.deleteCardByName(name); |
|
delete self.cardMap[name]; |
|
return true; |
|
} |
|
}); |
|
}, |
|
|
|
getSelect: function () { |
|
return this.curr; |
|
}, |
|
|
|
getSelectedTab: function () { |
|
return this.layout.getShowingCard(); |
|
}, |
|
|
|
getTab: function (v) { |
|
this._assertCard(v); |
|
return this.layout.getCardByName(v); |
|
}, |
|
|
|
setValue: function (v) { |
|
var card = this.layout.getShowingCard(); |
|
if (card) { |
|
card.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
var card = this.layout.getShowingCard(); |
|
if (card) { |
|
return card.getValue(); |
|
} |
|
}, |
|
|
|
populate: function () { |
|
var card = this.layout.getShowingCard(); |
|
if (card) { |
|
return card.populate && card.populate.apply(card, arguments); |
|
} |
|
}, |
|
|
|
empty: function () { |
|
this.layout.deleteAllCard(); |
|
this.cardMap = {}; |
|
}, |
|
|
|
destroy: function () { |
|
this.cardMap = {}; |
|
BI.Tab.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.Tab.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.tab", BI.Tab);/** |
|
* 表示当前对象 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.EL |
|
* @extends BI.Widget |
|
*/ |
|
BI.EL = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.EL.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-el", |
|
el: {}, |
|
layout: {} |
|
}); |
|
}, |
|
_init: function () { |
|
BI.EL.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.ele = BI.createWidget(o.el); |
|
BI.createWidget(o.layout, { |
|
type: "bi.adaptive", |
|
element: this, |
|
items: [this.ele] |
|
}); |
|
this.ele.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.ele.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.ele.getValue(); |
|
}, |
|
|
|
populate: function () { |
|
this.ele.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.el", BI.EL);/** |
|
* z-index在1亿层级 |
|
* 弹出提示消息框,用于模拟阻塞操作(通过回调函数实现) |
|
* @class BI.Msg |
|
*/ |
|
BI.Msg = function () { |
|
|
|
var $mask, $pop; |
|
|
|
var messageShows = []; |
|
|
|
var toastStack = []; |
|
|
|
return { |
|
alert: function (title, message, callback) { |
|
this._show(false, title, message, callback); |
|
}, |
|
confirm: function (title, message, callback) { |
|
this._show(true, title, message, callback); |
|
}, |
|
prompt: function (title, message, value, callback, min_width) { |
|
// BI.Msg.prompt(title, message, value, callback, min_width); |
|
}, |
|
toast: function (message, options, context) { |
|
options = options || {}; |
|
context = context || BI.Widget._renderEngine.createElement("body"); |
|
var level = options.level || "normal"; |
|
var autoClose = BI.isNull(options.autoClose) ? true : options.autoClose; |
|
var callback = BI.isFunction(options.callback) ? options.callback : BI.emptyFn; |
|
var toast = BI.createWidget({ |
|
type: "bi.toast", |
|
cls: "bi-message-animate bi-message-leave", |
|
level: level, |
|
autoClose: autoClose, |
|
text: message, |
|
listeners: [{ |
|
eventName: BI.Toast.EVENT_DESTORY, |
|
action: function () { |
|
BI.remove(toastStack, toast.element); |
|
var _height = 10; |
|
BI.each(toastStack, function (i, element) { |
|
element.css({"top": _height}); |
|
_height += element.outerHeight() + 10; |
|
}); |
|
callback(); |
|
} |
|
}] |
|
}); |
|
var height = 10; |
|
BI.each(toastStack, function (i, element) { |
|
height += element.outerHeight() + 10; |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: context, |
|
items: [{ |
|
el: toast, |
|
left: "50%", |
|
top: height |
|
}] |
|
}); |
|
toastStack.push(toast.element); |
|
toast.element.css({"margin-left": -1 * toast.element.outerWidth() / 2}); |
|
toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); |
|
|
|
autoClose && BI.delay(function () { |
|
toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); |
|
toast.destroy(); |
|
}, 5000); |
|
}, |
|
_show: function (hasCancel, title, message, callback) { |
|
BI.isNull($mask) && ($mask = BI.Widget._renderEngine.createElement("<div class=\"bi-z-index-mask\">").css({ |
|
position: "absolute", |
|
zIndex: BI.zIndex_tip - 2, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0, |
|
opacity: 0.5 |
|
}).appendTo("body")); |
|
$pop = BI.Widget._renderEngine.createElement("<div class=\"bi-message-depend\">").css({ |
|
position: "absolute", |
|
zIndex: BI.zIndex_tip - 1, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}).appendTo("body"); |
|
var close = function () { |
|
messageShows[messageShows.length - 1].destroy(); |
|
messageShows.pop(); |
|
if (messageShows.length === 0) { |
|
$mask.remove(); |
|
$mask = null; |
|
} |
|
}; |
|
var controlItems = []; |
|
if (hasCancel === true) { |
|
controlItems.push({ |
|
el: { |
|
type: "bi.button", |
|
text: BI.i18nText("BI-Basic_Cancel"), |
|
level: "ignore", |
|
handler: function () { |
|
close(); |
|
if (BI.isFunction(callback)) { |
|
callback.apply(null, [false]); |
|
} |
|
} |
|
} |
|
}); |
|
} |
|
controlItems.push({ |
|
el: { |
|
type: "bi.button", |
|
text: BI.i18nText("BI-Basic_OK"), |
|
handler: function () { |
|
close(); |
|
if (BI.isFunction(callback)) { |
|
callback.apply(null, [true]); |
|
} |
|
} |
|
} |
|
}); |
|
var conf = { |
|
element: $pop, |
|
type: "bi.center_adapt", |
|
items: [ |
|
{ |
|
type: "bi.border", |
|
cls: "bi-card", |
|
items: { |
|
north: { |
|
el: { |
|
type: "bi.border", |
|
cls: "bi-message-title bi-background", |
|
items: { |
|
center: { |
|
el: { |
|
type: "bi.label", |
|
cls: "bi-font-bold", |
|
text: title || BI.i18nText("BI-Basic_Prompt"), |
|
textAlign: "left", |
|
hgap: 20, |
|
height: 40 |
|
} |
|
}, |
|
east: { |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-message-close close-font", |
|
// height: 50, |
|
handler: function () { |
|
close(); |
|
if (BI.isFunction(callback)) { |
|
callback.apply(null, [false]); |
|
} |
|
} |
|
}, |
|
width: 60 |
|
} |
|
} |
|
}, |
|
height: 40 |
|
}, |
|
center: { |
|
el: { |
|
type: "bi.label", |
|
vgap: 10, |
|
hgap: 20, |
|
whiteSpace: "normal", |
|
text: message |
|
} |
|
}, |
|
south: { |
|
el: { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.right_vertical_adapt", |
|
lgap: 10, |
|
items: controlItems |
|
}, |
|
top: 0, |
|
left: 20, |
|
right: 20, |
|
bottom: 0 |
|
}] |
|
|
|
}, |
|
height: 44 |
|
} |
|
}, |
|
width: 450, |
|
height: 200 |
|
} |
|
] |
|
}; |
|
|
|
messageShows[messageShows.length] = BI.createWidget(conf); |
|
} |
|
}; |
|
}();/** |
|
* GridView |
|
* |
|
* Created by GUY on 2016/1/11. |
|
* @class BI.GridView |
|
* @extends BI.Widget |
|
*/ |
|
BI.GridView = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.GridView.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-grid-view", |
|
// width: 400, //必设 |
|
// height: 300, //必设 |
|
overflowX: true, |
|
overflowY: true, |
|
overscanColumnCount: 0, |
|
overscanRowCount: 0, |
|
rowHeightGetter: BI.emptyFn, // number类型或function类型 |
|
columnWidthGetter: BI.emptyFn, // number类型或function类型 |
|
// estimatedColumnSize: 100, //columnWidthGetter为function时必设 |
|
// estimatedRowSize: 30, //rowHeightGetter为function时必设 |
|
scrollLeft: 0, |
|
scrollTop: 0, |
|
items: [] |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.GridView.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.renderedCells = []; |
|
this.renderedKeys = []; |
|
this.renderRange = {}; |
|
this._scrollLock = false; |
|
this._debounceRelease = BI.debounce(function () { |
|
self._scrollLock = false; |
|
}, 1000 / 60); |
|
this.container = BI.createWidget({ |
|
type: "bi.absolute" |
|
}); |
|
this.element.scroll(function () { |
|
if (self._scrollLock === true) { |
|
return; |
|
} |
|
o.scrollLeft = self.element.scrollLeft(); |
|
o.scrollTop = self.element.scrollTop(); |
|
self._calculateChildrenToRender(); |
|
self.fireEvent(BI.GridView.EVENT_SCROLL, { |
|
scrollLeft: o.scrollLeft, |
|
scrollTop: o.scrollTop |
|
}); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
scrollable: o.overflowX === true && o.overflowY === true, |
|
scrolly: o.overflowX === false && o.overflowY === true, |
|
scrollx: o.overflowX === true && o.overflowY === false, |
|
items: [this.container] |
|
}); |
|
if (o.items.length > 0) { |
|
this._populate(); |
|
} |
|
}, |
|
|
|
mounted: function () { |
|
var o = this.options; |
|
if (o.scrollLeft !== 0 || o.scrollTop !== 0) { |
|
this.element.scrollTop(o.scrollTop); |
|
this.element.scrollLeft(o.scrollLeft); |
|
} |
|
}, |
|
|
|
_getOverscanIndices: function (cellCount, overscanCellsCount, startIndex, stopIndex) { |
|
return { |
|
overscanStartIndex: Math.max(0, startIndex - overscanCellsCount), |
|
overscanStopIndex: Math.min(cellCount - 1, stopIndex + overscanCellsCount) |
|
}; |
|
}, |
|
|
|
_calculateChildrenToRender: function () { |
|
var self = this, o = this.options; |
|
|
|
var width = o.width, height = o.height, scrollLeft = BI.clamp(o.scrollLeft, 0, this._getMaxScrollLeft()), |
|
scrollTop = BI.clamp(o.scrollTop, 0, this._getMaxScrollTop()), |
|
overscanColumnCount = o.overscanColumnCount, overscanRowCount = o.overscanRowCount; |
|
|
|
if (height > 0 && width > 0) { |
|
var visibleColumnIndices = this._columnSizeAndPositionManager.getVisibleCellRange(width, scrollLeft); |
|
var visibleRowIndices = this._rowSizeAndPositionManager.getVisibleCellRange(height, scrollTop); |
|
|
|
if (BI.isEmpty(visibleColumnIndices) || BI.isEmpty(visibleRowIndices)) { |
|
return; |
|
} |
|
var horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment(width, scrollLeft); |
|
var verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment(height, scrollTop); |
|
|
|
this._renderedColumnStartIndex = visibleColumnIndices.start; |
|
this._renderedColumnStopIndex = visibleColumnIndices.stop; |
|
this._renderedRowStartIndex = visibleRowIndices.start; |
|
this._renderedRowStopIndex = visibleRowIndices.stop; |
|
|
|
var overscanColumnIndices = this._getOverscanIndices(this.columnCount, overscanColumnCount, this._renderedColumnStartIndex, this._renderedColumnStopIndex); |
|
|
|
var overscanRowIndices = this._getOverscanIndices(this.rowCount, overscanRowCount, this._renderedRowStartIndex, this._renderedRowStopIndex); |
|
|
|
var columnStartIndex = overscanColumnIndices.overscanStartIndex; |
|
var columnStopIndex = overscanColumnIndices.overscanStopIndex; |
|
var rowStartIndex = overscanRowIndices.overscanStartIndex; |
|
var rowStopIndex = overscanRowIndices.overscanStopIndex; |
|
|
|
// 算区间size |
|
var minRowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowStartIndex); |
|
var minColumnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnStartIndex); |
|
var maxRowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowStopIndex); |
|
var maxColumnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnStopIndex); |
|
var top = minRowDatum.offset + verticalOffsetAdjustment; |
|
var left = minColumnDatum.offset + horizontalOffsetAdjustment; |
|
var bottom = maxRowDatum.offset + verticalOffsetAdjustment + maxRowDatum.size; |
|
var right = maxColumnDatum.offset + horizontalOffsetAdjustment + maxColumnDatum.size; |
|
// 如果滚动的区间并没有超出渲染的范围 |
|
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) { |
|
return; |
|
} |
|
|
|
var renderedCells = [], renderedKeys = {}, renderedWidgets = {}; |
|
var minX = this._getMaxScrollLeft(), minY = this._getMaxScrollTop(), maxX = 0, maxY = 0; |
|
var count = 0; |
|
for (var rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) { |
|
var rowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex); |
|
|
|
for (var columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) { |
|
var key = rowIndex + "-" + columnIndex; |
|
var columnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex); |
|
|
|
var index = this.renderedKeys[key] && this.renderedKeys[key][2]; |
|
var child; |
|
if (index >= 0) { |
|
if (columnDatum.size !== this.renderedCells[index]._width) { |
|
this.renderedCells[index]._width = columnDatum.size; |
|
this.renderedCells[index].el.setWidth(columnDatum.size); |
|
} |
|
if (rowDatum.size !== this.renderedCells[index]._height) { |
|
this.renderedCells[index]._height = rowDatum.size; |
|
this.renderedCells[index].el.setHeight(rowDatum.size); |
|
} |
|
if (this.renderedCells[index]._left !== columnDatum.offset + horizontalOffsetAdjustment) { |
|
this.renderedCells[index].el.element.css("left", (columnDatum.offset + horizontalOffsetAdjustment) + "px"); |
|
} |
|
if (this.renderedCells[index]._top !== rowDatum.offset + verticalOffsetAdjustment) { |
|
this.renderedCells[index].el.element.css("top", (rowDatum.offset + verticalOffsetAdjustment) + "px"); |
|
} |
|
renderedCells.push(child = this.renderedCells[index]); |
|
} else { |
|
child = BI.createWidget(BI.extend({ |
|
type: "bi.label", |
|
width: columnDatum.size, |
|
height: rowDatum.size |
|
}, o.items[rowIndex][columnIndex], { |
|
cls: (o.items[rowIndex][columnIndex].cls || "") + " grid-cell" + (rowIndex === 0 ? " first-row" : "") + (columnIndex === 0 ? " first-col" : ""), |
|
_rowIndex: rowIndex, |
|
_columnIndex: columnIndex, |
|
_left: columnDatum.offset + horizontalOffsetAdjustment, |
|
_top: rowDatum.offset + verticalOffsetAdjustment |
|
}), this); |
|
renderedCells.push({ |
|
el: child, |
|
left: columnDatum.offset + horizontalOffsetAdjustment, |
|
top: rowDatum.offset + verticalOffsetAdjustment, |
|
_left: columnDatum.offset + horizontalOffsetAdjustment, |
|
_top: rowDatum.offset + verticalOffsetAdjustment, |
|
_width: columnDatum.size, |
|
_height: rowDatum.size |
|
}); |
|
} |
|
minX = Math.min(minX, columnDatum.offset + horizontalOffsetAdjustment); |
|
maxX = Math.max(maxX, columnDatum.offset + horizontalOffsetAdjustment + columnDatum.size); |
|
minY = Math.min(minY, rowDatum.offset + verticalOffsetAdjustment); |
|
maxY = Math.max(maxY, rowDatum.offset + verticalOffsetAdjustment + rowDatum.size); |
|
renderedKeys[key] = [rowIndex, columnIndex, count]; |
|
renderedWidgets[count] = child; |
|
count++; |
|
} |
|
} |
|
// 已存在的, 需要添加的和需要删除的 |
|
var existSet = {}, addSet = {}, deleteArray = []; |
|
BI.each(renderedKeys, function (i, key) { |
|
if (self.renderedKeys[i]) { |
|
existSet[i] = key; |
|
} else { |
|
addSet[i] = key; |
|
} |
|
}); |
|
BI.each(this.renderedKeys, function (i, key) { |
|
if (existSet[i]) { |
|
return; |
|
} |
|
if (addSet[i]) { |
|
return; |
|
} |
|
deleteArray.push(key[2]); |
|
}); |
|
BI.each(deleteArray, function (i, index) { |
|
// 性能优化,不调用destroy方法防止触发destroy事件 |
|
self.renderedCells[index].el._destroy(); |
|
}); |
|
var addedItems = []; |
|
BI.each(addSet, function (index, key) { |
|
addedItems.push(renderedCells[key[2]]); |
|
}); |
|
// 与listview一样, 给上下文 |
|
this.container.addItems(addedItems, this); |
|
// 拦截父子级关系 |
|
this.container._children = renderedWidgets; |
|
this.container.attr("items", renderedCells); |
|
this.renderedCells = renderedCells; |
|
this.renderedKeys = renderedKeys; |
|
this.renderRange = {minX: minX, minY: minY, maxX: maxX, maxY: maxY}; |
|
} |
|
}, |
|
|
|
/** |
|
* 获取真实的可滚动的最大宽度 |
|
* 对于grid_view如果没有全部渲染过,this._columnSizeAndPositionManager.getTotalSize获取的宽度是不准确的 |
|
* 因此在调用setScrollLeft等函数时会造成没法移动到最右端(预估可移动具体太短) |
|
*/ |
|
_getRealMaxScrollLeft: function () { |
|
var o = this.options; |
|
var totalWidth = 0; |
|
BI.count(0, this.columnCount, function (index) { |
|
totalWidth += o.columnWidthGetter(index); |
|
}); |
|
return Math.max(0, totalWidth - this.options.width + (this.options.overflowX ? BI.DOM.getScrollWidth() : 0)); |
|
}, |
|
|
|
_getMaxScrollLeft: function () { |
|
return Math.max(0, this._columnSizeAndPositionManager.getTotalSize() - this.options.width + (this.options.overflowX ? BI.DOM.getScrollWidth() : 0)); |
|
}, |
|
|
|
_getMaxScrollTop: function () { |
|
return Math.max(0, this._rowSizeAndPositionManager.getTotalSize() - this.options.height + (this.options.overflowY ? BI.DOM.getScrollWidth() : 0)); |
|
}, |
|
|
|
_populate: function (items) { |
|
var self = this, o = this.options; |
|
this._reRange(); |
|
this.columnCount = 0; |
|
this.rowCount = 0; |
|
if (items && items !== this.options.items) { |
|
this.options.items = items; |
|
} |
|
if (BI.isNumber(o.columnCount)) { |
|
this.columnCount = o.columnCount; |
|
} else if (o.items.length > 0) { |
|
this.columnCount = o.items[0].length; |
|
} |
|
if (BI.isNumber(o.rowCount)) { |
|
this.rowCount = o.rowCount; |
|
} else { |
|
this.rowCount = o.items.length; |
|
} |
|
this.container.setWidth(this.columnCount * o.estimatedColumnSize); |
|
this.container.setHeight(this.rowCount * o.estimatedRowSize); |
|
|
|
this._columnSizeAndPositionManager = new BI.ScalingCellSizeAndPositionManager(this.columnCount, o.columnWidthGetter, o.estimatedColumnSize); |
|
this._rowSizeAndPositionManager = new BI.ScalingCellSizeAndPositionManager(this.rowCount, o.rowHeightGetter, o.estimatedRowSize); |
|
|
|
this._calculateChildrenToRender(); |
|
// 元素未挂载时不能设置scrollTop |
|
try { |
|
this.element.scrollTop(o.scrollTop); |
|
this.element.scrollLeft(o.scrollLeft); |
|
} catch (e) { |
|
} |
|
}, |
|
|
|
setScrollLeft: function (scrollLeft) { |
|
if (this.options.scrollLeft === scrollLeft) { |
|
return; |
|
} |
|
this._scrollLock = true; |
|
this.options.scrollLeft = BI.clamp(scrollLeft || 0, 0, this._getRealMaxScrollLeft()); |
|
this._debounceRelease(); |
|
this._calculateChildrenToRender(); |
|
this.element.scrollLeft(this.options.scrollLeft); |
|
}, |
|
|
|
setScrollTop: function (scrollTop) { |
|
if (this.options.scrollTop === scrollTop) { |
|
return; |
|
} |
|
this._scrollLock = true; |
|
this.options.scrollTop = BI.clamp(scrollTop || 0, 0, this._getMaxScrollTop()); |
|
this._debounceRelease(); |
|
this._calculateChildrenToRender(); |
|
this.element.scrollTop(this.options.scrollTop); |
|
}, |
|
|
|
setColumnCount: function (columnCount) { |
|
this.options.columnCount = columnCount; |
|
}, |
|
|
|
setRowCount: function (rowCount) { |
|
this.options.rowCount = rowCount; |
|
}, |
|
|
|
setOverflowX: function (b) { |
|
var self = this; |
|
if (this.options.overflowX !== !!b) { |
|
this.options.overflowX = !!b; |
|
BI.nextTick(function () { |
|
self.element.css({overflowX: b ? "auto" : "hidden"}); |
|
}); |
|
} |
|
}, |
|
|
|
setOverflowY: function (b) { |
|
var self = this; |
|
if (this.options.overflowY !== !!b) { |
|
this.options.overflowY = !!b; |
|
BI.nextTick(function () { |
|
self.element.css({overflowY: b ? "auto" : "hidden"}); |
|
}); |
|
} |
|
}, |
|
|
|
getScrollLeft: function () { |
|
return this.options.scrollLeft; |
|
}, |
|
|
|
getScrollTop: function () { |
|
return this.options.scrollTop; |
|
}, |
|
|
|
getMaxScrollLeft: function () { |
|
return this._getMaxScrollLeft(); |
|
}, |
|
|
|
getMaxScrollTop: function () { |
|
return this._getMaxScrollTop(); |
|
}, |
|
|
|
setEstimatedColumnSize: function (width) { |
|
this.options.estimatedColumnSize = width; |
|
}, |
|
|
|
setEstimatedRowSize: function (height) { |
|
this.options.estimatedRowSize = height; |
|
}, |
|
|
|
// 重新计算children |
|
_reRange: function () { |
|
this.renderRange = {}; |
|
}, |
|
|
|
_clearChildren: function () { |
|
this.container._children = {}; |
|
this.container.attr("items", []); |
|
}, |
|
|
|
restore: function () { |
|
BI.each(this.renderedCells, function (i, cell) { |
|
cell.el._destroy(); |
|
}); |
|
this._clearChildren(); |
|
this.renderedCells = []; |
|
this.renderedKeys = []; |
|
this.renderRange = {}; |
|
this._scrollLock = false; |
|
}, |
|
|
|
populate: function (items) { |
|
if (items && items !== this.options.items) { |
|
this.restore(); |
|
} |
|
this._populate(items); |
|
} |
|
}); |
|
BI.GridView.EVENT_SCROLL = "EVENT_SCROLL"; |
|
BI.shortcut("bi.grid_view", BI.GridView); |
|
/** |
|
* Popover弹出层, |
|
* @class BI.Popover |
|
* @extends BI.Widget |
|
*/ |
|
BI.Popover = BI.inherit(BI.Widget, { |
|
_constant: { |
|
SIZE: { |
|
SMALL: "small", |
|
NORMAL: "normal", |
|
BIG: "big" |
|
}, |
|
HEADER_HEIGHT: 40 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.Popover.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-popover bi-card bi-border-radius", |
|
// width: 600, |
|
// height: 500, |
|
size: "normal", // small, normal, big |
|
logic: { |
|
dynamic: false |
|
}, |
|
header: null, |
|
body: null, |
|
footer: null, |
|
closable: true // BI-40839 是否显示右上角的关闭按钮 |
|
}); |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
this.startX = 0; |
|
this.startY = 0; |
|
this.tracker = new BI.MouseMoveTracker(function (deltaX, deltaY) { |
|
var size = self._calculateSize(); |
|
var W = BI.Widget._renderEngine.createElement("body").width(), H = BI.Widget._renderEngine.createElement("body").height(); |
|
self.startX += deltaX; |
|
self.startY += deltaY; |
|
self.element.css({ |
|
left: BI.clamp(self.startX, 0, W - self.element.width()) + "px", |
|
top: BI.clamp(self.startY, 0, H - self.element.height()) + "px" |
|
}); |
|
// BI-12134 没有什么特别好的方法 |
|
BI.Resizers._resize(); |
|
}, function () { |
|
self.tracker.releaseMouseMoves(); |
|
}, _global); |
|
var items = [{ |
|
el: { |
|
type: "bi.htape", |
|
cls: "bi-message-title bi-header-background", |
|
ref: function (_ref) { |
|
self.dragger = _ref; |
|
}, |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: BI.isPlainObject(o.header) ? BI.createWidget(o.header, { |
|
extraCls: "bi-font-bold" |
|
}) : { |
|
type: "bi.label", |
|
cls: "bi-font-bold", |
|
height: this._constant.HEADER_HEIGHT, |
|
text: o.header, |
|
title: o.header, |
|
textAlign: "left" |
|
}, |
|
left: 20, |
|
top: 0, |
|
right: 0, |
|
bottom: 0 |
|
}] |
|
}, { |
|
el: o.closable ? { |
|
type: "bi.icon_button", |
|
cls: "bi-message-close close-font", |
|
height: this._constant.HEADER_HEIGHT, |
|
handler: function () { |
|
self.close(); |
|
} |
|
} : { |
|
type: "bi.layout" |
|
}, |
|
width: 56 |
|
}], |
|
height: this._constant.HEADER_HEIGHT |
|
}, |
|
height: this._constant.HEADER_HEIGHT |
|
}, { |
|
el: o.logic.dynamic ? { |
|
type: "bi.vertical", |
|
scrolly: false, |
|
cls: "popover-body", |
|
ref: function () { |
|
self.body = this; |
|
}, |
|
hgap: 20, |
|
tgap: 10, |
|
items: [{ |
|
el: BI.createWidget(o.body) |
|
}] |
|
} : { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: BI.createWidget(o.body), |
|
left: 20, |
|
top: 10, |
|
right: 20, |
|
bottom: 0 |
|
}] |
|
} |
|
}]; |
|
if (o.footer) { |
|
items.push({ |
|
el: { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: BI.createWidget(o.footer), |
|
left: 20, |
|
top: 0, |
|
right: 20, |
|
bottom: 0 |
|
}], |
|
height: 44 |
|
}, |
|
height: 44 |
|
}); |
|
} |
|
|
|
var size = this._calculateSize(); |
|
|
|
return BI.extend({ |
|
type: o.logic.dynamic ? "bi.vertical" : "bi.vtape", |
|
items: items, |
|
width: size.width |
|
}, o.logic.dynamic ? { |
|
type: "bi.vertical", |
|
scrolly: false |
|
} : { |
|
type: "bi.vtape", |
|
height: size.height |
|
}); |
|
}, |
|
|
|
mounted: function () { |
|
var self = this, o = this.options; |
|
this.dragger.element.mousedown(function (e) { |
|
var pos = self.element.offset(); |
|
self.startX = pos.left; |
|
self.startY = pos.top; |
|
self.tracker.captureMouseMoves(e); |
|
}); |
|
if (o.logic.dynamic) { |
|
var size = this._calculateSize(); |
|
var height = this.element.height(); |
|
var compareHeight = BI.clamp(height, size.height, 600) - (o.footer ? 84 : 44); |
|
this.body.element.height(compareHeight); |
|
} |
|
}, |
|
|
|
_calculateSize: function () { |
|
var o = this.options; |
|
var size = {}; |
|
if (BI.isNotNull(o.size)) { |
|
switch (o.size) { |
|
case this._constant.SIZE.SMALL: |
|
size.width = 450; |
|
size.height = 200; |
|
break; |
|
case this._constant.SIZE.BIG: |
|
size.width = 900; |
|
size.height = 500; |
|
break; |
|
default: |
|
size.width = 550; |
|
size.height = 500; |
|
} |
|
} |
|
return { |
|
width: o.width || size.width, |
|
height: o.height || size.height |
|
}; |
|
}, |
|
|
|
hide: function () { |
|
|
|
}, |
|
|
|
open: function () { |
|
this.show(); |
|
this.fireEvent(BI.Popover.EVENT_OPEN, arguments); |
|
}, |
|
|
|
close: function () { |
|
this.hide(); |
|
this.fireEvent(BI.Popover.EVENT_CLOSE, arguments); |
|
}, |
|
|
|
setZindex: function (zindex) { |
|
this.element.css({"z-index": zindex}); |
|
}, |
|
|
|
destroyed: function () { |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.popover", BI.Popover); |
|
|
|
BI.BarPopover = BI.inherit(BI.Popover, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.BarPopover.superclass._defaultConfig.apply(this, arguments), { |
|
btns: [BI.i18nText("BI-Basic_Sure"), BI.i18nText("BI-Basic_Cancel")] |
|
}); |
|
}, |
|
|
|
beforeCreate: function () { |
|
var self = this, o = this.options; |
|
o.footer || (o.footer = { |
|
type: "bi.right_vertical_adapt", |
|
lgap: 10, |
|
items: [{ |
|
type: "bi.button", |
|
text: this.options.btns[1], |
|
value: 1, |
|
level: "ignore", |
|
handler: function (v) { |
|
self.fireEvent(BI.Popover.EVENT_CANCEL, v); |
|
self.close(v); |
|
} |
|
}, { |
|
type: "bi.button", |
|
text: this.options.btns[0], |
|
warningTitle: o.warningTitle, |
|
value: 0, |
|
handler: function (v) { |
|
self.fireEvent(BI.Popover.EVENT_CONFIRM, v); |
|
self.close(v); |
|
} |
|
}] |
|
}); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.bar_popover", BI.BarPopover); |
|
|
|
BI.Popover.EVENT_CLOSE = "EVENT_CLOSE"; |
|
BI.Popover.EVENT_OPEN = "EVENT_OPEN"; |
|
BI.Popover.EVENT_CANCEL = "EVENT_CANCEL"; |
|
BI.Popover.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
/** |
|
* 下拉框弹出层, zIndex在1000w |
|
* @class BI.PopupView |
|
* @extends BI.Widget |
|
*/ |
|
BI.PopupView = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.PopupView.superclass._defaultConfig.apply(this, arguments), { |
|
_baseCls: "bi-popup-view", |
|
maxWidth: "auto", |
|
minWidth: 100, |
|
// maxHeight: 200, |
|
minHeight: 24, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
vgap: 0, |
|
hgap: 0, |
|
innerVGap: 0, |
|
direction: BI.Direction.Top, // 工具栏的方向 |
|
stopEvent: false, // 是否停止mousedown、mouseup事件 |
|
stopPropagation: false, // 是否停止mousedown、mouseup向上冒泡 |
|
logic: { |
|
dynamic: true |
|
}, |
|
|
|
tool: false, // 自定义工具栏 |
|
tabs: [], // 导航栏 |
|
buttons: [], // toolbar栏 |
|
|
|
el: { |
|
type: "bi.button_group", |
|
items: [], |
|
chooseType: 0, |
|
behaviors: {}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.PopupView.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var fn = function (e) { |
|
e.stopPropagation(); |
|
}, stop = function (e) { |
|
e.stopEvent(); |
|
return false; |
|
}; |
|
this.element.css({ |
|
"z-index": BI.zIndex_popup, |
|
"min-width": o.minWidth + "px", |
|
"max-width": o.maxWidth + "px" |
|
}).bind({click: fn}); |
|
|
|
this.element.bind("mousewheel", fn); |
|
|
|
o.stopPropagation && this.element.bind({mousedown: fn, mouseup: fn, mouseover: fn}); |
|
o.stopEvent && this.element.bind({mousedown: stop, mouseup: stop, mouseover: stop}); |
|
this.tool = this._createTool(); |
|
this.tab = this._createTab(); |
|
this.view = this._createView(); |
|
this.toolbar = this._createToolBar(); |
|
|
|
this.view.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.PopupView.EVENT_CHANGE); |
|
} |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, { |
|
scrolly: false, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
vgap: o.vgap, |
|
hgap: o.hgap, |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, |
|
BI.extend({ |
|
cls: "list-view-outer bi-card list-view-shadow" |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tool, this.tab, this.view, this.toolbar) |
|
}))) |
|
) |
|
})))); |
|
}, |
|
|
|
_createView: function () { |
|
var o = this.options; |
|
this.button_group = BI.createWidget(o.el, {type: "bi.button_group", value: o.value}); |
|
this.button_group.element.css({"min-height": o.minHeight + "px", "padding-top": o.innerVGap + "px", "padding-bottom": o.innerVGap + "px"}); |
|
return this.button_group; |
|
}, |
|
|
|
_createTool: function () { |
|
var o = this.options; |
|
if (false === o.tool) { |
|
return; |
|
} |
|
return BI.createWidget(o.tool); |
|
}, |
|
|
|
_createTab: function () { |
|
var o = this.options; |
|
if (o.tabs.length === 0) { |
|
return; |
|
} |
|
return BI.createWidget({ |
|
type: "bi.center", |
|
cls: "list-view-tab", |
|
height: 25, |
|
items: o.tabs, |
|
value: o.value |
|
}); |
|
}, |
|
|
|
_createToolBar: function () { |
|
var o = this.options; |
|
if (o.buttons.length === 0) { |
|
return; |
|
} |
|
|
|
return BI.createWidget({ |
|
type: "bi.center", |
|
cls: "list-view-toolbar bi-high-light bi-split-top", |
|
height: 24, |
|
items: BI.createItems(o.buttons, { |
|
once: false, |
|
shadow: true, |
|
isShadowShowingOnSelected: true |
|
}) |
|
}); |
|
}, |
|
|
|
getView: function () { |
|
return this.view; |
|
}, |
|
|
|
populate: function (items) { |
|
this.view.populate.apply(this.view, arguments); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.options.width = w; |
|
this.element.width(w); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
var tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, |
|
tabHeight = this.tab ? (this.tab.attr("height") || 24) : 0, |
|
toolHeight = ((this.tool && this.tool.attr("height")) || 24) * ((this.tool && this.tool.isVisible()) ? 1 : 0); |
|
var resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVGap; |
|
this.view.resetHeight ? this.view.resetHeight(resetHeight) : |
|
this.view.element.css({"max-height": resetHeight + "px"}); |
|
}, |
|
|
|
setValue: function (selectedValues) { |
|
this.tab && this.tab.setValue(selectedValues); |
|
this.view.setValue(selectedValues); |
|
}, |
|
|
|
getValue: function () { |
|
return this.view.getValue(); |
|
} |
|
}); |
|
BI.PopupView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.popup_view", BI.PopupView);/** |
|
* 搜索面板 |
|
* |
|
* Created by GUY on 2015/9/28. |
|
* @class BI.SearcherView |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.SearcherView = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
var conf = BI.SearcherView.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-searcher-view bi-card", |
|
tipText: BI.i18nText("BI-No_Select"), |
|
chooseType: BI.Selection.Single, |
|
|
|
matcher: {// 完全匹配的构造器 |
|
type: "bi.button_group", |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
items: [], |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
}, |
|
searcher: { |
|
type: "bi.button_group", |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
items: [], |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SearcherView.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.matcher = BI.createWidget(o.matcher, { |
|
type: "bi.button_group", |
|
chooseType: o.chooseType, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
value: o.value |
|
}); |
|
this.matcher.on(BI.Controller.EVENT_CHANGE, function (type, val, ob) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob); |
|
} |
|
}); |
|
this.spliter = BI.createWidget({ |
|
type: "bi.vertical", |
|
height: 1, |
|
hgap: 10, |
|
items: [{ |
|
type: "bi.layout", |
|
height: 1, |
|
cls: "searcher-view-spliter bi-background" |
|
}] |
|
}); |
|
this.searcher = BI.createWidget(o.searcher, { |
|
type: "bi.button_group", |
|
chooseType: o.chooseType, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
value: o.value |
|
}); |
|
this.searcher.on(BI.Controller.EVENT_CHANGE, function (type, val, ob) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
items: [this.matcher, this.spliter, this.searcher] |
|
}); |
|
}, |
|
|
|
startSearch: function () { |
|
|
|
}, |
|
|
|
stopSearch: function () { |
|
|
|
}, |
|
|
|
setValue: function (v) { |
|
this.matcher.setValue(v); |
|
this.searcher.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.matcher.getValue().concat(this.searcher.getValue()); |
|
}, |
|
|
|
populate: function (searchResult, matchResult, keyword) { |
|
searchResult || (searchResult = []); |
|
matchResult || (matchResult = []); |
|
this.setTipVisible(searchResult.length + matchResult.length === 0); |
|
this.spliter.setVisible(BI.isNotEmptyArray(matchResult) && BI.isNotEmptyArray(searchResult)); |
|
this.matcher.populate(matchResult, keyword); |
|
this.searcher.populate(searchResult, keyword); |
|
}, |
|
|
|
empty: function () { |
|
this.searcher.empty(); |
|
this.matcher.empty(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.matcher.getAllButtons().length > 0; |
|
} |
|
}); |
|
BI.SearcherView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.searcher_view", BI.SearcherView);/** |
|
* 表示当前对象 |
|
* |
|
* Created by GUY on 2017/5/23. |
|
* @class BI.ListView |
|
* @extends BI.Widget |
|
*/ |
|
BI.ListView = BI.inherit(BI.Widget, { |
|
props: function () { |
|
return { |
|
baseCls: "bi-list-view", |
|
overscanHeight: 100, |
|
blockSize: 10, |
|
scrollTop: 0, |
|
el: {}, |
|
items: [] |
|
}; |
|
}, |
|
|
|
init: function () { |
|
var self = this; |
|
this.renderedIndex = -1; |
|
this.cache = {}; |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.vertical", |
|
items: [BI.extend({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
ref: function () { |
|
self.container = this; |
|
} |
|
}, o.el)], |
|
element: this |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
var self = this, o = this.options; |
|
this._populate(); |
|
this.element.scroll(function (e) { |
|
o.scrollTop = self.element.scrollTop(); |
|
self._calculateBlocksToRender(); |
|
}); |
|
var lastWidth = this.element.width(), |
|
lastHeight = this.element.height(); |
|
BI.ResizeDetector.addResizeListener(this, function () { |
|
var width = self.element.width(), |
|
height = self.element.height(); |
|
if (width !== lastWidth || height !== lastHeight) { |
|
lastWidth = width; |
|
lastHeight = height; |
|
self._calculateBlocksToRender(); |
|
} |
|
}); |
|
}, |
|
|
|
_renderMoreIf: function () { |
|
var self = this, o = this.options; |
|
var height = this.element.height(); |
|
var minContentHeight = o.scrollTop + height + o.overscanHeight; |
|
var index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + o.blockSize)) || 0, |
|
cnt = this.renderedIndex + 1; |
|
var lastHeight; |
|
var getElementHeight = function () { |
|
return self.container.element.height(); |
|
}; |
|
while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) { |
|
var items = o.items.slice(index, index + o.blockSize); |
|
this.container.addItems(items, this); |
|
var addedHeight = getElementHeight() - lastHeight; |
|
this.cache[cnt] = { |
|
index: index, |
|
scrollTop: lastHeight, |
|
height: addedHeight |
|
}; |
|
this.renderedIndex = cnt; |
|
cnt++; |
|
index += o.blockSize; |
|
} |
|
}, |
|
|
|
_calculateBlocksToRender: function () { |
|
var o = this.options; |
|
this._renderMoreIf(); |
|
}, |
|
|
|
_populate: function (items) { |
|
var o = this.options; |
|
if (items && this.options.items !== items) { |
|
this.options.items = items; |
|
} |
|
this._calculateBlocksToRender(); |
|
this.element.scrollTop(o.scrollTop); |
|
}, |
|
|
|
restore: function () { |
|
this.renderedIndex = -1; |
|
this.container.empty(); |
|
this.cache = {}; |
|
}, |
|
|
|
populate: function (items) { |
|
if (items && this.options.items !== items) { |
|
this.restore(); |
|
} |
|
this._populate(items); |
|
}, |
|
|
|
destroyed: function () { |
|
this.restore(); |
|
} |
|
}); |
|
BI.shortcut("bi.list_view", BI.ListView); |
|
|
|
/** |
|
* 表示当前对象 |
|
* |
|
* Created by GUY on 2017/5/22. |
|
* @class BI.VirtualList |
|
* @extends BI.Widget |
|
*/ |
|
BI.VirtualList = BI.inherit(BI.Widget, { |
|
props: function () { |
|
return { |
|
baseCls: "bi-virtual-list", |
|
overscanHeight: 100, |
|
blockSize: 10, |
|
scrollTop: 0, |
|
items: [] |
|
}; |
|
}, |
|
|
|
init: function () { |
|
var self = this; |
|
this.renderedIndex = -1; |
|
this.cache = {}; |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.layout", |
|
ref: function () { |
|
self.topBlank = this; |
|
} |
|
}, { |
|
type: "bi.vertical", |
|
scrolly: false, |
|
ref: function () { |
|
self.container = this; |
|
} |
|
}, { |
|
type: "bi.layout", |
|
ref: function () { |
|
self.bottomBlank = this; |
|
} |
|
}], |
|
element: this |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
var self = this, o = this.options; |
|
this._populate(); |
|
this.element.scroll(function (e) { |
|
o.scrollTop = self.element.scrollTop(); |
|
self._calculateBlocksToRender(); |
|
}); |
|
BI.ResizeDetector.addResizeListener(this, function () { |
|
self._calculateBlocksToRender(); |
|
}); |
|
}, |
|
|
|
_renderMoreIf: function () { |
|
var self = this, o = this.options; |
|
var height = this.element.height(); |
|
var minContentHeight = o.scrollTop + height + o.overscanHeight; |
|
var index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + o.blockSize)) || 0, |
|
cnt = this.renderedIndex + 1; |
|
var lastHeight; |
|
var getElementHeight = function () { |
|
return self.container.element.height() + self.topBlank.element.height() + self.bottomBlank.element.height(); |
|
}; |
|
while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) { |
|
var items = o.items.slice(index, index + o.blockSize); |
|
this.container.addItems(items, this); |
|
var addedHeight = getElementHeight() - lastHeight; |
|
this.cache[cnt] = { |
|
index: index, |
|
scrollTop: lastHeight, |
|
height: addedHeight |
|
}; |
|
this.tree.set(cnt, addedHeight); |
|
this.renderedIndex = cnt; |
|
cnt++; |
|
index += o.blockSize; |
|
} |
|
}, |
|
|
|
_calculateBlocksToRender: function () { |
|
var o = this.options; |
|
this._renderMoreIf(); |
|
var height = this.element.height(); |
|
var minContentHeightFrom = o.scrollTop - o.overscanHeight; |
|
var minContentHeightTo = o.scrollTop + height + o.overscanHeight; |
|
var start = this.tree.greatestLowerBound(minContentHeightFrom); |
|
var end = this.tree.leastUpperBound(minContentHeightTo); |
|
var needDestroyed = []; |
|
for (var i = 0; i < start; i++) { |
|
var index = this.cache[i].index; |
|
if (!this.cache[i].destroyed) { |
|
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) { |
|
needDestroyed.push(this.container._children[j]); |
|
this.container._children[j] = null; |
|
} |
|
this.cache[i].destroyed = true; |
|
} |
|
} |
|
for (var i = end + 1; i <= this.renderedIndex; i++) { |
|
var index = this.cache[i].index; |
|
if (!this.cache[i].destroyed) { |
|
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) { |
|
needDestroyed.push(this.container._children[j]); |
|
this.container._children[j] = null; |
|
} |
|
this.cache[i].destroyed = true; |
|
} |
|
} |
|
var firstFragment = BI.Widget._renderEngine.createFragment(), lastFragment = BI.Widget._renderEngine.createFragment(); |
|
var currentFragment = firstFragment; |
|
for (var i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) { |
|
var index = this.cache[i].index; |
|
if (!this.cache[i].destroyed) { |
|
currentFragment = lastFragment; |
|
} |
|
if (this.cache[i].destroyed === true) { |
|
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) { |
|
var w = this.container._addElement(j, BI.extend({root: true}, BI.stripEL(o.items[j])), this); |
|
currentFragment.appendChild(w.element[0]); |
|
} |
|
this.cache[i].destroyed = false; |
|
} |
|
} |
|
this.container.element.prepend(firstFragment); |
|
this.container.element.append(lastFragment); |
|
this.topBlank.setHeight(this.cache[start < 0 ? 0 : start].scrollTop); |
|
var lastCache = this.cache[Math.min(end, this.renderedIndex)]; |
|
this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - lastCache.scrollTop - lastCache.height); |
|
BI.each(needDestroyed, function (i, child) { |
|
child && child._destroy(); |
|
}); |
|
}, |
|
|
|
_populate: function (items) { |
|
var o = this.options; |
|
if (items && this.options.items !== items) { |
|
this.options.items = items; |
|
} |
|
this.tree = BI.PrefixIntervalTree.empty(Math.ceil(o.items.length / o.blockSize)); |
|
this._calculateBlocksToRender(); |
|
this.element.scrollTop(o.scrollTop); |
|
}, |
|
|
|
_clearChildren: function () { |
|
BI.each(this.container._children, function (i, cell) { |
|
cell && cell._destroy(); |
|
}); |
|
this.container._children = {}; |
|
this.container.attr("items", []); |
|
}, |
|
|
|
restore: function () { |
|
this.renderedIndex = -1; |
|
this._clearChildren(); |
|
this.cache = {}; |
|
this.options.scrollTop = 0; |
|
// 依赖于cache的占位元素也要初始化 |
|
this.topBlank.setHeight(0); |
|
this.bottomBlank.setHeight(0); |
|
}, |
|
|
|
populate: function (items) { |
|
if (items && this.options.items !== items) { |
|
this.restore(); |
|
} |
|
this._populate(); |
|
}, |
|
|
|
destroyed: function () { |
|
this.restore(); |
|
} |
|
}); |
|
BI.shortcut("bi.virtual_list", BI.VirtualList); |
|
|
|
/** |
|
* 分页控件 |
|
* |
|
* Created by GUY on 2015/8/31. |
|
* @class BI.Pager |
|
* @extends BI.Widget |
|
*/ |
|
BI.Pager = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Pager.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-pager", |
|
behaviors: {}, |
|
layouts: [{ |
|
type: "bi.horizontal", |
|
hgap: 10, |
|
vgap: 0 |
|
}], |
|
|
|
dynamicShow: true, // 是否动态显示上一页、下一页、首页、尾页, 若为false,则指对其设置使能状态 |
|
// dynamicShow为false时以下两个有用 |
|
dynamicShowFirstLast: false, // 是否动态显示首页、尾页 |
|
dynamicShowPrevNext: false, // 是否动态显示上一页、下一页 |
|
pages: false, // 总页数 |
|
curr: function () { |
|
return 1; |
|
}, // 初始化当前页 |
|
groups: 0, // 连续显示分页数 |
|
jump: BI.emptyFn, // 分页的回调函数 |
|
|
|
first: false, // 是否显示首页 |
|
last: false, // 是否显示尾页 |
|
prev: "上一页", |
|
next: "下一页", |
|
|
|
firstPage: 1, |
|
lastPage: function () { // 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法 |
|
return 1; |
|
}, |
|
hasPrev: BI.emptyFn, // pages不可用时有效 |
|
hasNext: BI.emptyFn // pages不可用时有效 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.Pager.superclass._init.apply(this, arguments); |
|
var self = this; |
|
this.currPage = BI.result(this.options, "curr"); |
|
// 翻页太灵敏 |
|
// this._lock = false; |
|
// this._debouce = BI.debounce(function () { |
|
// self._lock = false; |
|
// }, 300); |
|
this._populate(); |
|
}, |
|
|
|
_populate: function () { |
|
var self = this, o = this.options, view = [], dict = {}; |
|
this.empty(); |
|
var pages = BI.result(o, "pages"); |
|
var curr = BI.result(this, "currPage"); |
|
var groups = BI.result(o, "groups"); |
|
var first = BI.result(o, "first"); |
|
var last = BI.result(o, "last"); |
|
var prev = BI.result(o, "prev"); |
|
var next = BI.result(o, "next"); |
|
|
|
if (pages === false) { |
|
groups = 0; |
|
first = false; |
|
last = false; |
|
} else { |
|
groups > pages && (groups = pages); |
|
} |
|
|
|
// 计算当前组 |
|
dict.index = Math.ceil((curr + ((groups > 1 && groups !== pages) ? 1 : 0)) / (groups === 0 ? 1 : groups)); |
|
|
|
// 当前页非首页,则输出上一页 |
|
if (((!o.dynamicShow && !o.dynamicShowPrevNext) || curr > 1) && prev !== false) { |
|
if (BI.isKey(prev)) { |
|
view.push({ |
|
text: prev, |
|
value: "prev", |
|
disabled: pages === false ? o.hasPrev(curr) === false : !(curr > 1 && prev !== false) |
|
}); |
|
} else { |
|
view.push(BI.extend({ |
|
disabled: pages === false ? o.hasPrev(curr) === false : !(curr > 1 && prev !== false) |
|
}, prev)); |
|
} |
|
} |
|
|
|
// 当前组非首组,则输出首页 |
|
if (((!o.dynamicShow && !o.dynamicShowFirstLast) || (dict.index > 1 && groups !== 0)) && first) { |
|
view.push({ |
|
text: first, |
|
value: "first", |
|
disabled: !(dict.index > 1 && groups !== 0) |
|
}); |
|
if (dict.index > 1 && groups !== 0) { |
|
view.push({ |
|
type: "bi.label", |
|
cls: "page-ellipsis", |
|
text: "\u2026" |
|
}); |
|
} |
|
} |
|
|
|
// 输出当前页组 |
|
dict.poor = Math.floor((groups - 1) / 2); |
|
dict.start = dict.index > 1 ? curr - dict.poor : 1; |
|
dict.end = dict.index > 1 ? (function () { |
|
var max = curr + (groups - dict.poor - 1); |
|
return max > pages ? pages : max; |
|
}()) : groups; |
|
if (dict.end - dict.start < groups - 1) { // 最后一组状态 |
|
dict.start = dict.end - groups + 1; |
|
} |
|
var s = dict.start, e = dict.end; |
|
if (first && last && (dict.index > 1 && groups !== 0) && (pages > groups && dict.end < pages && groups !== 0)) { |
|
s++; |
|
e--; |
|
} |
|
for (; s <= e; s++) { |
|
if (s === curr) { |
|
view.push({ |
|
text: s, |
|
value: s, |
|
selected: true |
|
}); |
|
} else { |
|
view.push({ |
|
text: s, |
|
value: s |
|
}); |
|
} |
|
} |
|
|
|
// 总页数大于连续分页数,且当前组最大页小于总页,输出尾页 |
|
if (((!o.dynamicShow && !o.dynamicShowFirstLast) || (pages > groups && dict.end < pages && groups !== 0)) && last) { |
|
if (pages > groups && dict.end < pages && groups !== 0) { |
|
view.push({ |
|
type: "bi.label", |
|
cls: "page-ellipsis", |
|
text: "\u2026" |
|
}); |
|
} |
|
view.push({ |
|
text: last, |
|
value: "last", |
|
disabled: !(pages > groups && dict.end < pages && groups !== 0) |
|
}); |
|
} |
|
|
|
// 当前页不为尾页时,输出下一页 |
|
dict.flow = !prev && groups === 0; |
|
if (((!o.dynamicShow && !o.dynamicShowPrevNext) && next) || (curr !== pages && next || dict.flow)) { |
|
view.push((function () { |
|
if (BI.isKey(next)) { |
|
if (pages === false) { |
|
return {text: next, value: "next", disabled: o.hasNext(curr) === false}; |
|
} |
|
return (dict.flow && curr === pages) |
|
? |
|
{text: next, value: "next", disabled: true} |
|
: |
|
{text: next, value: "next", disabled: !(curr !== pages && next || dict.flow)}; |
|
} |
|
return BI.extend({ |
|
disabled: pages === false ? o.hasNext(curr) === false : !(curr !== pages && next || dict.flow) |
|
}, next); |
|
|
|
}())); |
|
} |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.button_group", |
|
element: this, |
|
items: BI.createItems(view, { |
|
cls: "bi-list-item-select bi-border-radius", |
|
height: 23, |
|
hgap: 10 |
|
}), |
|
behaviors: o.behaviors, |
|
layouts: o.layouts |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
// if (self._lock === true) { |
|
// return; |
|
// } |
|
// self._lock = true; |
|
// self._debouce(); |
|
if (type === BI.Events.CLICK) { |
|
var v = self.button_group.getValue()[0]; |
|
switch (v) { |
|
case "first": |
|
self.currPage = 1; |
|
break; |
|
case "last": |
|
self.currPage = pages; |
|
break; |
|
case "prev": |
|
self.currPage--; |
|
break; |
|
case "next": |
|
self.currPage++; |
|
break; |
|
default: |
|
self.currPage = v; |
|
break; |
|
} |
|
o.jump.apply(self, [{ |
|
pages: pages, |
|
curr: self.currPage |
|
}]); |
|
self._populate(); |
|
self.fireEvent(BI.Pager.EVENT_CHANGE, obj); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.fireEvent(BI.Pager.EVENT_AFTER_POPULATE); |
|
}, |
|
|
|
getCurrentPage: function () { |
|
return this.currPage; |
|
}, |
|
|
|
setAllPages: function (pages) { |
|
this.options.pages = pages; |
|
}, |
|
|
|
hasPrev: function (v) { |
|
v || (v = 1); |
|
var o = this.options; |
|
var pages = this.options.pages; |
|
return pages === false ? o.hasPrev(v) : v > 1; |
|
}, |
|
|
|
hasNext: function (v) { |
|
v || (v = 1); |
|
var o = this.options; |
|
var pages = this.options.pages; |
|
return pages === false ? o.hasNext(v) : v < pages; |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
v = v | 0; |
|
v = v < 1 ? 1 : v; |
|
if (o.pages === false) { |
|
var lastPage = BI.result(o, "lastPage"), firstPage = 1; |
|
this.currPage = v > lastPage ? lastPage : ((firstPage = BI.result(o, "firstPage")), (v < firstPage ? firstPage : v)); |
|
} else { |
|
v = v > o.pages ? o.pages : v; |
|
this.currPage = v; |
|
} |
|
this._populate(); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.button_group.getValue()[0]; |
|
switch (val) { |
|
case "prev": |
|
return -1; |
|
case "next": |
|
return 1; |
|
case "first": |
|
return BI.MIN; |
|
case "last": |
|
return BI.MAX; |
|
default : |
|
return val; |
|
} |
|
}, |
|
|
|
attr: function (key, value) { |
|
BI.Pager.superclass.attr.apply(this, arguments); |
|
if (key === "curr") { |
|
this.currPage = BI.result(this.options, "curr"); |
|
} |
|
}, |
|
|
|
populate: function () { |
|
this._populate(); |
|
} |
|
}); |
|
BI.Pager.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.Pager.EVENT_AFTER_POPULATE = "EVENT_AFTER_POPULATE"; |
|
BI.shortcut("bi.pager", BI.Pager);/** |
|
* 超链接 |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.A |
|
* @extends BI.Text |
|
* @abstract |
|
*/ |
|
BI.A = BI.inherit(BI.Text, { |
|
_defaultConfig: function () { |
|
var conf = BI.A.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-a display-block", |
|
href: "", |
|
target: "_blank", |
|
el: null, |
|
tagName: "a" |
|
}); |
|
}, |
|
_init: function () { |
|
var o = this.options; |
|
BI.A.superclass._init.apply(this, arguments); |
|
this.element.attr({href: o.href, target: o.target}); |
|
if (o.el) { |
|
BI.createWidget(o.el, { |
|
element: this |
|
}); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.a", BI.A);/** |
|
* guy |
|
* 加载条 |
|
* @type {*|void|Object} |
|
*/ |
|
BI.LoadingBar = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.LoadingBar.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend( conf, { |
|
baseCls: (conf.baseCls || "") + " bi-loading-bar bi-tips", |
|
height: 30, |
|
handler: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.LoadingBar.superclass._init.apply(this, arguments); |
|
var self = this; |
|
this.loaded = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "loading-text bi-list-item-simple", |
|
text: BI.i18nText("BI-Load_More"), |
|
width: 120, |
|
handler: this.options.handler |
|
}); |
|
this.loaded.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.loading = BI.createWidget({ |
|
type: "bi.layout", |
|
width: this.options.height, |
|
height: this.options.height, |
|
cls: "loading-background cursor-default" |
|
}); |
|
var loaded = BI.createWidget({ |
|
type: "bi.center_adapt", |
|
items: [this.loaded] |
|
}); |
|
var loading = BI.createWidget({ |
|
type: "bi.center_adapt", |
|
items: [this.loading] |
|
}); |
|
this.cardLayout = BI.createWidget({ |
|
type: "bi.card", |
|
element: this, |
|
items: [{ |
|
el: loaded, |
|
cardName: "loaded" |
|
}, { |
|
el: loading, |
|
cardName: "loading" |
|
}] |
|
}); |
|
this.invisible(); |
|
}, |
|
|
|
_reset: function () { |
|
this.visible(); |
|
this.loaded.setText(BI.i18nText("BI-Load_More")); |
|
this.loaded.enable(); |
|
}, |
|
|
|
setLoaded: function () { |
|
this._reset(); |
|
this.cardLayout.showCardByName("loaded"); |
|
}, |
|
|
|
setEnd: function () { |
|
this.setLoaded(); |
|
this.loaded.setText(BI.i18nText("BI-No_More_Data")); |
|
this.loaded.disable(); |
|
}, |
|
|
|
setLoading: function () { |
|
this._reset(); |
|
this.cardLayout.showCardByName("loading"); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.loading_bar", BI.LoadingBar);/** |
|
* @class BI.IconButton |
|
* @extends BI.BasicButton |
|
* 图标的button |
|
*/ |
|
BI.IconButton = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.IconButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-icon-button horizon-center", |
|
iconWidth: null, |
|
iconHeight: null |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconButton.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.element.css({ |
|
textAlign: "center" |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon", |
|
width: o.iconWidth, |
|
height: o.iconHeight |
|
}); |
|
if (BI.isNumber(o.height) && o.height > 0 && BI.isNull(o.iconWidth) && BI.isNull(o.iconHeight)) { |
|
this.element.css("lineHeight", o.height + "px"); |
|
BI.createWidget({ |
|
type: "bi.default", |
|
element: this, |
|
items: [this.icon] |
|
}); |
|
} else { |
|
this.element.css("lineHeight", "1"); |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.center_adapt", |
|
items: [this.icon] |
|
}); |
|
} |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconButton.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.IconButton.EVENT_CHANGE, this); |
|
} |
|
} |
|
}); |
|
BI.IconButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_button", BI.IconButton);/** |
|
* 图片的button |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.ImageButton |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.ImageButton = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.ImageButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-image-button", |
|
src: "", |
|
iconWidth: "100%", |
|
iconHeight: "100%" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ImageButton.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.image = BI.createWidget({ |
|
type: "bi.img", |
|
width: o.iconWidth, |
|
height: o.iconHeight, |
|
src: o.src |
|
}); |
|
if (BI.isNumber(o.iconWidth) || BI.isNumber(o.iconHeight)) { |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
element: this, |
|
items: [this.image] |
|
}); |
|
} else { |
|
BI.createWidget({ |
|
type: "bi.adaptive", |
|
element: this, |
|
items: [this.image], |
|
scrollable: false |
|
}); |
|
} |
|
}, |
|
|
|
setWidth: function (w) { |
|
BI.ImageButton.superclass.setWidth.apply(this, arguments); |
|
this.options.width = w; |
|
}, |
|
|
|
setHeight: function (h) { |
|
BI.ImageButton.superclass.setHeight.apply(this, arguments); |
|
this.options.height = h; |
|
}, |
|
|
|
setImageWidth: function (w) { |
|
this.image.setWidth(w); |
|
}, |
|
|
|
setImageHeight: function (h) { |
|
this.image.setHeight(h); |
|
}, |
|
|
|
getImageWidth: function () { |
|
return this.image.element.width(); |
|
}, |
|
|
|
getImageHeight: function () { |
|
return this.image.element.height(); |
|
}, |
|
|
|
setSrc: function (src) { |
|
this.options.src = src; |
|
this.image.setSrc(src); |
|
}, |
|
|
|
getSrc: function () { |
|
return this.image.getSrc(); |
|
}, |
|
|
|
doClick: function () { |
|
BI.ImageButton.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.ImageButton.EVENT_CHANGE, this); |
|
} |
|
} |
|
}); |
|
BI.ImageButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.image_button", BI.ImageButton); |
|
/** |
|
* 文字类型的按钮 |
|
* @class BI.Button |
|
* @extends BI.BasicButton |
|
* |
|
* @cfg {JSON} options 配置属性 |
|
* @cfg {'common'/'success'/'warning'/'ignore'} [options.level='common'] 按钮类型,用不同颜色强调不同的场景 |
|
*/ |
|
BI.Button = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function (props) { |
|
var conf = BI.Button.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-button" + ((BI.isIE() && BI.isIE9Below()) ? " hack" : ""), |
|
minWidth: (props.block === true || props.clear === true) ? 0 : 80, |
|
height: 24, |
|
shadow: props.clear !== true, |
|
isShadowShowingOnSelected: true, |
|
readonly: true, |
|
iconCls: "", |
|
level: "common", |
|
block: false, // 是否块状显示,即不显示边框,没有最小宽度的限制 |
|
clear: false, // 是否去掉边框和背景 |
|
ghost: false, // 是否幽灵显示, 即正常状态无背景 |
|
textAlign: "center", |
|
whiteSpace: "nowrap", |
|
textWidth: null, |
|
textHeight: null, |
|
hgap: props.clear ? 0 : 10, |
|
vgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
lgap: 0, |
|
rgap: 0 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Button.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
if (BI.isNumber(o.height) && !o.clear && !o.block) { |
|
this.element.css({height: o.height + "px", lineHeight: (o.height - 2) + "px"}); |
|
} else if (o.clear || o.block) { |
|
this.element.css({lineHeight: o.height + "px"}); |
|
} else { |
|
this.element.css({lineHeight: (o.height - 2) + "px"}); |
|
} |
|
if (BI.isKey(o.iconCls)) { |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
cls: o.iconCls, |
|
width: 18, |
|
height: o.height - 2, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
text: o.text, |
|
value: o.value, |
|
height: o.height - 2 |
|
}); |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
element: this, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
items: [{ |
|
type: "bi.horizontal", |
|
items: [this.icon, this.text] |
|
}] |
|
}); |
|
} else { |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
textWidth: o.textWidth, |
|
textHeight: o.textHeight, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
element: this, |
|
text: o.text, |
|
value: o.value |
|
}); |
|
} |
|
if (o.block === true) { |
|
this.element.addClass("block"); |
|
} |
|
if (o.clear === true) { |
|
this.element.addClass("clear"); |
|
} |
|
if (o.ghost === true) { |
|
this.element.addClass("ghost"); |
|
} |
|
if (o.minWidth > 0) { |
|
this.element.css({"min-width": o.minWidth + "px"}); |
|
} |
|
}, |
|
|
|
doClick: function () { |
|
BI.Button.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.Button.EVENT_CHANGE, this); |
|
} |
|
}, |
|
|
|
setText: function (text) { |
|
BI.Button.superclass.setText.apply(this, arguments); |
|
this.text.setText(text); |
|
}, |
|
|
|
setValue: function (text) { |
|
BI.Button.superclass.setValue.apply(this, arguments); |
|
if (!this.isReadOnly()) { |
|
this.text.setValue(text); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
destroy: function () { |
|
BI.Button.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.button", BI.Button); |
|
BI.Button.EVENT_CHANGE = "EVENT_CHANGE"; |
|
/** |
|
* guy |
|
* 可以点击的一行文字 |
|
* @class BI.TextButton |
|
* @extends BI.BasicButton |
|
* 文字button |
|
*/ |
|
BI.TextButton = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.TextButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-button", |
|
textAlign: "center", |
|
whiteSpace: "nowrap", |
|
textWidth: null, |
|
textHeight: null, |
|
hgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
text: "", |
|
py: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextButton.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
element: this, |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
textWidth: o.textWidth, |
|
textHeight: o.textHeight, |
|
width: o.width, |
|
height: o.height, |
|
hgap: o.hgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
}, |
|
|
|
doClick: function () { |
|
BI.TextButton.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.TextButton.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
setText: function (text) { |
|
BI.TextButton.superclass.setText.apply(this, arguments); |
|
text = BI.isArray(text) ? text.join(",") : text; |
|
this.text.setText(text); |
|
}, |
|
|
|
setStyle: function (style) { |
|
this.text.setStyle(style); |
|
}, |
|
|
|
setValue: function (text) { |
|
BI.TextButton.superclass.setValue.apply(this, arguments); |
|
if (!this.isReadOnly()) { |
|
text = BI.isArray(text) ? text.join(",") : text; |
|
this.text.setValue(text); |
|
} |
|
} |
|
}); |
|
BI.TextButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_button", BI.TextButton);/** |
|
* 带有一个占位 |
|
* |
|
* Created by GUY on 2015/9/11. |
|
* @class BI.BlankIconIconTextItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.BlankIconIconTextItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.BlankIconIconTextItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-blank-icon-text-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
iconCls1: "close-ha-font", |
|
iconCls2: "close-ha-font", |
|
blankWidth: 0, |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BlankIconIconTextItem.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
var blank = BI.createWidget({ |
|
type: "bi.layout", |
|
width: o.blankWidth, |
|
height: o.height |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon1 = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: o.iconCls1, |
|
forceNotSelected: true, |
|
width: o.height, |
|
height: o.height |
|
}); |
|
this.icon2 = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: o.iconCls2, |
|
forceNotSelected: true, |
|
width: o.height, |
|
height: o.height |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", blank, this.icon1, this.icon2, this.text) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.BlankIconIconTextItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.BlankIconIconTextItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.BlankIconIconTextItem.superclass.setSelected.apply(this, arguments); |
|
this.icon1.setSelected(b); |
|
this.icon2.setSelected(b); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.BlankIconIconTextItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.blank_icon_icon_text_item", BI.BlankIconIconTextItem);/** |
|
* guy |
|
* 一个占位符和两个icon和一行数 组成的一行listitem |
|
* |
|
* Created by GUY on 2015/9/15. |
|
* @class BI.BlankIconTextIconItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.BlankIconTextIconItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.BlankIconTextIconItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-blank-icon-text-icon-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
iconCls1: "close-ha-font", |
|
iconCls2: "close-ha-font", |
|
blankWidth: 0, |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BlankIconTextIconItem.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
|
|
var icon1 = BI.createWidget({ |
|
type: "bi.icon_label", |
|
cls: o.iconCls1, |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_label", |
|
cls: o.iconCls2, |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}, |
|
top: 0, |
|
bottom: 0, |
|
right: 0 |
|
}] |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", { |
|
type: "bi.layout", |
|
width: o.blankWidth |
|
}, icon1, this.text, { |
|
type: "bi.layout", |
|
width: o.height |
|
}) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.BlankIconTextIconItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.BlankIconTextIconItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.BlankIconTextIconItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.blank_icon_text_icon_item", BI.BlankIconTextIconItem);/** |
|
* 带有一个占位 |
|
* |
|
* Created by GUY on 2015/9/11. |
|
* @class BI.BlankIconTextItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.BlankIconTextItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.BlankIconTextItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-blank-icon-text-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
cls: "close-ha-font", |
|
blankWidth: 0, |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BlankIconTextItem.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
var blank = BI.createWidget({ |
|
type: "bi.layout", |
|
width: o.blankWidth |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", blank, this.icon, this.text) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.BlankIconTextItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.BlankIconTextItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.BlankIconTextItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.blank_icon_text_item", BI.BlankIconTextItem);/** |
|
* guy |
|
* 两个icon和一行数 组成的一行listitem |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.IconTextIconItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.IconTextIconItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.IconTextIconItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-icon-text-icon-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
iconCls1: "close-ha-font", |
|
iconCls2: "close-ha-font", |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.IconTextIconItem.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
|
|
var icon1 = BI.createWidget({ |
|
type: "bi.icon_label", |
|
cls: o.iconCls1, |
|
width: o.leftIconWrapperWidth, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
var blank = BI.createWidget({ |
|
type: "bi.layout", |
|
width: o.height |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_label", |
|
cls: o.iconCls2, |
|
width: o.rightIconWrapperWidth, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}, |
|
top: 0, |
|
bottom: 0, |
|
right: 0 |
|
}] |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", icon1, this.text, blank) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconTextIconItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.IconTextIconItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.IconTextIconItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_text_icon_item", BI.IconTextIconItem);/** |
|
* guy |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.IconTextItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.IconTextItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.IconTextItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-icon-text-item", |
|
direction: BI.Direction.Left, |
|
logic: { |
|
dynamic: false |
|
}, |
|
iconWrapperWidth: null, |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.IconTextItem.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
width: o.iconWrapperWidth || o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.icon, this.text) |
|
})))); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconTextItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.IconTextItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.IconTextItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_text_item", BI.IconTextItem);/** |
|
* |
|
* 图标的button |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.TextIconItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.TextIconItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.TextIconItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-icon-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
cls: "close-ha-font", |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.TextIconItem.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", this.text, this.icon) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.TextIconItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.TextIconItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.TextIconItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_icon_item", BI.TextIconItem);/** |
|
* guy |
|
* 一个button和一行数 组成的一行listitem |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.TextItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.TextItem = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.TextItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-item", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.TextItem.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
element: this, |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
textHeight: o.whiteSpace == "nowrap" ? o.height : o.textHeight, |
|
height: o.height, |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
}, |
|
|
|
doClick: function () { |
|
BI.TextItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.TextItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.TextItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_item", BI.TextItem);/** |
|
* guy |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.IconTextIconNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.IconTextIconNode = BI.inherit(BI.NodeButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.IconTextIconNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-icon-text-icon-node", |
|
logic: { |
|
dynamic: false |
|
}, |
|
iconCls1: "close-ha-font", |
|
iconCls2: "close-ha-font", |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.IconTextIconNode.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
|
|
var icon1 = BI.createWidget({ |
|
type: "bi.icon_label", |
|
cls: o.iconCls1, |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
var blank = BI.createWidget({ |
|
type: "bi.layout", |
|
width: o.height, |
|
height: o.height |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_label", |
|
cls: o.iconCls2, |
|
width: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}, |
|
top: 0, |
|
bottom: 0, |
|
right: 0 |
|
}] |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", icon1, this.text, blank) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconTextIconNode.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.IconTextIconNode.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.IconTextIconNode.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_text_icon_node", BI.IconTextIconNode);/** |
|
* guy |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.IconTextNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.IconTextNode = BI.inherit(BI.NodeButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.IconTextNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-icon-text-node", |
|
logic: { |
|
dynamic: false |
|
}, |
|
cls: "close-ha-font", |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.IconTextNode.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", this.icon, this.text) |
|
})))); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconTextNode.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.IconTextNode.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.IconTextNode.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_text_node", BI.IconTextNode);/** |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.TextIconNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.TextIconNode = BI.inherit(BI.NodeButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.TextIconNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-icon-node", |
|
logic: { |
|
dynamic: false |
|
}, |
|
cls: "close-ha-font", |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.TextIconNode.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
width: o.height, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", this.text, this.icon) |
|
})))); |
|
}, |
|
|
|
doClick: function () { |
|
BI.TextIconNode.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.TextIconNode.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.TextIconNode.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_icon_node", BI.TextIconNode);/** |
|
* guy |
|
* |
|
* Created by GUY on 2015/9/9. |
|
* @class BI.TextNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.TextNode = BI.inherit(BI.NodeButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.TextNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-node", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.TextNode.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
element: this, |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
textHeight: o.whiteSpace == "nowrap" ? o.height : o.textHeight, |
|
height: o.height, |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
}, |
|
|
|
doClick: function () { |
|
BI.TextNode.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.TextNode.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.TextNode.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_node", BI.TextNode);/** |
|
* Created by GUY on 2015/4/15. |
|
* @class BI.Editor |
|
* @extends BI.Single |
|
*/ |
|
BI.Editor = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Editor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-editor bi-focus-shadow", |
|
hgap: 4, |
|
vgap: 2, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
// title,warningTitle这两个属性没用 |
|
tipType: "warning", |
|
inputType: "text", |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: false, |
|
watermark: "", |
|
errorText: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Editor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = this.addWidget(BI.createWidget({ |
|
type: "bi.input", |
|
element: "<input type='" + o.inputType + "'/>", |
|
root: true, |
|
value: o.value, |
|
watermark: o.watermark, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank |
|
})); |
|
this.editor.element.css({ |
|
width: "100%", |
|
height: "100%", |
|
border: "none", |
|
outline: "none", |
|
padding: "0", |
|
margin: "0" |
|
}); |
|
if (BI.isKey(this.options.watermark)) { |
|
this._assertWaterMark(); |
|
} |
|
|
|
var _items = []; |
|
if (this.watermark) { |
|
_items.push({ |
|
el: this.watermark, |
|
left: 3, |
|
right: 3, |
|
top: 0, |
|
bottom: 0 |
|
}); |
|
} |
|
_items.push({ |
|
el: this.editor, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}); |
|
|
|
var items = [{ |
|
el: { |
|
type: "bi.absolute", |
|
ref: function(_ref) { |
|
self.contentWrapper = _ref; |
|
}, |
|
items: _items |
|
}, |
|
left: o.hgap + o.lgap, |
|
right: o.hgap + o.rgap, |
|
top: o.vgap + o.tgap, |
|
bottom: o.vgap + o.bgap |
|
}]; |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: items |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_FOCUS, function () { |
|
self._checkError(); |
|
self.element.addClass("bi-editor-focus"); |
|
self.fireEvent(BI.Editor.EVENT_FOCUS, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_BLUR, function () { |
|
self._setErrorVisible(false); |
|
self.element.removeClass("bi-editor-focus"); |
|
self.fireEvent(BI.Editor.EVENT_BLUR, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_CLICK, function () { |
|
self.fireEvent(BI.Editor.EVENT_CLICK, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Editor.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.Editor.EVENT_KEY_DOWN, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_QUICK_DOWN, function (e) { |
|
// tab键就不要隐藏了 |
|
if (e.keyCode !== BI.KeyCode.TAB && self.watermark) { |
|
self.watermark.invisible(); |
|
} |
|
}); |
|
|
|
this.editor.on(BI.Input.EVENT_VALID, function () { |
|
self._checkWaterMark(); |
|
self._setErrorVisible(false); |
|
self.fireEvent(BI.Editor.EVENT_VALID, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_ERROR, function () { |
|
self._checkWaterMark(); |
|
self.fireEvent(BI.Editor.EVENT_ERROR, arguments); |
|
self._setErrorVisible(self.isEditing()); |
|
}); |
|
this.editor.on(BI.Input.EVENT_RESTRICT, function () { |
|
self._checkWaterMark(); |
|
var tip = self._setErrorVisible(true); |
|
tip && tip.element.fadeOut(100, function () { |
|
tip.element.fadeIn(100); |
|
}); |
|
self.fireEvent(BI.Editor.EVENT_RESTRICT, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_EMPTY, function () { |
|
self._checkWaterMark(); |
|
self.fireEvent(BI.Editor.EVENT_EMPTY, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_ENTER, function () { |
|
self.fireEvent(BI.Editor.EVENT_ENTER, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_SPACE, function () { |
|
self.fireEvent(BI.Editor.EVENT_SPACE, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_BACKSPACE, function () { |
|
self.fireEvent(BI.Editor.EVENT_BACKSPACE, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_REMOVE, function () { |
|
self.fireEvent(BI.Editor.EVENT_REMOVE, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_START, function () { |
|
self.fireEvent(BI.Editor.EVENT_START, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.Editor.EVENT_PAUSE, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_STOP, function () { |
|
self.fireEvent(BI.Editor.EVENT_STOP, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.Editor.EVENT_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Input.EVENT_CHANGE_CONFIRM, function () { |
|
self.fireEvent(BI.Editor.EVENT_CHANGE_CONFIRM, arguments); |
|
}); |
|
this.element.click(function (e) { |
|
e.stopPropagation(); |
|
return false; |
|
}); |
|
if (BI.isKey(this.options.value) || BI.isEmptyString(this.options.value)) { |
|
this._checkError(); |
|
this._checkWaterMark(); |
|
} else { |
|
this._checkWaterMark(); |
|
} |
|
}, |
|
|
|
_checkToolTip: function () { |
|
var o = this.options; |
|
var errorText = o.errorText; |
|
if (BI.isFunction(errorText)) { |
|
errorText = errorText(this.editor.getValue()); |
|
} |
|
if (BI.isKey(errorText)) { |
|
if (!this.isEnabled() || this.isValid() || (BI.Bubbles.has(this.getName()) && BI.Bubbles.get(this.getName()).isVisible())) { |
|
this.setTitle(""); |
|
} else { |
|
this.setTitle(errorText); |
|
} |
|
} |
|
}, |
|
|
|
_assertWaterMark: function() { |
|
var self = this, o = this.options; |
|
if(BI.isNull(this.watermark)) { |
|
this.watermark = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "bi-water-mark", |
|
text: this.options.watermark, |
|
height: o.height - 2 * (o.vgap + o.tgap), |
|
whiteSpace: "nowrap", |
|
textAlign: "left" |
|
}); |
|
this.watermark.element.bind({ |
|
mousedown: function (e) { |
|
if (self.isEnabled()) { |
|
self.editor.isEditing() || self.editor.focus(); |
|
} else { |
|
self.editor.isEditing() && self.editor.blur(); |
|
} |
|
e.stopEvent(); |
|
} |
|
}); |
|
this.watermark.element.bind("click", function (e) { |
|
if (self.isEnabled()) { |
|
self.editor.isEditing() || self.editor.focus(); |
|
} else { |
|
self.editor.isEditing() && self.editor.blur(); |
|
} |
|
e.stopEvent(); |
|
}); |
|
} |
|
}, |
|
|
|
_checkError: function () { |
|
this._setErrorVisible(this.isEnabled() && !this.isValid()); |
|
this._checkToolTip(); |
|
}, |
|
|
|
_checkWaterMark: function () { |
|
var o = this.options; |
|
if (!this.disabledWaterMark && this.editor.getValue() === "" && BI.isKey(o.watermark)) { |
|
this.watermark && this.watermark.visible(); |
|
} else { |
|
this.watermark && this.watermark.invisible(); |
|
} |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.options.errorText = text; |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.options.errorText; |
|
}, |
|
|
|
setWaterMark: function(v) { |
|
this.options.watermark = v; |
|
if(BI.isNull(this.watermark)) { |
|
this._assertWaterMark(); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this.contentWrapper, |
|
items: [{ |
|
el: this.watermark, |
|
left: 3, |
|
right: 3, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}) |
|
} |
|
BI.isKey(v) && this.watermark.setText(v); |
|
}, |
|
|
|
_setErrorVisible: function (b) { |
|
var o = this.options; |
|
var errorText = o.errorText; |
|
if (BI.isFunction(errorText)) { |
|
errorText = errorText(BI.trim(this.editor.getValue())); |
|
} |
|
if (!this.disabledError && BI.isKey(errorText)) { |
|
BI.Bubbles[b ? "show" : "hide"](this.getName(), errorText, this, { |
|
adjustYOffset: 2 |
|
}); |
|
this._checkToolTip(); |
|
return BI.Bubbles.get(this.getName()); |
|
} |
|
}, |
|
|
|
disableError: function () { |
|
this.disabledError = true; |
|
this._checkError(); |
|
}, |
|
|
|
enableError: function () { |
|
this.disabledError = false; |
|
this._checkError(); |
|
}, |
|
|
|
disableWaterMark: function () { |
|
this.disabledWaterMark = true; |
|
this._checkWaterMark(); |
|
}, |
|
|
|
enableWaterMark: function () { |
|
this.disabledWaterMark = false; |
|
this._checkWaterMark(); |
|
}, |
|
|
|
focus: function () { |
|
this.element.addClass("text-editor-focus"); |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.element.removeClass("text-editor-focus"); |
|
this.editor.blur(); |
|
}, |
|
|
|
selectAll: function () { |
|
this.editor.selectAll(); |
|
}, |
|
|
|
onKeyDown: function (k) { |
|
this.editor.onKeyDown(k); |
|
}, |
|
|
|
setValue: function (v) { |
|
BI.Editor.superclass.setValue.apply(this, arguments); |
|
this.editor.setValue(v); |
|
this._checkError(); |
|
this._checkWaterMark(); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
getValue: function () { |
|
if (!this.isValid()) { |
|
return BI.trim(this.editor.getLastValidValue()); |
|
} |
|
return BI.trim(this.editor.getValue()); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
destroyed: function () { |
|
BI.Bubbles.remove(this.getName()); |
|
} |
|
}); |
|
BI.Editor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.Editor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.Editor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.Editor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.Editor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.Editor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.Editor.EVENT_BACKSPACE = "EVENT_BACKSPACE"; |
|
|
|
BI.Editor.EVENT_START = "EVENT_START"; |
|
BI.Editor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.Editor.EVENT_STOP = "EVENT_STOP"; |
|
BI.Editor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.Editor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.Editor.EVENT_VALID = "EVENT_VALID"; |
|
BI.Editor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.Editor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.Editor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.Editor.EVENT_REMOVE = "EVENT_REMOVE"; |
|
BI.Editor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
|
|
BI.shortcut("bi.editor", BI.Editor);/** |
|
* 多文件 |
|
* |
|
* Created by GUY on 2016/4/13. |
|
* @class BI.MultifileEditor |
|
* @extends BI.Single |
|
* @abstract |
|
*/ |
|
BI.MultifileEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultifileEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-multifile-editor", |
|
multiple: false, |
|
maxSize: -1, // 1024 * 1024 |
|
accept: "", |
|
url: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
var self = this, o = this.options; |
|
BI.MultifileEditor.superclass._init.apply(this, arguments); |
|
this.file = BI.createWidget({ |
|
type: "bi.file", |
|
cls: "multifile-editor", |
|
width: "100%", |
|
height: "100%", |
|
name: o.name, |
|
url: o.url, |
|
multiple: o.multiple, |
|
accept: o.accept, |
|
maxSize: o.maxSize, |
|
title: o.title |
|
}); |
|
this.file.on(BI.File.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultifileEditor.EVENT_CHANGE, arguments); |
|
}); |
|
this.file.on(BI.File.EVENT_UPLOADSTART, function () { |
|
self.fireEvent(BI.MultifileEditor.EVENT_UPLOADSTART, arguments); |
|
}); |
|
this.file.on(BI.File.EVENT_ERROR, function () { |
|
self.fireEvent(BI.MultifileEditor.EVENT_ERROR, arguments); |
|
}); |
|
this.file.on(BI.File.EVENT_PROGRESS, function () { |
|
self.fireEvent(BI.MultifileEditor.EVENT_PROGRESS, arguments); |
|
}); |
|
this.file.on(BI.File.EVENT_UPLOADED, function () { |
|
self.fireEvent(BI.MultifileEditor.EVENT_UPLOADED, arguments); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.adaptive", |
|
scrollable: false, |
|
items: [this.file] |
|
}, |
|
top: 0, |
|
right: 0, |
|
left: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
select: function () { |
|
this.file.select(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.file.getValue(); |
|
}, |
|
|
|
upload: function () { |
|
this.file.upload(); |
|
}, |
|
|
|
reset: function () { |
|
this.file.reset(); |
|
} |
|
}); |
|
BI.MultifileEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultifileEditor.EVENT_UPLOADSTART = "EVENT_UPLOADSTART"; |
|
BI.MultifileEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.MultifileEditor.EVENT_PROGRESS = "EVENT_PROGRESS"; |
|
BI.MultifileEditor.EVENT_UPLOADED = "EVENT_UPLOADED"; |
|
BI.shortcut("bi.multifile_editor", BI.MultifileEditor);/** |
|
* |
|
* Created by GUY on 2016/1/18. |
|
* @class BI.TextAreaEditor |
|
* @extends BI.Single |
|
*/ |
|
BI.TextAreaEditor = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TextAreaEditor.superclass._defaultConfig.apply(), { |
|
baseCls: "bi-textarea-editor", |
|
value: "" |
|
}); |
|
}, |
|
|
|
render: function() { |
|
var o = this.options, self = this; |
|
this.content = BI.createWidget({ |
|
type: "bi.layout", |
|
tagName: "textarea", |
|
width: "100%", |
|
height: "100%", |
|
cls: "bi-textarea textarea-editor-content display-block" |
|
}); |
|
this.content.element.css({resize: "none"}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.adaptive", |
|
items: [this.content] |
|
}, |
|
left: 4, |
|
right: 4, |
|
top: 4, |
|
bottom: 8 |
|
}] |
|
}); |
|
|
|
this.content.element.on("input propertychange", function (e) { |
|
self._checkWaterMark(); |
|
self.fireEvent(BI.TextAreaEditor.EVENT_CHANGE); |
|
}); |
|
|
|
this.content.element.focus(function () { |
|
if (self.isValid()) { |
|
self._focus(); |
|
self.fireEvent(BI.TextAreaEditor.EVENT_FOCUS); |
|
} |
|
BI.Widget._renderEngine.createElement(document).bind("mousedown." + self.getName(), function (e) { |
|
if (BI.DOM.isExist(self) && !self.element.__isMouseInBounds__(e)) { |
|
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + self.getName()); |
|
self.content.element.blur(); |
|
} |
|
}); |
|
}); |
|
this.content.element.blur(function () { |
|
if (self.isValid()) { |
|
self._blur(); |
|
self.fireEvent(BI.TextAreaEditor.EVENT_BLUR); |
|
} |
|
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + self.getName()); |
|
}); |
|
if (BI.isKey(o.value)) { |
|
this.setValue(o.value); |
|
} |
|
if (BI.isNotNull(o.style)) { |
|
this.setStyle(o.style); |
|
} |
|
this._checkWaterMark(); |
|
}, |
|
|
|
_checkWaterMark: function () { |
|
var self = this, o = this.options; |
|
var val = this.getValue(); |
|
if (BI.isNotEmptyString(val)) { |
|
this.watermark && this.watermark.destroy(); |
|
this.watermark = null; |
|
} else { |
|
if (BI.isNotEmptyString(o.watermark)) { |
|
if (!this.watermark) { |
|
this.watermark = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "bi-water-mark cursor-default", |
|
textAlign: "left", |
|
whiteSpace: "normal", |
|
text: o.watermark, |
|
invalid: o.invalid, |
|
disabled: o.disabled |
|
}); |
|
this.watermark.on(BI.TextButton.EVENT_CHANGE, function () { |
|
self.focus(); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.watermark, |
|
left: 4, |
|
top: 4, |
|
right: 0 |
|
}] |
|
}); |
|
} else { |
|
this.watermark.setText(o.watermark); |
|
this.watermark.setValid(!o.invalid); |
|
this.watermark.setEnable(!o.disabled); |
|
} |
|
} |
|
} |
|
}, |
|
|
|
_focus: function () { |
|
this.content.element.addClass("textarea-editor-focus"); |
|
this._checkWaterMark(); |
|
}, |
|
|
|
_blur: function () { |
|
this.content.element.removeClass("textarea-editor-focus"); |
|
this._checkWaterMark(); |
|
}, |
|
|
|
focus: function () { |
|
this._focus(); |
|
this.content.element.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this._blur(); |
|
this.content.element.blur(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.content.element.val(); |
|
}, |
|
|
|
setValue: function (value) { |
|
this.content.element.val(value); |
|
this._checkWaterMark(); |
|
}, |
|
|
|
setStyle: function (style) { |
|
this.style = style; |
|
this.element.css(style); |
|
this.content.element.css(BI.extend({}, style, { |
|
color: style.color || BI.DOM.getContrastColor(BI.DOM.isRGBColor(style.backgroundColor) ? BI.DOM.rgb2hex(style.backgroundColor) : style.backgroundColor) |
|
})); |
|
}, |
|
|
|
getStyle: function () { |
|
return this.style; |
|
}, |
|
|
|
_setValid: function (b) { |
|
BI.TextAreaEditor.superclass._setValid.apply(this, arguments); |
|
// this.content.setValid(b); |
|
// this.watermark && this.watermark.setValid(b); |
|
}, |
|
|
|
_setEnable: function (b) { |
|
BI.TextAreaEditor.superclass._setEnable.apply(this, [b]); |
|
this.content && (this.content.element[0].disabled = !b); |
|
} |
|
}); |
|
BI.TextAreaEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.TextAreaEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.TextAreaEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.shortcut("bi.textarea_editor", BI.TextAreaEditor);/** |
|
* guy 表示一行数据,通过position来定位位置的数据 |
|
* @class BI.Html |
|
* @extends BI.Single |
|
*/ |
|
BI.Html = BI.inherit(BI.Single, { |
|
|
|
props: { |
|
baseCls: "bi-html", |
|
textAlign: "left", |
|
whiteSpace: "normal", |
|
lineHeight: null, |
|
handler: null, // 如果传入handler,表示处理文字的点击事件,不是区域的 |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
text: "", |
|
highLight: false |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
if (o.hgap + o.lgap > 0) { |
|
this.element.css({ |
|
"padding-left": o.hgap + o.lgap + "px" |
|
}); |
|
} |
|
if (o.hgap + o.rgap > 0) { |
|
this.element.css({ |
|
"padding-right": o.hgap + o.rgap + "px" |
|
}); |
|
} |
|
if (o.vgap + o.tgap > 0) { |
|
this.element.css({ |
|
"padding-top": o.vgap + o.tgap + "px" |
|
}); |
|
} |
|
if (o.vgap + o.bgap > 0) { |
|
this.element.css({ |
|
"padding-bottom": o.vgap + o.bgap + "px" |
|
}); |
|
} |
|
if (BI.isNumber(o.height)) { |
|
this.element.css({lineHeight: o.height + "px"}); |
|
} |
|
if (BI.isNumber(o.lineHeight)) { |
|
this.element.css({lineHeight: o.lineHeight + "px"}); |
|
} |
|
if (BI.isWidthOrHeight(o.maxWidth)) { |
|
this.element.css({maxWidth: o.maxWidth}); |
|
} |
|
this.element.css({ |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
textOverflow: o.whiteSpace === 'nowrap' ? "ellipsis" : "", |
|
overflow: o.whiteSpace === "nowrap" ? "" : "auto" |
|
}); |
|
if (o.handler) { |
|
this.text = BI.createWidget({ |
|
type: "bi.layout", |
|
tagName: "span" |
|
}); |
|
this.text.element.click(function () { |
|
o.handler(self.getValue()); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.default", |
|
element: this, |
|
items: [this.text] |
|
}); |
|
} else { |
|
this.text = this; |
|
} |
|
|
|
if (BI.isKey(o.text)) { |
|
this.setText(o.text); |
|
} else if (BI.isKey(o.value)) { |
|
this.setText(o.value); |
|
} |
|
if (o.highLight) { |
|
this.doHighLight(); |
|
} |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.element.addClass("bi-high-light"); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.element.removeClass("bi-high-light"); |
|
}, |
|
|
|
setValue: function (text) { |
|
BI.Html.superclass.setValue.apply(this, arguments); |
|
if (!this.isReadOnly()) { |
|
this.setText(text); |
|
} |
|
}, |
|
|
|
setStyle: function (css) { |
|
this.text.element.css(css); |
|
}, |
|
|
|
setText: function (text) { |
|
BI.Html.superclass.setText.apply(this, arguments); |
|
this.options.text = text; |
|
this.text.element.html(text); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.html", BI.Html);/** |
|
* guy 图标 |
|
* @class BI.Icon |
|
* @extends BI.Single |
|
*/ |
|
BI.Icon = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Icon.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
tagName: "i", |
|
baseCls: (conf.baseCls || "") + " x-icon b-font horizon-center display-block" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.Icon.superclass._init.apply(this, arguments); |
|
if (BI.isIE9Below && BI.isIE9Below()) { |
|
this.element.addClass("hack"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.icon", BI.Icon);/** |
|
* @class BI.Iframe |
|
* @extends BI.Single |
|
* @abstract |
|
* Created by GameJian on 2016/3/2. |
|
*/ |
|
BI.Iframe = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Iframe.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
tagName: "iframe", |
|
baseCls: (conf.baseCls || "") + " bi-iframe", |
|
src: "", |
|
name: "", |
|
attributes: {}, |
|
width: "100%", |
|
height: "100%" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
var o = this.options; |
|
o.attributes.frameborder = "0"; |
|
o.attributes.src = o.src; |
|
o.attributes.name = o.name; |
|
BI.Iframe.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
setSrc: function (src) { |
|
this.options.src = src; |
|
this.element.attr("src", src); |
|
}, |
|
|
|
getSrc: function () { |
|
return this.options.src; |
|
}, |
|
|
|
setName: function (name) { |
|
this.options.name = name; |
|
this.element.attr("name", name); |
|
}, |
|
|
|
getName: function () { |
|
return this.options.name; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.iframe", BI.Iframe);/** |
|
* ͼƬ |
|
* |
|
* Created by GUY on 2016/1/26. |
|
* @class BI.Img |
|
* @extends BI.Single |
|
* @abstract |
|
*/ |
|
BI.Img = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Img.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
tagName: "img", |
|
baseCls: (conf.baseCls || "") + " bi-img display-block", |
|
src: "", |
|
attributes: {}, |
|
width: "100%", |
|
height: "100%" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
var o = this.options; |
|
o.attributes.src = o.src; |
|
BI.Img.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
setSrc: function (src) { |
|
this.options.src = src; |
|
this.element.attr("src", src); |
|
}, |
|
|
|
getSrc: function () { |
|
return this.options.src; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.img", BI.Img); |
|
/** |
|
* guy |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.ImageCheckbox = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.ImageCheckbox.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-image-checkbox check-box-icon", |
|
selected: false, |
|
handler: BI.emptyFn, |
|
width: 16, |
|
height: 16, |
|
iconWidth: 16, |
|
iconHeight: 16 |
|
}); |
|
} |
|
}); |
|
BI.ImageCheckbox.EVENT_CHANGE = BI.IconButton.EVENT_CHANGE; |
|
|
|
BI.shortcut("bi.image_checkbox", BI.ImageCheckbox);/** |
|
* guy |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.Checkbox = BI.inherit(BI.BasicButton, { |
|
|
|
props: { |
|
baseCls: "bi-checkbox", |
|
selected: false, |
|
handler: BI.emptyFn, |
|
width: 16, |
|
height: 16, |
|
iconWidth: 16, |
|
iconHeight: 16 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.center_adapt", |
|
items: [{ |
|
type: "bi.default", |
|
ref: function (_ref) { |
|
self.checkbox = _ref; |
|
}, |
|
cls: "checkbox-content", |
|
width: o.iconWidth - 2, |
|
height: o.iconHeight - 2 |
|
}] |
|
}; |
|
}, |
|
|
|
_setEnable: function (enable) { |
|
BI.Checkbox.superclass._setEnable.apply(this, arguments); |
|
if (enable === true) { |
|
this.checkbox.element.removeClass("base-disabled disabled"); |
|
} else { |
|
this.checkbox.element.addClass("base-disabled disabled"); |
|
} |
|
}, |
|
|
|
doClick: function () { |
|
BI.Checkbox.superclass.doClick.apply(this, arguments); |
|
if(this.isValid()) { |
|
this.fireEvent(BI.Checkbox.EVENT_CHANGE); |
|
} |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.Checkbox.superclass.setSelected.apply(this, arguments); |
|
if (b) { |
|
this.checkbox.element.addClass("bi-high-light-background"); |
|
} else { |
|
this.checkbox.element.removeClass("bi-high-light-background"); |
|
} |
|
} |
|
}); |
|
BI.Checkbox.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.checkbox", BI.Checkbox);/** |
|
* guy |
|
* @class BI.Input 一个button和一行数 组成的一行listitem |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.Input = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Input.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-input display-block overflow-dot", |
|
tagName: "input", |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, // 按确定键能否退出编辑 |
|
allowBlank: false |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Input.superclass._init.apply(this, arguments); |
|
var self = this; |
|
var ctrlKey = false; |
|
var keyCode = null; |
|
var inputEventValid = false; |
|
var _keydown = BI.debounce(function (keyCode) { |
|
self.onKeyDown(keyCode, ctrlKey); |
|
self._keydown_ = false; |
|
}, 300); |
|
var _clk = BI.debounce(BI.bind(this._click, this), BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
this._focusDebounce = BI.debounce(BI.bind(this._focus, this), BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
this._blurDebounce = BI.debounce(BI.bind(this._blur, this), BI.EVENT_RESPONSE_TIME, { |
|
"leading": true, |
|
"trailing": false |
|
}); |
|
this.element |
|
.keydown(function (e) { |
|
inputEventValid = false; |
|
ctrlKey = e.ctrlKey || e.metaKey; // mac的cmd支持一下 |
|
keyCode = e.keyCode; |
|
self.fireEvent(BI.Input.EVENT_QUICK_DOWN, arguments); |
|
}) |
|
.keyup(function (e) { |
|
keyCode = null; |
|
if (!(inputEventValid && e.keyCode === BI.KeyCode.ENTER)) { |
|
self._keydown_ = true; |
|
_keydown(e.keyCode); |
|
} |
|
}) |
|
.on("input propertychange", function (e) { |
|
// 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了 |
|
// 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8 |
|
// 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓) |
|
var originalEvent = e.originalEvent; |
|
if (BI.isNull(originalEvent.propertyName) || originalEvent.propertyName === "value") { |
|
inputEventValid = true; |
|
self._keydown_ = true; |
|
_keydown(keyCode); |
|
keyCode = null; |
|
} |
|
}) |
|
.click(function (e) { |
|
e.stopPropagation(); |
|
_clk(); |
|
}) |
|
.mousedown(function (e) { |
|
self.element.val(self.element.val()); |
|
}) |
|
.focus(function (e) { // 可以不用冒泡 |
|
self._focusDebounce(); |
|
}) |
|
.focusout(function (e) { |
|
self._blurDebounce(); |
|
}); |
|
if (BI.isKey(this.options.value) || BI.isEmptyString(this.options.value)) { |
|
this.setValue(this.options.value); |
|
} |
|
}, |
|
|
|
_focus: function () { |
|
this.element.addClass("bi-input-focus"); |
|
this._checkValidationOnValueChange(); |
|
this._isEditing = true; |
|
if (this.getValue() == "") { |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this); |
|
this.fireEvent(BI.Input.EVENT_EMPTY); |
|
} |
|
this.fireEvent(BI.Input.EVENT_FOCUS); |
|
}, |
|
|
|
_blur: function () { |
|
var self = this; |
|
if (self._keydown_ === true) { |
|
BI.delay(blur, 300); |
|
} else { |
|
blur(); |
|
} |
|
|
|
function blur () { |
|
if (!self.isValid() && self.options.quitChecker.apply(self, [BI.trim(self.getValue())]) !== false) { |
|
self.element.val(self._lastValidValue ? self._lastValidValue : ""); |
|
self._checkValidationOnValueChange(); |
|
self._defaultState(); |
|
} |
|
self.element.removeClass("bi-input-focus"); |
|
self._isEditing = false; |
|
self._start = false; |
|
if (self.isValid()) { |
|
var lastValidValue = self._lastValidValue; |
|
self._lastValidValue = self.getValue(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CONFIRM, self.getValue(), self); |
|
self.fireEvent(BI.Input.EVENT_CONFIRM); |
|
if (self._lastValidValue !== lastValidValue) { |
|
self.fireEvent(BI.Input.EVENT_CHANGE_CONFIRM); |
|
} |
|
} |
|
self.fireEvent(BI.Input.EVENT_BLUR); |
|
} |
|
}, |
|
|
|
_click: function () { |
|
if (this._isEditing !== true) { |
|
this.selectAll(); |
|
this.fireEvent(BI.Input.EVENT_CLICK); |
|
} |
|
}, |
|
|
|
onClick: function () { |
|
this._click(); |
|
}, |
|
|
|
onKeyDown: function (keyCode, ctrlKey) { |
|
if (!this.isValid() || BI.trim(this._lastChangedValue) !== BI.trim(this.getValue())) { |
|
this._checkValidationOnValueChange(); |
|
} |
|
if (this.isValid() && BI.trim(this.getValue()) !== "") { |
|
if (BI.trim(this.getValue()) !== this._lastValue && (!this._start || this._lastValue == null || this._lastValue === "") |
|
|| (this._pause === true && !/(\s|\u00A0)$/.test(this.getValue()))) { |
|
this._start = true; |
|
this._pause = false; |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STARTEDIT, this.getValue(), this); |
|
this.fireEvent(BI.Input.EVENT_START); |
|
} |
|
} |
|
if (keyCode == BI.KeyCode.ENTER) { |
|
if (this.isValid() || this.options.quitChecker.apply(this, [BI.trim(this.getValue())]) !== false) { |
|
this.blur(); |
|
this.fireEvent(BI.Input.EVENT_ENTER); |
|
} else { |
|
this.fireEvent(BI.Input.EVENT_RESTRICT); |
|
} |
|
} |
|
if (keyCode == BI.KeyCode.SPACE) { |
|
this.fireEvent(BI.Input.EVENT_SPACE); |
|
} |
|
if (keyCode == BI.KeyCode.BACKSPACE && this._lastValue == "") { |
|
this.fireEvent(BI.Input.EVENT_REMOVE); |
|
} |
|
if (keyCode == BI.KeyCode.BACKSPACE || keyCode == BI.KeyCode.DELETE) { |
|
this.fireEvent(BI.Input.EVENT_BACKSPACE); |
|
} |
|
this.fireEvent(BI.Input.EVENT_KEY_DOWN, arguments); |
|
|
|
// _valueChange中会更新_lastValue, 这边缓存用以后续STOP事件服务 |
|
var lastValue = this._lastValue; |
|
if(BI.trim(this.getValue()) !== BI.trim(this._lastValue || "")){ |
|
this._valueChange(); |
|
} |
|
if (BI.isEndWithBlank(this.getValue())) { |
|
this._pause = true; |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.PAUSE, "", this); |
|
this.fireEvent(BI.Input.EVENT_PAUSE); |
|
this._defaultState(); |
|
} else if ((keyCode === BI.KeyCode.BACKSPACE || keyCode === BI.KeyCode.DELETE) && |
|
BI.trim(this.getValue()) === "" && (lastValue !== null && BI.trim(lastValue) !== "")) { |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STOPEDIT, this.getValue(), this); |
|
this.fireEvent(BI.Input.EVENT_STOP); |
|
} |
|
}, |
|
|
|
// 初始状态 |
|
_defaultState: function () { |
|
if (this.getValue() == "") { |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this); |
|
this.fireEvent(BI.Input.EVENT_EMPTY); |
|
} |
|
this._lastValue = this.getValue(); |
|
this._lastSubmitValue = null; |
|
}, |
|
|
|
_valueChange: function () { |
|
if (this.isValid() && BI.trim(this.getValue()) !== this._lastSubmitValue) { |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CHANGE, this.getValue(), this); |
|
this.fireEvent(BI.Input.EVENT_CHANGE); |
|
this._lastSubmitValue = BI.trim(this.getValue()); |
|
} |
|
if (this.getValue() == "") { |
|
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this); |
|
this.fireEvent(BI.Input.EVENT_EMPTY); |
|
} |
|
this._lastValue = this.getValue(); |
|
}, |
|
|
|
_checkValidationOnValueChange: function () { |
|
var o = this.options; |
|
var v = this.getValue(); |
|
this.setValid( |
|
(o.allowBlank === true && BI.trim(v) == "") || ( |
|
BI.isNotEmptyString(BI.trim(v)) && o.validationChecker.apply(this, [BI.trim(v)]) !== false |
|
) |
|
); |
|
}, |
|
|
|
focus: function () { |
|
if (!this.element.is(":visible")) { |
|
throw new Error("input输入框在不可见下不能focus"); |
|
} |
|
if (!this._isEditing === true) { |
|
this.element.focus(); |
|
this.selectAll(); |
|
} |
|
}, |
|
|
|
blur: function () { |
|
if (!this.element.is(":visible")) { |
|
throw new Error("input输入框在不可见下不能blur"); |
|
} |
|
if (this._isEditing === true) { |
|
this.element.blur(); |
|
this._blurDebounce(); |
|
} |
|
}, |
|
|
|
selectAll: function () { |
|
if (!this.element.is(":visible")) { |
|
throw new Error("input输入框在不可见下不能select"); |
|
} |
|
this.element.select(); |
|
this._isEditing = true; |
|
}, |
|
|
|
setValue: function (textValue) { |
|
this.element.val(textValue); |
|
BI.nextTick(BI.bind(function () { |
|
this._checkValidationOnValueChange(); |
|
this._defaultState(); |
|
if (this.isValid()) { |
|
this._lastValidValue = this._lastSubmitValue = this.getValue(); |
|
} |
|
}, this)); |
|
}, |
|
|
|
getValue: function () { |
|
return this.element.val() || ""; |
|
}, |
|
|
|
isEditing: function () { |
|
return this._isEditing; |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this._lastValidValue; |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this._lastChangedValue; |
|
}, |
|
|
|
_setValid: function () { |
|
BI.Input.superclass._setValid.apply(this, arguments); |
|
if (this.isValid()) { |
|
this._lastChangedValue = this.getValue(); |
|
this.element.removeClass("bi-input-error"); |
|
this.fireEvent(BI.Input.EVENT_VALID, BI.trim(this.getValue()), this); |
|
} else { |
|
if (this._lastChangedValue === this.getValue()) { |
|
this._lastChangedValue = null; |
|
} |
|
this.element.addClass("bi-input-error"); |
|
this.fireEvent(BI.Input.EVENT_ERROR, BI.trim(this.getValue()), this); |
|
} |
|
}, |
|
|
|
_setEnable: function (b) { |
|
BI.Input.superclass._setEnable.apply(this, [b]); |
|
this.element[0].disabled = !b; |
|
} |
|
}); |
|
BI.Input.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.Input.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.Input.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.Input.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.Input.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.Input.EVENT_QUICK_DOWN = "EVENT_QUICK_DOWN"; |
|
BI.Input.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.Input.EVENT_BACKSPACE = "EVENT_BACKSPACE"; |
|
|
|
BI.Input.EVENT_START = "EVENT_START"; |
|
BI.Input.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.Input.EVENT_STOP = "EVENT_STOP"; |
|
BI.Input.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.Input.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.Input.EVENT_REMOVE = "EVENT_REMOVE"; |
|
BI.Input.EVENT_EMPTY = "EVENT_EMPTY"; |
|
BI.Input.EVENT_VALID = "EVENT_VALID"; |
|
BI.Input.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.Input.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.Input.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.shortcut("bi.input", BI.Input); |
|
/** |
|
* guy |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.ImageRadio = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.ImageRadio.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-radio radio-icon", |
|
selected: false, |
|
handler: BI.emptyFn, |
|
width: 16, |
|
height: 16, |
|
iconWidth: 16, |
|
iconHeight: 16 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ImageRadio.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.ImageRadio.superclass.doClick.apply(this, arguments); |
|
if(this.isValid()) { |
|
this.fireEvent(BI.ImageRadio.EVENT_CHANGE); |
|
} |
|
} |
|
}); |
|
BI.ImageRadio.EVENT_CHANGE = BI.IconButton.EVENT_CHANGE; |
|
|
|
BI.shortcut("bi.image_radio", BI.ImageRadio);/** |
|
* guy |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.Radio = BI.inherit(BI.BasicButton, { |
|
|
|
props: { |
|
baseCls: "bi-radio", |
|
selected: false, |
|
handler: BI.emptyFn, |
|
width: 16, |
|
height: 16, |
|
iconWidth: 14, |
|
iconHeight: 14 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.center_adapt", |
|
element: this.element, |
|
items: [{ |
|
type: "bi.layout", |
|
cls: "radio-content", |
|
ref: function (_ref) { |
|
self.radio = _ref; |
|
}, |
|
width: o.iconWidth, |
|
height: o.iconHeight |
|
}] |
|
}; |
|
}, |
|
|
|
_setEnable: function (enable) { |
|
BI.Radio.superclass._setEnable.apply(this, arguments); |
|
if (enable === true) { |
|
this.radio.element.removeClass("base-disabled disabled"); |
|
} else { |
|
this.radio.element.addClass("base-disabled disabled"); |
|
} |
|
}, |
|
|
|
doClick: function () { |
|
BI.Radio.superclass.doClick.apply(this, arguments); |
|
if(this.isValid()) { |
|
this.fireEvent(BI.Radio.EVENT_CHANGE); |
|
} |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.Radio.superclass.setSelected.apply(this, arguments); |
|
if (b) { |
|
this.radio.element.addClass("bi-high-light-background"); |
|
} else { |
|
this.radio.element.removeClass("bi-high-light-background"); |
|
} |
|
} |
|
}); |
|
BI.Radio.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.radio", BI.Radio);/** |
|
* Created by dailer on 2019/6/19. |
|
*/ |
|
|
|
BI.AbstractLabel = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function (props) { |
|
var conf = BI.AbstractLabel.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
textAlign: "center", |
|
whiteSpace: "nowrap", // normal or nowrap |
|
textWidth: null, |
|
textHeight: null, |
|
hgap: 0, |
|
vgap: 0, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
text: "", |
|
highLight: false |
|
}); |
|
}, |
|
|
|
_createJson: function () { |
|
var o = this.options; |
|
return { |
|
type: "bi.text", |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
lineHeight: o.textHeight, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword, |
|
highLight: o.highLight |
|
}; |
|
}, |
|
|
|
_init: function () { |
|
BI.AbstractLabel.superclass._init.apply(this, arguments); |
|
|
|
if (this.options.textAlign === "center") { |
|
this._createCenterEl(); |
|
} else { |
|
this._createNotCenterEl(); |
|
} |
|
}, |
|
|
|
_createCenterEl: function () { |
|
var o = this.options; |
|
var json = this._createJson(); |
|
json.textAlign = "left"; |
|
if (BI.isNumber(o.width) && o.width > 0) { |
|
if (BI.isNumber(o.textWidth) && o.textWidth > 0) { |
|
json.maxWidth = o.textWidth; |
|
if (BI.isNumber(o.height) && o.height > 0) { // 1.1 |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
height: o.height, |
|
scrollable: o.whiteSpace === "normal", |
|
element: this, |
|
items: [ |
|
{ |
|
el: (this.text = BI.createWidget(json)) |
|
} |
|
] |
|
}); |
|
return; |
|
} |
|
BI.createWidget({ // 1.2 |
|
type: "bi.center_adapt", |
|
scrollable: o.whiteSpace === "normal", |
|
element: this, |
|
items: [ |
|
{ |
|
el: (this.text = BI.createWidget(json)) |
|
} |
|
] |
|
}); |
|
return; |
|
} |
|
if (o.whiteSpace == "normal") { // 1.3 |
|
BI.extend(json, { |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}); |
|
this.text = BI.createWidget(json); |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
scrollable: o.whiteSpace === "normal", |
|
element: this, |
|
items: [this.text] |
|
}); |
|
return; |
|
} |
|
if (BI.isNumber(o.height) && o.height > 0) { // 1.4 |
|
this.element.css({ |
|
"line-height": o.height + "px" |
|
}); |
|
json.textAlign = o.textAlign; |
|
this.text = BI.createWidget(BI.extend(json, { |
|
element: this, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
})); |
|
return; |
|
} |
|
BI.extend(json, { // 1.5 |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
maxWidth: "100%" |
|
}); |
|
this.text = BI.createWidget(json); |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
scrollable: o.whiteSpace === "normal", |
|
element: this, |
|
items: [this.text] |
|
}); |
|
return; |
|
} |
|
if (BI.isNumber(o.textWidth) && o.textWidth > 0) { // 1.6 |
|
json.maxWidth = o.textWidth; |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
scrollable: o.whiteSpace === "normal", |
|
element: this, |
|
items: [ |
|
{ |
|
el: (this.text = BI.createWidget(json)) |
|
} |
|
] |
|
}); |
|
return; |
|
} |
|
if (o.whiteSpace == "normal") { // 1.7 |
|
BI.extend(json, { |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}); |
|
this.text = BI.createWidget(json); |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
scrollable: true, |
|
element: this, |
|
items: [this.text] |
|
}); |
|
return; |
|
} |
|
if (BI.isNumber(o.height) && o.height > 0) { // 1.8 |
|
this.element.css({ |
|
"line-height": o.height + "px" |
|
}); |
|
json.textAlign = o.textAlign; |
|
this.text = BI.createWidget(BI.extend(json, { |
|
element: this, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
})); |
|
return; |
|
} |
|
BI.extend(json, { |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}); |
|
|
|
this.text = BI.createWidget(BI.extend(json, { |
|
maxWidth: "100%" |
|
})); |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
element: this, |
|
items: [this.text] |
|
}); |
|
}, |
|
|
|
_createNotCenterEl: function () { |
|
var o = this.options; |
|
var adaptLayout = o.textAlign === "right" ? "bi.right_vertical_adapt" : "bi.vertical_adapt"; |
|
var json = this._createJson(); |
|
if (BI.isNumber(o.width) && o.width > 0) { |
|
if (BI.isNumber(o.textWidth) && o.textWidth > 0) { |
|
json.width = o.textWidth; |
|
if (BI.isNumber(o.height) && o.height > 0) { // 2.1 |
|
BI.createWidget({ |
|
type: adaptLayout, |
|
height: o.height, |
|
scrollable: o.whiteSpace === "normal", |
|
element: this, |
|
items: [ |
|
{ |
|
el: (this.text = BI.createWidget(json)) |
|
} |
|
] |
|
}); |
|
return; |
|
} |
|
BI.createWidget({ // 2.2 |
|
type: adaptLayout, |
|
scrollable: o.whiteSpace === "normal", |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
element: this, |
|
items: [ |
|
{ |
|
el: (this.text = BI.createWidget(json)) |
|
} |
|
] |
|
}); |
|
return; |
|
} |
|
if (BI.isNumber(o.height) && o.height > 0) { // 2.3 |
|
this.text = BI.createWidget(BI.extend(json, { |
|
element: this, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
})); |
|
if (o.whiteSpace !== "normal") { |
|
this.element.css({ |
|
"line-height": o.height - (o.vgap * 2) + "px" |
|
}); |
|
} |
|
return; |
|
} |
|
json.width = o.width - 2 * o.hgap - o.lgap - o.rgap; |
|
BI.createWidget({ // 2.4 |
|
type: adaptLayout, |
|
scrollable: o.whiteSpace === "normal", |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
element: this, |
|
items: [{ |
|
el: (this.text = BI.createWidget(json)) |
|
}] |
|
}); |
|
return; |
|
} |
|
if (BI.isNumber(o.textWidth) && o.textWidth > 0) { |
|
json.width = o.textWidth; |
|
BI.createWidget({ // 2.5 |
|
type: adaptLayout, |
|
scrollable: o.whiteSpace === "normal", |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
element: this, |
|
items: [ |
|
{ |
|
el: (this.text = BI.createWidget(json)) |
|
} |
|
] |
|
}); |
|
return; |
|
} |
|
if (BI.isNumber(o.height) && o.height > 0) { |
|
if (o.whiteSpace !== "normal") { |
|
this.element.css({ |
|
"line-height": o.height - (o.vgap * 2) + "px" |
|
}); |
|
} |
|
this.text = BI.createWidget(BI.extend(json, { // 2.6 |
|
element: this, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
})); |
|
return; |
|
} |
|
BI.extend(json, { |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap |
|
}); |
|
|
|
this.text = BI.createWidget(BI.extend(json, { |
|
maxWidth: "100%" |
|
})); |
|
BI.createWidget({ |
|
type: adaptLayout, |
|
element: this, |
|
items: [this.text] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
setText: function (v) { |
|
this.options.text = v; |
|
this.text.setText(v); |
|
}, |
|
|
|
getText: function () { |
|
return this.options.text; |
|
}, |
|
|
|
setStyle: function (css) { |
|
this.text.setStyle(css); |
|
}, |
|
|
|
setValue: function (v) { |
|
BI.AbstractLabel.superclass.setValue.apply(this, arguments); |
|
if (!this.isReadOnly()) { |
|
this.text.setValue(v); |
|
} |
|
}, |
|
|
|
populate: function () { |
|
BI.AbstractLabel.superclass.populate.apply(this, arguments); |
|
} |
|
});/** |
|
* Created by GUY on 2015/6/26. |
|
*/ |
|
|
|
BI.HtmlLabel = BI.inherit(BI.AbstractLabel, { |
|
|
|
props: { |
|
baseCls: "bi-html-label" |
|
}, |
|
|
|
_createJson: function () { |
|
var o = this.options; |
|
return { |
|
type: "bi.html", |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
lineHeight: o.textHeight, |
|
text: o.text, |
|
value: o.value |
|
}; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.html_label", BI.HtmlLabel);/** |
|
* @class BI.IconButton |
|
* @extends BI.BasicButton |
|
* 图标标签 |
|
*/ |
|
BI.IconLabel = BI.inherit(BI.Single, { |
|
|
|
props: { |
|
baseCls: "bi-icon-label horizon-center", |
|
iconWidth: null, |
|
iconHeight: null |
|
}, |
|
|
|
_init: function () { |
|
BI.IconLabel.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.element.css({ |
|
textAlign: "center" |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.icon", |
|
width: o.iconWidth, |
|
height: o.iconHeight |
|
}); |
|
if (BI.isNumber(o.height) && o.height > 0 && BI.isNull(o.iconWidth) && BI.isNull(o.iconHeight)) { |
|
this.element.css("lineHeight", o.height + "px"); |
|
BI.createWidget({ |
|
type: "bi.default", |
|
element: this, |
|
items: [this.icon] |
|
}); |
|
} else { |
|
this.element.css("lineHeight", "1"); |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.center_adapt", |
|
items: [this.icon] |
|
}); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.icon_label", BI.IconLabel);/** |
|
* Created by GUY on 2015/6/26. |
|
*/ |
|
|
|
BI.Label = BI.inherit(BI.AbstractLabel, { |
|
|
|
props: { |
|
baseCls: "bi-label", |
|
py: "", |
|
keyword: "" |
|
}, |
|
|
|
_createJson: function () { |
|
var o = this.options; |
|
return { |
|
type: "bi.text", |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
lineHeight: o.textHeight, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword, |
|
highLight: o.highLight |
|
}; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.label", BI.Label);/** |
|
* guy a元素 |
|
* @class BI.Link |
|
* @extends BI.Text |
|
*/ |
|
BI.Link = BI.inherit(BI.Label, { |
|
_defaultConfig: function () { |
|
var conf = BI.Link.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-link display-block", |
|
tagName: "a", |
|
href: "", |
|
target: "_blank" |
|
}); |
|
}, |
|
|
|
_createJson: function () { |
|
var o = this.options; |
|
return { |
|
type: "bi.a", |
|
textAlign: o.textAlign, |
|
whiteSpace: o.whiteSpace, |
|
lineHeight: o.textHeight, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
py: o.py, |
|
href: o.href, |
|
target: o.target |
|
}; |
|
}, |
|
|
|
_init: function () { |
|
BI.Link.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.link", BI.Link);/** |
|
* guy |
|
* 气泡提示 |
|
* @class BI.Bubble |
|
* @extends BI.Tip |
|
* @type {*|void|Object} |
|
*/ |
|
BI.Bubble = BI.inherit(BI.Tip, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Bubble.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-bubble", |
|
direction: "top", |
|
text: "", |
|
level: "error", |
|
height: 18 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.Bubble.superclass._init.apply(this, arguments); |
|
var fn = function (e) { |
|
e.stopPropagation(); |
|
e.stopEvent(); |
|
return false; |
|
}; |
|
this.element.bind({click: fn, mousedown: fn, mouseup: fn, mouseover: fn, mouseenter: fn, mouseleave: fn, mousemove: fn}); |
|
BI.createWidget({ |
|
type: "bi.left", |
|
element: this, |
|
items: [this["_" + this.options.direction]()] |
|
}); |
|
}, |
|
|
|
_createBubbleText: function () { |
|
var o = this.options; |
|
return (this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "bubble-text" + (" bubble-" + o.level), |
|
text: o.text, |
|
hgap: 5, |
|
height: 18 |
|
})); |
|
}, |
|
|
|
_top: function () { |
|
return BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
el: this._createBubbleText(), |
|
height: 18 |
|
}, { |
|
el: { |
|
type: "bi.layout" |
|
}, |
|
height: 3 |
|
}] |
|
}); |
|
}, |
|
|
|
_bottom: function () { |
|
return BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
el: { |
|
type: "bi.layout" |
|
}, |
|
height: 3 |
|
}, { |
|
el: this._createBubbleText(), |
|
height: 18 |
|
}] |
|
}); |
|
}, |
|
|
|
_left: function () { |
|
return BI.createWidget({ |
|
type: "bi.right", |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
width: 3, |
|
height: 18 |
|
} |
|
}, { |
|
el: this._createBubbleText() |
|
}] |
|
}); |
|
}, |
|
|
|
_right: function () { |
|
return BI.createWidget({ |
|
type: "bi.left", |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
width: 3, |
|
height: 18 |
|
} |
|
}, { |
|
el: this._createBubbleText() |
|
}] |
|
}); |
|
}, |
|
|
|
setText: function (text) { |
|
this.text.setText(text); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.bubble", BI.Bubble);/** |
|
* toast提示 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.Toast |
|
* @extends BI.Tip |
|
*/ |
|
BI.Toast = BI.inherit(BI.Tip, { |
|
_const: { |
|
minWidth: 200, |
|
hgap: 10 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.Toast.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-toast", |
|
text: "", |
|
level: "success" // success或warning |
|
}); |
|
}, |
|
_init: function () { |
|
BI.Toast.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.element.css({ |
|
minWidth: this._const.minWidth + "px" |
|
}); |
|
this.element.addClass("toast-" + o.level); |
|
var fn = function (e) { |
|
e.stopPropagation(); |
|
e.stopEvent(); |
|
return false; |
|
}; |
|
this.element.bind({click: fn, mousedown: fn, mouseup: fn, mouseover: fn, mouseenter: fn, mouseleave: fn, mousemove: fn}); |
|
var cls = "close-font"; |
|
switch(o.level) { |
|
case "success": |
|
cls = "toast-success-font"; |
|
break; |
|
case "error": |
|
cls = "toast-error-font"; |
|
break; |
|
case "warning": |
|
cls = "toast-warning-font"; |
|
break; |
|
case "normal": |
|
default: |
|
cls = "toast-message-font"; |
|
break; |
|
} |
|
|
|
var items = [{ |
|
type: "bi.icon_label", |
|
cls: cls + " toast-icon", |
|
width: 36 |
|
}, { |
|
el: { |
|
type: "bi.label", |
|
whiteSpace: "normal", |
|
text: o.text, |
|
textHeight: 16, |
|
textAlign: "left" |
|
}, |
|
rgap: o.autoClose ? this._const.hgap : 0 |
|
}]; |
|
|
|
var columnSize = [36, ""]; |
|
|
|
if(o.autoClose === false) { |
|
items.push({ |
|
type: "bi.icon_button", |
|
cls: "close-font toast-icon", |
|
handler: function () { |
|
self.destroy(); |
|
}, |
|
width: 36 |
|
}); |
|
columnSize.push(36); |
|
} |
|
|
|
this.text = BI.createWidget({ |
|
type: "bi.horizontal_adapt", |
|
element: this, |
|
items: items, |
|
vgap: 7, |
|
columnSize: columnSize |
|
}); |
|
}, |
|
|
|
setText: function (text) { |
|
this.text.setText(text); |
|
}, |
|
|
|
beforeDestroy: function () { |
|
this.fireEvent(BI.Toast.EVENT_DESTORY); |
|
} |
|
}); |
|
BI.Toast.EVENT_DESTORY = "EVENT_DESTORY"; |
|
BI.shortcut("bi.toast", BI.Toast);/** |
|
* title提示 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.Tooltip |
|
* @extends BI.Tip |
|
*/ |
|
BI.Tooltip = BI.inherit(BI.Tip, { |
|
_const: { |
|
hgap: 5, |
|
vgap: 3 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.Tooltip.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-tooltip", |
|
text: "", |
|
level: "success", // success或warning |
|
stopEvent: false, |
|
stopPropagation: false |
|
}); |
|
}, |
|
_init: function () { |
|
BI.Tooltip.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.element.addClass("tooltip-" + o.level); |
|
var fn = function (e) { |
|
o.stopPropagation && e.stopPropagation(); |
|
o.stopEvent && e.stopEvent(); |
|
}; |
|
this.element.bind({ |
|
click: fn, |
|
mousedown: fn, |
|
mouseup: fn, |
|
mouseover: fn, |
|
mouseenter: fn, |
|
mouseleave: fn, |
|
mousemove: fn |
|
}); |
|
|
|
var texts = (o.text + "").split("\n"); |
|
if (texts.length > 1) { |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
hgap: this._const.hgap, |
|
items: BI.map(texts, function (i, text) { |
|
return { |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "normal", |
|
text: text, |
|
textHeight: 18 |
|
}; |
|
}) |
|
}); |
|
} else { |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
element: this, |
|
textAlign: "left", |
|
whiteSpace: "normal", |
|
text: o.text, |
|
textHeight: 18, |
|
hgap: this._const.hgap |
|
}); |
|
} |
|
}, |
|
|
|
setWidth: function (width) { |
|
this.element.width(width - 2 * this._const.hgap); |
|
}, |
|
|
|
setText: function (text) { |
|
this.text && this.text.setText(text); |
|
}, |
|
|
|
setLevel: function (level) { |
|
this.element.removeClass("tooltip-success").removeClass("tooltip-warning"); |
|
this.element.addClass("tooltip-" + level); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.tooltip", BI.Tooltip);/** |
|
* 下拉 |
|
* @class BI.Trigger |
|
* @extends BI.Single |
|
* @abstract |
|
*/ |
|
BI.Trigger = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.Trigger.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-trigger cursor-pointer", |
|
height: 24 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Trigger.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
setKey: function () { |
|
|
|
}, |
|
|
|
getKey: function () { |
|
|
|
} |
|
});/** |
|
* |
|
* 自定义树 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.CustomTree |
|
* @extends BI.Single |
|
*/ |
|
BI.CustomTree = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.CustomTree.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-custom-tree", |
|
expander: { |
|
el: {}, |
|
popup: { |
|
type: "bi.custom_tree" |
|
} |
|
}, |
|
|
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
|
|
el: { |
|
type: "bi.button_tree", |
|
chooseType: 0, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.CustomTree.superclass._init.apply(this, arguments); |
|
this.initTree(this.options.items); |
|
}, |
|
|
|
_formatItems: function (nodes) { |
|
var self = this, o = this.options; |
|
nodes = BI.Tree.transformToTreeFormat(nodes); |
|
|
|
var items = []; |
|
BI.each(nodes, function (i, node) { |
|
if (BI.isNotEmptyArray(node.children) || node.isParent === true) { |
|
var item = BI.extend({ |
|
type: "bi.expander", |
|
el: { |
|
value: node.value |
|
}, |
|
popup: {type: "bi.custom_tree"} |
|
}, BI.deepClone(o.expander), { |
|
id: node.id, |
|
pId: node.pId |
|
}); |
|
var el = BI.stripEL(node); |
|
if (!BI.isWidget(el)) { |
|
el = BI.clone(el); |
|
delete el.children; |
|
BI.extend(item.el, el); |
|
} else { |
|
item.el = el; |
|
} |
|
item.popup.expander = BI.deepClone(o.expander); |
|
item.items = item.popup.items = node.children; |
|
item.itemsCreator = item.popup.itemsCreator = function (op) { |
|
if (BI.isNotNull(op.node)) {// 从子节点传过来的itemsCreator直接向上传递 |
|
return o.itemsCreator.apply(self, arguments); |
|
} |
|
var args = Array.prototype.slice.call(arguments, 0); |
|
args[0].node = node; |
|
return o.itemsCreator.apply(self, args); |
|
}; |
|
BI.isNull(item.popup.el) && (item.popup.el = BI.deepClone(o.el)); |
|
items.push(item); |
|
} else { |
|
items.push(node); |
|
} |
|
}); |
|
return items; |
|
}, |
|
|
|
// 构造树结构, |
|
initTree: function (nodes) { |
|
var self = this, o = this.options; |
|
this.tree = BI.createWidget(o.el, { |
|
element: this, |
|
items: this._formatItems(nodes), |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator.apply(this, [op, function (items) { |
|
var args = Array.prototype.slice.call(arguments, 0); |
|
args[0] = self._formatItems(items); |
|
callback.apply(null, args); |
|
}]); |
|
}, |
|
value: o.value |
|
}); |
|
this.tree.on(BI.Controller.EVENT_CHANGE, function (type, val, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.CustomTree.EVENT_CHANGE, val, obj); |
|
} |
|
}); |
|
}, |
|
|
|
// 生成树方法 |
|
stroke: function (nodes) { |
|
this.populate.apply(this, arguments); |
|
}, |
|
|
|
populate: function (nodes) { |
|
var args = Array.prototype.slice.call(arguments, 0); |
|
if (arguments.length > 0) { |
|
args[0] = this._formatItems(nodes); |
|
} |
|
this.tree.populate.apply(this.tree, args); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.tree && this.tree.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree ? this.tree.getValue() : []; |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.tree ? this.tree.getAllButtons() : []; |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.tree ? this.tree.getAllLeaves() : []; |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.tree && this.tree.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (id) { |
|
return this.tree && this.tree.getNodeByValue(id); |
|
}, |
|
|
|
empty: function () { |
|
this.tree.empty(); |
|
} |
|
}); |
|
BI.CustomTree.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.custom_tree", BI.CustomTree);/** |
|
* 可以改变图标的button |
|
* |
|
* Created by GUY on 2016/2/2. |
|
* |
|
* @class BI.IconChangeButton |
|
* @extends BI.Single |
|
*/ |
|
BI.IconChangeButton = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
var conf = BI.IconChangeButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-icon-change-button", |
|
iconCls: "", |
|
iconWidth: null, |
|
iconHeight: null, |
|
|
|
stopEvent: false, |
|
stopPropagation: false, |
|
selected: false, |
|
once: false, // 点击一次选中有效,再点无效 |
|
forceSelected: false, // 点击即选中, 选中了就不会被取消 |
|
forceNotSelected: false, // 无论怎么点击都不会被选中 |
|
disableSelected: false, // 使能选中 |
|
|
|
shadow: false, |
|
isShadowShowingOnSelected: false, // 选中状态下是否显示阴影 |
|
trigger: null, |
|
handler: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconChangeButton.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.button = BI.createWidget({ |
|
type: "bi.icon_button", |
|
element: this, |
|
cls: o.iconCls, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight, |
|
|
|
stopEvent: o.stopEvent, |
|
stopPropagation: o.stopPropagation, |
|
selected: o.selected, |
|
once: o.once, |
|
forceSelected: o.forceSelected, |
|
forceNotSelected: o.forceNotSelected, |
|
disableSelected: o.disableSelected, |
|
|
|
shadow: o.shadow, |
|
isShadowShowingOnSelected: o.isShadowShowingOnSelected, |
|
trigger: o.trigger, |
|
handler: o.handler |
|
}); |
|
|
|
this.button.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.IconChangeButton.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.button.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
this.button.setSelected(b); |
|
}, |
|
|
|
setIcon: function (cls) { |
|
var o = this.options; |
|
if (o.iconCls !== cls) { |
|
this.element.removeClass(o.iconCls).addClass(cls); |
|
o.iconCls = cls; |
|
} |
|
} |
|
}); |
|
BI.IconChangeButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_change_button", BI.IconChangeButton);/** |
|
* 统一的trigger图标按钮 |
|
* |
|
* Created by GUY on 2015/9/16. |
|
* @class BI.TriggerIconButton |
|
* @extends BI.IconButton |
|
*/ |
|
BI.TriggerIconButton = BI.inherit(BI.IconButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.TriggerIconButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-trigger-icon-button", |
|
extraCls: "pull-down-font" |
|
}); |
|
} |
|
}); |
|
BI.TriggerIconButton.EVENT_CHANGE = BI.IconButton.EVENT_CHANGE; |
|
BI.shortcut("bi.trigger_icon_button", BI.TriggerIconButton);/** |
|
* guy |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.HalfIconButton = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.HalfIconButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-half-icon-button check-half-select-icon", |
|
height: 16, |
|
width: 16, |
|
iconWidth: 16, |
|
iconHeight: 16, |
|
selected: false |
|
}); |
|
} |
|
}); |
|
BI.HalfIconButton.EVENT_CHANGE = BI.IconButton.EVENT_CHANGE; |
|
|
|
BI.shortcut("bi.half_icon_button", BI.HalfIconButton);/** |
|
* guy |
|
* @extends BI.Single |
|
* @type {*|void|Object} |
|
*/ |
|
BI.HalfButton = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.HalfIconButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-half-button bi-high-light-border", |
|
height: 14, |
|
width: 14, |
|
selected: false |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.HalfButton.superclass._init.apply(this, arguments); |
|
BI.createWidget({ |
|
type: "bi.center_adapt", |
|
element: this.element, |
|
items: [{ |
|
type: "bi.layout", |
|
cls: "bi-high-light-background", |
|
width: 8, |
|
height: 8 |
|
}] |
|
}); |
|
}, |
|
|
|
doClick: function () { |
|
BI.HalfButton.superclass.doClick.apply(this, arguments); |
|
if(this.isValid()) { |
|
this.fireEvent(BI.HalfButton.EVENT_CHANGE); |
|
} |
|
} |
|
}); |
|
BI.HalfButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.half_button", BI.HalfButton);/** |
|
* guy |
|
* 复选框item |
|
* @type {*|void|Object} |
|
*/ |
|
BI.MultiSelectItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-multi-select-item", |
|
height: 24, |
|
logic: { |
|
dynamic: false |
|
}, |
|
iconWrapperWidth: 26 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiSelectItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.checkbox" |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
rgap: o.rgap, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.setSelected(self.isSelected()); |
|
} |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", { |
|
type: "bi.center_adapt", |
|
items: [this.checkbox], |
|
width: o.iconWrapperWidth |
|
}, this.text) |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiSelectItem.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.MultiSelectItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MultiSelectItem.superclass.setSelected.apply(this, arguments); |
|
this.checkbox.setSelected(v); |
|
} |
|
}); |
|
BI.MultiSelectItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_item", BI.MultiSelectItem);/** |
|
* Created by GUY on 2016/2/2. |
|
* |
|
* @class BI.SingleSelectIconTextItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.SingleSelectIconTextItem = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectIconTextItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-single-select-icon-text-item bi-list-item-active", |
|
iconCls: "", |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSelectIconTextItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.icon_text_item", |
|
element: this, |
|
cls: o.iconCls, |
|
once: o.once, |
|
iconWrapperWidth: o.iconWrapperWidth, |
|
selected: o.selected, |
|
height: o.height, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.text.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.text.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
this.text.setSelected(b); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.SingleSelectIconTextItem.superclass.doClick.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.single_select_icon_text_item", BI.SingleSelectIconTextItem);BI.SingleSelectItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-single-select-item bi-list-item-active", |
|
hgap: 10, |
|
height: 24, |
|
textAlign: "left" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSelectItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
element: this, |
|
textAlign: o.textAlign, |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
title: o.title || o.text, |
|
warningTitle: o.warningTitle, |
|
py: o.py |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.SingleSelectItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.SingleSelectItem.EVENT_CHANGE, this.isSelected(), this); |
|
} |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.SingleSelectItem.superclass.setSelected.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.SingleSelectItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_item", BI.SingleSelectItem);/** |
|
* guy |
|
* 单选框item |
|
* @type {*|void|Object} |
|
*/ |
|
BI.SingleSelectRadioItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectRadioItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-single-select-radio-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
hgap: 10, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSelectRadioItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.radio = BI.createWidget({ |
|
type: "bi.radio", |
|
once: o.once |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", { |
|
type: "bi.center_adapt", |
|
items: [this.radio], |
|
width: 16 |
|
}, this.text) |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.SingleSelectRadioItem.superclass.doClick.apply(this, arguments); |
|
this.radio.setSelected(this.isSelected()); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.SingleSelectRadioItem.EVENT_CHANGE, this.isSelected(), this); |
|
} |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.SingleSelectRadioItem.superclass.setSelected.apply(this, arguments); |
|
this.radio.setSelected(v); |
|
|
|
} |
|
}); |
|
|
|
BI.SingleSelectRadioItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_radio_item", BI.SingleSelectRadioItem);/** |
|
* Created by roy on 15/10/16. |
|
*/ |
|
BI.ArrowNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.ArrowNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-arrow-group-node bi-list-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
var self = this, o = this.options; |
|
BI.ArrowNode.superclass._init.apply(this, arguments); |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.arrow_group_node_checkbox" |
|
}); |
|
|
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
|
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.setSelected(self.isSelected()); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 16, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.ArrowNode.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isOpened()); |
|
}, |
|
|
|
setText: function (text) { |
|
BI.ArrowNode.superclass.setText.apply(this, arguments); |
|
this.text.setText(text); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.ArrowNode.superclass.setOpened.apply(this, arguments); |
|
this.checkbox.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.arrow_group_node", BI.ArrowNode);/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.FirstPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.FirstPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.FirstPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-first-plus-group-node bi-list-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.FirstPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.first_tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.FirstPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.FirstPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.first_plus_group_node", BI.FirstPlusGroupNode);/** |
|
* Created by User on 2016/3/31. |
|
*/ |
|
/** |
|
* > + icon + 文本 |
|
* @class BI.IconArrowNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.IconArrowNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.IconArrowNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-icon-arrow-node bi-list-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24, |
|
iconHeight: 12, |
|
iconWidth: 12, |
|
iconCls: "" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.IconArrowNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.arrow_group_node_checkbox", |
|
width: 24, |
|
stopPropagation: true |
|
}); |
|
|
|
var icon = BI.createWidget({ |
|
type: "bi.icon_label", |
|
width: 24, |
|
cls: o.iconCls, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
|
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 16, |
|
el: this.checkbox |
|
}, { |
|
width: 16, |
|
el: icon |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items, |
|
rgap: 5 |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconArrowNode.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.IconArrowNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.icon_arrow_node", BI.IconArrowNode);/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.LastPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.LastPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.LastPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-last-plus-group-node bi-list-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.LastPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.last_tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if(type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.LastPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.LastPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.last_plus_group_node", BI.LastPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.MidPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MidPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MidPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-mid-plus-group-node bi-list-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MidPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.mid_tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MidPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MidPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.mid_plus_group_node", BI.MidPlusGroupNode);BI.MultiLayerIconArrowNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerIconArrowNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-icon-arrow-node bi-list-item", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24, |
|
iconHeight: 16, |
|
iconWidth: 16, |
|
iconCls: "" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerIconArrowNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = BI.createWidget({ |
|
type: "bi.icon_arrow_node", |
|
iconCls: o.iconCls, |
|
cls: "bi-list-item-none", |
|
id: o.id, |
|
pId: o.pId, |
|
open: o.open, |
|
height: o.height, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.node.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.setSelected(self.isSelected()); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function () { |
|
items.push({ |
|
type: "bi.layout", |
|
width: 15, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 15), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.node.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.MultiLayerIconArrowNode.superclass.setSelected.apply(this, arguments); |
|
this.node.setSelected(b); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerIconArrowNode.superclass.setOpened.apply(this, arguments); |
|
this.node.setOpened(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_icon_arrow_node", BI.MultiLayerIconArrowNode); |
|
/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.PlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.PlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.PlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-plus-group-node bi-list-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.PlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.tree_node_checkbox" |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.setSelected(self.isSelected()); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.PlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.PlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (this.checkbox) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.plus_group_node", BI.PlusGroupNode);/** |
|
* Created by Windy on 2018/2/1. |
|
*/ |
|
BI.Switch = BI.inherit(BI.BasicButton, { |
|
|
|
props: { |
|
extraCls: "bi-switch", |
|
height: 22, |
|
width: 44, |
|
logic: { |
|
dynamic: false |
|
} |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
return { |
|
type: "bi.absolute", |
|
ref: function () { |
|
self.layout = this; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.text_button", |
|
cls: "circle-button bi-card" |
|
}, |
|
width: 18, |
|
height: 18, |
|
top: 2, |
|
left: this.options.selected ? 24 : 2 |
|
}] |
|
}; |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.Switch.superclass.setSelected.apply(this, arguments); |
|
this.layout.attr("items")[0].left = v ? 24 : 2; |
|
this.layout.resize(); |
|
}, |
|
|
|
doClick: function () { |
|
BI.Switch.superclass.doClick.apply(this, arguments); |
|
this.fireEvent(BI.Switch.EVENT_CHANGE); |
|
} |
|
}); |
|
BI.Switch.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.switch", BI.Switch);BI.FirstTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.FirstTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-first-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
layer: 0, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.FirstTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.checkbox" |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.setSelected(self.isSelected()); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, ((o.layer === 0) ? "" : { |
|
width: 12, |
|
el: { |
|
type: "bi.layout", |
|
cls: (o.pNode && o.pNode.isLastNode) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
} |
|
}), { |
|
width: 24, |
|
el: { |
|
type: "bi.layout", |
|
cls: "first-line-conn-background", |
|
width: 24, |
|
height: o.height |
|
} |
|
}, { |
|
el: this.text |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.FirstTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.FirstTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
this.checkbox.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.first_tree_leaf_item", BI.FirstTreeLeafItem);BI.IconTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-icon-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
height: 24, |
|
iconWidth: 16, |
|
iconHeight: 16, |
|
iconCls: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var icon = BI.createWidget({ |
|
type: "bi.center_adapt", |
|
width: 24, |
|
cls: o.iconCls, |
|
items: [{ |
|
type: "bi.icon", |
|
width: o.iconWidth, |
|
height: o.iconHeight |
|
}] |
|
}); |
|
|
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 16, |
|
el: icon |
|
}, { |
|
el: this.text |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items, |
|
hgap: 5 |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.IconTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.IconTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.icon_tree_leaf_item", BI.IconTreeLeafItem);BI.LastTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.LastTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-last-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
layer: 0, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.LastTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.checkbox" |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.setSelected(self.isSelected()); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, ((o.layer === 0) ? "" : { |
|
width: 12, |
|
el: { |
|
type: "bi.layout", |
|
cls: (o.pNode && o.pNode.isLastNode) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
} |
|
}), { |
|
width: 24, |
|
el: { |
|
type: "bi.layout", |
|
cls: "last-line-conn-background", |
|
width: 24, |
|
height: o.height |
|
} |
|
}, { |
|
el: this.text |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.LastTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
// this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.LastTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
// this.checkbox.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.last_tree_leaf_item", BI.LastTreeLeafItem);BI.MidTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MidTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-mid-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
layer: 0, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MidTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.checkbox" |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.setSelected(self.isSelected()); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, ((o.layer === 0) ? "" : { |
|
width: 12, |
|
el: { |
|
type: "bi.layout", |
|
cls: (o.pNode && o.pNode.isLastNode) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
} |
|
}), { |
|
width: 24, |
|
el: { |
|
type: "bi.layout", |
|
cls: "mid-line-conn-background", |
|
width: 24, |
|
height: o.height |
|
} |
|
}, { |
|
el: this.text |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.MidTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
this.checkbox.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MidTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
this.checkbox.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.mid_tree_leaf_item", BI.MidTreeLeafItem);/** |
|
* @class BI.MultiLayerIconTreeLeafItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.MultiLayerIconTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerIconTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-multilayer-icon-tree-leaf-item bi-list-item-active", |
|
layer: 0, |
|
height: 24, |
|
iconCls: "", |
|
iconHeight: 16, |
|
iconWidth: 16 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerIconTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.item = BI.createWidget({ |
|
type: "bi.icon_tree_leaf_item", |
|
cls: "bi-list-item-none", |
|
iconCls: o.iconCls, |
|
id: o.id, |
|
pId: o.pId, |
|
isFront: true, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight |
|
}); |
|
this.item.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function () { |
|
items.push({ |
|
type: "bi.layout", |
|
width: 15, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.item); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 15), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.item.doRedMark.apply(this.item, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.item.unRedMark.apply(this.item, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.item.doHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.item.unHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerIconTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
this.item.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MultiLayerIconTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
this.item.setSelected(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.options.value; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_icon_tree_leaf_item", BI.MultiLayerIconTreeLeafItem); |
|
/** |
|
* 树叶子节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.TreeTextLeafItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.TreeTextLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TreeTextLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-tree-text-leaf-item bi-list-item-active", |
|
id: "", |
|
pId: "", |
|
height: 24, |
|
hgap: 0, |
|
lgap: 0, |
|
rgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.TreeTextLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
lgap: o.lgap, |
|
rgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
el: this.text |
|
}] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.tree_text_leaf_item", BI.TreeTextLeafItem);/** |
|
* 专门为calendar的视觉加的button,作为私有button,不能配置任何属性,也不要用这个玩意 |
|
*/ |
|
BI.CalendarDateItem = BI.inherit(BI.BasicButton, { |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.text_item", |
|
cls: "bi-list-item-select", |
|
textAlign: "center", |
|
whiteSpace: "normal", |
|
text: o.text, |
|
value: o.value, |
|
ref: function () { |
|
self.text = this; |
|
} |
|
}, |
|
left: o.lgap, |
|
right: o.rgap, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.CalendarDateItem.superclass.setSelected.apply(this, arguments); |
|
this.text.setSelected(b); |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
} |
|
}); |
|
BI.shortcut("bi.calendar_date_item", BI.CalendarDateItem);/** |
|
* Created by GUY on 2015/8/28. |
|
* @class BI.Calendar |
|
* @extends BI.Widget |
|
*/ |
|
BI.Calendar = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.Calendar.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-calendar", |
|
logic: { |
|
dynamic: false |
|
}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
year: 2015, |
|
month: 8, |
|
day: 25 |
|
}); |
|
}, |
|
|
|
_dateCreator: function (Y, M, D) { |
|
var self = this, o = this.options, log = {}, De = BI.getDate(); |
|
var mins = o.min.match(/\d+/g); |
|
var maxs = o.max.match(/\d+/g); |
|
Y < (mins[0] | 0) && (Y = (mins[0] | 0)); |
|
Y > (maxs[0] | 0) && (Y = (maxs[0] | 0)); |
|
|
|
De.setFullYear(Y, M, D); |
|
log.ymd = [De.getFullYear(), De.getMonth(), De.getDate()]; |
|
|
|
var MD = BI.Date._MD.slice(0); |
|
MD[1] = BI.isLeapYear(log.ymd[0]) ? 29 : 28; |
|
|
|
// 日期所在月第一天 |
|
De.setFullYear(log.ymd[0], log.ymd[1], 1); |
|
// 是周几 |
|
log.FDay = De.getDay(); |
|
|
|
// 当前BI.StartOfWeek与周日对齐后的FDay是周几 |
|
var offSetFDay = (7 - BI.StartOfWeek + log.FDay) % 7; |
|
|
|
// 当前月页第一天是几号 |
|
log.PDay = MD[M === 0 ? 11 : M - 1] - offSetFDay + 1; |
|
log.NDay = 1; |
|
|
|
var items = []; |
|
BI.each(BI.range(42), function (i) { |
|
var td = {}, YY = log.ymd[0], MM = log.ymd[1] + 1, DD; |
|
// 上个月的日期 |
|
if (i < offSetFDay) { |
|
td.lastMonth = true; |
|
DD = i + log.PDay; |
|
// 上一年 |
|
MM === 1 && (YY -= 1); |
|
MM = MM === 1 ? 12 : MM - 1; |
|
} else if (i >= offSetFDay && i < offSetFDay + MD[log.ymd[1]]) { |
|
DD = i - offSetFDay + 1; |
|
if (i - offSetFDay + 1 === log.ymd[2]) { |
|
td.currentDay = true; |
|
} |
|
} else { |
|
td.nextMonth = true; |
|
DD = log.NDay++; |
|
MM === 12 && (YY += 1); |
|
MM = MM === 12 ? 1 : MM + 1; |
|
} |
|
if (BI.checkDateVoid(YY, MM, DD, mins, maxs)[0]) { |
|
td.disabled = true; |
|
} |
|
td.text = DD; |
|
items.push(td); |
|
}); |
|
return items; |
|
}, |
|
|
|
_init: function () { |
|
BI.Calendar.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var items = BI.map(this._getWeekLabel(), function (i, value) { |
|
return { |
|
type: "bi.label", |
|
height: 24, |
|
text: value |
|
}; |
|
}); |
|
var title = BI.createWidget({ |
|
type: "bi.button_group", |
|
height: 44, |
|
items: items, |
|
layouts: [{ |
|
type: "bi.center", |
|
hgap: 5, |
|
vgap: 10 |
|
}] |
|
}); |
|
|
|
this.days = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: BI.createItems(this._getItems(), {}), |
|
layouts: [BI.LogicFactory.createLogic("table", BI.extend({}, o.logic, { |
|
columns: 7, |
|
rows: 6, |
|
columnSize: [1 / 7, 1 / 7, 1 / 7, 1 / 7, 1 / 7, 1 / 7, 1 / 7], |
|
rowSize: 24, |
|
vgap: 10 |
|
}))] |
|
}); |
|
this.days.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
|
|
}, BI.LogicFactory.createLogic("vertical", BI.extend({}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("top", title, this.days) |
|
})))); |
|
}, |
|
|
|
_getWeekLabel: function () { |
|
return BI.map(BI.range(0, 7), function (idx, v) { |
|
return BI.Date._SDN[(v + BI.StartOfWeek) % 7]; |
|
}); |
|
}, |
|
|
|
isFrontDate: function () { |
|
var o = this.options, c = this._const; |
|
var Y = o.year, M = o.month, De = BI.getDate(), day = De.getDay(); |
|
Y = Y | 0; |
|
De.setFullYear(Y, M, 1); |
|
var newDate = BI.getOffsetDate(De, -1 * (day + 1)); |
|
return !!BI.checkDateVoid(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), o.min, o.max)[0]; |
|
}, |
|
|
|
isFinalDate: function () { |
|
var o = this.options, c = this._const; |
|
var Y = o.year, M = o.month, De = BI.getDate(), day = De.getDay(); |
|
Y = Y | 0; |
|
De.setFullYear(Y, M, 1); |
|
var newDate = BI.getOffsetDate(De, 42 - day); |
|
return !!BI.checkDateVoid(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), o.min, o.max)[0]; |
|
}, |
|
|
|
_getItems: function () { |
|
var o = this.options; |
|
var days = this._dateCreator(o.year, o.month - 1, o.day); |
|
var items = []; |
|
items.push(days.slice(0, 7)); |
|
items.push(days.slice(7, 14)); |
|
items.push(days.slice(14, 21)); |
|
items.push(days.slice(21, 28)); |
|
items.push(days.slice(28, 35)); |
|
items.push(days.slice(35, 42)); |
|
|
|
return BI.map(items, function (i, item) { |
|
return BI.map(item, function (j, td) { |
|
var month = td.lastMonth ? o.month - 1 : (td.nextMonth ? o.month + 1 : o.month); |
|
return BI.extend(td, { |
|
type: "bi.calendar_date_item", |
|
textAlign: "center", |
|
whiteSpace: "normal", |
|
once: false, |
|
forceSelected: true, |
|
height: 24, |
|
value: o.year + "-" + month + "-" + td.text, |
|
disabled: td.lastMonth || td.nextMonth || td.disabled, |
|
lgap: 5, |
|
rgap: 5 |
|
// selected: td.currentDay |
|
}); |
|
}); |
|
}); |
|
}, |
|
|
|
_populate: function() { |
|
this.days.populate(this._getItems()); |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
var o = this.options; |
|
if (BI.isNotEmptyString(o.min)) { |
|
o.min = minDate; |
|
this._populate(); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
var o = this.options; |
|
if (BI.isNotEmptyString(o.max)) { |
|
o.max = maxDate; |
|
this._populate(); |
|
} |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.days.setValue([ob.year + "-" + ob.month + "-" + ob.day]); |
|
}, |
|
|
|
getValue: function () { |
|
var date = this.days.getValue()[0].match(/\d+/g); |
|
return { |
|
year: date[0] | 0, |
|
month: date[1] | 0, |
|
day: date[2] | 0 |
|
}; |
|
} |
|
}); |
|
|
|
BI.extend(BI.Calendar, { |
|
getPageByDateJSON: function (json) { |
|
var year = BI.getDate().getFullYear(); |
|
var month = BI.getDate().getMonth(); |
|
var page = (json.year - year) * 12; |
|
page += json.month - 1 - month; |
|
return page; |
|
}, |
|
getDateJSONByPage: function (v) { |
|
var months = BI.getDate().getMonth(); |
|
var page = v; |
|
|
|
// 对当前page做偏移,使到当前年初 |
|
page = page + months; |
|
|
|
var year = BI.parseInt(page / 12); |
|
if(page < 0 && page % 12 !== 0) { |
|
year--; |
|
} |
|
var month = page >= 0 ? (page % 12) : ((12 + page % 12) % 12); |
|
return { |
|
year: BI.getDate().getFullYear() + year, |
|
month: month + 1 |
|
}; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.calendar", BI.Calendar);/** |
|
* Created by GUY on 2015/8/28. |
|
* @class BI.YearCalendar |
|
* @extends BI.Widget |
|
*/ |
|
BI.YearCalendar = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.YearCalendar.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-year-calendar", |
|
behaviors: {}, |
|
logic: { |
|
dynamic: false |
|
}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
year: null |
|
}); |
|
}, |
|
|
|
_yearCreator: function (Y) { |
|
var o = this.options; |
|
Y = Y | 0; |
|
var start = BI.YearCalendar.getStartYear(Y); |
|
var items = []; |
|
// 对于年控件来说,只要传入的minDate和maxDate的year区间包含v就是合法的 |
|
var startDate = BI.parseDateTime(o.min, "%Y-%X-%d"); |
|
var endDate = BI.parseDateTime(o.max, "%Y-%X-%d"); |
|
BI.each(BI.range(BI.YearCalendar.INTERVAL), function (i) { |
|
var td = {}; |
|
if (BI.checkDateVoid(start + i, 1, 1, BI.print(BI.getDate(startDate.getFullYear(), 0, 1), "%Y-%X-%d"), BI.print(BI.getDate(endDate.getFullYear(), 0, 1), "%Y-%X-%d"))[0]) { |
|
td.disabled = true; |
|
} |
|
td.text = start + i; |
|
items.push(td); |
|
}); |
|
return items; |
|
}, |
|
|
|
_init: function () { |
|
BI.YearCalendar.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.currentYear = BI.getDate().getFullYear(); |
|
|
|
this.years = BI.createWidget({ |
|
type: "bi.button_group", |
|
behaviors: o.behaviors, |
|
items: BI.createItems(this._getItems(), {}), |
|
layouts: [BI.LogicFactory.createLogic("table", BI.extend({}, o.logic, { |
|
columns: 2, |
|
rows: 6, |
|
columnSize: [1 / 2, 1 / 2], |
|
rowSize: 24 |
|
})), { |
|
type: "bi.center_adapt", |
|
vgap: 1 |
|
}] |
|
}); |
|
this.years.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
|
|
}, BI.LogicFactory.createLogic("vertical", BI.extend({}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("top", this.years) |
|
})))); |
|
}, |
|
|
|
isFrontYear: function () { |
|
var o = this.options; |
|
var Y = o.year; |
|
Y = Y | 0; |
|
return !!BI.checkDateVoid(BI.YearCalendar.getStartYear(Y) - 1, 1, 1, o.min, o.max)[0]; |
|
}, |
|
|
|
isFinalYear: function () { |
|
var o = this.options, c = this._const; |
|
var Y = o.year; |
|
Y = Y | 0; |
|
return !!BI.checkDateVoid(BI.YearCalendar.getEndYear(Y) + 1, 1, 1, o.min, o.max)[0]; |
|
}, |
|
|
|
_getItems: function () { |
|
var o = this.options; |
|
var years = this._yearCreator(o.year || this.currentYear); |
|
|
|
// 纵向排列年 |
|
var len = years.length, tyears = BI.makeArray(len, ""); |
|
var map = [0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11]; |
|
BI.each(years, function (i, y) { |
|
tyears[i] = years[map[i]]; |
|
}); |
|
|
|
var items = []; |
|
items.push(tyears.slice(0, 2)); |
|
items.push(tyears.slice(2, 4)); |
|
items.push(tyears.slice(4, 6)); |
|
items.push(tyears.slice(6, 8)); |
|
items.push(tyears.slice(8, 10)); |
|
items.push(tyears.slice(10, 12)); |
|
|
|
return BI.map(items, function (i, item) { |
|
return BI.map(item, function (j, td) { |
|
return BI.extend(td, { |
|
type: "bi.text_item", |
|
cls: "bi-list-item-select", |
|
textAlign: "center", |
|
whiteSpace: "normal", |
|
once: false, |
|
forceSelected: true, |
|
height: 24, |
|
width: 45, |
|
value: td.text, |
|
disabled: td.disabled |
|
}); |
|
}); |
|
}); |
|
}, |
|
|
|
_populate: function () { |
|
this.years.populate(this._getItems()); |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
var o = this.options; |
|
if (BI.isNotEmptyString(o.min)) { |
|
o.min = minDate; |
|
this._populate(); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
var o = this.options; |
|
if (BI.isNotEmptyString(this.options.max)) { |
|
o.max = maxDate; |
|
this._populate(); |
|
} |
|
}, |
|
|
|
setValue: function (val) { |
|
this.years.setValue([val]); |
|
}, |
|
|
|
getValue: function () { |
|
return this.years.getValue()[0]; |
|
} |
|
}); |
|
// 类方法 |
|
BI.extend(BI.YearCalendar, { |
|
INTERVAL: 12, |
|
|
|
// 获取显示的第一年 |
|
getStartYear: function (year) { |
|
var cur = BI.getDate().getFullYear(); |
|
return year - ((year - cur + 3) % BI.YearCalendar.INTERVAL + 12) % BI.YearCalendar.INTERVAL; |
|
}, |
|
|
|
getEndYear: function (year) { |
|
return BI.YearCalendar.getStartYear(year) + BI.YearCalendar.INTERVAL - 1; |
|
}, |
|
|
|
getPageByYear: function (year) { |
|
var cur = BI.getDate().getFullYear(); |
|
year = BI.YearCalendar.getStartYear(year); |
|
return (year - cur + 3) / BI.YearCalendar.INTERVAL; |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.year_calendar", BI.YearCalendar);/** |
|
* Created by roy on 15/10/16. |
|
* 右与下箭头切换的树节点 |
|
*/ |
|
BI.ArrowTreeGroupNodeCheckbox = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ArrowTreeGroupNodeCheckbox.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-arrow-group-node-checkbox" |
|
}); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.ArrowTreeGroupNodeCheckbox.superclass.setSelected.apply(this, arguments); |
|
if(v) { |
|
this.element.removeClass("expander-right-font").addClass("expander-down-font"); |
|
} else { |
|
this.element.removeClass("expander-down-font").addClass("expander-right-font"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.arrow_group_node_checkbox", BI.ArrowTreeGroupNodeCheckbox);/** |
|
* 十字型的树节点 |
|
* @class BI.CheckingMarkNode |
|
* @extends BI.IconButton |
|
*/ |
|
BI.CheckingMarkNode = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
return BI.extend( BI.CheckingMarkNode.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "check-mark-font" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.CheckingMarkNode.superclass._init.apply(this, arguments); |
|
this.setSelected(this.options.selected); |
|
|
|
}, |
|
setSelected: function (v) { |
|
BI.CheckingMarkNode.superclass.setSelected.apply(this, arguments); |
|
if(v === true) { |
|
this.element.addClass("check-mark-font"); |
|
} else { |
|
this.element.removeClass("check-mark-font"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.checking_mark_node", BI.CheckingMarkNode);/** |
|
* 十字型的树节点 |
|
* @class BI.FirstTreeNodeCheckbox |
|
* @extends BI.IconButton |
|
*/ |
|
BI.FirstTreeNodeCheckbox = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
return BI.extend( BI.FirstTreeNodeCheckbox.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "tree-collapse-icon-type2", |
|
iconWidth: 24, |
|
iconHeight: 24 |
|
}); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.FirstTreeNodeCheckbox.superclass.setSelected.apply(this, arguments); |
|
if(v === true) { |
|
this.element.addClass("tree-expand-icon-type2"); |
|
} else { |
|
this.element.removeClass("tree-expand-icon-type2"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.first_tree_node_checkbox", BI.FirstTreeNodeCheckbox);/** |
|
* 十字型的树节点 |
|
* @class BI.LastTreeNodeCheckbox |
|
* @extends BI.IconButton |
|
*/ |
|
BI.LastTreeNodeCheckbox = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.LastTreeNodeCheckbox.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "tree-collapse-icon-type4", |
|
iconWidth: 24, |
|
iconHeight: 24 |
|
}); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.LastTreeNodeCheckbox.superclass.setSelected.apply(this, arguments); |
|
if (v === true) { |
|
this.element.addClass("tree-expand-icon-type4"); |
|
} else { |
|
this.element.removeClass("tree-expand-icon-type4"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.last_tree_node_checkbox", BI.LastTreeNodeCheckbox);/** |
|
* 十字型的树节点 |
|
* @class BI.MidTreeNodeCheckbox |
|
* @extends BI.IconButton |
|
*/ |
|
BI.MidTreeNodeCheckbox = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
return BI.extend( BI.MidTreeNodeCheckbox.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "tree-collapse-icon-type3", |
|
iconWidth: 24, |
|
iconHeight: 24 |
|
}); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MidTreeNodeCheckbox.superclass.setSelected.apply(this, arguments); |
|
if(v === true) { |
|
this.element.addClass("tree-expand-icon-type3"); |
|
} else { |
|
this.element.removeClass("tree-expand-icon-type3"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.mid_tree_node_checkbox", BI.MidTreeNodeCheckbox);/** |
|
* 十字型的树节点 |
|
* @class BI.TreeNodeCheckbox |
|
* @extends BI.IconButton |
|
*/ |
|
BI.TreeNodeCheckbox = BI.inherit(BI.IconButton, { |
|
_defaultConfig: function () { |
|
return BI.extend( BI.TreeNodeCheckbox.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "tree-collapse-icon-type1", |
|
iconWidth: 24, |
|
iconHeight: 24 |
|
}); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.TreeNodeCheckbox.superclass.setSelected.apply(this, arguments); |
|
if(v) { |
|
this.element.addClass("tree-expand-icon-type1"); |
|
} else { |
|
this.element.removeClass("tree-expand-icon-type1"); |
|
} |
|
} |
|
}); |
|
BI.shortcut("bi.tree_node_checkbox", BI.TreeNodeCheckbox);/** |
|
* Created by GUY on 2017/2/8. |
|
* |
|
* @class BI.BubbleCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.BubbleCombo = BI.inherit(BI.Widget, { |
|
_const: { |
|
TRIANGLE_LENGTH: 6 |
|
}, |
|
_defaultConfig: function () { |
|
return BI.extend(BI.BubbleCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-bubble-combo", |
|
trigger: "click", |
|
toggle: true, |
|
direction: "bottom,left", // top||bottom||left||right||top,left||top,right||bottom,left||bottom,right |
|
isDefaultInit: false, |
|
destroyWhenHide: false, |
|
isNeedAdjustHeight: true, // 是否需要高度调整 |
|
isNeedAdjustWidth: true, |
|
stopPropagation: false, |
|
adjustLength: 0, // 调整的距离 |
|
// adjustXOffset: 0, |
|
// adjustYOffset: 10, |
|
hideChecker: BI.emptyFn, |
|
offsetStyle: "left", // left,right,center |
|
el: {}, |
|
popup: {} |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BubbleCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
element: this, |
|
trigger: o.trigger, |
|
toggle: o.toggle, |
|
container: o.container, |
|
direction: o.direction, |
|
isDefaultInit: o.isDefaultInit, |
|
destroyWhenHide: o.destroyWhenHide, |
|
isNeedAdjustHeight: o.isNeedAdjustHeight, |
|
isNeedAdjustWidth: o.isNeedAdjustWidth, |
|
adjustLength: this._getAdjustLength(), |
|
stopPropagation: o.stopPropagation, |
|
adjustXOffset: 0, |
|
adjustYOffset: 0, |
|
hideChecker: o.hideChecker, |
|
offsetStyle: o.offsetStyle, |
|
el: o.el, |
|
popup: BI.extend({ |
|
type: "bi.bubble_popup_view" |
|
}, o.popup) |
|
}); |
|
this.combo.on(BI.Combo.EVENT_TRIGGER_CHANGE, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_TRIGGER_CHANGE, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_CHANGE, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_EXPAND, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_EXPAND, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_COLLAPSE, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_COLLAPSE, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_AFTER_INIT, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_AFTER_INIT, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_AFTER_POPUPVIEW, function () { |
|
self._showTriangle(); |
|
self.fireEvent(BI.BubbleCombo.EVENT_AFTER_POPUPVIEW, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { |
|
self._hideTriangle(); |
|
self.fireEvent(BI.BubbleCombo.EVENT_BEFORE_HIDEVIEW, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
self.fireEvent(BI.BubbleCombo.EVENT_AFTER_HIDEVIEW, arguments); |
|
}); |
|
}, |
|
|
|
_getAdjustLength: function () { |
|
return this._const.TRIANGLE_LENGTH + this.options.adjustLength; |
|
}, |
|
|
|
_createTriangle: function (direction) { |
|
var pos = {}, op = {}; |
|
var adjustLength = this.options.adjustLength; |
|
var offset = this.element.offset(); |
|
var left = offset.left, right = offset.left + this.element.outerWidth(); |
|
var top = offset.top, bottom = offset.top + this.element.outerHeight(); |
|
switch (direction) { |
|
case "left": |
|
pos = { |
|
top: top, |
|
height: this.element.outerHeight(), |
|
left: left - adjustLength - this._const.TRIANGLE_LENGTH |
|
}; |
|
op = {width: this._const.TRIANGLE_LENGTH}; |
|
break; |
|
case "right": |
|
pos = { |
|
top: top, |
|
height: this.element.outerHeight(), |
|
left: right + adjustLength |
|
}; |
|
op = {width: this._const.TRIANGLE_LENGTH}; |
|
break; |
|
case "top": |
|
pos = { |
|
left: left, |
|
width: this.element.outerWidth(), |
|
top: top - adjustLength - this._const.TRIANGLE_LENGTH |
|
}; |
|
op = {height: this._const.TRIANGLE_LENGTH}; |
|
break; |
|
case "bottom": |
|
pos = { |
|
left: left, |
|
width: this.element.outerWidth(), |
|
top: bottom + adjustLength |
|
}; |
|
op = {height: this._const.TRIANGLE_LENGTH}; |
|
break; |
|
default: |
|
break; |
|
} |
|
this.triangle && this.triangle.destroy(); |
|
this.triangle = BI.createWidget(op, { |
|
type: "bi.center_adapt", |
|
cls: "button-combo-triangle-wrapper", |
|
items: [{ |
|
type: "bi.layout", |
|
cls: "bubble-combo-triangle-" + direction |
|
}] |
|
}); |
|
pos.el = this.triangle; |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [pos] |
|
}); |
|
}, |
|
|
|
_createLeftTriangle: function () { |
|
this._createTriangle("left"); |
|
}, |
|
|
|
_createRightTriangle: function () { |
|
this._createTriangle("right"); |
|
}, |
|
|
|
_createTopTriangle: function () { |
|
this._createTriangle("top"); |
|
}, |
|
|
|
_createBottomTriangle: function () { |
|
this._createTriangle("bottom"); |
|
}, |
|
|
|
_showTriangle: function () { |
|
var pos = this.combo.getPopupPosition(); |
|
switch (pos.dir) { |
|
case "left,top": |
|
case "left,bottom": |
|
this._createLeftTriangle(); |
|
break; |
|
case "right,top": |
|
case "right,bottom": |
|
this._createRightTriangle(); |
|
break; |
|
case "top,left": |
|
case "top,right": |
|
this._createTopTriangle(); |
|
break; |
|
case "bottom,left": |
|
case "bottom,right": |
|
this._createBottomTriangle(); |
|
break; |
|
} |
|
}, |
|
|
|
_hideTriangle: function () { |
|
this.triangle && this.triangle.destroy(); |
|
this.triangle = null; |
|
}, |
|
|
|
hideView: function () { |
|
this._hideTriangle(); |
|
this.combo && this.combo.hideView(); |
|
}, |
|
|
|
showView: function () { |
|
this.combo && this.combo.showView(); |
|
}, |
|
|
|
isViewVisible: function () { |
|
return this.combo.isViewVisible(); |
|
} |
|
}); |
|
|
|
BI.BubbleCombo.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE"; |
|
BI.BubbleCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.BubbleCombo.EVENT_EXPAND = "EVENT_EXPAND"; |
|
BI.BubbleCombo.EVENT_COLLAPSE = "EVENT_COLLAPSE"; |
|
BI.BubbleCombo.EVENT_AFTER_INIT = "EVENT_AFTER_INIT"; |
|
|
|
|
|
BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.BubbleCombo.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW"; |
|
BI.BubbleCombo.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW"; |
|
BI.BubbleCombo.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW"; |
|
BI.shortcut("bi.bubble_combo", BI.BubbleCombo);/** |
|
* Created by GUY on 2017/2/8. |
|
* |
|
* @class BI.BubblePopupView |
|
* @extends BI.PopupView |
|
*/ |
|
BI.BubblePopupView = BI.inherit(BI.PopupView, { |
|
_defaultConfig: function () { |
|
var config = BI.BubblePopupView.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(config, { |
|
baseCls: config.baseCls + " bi-bubble-popup-view", |
|
minWidth: 220, |
|
maxWidth: 300, |
|
minHeight: 90 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BubblePopupView.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.bubble_popup_view", BI.BubblePopupView); |
|
|
|
/** |
|
* Created by GUY on 2017/2/8. |
|
* |
|
* @class BI.BubblePopupBarView |
|
* @extends BI.BubblePopupView |
|
*/ |
|
BI.BubblePopupBarView = BI.inherit(BI.BubblePopupView, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.BubblePopupBarView.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-bubble-bar-popup-view", |
|
buttons: [{ |
|
value: false, |
|
text: BI.i18nText("BI-Basic_Cancel"), |
|
ghost: true |
|
}, { |
|
text: BI.i18nText(BI.i18nText("BI-Basic_Sure")), |
|
value: true |
|
}] |
|
}); |
|
}, |
|
_init: function () { |
|
BI.BubblePopupBarView.superclass._init.apply(this, arguments); |
|
}, |
|
_createToolBar: function () { |
|
var o = this.options, self = this; |
|
|
|
var items = []; |
|
BI.each(o.buttons, function (i, buttonOpt) { |
|
if (BI.isWidget(buttonOpt)) { |
|
items.push(buttonOpt); |
|
} else { |
|
items.push(BI.extend({ |
|
type: "bi.button", |
|
height: 24, |
|
handler: function (v) { |
|
self.fireEvent(BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON, v); |
|
} |
|
}, buttonOpt)); |
|
} |
|
}); |
|
return BI.createWidget({ |
|
type: "bi.center", |
|
height: 44, |
|
rgap: 15, |
|
items: [{ |
|
type: "bi.right_vertical_adapt", |
|
lgap: 10, |
|
items: items |
|
}] |
|
}); |
|
}, |
|
|
|
_createView: function () { |
|
var o = this.options; |
|
|
|
var button = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: [o.el], |
|
layouts: [{ |
|
type: "bi.vertical", |
|
cls: "bar-popup-container", |
|
hgap: 15, |
|
tgap: 10 |
|
}] |
|
}); |
|
|
|
button.element.css("min-height", o.minHeight - 44); |
|
|
|
return button; |
|
} |
|
}); |
|
BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON = "EVENT_CLICK_TOOLBAR_BUTTON"; |
|
BI.shortcut("bi.bubble_bar_popup_view", BI.BubblePopupBarView); |
|
|
|
/** |
|
* Created by Windy on 2018/2/2. |
|
* |
|
* @class BI.TextBubblePopupBarView |
|
* @extends BI.BubblePopupView |
|
*/ |
|
BI.TextBubblePopupBarView = BI.inherit(BI.Widget, { |
|
|
|
props: function () { |
|
return { |
|
baseCls: "bi-text-bubble-bar-popup-view", |
|
text: "", |
|
buttons: [{ |
|
level: "ignore", |
|
value: false, |
|
stopPropagation: true, |
|
text: BI.i18nText("BI-Basic_Cancel") |
|
}, { |
|
value: true, |
|
stopPropagation: true, |
|
text: BI.i18nText("BI-Basic_Sure") |
|
}] |
|
}; |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
var buttons = BI.map(o.buttons, function (index, buttonOpt) { |
|
if (BI.isWidget(buttonOpt)) { |
|
return buttonOpt; |
|
} |
|
return BI.extend({ |
|
type: "bi.button", |
|
height: 24, |
|
handler: function (v) { |
|
self.fireEvent(BI.TextBubblePopupBarView.EVENT_CHANGE, v); |
|
} |
|
}, buttonOpt); |
|
|
|
}); |
|
return { |
|
type: "bi.bubble_bar_popup_view", |
|
minWidth: o.minWidth, |
|
maxWidth: o.maxWidth, |
|
minHeight: o.minHeight, |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
el: { |
|
type: "bi.label", |
|
text: o.text, |
|
whiteSpace: "normal", |
|
textAlign: "left", |
|
ref: function () { |
|
self.text = this; |
|
} |
|
}, |
|
buttons: buttons |
|
}; |
|
}, |
|
|
|
populate: function (v) { |
|
this.text.setText(v || this.options.text); |
|
} |
|
}); |
|
BI.TextBubblePopupBarView.EVENT_CHANGE = "EVENT_CLICK_TOOLBAR_BUTTON"; |
|
BI.shortcut("bi.text_bubble_bar_popup_view", BI.TextBubblePopupBarView); |
|
/** |
|
* Created by Young's on 2016/4/28. |
|
*/ |
|
BI.EditorIconCheckCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.EditorIconCheckCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseClass: "bi-check-editor-combo", |
|
width: 100, |
|
height: 24, |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: true, |
|
watermark: "", |
|
errorText: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.EditorIconCheckCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.editor_trigger", |
|
items: o.items, |
|
height: o.height, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText, |
|
value: o.value |
|
}); |
|
this.trigger.on(BI.EditorTrigger.EVENT_CHANGE, function () { |
|
self.popup.setValue(this.getValue()); |
|
self.fireEvent(BI.EditorIconCheckCombo.EVENT_CHANGE, arguments); |
|
}); |
|
this.trigger.on(BI.EditorTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.EditorIconCheckCombo.EVENT_FOCUS, arguments); |
|
}); |
|
this.trigger.on(BI.EditorTrigger.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.EditorIconCheckCombo.EVENT_EMPTY, arguments); |
|
}); |
|
this.trigger.on(BI.EditorTrigger.EVENT_VALID, function () { |
|
self.fireEvent(BI.EditorIconCheckCombo.EVENT_VALID, arguments); |
|
}); |
|
this.trigger.on(BI.EditorTrigger.EVENT_ERROR, function () { |
|
self.fireEvent(BI.EditorIconCheckCombo.EVENT_ERROR, arguments); |
|
}); |
|
|
|
this.popup = BI.createWidget({ |
|
type: "bi.text_value_check_combo_popup", |
|
chooseType: o.chooseType, |
|
items: o.items, |
|
value: o.value |
|
}); |
|
this.popup.on(BI.TextValueCheckComboPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.editorIconCheckCombo.hideView(); |
|
self.fireEvent(BI.EditorIconCheckCombo.EVENT_CHANGE); |
|
}); |
|
this.popup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editorIconCheckCombo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
element: this, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup, |
|
maxHeight: 300 |
|
} |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editorIconCheckCombo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.trigger.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.editorIconCheckCombo.populate(items); |
|
} |
|
}); |
|
BI.EditorIconCheckCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.EditorIconCheckCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.EditorIconCheckCombo.EVENT_EMPTY = "EVENT_EMPTY"; |
|
BI.EditorIconCheckCombo.EVENT_VALID = "EVENT_VALID"; |
|
BI.EditorIconCheckCombo.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.shortcut("bi.editor_icon_check_combo", BI.EditorIconCheckCombo); |
|
/** |
|
* Created by GUY on 2016/2/2. |
|
* |
|
* @class BI.IconCombo |
|
* @extend BI.Widget |
|
*/ |
|
BI.IconCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-icon-combo", |
|
width: 24, |
|
height: 24, |
|
el: {}, |
|
popup: {}, |
|
minWidth: 100, |
|
maxWidth: "auto", |
|
maxHeight: 300, |
|
direction: "bottom", |
|
adjustLength: 3, // 调整的距离 |
|
adjustXOffset: 0, |
|
adjustYOffset: 0, |
|
offsetStyle: "left", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.trigger = BI.createWidget(o.el, { |
|
type: "bi.icon_combo_trigger", |
|
iconCls: o.iconCls, |
|
title: o.title, |
|
items: o.items, |
|
width: o.width, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight, |
|
value: o.value |
|
}); |
|
this.popup = BI.createWidget(o.popup, { |
|
type: "bi.icon_combo_popup", |
|
chooseType: o.chooseType, |
|
items: o.items, |
|
value: o.value |
|
}); |
|
this.popup.on(BI.IconComboPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.iconCombo.hideView(); |
|
self.fireEvent(BI.IconCombo.EVENT_CHANGE); |
|
}); |
|
this.popup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.iconCombo = BI.createWidget({ |
|
type: "bi.combo", |
|
element: this, |
|
direction: o.direction, |
|
trigger: o.trigger, |
|
container: o.container, |
|
adjustLength: o.adjustLength, |
|
adjustXOffset: o.adjustXOffset, |
|
adjustYOffset: o.adjustYOffset, |
|
offsetStyle: o.offsetStyle, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup, |
|
maxWidth: o.maxWidth, |
|
maxHeight: o.maxHeight, |
|
minWidth: o.minWidth |
|
} |
|
}); |
|
}, |
|
|
|
showView: function () { |
|
this.iconCombo.showView(); |
|
}, |
|
|
|
hideView: function () { |
|
this.iconCombo.hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
var value = this.popup.getValue(); |
|
return BI.isNull(value) ? [] : (BI.isArray(value) ? value : [value]); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.iconCombo.populate(items); |
|
} |
|
}); |
|
BI.IconCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_combo", BI.IconCombo);/** |
|
* Created by GUY on 2016/2/2. |
|
* |
|
* @class BI.IconComboPopup |
|
* @extend BI.Pane |
|
*/ |
|
BI.IconComboPopup = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconComboPopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi.icon-combo-popup", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconComboPopup.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
this.popup = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: BI.createItems(o.items, { |
|
type: "bi.single_select_icon_text_item", |
|
height: 24 |
|
}), |
|
chooseType: o.chooseType, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
value: o.value |
|
}); |
|
|
|
this.popup.on(BI.Controller.EVENT_CHANGE, function (type, val, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.IconComboPopup.EVENT_CHANGE, val, obj); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
vgap: 5, |
|
items: [this.popup] |
|
}); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.IconComboPopup.superclass.populate.apply(this, arguments); |
|
items = BI.createItems(items, { |
|
type: "bi.single_select_icon_text_item", |
|
height: 24 |
|
}); |
|
this.popup.populate(items); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popup.setValue(v); |
|
} |
|
|
|
}); |
|
BI.IconComboPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_combo_popup", BI.IconComboPopup);/** |
|
* Created by GUY on 2016/2/2. |
|
* |
|
* @class BI.IconComboTrigger |
|
* @extend BI.Widget |
|
*/ |
|
BI.IconComboTrigger = BI.inherit(BI.Trigger, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconComboTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-icon-combo-trigger", |
|
el: {}, |
|
items: [], |
|
iconCls: "", |
|
width: 24, |
|
height: 24, |
|
isShowDown: true, |
|
value: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconComboTrigger.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
var iconCls = ""; |
|
if(BI.isKey(o.value)){ |
|
iconCls = this._digest(o.value, o.items); |
|
} |
|
this.button = BI.createWidget(o.el, { |
|
type: "bi.icon_change_button", |
|
cls: "icon-combo-trigger-icon", |
|
iconCls: iconCls, |
|
disableSelected: true, |
|
width: o.isShowDown ? o.width - 12 : o.width, |
|
height: o.height, |
|
iconWidth: o.iconWidth, |
|
iconHeight: o.iconHeight, |
|
selected: BI.isNotEmptyString(iconCls) |
|
}); |
|
this.down = BI.createWidget({ |
|
type: "bi.icon_button", |
|
disableSelected: true, |
|
cls: "icon-combo-down-icon trigger-triangle-font font-size-12", |
|
width: 12, |
|
height: 8, |
|
selected: BI.isNotEmptyString(iconCls) |
|
}); |
|
this.down.setVisible(o.isShowDown); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.button, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: this.down, |
|
right: 3, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_digest: function (v, items) { |
|
var iconCls = ""; |
|
v = BI.isArray(v) ? v[0] : v; |
|
BI.any(items, function (i, item) { |
|
if (v === item.value) { |
|
iconCls = item.iconCls; |
|
return true; |
|
} |
|
}); |
|
return iconCls; |
|
}, |
|
|
|
populate: function (items) { |
|
var o = this.options; |
|
this.options.items = items || []; |
|
this.button.setIcon(o.iconCls); |
|
this.button.setSelected(false); |
|
this.down.setSelected(false); |
|
}, |
|
|
|
setValue: function (v) { |
|
BI.IconComboTrigger.superclass.setValue.apply(this, arguments); |
|
var o = this.options; |
|
var iconCls = this._digest(v, this.options.items); |
|
v = BI.isArray(v) ? v[0] : v; |
|
if (BI.isNotEmptyString(iconCls)) { |
|
this.button.setIcon(iconCls); |
|
this.button.setSelected(true); |
|
this.down.setSelected(true); |
|
} else { |
|
this.button.setIcon(o.iconCls); |
|
this.button.setSelected(false); |
|
this.down.setSelected(false); |
|
} |
|
} |
|
}); |
|
BI.IconComboTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_combo_trigger", BI.IconComboTrigger);/** |
|
* Created by Windy on 2017/12/12. |
|
* combo : icon + text + icon, popup : icon + text |
|
*/ |
|
BI.IconTextValueCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconTextValueCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-icon-text-value-combo", |
|
height: 24, |
|
iconHeight: null, |
|
iconWidth: null, |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconTextValueCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.select_icon_text_trigger", |
|
cls: "icon-text-value-trigger", |
|
items: o.items, |
|
height: o.height, |
|
text: o.text, |
|
iconCls: o.iconCls, |
|
value: o.value, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
iconWrapperWidth: o.iconWrapperWidth, |
|
title: o.title, |
|
warningTitle: o.warningTitle |
|
}); |
|
this.popup = BI.createWidget({ |
|
type: "bi.icon_text_value_combo_popup", |
|
items: o.items, |
|
value: o.value, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
iconWrapperWidth: o.iconWrapperWidth |
|
}); |
|
this.popup.on(BI.IconTextValueComboPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.textIconCombo.hideView(); |
|
self.fireEvent(BI.IconTextValueCombo.EVENT_CHANGE, arguments); |
|
}); |
|
this.popup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.textIconCombo = BI.createWidget({ |
|
type: "bi.combo", |
|
element: this, |
|
container: o.container, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup, |
|
maxHeight: 240, |
|
minHeight: 25 |
|
} |
|
}); |
|
if (BI.isKey(o.value)) { |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_checkError: function (v) { |
|
if(BI.isNotNull(v)) { |
|
v = BI.isArray(v) ? v : [v]; |
|
var result = BI.find(this.options.items, function (idx, item) { |
|
return BI.contains(v, item.value); |
|
}); |
|
if (BI.isNull(result)) { |
|
this.trigger.options.tipType = "warning"; |
|
this.element.removeClass("combo-error").addClass("combo-error"); |
|
} else { |
|
this.trigger.options.tipType = "success"; |
|
this.element.removeClass("combo-error"); |
|
} |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
this._checkError(v); |
|
}, |
|
|
|
getValue: function () { |
|
var value = this.popup.getValue(); |
|
return BI.isNull(value) ? [] : (BI.isArray(value) ? value : [value]); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.textIconCombo.populate(items); |
|
} |
|
}); |
|
BI.IconTextValueCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_text_value_combo", BI.IconTextValueCombo); |
|
/** |
|
* Created by Windy on 2017/12/12. |
|
*/ |
|
BI.IconTextValueComboPopup = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconTextValueComboPopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-icon-text-icon-popup", |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconTextValueComboPopup.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
this.popup = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: BI.createItems(o.items, { |
|
type: "bi.single_select_icon_text_item", |
|
height: 24, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
iconWrapperWidth: o.iconWrapperWidth |
|
}), |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
behaviors: o.behaviors, |
|
value: o.value |
|
}); |
|
|
|
this.popup.on(BI.Controller.EVENT_CHANGE, function (type, val, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.IconTextValueComboPopup.EVENT_CHANGE, val, obj); |
|
} |
|
}); |
|
|
|
this.check(); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
vgap: 5, |
|
items: [this.popup] |
|
}); |
|
}, |
|
|
|
populate: function (items, keyword) { |
|
BI.IconTextValueComboPopup.superclass.populate.apply(this, arguments); |
|
var o = this.options; |
|
items = BI.createItems(items, { |
|
type: "bi.single_select_icon_text_item", |
|
height: 24, |
|
iconWrapperWidth: o.iconWrapperWidth, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth |
|
}); |
|
this.popup.populate(items, keyword); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popup.setValue(v); |
|
} |
|
|
|
}); |
|
BI.IconTextValueComboPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.icon_text_value_combo_popup", BI.IconTextValueComboPopup); |
|
/** |
|
* Created by Windy on 2018/2/2. |
|
*/ |
|
BI.SearchTextValueCombo = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-search-text-value-combo", |
|
height: 24, |
|
text: "", |
|
items: [], |
|
tipType: "", |
|
warningTitle: "", |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.combo", |
|
container: o.container, |
|
adjustLength: 2, |
|
toggle: false, |
|
ref: function () { |
|
self.combo = this; |
|
}, |
|
el: { |
|
type: "bi.search_text_value_trigger", |
|
cls: "search-text-value-trigger", |
|
ref: function () { |
|
self.trigger = this; |
|
}, |
|
items: o.items, |
|
height: o.height - 2, |
|
text: o.text, |
|
value: o.value, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle, |
|
title: o.title, |
|
listeners: [{ |
|
eventName: BI.SearchTextValueTrigger.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(this.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.SearchTextValueCombo.EVENT_CHANGE); |
|
} |
|
}] |
|
}, |
|
popup: { |
|
el: { |
|
type: "bi.text_value_combo_popup", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
value: o.value, |
|
items: o.items, |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.getSearcher().setAdapter(self.popup); |
|
}, |
|
listeners: [{ |
|
eventName: BI.TextValueComboPopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(this.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.SearchTextValueCombo.EVENT_CHANGE); |
|
} |
|
}] |
|
}, |
|
value: o.value, |
|
maxHeight: 252, |
|
minHeight: 25 |
|
}, |
|
listeners: [{ |
|
eventName: BI.Combo.EVENT_AFTER_HIDEVIEW, |
|
action: function () { |
|
self.trigger.stopEditing(); |
|
} |
|
}, { |
|
eventName: BI.Combo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
self.fireEvent(BI.SearchTextValueCombo.EVENT_BEFORE_POPUPVIEW); |
|
} |
|
}], |
|
hideChecker: function (e) { |
|
return self.triggerBtn.element.find(e.target).length === 0; |
|
} |
|
}, |
|
left: 0, |
|
right: 0, |
|
bottom: 0, |
|
top: 0 |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
cls: "trigger-icon-button", |
|
ref: function () { |
|
self.triggerBtn = this; |
|
}, |
|
width: o.height, |
|
height: o.height, |
|
handler: function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
} |
|
}, |
|
right: 0, |
|
bottom: 0, |
|
top: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
var o = this.options; |
|
if(BI.isKey(o.value)) { |
|
this._checkError(o.value); |
|
} |
|
}, |
|
|
|
_checkError: function (v) { |
|
if(BI.isNotNull(v)) { |
|
v = BI.isArray(v) ? v : [v]; |
|
var result = BI.find(this.options.items, function (idx, item) { |
|
return BI.contains(v, item.value); |
|
}); |
|
if (BI.isNull(result)) { |
|
this.element.removeClass("combo-error").addClass("combo-error"); |
|
this.trigger.attr("tipType", "warning"); |
|
} else { |
|
this.element.removeClass("combo-error"); |
|
this.trigger.attr("tipType", "success"); |
|
} |
|
} |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.combo.populate(items); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
this._checkError(v); |
|
}, |
|
|
|
getValue: function () { |
|
var value = this.combo.getValue(); |
|
return BI.isNull(value) ? [] : (BI.isArray(value) ? value : [value]); |
|
} |
|
}); |
|
BI.SearchTextValueCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SearchTextValueCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.search_text_value_combo", BI.SearchTextValueCombo); |
|
/** |
|
* Created by Windy on 2018/2/5. |
|
*/ |
|
BI.SearchTextValueComboPopup = BI.inherit(BI.Pane, { |
|
|
|
props: { |
|
baseCls: "bi-search-text-value-popup" |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.vertical", |
|
vgap: 5, |
|
items: [{ |
|
type: "bi.button_group", |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
items: BI.createItems(o.items, { |
|
type: "bi.single_select_item", |
|
textAlign: o.textAlign, |
|
height: 24 |
|
}), |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
value: o.value, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function (type, val, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.SearchTextValueComboPopup.EVENT_CHANGE, val, obj); |
|
} |
|
} |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
mounted: function() { |
|
this.check(); |
|
}, |
|
|
|
populate: function (find, match, keyword) { |
|
var items = BI.concat(find, match); |
|
BI.SearchTextValueComboPopup.superclass.populate.apply(this, items); |
|
items = BI.createItems(items, { |
|
type: "bi.single_select_item", |
|
height: 24 |
|
}); |
|
this.popup.populate(items, keyword); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popup.setValue(v); |
|
} |
|
|
|
}); |
|
BI.SearchTextValueComboPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.search_text_value_combo_popup", BI.SearchTextValueComboPopup);/** |
|
* Created by Windy on 2018/2/2. |
|
*/ |
|
BI.SearchTextValueTrigger = BI.inherit(BI.Trigger, { |
|
|
|
props: { |
|
extraCls: "bi-search-text-value-trigger bi-border", |
|
height: 24 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: { |
|
type: "bi.searcher", |
|
ref: function () { |
|
self.searcher = this; |
|
}, |
|
isAutoSearch: false, |
|
el: { |
|
type: "bi.state_editor", |
|
ref: function () { |
|
self.editor = this; |
|
}, |
|
defaultText: o.text, |
|
text: this._digest(o.value, o.items), |
|
value: o.value, |
|
height: o.height, |
|
tipText: "" |
|
}, |
|
popup: { |
|
type: "bi.search_text_value_combo_popup", |
|
cls: "bi-card", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE |
|
}, |
|
onSearch: function (obj, callback) { |
|
var keyword = obj.keyword; |
|
var finding = BI.Func.getSearchResult(o.items, keyword); |
|
var matched = finding.match, find = finding.find; |
|
callback(find, matched); |
|
}, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.SearchTextValueTrigger.EVENT_CHANGE); |
|
} |
|
}] |
|
} |
|
}, { |
|
el: { |
|
type: "bi.layout", |
|
width: 24 |
|
}, |
|
width: 24 |
|
} |
|
] |
|
}; |
|
}, |
|
|
|
_setState: function (v) { |
|
this.editor.setState(v); |
|
}, |
|
|
|
_digest: function(vals, items){ |
|
var o = this.options; |
|
vals = BI.isArray(vals) ? vals : [vals]; |
|
var result = []; |
|
var formatItems = BI.Tree.transformToArrayFormat(items); |
|
BI.each(formatItems, function (i, item) { |
|
if (BI.deepContains(vals, item.value) && !BI.contains(result, item.text || item.value)) { |
|
result.push(item.text || item.value); |
|
} |
|
}); |
|
|
|
if (result.length > 0) { |
|
return result.join(","); |
|
} else { |
|
return BI.isFunction(o.text) ? o.text() : o.text; |
|
} |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
}, |
|
|
|
setValue: function (vals) { |
|
this._setState(this._digest(vals, this.options.items)); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
BI.SearchTextValueTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.SearchTextValueTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.SearchTextValueTrigger.EVENT_START = "EVENT_START"; |
|
BI.SearchTextValueTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.search_text_value_trigger", BI.SearchTextValueTrigger);/** |
|
* @class BI.TextValueCheckCombo |
|
* @extend BI.Widget |
|
* combo : text + icon, popup : check + text |
|
*/ |
|
BI.TextValueCheckCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TextValueCheckCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-text-value-check-combo", |
|
width: 100, |
|
height: 24, |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextValueCheckCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.select_text_trigger", |
|
cls: "text-value-trigger", |
|
items: o.items, |
|
height: o.height, |
|
text: o.text, |
|
value: o.value |
|
}); |
|
this.popup = BI.createWidget({ |
|
type: "bi.text_value_check_combo_popup", |
|
chooseType: o.chooseType, |
|
items: o.items, |
|
value: o.value |
|
}); |
|
this.popup.on(BI.TextValueCheckComboPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.textIconCheckCombo.hideView(); |
|
self.fireEvent(BI.TextValueCheckCombo.EVENT_CHANGE); |
|
}); |
|
this.popup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.textIconCheckCombo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
element: this, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup, |
|
maxHeight: 300 |
|
} |
|
}); |
|
|
|
if (BI.isKey(o.value)) { |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
setTitle: function (title) { |
|
this.trigger.setTitle(title); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
setWarningTitle: function (title) { |
|
this.trigger.setWarningTitle(title); |
|
}, |
|
|
|
getValue: function () { |
|
var value = this.popup.getValue(); |
|
return BI.isNull(value) ? [] : (BI.isArray(value) ? value : [value]); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.textIconCheckCombo.populate(items); |
|
} |
|
}); |
|
BI.TextValueCheckCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_value_check_combo", BI.TextValueCheckCombo);BI.TextValueCheckComboPopup = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TextValueCheckComboPopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-text-icon-popup", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextValueCheckComboPopup.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
this.popup = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: this._formatItems(o.items), |
|
chooseType: o.chooseType, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
value: o.value |
|
}); |
|
|
|
this.popup.on(BI.Controller.EVENT_CHANGE, function (type, val, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.TextValueCheckComboPopup.EVENT_CHANGE, val, obj); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
vgap: 5, |
|
items: [this.popup] |
|
}); |
|
}, |
|
|
|
_formatItems: function (items) { |
|
return BI.map(items, function (i, item) { |
|
return BI.extend({ |
|
type: "bi.single_select_item", |
|
cls: "bi-list-item", |
|
height: 24 |
|
}, item); |
|
}); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.TextValueCheckComboPopup.superclass.populate.apply(this, arguments); |
|
this.popup.populate(this._formatItems(items)); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popup.setValue(v); |
|
} |
|
|
|
}); |
|
BI.TextValueCheckComboPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_value_check_combo_popup", BI.TextValueCheckComboPopup); |
|
/** |
|
* @class BI.TextValueCombo |
|
* @extend BI.Widget |
|
* combo : text + icon, popup : text |
|
* 参见场景dashboard布局方式选择 |
|
*/ |
|
BI.TextValueCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TextValueCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-text-value-combo", |
|
height: 24, |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
text: "", |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextValueCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.select_text_trigger", |
|
cls: "text-value-trigger", |
|
items: o.items, |
|
height: o.height, |
|
text: o.text, |
|
value: o.value, |
|
warningTitle: o.warningTitle |
|
}); |
|
this.popup = BI.createWidget({ |
|
type: "bi.text_value_combo_popup", |
|
chooseType: o.chooseType, |
|
value: o.value, |
|
items: o.items |
|
}); |
|
this.popup.on(BI.TextValueComboPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.textIconCombo.hideView(); |
|
self.fireEvent(BI.TextValueCombo.EVENT_CHANGE, arguments); |
|
}); |
|
this.popup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.textIconCombo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
element: this, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup, |
|
maxHeight: 240, |
|
minHeight: 25 |
|
} |
|
}); |
|
if(BI.isKey(o.value)) { |
|
this._checkError(o.value); |
|
} |
|
}, |
|
|
|
_checkError: function (v) { |
|
if(BI.isNotNull(v)) { |
|
v = BI.isArray(v) ? v : [v]; |
|
var result = BI.find(this.options.items, function (idx, item) { |
|
return BI.contains(v, item.value); |
|
}); |
|
if (BI.isNull(result)) { |
|
this.trigger.setTipType("warning"); |
|
this.element.removeClass("combo-error").addClass("combo-error"); |
|
} else { |
|
this.trigger.setTipType("success"); |
|
this.element.removeClass("combo-error"); |
|
} |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
this._checkError(v); |
|
}, |
|
|
|
getValue: function () { |
|
var value = this.popup.getValue(); |
|
return BI.isNull(value) ? [] : (BI.isArray(value) ? value : [value]); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.textIconCombo.populate(items); |
|
} |
|
}); |
|
BI.TextValueCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_value_combo", BI.TextValueCombo); |
|
/** |
|
* @class BI.SmallTextValueCombo |
|
* @extend BI.Widget |
|
* combo : text + icon, popup : text |
|
* 参见场景dashboard布局方式选择 |
|
*/ |
|
BI.SmallTextValueCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SmallTextValueCombo.superclass._defaultConfig.apply(this, arguments), { |
|
width: 100, |
|
height: 20, |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
el: {}, |
|
text: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SmallTextValueCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.trigger = BI.createWidget(o.el, { |
|
type: "bi.small_select_text_trigger", |
|
items: o.items, |
|
height: o.height, |
|
text: o.text |
|
}); |
|
this.popup = BI.createWidget({ |
|
type: "bi.text_value_combo_popup", |
|
chooseType: o.chooseType, |
|
items: o.items |
|
}); |
|
this.popup.on(BI.TextValueComboPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.SmallTextValueCombo.hideView(); |
|
self.fireEvent(BI.SmallTextValueCombo.EVENT_CHANGE); |
|
}); |
|
this.popup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.SmallTextValueCombo = BI.createWidget({ |
|
type: "bi.combo", |
|
element: this, |
|
container: o.container, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup, |
|
maxHeight: 240, |
|
minHeight: 25 |
|
} |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.SmallTextValueCombo.populate(items); |
|
} |
|
}); |
|
BI.SmallTextValueCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.small_text_value_combo", BI.SmallTextValueCombo);BI.TextValueComboPopup = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TextValueComboPopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-text-icon-popup", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextValueComboPopup.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
this.popup = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: BI.createItems(o.items, { |
|
type: "bi.single_select_item", |
|
textAlign: o.textAlign, |
|
height: 24 |
|
}), |
|
chooseType: o.chooseType, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}], |
|
value: o.value |
|
}); |
|
|
|
this.popup.on(BI.Controller.EVENT_CHANGE, function (type, val, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.TextValueComboPopup.EVENT_CHANGE, val, obj); |
|
} |
|
}); |
|
this.check(); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
vgap: 5, |
|
items: [this.popup] |
|
}); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.TextValueComboPopup.superclass.populate.apply(this, arguments); |
|
items = BI.createItems(items, { |
|
type: "bi.single_select_item", |
|
height: 24 |
|
}); |
|
this.popup.populate(items); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popup.setValue(v); |
|
} |
|
|
|
}); |
|
BI.TextValueComboPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_value_combo_popup", BI.TextValueComboPopup);/** |
|
* 有清楚按钮的文本框 |
|
* Created by GUY on 2015/9/29. |
|
* @class BI.SmallTextEditor |
|
* @extends BI.SearchEditor |
|
*/ |
|
BI.ClearEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.ClearEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-clear-editor", |
|
height: 24, |
|
errorText: "", |
|
watermark: "", |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.ClearEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
watermark: o.watermark, |
|
allowBlank: true, |
|
errorText: o.errorText, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
value: o.value |
|
}); |
|
this.clear = BI.createWidget({ |
|
type: "bi.icon_button", |
|
stopEvent: true, |
|
cls: "search-close-h-font" |
|
}); |
|
this.clear.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self.setValue(""); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STOPEDIT); |
|
self.fireEvent(BI.ClearEditor.EVENT_CLEAR); |
|
}); |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: this.editor |
|
}, |
|
{ |
|
el: this.clear, |
|
width: 24 |
|
}] |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_BLUR); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_CLICK); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self._checkClear(); |
|
self.fireEvent(BI.ClearEditor.EVENT_CHANGE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.ClearEditor.EVENT_KEY_DOWN, v); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_SPACE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BACKSPACE, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_BACKSPACE); |
|
}); |
|
|
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_VALID); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_ERROR); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_ENTER); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_RESTRICT); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self._checkClear(); |
|
self.fireEvent(BI.ClearEditor.EVENT_EMPTY); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_REMOVE, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_REMOVE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_CONFIRM); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_CHANGE_CONFIRM); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_START); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_PAUSE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.ClearEditor.EVENT_STOP); |
|
}); |
|
|
|
if (BI.isKey(o.value)) { |
|
this.clear.visible(); |
|
} else { |
|
this.clear.invisible(); |
|
} |
|
}, |
|
|
|
_checkClear: function () { |
|
if (!this.getValue()) { |
|
this.clear.invisible(); |
|
} else { |
|
this.clear.visible(); |
|
} |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
focus: function () { |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
}, |
|
|
|
getValue: function () { |
|
if (this.isValid()) { |
|
var res = this.editor.getValue().match(/[\S]+/g); |
|
return BI.isNull(res) ? "" : res[res.length - 1]; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setValue(v); |
|
if (BI.isKey(v)) { |
|
this.clear.visible(); |
|
} |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
} |
|
}); |
|
BI.ClearEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.ClearEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.ClearEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.ClearEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.ClearEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.ClearEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.ClearEditor.EVENT_BACKSPACE = "EVENT_BACKSPACE"; |
|
BI.ClearEditor.EVENT_CLEAR = "EVENT_CLEAR"; |
|
|
|
BI.ClearEditor.EVENT_START = "EVENT_START"; |
|
BI.ClearEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.ClearEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.ClearEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.ClearEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.ClearEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.ClearEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.ClearEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.ClearEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.ClearEditor.EVENT_REMOVE = "EVENT_REMOVE"; |
|
BI.ClearEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
BI.shortcut("bi.clear_editor", BI.ClearEditor);/** |
|
* 带标记的文本框 |
|
* Created by GUY on 2016/1/25. |
|
* @class BI.ShelterEditor |
|
* @extends BI.Widget |
|
*/ |
|
BI.ShelterEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.ShelterEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-shelter-editor", |
|
hgap: 4, |
|
vgap: 2, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: true, |
|
watermark: "", |
|
errorText: "", |
|
height: 24, |
|
textAlign: "left" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ShelterEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
value: o.value, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "shelter-editor-text", |
|
title: o.title, |
|
warningTitle: o.warningTitle, |
|
tipType: o.tipType, |
|
textAlign: o.textAlign, |
|
height: o.height, |
|
hgap: o.hgap |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.text, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.text.on(BI.Controller.EVENT_CHANGE, function () { |
|
arguments[2] = self; |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.text.on(BI.TextButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_CLICK_LABEL); |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_FOCUS, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_BLUR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_CLICK, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.ShelterEditor.EVENT_KEY_DOWN, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_VALID, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self._showHint(); |
|
self._checkText(); |
|
self.fireEvent(BI.ShelterEditor.EVENT_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self._showHint(); |
|
self._checkText(); |
|
self.fireEvent(BI.ShelterEditor.EVENT_CHANGE_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_START, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_PAUSE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_STOP, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_SPACE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self._checkText(); |
|
self.fireEvent(BI.ShelterEditor.EVENT_ERROR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_ENTER, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_RESTRICT, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.ShelterEditor.EVENT_EMPTY, arguments); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [this.editor] |
|
}); |
|
this._showHint(); |
|
self._checkText(); |
|
}, |
|
|
|
_checkText: function () { |
|
var o = this.options; |
|
if (this.editor.getValue() === "") { |
|
this.text.setValue(o.watermark || ""); |
|
this.text.element.addClass("bi-water-mark"); |
|
} else { |
|
this.text.setValue(this.editor.getValue()); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} |
|
BI.isKey(o.keyword) && this.text.doRedMark(o.keyword); |
|
}, |
|
|
|
_showInput: function () { |
|
this.editor.visible(); |
|
this.text.invisible(); |
|
}, |
|
|
|
_showHint: function () { |
|
this.editor.invisible(); |
|
this.text.visible(); |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
setTitle: function (title) { |
|
this.text.setTitle(title); |
|
}, |
|
|
|
setWarningTitle: function (title) { |
|
this.text.setWarningTitle(title); |
|
}, |
|
|
|
focus: function () { |
|
this._showInput(); |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
this._showHint(); |
|
this._checkText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.editor.setErrorText(text); |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.editor.getErrorText(); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
setTextStyle: function (style) { |
|
this.text.setStyle(style); |
|
}, |
|
|
|
setValue: function (k) { |
|
var o = this.options; |
|
this.editor.setValue(k); |
|
this._checkText(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getState: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setState: function (v) { |
|
this._showHint(); |
|
this.text.setValue(v); |
|
} |
|
}); |
|
BI.ShelterEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.ShelterEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.ShelterEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.ShelterEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.ShelterEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.ShelterEditor.EVENT_CLICK_LABEL = "EVENT_CLICK_LABEL"; |
|
|
|
BI.ShelterEditor.EVENT_START = "EVENT_START"; |
|
BI.ShelterEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.ShelterEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.ShelterEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.ShelterEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.ShelterEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.ShelterEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.ShelterEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.ShelterEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.ShelterEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.ShelterEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
|
|
BI.shortcut("bi.shelter_editor", BI.ShelterEditor); |
|
/** |
|
* 带标记的文本框 |
|
* Created by GUY on 2015/8/28. |
|
* @class BI.SignEditor |
|
* @extends BI.Widget |
|
*/ |
|
BI.SignEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.SignEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-sign-editor", |
|
hgap: 4, |
|
vgap: 2, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: true, |
|
watermark: "", |
|
errorText: "", |
|
height: 24 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SignEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
value: o.value, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "sign-editor-text", |
|
title: o.title, |
|
warningTitle: o.warningTitle, |
|
tipType: o.tipType, |
|
textAlign: "left", |
|
height: o.height, |
|
hgap: o.hgap, |
|
handler: function () { |
|
self._showInput(); |
|
self.editor.focus(); |
|
self.editor.selectAll(); |
|
} |
|
}); |
|
this.text.on(BI.TextButton.EVENT_CHANGE, function () { |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.SignEditor.EVENT_CLICK_LABEL); |
|
}); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.text, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_FOCUS, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_BLUR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_CLICK, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.SignEditor.EVENT_KEY_DOWN, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_VALID, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self._showHint(); |
|
self._checkText(); |
|
self.fireEvent(BI.SignEditor.EVENT_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self._showHint(); |
|
self._checkText(); |
|
self.fireEvent(BI.SignEditor.EVENT_CHANGE_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_START, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_PAUSE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_STOP, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_SPACE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self._checkText(); |
|
self.fireEvent(BI.SignEditor.EVENT_ERROR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_ENTER, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_RESTRICT, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.SignEditor.EVENT_EMPTY, arguments); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [this.editor] |
|
}); |
|
this._showHint(); |
|
self._checkText(); |
|
}, |
|
|
|
_checkText: function () { |
|
var o = this.options; |
|
BI.nextTick(BI.bind(function () { |
|
if (this.editor.getValue() === "") { |
|
this.text.setValue(o.watermark || ""); |
|
this.text.element.addClass("bi-water-mark"); |
|
} else { |
|
this.text.setValue(this.editor.getValue()); |
|
this.text.element.removeClass("bi-water-mark"); |
|
BI.isKey(o.keyword) && this.text.doRedMark(o.keyword); |
|
} |
|
}, this)); |
|
}, |
|
|
|
_showInput: function () { |
|
this.editor.visible(); |
|
this.text.invisible(); |
|
}, |
|
|
|
_showHint: function () { |
|
this.editor.invisible(); |
|
this.text.visible(); |
|
}, |
|
|
|
setTitle: function (title) { |
|
this.text.setTitle(title); |
|
}, |
|
|
|
setWarningTitle: function (title) { |
|
this.text.setWarningTitle(title); |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
focus: function () { |
|
this._showInput(); |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
this._showHint(); |
|
this._checkText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.editor.setErrorText(text); |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.editor.getErrorText(); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
setValue: function (k) { |
|
this.editor.setValue(k); |
|
this._checkText(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getState: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setState: function (v) { |
|
this._showHint(); |
|
this.text.setValue(v); |
|
} |
|
}); |
|
BI.SignEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SignEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SignEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SignEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.SignEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.SignEditor.EVENT_CLICK_LABEL = "EVENT_CLICK_LABEL"; |
|
|
|
BI.SignEditor.EVENT_START = "EVENT_START"; |
|
BI.SignEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SignEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.SignEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.SignEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.SignEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.SignEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.SignEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.SignEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.SignEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.SignEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
|
|
BI.shortcut("bi.sign_editor", BI.SignEditor);/** |
|
* guy |
|
* 记录状态的输入框 |
|
* @class BI.StateEditor |
|
* @extends BI.Single |
|
*/ |
|
BI.StateEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.StateEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-state-editor", |
|
hgap: 4, |
|
vgap: 2, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: true, |
|
watermark: "", |
|
errorText: "", |
|
height: 24, |
|
defaultText: "", // 默认显示值,默认显示值与显示值的区别是默认显示值标记灰色 |
|
text: BI.i18nText("BI-Basic_Unrestricted") // 显示值 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.StateEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
value: o.value, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "bi-water-mark tip-text-style", |
|
textAlign: "left", |
|
height: o.height, |
|
text: o.text, |
|
hgap: o.hgap, |
|
handler: function () { |
|
self._showInput(); |
|
self.editor.focus(); |
|
self.editor.setValue(""); |
|
}, |
|
title: BI.isNotNull(o.tipText) ? o.tipText : function () { |
|
var title = ""; |
|
if (BI.isString(self.stateValue)) { |
|
title = self.stateValue; |
|
} |
|
if (BI.isArray(self.stateValue) && self.stateValue.length === 1) { |
|
title = self.stateValue[0]; |
|
} |
|
return title; |
|
}, |
|
warningTitle: o.warningTitle, |
|
tipType: o.tipType |
|
}); |
|
this.text.on(BI.TextButton.EVENT_CHANGE, function () { |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.StateEditor.EVENT_CLICK_LABEL); |
|
}); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.text, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_FOCUS, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_BLUR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_CLICK, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.StateEditor.EVENT_KEY_DOWN, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_VALID, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self._showHint(); |
|
self.fireEvent(BI.StateEditor.EVENT_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self._showHint(); |
|
self.fireEvent(BI.StateEditor.EVENT_CHANGE_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_START, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_PAUSE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_STOP, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_SPACE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_ERROR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_ENTER, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_RESTRICT, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.StateEditor.EVENT_EMPTY, arguments); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [this.editor] |
|
}); |
|
this._showHint(); |
|
if (BI.isNotNull(o.text)) { |
|
this.setState(o.text); |
|
} |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
doRedMark: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
focus: function () { |
|
if (this.options.disabled === false) { |
|
this._showInput(); |
|
this.editor.focus(); |
|
} |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
this._showHint(); |
|
}, |
|
|
|
_showInput: function () { |
|
this.editor.visible(); |
|
this.text.invisible(); |
|
}, |
|
|
|
_showHint: function () { |
|
this.editor.invisible(); |
|
this.text.visible(); |
|
}, |
|
|
|
_setText: function (v) { |
|
this.text.setText(v); |
|
this.text.setTitle(v); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.editor.setErrorText(text); |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.editor.getErrorText(); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
setValue: function (k) { |
|
this.editor.setValue(k); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getState: function () { |
|
return this.editor.getValue().match(/[^\s]+/g); |
|
}, |
|
|
|
setState: function (v) { |
|
var o = this.options; |
|
BI.StateEditor.superclass.setValue.apply(this, arguments); |
|
this.stateValue = v; |
|
if (BI.isNumber(v)) { |
|
if (v === BI.Selection.All) { |
|
this._setText(BI.i18nText("BI-Select_All")); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} else if (v === BI.Selection.Multi) { |
|
this._setText(BI.i18nText("BI-Select_Part")); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} else { |
|
this._setText(BI.isKey(o.defaultText) ? o.defaultText : o.text); |
|
BI.isKey(o.defaultText) ? this.text.element.addClass("bi-water-mark") : this.text.element.removeClass("bi-water-mark"); |
|
} |
|
return; |
|
} |
|
if (BI.isString(v)) { |
|
this._setText(v); |
|
// 配置了defaultText才判断标灰,其他情况不标灰 |
|
(BI.isKey(o.defaultText) && o.defaultText === v) ? this.text.element.addClass("bi-water-mark") : this.text.element.removeClass("bi-water-mark"); |
|
return; |
|
} |
|
if (BI.isArray(v)) { |
|
if (BI.isEmpty(v)) { |
|
this._setText(BI.isKey(o.defaultText) ? o.defaultText : o.text); |
|
BI.isKey(o.defaultText) ? this.text.element.addClass("bi-water-mark") : this.text.element.removeClass("bi-water-mark"); |
|
} else if (v.length === 1) { |
|
this._setText(v[0]); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} else { |
|
this._setText(BI.i18nText("BI-Select_Part")); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} |
|
} |
|
}, |
|
|
|
setTipType: function (v) { |
|
this.text.options.tipType = v; |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.StateEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.StateEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.StateEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.StateEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.StateEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.StateEditor.EVENT_CLICK_LABEL = "EVENT_CLICK_LABEL"; |
|
|
|
BI.StateEditor.EVENT_START = "EVENT_START"; |
|
BI.StateEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.StateEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.StateEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.StateEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.StateEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.StateEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.StateEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.StateEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.StateEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.StateEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
|
|
BI.shortcut("bi.state_editor", BI.StateEditor); |
|
/** |
|
* 无限制-已选择状态输入框 |
|
* Created by GUY on 2016/5/18. |
|
* @class BI.SimpleStateEditor |
|
* @extends BI.Single |
|
*/ |
|
BI.SimpleStateEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.SimpleStateEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-simple-state-editor", |
|
hgap: 4, |
|
vgap: 2, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
mouseOut: false, |
|
allowBlank: true, |
|
watermark: "", |
|
errorText: "", |
|
height: 24, |
|
text: BI.i18nText("BI-Basic_Unrestricted") |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SimpleStateEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
value: o.value, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "bi-water-mark", |
|
textAlign: "left", |
|
text: o.text, |
|
height: o.height, |
|
hgap: o.hgap, |
|
handler: function () { |
|
self._showInput(); |
|
self.editor.focus(); |
|
self.editor.setValue(""); |
|
} |
|
}); |
|
this.text.on(BI.TextButton.EVENT_CHANGE, function () { |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_CLICK_LABEL); |
|
}); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.text, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_FOCUS, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_BLUR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_CLICK, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_KEY_DOWN, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_VALID, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self._showHint(); |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self._showHint(); |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_CHANGE_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_START, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_PAUSE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_STOP, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_SPACE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_ERROR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_ENTER, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_RESTRICT, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.SimpleStateEditor.EVENT_EMPTY, arguments); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [this.editor] |
|
}); |
|
this._showHint(); |
|
if(BI.isNotNull(o.text)){ |
|
this.setState(o.text); |
|
} |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
doRedMark: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
focus: function () { |
|
this._showInput(); |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
this._showHint(); |
|
}, |
|
|
|
_showInput: function () { |
|
this.editor.visible(); |
|
this.text.invisible(); |
|
}, |
|
|
|
_showHint: function () { |
|
this.editor.invisible(); |
|
this.text.visible(); |
|
}, |
|
|
|
_setText: function (v) { |
|
this.text.setText(v); |
|
this.text.setTitle(v); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.editor.setErrorText(text); |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.editor.getErrorText(); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
setValue: function (k) { |
|
this.editor.setValue(k); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getState: function () { |
|
return this.editor.getValue().match(/[^\s]+/g); |
|
}, |
|
|
|
setState: function (v) { |
|
var o = this.options; |
|
BI.SimpleStateEditor.superclass.setValue.apply(this, arguments); |
|
if (BI.isNumber(v)) { |
|
if (v === BI.Selection.All) { |
|
this._setText(BI.i18nText("BI-Already_Selected")); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} else if (v === BI.Selection.Multi) { |
|
this._setText(BI.i18nText("BI-Already_Selected")); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} else { |
|
this._setText(o.text); |
|
this.text.element.addClass("bi-water-mark"); |
|
} |
|
return; |
|
} |
|
if (!BI.isArray(v) || v.length === 1) { |
|
this._setText(v); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} else if (BI.isEmpty(v)) { |
|
this._setText(o.text); |
|
this.text.element.addClass("bi-water-mark"); |
|
} else { |
|
this._setText(BI.i18nText("BI-Already_Selected")); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
} |
|
}); |
|
BI.SimpleStateEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SimpleStateEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SimpleStateEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SimpleStateEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.SimpleStateEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.SimpleStateEditor.EVENT_CLICK_LABEL = "EVENT_CLICK_LABEL"; |
|
|
|
BI.SimpleStateEditor.EVENT_START = "EVENT_START"; |
|
BI.SimpleStateEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SimpleStateEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.SimpleStateEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.SimpleStateEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.SimpleStateEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.SimpleStateEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.SimpleStateEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.SimpleStateEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.SimpleStateEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.SimpleStateEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
|
|
BI.shortcut("bi.simple_state_editor", BI.SimpleStateEditor);/** |
|
* 下拉框弹出层的多选版本,toolbar带有若干按钮, zIndex在1000w |
|
* @class BI.MultiPopupView |
|
* @extends BI.Widget |
|
*/ |
|
|
|
BI.MultiPopupView = BI.inherit(BI.PopupView, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.MultiPopupView.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
_baseCls: (conf._baseCls || "") + " bi-multi-list-view", |
|
buttons: [BI.i18nText("BI-Basic_Sure")] |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiPopupView.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
_createToolBar: function () { |
|
var o = this.options, self = this; |
|
if (o.buttons.length === 0) { |
|
return; |
|
} |
|
|
|
var text = []; // 构造[{text:content},……] |
|
BI.each(o.buttons, function (idx, item) { |
|
text.push({ |
|
text: item, |
|
value: idx |
|
}); |
|
}); |
|
|
|
this.buttongroup = BI.createWidget({ |
|
type: "bi.button_group", |
|
cls: "list-view-toolbar bi-high-light bi-split-top", |
|
height: 24, |
|
items: BI.createItems(text, { |
|
type: "bi.text_button", |
|
once: false, |
|
shadow: true, |
|
isShadowShowingOnSelected: true |
|
}), |
|
layouts: [{ |
|
type: "bi.center", |
|
hgap: 0, |
|
vgap: 0 |
|
}] |
|
}); |
|
|
|
this.buttongroup.on(BI.ButtonGroup.EVENT_CHANGE, function (value, obj) { |
|
self.fireEvent(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, value, obj); |
|
}); |
|
|
|
return this.buttongroup; |
|
} |
|
|
|
}); |
|
|
|
BI.MultiPopupView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON = "EVENT_CLICK_TOOLBAR_BUTTON"; |
|
|
|
BI.shortcut("bi.multi_popup_view", BI.MultiPopupView);/** |
|
* 可以理解为MultiPopupView和Panel两个面板的结合体 |
|
* @class BI.PopupPanel |
|
* @extends BI.MultiPopupView |
|
*/ |
|
|
|
BI.PopupPanel = BI.inherit(BI.MultiPopupView, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.PopupPanel.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-popup-panel", |
|
title: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.PopupPanel.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
_createTool: function () { |
|
var self = this, o = this.options; |
|
var close = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "close-h-font", |
|
width: 25, |
|
height: 25 |
|
}); |
|
close.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self.setVisible(false); |
|
self.fireEvent(BI.PopupPanel.EVENT_CLOSE); |
|
}); |
|
return BI.createWidget({ |
|
type: "bi.htape", |
|
cls: "popup-panel-title bi-header-background", |
|
height: 25, |
|
items: [{ |
|
el: { |
|
type: "bi.label", |
|
textAlign: "left", |
|
text: o.title, |
|
height: 25, |
|
lgap: 10 |
|
} |
|
}, { |
|
el: close, |
|
width: 25 |
|
}] |
|
}); |
|
} |
|
}); |
|
|
|
BI.PopupPanel.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.PopupPanel.EVENT_CLOSE = "EVENT_CLOSE"; |
|
BI.PopupPanel.EVENT_CLICK_TOOLBAR_BUTTON = "EVENT_CLICK_TOOLBAR_BUTTON"; |
|
|
|
BI.shortcut("bi.popup_panel", BI.PopupPanel);/** |
|
* list面板 |
|
* |
|
* Created by GUY on 2015/10/30. |
|
* @class BI.ListPane |
|
* @extends BI.Pane |
|
*/ |
|
BI.ListPane = BI.inherit(BI.Pane, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.ListPane.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-list-pane", |
|
logic: { |
|
dynamic: true |
|
}, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
vgap: 0, |
|
hgap: 0, |
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
hasNext: BI.emptyFn, |
|
onLoaded: BI.emptyFn, |
|
el: { |
|
type: "bi.button_group" |
|
} |
|
}); |
|
}, |
|
_init: function () { |
|
BI.ListPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.button_group = BI.createWidget(o.el, { |
|
type: "bi.button_group", |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
behaviors: {}, |
|
items: o.items, |
|
itemsCreator: function (op, calback) { |
|
if (op.times === 1) { |
|
self.empty(); |
|
BI.nextTick(function () { |
|
self.loading(); |
|
}); |
|
} |
|
o.itemsCreator(op, function () { |
|
calback.apply(self, arguments); |
|
op.times === 1 && BI.nextTick(function () { |
|
self.loaded(); |
|
// callback可能在loading之前执行, check保证显示正确 |
|
self.check(); |
|
}); |
|
}); |
|
}, |
|
hasNext: o.hasNext, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
}); |
|
|
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.ListPane.EVENT_CHANGE, value, obj); |
|
} |
|
}); |
|
this.check(); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Top), BI.extend({ |
|
scrolly: true, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
vgap: o.vgap, |
|
hgap: o.hgap |
|
}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Top, this.button_group) |
|
})))); |
|
}, |
|
|
|
hasPrev: function () { |
|
return this.button_group.hasPrev && this.button_group.hasPrev(); |
|
}, |
|
|
|
hasNext: function () { |
|
return this.button_group.hasNext && this.button_group.hasNext(); |
|
}, |
|
|
|
prependItems: function (items) { |
|
this.options.items = items.concat(this.options.items); |
|
this.button_group.prependItems.apply(this.button_group, arguments); |
|
this.check(); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.options.items = this.options.items.concat(items); |
|
this.button_group.addItems.apply(this.button_group, arguments); |
|
this.check(); |
|
}, |
|
|
|
removeItemAt: function (indexes) { |
|
indexes = indexes || []; |
|
BI.removeAt(this.options.items, indexes); |
|
this.button_group.removeItemAt.apply(this.button_group, arguments); |
|
this.check(); |
|
}, |
|
|
|
populate: function (items) { |
|
var self = this, o = this.options; |
|
if (arguments.length === 0 && (BI.isFunction(this.button_group.attr("itemsCreator")))) {// 接管loader的populate方法 |
|
this.button_group.attr("itemsCreator").apply(this, [{times: 1}, function () { |
|
if (arguments.length === 0) { |
|
throw new Error("参数不能为空"); |
|
} |
|
self.populate.apply(self, arguments); |
|
}]); |
|
return; |
|
} |
|
BI.ListPane.superclass.populate.apply(this, arguments); |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.button_group.setNotSelectedValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.button_group.getNotSelectedValue(); |
|
}, |
|
|
|
setValue: function () { |
|
this.button_group.setValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.button_group.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.button_group.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.button_group.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.button_group.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.button_group.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.button_group.getNodeByValue(value); |
|
} |
|
}); |
|
BI.ListPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.list_pane", BI.ListPane);/** |
|
* 带有标题栏的pane |
|
* @class BI.Panel |
|
* @extends BI.Widget |
|
*/ |
|
BI.Panel = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Panel.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-panel bi-border", |
|
title: "", |
|
titleButtons: [], |
|
el: {}, |
|
logic: { |
|
dynamic: false |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.Panel.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("vertical", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("top", this._createTitle() |
|
, this.options.el) |
|
})))); |
|
}, |
|
|
|
_createTitle: function () { |
|
var self = this, o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "panel-title-text", |
|
text: o.title, |
|
height: 30 |
|
}); |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.button_group", |
|
items: o.titleButtons, |
|
layouts: [{ |
|
type: "bi.center_adapt", |
|
lgap: 10 |
|
}] |
|
}); |
|
|
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.button_group.on(BI.ButtonGroup.EVENT_CHANGE, function (value, obj) { |
|
self.fireEvent(BI.Panel.EVENT_CHANGE, value, obj); |
|
}); |
|
|
|
return { |
|
el: { |
|
type: "bi.left_right_vertical_adapt", |
|
cls: "panel-title bi-header-background bi-border-bottom", |
|
height: 29, |
|
items: { |
|
left: [this.text], |
|
right: [this.button_group] |
|
}, |
|
lhgap: 10, |
|
rhgap: 10 |
|
}, |
|
height: 29 |
|
}; |
|
}, |
|
|
|
setTitle: function (title) { |
|
this.text.setValue(title); |
|
} |
|
}); |
|
BI.Panel.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.panel", BI.Panel); |
|
BI.LinearSegmentButton = BI.inherit(BI.BasicButton, { |
|
|
|
props: { |
|
extraCls: "bi-line-segment-button bi-list-item-effect", |
|
once: true, |
|
readonly: true, |
|
hgap: 10, |
|
height: 25 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
|
|
return [{ |
|
type: "bi.label", |
|
text: o.text, |
|
height: o.height, |
|
value: o.value, |
|
hgap: o.hgap, |
|
ref: function () { |
|
self.text = this; |
|
} |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
cls: "line-segment-button-line", |
|
height: 2, |
|
ref: function () { |
|
self.line = this; |
|
} |
|
}, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}] |
|
}]; |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.LinearSegmentButton.superclass.setSelected.apply(this, arguments); |
|
if (v) { |
|
this.line.element.addClass("bi-high-light-background"); |
|
} else { |
|
this.line.element.removeClass("bi-high-light-background"); |
|
} |
|
}, |
|
|
|
setText: function (text) { |
|
this.text.setText(text); |
|
} |
|
}); |
|
BI.shortcut("bi.linear_segment_button", BI.LinearSegmentButton);BI.LinearSegment = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-linear-segment bi-split-bottom", |
|
items: [], |
|
height: 29 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.button_group", |
|
items: BI.createItems(o.items, { |
|
type: "bi.linear_segment_button", |
|
height: o.height - 1 |
|
}), |
|
layout: [{ |
|
type: "bi.center" |
|
}], |
|
listeners: [{ |
|
eventName: "__EVENT_CHANGE__", |
|
action: function () { |
|
self.fireEvent("__EVENT_CHANGE__", arguments); |
|
} |
|
}, { |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}], |
|
ref: function () { |
|
self.buttonGroup = this; |
|
} |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.buttonGroup.setValue(v); |
|
}, |
|
|
|
setEnabledValue: function (v) { |
|
this.buttonGroup.setEnabledValue(v); |
|
}, |
|
|
|
|
|
getValue: function () { |
|
return this.buttonGroup.getValue(); |
|
} |
|
}); |
|
BI.shortcut("bi.linear_segment", BI.LinearSegment);/** |
|
* 选择列表 |
|
* |
|
* Created by GUY on 2015/11/1. |
|
* @class BI.SelectList |
|
* @extends BI.Widget |
|
*/ |
|
BI.SelectList = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SelectList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-list", |
|
direction: BI.Direction.Top, // toolbar的位置 |
|
logic: { |
|
dynamic: true |
|
}, |
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
hasNext: BI.emptyFn, |
|
onLoaded: BI.emptyFn, |
|
toolbar: { |
|
type: "bi.multi_select_bar", |
|
iconWrapperWidth: 36 |
|
}, |
|
el: { |
|
type: "bi.list_pane" |
|
} |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SelectList.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
// 全选 |
|
this.toolbar = BI.createWidget(o.toolbar); |
|
this.allSelected = false; |
|
this.toolbar.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.allSelected = this.isSelected(); |
|
if (type === BI.Events.CLICK) { |
|
self.setAllSelected(self.allSelected); |
|
self.fireEvent(BI.SelectList.EVENT_CHANGE, value, obj); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.list = BI.createWidget(o.el, { |
|
type: "bi.list_pane", |
|
items: o.items, |
|
itemsCreator: function (op, callback) { |
|
op.times === 1 && self.toolbar.setVisible(false); |
|
o.itemsCreator(op, function (items) { |
|
callback.apply(self, arguments); |
|
if (op.times === 1) { |
|
self.toolbar.setVisible(items && items.length > 0); |
|
self.toolbar.setEnable(self.isEnabled() && items && items.length > 0); |
|
} |
|
self._checkAllSelected(); |
|
}); |
|
}, |
|
onLoaded: o.onLoaded, |
|
hasNext: o.hasNext |
|
}); |
|
|
|
this.list.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (type === BI.Events.CLICK) { |
|
self._checkAllSelected(); |
|
self.fireEvent(BI.SelectList.EVENT_CHANGE, value, obj); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({ |
|
scrolly: true |
|
}, o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.toolbar, this.list) |
|
})))); |
|
|
|
if (o.items.length <= 0) { |
|
this.toolbar.setVisible(false); |
|
this.toolbar.setEnable(false); |
|
} |
|
if(BI.isNotNull(o.value)){ |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_checkAllSelected: function () { |
|
var selectLength = this.list.getValue().length; |
|
var notSelectLength = this.getAllLeaves().length - selectLength; |
|
var hasNext = this.list.hasNext(); |
|
var isAlreadyAllSelected = this.toolbar.isSelected(); |
|
var isHalf = selectLength > 0 && (notSelectLength > 0 || (!isAlreadyAllSelected && hasNext)); |
|
isHalf = isHalf || (notSelectLength > 0 && hasNext && isAlreadyAllSelected); |
|
this.toolbar.setHalfSelected(isHalf); |
|
!isHalf && this.toolbar.setSelected(selectLength > 0 && notSelectLength <= 0 && (!hasNext || isAlreadyAllSelected)); |
|
}, |
|
|
|
setAllSelected: function (v) { |
|
BI.each(this.getAllButtons(), function (i, btn) { |
|
(btn.setSelected || btn.setAllSelected).apply(btn, [v]); |
|
}); |
|
this.allSelected = !!v; |
|
this.toolbar.setSelected(v); |
|
this.toolbar.setHalfSelected(false); |
|
}, |
|
|
|
setToolBarVisible: function (b) { |
|
this.toolbar.setVisible(b); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.allSelected; |
|
// return this.toolbar.isSelected(); |
|
}, |
|
|
|
hasPrev: function () { |
|
return this.list.hasPrev(); |
|
}, |
|
|
|
hasNext: function () { |
|
return this.list.hasNext(); |
|
}, |
|
|
|
prependItems: function (items) { |
|
this.list.prependItems.apply(this.list, arguments); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.list.addItems.apply(this.list, arguments); |
|
}, |
|
|
|
setValue: function (data) { |
|
var selectAll = data.type === BI.ButtonGroup.CHOOSE_TYPE_ALL; |
|
this.setAllSelected(selectAll); |
|
this.list[selectAll ? "setNotSelectedValue" : "setValue"](data.value); |
|
this._checkAllSelected(); |
|
}, |
|
|
|
getValue: function () { |
|
if (this.isAllSelected() === false) { |
|
return { |
|
type: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
value: this.list.getValue(), |
|
assist: this.list.getNotSelectedValue() |
|
}; |
|
} |
|
return { |
|
type: BI.ButtonGroup.CHOOSE_TYPE_ALL, |
|
value: this.list.getNotSelectedValue(), |
|
assist: this.list.getValue() |
|
}; |
|
|
|
}, |
|
|
|
empty: function () { |
|
this.list.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.toolbar.setVisible(!BI.isEmptyArray(items)); |
|
this.toolbar.setEnable(this.isEnabled() && !BI.isEmptyArray(items)); |
|
this.list.populate.apply(this.list, arguments); |
|
this._checkAllSelected(); |
|
}, |
|
|
|
_setEnable: function (enable) { |
|
BI.SelectList.superclass._setEnable.apply(this, arguments); |
|
this.toolbar.setEnable(enable); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
var toolHeight = ( this.toolbar.element.outerHeight() || 25) * ( this.toolbar.isVisible() ? 1 : 0); |
|
this.list.resetHeight ? this.list.resetHeight(h - toolHeight) : |
|
this.list.element.css({"max-height": h - toolHeight + "px"}); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.list.setNotSelectedValue.apply(this.list, arguments); |
|
this._checkAllSelected(); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.list.getNotSelectedValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.list.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.list.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.list.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.list.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.list.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.list.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.list.getNodeByValue(value); |
|
} |
|
}); |
|
BI.SelectList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.select_list", BI.SelectList);/** |
|
* Created by roy on 15/11/6. |
|
*/ |
|
BI.LazyLoader = BI.inherit(BI.Widget, { |
|
_const: { |
|
PAGE: 100 |
|
}, |
|
_defaultConfig: function () { |
|
return BI.extend(BI.LazyLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-lazy-loader", |
|
el: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
var self = this, o = this.options; |
|
BI.LazyLoader.superclass._init.apply(this, arguments); |
|
var all = o.items.length; |
|
this.loader = BI.createWidget({ |
|
type: "bi.loader", |
|
element: this, |
|
// 下面是button_group的属性 |
|
el: o.el, |
|
|
|
itemsCreator: function (options, populate) { |
|
populate(self._getNextItems(options)); |
|
}, |
|
hasNext: function (option) { |
|
return option.count < all; |
|
} |
|
}); |
|
|
|
this.loader.on(BI.Loader.EVENT_CHANGE, function (obj) { |
|
self.fireEvent(BI.LazyLoader.EVENT_CHANGE, obj); |
|
}); |
|
}, |
|
_getNextItems: function (options) { |
|
var self = this, o = this.options; |
|
var lastNum = o.items.length - this._const.PAGE * (options.times - 1); |
|
var lastItems = BI.takeRight(o.items, lastNum); |
|
var nextItems = BI.take(lastItems, this._const.PAGE); |
|
return nextItems; |
|
}, |
|
|
|
populate: function (items) { |
|
this.loader.populate(items); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.loader.addItems(items); |
|
}, |
|
|
|
empty: function () { |
|
this.loader.empty(); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.loader.setNotSelectedValue.apply(this.loader, arguments); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.loader.getNotSelectedValue(); |
|
}, |
|
|
|
setValue: function () { |
|
this.loader.setValue.apply(this.loader, arguments); |
|
}, |
|
|
|
getValue: function () { |
|
return this.loader.getValue.apply(this.loader, arguments); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.loader.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.loader.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.loader.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.loader.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.loader.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.loader.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.loader.getNodeByValue(value); |
|
} |
|
}); |
|
BI.LazyLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.lazy_loader", BI.LazyLoader);/** |
|
* 恶心的加载控件, 为解决排序问题引入的控件 |
|
* |
|
* Created by GUY on 2015/11/12. |
|
* @class BI.ListLoader |
|
* @extends BI.Widget |
|
*/ |
|
BI.ListLoader = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.ListLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-list-loader", |
|
|
|
isDefaultInit: true, // 是否默认初始化数据 |
|
|
|
// 下面是button_group的属性 |
|
el: { |
|
type: "bi.button_group" |
|
}, |
|
|
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn, |
|
|
|
// 下面是分页信息 |
|
count: false, |
|
next: {}, |
|
hasNext: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_nextLoad: function () { |
|
var self = this, o = this.options; |
|
this.next.setLoading(); |
|
o.itemsCreator.apply(this, [{times: ++this.times}, function () { |
|
self.next.setLoaded(); |
|
self.addItems.apply(self, arguments); |
|
}]); |
|
}, |
|
|
|
_init: function () { |
|
BI.ListLoader.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (o.itemsCreator === false) { |
|
o.next = false; |
|
} |
|
|
|
this.button_group = BI.createWidget(o.el, { |
|
type: "bi.button_group", |
|
element: this, |
|
chooseType: 0, |
|
items: o.items, |
|
behaviors: {}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.ListLoader.EVENT_CHANGE, obj); |
|
} |
|
}); |
|
|
|
if (o.next !== false) { |
|
this.next = BI.createWidget(BI.extend({ |
|
type: "bi.loading_bar" |
|
}, o.next)); |
|
this.next.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self._nextLoad(); |
|
} |
|
}); |
|
} |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
items: [this.next] |
|
}); |
|
|
|
o.isDefaultInit && BI.isEmpty(o.items) && BI.nextTick(BI.bind(function () { |
|
this.populate(); |
|
}, this)); |
|
if (BI.isNotEmptyArray(o.items)) { |
|
this.populate(o.items); |
|
} |
|
}, |
|
|
|
hasNext: function () { |
|
var o = this.options; |
|
if (BI.isNumber(o.count)) { |
|
return this.count < o.count; |
|
} |
|
return !!o.hasNext.apply(this, [{ |
|
times: this.times, |
|
count: this.count |
|
}]); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.count += items.length; |
|
if (BI.isObject(this.next)) { |
|
this.options.items = this.options.items.concat(items); |
|
if (this.hasNext()) { |
|
this.next.setLoaded(); |
|
} else { |
|
this.next.setEnd(); |
|
} |
|
} |
|
this.button_group.addItems.apply(this.button_group, arguments); |
|
this.next.element.appendTo(this.element); |
|
}, |
|
|
|
populate: function (items) { |
|
var self = this, o = this.options; |
|
if (arguments.length === 0 && (BI.isFunction(o.itemsCreator))) { |
|
o.itemsCreator.apply(this, [{times: 1}, function () { |
|
if (arguments.length === 0) { |
|
throw new Error("参数不能为空"); |
|
} |
|
self.populate.apply(self, arguments); |
|
o.onLoaded(); |
|
}]); |
|
return; |
|
} |
|
this.options.items = items; |
|
this.times = 1; |
|
this.count = 0; |
|
this.count += items.length; |
|
if (BI.isObject(this.next)) { |
|
if (this.hasNext()) { |
|
this.next.setLoaded(); |
|
} else { |
|
this.next.invisible(); |
|
} |
|
} |
|
BI.DOM.hang([this.next]); |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
this.next.element.appendTo(this.element); |
|
}, |
|
|
|
empty: function () { |
|
BI.DOM.hang([this.next]); |
|
this.button_group.empty(); |
|
this.next.element.appendTo(this.element); |
|
BI.each([this.next], function (i, ob) { |
|
ob && ob.setVisible(false); |
|
}); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.button_group.setNotSelectedValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.button_group.getNotSelectedValue(); |
|
}, |
|
|
|
setValue: function () { |
|
this.button_group.setValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue.apply(this.button_group, arguments); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.button_group.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.button_group.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.button_group.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.button_group.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.button_group.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.button_group.getNodeByValue(value); |
|
} |
|
}); |
|
BI.ListLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.list_loader", BI.ListLoader);/** |
|
* Created by GUY on 2016/4/29. |
|
* |
|
* @class BI.SortList |
|
* @extends BI.Widget |
|
*/ |
|
BI.SortList = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SortList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-sort-list", |
|
|
|
isDefaultInit: true, // 是否默认初始化数据 |
|
|
|
// 下面是button_group的属性 |
|
el: { |
|
type: "bi.button_group" |
|
}, |
|
|
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn, |
|
|
|
// 下面是分页信息 |
|
count: false, |
|
next: {}, |
|
hasNext: BI.emptyFn |
|
|
|
// containment: this.element, |
|
// connectWith: ".bi-sort-list", |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SortList.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.loader = BI.createWidget({ |
|
type: "bi.list_loader", |
|
element: this, |
|
isDefaultInit: o.isDefaultInit, |
|
el: o.el, |
|
items: this._formatItems(o.items), |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator(op, function (items) { |
|
callback(self._formatItems(items)); |
|
}); |
|
}, |
|
onLoaded: o.onLoaded, |
|
count: o.count, |
|
next: o.next, |
|
hasNext: o.hasNext |
|
}); |
|
this.loader.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.SortList.EVENT_CHANGE, value, obj); |
|
} |
|
}); |
|
|
|
this.loader.element.sortable({ |
|
containment: o.containment || this.element, |
|
connectWith: o.connectWith || ".bi-sort-list", |
|
items: ".sort-item", |
|
cursor: o.cursor || "drag", |
|
tolerance: o.tolerance || "intersect", |
|
placeholder: { |
|
element: function ($currentItem) { |
|
var holder = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "bi-sortable-holder", |
|
height: $currentItem.outerHeight() |
|
}); |
|
holder.element.css({ |
|
"margin-left": $currentItem.css("margin-left"), |
|
"margin-right": $currentItem.css("margin-right"), |
|
"margin-top": $currentItem.css("margin-top"), |
|
"margin-bottom": $currentItem.css("margin-bottom"), |
|
margin: $currentItem.css("margin") |
|
}); |
|
return holder.element; |
|
}, |
|
update: function () { |
|
|
|
} |
|
}, |
|
start: function (event, ui) { |
|
|
|
}, |
|
stop: function (event, ui) { |
|
self.fireEvent(BI.SortList.EVENT_CHANGE); |
|
}, |
|
over: function (event, ui) { |
|
|
|
} |
|
}); |
|
}, |
|
|
|
_formatItems: function (items) { |
|
BI.each(items, function (i, item) { |
|
item = BI.stripEL(item); |
|
item.cls = item.cls ? item.cls + " sort-item" : "sort-item"; |
|
item.attributes = { |
|
sorted: item.value |
|
}; |
|
}); |
|
return items; |
|
}, |
|
|
|
hasNext: function () { |
|
return this.loader.hasNext(); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.loader.addItems(items); |
|
}, |
|
|
|
populate: function (items) { |
|
if (items) { |
|
arguments[0] = this._formatItems(items); |
|
} |
|
this.loader.populate.apply(this.loader, arguments); |
|
}, |
|
|
|
empty: function () { |
|
this.loader.empty(); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.loader.setNotSelectedValue.apply(this.loader, arguments); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.loader.getNotSelectedValue(); |
|
}, |
|
|
|
setValue: function () { |
|
this.loader.setValue.apply(this.loader, arguments); |
|
}, |
|
|
|
getValue: function () { |
|
return this.loader.getValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.loader.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.loader.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.loader.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.loader.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.loader.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.loader.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.loader.getNodeByValue(value); |
|
}, |
|
|
|
getSortedValues: function () { |
|
return this.loader.element.sortable("toArray", {attribute: "sorted"}); |
|
} |
|
}); |
|
BI.SortList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.sort_list", BI.SortList); |
|
/** |
|
* author: young |
|
* createdDate: 2018/12/18 |
|
* description: |
|
*/ |
|
BI.LoadingPane = BI.inherit(BI.Pane, { |
|
_mount: function () { |
|
var isMounted = BI.Pane.superclass._mount.apply(this, arguments); |
|
if (isMounted) { |
|
if (this.beforeInit) { |
|
this.__asking = true; |
|
this.loading(); |
|
this.beforeInit(BI.bind(this.__loaded, this)); |
|
} |
|
} |
|
}, |
|
|
|
_initRender: function () { |
|
if (this.beforeInit) { |
|
this.__async = true; |
|
} else { |
|
this._render(); |
|
} |
|
}, |
|
|
|
__loaded: function () { |
|
this.__asking = false; |
|
this.loaded(); |
|
this._render(); |
|
} |
|
});/** |
|
* 有总页数和总行数的分页控件 |
|
* Created by Young's on 2016/10/13. |
|
*/ |
|
BI.AllCountPager = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.AllCountPager.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-all-count-pager", |
|
pagerDirection: "vertical", // 翻页按钮方向,可选值:vertical/horizontal |
|
height: 24, |
|
pages: 1, // 必选项 |
|
curr: 1, // 初始化当前页, pages为数字时可用, |
|
count: 1 // 总行数 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.AllCountPager.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, pagerIconCls = this._getPagerIconCls(); |
|
this.editor = BI.createWidget({ |
|
type: "bi.small_text_editor", |
|
cls: "pager-editor bi-border-radius", |
|
validationChecker: function (v) { |
|
return (self.rowCount.getValue() === 0 && v === "0") || BI.isPositiveInteger(v); |
|
}, |
|
hgap: 4, |
|
vgap: 0, |
|
value: o.curr, |
|
errorText: BI.i18nText("BI-Please_Input_Positive_Integer"), |
|
width: 40, |
|
height: 24, |
|
invisible: o.pages <= 1 |
|
}); |
|
|
|
this.pager = BI.createWidget({ |
|
type: "bi.pager", |
|
width: 58, |
|
layouts: [{ |
|
type: "bi.horizontal", |
|
lgap: 5 |
|
}], |
|
|
|
dynamicShow: false, |
|
pages: o.pages, |
|
curr: o.curr, |
|
groups: 0, |
|
|
|
first: false, |
|
last: false, |
|
prev: { |
|
type: "bi.icon_button", |
|
value: "prev", |
|
title: BI.i18nText("BI-Previous_Page"), |
|
warningTitle: BI.i18nText("BI-Current_Is_First_Page"), |
|
height: 22, |
|
width: 22, |
|
cls: "bi-border bi-border-radius all-pager-prev bi-list-item-select2 " + pagerIconCls.preCls |
|
}, |
|
next: { |
|
type: "bi.icon_button", |
|
value: "next", |
|
title: BI.i18nText("BI-Next_Page"), |
|
warningTitle: BI.i18nText("BI-Current_Is_Last_Page"), |
|
height: 22, |
|
width: 22, |
|
cls: "bi-border bi-border-radius all-pager-next bi-list-item-select2 " + pagerIconCls.nextCls |
|
}, |
|
|
|
hasPrev: o.hasPrev, |
|
hasNext: o.hasNext, |
|
firstPage: o.firstPage, |
|
lastPage: o.lastPage, |
|
invisible: o.pages <= 1 |
|
}); |
|
|
|
this.editor.on(BI.TextEditor.EVENT_CONFIRM, function () { |
|
self.pager.setValue(BI.parseInt(self.editor.getValue())); |
|
self.fireEvent(BI.AllCountPager.EVENT_CHANGE); |
|
}); |
|
this.pager.on(BI.Pager.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.AllCountPager.EVENT_CHANGE); |
|
}); |
|
this.pager.on(BI.Pager.EVENT_AFTER_POPULATE, function () { |
|
self.editor.setValue(self.pager.getCurrentPage()); |
|
}); |
|
|
|
this.allPages = BI.createWidget({ |
|
type: "bi.label", |
|
title: o.pages, |
|
text: "/" + o.pages, |
|
lgap: 5, |
|
invisible: o.pages <= 1 |
|
}); |
|
|
|
this.rowCount = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "row-count", |
|
height: o.height, |
|
hgap: 5, |
|
text: o.count, |
|
title: o.count |
|
}); |
|
|
|
var count = BI.createWidget({ |
|
type: "bi.left", |
|
height: o.height, |
|
scrollable: false, |
|
items: [{ |
|
type: "bi.label", |
|
height: o.height, |
|
text: BI.i18nText("BI-Basic_Total"), |
|
width: 15 |
|
}, this.rowCount, { |
|
type: "bi.label", |
|
height: o.height, |
|
text: BI.i18nText("BI-Tiao_Data"), |
|
width: 50, |
|
textAlign: "left" |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.left_right_vertical_adapt", |
|
element: this, |
|
items: { |
|
left: [count], |
|
right: [this.editor, this.allPages, this.pager] |
|
} |
|
}); |
|
}, |
|
|
|
alwaysShowPager: true, |
|
|
|
_getPagerIconCls: function () { |
|
var o = this.options; |
|
switch (o.pagerDirection) { |
|
case "horizontal": |
|
return { |
|
preCls: "row-pre-page-h-font ", |
|
nextCls: "row-next-page-h-font " |
|
}; |
|
case "vertical": |
|
default: |
|
return { |
|
preCls: "column-pre-page-h-font ", |
|
nextCls: "column-next-page-h-font " |
|
}; |
|
} |
|
}, |
|
|
|
setAllPages: function (v) { |
|
this.allPages.setText("/" + v); |
|
this.allPages.setTitle(v); |
|
this.options.pages = v; |
|
this.pager.setAllPages(v); |
|
this.editor.setEnable(v >= 1); |
|
this.setPagerVisible(v > 1); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.pager.setValue(v); |
|
}, |
|
|
|
setVPage: function (v) { |
|
this.pager.setValue(v); |
|
}, |
|
|
|
setCount: function (count) { |
|
this.rowCount.setText(count); |
|
this.rowCount.setTitle(count); |
|
}, |
|
|
|
getCurrentPage: function () { |
|
return this.pager.getCurrentPage(); |
|
}, |
|
|
|
hasPrev: function () { |
|
return this.pager.hasPrev(); |
|
}, |
|
|
|
hasNext: function () { |
|
return this.pager.hasNext(); |
|
}, |
|
|
|
setPagerVisible: function (b) { |
|
this.editor.setVisible(b); |
|
this.allPages.setVisible(b); |
|
this.pager.setVisible(b); |
|
}, |
|
|
|
populate: function () { |
|
this.pager.populate(); |
|
this.setPagerVisible(this.options.pages > 1); |
|
} |
|
}); |
|
BI.AllCountPager.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.all_count_pager", BI.AllCountPager);/** |
|
* 显示页码的分页控件 |
|
* |
|
* Created by GUY on 2016/6/30. |
|
* @class BI.DirectionPager |
|
* @extends BI.Widget |
|
*/ |
|
BI.DirectionPager = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.DirectionPager.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-direction-pager", |
|
height: 24, |
|
horizontal: { |
|
pages: false, // 总页数 |
|
curr: 1, // 初始化当前页, pages为数字时可用 |
|
|
|
hasPrev: BI.emptyFn, |
|
hasNext: BI.emptyFn, |
|
firstPage: 1, |
|
lastPage: BI.emptyFn |
|
}, |
|
vertical: { |
|
pages: false, // 总页数 |
|
curr: 1, // 初始化当前页, pages为数字时可用 |
|
|
|
hasPrev: BI.emptyFn, |
|
hasNext: BI.emptyFn, |
|
firstPage: 1, |
|
lastPage: BI.emptyFn |
|
} |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DirectionPager.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var v = o.vertical, h = o.horizontal; |
|
this._createVPager(); |
|
this._createHPager(); |
|
this.layout = BI.createWidget({ |
|
type: "bi.absolute", |
|
scrollable: false, |
|
element: this, |
|
items: [{ |
|
el: this.vpager, |
|
top: 0, |
|
right: 86 |
|
}, { |
|
el: this.vlabel, |
|
top: 0, |
|
right: 110 |
|
}, { |
|
el: this.hpager, |
|
top: 0, |
|
right: 0 |
|
}, { |
|
el: this.hlabel, |
|
top: 0, |
|
right: 24 |
|
}] |
|
}); |
|
}, |
|
|
|
_createVPager: function () { |
|
var self = this, o = this.options; |
|
var v = o.vertical; |
|
this.vlabel = BI.createWidget({ |
|
type: "bi.label", |
|
width: 24, |
|
height: 24, |
|
value: v.curr, |
|
title: v.curr, |
|
invisible: true |
|
}); |
|
this.vpager = BI.createWidget({ |
|
type: "bi.pager", |
|
width: 72, |
|
layouts: [{ |
|
type: "bi.horizontal", |
|
scrollx: false, |
|
rgap: 24 |
|
}], |
|
invisible: true, |
|
|
|
dynamicShow: false, |
|
pages: v.pages, |
|
curr: v.curr, |
|
groups: 0, |
|
|
|
first: false, |
|
last: false, |
|
prev: { |
|
type: "bi.icon_button", |
|
value: "prev", |
|
title: BI.i18nText("BI-Up_Page"), |
|
warningTitle: BI.i18nText("BI-Current_Is_First_Page"), |
|
height: 22, |
|
width: 22, |
|
cls: "bi-border bi-border-radius direction-pager-prev column-pre-page-h-font bi-list-item-select2" |
|
}, |
|
next: { |
|
type: "bi.icon_button", |
|
value: "next", |
|
title: BI.i18nText("BI-Down_Page"), |
|
warningTitle: BI.i18nText("BI-Current_Is_Last_Page"), |
|
height: 22, |
|
width: 22, |
|
cls: "bi-border bi-border-radius direction-pager-next column-next-page-h-font bi-list-item-select2" |
|
}, |
|
|
|
hasPrev: v.hasPrev, |
|
hasNext: v.hasNext, |
|
firstPage: v.firstPage, |
|
lastPage: v.lastPage |
|
}); |
|
|
|
this.vpager.on(BI.Pager.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DirectionPager.EVENT_CHANGE); |
|
}); |
|
this.vpager.on(BI.Pager.EVENT_AFTER_POPULATE, function () { |
|
self.vlabel.setValue(this.getCurrentPage()); |
|
self.vlabel.setTitle(this.getCurrentPage()); |
|
}); |
|
}, |
|
|
|
_createHPager: function () { |
|
var self = this, o = this.options; |
|
var h = o.horizontal; |
|
this.hlabel = BI.createWidget({ |
|
type: "bi.label", |
|
width: 24, |
|
height: 24, |
|
value: h.curr, |
|
title: h.curr, |
|
invisible: true |
|
}); |
|
this.hpager = BI.createWidget({ |
|
type: "bi.pager", |
|
width: 72, |
|
layouts: [{ |
|
type: "bi.horizontal", |
|
scrollx: false, |
|
rgap: 24 |
|
}], |
|
invisible: true, |
|
|
|
dynamicShow: false, |
|
pages: h.pages, |
|
curr: h.curr, |
|
groups: 0, |
|
|
|
first: false, |
|
last: false, |
|
prev: { |
|
type: "bi.icon_button", |
|
value: "prev", |
|
title: BI.i18nText("BI-Left_Page"), |
|
warningTitle: BI.i18nText("BI-Current_Is_First_Page"), |
|
height: 22, |
|
width: 22, |
|
cls: "bi-border bi-border-radius direction-pager-prev row-pre-page-h-font bi-list-item-select2" |
|
}, |
|
next: { |
|
type: "bi.icon_button", |
|
value: "next", |
|
title: BI.i18nText("BI-Right_Page"), |
|
warningTitle: BI.i18nText("BI-Current_Is_Last_Page"), |
|
height: 22, |
|
width: 22, |
|
cls: "bi-border bi-border-radius direction-pager-next row-next-page-h-font bi-list-item-select2" |
|
}, |
|
|
|
hasPrev: h.hasPrev, |
|
hasNext: h.hasNext, |
|
firstPage: h.firstPage, |
|
lastPage: h.lastPage |
|
}); |
|
|
|
this.hpager.on(BI.Pager.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DirectionPager.EVENT_CHANGE); |
|
}); |
|
this.hpager.on(BI.Pager.EVENT_AFTER_POPULATE, function () { |
|
self.hlabel.setValue(this.getCurrentPage()); |
|
self.hlabel.setTitle(this.getCurrentPage()); |
|
}); |
|
}, |
|
|
|
getVPage: function () { |
|
return this.vpager.getCurrentPage(); |
|
}, |
|
|
|
getHPage: function () { |
|
return this.hpager.getCurrentPage(); |
|
}, |
|
|
|
setVPage: function (v) { |
|
this.vpager.setValue(v); |
|
this.vlabel.setValue(v); |
|
this.vlabel.setTitle(v); |
|
}, |
|
|
|
setHPage: function (v) { |
|
this.hpager.setValue(v); |
|
this.hlabel.setValue(v); |
|
this.hlabel.setTitle(v); |
|
}, |
|
|
|
hasVNext: function () { |
|
return this.vpager.hasNext(); |
|
}, |
|
|
|
hasHNext: function () { |
|
return this.hpager.hasNext(); |
|
}, |
|
|
|
hasVPrev: function () { |
|
return this.vpager.hasPrev(); |
|
}, |
|
|
|
hasHPrev: function () { |
|
return this.hpager.hasPrev(); |
|
}, |
|
|
|
setHPagerVisible: function (b) { |
|
this.hpager.setVisible(b); |
|
this.hlabel.setVisible(b); |
|
}, |
|
|
|
setVPagerVisible: function (b) { |
|
this.vpager.setVisible(b); |
|
this.vlabel.setVisible(b); |
|
}, |
|
|
|
populate: function () { |
|
this.vpager.populate(); |
|
this.hpager.populate(); |
|
var vShow = false, hShow = false; |
|
if (!this.hasHNext() && !this.hasHPrev()) { |
|
this.setHPagerVisible(false); |
|
} else { |
|
this.setHPagerVisible(true); |
|
hShow = true; |
|
} |
|
if (!this.hasVNext() && !this.hasVPrev()) { |
|
this.setVPagerVisible(false); |
|
} else { |
|
this.setVPagerVisible(true); |
|
vShow = true; |
|
} |
|
this.setVisible(hShow || vShow); |
|
var num = [86, 110, 0, 24]; |
|
var items = this.layout.attr("items"); |
|
|
|
if (vShow === true && hShow === true) { |
|
items[0].right = num[0]; |
|
items[1].right = num[1]; |
|
items[2].right = num[2]; |
|
items[3].right = num[3]; |
|
} else if (vShow === true) { |
|
items[0].right = num[2]; |
|
items[1].right = num[3]; |
|
} else if (hShow === true) { |
|
items[2].right = num[2]; |
|
items[3].right = num[3]; |
|
} |
|
this.layout.attr("items", items); |
|
this.layout.resize(); |
|
}, |
|
|
|
clear: function () { |
|
this.vpager.attr("curr", 1); |
|
this.hpager.attr("curr", 1); |
|
} |
|
}); |
|
BI.DirectionPager.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.direction_pager", BI.DirectionPager);/** |
|
* 分页控件 |
|
* |
|
* Created by GUY on 2015/8/31. |
|
* @class BI.DetailPager |
|
* @extends BI.Widget |
|
*/ |
|
BI.DetailPager = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.DetailPager.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-detail-pager", |
|
behaviors: {}, |
|
layouts: [{ |
|
type: "bi.horizontal", |
|
hgap: 10, |
|
vgap: 0 |
|
}], |
|
|
|
dynamicShow: true, // 是否动态显示上一页、下一页、首页、尾页, 若为false,则指对其设置使能状态 |
|
// dynamicShow为false时以下两个有用 |
|
dynamicShowFirstLast: false, // 是否动态显示首页、尾页 |
|
dynamicShowPrevNext: false, // 是否动态显示上一页、下一页 |
|
pages: false, // 总页数 |
|
curr: function () { |
|
return 1; |
|
}, // 初始化当前页 |
|
groups: 0, // 连续显示分页数 |
|
jump: BI.emptyFn, // 分页的回调函数 |
|
|
|
first: false, // 是否显示首页 |
|
last: false, // 是否显示尾页 |
|
prev: "上一页", |
|
next: "下一页", |
|
|
|
firstPage: 1, |
|
lastPage: function () { // 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法 |
|
return 1; |
|
}, |
|
hasPrev: BI.emptyFn, // pages不可用时有效 |
|
hasNext: BI.emptyFn // pages不可用时有效 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DetailPager.superclass._init.apply(this, arguments); |
|
var self = this; |
|
this.currPage = BI.result(this.options, "curr"); |
|
// 翻页太灵敏 |
|
this._lock = false; |
|
this._debouce = BI.debounce(function () { |
|
self._lock = false; |
|
}, 300); |
|
this._populate(); |
|
}, |
|
|
|
_populate: function () { |
|
var self = this, o = this.options, view = [], dict = {}; |
|
this.empty(); |
|
var pages = BI.result(o, "pages"); |
|
var curr = BI.result(this, "currPage"); |
|
var groups = BI.result(o, "groups"); |
|
var first = BI.result(o, "first"); |
|
var last = BI.result(o, "last"); |
|
var prev = BI.result(o, "prev"); |
|
var next = BI.result(o, "next"); |
|
|
|
if (pages === false) { |
|
groups = 0; |
|
first = false; |
|
last = false; |
|
} else { |
|
groups > pages && (groups = pages); |
|
} |
|
|
|
// 计算当前组 |
|
dict.index = Math.ceil((curr + ((groups > 1 && groups !== pages) ? 1 : 0)) / (groups === 0 ? 1 : groups)); |
|
|
|
// 当前页非首页,则输出上一页 |
|
if (((!o.dynamicShow && !o.dynamicShowPrevNext) || curr > 1) && prev !== false) { |
|
if (BI.isKey(prev)) { |
|
view.push({ |
|
text: prev, |
|
value: "prev", |
|
disabled: pages === false ? o.hasPrev(curr) === false : !(curr > 1 && prev !== false) |
|
}); |
|
} else { |
|
view.push(BI.extend({ |
|
disabled: pages === false ? o.hasPrev(curr) === false : !(curr > 1 && prev !== false) |
|
}, prev)); |
|
} |
|
} |
|
|
|
// 当前组非首组,则输出首页 |
|
if (((!o.dynamicShow && !o.dynamicShowFirstLast) || (dict.index > 1 && groups !== 0)) && first) { |
|
view.push({ |
|
text: first, |
|
value: "first", |
|
disabled: !(dict.index > 1 && groups !== 0) |
|
}); |
|
if (dict.index > 1 && groups !== 0) { |
|
view.push({ |
|
type: "bi.label", |
|
cls: "page-ellipsis", |
|
text: "\u2026" |
|
}); |
|
} |
|
} |
|
|
|
// 输出当前页组 |
|
dict.poor = Math.floor((groups - 1) / 2); |
|
dict.start = dict.index > 1 ? curr - dict.poor : 1; |
|
dict.end = dict.index > 1 ? (function () { |
|
var max = curr + (groups - dict.poor - 1); |
|
return max > pages ? pages : max; |
|
}()) : groups; |
|
if (dict.end - dict.start < groups - 1) { // 最后一组状态 |
|
dict.start = dict.end - groups + 1; |
|
} |
|
var s = dict.start, e = dict.end; |
|
if (first && last && (dict.index > 1 && groups !== 0) && (pages > groups && dict.end < pages && groups !== 0)) { |
|
s++; |
|
e--; |
|
} |
|
for (; s <= e; s++) { |
|
if (s === curr) { |
|
view.push({ |
|
text: s, |
|
value: s, |
|
selected: true |
|
}); |
|
} else { |
|
view.push({ |
|
text: s, |
|
value: s |
|
}); |
|
} |
|
} |
|
|
|
// 总页数大于连续分页数,且当前组最大页小于总页,输出尾页 |
|
if (((!o.dynamicShow && !o.dynamicShowFirstLast) || (pages > groups && dict.end < pages && groups !== 0)) && last) { |
|
if (pages > groups && dict.end < pages && groups !== 0) { |
|
view.push({ |
|
type: "bi.label", |
|
cls: "page-ellipsis", |
|
text: "\u2026" |
|
}); |
|
} |
|
view.push({ |
|
text: last, |
|
value: "last", |
|
disabled: !(pages > groups && dict.end < pages && groups !== 0) |
|
}); |
|
} |
|
|
|
// 当前页不为尾页时,输出下一页 |
|
dict.flow = !prev && groups === 0; |
|
if (((!o.dynamicShow && !o.dynamicShowPrevNext) && next) || (curr !== pages && next || dict.flow)) { |
|
view.push((function () { |
|
if (BI.isKey(next)) { |
|
if (pages === false) { |
|
return {text: next, value: "next", disabled: o.hasNext(curr) === false}; |
|
} |
|
return (dict.flow && curr === pages) |
|
? |
|
{text: next, value: "next", disabled: true} |
|
: |
|
{text: next, value: "next", disabled: !(curr !== pages && next || dict.flow)}; |
|
} |
|
return BI.extend({ |
|
disabled: pages === false ? o.hasNext(curr) === false : !(curr !== pages && next || dict.flow) |
|
}, next); |
|
|
|
}())); |
|
} |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.button_group", |
|
element: this, |
|
items: BI.createItems(view, { |
|
cls: "page-item bi-border bi-list-item-active", |
|
height: 23, |
|
hgap: 10 |
|
}), |
|
behaviors: o.behaviors, |
|
layouts: o.layouts |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (self._lock === true) { |
|
return; |
|
} |
|
self._lock = true; |
|
self._debouce(); |
|
if (type === BI.Events.CLICK) { |
|
var v = self.button_group.getValue()[0]; |
|
switch (v) { |
|
case "first": |
|
self.currPage = 1; |
|
break; |
|
case "last": |
|
self.currPage = pages; |
|
break; |
|
case "prev": |
|
self.currPage--; |
|
break; |
|
case "next": |
|
self.currPage++; |
|
break; |
|
default: |
|
self.currPage = v; |
|
break; |
|
} |
|
o.jump.apply(self, [{ |
|
pages: pages, |
|
curr: self.currPage |
|
}]); |
|
self._populate(); |
|
self.fireEvent(BI.DetailPager.EVENT_CHANGE, obj); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.fireEvent(BI.DetailPager.EVENT_AFTER_POPULATE); |
|
}, |
|
|
|
getCurrentPage: function () { |
|
return this.currPage; |
|
}, |
|
|
|
setAllPages: function (pages) { |
|
this.options.pages = pages; |
|
}, |
|
|
|
hasPrev: function (v) { |
|
v || (v = 1); |
|
var o = this.options; |
|
var pages = this.options.pages; |
|
return pages === false ? o.hasPrev(v) : v > 1; |
|
}, |
|
|
|
hasNext: function (v) { |
|
v || (v = 1); |
|
var o = this.options; |
|
var pages = this.options.pages; |
|
return pages === false ? o.hasNext(v) : v < pages; |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
v = v | 0; |
|
v = v < 1 ? 1 : v; |
|
if (o.pages === false) { |
|
var lastPage = BI.result(o, "lastPage"), firstPage = 1; |
|
this.currPage = v > lastPage ? lastPage : ((firstPage = BI.result(o, "firstPage")), (v < firstPage ? firstPage : v)); |
|
} else { |
|
v = v > o.pages ? o.pages : v; |
|
this.currPage = v; |
|
} |
|
this._populate(); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.button_group.getValue()[0]; |
|
switch (val) { |
|
case "prev": |
|
return -1; |
|
case "next": |
|
return 1; |
|
case "first": |
|
return BI.MIN; |
|
case "last": |
|
return BI.MAX; |
|
default : |
|
return val; |
|
} |
|
}, |
|
|
|
attr: function (key, value) { |
|
BI.DetailPager.superclass.attr.apply(this, arguments); |
|
if (key === "curr") { |
|
this.currPage = BI.result(this.options, "curr"); |
|
} |
|
}, |
|
|
|
populate: function () { |
|
this._populate(); |
|
} |
|
}); |
|
BI.DetailPager.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DetailPager.EVENT_AFTER_POPULATE = "EVENT_AFTER_POPULATE"; |
|
BI.shortcut("bi.detail_pager", BI.DetailPager);/** |
|
* 分段控件使用的button |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.SegmentButton |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.SegmentButton = BI.inherit(BI.BasicButton, { |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.SegmentButton.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-segment-button bi-list-item-select", |
|
shadow: true, |
|
readonly: true, |
|
hgap: 5 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SegmentButton.superclass._init.apply(this, arguments); |
|
var opts = this.options, self = this; |
|
// if (BI.isNumber(opts.height) && BI.isNull(opts.lineHeight)) { |
|
// this.element.css({lineHeight : (opts.height - 2) + 'px'}); |
|
// } |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
element: this, |
|
textHeight: opts.height, |
|
whiteSpace: opts.whiteSpace, |
|
text: opts.text, |
|
value: opts.value, |
|
hgap: opts.hgap |
|
}); |
|
}, |
|
|
|
setSelected: function () { |
|
BI.SegmentButton.superclass.setSelected.apply(this, arguments); |
|
}, |
|
|
|
setText: function (text) { |
|
BI.SegmentButton.superclass.setText.apply(this, arguments); |
|
this.text.setText(text); |
|
}, |
|
|
|
destroy: function () { |
|
BI.SegmentButton.superclass.destroy.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.segment_button", BI.SegmentButton);/** |
|
* 单选按钮组 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.Segment |
|
* @extends BI.Widget |
|
*/ |
|
BI.Segment = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.Segment.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-segment", |
|
items: [], |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.Segment.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.buttonGroup = BI.createWidget({ |
|
element: this, |
|
type: "bi.button_group", |
|
value: o.value, |
|
items: BI.createItems(o.items, { |
|
type: "bi.segment_button", |
|
height: o.height - 2, |
|
whiteSpace: o.whiteSpace |
|
}), |
|
layout: [ |
|
{ |
|
type: "bi.center" |
|
} |
|
] |
|
}); |
|
this.buttonGroup.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.buttonGroup.on(BI.ButtonGroup.EVENT_CHANGE, function (value, obj) { |
|
self.fireEvent(BI.Segment.EVENT_CHANGE, value, obj); |
|
}); |
|
}, |
|
|
|
_setEnable: function (enable) { |
|
BI.Segment.superclass._setEnable.apply(this, arguments); |
|
if (enable === true) { |
|
this.element.removeClass("base-disabled disabled"); |
|
} else if (enable === false) { |
|
this.element.addClass("base-disabled disabled"); |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.buttonGroup.setValue(v); |
|
}, |
|
|
|
setEnabledValue: function (v) { |
|
this.buttonGroup.setEnabledValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.buttonGroup.getValue(); |
|
} |
|
}); |
|
BI.Segment.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.segment", BI.Segment);/** |
|
* guy |
|
* 复选导航条 |
|
* Created by GUY on 2015/8/25. |
|
* @class BI.MultiSelectBar |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.MultiSelectBar = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectBar.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-multi-select-bar", |
|
height: 25, |
|
text: BI.i18nText("BI-Select_All"), |
|
isAllCheckedBySelectedValue: BI.emptyFn, |
|
// 手动控制选中 |
|
disableSelected: true, |
|
isHalfCheckedBySelectedValue: function (selectedValues) { |
|
return selectedValues.length > 0; |
|
}, |
|
halfSelected: false, |
|
iconWrapperWidth: 26 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiSelectBar.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var isSelect = o.selected === true; |
|
var isHalfSelect = !o.selected && o.halfSelected; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.checkbox", |
|
stopPropagation: true, |
|
handler: function () { |
|
self.setSelected(self.isSelected()); |
|
}, |
|
selected: isSelect, |
|
invisible: isHalfSelect |
|
}); |
|
this.half = BI.createWidget({ |
|
type: "bi.half_icon_button", |
|
stopPropagation: true, |
|
handler: function () { |
|
self.setSelected(true); |
|
}, |
|
invisible: isSelect || !isHalfSelect |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, self.isSelected(), self); |
|
}); |
|
this.checkbox.on(BI.Checkbox.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectBar.EVENT_CHANGE, self.isSelected(), self); |
|
}); |
|
this.half.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, self.isSelected(), self); |
|
}); |
|
this.half.on(BI.HalfIconButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectBar.EVENT_CHANGE, self.isSelected(), self); |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
width: o.iconWrapperWidth, |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [this.checkbox, this.half] |
|
} |
|
}, { |
|
el: this.text |
|
}] |
|
}); |
|
}, |
|
|
|
_setSelected: function (v) { |
|
this.checkbox.setSelected(!!v); |
|
}, |
|
|
|
// 自己手动控制选中 |
|
beforeClick: function () { |
|
var isHalf = this.isHalfSelected(), isSelected = this.isSelected(); |
|
if (isHalf === true) { |
|
this.setSelected(true); |
|
} else { |
|
this.setSelected(!isSelected); |
|
} |
|
}, |
|
|
|
setSelected: function (v) { |
|
this.checkbox.setSelected(v); |
|
this.setHalfSelected(false); |
|
}, |
|
|
|
setHalfSelected: function (b) { |
|
this.halfSelected = !!b; |
|
if (b === true) { |
|
this.checkbox.setSelected(false); |
|
this.half.visible(); |
|
this.checkbox.invisible(); |
|
} else { |
|
this.half.invisible(); |
|
this.checkbox.visible(); |
|
} |
|
}, |
|
|
|
isHalfSelected: function () { |
|
return !this.isSelected() && !!this.halfSelected; |
|
}, |
|
|
|
isSelected: function () { |
|
return this.checkbox.isSelected(); |
|
}, |
|
|
|
setValue: function (selectedValues) { |
|
BI.MultiSelectBar.superclass.setValue.apply(this, arguments); |
|
var isAllChecked = this.options.isAllCheckedBySelectedValue.apply(this, arguments); |
|
this._setSelected(isAllChecked); |
|
!isAllChecked && this.setHalfSelected(this.options.isHalfCheckedBySelectedValue.apply(this, arguments)); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiSelectBar.superclass.doClick.apply(this, arguments); |
|
if(this.isValid()) { |
|
this.fireEvent(BI.MultiSelectBar.EVENT_CHANGE, this.isSelected(), this); |
|
} |
|
} |
|
}); |
|
BI.MultiSelectBar.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_bar", BI.MultiSelectBar); |
|
/** |
|
* guy |
|
* 二级树 |
|
* @class BI.LevelTree |
|
* @extends BI.Single |
|
*/ |
|
BI.LevelTree = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.LevelTree.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-level-tree", |
|
el: { |
|
chooseType: 0 |
|
}, |
|
expander: {}, |
|
items: [], |
|
value: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.LevelTree.superclass._init.apply(this, arguments); |
|
|
|
this.initTree(this.options.items); |
|
}, |
|
|
|
_formatItems: function (nodes, layer, pNode) { |
|
var self = this; |
|
BI.each(nodes, function (i, node) { |
|
var extend = {layer: layer}; |
|
if (!BI.isKey(node.id)) { |
|
node.id = BI.UUID(); |
|
} |
|
extend.pNode = pNode; |
|
if (node.isParent === true || node.parent === true || BI.isNotEmptyArray(node.children)) { |
|
extend.type = "bi.mid_plus_group_node"; |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.last_plus_group_node"; |
|
extend.isLastNode = true; |
|
} |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.first_plus_group_node" |
|
} |
|
if (i === 0 && i === nodes.length - 1) { // 根 |
|
extend.type = "bi.plus_group_node"; |
|
} |
|
BI.defaults(node, extend); |
|
self._formatItems(node.children, layer + 1, node); |
|
} else { |
|
extend.type = "bi.mid_tree_leaf_item"; |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.first_tree_leaf_item" |
|
} |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.last_tree_leaf_item"; |
|
} |
|
BI.defaults(node, extend); |
|
} |
|
}); |
|
return nodes; |
|
}, |
|
|
|
_assertId: function (sNodes) { |
|
BI.each(sNodes, function (i, node) { |
|
if (!BI.isKey(node.id)) { |
|
node.id = BI.UUID(); |
|
} |
|
}); |
|
}, |
|
|
|
// 构造树结构, |
|
initTree: function (nodes) { |
|
var self = this, o = this.options; |
|
this.empty(); |
|
this._assertId(nodes); |
|
this.tree = BI.createWidget({ |
|
type: "bi.custom_tree", |
|
element: this, |
|
expander: BI.extend({ |
|
el: {}, |
|
popup: { |
|
type: "bi.custom_tree" |
|
} |
|
}, o.expander), |
|
|
|
items: this._formatItems(BI.Tree.transformToTreeFormat(nodes), 0), |
|
value: o.value, |
|
|
|
el: BI.extend({ |
|
type: "bi.button_tree", |
|
chooseType: 0, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
}, o.el) |
|
}); |
|
this.tree.on(BI.Controller.EVENT_CHANGE, function (type, value, ob) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.LevelTree.EVENT_CHANGE, value, ob); |
|
} |
|
}); |
|
}, |
|
|
|
// 生成树方法 |
|
stroke: function (nodes) { |
|
this.tree.stroke.apply(this.tree, arguments); |
|
}, |
|
|
|
populate: function (items, keyword) { |
|
items = this._formatItems(BI.Tree.transformToTreeFormat(items), 0); |
|
this.tree.populate(items, keyword); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.tree.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.tree.getAllLeaves(); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.tree.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (id) { |
|
return this.tree.getNodeByValue(id); |
|
} |
|
}); |
|
BI.LevelTree.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.level_tree", BI.LevelTree);/** |
|
* 文本输入框trigger |
|
* |
|
* Created by GUY on 2015/9/15. |
|
* @class BI.EditorTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.EditorTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.EditorTrigger.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-editor-trigger bi-border", |
|
height: 24, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: false, |
|
watermark: "", |
|
errorText: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
this.options.height -= 2; |
|
BI.EditorTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
value: o.value, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText, |
|
title: function () { |
|
return self.getValue(); |
|
} |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.EditorTrigger.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.EditorTrigger.EVENT_FOCUS, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.EditorTrigger.EVENT_EMPTY, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_VALID, function () { |
|
self.fireEvent(BI.EditorTrigger.EVENT_VALID, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.EditorTrigger.EVENT_ERROR, arguments); |
|
}); |
|
|
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: this.editor |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
width: o.triggerWidth || o.height |
|
}, |
|
width: o.triggerWidth || o.height |
|
} |
|
] |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
setValue: function (value) { |
|
this.editor.setValue(value); |
|
}, |
|
|
|
setText: function (text) { |
|
this.editor.setState(text); |
|
} |
|
}); |
|
BI.EditorTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.EditorTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.EditorTrigger.EVENT_EMPTY = "EVENT_EMPTY"; |
|
BI.EditorTrigger.EVENT_VALID = "EVENT_VALID"; |
|
BI.EditorTrigger.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.shortcut("bi.editor_trigger", BI.EditorTrigger); |
|
/** |
|
* 图标按钮trigger |
|
* |
|
* Created by GUY on 2015/10/8. |
|
* @class BI.IconTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.IconTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.IconTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-icon-trigger", |
|
extraCls: "pull-down-font", |
|
el: {}, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
var o = this.options; |
|
BI.IconTrigger.superclass._init.apply(this, arguments); |
|
this.iconButton = BI.createWidget(o.el, { |
|
type: "bi.trigger_icon_button", |
|
element: this, |
|
width: o.width, |
|
height: o.height, |
|
extraCls: o.extraCls |
|
}); |
|
} |
|
}); |
|
BI.shortcut("bi.icon_trigger", BI.IconTrigger);/** |
|
* 文字trigger |
|
* |
|
* Created by GUY on 2015/9/15. |
|
* @class BI.IconTextTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.IconTextTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.IconTextTrigger.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-trigger", |
|
height: 24, |
|
iconHeight: null, |
|
iconWidth: null, |
|
textCls: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.IconTextTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "select-text-label" + (BI.isKey(o.textCls) ? (" " + o.textCls) : ""), |
|
textAlign: "left", |
|
height: o.height, |
|
text: o.text |
|
}); |
|
this.trigerButton = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.triggerWidth || o.height |
|
}); |
|
|
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
ref: function (_ref) { |
|
self.wrapper = _ref; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_change_button", |
|
cls: "icon-combo-trigger-icon", |
|
iconCls: o.iconCls, |
|
ref: function (_ref) { |
|
self.icon = _ref; |
|
}, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
disableSelected: true |
|
}, |
|
width: BI.isEmptyString(o.iconCls) ? 0 : (o.iconWrapperWidth || o.height) |
|
}, |
|
{ |
|
el: this.text, |
|
lgap: BI.isEmptyString(o.iconCls) ? 5 : 0 |
|
}, { |
|
el: this.trigerButton, |
|
width: o.triggerWidth || o.height |
|
} |
|
] |
|
}); |
|
}, |
|
|
|
setValue: function (value) { |
|
this.text.setValue(value); |
|
}, |
|
|
|
setIcon: function (iconCls) { |
|
var o = this.options; |
|
this.icon.setIcon(iconCls); |
|
var iconItem = this.wrapper.attr("items")[0]; |
|
var textItem = this.wrapper.attr("items")[1]; |
|
if(BI.isNull(iconCls) || BI.isEmptyString(iconCls)) { |
|
if(iconItem.width !== 0) { |
|
iconItem.width = 0; |
|
textItem.lgap = 5; |
|
this.wrapper.resize(); |
|
} |
|
}else{ |
|
if(iconItem.width !== (o.iconWrapperWidth || o.height)) { |
|
iconItem.width = (o.iconWrapperWidth || o.height); |
|
textItem.lgap = 0; |
|
this.wrapper.resize(); |
|
} |
|
} |
|
}, |
|
|
|
setTextCls: function(cls) { |
|
var o = this.options; |
|
var oldCls = o.textCls; |
|
o.textCls = cls; |
|
this.text.element.removeClass(oldCls).addClass(cls); |
|
}, |
|
|
|
setText: function (text) { |
|
this.text.setText(text); |
|
} |
|
}); |
|
BI.shortcut("bi.icon_text_trigger", BI.IconTextTrigger);/** |
|
* Created by Windy on 2017/12/12. |
|
*/ |
|
BI.SelectIconTextTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SelectIconTextTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-text-trigger bi-border", |
|
height: 24, |
|
iconHeight: null, |
|
iconWidth: null, |
|
iconCls: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
this.options.height -= 2; |
|
BI.SelectIconTextTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var obj = this._digist(o.value, o.items); |
|
this.trigger = BI.createWidget({ |
|
type: "bi.icon_text_trigger", |
|
element: this, |
|
text: obj.text, |
|
textCls: obj.textCls, |
|
iconCls: obj.iconCls, |
|
height: o.height, |
|
iconHeight: o.iconHeight, |
|
iconWidth: o.iconWidth, |
|
iconWrapperWidth: o.iconWrapperWidth |
|
}); |
|
}, |
|
|
|
_digist: function (vals, items) { |
|
var o = this.options; |
|
vals = BI.isArray(vals) ? vals : [vals]; |
|
var result; |
|
var formatItems = BI.Tree.transformToArrayFormat(items); |
|
BI.any(formatItems, function (i, item) { |
|
if (BI.deepContains(vals, item.value)) { |
|
result = { |
|
text: item.text || item.value, |
|
iconCls: item.iconCls |
|
}; |
|
return true; |
|
} |
|
}); |
|
|
|
if (BI.isNotNull(result)) { |
|
return { |
|
text: result.text, |
|
textCls: "", |
|
iconCls: result.iconCls |
|
}; |
|
} else { |
|
return { |
|
text: BI.isFunction(o.text) ? o.text() : o.text, |
|
textCls: "bi-water-mark", |
|
iconCls: o.iconCls |
|
}; |
|
} |
|
}, |
|
|
|
setValue: function (vals) { |
|
var obj = this._digist(vals, this.options.items); |
|
this.trigger.setText(obj.text); |
|
this.trigger.setIcon(obj.iconCls); |
|
this.trigger.setTextCls(obj.textCls); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
} |
|
}); |
|
BI.shortcut("bi.select_icon_text_trigger", BI.SelectIconTextTrigger);/** |
|
* 文字trigger |
|
* |
|
* Created by GUY on 2015/9/15. |
|
* @class BI.TextTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.TextTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.TextTrigger.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-trigger", |
|
height: 24, |
|
textCls: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "select-text-label" + (BI.isKey(o.textCls) ? (" " + o.textCls) : ""), |
|
textAlign: "left", |
|
height: o.height, |
|
text: o.text, |
|
title: function () { |
|
return self.text.getText(); |
|
}, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle, |
|
hgap: c.hgap, |
|
readonly: o.readonly |
|
}); |
|
this.trigerButton = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.triggerWidth || o.height |
|
}); |
|
|
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: this.text |
|
}, { |
|
el: this.trigerButton, |
|
width: o.triggerWidth || o.height |
|
} |
|
] |
|
}); |
|
}, |
|
|
|
setTextCls: function(cls) { |
|
var o = this.options; |
|
var oldCls = o.textCls; |
|
o.textCls = cls; |
|
this.text.element.removeClass(oldCls).addClass(cls); |
|
}, |
|
|
|
setText: function (text) { |
|
this.text.setText(text); |
|
}, |
|
|
|
setTipType: function (v) { |
|
this.text.options.tipType = v; |
|
} |
|
}); |
|
BI.shortcut("bi.text_trigger", BI.TextTrigger); |
|
/** |
|
* 选择字段trigger |
|
* |
|
* Created by GUY on 2015/9/15. |
|
* @class BI.SelectTextTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.SelectTextTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SelectTextTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-text-trigger bi-border bi-focus-shadow", |
|
height: 24 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
this.options.height -= 2; |
|
BI.SelectTextTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var obj = this._digest(o.value, o.items); |
|
this.trigger = BI.createWidget({ |
|
type: "bi.text_trigger", |
|
element: this, |
|
height: o.height, |
|
readonly: o.readonly, |
|
text: obj.text, |
|
textCls: obj.textCls, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle |
|
}); |
|
}, |
|
|
|
_digest: function(vals, items){ |
|
var o = this.options; |
|
vals = BI.isArray(vals) ? vals : [vals]; |
|
var result = []; |
|
var formatItems = BI.Tree.transformToArrayFormat(items); |
|
BI.each(formatItems, function (i, item) { |
|
if (BI.deepContains(vals, item.value) && !BI.contains(result, item.text || item.value)) { |
|
result.push(item.text || item.value); |
|
} |
|
}); |
|
|
|
if (result.length > 0) { |
|
return { |
|
textCls: "", |
|
text: result.join(",") |
|
} |
|
} else { |
|
return { |
|
textCls: "bi-water-mark", |
|
text: BI.isFunction(o.text) ? o.text() : o.text |
|
} |
|
} |
|
}, |
|
|
|
setValue: function (vals) { |
|
var formatValue = this._digest(vals, this.options.items); |
|
this.trigger.setTextCls(formatValue.textCls); |
|
this.trigger.setText(formatValue.text); |
|
}, |
|
|
|
setTipType: function (v) { |
|
this.trigger.setTipType(v); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
} |
|
}); |
|
BI.shortcut("bi.select_text_trigger", BI.SelectTextTrigger); |
|
/** |
|
* 选择字段trigger小一号的 |
|
* |
|
* @class BI.SmallSelectTextTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.SmallSelectTextTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SmallSelectTextTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-small-select-text-trigger bi-border", |
|
height: 20 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
this.options.height -= 2; |
|
BI.SmallSelectTextTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var obj = this._digest(o.value, o.items); |
|
this.trigger = BI.createWidget({ |
|
type: "bi.small_text_trigger", |
|
element: this, |
|
height: o.height - 2, |
|
text: obj.text, |
|
cls: obj.cls |
|
}); |
|
}, |
|
|
|
_digest: function(vals, items){ |
|
var o = this.options; |
|
vals = BI.isArray(vals) ? vals : [vals]; |
|
var result = []; |
|
var formatItems = BI.Tree.transformToArrayFormat(items); |
|
BI.each(formatItems, function (i, item) { |
|
if (BI.deepContains(vals, item.value) && !BI.contains(result, item.text || item.value)) { |
|
result.push(item.text || item.value); |
|
} |
|
}); |
|
|
|
if (result.length > 0) { |
|
return { |
|
cls: "", |
|
text: result.join(",") |
|
} |
|
} else { |
|
return { |
|
cls: "bi-water-mark", |
|
text: o.text |
|
} |
|
} |
|
}, |
|
|
|
setValue: function (vals) { |
|
var formatValue = this._digest(vals, this.options.items); |
|
this.trigger.element.removeClass("bi-water-mark").addClass(formatValue.cls); |
|
this.trigger.setText(formatValue.text); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
} |
|
}); |
|
BI.shortcut("bi.small_select_text_trigger", BI.SmallSelectTextTrigger);/** |
|
* 文字trigger(右边小三角小一号的) == |
|
* |
|
* @class BI.SmallTextTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.SmallTextTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
var conf = BI.SmallTextTrigger.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-text-trigger", |
|
height: 20 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SmallTextTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
height: o.height, |
|
text: o.text, |
|
hgap: c.hgap |
|
}); |
|
this.trigerButton = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.triggerWidth || o.height |
|
}); |
|
|
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: this.text |
|
}, { |
|
el: this.trigerButton, |
|
width: o.triggerWidth || o.height |
|
} |
|
] |
|
}); |
|
}, |
|
|
|
setValue: function (value) { |
|
this.text.setValue(value); |
|
}, |
|
|
|
setText: function (text) { |
|
this.text.setText(text); |
|
} |
|
}); |
|
BI.shortcut("bi.small_text_trigger", BI.SmallTextTrigger);/** |
|
* 日期控件中的月份下拉框 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.MonthDateCombo |
|
* @extends BI.Trigger |
|
*/ |
|
BI.MonthDateCombo = BI.inherit(BI.Trigger, { |
|
_defaultConfig: function () { |
|
return BI.extend( BI.MonthDateCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-month-combo", |
|
height: 24, |
|
container: null |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MonthDateCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.date_triangle_trigger" |
|
}); |
|
|
|
this.popup = BI.createWidget({ |
|
type: "bi.month_popup", |
|
behaviors: o.behaviors |
|
}); |
|
|
|
this.popup.on(BI.YearPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
}); |
|
|
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
offsetStyle: "center", |
|
container: o.container, |
|
element: this, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: this.trigger, |
|
popup: { |
|
minWidth: 85, |
|
stopPropagation: false, |
|
el: this.popup |
|
} |
|
}); |
|
this.combo.on(BI.Combo.EVENT_CHANGE, function () { |
|
self.combo.hideView(); |
|
self.fireEvent(BI.MonthDateCombo.EVENT_CHANGE); |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.doBehavior(); |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
} |
|
}); |
|
BI.MonthDateCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.month_date_combo", BI.MonthDateCombo);/** |
|
* 年份下拉框 |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.YearDateCombo |
|
* @extends BI.Trigger |
|
*/ |
|
BI.YearDateCombo = BI.inherit(BI.Trigger, { |
|
_defaultConfig: function () { |
|
return BI.extend( BI.YearDateCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-year-combo", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
behaviors: {}, |
|
height: 24, |
|
container: null |
|
}); |
|
}, |
|
_init: function () { |
|
BI.YearDateCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.date_triangle_trigger" |
|
}); |
|
|
|
this.popup = BI.createWidget({ |
|
type: "bi.year_popup", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}); |
|
|
|
this.popup.on(BI.YearPopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.YearDateCombo.EVENT_CHANGE); |
|
}); |
|
|
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
offsetStyle: "center", |
|
element: this, |
|
container: o.container, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: this.trigger, |
|
popup: { |
|
minWidth: 100, |
|
stopPropagation: false, |
|
el: this.popup |
|
} |
|
}); |
|
this.combo.on(BI.Combo.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.YearDateCombo.EVENT_CHANGE); |
|
}); |
|
// BI-22551 popup未初始化传入的behavior无效 |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.doBehavior(); |
|
}); |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
this.popup.setMinDate(minDate); |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
this.popup.setMaxDate(maxDate); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
} |
|
}); |
|
BI.YearDateCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.year_date_combo", BI.YearDateCombo); |
|
/** |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.DatePicker |
|
* @extends BI.Widget |
|
*/ |
|
BI.DatePicker = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.DatePicker.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-date-picker", |
|
height: 40, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31" // 最大日期 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.DatePicker.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this._year = BI.getDate().getFullYear(); |
|
this._month = BI.getDate().getMonth() + 1; |
|
this.left = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "pre-page-h-font", |
|
width: 24, |
|
height: 24 |
|
}); |
|
this.left.on(BI.IconButton.EVENT_CHANGE, function () { |
|
if (self._month === 1) { |
|
self.setValue({ |
|
year: self.year.getValue() - 1, |
|
month: 12 |
|
}); |
|
} else { |
|
self.setValue({ |
|
year: self.year.getValue(), |
|
month: self.month.getValue() - 1 |
|
}); |
|
} |
|
self.fireEvent(BI.DatePicker.EVENT_CHANGE); |
|
self._checkLeftValid(); |
|
self._checkRightValid(); |
|
}); |
|
|
|
this.right = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "next-page-h-font", |
|
width: 24, |
|
height: 24 |
|
}); |
|
|
|
this.right.on(BI.IconButton.EVENT_CHANGE, function () { |
|
if (self._month === 12) { |
|
self.setValue({ |
|
year: self.year.getValue() + 1, |
|
month: 1 |
|
}); |
|
} else { |
|
self.setValue({ |
|
year: self.year.getValue(), |
|
month: self.month.getValue() + 1 |
|
}); |
|
} |
|
self.fireEvent(BI.DatePicker.EVENT_CHANGE); |
|
self._checkLeftValid(); |
|
self._checkRightValid(); |
|
}); |
|
|
|
this.year = BI.createWidget({ |
|
type: "bi.year_date_combo", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}); |
|
this.year.on(BI.YearDateCombo.EVENT_CHANGE, function () { |
|
self.setValue({ |
|
year: self.year.getValue(), |
|
month: self.month.getValue() |
|
}); |
|
self.fireEvent(BI.DatePicker.EVENT_CHANGE); |
|
}); |
|
this.month = BI.createWidget({ |
|
type: "bi.month_date_combo", |
|
behaviors: o.behaviors |
|
}); |
|
this.month.on(BI.MonthDateCombo.EVENT_CHANGE, function () { |
|
self.setValue({ |
|
year: self.year.getValue(), |
|
month: self.month.getValue() |
|
}); |
|
self.fireEvent(BI.DatePicker.EVENT_CHANGE); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [this.left] |
|
}, |
|
width: 24 |
|
}, { |
|
type: "bi.center_adapt", |
|
items: [{ |
|
el: { |
|
type: "bi.horizontal", |
|
width: 120, |
|
rgap: 10, |
|
items: [{ |
|
el: this.year, |
|
lgap: 10 |
|
}, this.month] |
|
} |
|
}] |
|
}, { |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [this.right] |
|
}, |
|
width: 24 |
|
}] |
|
}); |
|
this.setValue({ |
|
year: this._year, |
|
month: this._month |
|
}); |
|
}, |
|
|
|
_checkLeftValid: function () { |
|
var o = this.options; |
|
var valid = !(this._month === 1 && this._year === BI.parseDateTime(o.min, "%Y-%X-%d").getFullYear()); |
|
this.left.setEnable(valid); |
|
return valid; |
|
}, |
|
|
|
_checkRightValid: function () { |
|
var o = this.options; |
|
var valid = !(this._month === 12 && this._year === BI.parseDateTime(o.max, "%Y-%X-%d").getFullYear()); |
|
this.right.setEnable(valid); |
|
return valid; |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
this.year.setMinDate(minDate); |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
this.year.setMaxDate(maxDate); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this._year = BI.parseInt(ob.year); |
|
this._month = BI.parseInt(ob.month); |
|
this.year.setValue(ob.year); |
|
this.month.setValue(ob.month); |
|
this._checkLeftValid(); |
|
this._checkRightValid(); |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
year: this.year.getValue(), |
|
month: this.month.getValue() |
|
}; |
|
} |
|
}); |
|
BI.DatePicker.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.date_picker", BI.DatePicker);/** |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.YearPicker |
|
* @extends BI.Widget |
|
*/ |
|
BI.YearPicker = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.YearPicker.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-year-picker", |
|
behaviors: {}, |
|
height: 40, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31" // 最大日期 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.YearPicker.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this._year = BI.getDate().getFullYear(); |
|
this.left = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "pre-page-h-font", |
|
width: 25, |
|
height: 25 |
|
}); |
|
this.left.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self.setValue(self.year.getValue() - 1); |
|
self.fireEvent(BI.YearPicker.EVENT_CHANGE); |
|
self._checkLeftValid(); |
|
self._checkRightValid(); |
|
}); |
|
|
|
this.right = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "next-page-h-font", |
|
width: 25, |
|
height: 25 |
|
}); |
|
|
|
this.right.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self.setValue(self.year.getValue() + 1); |
|
self.fireEvent(BI.YearPicker.EVENT_CHANGE); |
|
self._checkLeftValid(); |
|
self._checkRightValid(); |
|
}); |
|
|
|
this.year = BI.createWidget({ |
|
type: "bi.year_date_combo", |
|
min: o.min, |
|
behaviors: o.behaviors, |
|
max: o.max |
|
}); |
|
this.year.on(BI.YearDateCombo.EVENT_CHANGE, function () { |
|
self.setValue(self.year.getValue()); |
|
self.fireEvent(BI.YearPicker.EVENT_CHANGE); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [this.left] |
|
}, |
|
width: 25 |
|
}, { |
|
type: "bi.center_adapt", |
|
items: [{ |
|
el: { |
|
type: "bi.horizontal_float", |
|
width: 50, |
|
items: [{ |
|
el: this.year |
|
}] |
|
} |
|
}] |
|
}, { |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [this.right] |
|
}, |
|
width: 25 |
|
}] |
|
}); |
|
this.setValue({ |
|
year: this._year |
|
}); |
|
}, |
|
|
|
_checkLeftValid: function () { |
|
var o = this.options; |
|
var valid = !(this._year === BI.parseDateTime(o.min, "%Y-%X-%d").getFullYear()); |
|
this.left.setEnable(valid); |
|
return valid; |
|
}, |
|
|
|
_checkRightValid: function () { |
|
var o = this.options; |
|
var valid = !(this._year === BI.parseDateTime(o.max, "%Y-%X-%d").getFullYear()); |
|
this.right.setEnable(valid); |
|
return valid; |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
this.options.min = minDate; |
|
this.year.setMinDate(minDate); |
|
this._checkLeftValid(); |
|
this._checkRightValid(); |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
this.options.max = maxDate; |
|
this.year.setMaxDate(maxDate); |
|
this._checkLeftValid(); |
|
this._checkRightValid(); |
|
}, |
|
|
|
|
|
setValue: function (v) { |
|
this._year = v; |
|
this.year.setValue(v); |
|
this._checkLeftValid(); |
|
this._checkRightValid(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.year.getValue(); |
|
} |
|
}); |
|
BI.YearPicker.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.year_picker", BI.YearPicker); |
|
/** |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.DateCalendarPopup |
|
* @extends BI.Widget |
|
*/ |
|
BI.DateCalendarPopup = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.DateCalendarPopup.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-date-calendar-popup", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
selectedTime: null |
|
}); |
|
}, |
|
|
|
_createNav: function (v) { |
|
var date = BI.Calendar.getDateJSONByPage(v); |
|
var calendar = BI.createWidget({ |
|
type: "bi.calendar", |
|
logic: { |
|
dynamic: true |
|
}, |
|
min: this.options.min, |
|
max: this.options.max, |
|
year: date.year, |
|
month: date.month, |
|
// BI-45616 此处为确定当前应该展示哪个年月对应的Calendar, day不是关键数据, 给1号就可 |
|
day: 1 |
|
}); |
|
return calendar; |
|
}, |
|
|
|
_init: function () { |
|
BI.DateCalendarPopup.superclass._init.apply(this, arguments); |
|
var self = this, |
|
o = this.options; |
|
this.today = BI.getDate(); |
|
this._year = this.today.getFullYear(); |
|
this._month = this.today.getMonth() + 1; |
|
this._day = this.today.getDate(); |
|
|
|
this.selectedTime = o.selectedTime || { |
|
year: this._year, |
|
month: this._month, |
|
day: this._day |
|
}; |
|
this.datePicker = BI.createWidget({ |
|
type: "bi.date_picker", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}); |
|
|
|
this.calendar = BI.createWidget({ |
|
direction: "top", |
|
logic: { |
|
dynamic: true |
|
}, |
|
type: "bi.navigation", |
|
tab: this.datePicker, |
|
cardCreator: BI.bind(this._createNav, this), |
|
|
|
afterCardCreated: function () { |
|
|
|
}, |
|
|
|
afterCardShow: function () { |
|
this.setValue(self.selectedTime); |
|
} |
|
}); |
|
|
|
this.datePicker.on(BI.DatePicker.EVENT_CHANGE, function () { |
|
self.selectedTime = self.datePicker.getValue(); |
|
self.selectedTime.day = 1; |
|
self.calendar.setSelect(BI.Calendar.getPageByDateJSON(self.selectedTime)); |
|
}); |
|
|
|
this.calendar.on(BI.Navigation.EVENT_CHANGE, function () { |
|
self.selectedTime = self.calendar.getValue(); |
|
self.setValue(self.selectedTime); |
|
self.fireEvent(BI.DateCalendarPopup.EVENT_CHANGE); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.calendar, |
|
left: 5, |
|
right: 5 |
|
}, { |
|
el: { |
|
type: "bi.layout", |
|
cls: "bi-split-top" |
|
}, |
|
height: 1, |
|
top: 40, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_checkMin: function () { |
|
var calendar = this.calendar.getSelectedCard(); |
|
if (BI.isNotNull(calendar)) { |
|
calendar.setMinDate(this.options.min); |
|
} |
|
}, |
|
|
|
_checkMax: function () { |
|
var calendar = this.calendar.getSelectedCard(); |
|
if (BI.isNotNull(calendar)) { |
|
calendar.setMaxDate(this.options.max); |
|
} |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (BI.isNotEmptyString(this.options.min)) { |
|
this.options.min = minDate; |
|
this.datePicker.setMinDate(minDate); |
|
this._checkMin(); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (BI.isNotEmptyString(this.options.max)) { |
|
this.options.max = maxDate; |
|
this.datePicker.setMaxDate(maxDate); |
|
this._checkMax(); |
|
} |
|
}, |
|
|
|
setValue: function (timeOb) { |
|
this.datePicker.setValue(timeOb); |
|
this.calendar.setSelect(BI.Calendar.getPageByDateJSON(timeOb)); |
|
this.calendar.setValue(timeOb); |
|
this.selectedTime = timeOb; |
|
}, |
|
|
|
getValue: function () { |
|
return this.selectedTime; |
|
} |
|
}); |
|
BI.DateCalendarPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.date_calendar_popup", BI.DateCalendarPopup);/** |
|
* 月份展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.MonthPopup |
|
* @extends BI.Trigger |
|
*/ |
|
BI.MonthPopup = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MonthPopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-month-popup", |
|
behaviors: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MonthPopup.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
// 纵向排列月 |
|
var month = [1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12]; |
|
var items = []; |
|
items.push(month.slice(0, 2)); |
|
items.push(month.slice(2, 4)); |
|
items.push(month.slice(4, 6)); |
|
items.push(month.slice(6, 8)); |
|
items.push(month.slice(8, 10)); |
|
items.push(month.slice(10, 12)); |
|
items = BI.map(items, function (i, item) { |
|
return BI.map(item, function (j, td) { |
|
return { |
|
type: "bi.text_item", |
|
cls: "bi-list-item-select", |
|
textAlign: "center", |
|
whiteSpace: "nowrap", |
|
once: false, |
|
forceSelected: true, |
|
height: 23, |
|
width: 38, |
|
value: td, |
|
text: td |
|
}; |
|
}); |
|
}); |
|
|
|
this.month = BI.createWidget({ |
|
type: "bi.button_group", |
|
element: this, |
|
behaviors: o.behaviors, |
|
items: BI.createItems(items, {}), |
|
layouts: [BI.LogicFactory.createLogic("table", BI.extend({ |
|
dynamic: true |
|
}, { |
|
columns: 2, |
|
rows: 6, |
|
columnSize: [1 / 2, 1 / 2], |
|
rowSize: 25 |
|
})), { |
|
type: "bi.center_adapt", |
|
vgap: 1, |
|
hgap: 2 |
|
}], |
|
value: o.value |
|
}); |
|
|
|
this.month.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.MonthPopup.EVENT_CHANGE); |
|
} |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return this.month.getValue()[0]; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.parseInt(v); |
|
this.month.setValue([v]); |
|
} |
|
}); |
|
BI.MonthPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.month_popup", BI.MonthPopup);/** |
|
* 年份展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.YearPopup |
|
* @extends BI.Trigger |
|
*/ |
|
BI.YearPopup = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.YearPopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-year-popup", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31" // 最大日期 |
|
}); |
|
}, |
|
|
|
_createYearCalendar: function (v) { |
|
var o = this.options, y = this._year; |
|
|
|
var calendar = BI.createWidget({ |
|
type: "bi.year_calendar", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max, |
|
logic: { |
|
dynamic: true |
|
}, |
|
year: y + v * 12 |
|
}); |
|
calendar.setValue(this._year); |
|
return calendar; |
|
}, |
|
|
|
_init: function () { |
|
BI.YearPopup.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.selectedYear = this._year = BI.getDate().getFullYear(); |
|
|
|
this.backBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "pre-page-h-font", |
|
width: 24, |
|
height: 24, |
|
value: -1 |
|
}); |
|
|
|
this.preBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "next-page-h-font", |
|
width: 24, |
|
height: 24, |
|
value: 1 |
|
}); |
|
|
|
this.navigation = BI.createWidget({ |
|
type: "bi.navigation", |
|
element: this, |
|
single: true, |
|
logic: { |
|
dynamic: true |
|
}, |
|
tab: { |
|
cls: "year-popup-navigation bi-high-light bi-split-top", |
|
height: 24, |
|
items: [this.backBtn, this.preBtn] |
|
}, |
|
cardCreator: BI.bind(this._createYearCalendar, this), |
|
|
|
afterCardShow: function () { |
|
this.setValue(self.selectedYear); |
|
var calendar = this.getSelectedCard(); |
|
calendar && self.backBtn.setEnable(!calendar.isFrontYear()); |
|
calendar && self.preBtn.setEnable(!calendar.isFinalYear()); |
|
} |
|
}); |
|
|
|
this.navigation.on(BI.Navigation.EVENT_CHANGE, function () { |
|
self.selectedYear = this.getValue(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.fireEvent(BI.YearPopup.EVENT_CHANGE, self.selectedYear); |
|
}); |
|
|
|
if(BI.isKey(o.value)){ |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_checkMin: function () { |
|
var calendar = this.navigation.getSelectedCard(); |
|
if (BI.isNotNull(calendar)) { |
|
calendar.setMinDate(this.options.min); |
|
this.backBtn.setEnable(!calendar.isFrontYear()); |
|
this.preBtn.setEnable(!calendar.isFinalYear()); |
|
} |
|
}, |
|
|
|
_checkMax: function () { |
|
var calendar = this.navigation.getSelectedCard(); |
|
if (BI.isNotNull(calendar)) { |
|
calendar.setMaxDate(this.options.max); |
|
this.backBtn.setEnable(!calendar.isFrontYear()); |
|
this.preBtn.setEnable(!calendar.isFinalYear()); |
|
} |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (BI.isNotEmptyString(this.options.min)) { |
|
this.options.min = minDate; |
|
this._checkMin(); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (BI.isNotEmptyString(this.options.max)) { |
|
this.options.max = maxDate; |
|
this._checkMax(); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.selectedYear; |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
v = BI.parseInt(v); |
|
// 对于年控件来说,只要传入的minDate和maxDate的year区间包含v就是合法的 |
|
var startDate = BI.parseDateTime(o.min, "%Y-%X-%d"); |
|
var endDate = BI.parseDateTime(o.max, "%Y-%X-%d"); |
|
if (BI.checkDateVoid(v, 1, 1, BI.print(BI.getDate(startDate.getFullYear(), 0, 1), "%Y-%X-%d"), BI.print(BI.getDate(endDate.getFullYear(), 0, 1), "%Y-%X-%d"))[0]) { |
|
v = BI.getDate().getFullYear(); |
|
this.selectedYear = ""; |
|
this.navigation.setSelect(BI.YearCalendar.getPageByYear(v)); |
|
this.navigation.setValue(""); |
|
} else { |
|
this.selectedYear = v; |
|
this.navigation.setSelect(BI.YearCalendar.getPageByYear(v)); |
|
this.navigation.setValue(v); |
|
} |
|
} |
|
}); |
|
BI.YearPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.year_popup", BI.YearPopup);/** |
|
* 日期控件中的年份或月份trigger |
|
* |
|
* Created by GUY on 2015/9/7. |
|
* @class BI.DateTriangleTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DateTriangleTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
height: 24, |
|
iconWidth: 12, |
|
iconHeight: 12 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend( BI.DateTriangleTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-date-triangle-trigger pull-down-ha-font cursor-pointer", |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DateTriangleTrigger.superclass._init.apply(this, arguments); |
|
var o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "right", |
|
text: o.text, |
|
value: o.value, |
|
height: c.height |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical_adapt", |
|
element: this, |
|
items: [{ |
|
el: this.text, |
|
rgap: 5 |
|
}, { |
|
type: "bi.icon_label", |
|
width: 16 |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.text.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function (v) { |
|
this.text.setText(v); |
|
}, |
|
|
|
getText: function () { |
|
return this.item.getText(); |
|
}, |
|
|
|
getKey: function () { |
|
|
|
} |
|
}); |
|
BI.shortcut("bi.date_triangle_trigger", BI.DateTriangleTrigger);/** |
|
* Created by zcf on 2017/2/20. |
|
*/ |
|
BI.StaticDatePaneCard = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.StaticDatePaneCard.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-date-pane", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
selectedTime: null |
|
}); |
|
}, |
|
_init: function () { |
|
BI.StaticDatePaneCard.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.today = BI.getDate(); |
|
this._year = this.today.getFullYear(); |
|
this._month = this.today.getMonth() + 1; |
|
|
|
this.selectedTime = o.selectedTime || { |
|
year: this._year, |
|
month: this._month |
|
}; |
|
|
|
this.datePicker = BI.createWidget({ |
|
type: "bi.date_picker", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}); |
|
this.datePicker.on(BI.DatePicker.EVENT_CHANGE, function () { |
|
var value = self.datePicker.getValue(); |
|
var monthDay = BI.getMonthDays(BI.getDate(value.year, value.month - 1, 1)); |
|
var day = self.selectedTime.day || 0; |
|
if (day > monthDay) { |
|
day = monthDay; |
|
} |
|
self.selectedTime = { |
|
year: value.year, |
|
month: value.month |
|
}; |
|
day !== 0 && (self.selectedTime.day = day); |
|
self.calendar.setSelect(BI.Calendar.getPageByDateJSON(self.selectedTime)); |
|
self.calendar.setValue(self.selectedTime); |
|
day !== 0 && self.fireEvent(BI.DateCalendarPopup.EVENT_CHANGE); |
|
}); |
|
|
|
this.calendar = BI.createWidget({ |
|
direction: "custom", |
|
// logic: { |
|
// dynamic: false |
|
// }, |
|
type: "bi.navigation", |
|
tab: this.datePicker, |
|
cardCreator: BI.bind(this._createNav, this) |
|
}); |
|
this.calendar.on(BI.Navigation.EVENT_CHANGE, function () { |
|
self.selectedTime = self.calendar.getValue(); |
|
self.calendar.empty(); |
|
self.setValue(self.selectedTime); |
|
self.fireEvent(BI.DateCalendarPopup.EVENT_CHANGE); |
|
}); |
|
this.setValue(o.selectedTime); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.datePicker, |
|
height: 40 |
|
}, this.calendar], |
|
hgap: 10 |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
cls: "bi-split-top" |
|
}, |
|
height: 1, |
|
top: 40, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
|
|
}, |
|
|
|
_createNav: function (v) { |
|
var date = BI.Calendar.getDateJSONByPage(v); |
|
var calendar = BI.createWidget({ |
|
type: "bi.calendar", |
|
logic: { |
|
dynamic: false |
|
}, |
|
min: this.options.min, |
|
max: this.options.max, |
|
year: date.year, |
|
month: date.month, |
|
day: this.selectedTime.day |
|
}); |
|
return calendar; |
|
}, |
|
|
|
_getNewCurrentDate: function () { |
|
var today = BI.getDate(); |
|
return { |
|
year: today.getFullYear(), |
|
month: today.getMonth() + 1 |
|
}; |
|
}, |
|
|
|
_setCalenderValue: function (date) { |
|
this.calendar.setSelect(BI.Calendar.getPageByDateJSON(date)); |
|
this.calendar.setValue(date); |
|
this.selectedTime = date; |
|
}, |
|
|
|
_setDatePicker: function (timeOb) { |
|
if (BI.isNull(timeOb) || BI.isNull(timeOb.year) || BI.isNull(timeOb.month)) { |
|
this.datePicker.setValue(this._getNewCurrentDate()); |
|
} else { |
|
this.datePicker.setValue(timeOb); |
|
} |
|
}, |
|
|
|
_setCalendar: function (timeOb) { |
|
if (BI.isNull(timeOb) || BI.isNull(timeOb.day)) { |
|
this.calendar.empty(); |
|
this._setCalenderValue(this._getNewCurrentDate()); |
|
} else { |
|
this._setCalenderValue(timeOb); |
|
} |
|
}, |
|
|
|
setValue: function (timeOb) { |
|
this._setDatePicker(timeOb); |
|
this._setCalendar(timeOb); |
|
}, |
|
|
|
getValue: function () { |
|
return this.selectedTime; |
|
} |
|
|
|
}); |
|
BI.shortcut("bi.static_date_pane_card", BI.StaticDatePaneCard);BI.DynamicDatePane = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-pane" |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
el: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: 30, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Multi_Date_YMD"), |
|
value: BI.DynamicDatePane.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicDatePane.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}), |
|
listeners: [{ |
|
eventName: BI.ButtonGroup.EVENT_CHANGE, |
|
action: function () { |
|
var value = this.getValue()[0]; |
|
self.dateTab.setSelect(value); |
|
switch (value) { |
|
case BI.DynamicDatePane.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
break; |
|
case BI.DynamicDatePane.Dynamic: |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
break; |
|
default: |
|
break; |
|
} |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}], |
|
ref: function () { |
|
self.switcher = this; |
|
} |
|
}, |
|
height: 30 |
|
}, { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
showIndex: BI.DynamicDatePane.Static, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicDatePane.Static: |
|
return { |
|
type: "bi.static_date_pane_card", |
|
behaviors: o.behaviors, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}], |
|
ref: function () { |
|
self.ymd = this; |
|
} |
|
}; |
|
case BI.DynamicDatePane.Dynamic: |
|
default: |
|
return { |
|
type: "bi.dynamic_date_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
if(self._checkValue(self.getValue())) { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
this.setValue(this.options.value); |
|
}, |
|
|
|
_checkValueValid: function (value) { |
|
return BI.isNull(value) || BI.isEmptyObject(value) || BI.isEmptyString(value); |
|
}, |
|
|
|
_checkValue: function (v) { |
|
switch (v.type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
return BI.isNotEmptyObject(v.value); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
return true; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {}; |
|
var type = v.type || BI.DynamicDateCombo.Static; |
|
var value = v.value || v; |
|
this.switcher.setValue(type); |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (this._checkValueValid(value)) { |
|
var date = BI.getDate(); |
|
this.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1 |
|
}); |
|
} else { |
|
this.ymd.setValue(value); |
|
} |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: this.dateTab.getSelect(), |
|
value: this.dateTab.getValue() |
|
}; |
|
} |
|
}); |
|
BI.shortcut("bi.dynamic_date_pane", BI.DynamicDatePane); |
|
|
|
BI.extend(BI.DynamicDatePane, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});/** |
|
* Created by Urthur on 2017/7/14. |
|
*/ |
|
BI.DateTimeCombo = BI.inherit(BI.Single, { |
|
constants: { |
|
popupHeight: 290, |
|
popupWidth: 270, |
|
comboAdjustHeight: 1, |
|
border: 1 |
|
}, |
|
_defaultConfig: function () { |
|
return BI.extend(BI.DateTimeCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-date-time-combo bi-border bi-border-radius", |
|
width: 200, |
|
height: 24, |
|
minDate: "1900-01-01", |
|
maxDate: "2099-12-31" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DateTimeCombo.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options; |
|
var date = BI.getDate(); |
|
this.storeValue = BI.isNotNull(opts.value) ? opts.value : { |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate(), |
|
hour: date.getHours(), |
|
minute: date.getMinutes(), |
|
second: date.getSeconds() |
|
}; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.date_time_trigger", |
|
min: opts.minDate, |
|
max: opts.maxDate, |
|
value: opts.value |
|
}); |
|
|
|
this.popup = BI.createWidget({ |
|
type: "bi.date_time_popup", |
|
behaviors: opts.behaviors, |
|
min: opts.minDate, |
|
max: opts.maxDate, |
|
value: opts.value |
|
}); |
|
self.setValue(this.storeValue); |
|
|
|
this.popup.on(BI.DateTimePopup.BUTTON_CANCEL_EVENT_CHANGE, function () { |
|
self.setValue(self.storeValue); |
|
self.hidePopupView(); |
|
self.fireEvent(BI.DateTimeCombo.EVENT_CANCEL); |
|
}); |
|
this.popup.on(BI.DateTimePopup.BUTTON_OK_EVENT_CHANGE, function () { |
|
self.storeValue = self.popup.getValue(); |
|
self.setValue(self.storeValue); |
|
self.hidePopupView(); |
|
self.fireEvent(BI.DateTimeCombo.EVENT_CONFIRM); |
|
}); |
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: opts.container, |
|
toggle: false, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: this.trigger, |
|
adjustLength: this.constants.comboAdjustHeight, |
|
popup: { |
|
el: this.popup, |
|
width: this.constants.popupWidth, |
|
stopPropagation: false |
|
}, |
|
// DEC-4250 和复选下拉一样,点击不收起 |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0; |
|
} |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.popup.setValue(self.storeValue); |
|
self.fireEvent(BI.DateTimeCombo.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-font", |
|
width: 24, |
|
height: 24 |
|
}); |
|
triggerBtn.on(BI.IconButton.EVENT_CHANGE, function () { |
|
if (self.combo.isViewVisible()) { |
|
// self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.combo, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
top: 0, |
|
right: 0 |
|
}] |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.popup.setValue(v); |
|
this.trigger.setValue(v); |
|
}, |
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
hidePopupView: function () { |
|
this.combo.hideView(); |
|
} |
|
}); |
|
|
|
BI.DateTimeCombo.EVENT_CANCEL = "EVENT_CANCEL"; |
|
BI.DateTimeCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DateTimeCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DateTimeCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.date_time_combo", BI.DateTimeCombo); |
|
/** |
|
* Created by Urthur on 2017/7/14. |
|
*/ |
|
BI.DateTimePopup = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.DateTimePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-date-time-popup", |
|
width: 268, |
|
height: 374 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DateTimePopup.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options; |
|
this.cancelButton = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "multidate-popup-button bi-border-top bi-border-right", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Cancel") |
|
}); |
|
this.cancelButton.on(BI.TextButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DateTimePopup.BUTTON_CANCEL_EVENT_CHANGE); |
|
}); |
|
|
|
this.okButton = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "multidate-popup-button bi-border-top", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_OK") |
|
}); |
|
this.okButton.on(BI.TextButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DateTimePopup.BUTTON_OK_EVENT_CHANGE); |
|
}); |
|
|
|
this.dateCombo = BI.createWidget({ |
|
type: "bi.date_calendar_popup", |
|
behaviors: opts.behaviors, |
|
min: self.options.min, |
|
max: self.options.max |
|
}); |
|
self.dateCombo.on(BI.DateCalendarPopup.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DateTimePopup.CALENDAR_EVENT_CHANGE); |
|
}); |
|
|
|
this.dateButton = BI.createWidget({ |
|
type: "bi.grid", |
|
items: [[this.cancelButton, this.okButton]] |
|
}); |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.vtape", |
|
items: [{ |
|
el: this.dateCombo |
|
}, { |
|
el: { |
|
type: "bi.center_adapt", |
|
cls: "bi-split-top", |
|
items: [{ |
|
type: "bi.dynamic_date_time_select", |
|
ref: function (_ref) { |
|
self.timeSelect = _ref; |
|
} |
|
}] |
|
}, |
|
height: 50 |
|
}, { |
|
el: this.dateButton, |
|
height: 30 |
|
}] |
|
}); |
|
this.setValue(opts.value); |
|
}, |
|
|
|
setValue: function (v) { |
|
var value = v, date; |
|
if (BI.isNull(value)) { |
|
date = BI.getDate(); |
|
this.dateCombo.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
this.timeSelect.setValue({ |
|
hour: date.getHours(), |
|
minute: date.getMinutes(), |
|
second: date.getSeconds() |
|
}); |
|
} else { |
|
this.dateCombo.setValue({ |
|
year: value.year, |
|
month: value.month, |
|
day: value.day |
|
}); |
|
this.timeSelect.setValue({ |
|
hour: value.hour, |
|
minute: value.minute, |
|
second: value.second |
|
}); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return BI.extend({ |
|
year: this.dateCombo.getValue().year, |
|
month: this.dateCombo.getValue().month, |
|
day: this.dateCombo.getValue().day |
|
}, this.timeSelect.getValue()); |
|
} |
|
}); |
|
BI.DateTimePopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.DateTimePopup.BUTTON_CANCEL_EVENT_CHANGE = "BUTTON_CANCEL_EVENT_CHANGE"; |
|
BI.DateTimePopup.CALENDAR_EVENT_CHANGE = "CALENDAR_EVENT_CHANGE"; |
|
BI.shortcut("bi.date_time_popup", BI.DateTimePopup); |
|
/** |
|
* Created by Urthur on 2017/7/14. |
|
*/ |
|
BI.DateTimeTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.DateTimeTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-date-time-trigger", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 24, |
|
width: 200 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DateTimeTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
height: o.height, |
|
width: o.width, |
|
hgap: c.hgap |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
el: this.text |
|
},{ |
|
el: BI.createWidget(), |
|
width: o.height |
|
}] |
|
}); |
|
this.setValue(o.value); |
|
}, |
|
|
|
_printTime: function (v) { |
|
return v < 10 ? "0" + v : v; |
|
}, |
|
|
|
setValue: function (v) { |
|
var self = this; |
|
var value = v, dateStr; |
|
if(BI.isNull(value)) { |
|
value = BI.getDate(); |
|
dateStr = BI.print(value, "%Y-%X-%d %H:%M:%S"); |
|
} else { |
|
var date = BI.getDate(value.year, value.month - 1, value.day, value.hour, value.minute, value.second); |
|
dateStr = BI.print(date, "%Y-%X-%d %H:%M:%S"); |
|
|
|
} |
|
this.text.setText(dateStr); |
|
this.text.setTitle(dateStr); |
|
} |
|
|
|
}); |
|
BI.shortcut("bi.date_time_trigger", BI.DateTimeTrigger); |
|
BI.StaticDateTimePaneCard = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.StaticDateTimePaneCard.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-date-time-pane", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
selectedTime: null |
|
}); |
|
}, |
|
_init: function () { |
|
BI.StaticDateTimePaneCard.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.today = BI.getDate(); |
|
this._year = this.today.getFullYear(); |
|
this._month = this.today.getMonth() + 1; |
|
|
|
this.selectedTime = o.selectedTime || { |
|
year: this._year, |
|
month: this._month |
|
}; |
|
|
|
this.datePicker = BI.createWidget({ |
|
type: "bi.date_picker", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}); |
|
this.datePicker.on(BI.DatePicker.EVENT_CHANGE, function () { |
|
var value = self.datePicker.getValue(); |
|
var monthDay = BI.getMonthDays(BI.getDate(value.year, value.month - 1, 1)); |
|
var day = self.selectedTime.day || 0; |
|
if (day > monthDay) { |
|
day = monthDay; |
|
} |
|
self.selectedTime = BI.extend(self.selectedTime, { |
|
year: value.year, |
|
month: value.month |
|
}); |
|
day !== 0 && (self.selectedTime.day = day); |
|
self.calendar.setSelect(BI.Calendar.getPageByDateJSON(self.selectedTime)); |
|
self.calendar.setValue(self.selectedTime); |
|
day !== 0 && self.fireEvent(BI.DateCalendarPopup.EVENT_CHANGE); |
|
}); |
|
|
|
this.calendar = BI.createWidget({ |
|
direction: "custom", |
|
// logic: { |
|
// dynamic: false |
|
// }, |
|
type: "bi.navigation", |
|
tab: this.datePicker, |
|
cardCreator: BI.bind(this._createNav, this) |
|
}); |
|
this.calendar.on(BI.Navigation.EVENT_CHANGE, function () { |
|
self.selectedTime = BI.extend(self.calendar.getValue(), self.timeSelect.getValue()); |
|
self.calendar.empty(); |
|
self.setValue(self.selectedTime); |
|
self.fireEvent(BI.DateCalendarPopup.EVENT_CHANGE); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
hgap: 10, |
|
items: [{ |
|
el: this.datePicker, |
|
height: 40 |
|
}, this.calendar, { |
|
el: { |
|
type: "bi.dynamic_date_time_select", |
|
cls: "bi-split-top", |
|
ref: function () { |
|
self.timeSelect = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicDateTimeSelect.EVENT_CONFIRM, |
|
action: function () { |
|
self.selectedTime = BI.extend(self.calendar.getValue(), self.timeSelect.getValue()); |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}, |
|
height: 40 |
|
}] |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
cls: "bi-split-top" |
|
}, |
|
height: 1, |
|
top: 40, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
this.setValue(o.selectedTime); |
|
|
|
}, |
|
|
|
_createNav: function (v) { |
|
var date = BI.Calendar.getDateJSONByPage(v); |
|
var calendar = BI.createWidget({ |
|
type: "bi.calendar", |
|
logic: { |
|
dynamic: false |
|
}, |
|
min: this.options.min, |
|
max: this.options.max, |
|
year: date.year, |
|
month: date.month, |
|
day: this.selectedTime.day |
|
}); |
|
return calendar; |
|
}, |
|
|
|
_getNewCurrentDate: function () { |
|
var today = BI.getDate(); |
|
return { |
|
year: today.getFullYear(), |
|
month: today.getMonth() + 1 |
|
}; |
|
}, |
|
|
|
_setCalenderValue: function (date) { |
|
this.calendar.setSelect(BI.Calendar.getPageByDateJSON(date)); |
|
this.calendar.setValue(date); |
|
this.selectedTime = BI.extend({}, this.timeSelect.getValue(), date); |
|
}, |
|
|
|
_setDatePicker: function (timeOb) { |
|
if (BI.isNull(timeOb) || BI.isNull(timeOb.year) || BI.isNull(timeOb.month)) { |
|
this.datePicker.setValue(this._getNewCurrentDate()); |
|
} else { |
|
this.datePicker.setValue(timeOb); |
|
} |
|
}, |
|
|
|
_setCalendar: function (timeOb) { |
|
if (BI.isNull(timeOb) || BI.isNull(timeOb.day)) { |
|
this.calendar.empty(); |
|
this._setCalenderValue(this._getNewCurrentDate()); |
|
} else { |
|
this._setCalenderValue(timeOb); |
|
} |
|
}, |
|
|
|
setValue: function (timeOb) { |
|
timeOb = timeOb || {}; |
|
this._setDatePicker(timeOb); |
|
this._setCalendar(timeOb); |
|
this.timeSelect.setValue({ |
|
hour: timeOb.hour, |
|
minute: timeOb.minute, |
|
second: timeOb.second |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return this.selectedTime; |
|
} |
|
|
|
}); |
|
BI.shortcut("bi.static_date_time_pane_card", BI.StaticDateTimePaneCard);BI.DynamicDateTimePane = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-pane" |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
el: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: 30, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Multi_Date_YMD"), |
|
value: BI.DynamicDateTimePane.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicDateTimePane.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}), |
|
listeners: [{ |
|
eventName: BI.ButtonGroup.EVENT_CHANGE, |
|
action: function () { |
|
var value = this.getValue()[0]; |
|
self.dateTab.setSelect(value); |
|
switch (value) { |
|
case BI.DynamicDateTimePane.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
break; |
|
case BI.DynamicDateTimePane.Dynamic: |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
}], |
|
ref: function () { |
|
self.switcher = this; |
|
} |
|
}, |
|
height: 30 |
|
}, { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
showIndex: BI.DynamicDateTimePane.Static, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicDateTimePane.Static: |
|
return { |
|
type: "bi.static_date_time_pane_card", |
|
behaviors: o.behaviors, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}], |
|
ref: function () { |
|
self.ymd = this; |
|
} |
|
}; |
|
case BI.DynamicDateTimePane.Dynamic: |
|
default: |
|
return { |
|
type: "bi.dynamic_date_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
if(self._checkValue(self.getValue())) { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
this.setValue(this.options.value); |
|
}, |
|
|
|
_checkValueValid: function (value) { |
|
return BI.isNull(value) || BI.isEmptyObject(value) || BI.isEmptyString(value); |
|
}, |
|
|
|
_checkValue: function (v) { |
|
switch (v.type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
return BI.isNotEmptyObject(v.value); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
return true; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {}; |
|
var type = v.type || BI.DynamicDateTimePane.Static; |
|
var value = v.value || v; |
|
this.switcher.setValue(type); |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateTimePane.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
break; |
|
case BI.DynamicDateTimePane.Static: |
|
default: |
|
if (this._checkValueValid(value)) { |
|
var date = BI.getDate(); |
|
this.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1 |
|
}); |
|
} else { |
|
this.ymd.setValue(value); |
|
} |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: this.dateTab.getSelect(), |
|
value: this.dateTab.getValue() |
|
}; |
|
} |
|
}); |
|
BI.shortcut("bi.dynamic_date_time_pane", BI.DynamicDateTimePane); |
|
|
|
BI.extend(BI.DynamicDateTimePane, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});/** |
|
* Created by roy on 15/8/14. |
|
*/ |
|
BI.DownListCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.DownListCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-down-list-combo", |
|
height: 24, |
|
items: [], |
|
adjustLength: 0, |
|
direction: "bottom", |
|
trigger: "click", |
|
container: null, |
|
stopPropagation: false, |
|
el: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.DownListCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.popupview = BI.createWidget({ |
|
type: "bi.down_list_popup", |
|
items: o.items, |
|
chooseType: o.chooseType, |
|
value: o.value |
|
}); |
|
|
|
this.popupview.on(BI.DownListPopup.EVENT_CHANGE, function (value) { |
|
self.fireEvent(BI.DownListCombo.EVENT_CHANGE, value); |
|
self.downlistcombo.hideView(); |
|
}); |
|
|
|
this.popupview.on(BI.DownListPopup.EVENT_SON_VALUE_CHANGE, function (value, fatherValue) { |
|
self.fireEvent(BI.DownListCombo.EVENT_SON_VALUE_CHANGE, value, fatherValue); |
|
self.downlistcombo.hideView(); |
|
}); |
|
|
|
|
|
this.downlistcombo = BI.createWidget({ |
|
element: this, |
|
type: "bi.combo", |
|
trigger: o.trigger, |
|
isNeedAdjustWidth: false, |
|
container: o.container, |
|
adjustLength: o.adjustLength, |
|
direction: o.direction, |
|
stopPropagation: o.stopPropagation, |
|
el: BI.createWidget(o.el, { |
|
type: "bi.icon_trigger", |
|
extraCls: o.iconCls, |
|
width: o.width, |
|
height: o.height |
|
}), |
|
popup: { |
|
el: this.popupview, |
|
stopPropagation: o.stopPropagation, |
|
maxHeight: 1000, |
|
minWidth: 140 |
|
} |
|
}); |
|
|
|
this.downlistcombo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.fireEvent(BI.DownListCombo.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
}, |
|
|
|
hideView: function () { |
|
this.downlistcombo.hideView(); |
|
}, |
|
|
|
showView: function (e) { |
|
this.downlistcombo.showView(e); |
|
}, |
|
|
|
populate: function (items) { |
|
this.popupview.populate(items); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popupview.setValue(v); |
|
}, |
|
getValue: function () { |
|
return this.popupview.getValue(); |
|
} |
|
}); |
|
BI.DownListCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DownListCombo.EVENT_SON_VALUE_CHANGE = "EVENT_SON_VALUE_CHANGE"; |
|
BI.DownListCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
|
|
BI.shortcut("bi.down_list_combo", BI.DownListCombo);/** |
|
* Created by roy on 15/9/6. |
|
*/ |
|
BI.DownListGroup = BI.inherit(BI.Widget, { |
|
constants: { |
|
iconCls: "check-mark-ha-font" |
|
}, |
|
_defaultConfig: function () { |
|
return BI.extend(BI.DownListGroup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-down-list-group", |
|
items: [ |
|
{ |
|
el: {} |
|
} |
|
] |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DownListGroup.superclass._init.apply(this, arguments); |
|
var o = this.options, self = this; |
|
|
|
this.downlistgroup = BI.createWidget({ |
|
element: this, |
|
type: "bi.button_tree", |
|
items: o.items, |
|
chooseType: 0, // 0单选,1多选 |
|
layouts: [{ |
|
type: "bi.vertical", |
|
hgap: 0, |
|
vgap: 0 |
|
}], |
|
value: o.value |
|
}); |
|
this.downlistgroup.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if(type === BI.Events.CLICK) { |
|
self.fireEvent(BI.DownListGroup.EVENT_CHANGE, arguments); |
|
} |
|
}); |
|
}, |
|
getValue: function () { |
|
return this.downlistgroup.getValue(); |
|
}, |
|
setValue: function (v) { |
|
this.downlistgroup.setValue(v); |
|
} |
|
|
|
|
|
}); |
|
BI.DownListGroup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.down_list_group", BI.DownListGroup);BI.DownListItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.DownListItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-down-list-item bi-list-item-active", |
|
cls: "", |
|
height: 24, |
|
logic: { |
|
dynamic: true |
|
}, |
|
selected: false, |
|
iconHeight: null, |
|
iconWidth: null, |
|
textHgap: 0, |
|
textVgap: 0, |
|
textLgap: 0, |
|
textRgap: 0 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DownListItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
hgap: o.textHgap, |
|
vgap: o.textVgap, |
|
lgap: o.textLgap, |
|
rgap: o.textRgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
height: o.height |
|
}); |
|
this.icon = BI.createWidget({ |
|
type: "bi.center_adapt", |
|
width: 36, |
|
height: o.height, |
|
items: [{ |
|
el: { |
|
type: "bi.icon", |
|
width: o.iconWidth, |
|
height: o.iconHeight |
|
} |
|
}] |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left), BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, this.icon, this.text) |
|
})))); |
|
}, |
|
|
|
setValue: function () { |
|
if (!this.isReadOnly()) { |
|
this.text.setValue.apply(this.text, arguments); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setText: function () { |
|
this.text.setText.apply(this.text, arguments); |
|
}, |
|
|
|
getText: function () { |
|
return this.text.getText(); |
|
}, |
|
|
|
doClick: function () { |
|
BI.DownListItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.DownListItem.EVENT_CHANGE, this.getValue(), this); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
} |
|
}); |
|
BI.DownListItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.down_list_item", BI.DownListItem);BI.DownListGroupItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.DownListGroupItem.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-down-list-group-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
// invalid: true, |
|
iconCls1: "dot-e-font", |
|
iconCls2: "pull-right-e-font" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DownListGroupItem.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
var self = this; |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-group-item-text", |
|
textAlign: "left", |
|
text: o.text, |
|
value: o.value, |
|
height: o.height |
|
}); |
|
|
|
this.icon1 = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: o.iconCls1, |
|
width: 36, |
|
disableSelected: true, |
|
selected: this._digest(o.value) |
|
}); |
|
|
|
this.icon2 = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: o.iconCls2, |
|
width: 24, |
|
forceNotSelected: true |
|
}); |
|
|
|
var blank = BI.createWidget({ |
|
type: "bi.layout", |
|
width: 24 |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.icon2, |
|
top: 0, |
|
bottom: 0, |
|
right: 0 |
|
}] |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", this.icon1, this.text, blank) |
|
})))); |
|
|
|
this.element.hover(function () { |
|
if (self.isEnabled()) { |
|
self.hover(); |
|
} |
|
}, function () { |
|
if (self.isEnabled()) { |
|
self.dishover(); |
|
} |
|
}); |
|
}, |
|
|
|
_digest: function (v) { |
|
var self = this, o = this.options; |
|
v = BI.isArray(v) ? v : [v]; |
|
return BI.any(v, function (idx, value) { |
|
return BI.contains(o.childValues, value); |
|
}); |
|
}, |
|
|
|
hover: function () { |
|
BI.DownListGroupItem.superclass.hover.apply(this, arguments); |
|
this.icon1.element.addClass("hover"); |
|
this.icon2.element.addClass("hover"); |
|
|
|
}, |
|
|
|
dishover: function () { |
|
BI.DownListGroupItem.superclass.dishover.apply(this, arguments); |
|
this.icon1.element.removeClass("hover"); |
|
this.icon2.element.removeClass("hover"); |
|
}, |
|
|
|
doClick: function () { |
|
BI.DownListGroupItem.superclass.doClick.apply(this, arguments); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.DownListGroupItem.EVENT_CHANGE, this.getValue()); |
|
} |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.icon1.setSelected(this._digest(v)); |
|
} |
|
}); |
|
BI.DownListGroupItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.down_list_group_item", BI.DownListGroupItem);/** |
|
* Created by roy on 15/9/8. |
|
* 处理popup中的item分组样式 |
|
* 一个item分组中的成员大于一时,该分组设置为单选,并且默认状态第一个成员设置为已选择项 |
|
*/ |
|
BI.DownListPopup = BI.inherit(BI.Pane, { |
|
constants: { |
|
nextIcon: "pull-right-e-font", |
|
height: 24, |
|
iconHeight: 12, |
|
iconWidth: 12, |
|
hgap: 0, |
|
vgap: 0, |
|
border: 1 |
|
}, |
|
_defaultConfig: function () { |
|
var conf = BI.DownListPopup.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-down-list-popup", |
|
items: [], |
|
chooseType: BI.Selection.Multi |
|
}); |
|
}, |
|
_init: function () { |
|
BI.DownListPopup.superclass._init.apply(this, arguments); |
|
this.singleValues = []; |
|
this.childValueMap = {}; |
|
this.fatherValueMap = {}; |
|
this.items = BI.deepClone(this.options.items); |
|
var self = this, o = this.options, children = this._createChildren(this.items); |
|
this.popup = BI.createWidget({ |
|
type: "bi.button_tree", |
|
items: BI.createItems(children, |
|
{}, { |
|
adjustLength: -2 |
|
} |
|
), |
|
layouts: [{ |
|
type: "bi.vertical", |
|
hgap: this.constants.hgap, |
|
vgap: this.constants.vgap |
|
}], |
|
value: this._digest(o.value), |
|
chooseType: o.chooseType |
|
}); |
|
|
|
this.popup.on(BI.ButtonTree.EVENT_CHANGE, function (value, object) { |
|
var changedValue = value; |
|
if (BI.isNotNull(self.childValueMap[value])) { |
|
changedValue = self.childValueMap[value]; |
|
self.fireEvent(BI.DownListPopup.EVENT_SON_VALUE_CHANGE, changedValue, self.fatherValueMap[value]); |
|
} else { |
|
self.fireEvent(BI.DownListPopup.EVENT_CHANGE, changedValue, object); |
|
} |
|
|
|
|
|
if (!BI.contains(self.singleValues, changedValue)) { |
|
var item = self.getValue(); |
|
var result = []; |
|
BI.each(item, function (i, valueObject) { |
|
if (valueObject.value != changedValue) { |
|
result.push(valueObject); |
|
} |
|
}); |
|
self.setValue(result); |
|
} |
|
|
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
items: [this.popup], |
|
vgap: 5 |
|
}); |
|
|
|
}, |
|
_createChildren: function (items) { |
|
var self = this, result = []; |
|
// 不能修改populate进来的item的引用 |
|
BI.each(items, function (i, it) { |
|
var item_done = { |
|
type: "bi.down_list_group", |
|
items: [] |
|
}; |
|
|
|
BI.each(it, function (i, item) { |
|
if (BI.isNotEmptyArray(item.children) && !BI.isEmpty(item.el)) { |
|
item.type = "bi.combo_group"; |
|
// popup未初始化返回的是options中的value, 在经过buttontree的getValue concat之后,无法区分值来自options |
|
// 还是item自身, 这边控制defaultInit为true来避免这个问题 |
|
item.isDefaultInit = true; |
|
item.cls = "down-list-group"; |
|
item.trigger = "hover"; |
|
item.isNeedAdjustWidth = false; |
|
item.el.title = item.el.title || item.el.text; |
|
item.el.type = "bi.down_list_group_item"; |
|
item.el.logic = { |
|
dynamic: true |
|
}; |
|
item.el.height = self.constants.height; |
|
item.el.iconCls2 = self.constants.nextIcon; |
|
item.popup = { |
|
lgap: 1, |
|
el: { |
|
type: "bi.button_tree", |
|
chooseType: 0, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
|
|
}, |
|
innerVGap: 5, |
|
maxHeight: 378 |
|
}; |
|
item.el.childValues = []; |
|
BI.each(item.children, function (i, child) { |
|
var fatherValue = BI.deepClone(item.el.value); |
|
var childValue = BI.deepClone(child.value); |
|
self.singleValues.push(child.value); |
|
child.type = "bi.down_list_item"; |
|
child.extraCls = " child-down-list-item"; |
|
child.title = child.title || child.text; |
|
child.textRgap = 10; |
|
child.isNeedAdjustWidth = false; |
|
child.logic = { |
|
dynamic: true |
|
}; |
|
child.father = fatherValue; |
|
self.fatherValueMap[self._createChildValue(fatherValue, childValue)] = fatherValue; |
|
self.childValueMap[self._createChildValue(fatherValue, childValue)] = childValue; |
|
child.value = self._createChildValue(fatherValue, childValue); |
|
item.el.childValues.push(child.value); |
|
}); |
|
} else { |
|
item.type = "bi.down_list_item"; |
|
item.title = item.title || item.text; |
|
item.textRgap = 10; |
|
item.isNeedAdjustWidth = false; |
|
item.logic = { |
|
dynamic: true |
|
}; |
|
} |
|
var el_done = {}; |
|
el_done.el = item; |
|
item_done.items.push(el_done); |
|
}); |
|
if (self._isGroup(item_done.items)) { |
|
BI.each(item_done.items, function (i, item) { |
|
self.singleValues.push(item.el.value); |
|
}); |
|
} |
|
|
|
result.push(item_done); |
|
if (self._needSpliter(i, items.length)) { |
|
var spliter_container = BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
cls: "bi-down-list-spliter bi-split-top cursor-pointer", |
|
height: 0 |
|
} |
|
|
|
}], |
|
cls: "bi-down-list-spliter-container cursor-pointer", |
|
vgap: 5, |
|
lgap: 10, |
|
rgap: 0 |
|
}); |
|
result.push(spliter_container); |
|
} |
|
}); |
|
return result; |
|
}, |
|
|
|
_isGroup: function (i) { |
|
return i.length > 1; |
|
}, |
|
|
|
_needSpliter: function (i, itemLength) { |
|
return i < itemLength - 1; |
|
}, |
|
|
|
_createChildValue: function (fatherValue, childValue) { |
|
return fatherValue + "_" + childValue; |
|
}, |
|
|
|
_digest: function (valueItem) { |
|
var self = this; |
|
var valueArray = []; |
|
BI.each(valueItem, function (i, item) { |
|
var value; |
|
if (BI.isNotNull(item.childValue)) { |
|
value = self._createChildValue(item.value, item.childValue); |
|
} else { |
|
value = item.value; |
|
} |
|
valueArray.push(value); |
|
} |
|
); |
|
return valueArray; |
|
}, |
|
|
|
_checkValues: function (values) { |
|
var value = []; |
|
BI.each(this.items, function (idx, itemGroup) { |
|
BI.each(itemGroup, function (id, item) { |
|
if(BI.isNotNull(item.children)) { |
|
var childValues = BI.map(item.children, "value"); |
|
var v = joinValue(childValues, values[idx]); |
|
if(BI.isNotEmptyString(v)) { |
|
value.push(v); |
|
} |
|
}else{ |
|
if(item.value === values[idx][0]) { |
|
value.push(values[idx][0]); |
|
} |
|
} |
|
}); |
|
}); |
|
return value; |
|
|
|
function joinValue (sources, targets) { |
|
var value = ""; |
|
BI.some(sources, function (idx, s) { |
|
return BI.some(targets, function (id, t) { |
|
if(s === t) { |
|
value = s; |
|
return true; |
|
} |
|
}); |
|
}); |
|
return value; |
|
} |
|
}, |
|
|
|
populate: function (items) { |
|
BI.DownListPopup.superclass.populate.apply(this, arguments); |
|
this.items = BI.deepClone(items); |
|
this.childValueMap = {}; |
|
this.fatherValueMap = {}; |
|
this.singleValues = []; |
|
var children = this._createChildren(this.items); |
|
var popupItem = BI.createItems(children, |
|
{}, { |
|
adjustLength: -2 |
|
} |
|
); |
|
this.popup.populate(popupItem); |
|
}, |
|
|
|
setValue: function (valueItem) { |
|
this.popup.setValue(this._digest(valueItem)); |
|
}, |
|
|
|
_getValue: function () { |
|
var v = []; |
|
BI.each(this.popup.getAllButtons(), function (i, item) { |
|
i % 2 === 0 && v.push(item.getValue()); |
|
}); |
|
return v; |
|
}, |
|
|
|
getValue: function () { |
|
var self = this, result = []; |
|
var values = this._checkValues(this._getValue()); |
|
BI.each(values, function (i, value) { |
|
var valueItem = {}; |
|
if (BI.isNotNull(self.childValueMap[value])) { |
|
var fartherValue = self.fatherValueMap[value]; |
|
valueItem.childValue = self.childValueMap[value]; |
|
valueItem.value = fartherValue; |
|
} else { |
|
valueItem.value = value; |
|
} |
|
result.push(valueItem); |
|
}); |
|
return result; |
|
} |
|
|
|
|
|
}); |
|
|
|
BI.DownListPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DownListPopup.EVENT_SON_VALUE_CHANGE = "EVENT_SON_VALUE_CHANGE"; |
|
BI.shortcut("bi.down_list_popup", BI.DownListPopup);!(function () { |
|
BI.DynamicDateHelper = {}; |
|
BI.extend(BI.DynamicDateHelper, { |
|
getCalculation: function (obj) { |
|
var date = BI.getDate(); |
|
|
|
return this.getCalculationByDate(date, obj); |
|
}, |
|
|
|
getCalculationByDate: function (date, obj) { |
|
if (BI.isNotNull(obj.year)) { |
|
date = BI.getDate((date.getFullYear() + BI.parseInt(obj.year)), date.getMonth(), date.getDate()); |
|
} |
|
if (BI.isNotNull(obj.quarter)) { |
|
date = BI.getOffsetQuarter(date, BI.parseInt(obj.quarter)); |
|
} |
|
if (BI.isNotNull(obj.month)) { |
|
date = BI.getOffsetMonth(date, BI.parseInt(obj.month)); |
|
} |
|
if (BI.isNotNull(obj.week)) { |
|
date = BI.getOffsetDate(date, BI.parseInt(obj.week) * 7); |
|
} |
|
if (BI.isNotNull(obj.day)) { |
|
date = BI.getOffsetDate(date, BI.parseInt(obj.day)); |
|
} |
|
if (BI.isNotNull(obj.workDay)) { |
|
// 配置了节假日就按照节假日计算工作日偏移,否则按正常的天去算 |
|
if(BI.isNotNull(BI.holidays)) { |
|
var count = Math.abs(obj.workDay); |
|
for (var i = 0; i < count; i++) { |
|
date = BI.getOffsetDate(date, obj.workDay < 0 ? -1 : 1); |
|
if(BI.isNotNull(BI.holidays[BI.print(date, "%Y-%X-%d")])) { |
|
i--; |
|
} |
|
} |
|
} else { |
|
date = BI.getOffsetDate(date, BI.parseInt(obj.workDay)); |
|
} |
|
} |
|
if (BI.isNotNull(obj.position) && obj.position !== BI.DynamicDateCard.OFFSET.CURRENT) { |
|
date = this.getBeginDate(date, obj); |
|
} |
|
|
|
return BI.getDate(date.getFullYear(), date.getMonth(), date.getDate()); |
|
}, |
|
|
|
getBeginDate: function (date, obj) { |
|
if (BI.isNotNull(obj.day)) { |
|
return obj.position === BI.DynamicDateCard.OFFSET.BEGIN ? BI.getDate(date.getFullYear(), date.getMonth(), 1) : BI.getDate(date.getFullYear(), date.getMonth(), (BI.getLastDateOfMonth(date)).getDate()); |
|
} |
|
if (BI.isNotNull(obj.week)) { |
|
return obj.position === BI.DynamicDateCard.OFFSET.BEGIN ? BI.getWeekStartDate(date) : BI.getWeekEndDate(date); |
|
} |
|
if (BI.isNotNull(obj.month)) { |
|
return obj.position === BI.DynamicDateCard.OFFSET.BEGIN ? BI.getDate(date.getFullYear(), date.getMonth(), 1) : BI.getDate(date.getFullYear(), date.getMonth(), (BI.getLastDateOfMonth(date)).getDate()); |
|
} |
|
if (BI.isNotNull(obj.quarter)) { |
|
return obj.position === BI.DynamicDateCard.OFFSET.BEGIN ? BI.getQuarterStartDate(date) : BI.getQuarterEndDate(date); |
|
} |
|
if (BI.isNotNull(obj.year)) { |
|
return obj.position === BI.DynamicDateCard.OFFSET.BEGIN ? BI.getDate(date.getFullYear(), 0, 1) : BI.getDate(date.getFullYear(), 11, 31); |
|
} |
|
return date; |
|
} |
|
}); |
|
})(); |
|
BI.DynamicDateCard = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-card" |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
this.position = BI.DynamicDateCard.OFFSET.CURRENT; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
el: { |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Multi_Date_Relative_Current_Time"), |
|
textAlign: "left", |
|
height: 12, |
|
lgap: 10 |
|
}, |
|
tgap: 10, |
|
bgap: 5 |
|
}, { |
|
type: "bi.button_group", |
|
ref: function () { |
|
self.checkgroup = this; |
|
}, |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
lgap: 4, |
|
value: [BI.DynamicDateCard.TYPE.YEAR], |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Basic_Year"), |
|
value: BI.DynamicDateCard.TYPE.YEAR |
|
}, { |
|
text: BI.i18nText("BI-Basic_Single_Quarter"), |
|
value: BI.DynamicDateCard.TYPE.QUARTER |
|
}, { |
|
text: BI.i18nText("BI-Basic_Month"), |
|
value: BI.DynamicDateCard.TYPE.MONTH |
|
}, { |
|
text: BI.i18nText("BI-Basic_Week"), |
|
value: BI.DynamicDateCard.TYPE.WEEK |
|
}, { |
|
text: BI.i18nText("BI-Basic_Day"), |
|
value: BI.DynamicDateCard.TYPE.DAY |
|
}], { |
|
type: "bi.multi_select_item", |
|
logic: { |
|
dynamic: true |
|
} |
|
}), |
|
layouts: [{ |
|
type: "bi.left", |
|
rgap: 4 |
|
}], |
|
listeners: [{ |
|
eventName: BI.ButtonGroup.EVENT_CHANGE, |
|
action: function () { |
|
var value = self.checkgroup.getValue(); |
|
if(value.length !== 0) { |
|
self.workDayBox.setSelected(false); |
|
} |
|
|
|
var plainValue = {}; |
|
BI.each(self.resultPane.getAllButtons(), function (idx, button) { |
|
var value = button.getValue(); |
|
if(BI.isNotNull(value.dateType)) { |
|
plainValue[value.dateType] = { |
|
value: value.value, |
|
offset: value.offset |
|
}; |
|
} |
|
}); |
|
self.resultPane.populate(self._getParamJson(BI.map(self.checkgroup.getValue(), function (idx, v) { |
|
var obj = { |
|
dateType: v |
|
}; |
|
if(BI.has(plainValue, v)) { |
|
obj.value = plainValue[v].value; |
|
obj.offset = plainValue[v].offset; |
|
} |
|
return obj; |
|
}))); |
|
self.position = BI.DynamicDateCard.OFFSET.CURRENT; |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}, { |
|
type: "bi.vertical_adapt", |
|
lgap: 2, |
|
items: [{ |
|
el: { |
|
type: "bi.multi_select_item", |
|
ref: function () { |
|
self.workDayBox = this; |
|
}, |
|
logic: { |
|
dynamic: true |
|
}, |
|
text: BI.i18nText("BI-Basic_Work_Day"), |
|
value: BI.DynamicDateCard.TYPE.WORK_DAY, |
|
listeners: [{ |
|
eventName: BI.MultiSelectItem.EVENT_CHANGE, |
|
action: function () { |
|
if(this.isSelected()) { |
|
self.checkgroup.setValue(); |
|
} |
|
self.resultPane.populate(this.isSelected() ? self._getParamJson([{ |
|
dateType: BI.DynamicDateCard.TYPE.WORK_DAY |
|
}]) : []); |
|
self.position = BI.DynamicDateCard.OFFSET.CURRENT; |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
} |
|
}], |
|
ref: function () { |
|
self.workDay = this; |
|
} |
|
}, { |
|
type: "bi.button_group", |
|
items: this._getParamJson([{ |
|
dateType: BI.DynamicDateCard.TYPE.YEAR |
|
}]), |
|
ref: function () { |
|
self.resultPane = this; |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical", |
|
bgap: 10, |
|
hgap: 10 |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
_getParamJson: function (values, positionValue) { |
|
var self = this; |
|
var items = BI.map(values, function (idx, value) { |
|
return { |
|
el: { |
|
type: "bi.dynamic_date_param_item", |
|
dateType: value.dateType, |
|
value: value.value, |
|
offset: value.offset, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}, |
|
tgap: idx === 0 ? 5 : 0 |
|
}; |
|
}); |
|
|
|
if(values.length === 1 && values[0].dateType === BI.DynamicDateCard.TYPE.DAY) { |
|
var comboItems = this._getText(BI.DynamicDateCard.TYPE.MONTH); |
|
comboItems[0].text = BI.i18nText("BI-Basic_Empty"); |
|
items.push({ |
|
type: "bi.text_value_combo", |
|
height: 24, |
|
items: comboItems, |
|
container: null, |
|
value: positionValue || BI.DynamicDateCard.OFFSET.CURRENT, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.position = this.getValue()[0]; |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}); |
|
}else{ |
|
if(values.length !== 0 && BI.last(values).dateType !== BI.DynamicDateCard.TYPE.DAY && BI.last(values).dateType !== BI.DynamicDateCard.TYPE.WORK_DAY) { |
|
items.push({ |
|
type: "bi.text_value_combo", |
|
height: 24, |
|
container: null, |
|
items: this._getText(BI.last(values).dateType), |
|
value: positionValue || BI.DynamicDateCard.OFFSET.CURRENT, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.position = this.getValue()[0]; |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}); |
|
|
|
} |
|
} |
|
|
|
return items; |
|
}, |
|
|
|
_getText: function (lastValue) { |
|
switch (lastValue) { |
|
case BI.DynamicDateCard.TYPE.YEAR: |
|
return [{ |
|
text: BI.i18nText("BI-Basic_Current_Day"), |
|
value: BI.DynamicDateCard.OFFSET.CURRENT |
|
}, { |
|
text: BI.i18nText("BI-Basic_Year_Begin"), |
|
value: BI.DynamicDateCard.OFFSET.BEGIN |
|
}, { |
|
text: BI.i18nText("BI-Basic_Year_End"), |
|
value: BI.DynamicDateCard.OFFSET.END |
|
}]; |
|
case BI.DynamicDateCard.TYPE.QUARTER: |
|
return [{ |
|
text: BI.i18nText("BI-Basic_Current_Day"), |
|
value: BI.DynamicDateCard.OFFSET.CURRENT |
|
}, { |
|
text: BI.i18nText("BI-Basic_Quarter_Begin"), |
|
value: BI.DynamicDateCard.OFFSET.BEGIN |
|
}, { |
|
text: BI.i18nText("BI-Basic_Quarter_End"), |
|
value: BI.DynamicDateCard.OFFSET.END |
|
}]; |
|
case BI.DynamicDateCard.TYPE.MONTH: |
|
return [{ |
|
text: BI.i18nText("BI-Basic_Current_Day"), |
|
value: BI.DynamicDateCard.OFFSET.CURRENT |
|
}, { |
|
text: BI.i18nText("BI-Basic_Month_Begin"), |
|
value: BI.DynamicDateCard.OFFSET.BEGIN |
|
}, { |
|
text: BI.i18nText("BI-Basic_Month_End"), |
|
value: BI.DynamicDateCard.OFFSET.END |
|
}]; |
|
case BI.DynamicDateCard.TYPE.WEEK: |
|
default: |
|
return [{ |
|
text: BI.i18nText("BI-Basic_Current_Day"), |
|
value: BI.DynamicDateCard.OFFSET.CURRENT |
|
}, { |
|
text: BI.i18nText("BI-Basic_Week_Begin"), |
|
value: BI.DynamicDateCard.OFFSET.BEGIN |
|
}, { |
|
text: BI.i18nText("BI-Basic_Week_End"), |
|
value: BI.DynamicDateCard.OFFSET.END |
|
}]; |
|
} |
|
}, |
|
|
|
_createValue: function (type, v) { |
|
return { |
|
dateType: type, |
|
value: Math.abs(v), |
|
offset: v > 0 ? 1 : 0 |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {}; |
|
this.position = v.position || BI.DynamicDateCard.OFFSET.CURRENT; |
|
var values = []; |
|
var valuesItems = []; |
|
if(BI.isNotNull(v.year)) { |
|
values.push(BI.DynamicDateCard.TYPE.YEAR); |
|
valuesItems.push(this._createValue(BI.DynamicDateCard.TYPE.YEAR, v.year)); |
|
} |
|
if(BI.isNotNull(v.quarter)) { |
|
values.push(BI.DynamicDateCard.TYPE.QUARTER); |
|
valuesItems.push(this._createValue(BI.DynamicDateCard.TYPE.QUARTER, v.quarter)); |
|
} |
|
if(BI.isNotNull(v.month)) { |
|
values.push(BI.DynamicDateCard.TYPE.MONTH); |
|
valuesItems.push(this._createValue(BI.DynamicDateCard.TYPE.MONTH, v.month)); |
|
} |
|
if(BI.isNotNull(v.week)) { |
|
values.push(BI.DynamicDateCard.TYPE.WEEK); |
|
valuesItems.push(this._createValue(BI.DynamicDateCard.TYPE.WEEK, v.week)); |
|
} |
|
if(BI.isNotNull(v.day)) { |
|
values.push(BI.DynamicDateCard.TYPE.DAY); |
|
valuesItems.push(this._createValue(BI.DynamicDateCard.TYPE.DAY, v.day)); |
|
} |
|
if(BI.isNotNull(v.workDay)) { |
|
values.push(BI.DynamicDateCard.TYPE.WORK_DAY); |
|
valuesItems.push(this._createValue(BI.DynamicDateCard.TYPE.WORK_DAY, v.workDay)); |
|
} |
|
this.checkgroup.setValue(values); |
|
this.workDayBox.setSelected(BI.isNotNull(v.workDay)); |
|
this.resultPane.populate(this._getParamJson(valuesItems, v.position)); |
|
}, |
|
|
|
getValue: function () { |
|
var self = this; |
|
var valueMap = {}; |
|
var selectValues = this.checkgroup.getValue(); |
|
var buttons = this.resultPane.getAllButtons(); |
|
if(selectValues.length !== 0) { |
|
BI.each(buttons, function (idx, button) { |
|
var value = button.getValue(); |
|
switch (value.dateType) { |
|
case BI.DynamicDateCard.TYPE.YEAR: |
|
valueMap.year = (value.offset === 0 ? -value.value : value.value); |
|
break; |
|
case BI.DynamicDateCard.TYPE.QUARTER: |
|
valueMap.quarter = (value.offset === 0 ? -value.value : value.value); |
|
break; |
|
case BI.DynamicDateCard.TYPE.MONTH: |
|
valueMap.month = (value.offset === 0 ? -value.value : value.value); |
|
break; |
|
case BI.DynamicDateCard.TYPE.WEEK: |
|
valueMap.week = (value.offset === 0 ? -value.value : value.value); |
|
break; |
|
case BI.DynamicDateCard.TYPE.DAY: |
|
valueMap.day = (value.offset === 0 ? -value.value : value.value); |
|
break; |
|
default: |
|
break; |
|
} |
|
if(BI.isNull(value.dateType)) { |
|
valueMap.position = self.position || BI.DynamicDateCard.OFFSET.CURRENT; |
|
} |
|
}); |
|
} |
|
if(this.workDayBox.isSelected()) { |
|
var value = buttons[0].getValue(); |
|
valueMap.workDay = (value.offset === 0 ? -value.value : value.value); |
|
} |
|
return valueMap; |
|
} |
|
|
|
}); |
|
BI.shortcut("bi.dynamic_date_card", BI.DynamicDateCard); |
|
|
|
BI.extend(BI.DynamicDateCard, { |
|
TYPE: { |
|
YEAR: 1, |
|
QUARTER: 2, |
|
MONTH: 3, |
|
WEEK: 4, |
|
DAY: 5, |
|
WORK_DAY: 6 |
|
}, |
|
OFFSET: { |
|
CURRENT: 1, |
|
BEGIN: 2, |
|
END: 3 |
|
} |
|
|
|
});BI.DynamicDateCombo = BI.inherit(BI.Single, { |
|
constants: { |
|
popupHeight: 259, |
|
popupWidth: 270, |
|
comboAdjustHeight: 1, |
|
border: 1 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-combo bi-border bi-focus-shadow bi-border-radius", |
|
height: 22, |
|
minDate: "1900-01-01", |
|
maxDate: "2099-12-31", |
|
format: "", |
|
allowEdit: true |
|
}, |
|
|
|
|
|
render: function () { |
|
var self = this, opts = this.options; |
|
this.storeTriggerValue = ""; |
|
var date = BI.getDate(); |
|
this.storeValue = opts.value; |
|
return { |
|
type: "bi.htape", |
|
items: [{ |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-change-h-font", |
|
width: opts.height, |
|
height: opts.height, |
|
ref: function () { |
|
self.changeIcon = this; |
|
} |
|
}, |
|
width: opts.height |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.combo", |
|
container: opts.container, |
|
ref: function () { |
|
self.combo = this; |
|
}, |
|
toggle: false, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
destroyWhenHide: true, |
|
el: { |
|
type: "bi.dynamic_date_trigger", |
|
min: opts.minDate, |
|
max: opts.maxDate, |
|
format: opts.format, |
|
allowEdit: opts.allowEdit, |
|
watermark: opts.watermark, |
|
height: opts.height, |
|
value: opts.value, |
|
ref: function () { |
|
self.trigger = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicDateTrigger.EVENT_KEY_DOWN, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_KEY_DOWN, arguments); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_STOP, |
|
action: function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_FOCUS, |
|
action: function () { |
|
self.storeTriggerValue = self.trigger.getKey(); |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_ERROR, |
|
action: function () { |
|
self.storeValue = { |
|
type: BI.DynamicDateCombo.Static, |
|
value: { |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1 |
|
} |
|
}; |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_ERROR); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_VALID, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_VALID); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTrigger.EVENT_CONFIRM, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
return; |
|
} |
|
var dateStore = self.storeTriggerValue; |
|
var dateObj = self.trigger.getKey(); |
|
if (BI.isNotEmptyString(dateObj) && !BI.isEqual(dateObj, dateStore)) { |
|
self.storeValue = self.trigger.getValue(); |
|
self.setValue(self.trigger.getValue()); |
|
} else if (BI.isEmptyString(dateObj)) { |
|
self.storeValue = null; |
|
self.trigger.setValue(); |
|
} |
|
self._checkDynamicValue(self.storeValue); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}, |
|
adjustLength: this.constants.comboAdjustHeight, |
|
popup: { |
|
el: { |
|
type: "bi.dynamic_date_popup", |
|
behaviors: opts.behaviors, |
|
min: opts.minDate, |
|
max: opts.maxDate, |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicDatePopup.BUTTON_CLEAR_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicDatePopup.BUTTON_lABEL_EVENT_CHANGE, |
|
action: function () { |
|
var date = BI.getDate(); |
|
self.setValue({ |
|
type: BI.DynamicDateCombo.Static, |
|
value: { |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
} |
|
}); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicDatePopup.BUTTON_OK_EVENT_CHANGE, |
|
action: function () { |
|
var value = self.popup.getValue(); |
|
if(self._checkValue(value)) { |
|
self.setValue(value); |
|
} |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicDatePopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}, |
|
stopPropagation: false |
|
}, |
|
// DEC-4250 和复选下拉一样,点击triggerBtn不默认收起 |
|
hideChecker: function (e) { |
|
return self.triggerBtn.element.find(e.target).length === 0; |
|
}, |
|
listeners: [{ |
|
eventName: BI.Combo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
self.popup.setValue(self.storeValue); |
|
self.popup.setMinDate(opts.minDate); |
|
self.popup.setMaxDate(opts.maxDate); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_BEFORE_POPUPVIEW); |
|
} |
|
}] |
|
}, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-font", |
|
width: opts.height, |
|
height: opts.height, |
|
listeners: [{ |
|
eventName: BI.IconButton.EVENT_CHANGE, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
// self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
} |
|
}], |
|
ref: function () { |
|
self.triggerBtn = this; |
|
} |
|
}, |
|
top: 0, |
|
right: 0 |
|
}] |
|
}], |
|
ref: function (_ref) { |
|
self.comboWrapper = _ref; |
|
} |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
this._checkDynamicValue(this.storeValue); |
|
}, |
|
|
|
_checkDynamicValue: function (v) { |
|
var o = this.options; |
|
var type = null; |
|
if (BI.isNotNull(v)) { |
|
type = v.type; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.changeIcon.setVisible(true); |
|
this.comboWrapper.attr("items")[0].width = o.height; |
|
this.comboWrapper.resize(); |
|
break; |
|
default: |
|
this.comboWrapper.attr("items")[0].width = 0; |
|
this.comboWrapper.resize(); |
|
this.changeIcon.setVisible(false); |
|
break; |
|
} |
|
}, |
|
|
|
_checkValue: function (v) { |
|
switch (v.type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
return BI.isNotEmptyObject(v.value); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
return true; |
|
} |
|
}, |
|
|
|
_defaultState: function () { |
|
|
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
var o = this.options; |
|
o.minDate = minDate; |
|
this.trigger.setMinDate(minDate); |
|
this.popup && this.popup.setMinDate(minDate); |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
var o = this.options; |
|
o.maxDate = maxDate; |
|
this.trigger.setMaxDate(maxDate); |
|
this.popup && this.popup.setMaxDate(maxDate); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.trigger.setValue(v); |
|
this._checkDynamicValue(v); |
|
}, |
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
getKey: function () { |
|
return this.trigger.getKey(); |
|
}, |
|
hidePopupView: function () { |
|
this.combo.hideView(); |
|
} |
|
}); |
|
|
|
BI.DynamicDateCombo.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.DynamicDateCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicDateCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicDateCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.DynamicDateCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DynamicDateCombo.EVENT_VALID = "EVENT_VALID"; |
|
BI.DynamicDateCombo.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicDateCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
|
|
BI.shortcut("bi.dynamic_date_combo", BI.DynamicDateCombo); |
|
|
|
BI.extend(BI.DynamicDateCombo, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});BI.DynamicDateParamItem = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-param-item", |
|
dateType: BI.DynamicDateCard.TYPE.YEAR, |
|
value: 0, |
|
offset: 0, |
|
height: 24 |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.htape", |
|
items: [{ |
|
el: { |
|
type: "bi.sign_editor", |
|
cls: "bi-border", |
|
height: 22, |
|
validationChecker: function (v) { |
|
return BI.isNaturalNumber(v); |
|
}, |
|
value: o.value, |
|
ref: function () { |
|
self.editor = this; |
|
}, |
|
errorText: function (v) { |
|
if(BI.isEmptyString(v)) { |
|
return BI.i18nText("BI-Basic_Please_Input_Content"); |
|
} |
|
return BI.i18nText("BI-Please_Input_Natural_Number"); |
|
}, |
|
allowBlank: false, |
|
listeners: [{ |
|
eventName: BI.SignEditor.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateParamItem.EVENT_CHANGE); |
|
} |
|
}] |
|
}, |
|
width: 60 |
|
}, { |
|
el: { |
|
type: "bi.label", |
|
height: 24, |
|
text: this._getText() |
|
}, |
|
width: o.dateType === BI.DynamicDateCard.TYPE.WORK_DAY ? 60 : 20 |
|
}, { |
|
type: "bi.text_value_combo", |
|
height: 24, |
|
items: [{ |
|
text: BI.i18nText("BI-Basic_Front"), |
|
value: 0 |
|
}, { |
|
text: BI.i18nText("BI-Basic_Behind"), |
|
value: 1 |
|
}], |
|
ref: function () { |
|
self.offsetCombo = this; |
|
}, |
|
container: null, |
|
value: o.offset, |
|
listeners: [{ |
|
eventName: BI.TextValueCombo.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateParamItem.EVENT_CHANGE); |
|
} |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
_getText: function () { |
|
var text = ""; |
|
switch (this.options.dateType) { |
|
case BI.DynamicDateCard.TYPE.YEAR: |
|
text = BI.i18nText("BI-Basic_Year"); |
|
break; |
|
case BI.DynamicDateCard.TYPE.QUARTER: |
|
text = BI.i18nText("BI-Basic_Single_Quarter"); |
|
break; |
|
case BI.DynamicDateCard.TYPE.MONTH: |
|
text = BI.i18nText("BI-Basic_Month"); |
|
break; |
|
case BI.DynamicDateCard.TYPE.WEEK: |
|
text = BI.i18nText("BI-Basic_Week"); |
|
break; |
|
case BI.DynamicDateCard.TYPE.DAY: |
|
text = BI.i18nText("BI-Basic_Day"); |
|
break; |
|
case BI.DynamicDateCard.TYPE.WORK_DAY: |
|
default: |
|
text = BI.i18nText("BI-Basic_Work_Day"); |
|
break; |
|
} |
|
return text; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {}; |
|
v.value = v.value || 0; |
|
v.offset = v.offset || 0; |
|
this.editor.setValue(v.value); |
|
this.offsetCombo.setValue(v.offset); |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
dateType: this.options.dateType, |
|
value: this.editor.getValue(), |
|
offset: this.offsetCombo.getValue()[0] |
|
}; |
|
} |
|
|
|
}); |
|
BI.DynamicDateParamItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_date_param_item", BI.DynamicDateParamItem); |
|
BI.DynamicDatePopup = BI.inherit(BI.Widget, { |
|
constants: { |
|
tabHeight: 30, |
|
buttonHeight: 24 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-popup", |
|
width: 248, |
|
height: 344 |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicDatePopup.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options, c = this.constants; |
|
this.storeValue = {type: BI.DynamicDateCombo.Static}; |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.vtape", |
|
items: [{ |
|
el: this._getTabJson() |
|
}, { |
|
el: { |
|
type: "bi.grid", |
|
items: [[{ |
|
type: "bi.text_button", |
|
cls: "bi-high-light bi-split-top", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Clear"), |
|
textHeight: c.buttonHeight - 1, |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDatePopup.BUTTON_CLEAR_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-left bi-split-right bi-high-light bi-split-top", |
|
shadow: true, |
|
textHeight: c.buttonHeight - 1, |
|
text: BI.i18nText("BI-Multi_Date_Today"), |
|
ref: function () { |
|
self.textButton = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDatePopup.BUTTON_lABEL_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-high-light bi-split-top", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_OK"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDatePopup.BUTTON_OK_EVENT_CHANGE); |
|
} |
|
}] |
|
}]] |
|
}, |
|
height: 24 |
|
}] |
|
}); |
|
this.setValue(opts.value); |
|
}, |
|
|
|
_getTabJson: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
tab: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: this.constants.tabHeight, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Multi_Date_YMD"), |
|
value: BI.DynamicDateCombo.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicDateCombo.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}) |
|
}, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
return { |
|
type: "bi.dynamic_date_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self._setInnerValue(self.year, v); |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
return { |
|
type: "bi.date_calendar_popup", |
|
behaviors: o.behaviors, |
|
min: self.options.min, |
|
max: self.options.max, |
|
listeners: [{ |
|
eventName: BI.DateCalendarPopup.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDatePopup.EVENT_CHANGE); |
|
} |
|
}], |
|
ref: function () { |
|
self.ymd = this; |
|
} |
|
}; |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Tab.EVENT_CHANGE, |
|
action: function () { |
|
var v = self.dateTab.getSelect(); |
|
switch (v) { |
|
case BI.DynamicDateCombo.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Dynamic: |
|
default: |
|
if(self.storeValue && self.storeValue.type === BI.DynamicDateCombo.Dynamic) { |
|
self.dynamicPane.setValue(self.storeValue.value); |
|
}else{ |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
} |
|
self._setInnerValue(); |
|
break; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
_setInnerValue: function () { |
|
if (this.dateTab.getSelect() === BI.DynamicDateCombo.Static) { |
|
this.textButton.setValue(BI.i18nText("BI-Multi_Date_Today")); |
|
this.textButton.setEnable(true); |
|
} else { |
|
var date = BI.DynamicDateHelper.getCalculation(this.dynamicPane.getValue()); |
|
date = BI.print(date, "%Y-%X-%d"); |
|
this.textButton.setValue(date); |
|
this.textButton.setEnable(false); |
|
} |
|
}, |
|
|
|
_checkValueValid: function (value) { |
|
return BI.isNull(value) || BI.isEmptyObject(value) || BI.isEmptyString(value); |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (this.options.min !== minDate) { |
|
this.options.min = minDate; |
|
this.ymd.setMinDate(minDate); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (this.options.max !== maxDate) { |
|
this.options.max = maxDate; |
|
this.ymd.setMaxDate(maxDate); |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
var self = this; |
|
var type, value; |
|
v = v || {}; |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (this._checkValueValid(value)) { |
|
var date = BI.getDate(); |
|
this.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
this.textButton.setValue(BI.i18nText("BI-Multi_Date_Today")); |
|
} else { |
|
this.ymd.setValue(value); |
|
this.textButton.setValue(BI.i18nText("BI-Multi_Date_Today")); |
|
} |
|
this.textButton.setEnable(true); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: this.dateTab.getSelect(), |
|
value: this.dateTab.getValue() |
|
}; |
|
} |
|
}); |
|
BI.DynamicDatePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DynamicDatePopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.DynamicDatePopup.BUTTON_lABEL_EVENT_CHANGE = "BUTTON_lABEL_EVENT_CHANGE"; |
|
BI.DynamicDatePopup.BUTTON_CLEAR_EVENT_CHANGE = "BUTTON_CLEAR_EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_date_popup", BI.DynamicDatePopup);BI.DynamicDateTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4, |
|
vgap: 2, |
|
yearLength: 4, |
|
yearMonthLength: 6, |
|
yearFullMonthLength: 7, |
|
compareFormat: "%Y-%X-%d" |
|
}, |
|
|
|
props: { |
|
extraCls: "bi-date-trigger", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 24, |
|
format: "", // 显示的日期格式化方式 |
|
allowEdit: true, // 是否允许编辑 |
|
watermark: "" |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicDateTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.storeTriggerValue = ""; |
|
this.editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
validationChecker: function (v) { |
|
var formatStr = self._getStandardDateStr(v); |
|
var date = formatStr.match(/\d+/g); |
|
!BI.isKey(o.format) && self._autoAppend(v, date); |
|
return self._dateCheck(formatStr) && BI.checkDateLegal(formatStr) && self._checkVoid({ |
|
year: date[0] | 0, |
|
month: date[1] | 0, |
|
day: date[2] | 0 |
|
}); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
hgap: c.hgap, |
|
vgap: c.vgap, |
|
allowBlank: true, |
|
watermark: BI.isKey(o.watermark) ? o.watermark : BI.i18nText("BI-Basic_Unrestricted"), |
|
errorText: function () { |
|
var str = ""; |
|
if (!BI.isKey(o.format)) { |
|
str = self.editor.isEditing() ? BI.i18nText("BI-Date_Trigger_Error_Text") : BI.i18nText("BI-Year_Trigger_Invalid_Text"); |
|
} |
|
return str; |
|
}, |
|
title: BI.bind(this._getTitle, this) |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_KEY_DOWN, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_KEY_DOWN, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_FOCUS, function () { |
|
self.storeTriggerValue = self.getKey(); |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_BLUR); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_STOP, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_STOP); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_VALID, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_VALID); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_ERROR); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_CONFIRM, function () { |
|
var value = self.editor.getValue(); |
|
if (BI.isNotNull(value)) { |
|
self.editor.setState(value); |
|
} |
|
|
|
if (BI.isNotEmptyString(value) && !BI.isEqual(self.storeTriggerValue, self.getKey())) { |
|
var formatStr = self._getStandardDateStr(value); |
|
var date = formatStr.match(/\d+/g); |
|
self.storeValue = { |
|
type: BI.DynamicDateCombo.Static, |
|
value: { |
|
year: date[0] | 0, |
|
month: date[1] | 0, |
|
day: date[2] | 0 |
|
} |
|
}; |
|
} |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_CONFIRM); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_SPACE, function () { |
|
if (self.editor.isValid()) { |
|
self.editor.blur(); |
|
} |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_START, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_START); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DynamicDateTrigger.EVENT_CHANGE); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
el: this.editor |
|
}, { |
|
el: BI.createWidget(), |
|
width: 24 |
|
}] |
|
}); |
|
!o.allowEdit && BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.text", |
|
title: BI.bind(this._getTitle, this) |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.setValue(o.value); |
|
}, |
|
|
|
_getTitle: function () { |
|
var storeValue = this.storeValue || {}; |
|
var type = storeValue.type || BI.DynamicDateCombo.Static; |
|
var value = storeValue.value; |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
var date = BI.getDate(); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
var dateStr = BI.print(date, this._getFormatString()); |
|
return BI.isEmptyString(text) ? dateStr : (text + ":" + dateStr); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (BI.isNull(value) || BI.isNull(value.day)) { |
|
return ""; |
|
} |
|
return BI.print(BI.getDate(value.year, (value.month - 1), value.day), this._getFormatString()); |
|
} |
|
}, |
|
|
|
_getStandardDateStr: function (v) { |
|
var c = this._const; |
|
var result = [0, 1, 2]; |
|
var formatArray = this._getFormatString().match(/%./g); |
|
BI.each(formatArray, function (idx, v) { |
|
switch (v) { |
|
case "%Y": |
|
case "%y": |
|
result[0] = idx; |
|
break; |
|
case "%X": |
|
case "%x": |
|
result[1] = idx; |
|
break; |
|
case "%d": |
|
case "%e": |
|
default: |
|
result[2] = idx; |
|
break; |
|
} |
|
}); |
|
// 这边不能直接用\d+去切日期, 因为format格式可能是20190607这样的没有分割符的 = = |
|
// 先看一下是否是合法的, 如果合法就变成标准格式的走原来的流程, 不合法不关心 |
|
var date = BI.parseDateTime(v, this._getFormatString()); |
|
if(BI.print(date, this._getFormatString()) === v) { |
|
v = BI.print(date, c.compareFormat); |
|
result = [0, 1, 2]; |
|
} |
|
var dateArray = v.match(/\d+/g); |
|
var newArray = []; |
|
BI.each(dateArray, function (idx) { |
|
newArray[idx] = dateArray[result[idx]]; |
|
}); |
|
// 这边之所以不直接返回join结果是因为年的格式可能只有2位,所以需要format一下 |
|
if(newArray.length === result.length && newArray[0].length === 2) { |
|
return BI.print(BI.parseDateTime(newArray.join("-"), c.compareFormat), c.compareFormat); |
|
} |
|
// 这边format成-20-也没关系, 反正都是不合法的 |
|
return newArray.join("-"); |
|
}, |
|
|
|
_getFormatString: function () { |
|
return this.options.format || this._const.compareFormat; |
|
}, |
|
|
|
_dateCheck: function (date) { |
|
return BI.print(BI.parseDateTime(date, "%Y-%x-%d"), "%Y-%x-%d") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%d"), "%Y-%X-%d") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%x-%e"), "%Y-%x-%e") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%e"), "%Y-%X-%e") === date; |
|
}, |
|
_checkVoid: function (obj) { |
|
return !BI.checkDateVoid(obj.year, obj.month, obj.day, this.options.min, this.options.max)[0]; |
|
}, |
|
_autoAppend: function (v, dateObj) { |
|
if (BI.isNotNull(dateObj) && BI.checkDateLegal(v)) { |
|
switch (v.length) { |
|
case this._const.yearLength: |
|
if (this._yearCheck(v)) { |
|
this.editor.setValue(v + "-"); |
|
} |
|
break; |
|
case this._const.yearMonthLength: |
|
case this._const.yearFullMonthLength: |
|
var splitMonth = v.split("-")[1]; |
|
if ((BI.isNotNull(splitMonth) && splitMonth.length === 2) || this._monthCheck(v)) { |
|
this.editor.setValue(v + "-"); |
|
} |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
_yearCheck: function (v) { |
|
var date = BI.print(BI.parseDateTime(v, this._getFormatString()), this._const.compareFormat); |
|
return BI.print(BI.parseDateTime(v, "%Y"), "%Y") === v && date >= this.options.min && date <= this.options.max; |
|
}, |
|
|
|
_monthCheck: function (v) { |
|
var date = BI.parseDateTime(v, this._getFormatString()); |
|
var dateStr = BI.print(date, this._const.compareFormat); |
|
return (date.getMonth() >= 0 && (BI.print(BI.parseDateTime(v, "%Y-%X"), "%Y-%X") === v || |
|
BI.print(BI.parseDateTime(v, "%Y-%x"), "%Y-%x") === v)) && dateStr >= this.options.min && dateStr <= this.options.max; |
|
}, |
|
|
|
_setInnerValue: function (date) { |
|
var dateStr = BI.print(date, this._getFormatString()); |
|
this.editor.setState(dateStr); |
|
this.editor.setValue(dateStr); |
|
}, |
|
|
|
_getText: function (obj) { |
|
var value = ""; |
|
var endText = ""; |
|
if(BI.isNotNull(obj.year)) { |
|
if(BI.parseInt(obj.year) !== 0) { |
|
value += Math.abs(obj.year) + BI.i18nText("BI-Basic_Year") + (obj.year < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Year"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.quarter)) { |
|
if(BI.parseInt(obj.quarter) !== 0) { |
|
value += Math.abs(obj.quarter) + BI.i18nText("BI-Basic_Single_Quarter") + (obj.quarter < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Single_Quarter"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.month)) { |
|
if(BI.parseInt(obj.month) !== 0) { |
|
value += Math.abs(obj.month) + BI.i18nText("BI-Basic_Month") + (obj.month < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Month"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.week)) { |
|
if(BI.parseInt(obj.week) !== 0) { |
|
value += Math.abs(obj.week) + BI.i18nText("BI-Basic_Week") + (obj.week < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Week"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.day)) { |
|
if(BI.parseInt(obj.day) !== 0) { |
|
value += Math.abs(obj.day) + BI.i18nText("BI-Basic_Day") + (obj.day < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = BI.size(obj) === 1 ? getPositionText(BI.i18nText("BI-Basic_Month"), obj.position) : ""; |
|
} |
|
if(BI.isNotNull(obj.workDay) && BI.parseInt(obj.workDay) !== 0) { |
|
value += Math.abs(obj.workDay) + BI.i18nText("BI-Basic_Work_Day") + (obj.workDay < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
return value + endText; |
|
|
|
function getPositionText (baseText, position) { |
|
switch (position) { |
|
case BI.DynamicDateCard.OFFSET.BEGIN: |
|
return baseText + BI.i18nText("BI-Basic_Begin_Start"); |
|
case BI.DynamicDateCard.OFFSET.END: |
|
return baseText + BI.i18nText("BI-Basic_End_Stop"); |
|
case BI.DynamicDateCard.OFFSET.CURRENT: |
|
default: |
|
return BI.i18nText("BI-Basic_Current_Day"); |
|
} |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
var type, value, self = this; |
|
var date = BI.getDate(); |
|
this.storeValue = v; |
|
if (BI.isNotNull(v)) { |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
this._setInnerValue(date, text); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (BI.isNull(value) || BI.isNull(value.day)) { |
|
this.editor.setState(""); |
|
this.editor.setValue(""); |
|
} else { |
|
var dateStr = BI.print(BI.getDate(value.year, (value.month - 1), value.day), this._getFormatString()); |
|
this.editor.setState(dateStr); |
|
this.editor.setValue(dateStr); |
|
} |
|
break; |
|
} |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (BI.isNotEmptyString(this.options.min)) { |
|
this.options.min = minDate; |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (BI.isNotEmptyString(this.options.max)) { |
|
this.options.max = maxDate; |
|
} |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
getValue: function () { |
|
return this.storeValue; |
|
} |
|
|
|
}); |
|
|
|
BI.DynamicDateTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.DynamicDateTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicDateTrigger.EVENT_START = "EVENT_START"; |
|
BI.DynamicDateTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.DynamicDateTrigger.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicDateTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DynamicDateTrigger.EVENT_VALID = "EVENT_VALID"; |
|
BI.DynamicDateTrigger.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicDateTrigger.EVENT_TRIGGER_CLICK = "EVENT_TRIGGER_CLICK"; |
|
BI.DynamicDateTrigger.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.shortcut("bi.dynamic_date_trigger", BI.DynamicDateTrigger); |
|
BI.DynamicDateTimeCombo = BI.inherit(BI.Single, { |
|
constants: { |
|
popupHeight: 259, |
|
popupWidth: 270, |
|
comboAdjustHeight: 1, |
|
border: 1 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-combo bi-border bi-focus-shadow bi-border-radius", |
|
height: 22, |
|
minDate: "1900-01-01", |
|
maxDate: "2099-12-31", |
|
format: "", |
|
allowEdit: true |
|
}, |
|
|
|
|
|
render: function () { |
|
var self = this, opts = this.options; |
|
this.storeTriggerValue = ""; |
|
var date = BI.getDate(); |
|
this.storeValue = opts.value; |
|
return { |
|
type: "bi.htape", |
|
items: [{ |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-change-h-font", |
|
width: opts.height, |
|
height: opts.height, |
|
ref: function () { |
|
self.changeIcon = this; |
|
} |
|
}, |
|
width: opts.height |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.combo", |
|
destroyWhenHide: true, |
|
container: opts.container, |
|
ref: function () { |
|
self.combo = this; |
|
}, |
|
toggle: false, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: { |
|
type: "bi.dynamic_date_time_trigger", |
|
min: opts.minDate, |
|
max: opts.maxDate, |
|
allowEdit: opts.allowEdit, |
|
watermark: opts.watermark, |
|
format: opts.format, |
|
height: opts.height, |
|
value: opts.value, |
|
ref: function () { |
|
self.trigger = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_KEY_DOWN, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_KEY_DOWN, arguments); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_STOP, |
|
action: function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_TRIGGER_CLICK, |
|
action: function () { |
|
self.combo.toggle(); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_FOCUS, |
|
action: function () { |
|
self.storeTriggerValue = self.trigger.getKey(); |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_ERROR, |
|
action: function () { |
|
self.storeValue = { |
|
type: BI.DynamicDateTimeCombo.Static, |
|
value: { |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1 |
|
} |
|
}; |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_ERROR); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_VALID, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_VALID); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimeTrigger.EVENT_CONFIRM, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
return; |
|
} |
|
var dateStore = self.storeTriggerValue; |
|
var dateObj = self.trigger.getKey(); |
|
if (BI.isNotEmptyString(dateObj) && !BI.isEqual(dateObj, dateStore)) { |
|
self.storeValue = self.trigger.getValue(); |
|
self.setValue(self.trigger.getValue()); |
|
} else if (BI.isEmptyString(dateObj)) { |
|
self.storeValue = null; |
|
self.trigger.setValue(); |
|
} |
|
self._checkDynamicValue(self.storeValue); |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}, |
|
adjustLength: this.constants.comboAdjustHeight, |
|
popup: { |
|
el: { |
|
type: "bi.dynamic_date_time_popup", |
|
behaviors: opts.behaviors, |
|
min: opts.minDate, |
|
max: opts.maxDate, |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicDateTimePopup.BUTTON_CLEAR_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimePopup.BUTTON_lABEL_EVENT_CHANGE, |
|
action: function () { |
|
var date = BI.getDate(); |
|
self.setValue({ |
|
type: BI.DynamicDateTimeCombo.Static, |
|
value: { |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate(), |
|
hour: 0, |
|
minute: 0, |
|
second: 0 |
|
} |
|
}); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimePopup.BUTTON_OK_EVENT_CHANGE, |
|
action: function () { |
|
var value = self.popup.getValue(); |
|
if(self._checkValue(value)) { |
|
self.setValue(value); |
|
} |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicDateTimePopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}, |
|
stopPropagation: false |
|
}, |
|
listeners: [{ |
|
eventName: BI.Combo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
self.popup.setValue(self.storeValue); |
|
self.popup.setMinDate(opts.minDate); |
|
self.popup.setMaxDate(opts.maxDate); |
|
self.fireEvent(BI.DynamicDateTimeCombo.EVENT_BEFORE_POPUPVIEW); |
|
} |
|
}], |
|
// DEC-4250 和复选下拉一样,点击不收起 |
|
hideChecker: function (e) { |
|
return self.triggerBtn.element.find(e.target).length === 0; |
|
} |
|
}, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-font", |
|
width: opts.height, |
|
height: opts.height, |
|
listeners: [{ |
|
eventName: BI.IconButton.EVENT_CHANGE, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
// self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
} |
|
}], |
|
ref: function () { |
|
self.triggerBtn = this; |
|
} |
|
}, |
|
top: 0, |
|
right: 0 |
|
}] |
|
}], |
|
ref: function (_ref) { |
|
self.comboWrapper = _ref; |
|
} |
|
}; |
|
}, |
|
|
|
mounted: function () { |
|
this._checkDynamicValue(this.storeValue); |
|
}, |
|
|
|
_checkDynamicValue: function (v) { |
|
var o = this.options; |
|
var type = null; |
|
if (BI.isNotNull(v)) { |
|
type = v.type; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateTimeCombo.Dynamic: |
|
this.changeIcon.setVisible(true); |
|
this.comboWrapper.attr("items")[0].width = o.height; |
|
this.comboWrapper.resize(); |
|
break; |
|
default: |
|
this.comboWrapper.attr("items")[0].width = 0; |
|
this.comboWrapper.resize(); |
|
this.changeIcon.setVisible(false); |
|
break; |
|
} |
|
}, |
|
|
|
_checkValue: function (v) { |
|
switch (v.type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
return BI.isNotEmptyObject(v.value); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
return true; |
|
} |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
var o = this.options; |
|
o.minDate = minDate; |
|
this.trigger.setMinDate(minDate); |
|
this.popup && this.popup.setMinDate(minDate); |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
var o = this.options; |
|
o.maxDate = maxDate; |
|
this.trigger.setMaxDate(maxDate); |
|
this.popup && this.popup.setMaxDate(maxDate); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.trigger.setValue(v); |
|
this._checkDynamicValue(v); |
|
}, |
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
getKey: function () { |
|
return this.trigger.getKey(); |
|
}, |
|
hidePopupView: function () { |
|
this.combo.hideView(); |
|
}, |
|
|
|
isValid: function () { |
|
return this.trigger.isValid(); |
|
} |
|
}); |
|
|
|
BI.DynamicDateTimeCombo.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.DynamicDateTimeCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicDateTimeCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicDateTimeCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.DynamicDateTimeCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DynamicDateTimeCombo.EVENT_VALID = "EVENT_VALID"; |
|
BI.DynamicDateTimeCombo.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicDateTimeCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
|
|
BI.shortcut("bi.dynamic_date_time_combo", BI.DynamicDateTimeCombo); |
|
|
|
BI.extend(BI.DynamicDateTimeCombo, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});BI.DynamicDateTimePopup = BI.inherit(BI.Widget, { |
|
constants: { |
|
tabHeight: 30, |
|
buttonHeight: 24 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-dynamic-date-time-popup", |
|
width: 248, |
|
height: 385 |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicDateTimePopup.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options, c = this.constants; |
|
this.storeValue = {type: BI.DynamicDateCombo.Static}; |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.vtape", |
|
items: [{ |
|
el: this._getTabJson() |
|
}, { |
|
el: { |
|
type: "bi.grid", |
|
items: [[{ |
|
type: "bi.text_button", |
|
cls: "bi-high-light bi-split-top", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Clear"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateTimePopup.BUTTON_CLEAR_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-left bi-split-right bi-high-light bi-split-top", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Multi_Date_Today"), |
|
ref: function () { |
|
self.textButton = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateTimePopup.BUTTON_lABEL_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-high-light bi-split-top", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_OK"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicDateTimePopup.BUTTON_OK_EVENT_CHANGE); |
|
} |
|
}] |
|
}]] |
|
}, |
|
height: 24 |
|
}] |
|
}); |
|
this.setValue(opts.value); |
|
}, |
|
|
|
_getTabJson: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
tab: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: this.constants.tabHeight, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Multi_Date_YMD"), |
|
value: BI.DynamicDateCombo.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicDateCombo.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}) |
|
}, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
return { |
|
type: "bi.dynamic_date_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self._setInnerValue(self.year, v); |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
type: "bi.date_calendar_popup", |
|
behaviors: o.behaviors, |
|
min: self.options.min, |
|
max: self.options.max, |
|
ref: function () { |
|
self.ymd = this; |
|
} |
|
}, { |
|
el: { |
|
type: "bi.dynamic_date_time_select", |
|
cls: "bi-split-top", |
|
ref: function () { |
|
self.timeSelect = this; |
|
} |
|
}, |
|
height: 40 |
|
}] |
|
}; |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Tab.EVENT_CHANGE, |
|
action: function () { |
|
var v = self.dateTab.getSelect(); |
|
switch (v) { |
|
case BI.DynamicDateCombo.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
self.timeSelect.setValue(); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Dynamic: |
|
default: |
|
if(self.storeValue && self.storeValue.type === BI.DynamicDateCombo.Dynamic) { |
|
self.dynamicPane.setValue(self.storeValue.value); |
|
}else{ |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
} |
|
self._setInnerValue(); |
|
break; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
_setInnerValue: function () { |
|
if (this.dateTab.getSelect() === BI.DynamicDateCombo.Static) { |
|
this.textButton.setValue(BI.i18nText("BI-Multi_Date_Today")); |
|
this.textButton.setEnable(true); |
|
} else { |
|
var date = BI.DynamicDateHelper.getCalculation(this.dynamicPane.getValue()); |
|
date = BI.print(date, "%Y-%X-%d"); |
|
this.textButton.setValue(date); |
|
this.textButton.setEnable(false); |
|
} |
|
}, |
|
|
|
_checkValueValid: function (value) { |
|
return BI.isNull(value) || BI.isEmptyObject(value) || BI.isEmptyString(value); |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (this.options.min !== minDate) { |
|
this.options.min = minDate; |
|
this.ymd.setMinDate(minDate); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (this.options.max !== maxDate) { |
|
this.options.max = maxDate; |
|
this.ymd.setMaxDate(maxDate); |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
var self = this; |
|
var type, value; |
|
v = v || {}; |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (this._checkValueValid(value)) { |
|
var date = BI.getDate(); |
|
this.ymd.setValue({ |
|
year: date.getFullYear(), |
|
month: date.getMonth() + 1, |
|
day: date.getDate() |
|
}); |
|
this.timeSelect.setValue(); |
|
this.textButton.setValue(BI.i18nText("BI-Multi_Date_Today")); |
|
} else { |
|
this.ymd.setValue(value); |
|
this.timeSelect.setValue({ |
|
hour: value.hour, |
|
minute: value.minute, |
|
second: value.second |
|
}); |
|
this.textButton.setValue(BI.i18nText("BI-Multi_Date_Today")); |
|
} |
|
this.textButton.setEnable(true); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
var type = this.dateTab.getSelect(); |
|
return { |
|
type: type, |
|
value: type === BI.DynamicDateTimeCombo.Static ? BI.extend(this.ymd.getValue(), this.timeSelect.getValue()) : this.dynamicPane.getValue() |
|
}; |
|
} |
|
}); |
|
BI.DynamicDateTimePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DynamicDateTimePopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.DynamicDateTimePopup.BUTTON_lABEL_EVENT_CHANGE = "BUTTON_lABEL_EVENT_CHANGE"; |
|
BI.DynamicDateTimePopup.BUTTON_CLEAR_EVENT_CHANGE = "BUTTON_CLEAR_EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_date_time_popup", BI.DynamicDateTimePopup);BI.DynamicDateTimeSelect = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-date-time-select" |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
return { |
|
type: "bi.center_adapt", |
|
items: [{ |
|
type: "bi.vertical_adapt", |
|
items: [{ |
|
el: { |
|
type: "bi.number_editor", |
|
ref: function () { |
|
self.hour = this; |
|
}, |
|
validationChecker: function (v) { |
|
return BI.isNaturalNumber(v) && BI.parseInt(v) < 24; |
|
}, |
|
errorText: function (v) { |
|
if(BI.isNumeric(v)) { |
|
return BI.i18nText("BI-Basic_Input_From_To_Number", "\"00-23\""); |
|
} |
|
return BI.i18nText("BI-Numerical_Interval_Input_Data"); |
|
}, |
|
listeners: [{ |
|
eventName: BI.SignEditor.EVENT_CONFIRM, |
|
action: function () { |
|
var value = this.getValue(); |
|
self._checkHour(value); |
|
this.setValue(self._formatValueToDoubleDigit(value)); |
|
self.fireEvent(BI.DynamicDateTimeSelect.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.SignEditor.EVENT_CHANGE, |
|
action: function () { |
|
var value = self._autoSwitch(this.getValue(), BI.DynamicDateTimeSelect.HOUR); |
|
this.setValue(value); |
|
} |
|
}], |
|
width: 60, |
|
height: 24 |
|
} |
|
}, { |
|
type: "bi.label", |
|
text: ":", |
|
width: 20 |
|
}, { |
|
type: "bi.number_editor", |
|
ref: function () { |
|
self.minute = this; |
|
}, |
|
validationChecker: function (v) { |
|
return BI.isNaturalNumber(v) && BI.parseInt(v) < 60; |
|
}, |
|
errorText: function (v) { |
|
if(BI.isNumeric(v)) { |
|
return BI.i18nText("BI-Basic_Input_From_To_Number", "\"00-59\""); |
|
} |
|
return BI.i18nText("BI-Numerical_Interval_Input_Data"); |
|
}, |
|
listeners: [{ |
|
eventName: BI.SignEditor.EVENT_CONFIRM, |
|
action: function () { |
|
var value = this.getValue(); |
|
self._checkMinute(value); |
|
this.setValue(self._formatValueToDoubleDigit(value), BI.DynamicDateTimeSelect.MINUTE); |
|
self.fireEvent(BI.DynamicDateTimeSelect.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.SignEditor.EVENT_CHANGE, |
|
action: function () { |
|
var value = self._autoSwitch(this.getValue(), BI.DynamicDateTimeSelect.MINUTE); |
|
this.setValue(value); |
|
} |
|
}], |
|
width: 60, |
|
height: 24 |
|
}, { |
|
type: "bi.label", |
|
text: ":", |
|
width: 20 |
|
}, { |
|
type: "bi.number_editor", |
|
ref: function () { |
|
self.second = this; |
|
}, |
|
validationChecker: function (v) { |
|
return BI.isNaturalNumber(v) && BI.parseInt(v) < 60; |
|
}, |
|
errorText: function (v) { |
|
if(BI.isNumeric(v)) { |
|
return BI.i18nText("BI-Basic_Input_From_To_Number", "\"00-59\""); |
|
} |
|
return BI.i18nText("BI-Numerical_Interval_Input_Data"); |
|
}, |
|
listeners: [{ |
|
eventName: BI.SignEditor.EVENT_CONFIRM, |
|
action: function () { |
|
var value = this.getValue(); |
|
self._checkSecond(value); |
|
this.setValue(self._formatValueToDoubleDigit(value)); |
|
self.fireEvent(BI.DynamicDateTimeSelect.EVENT_CONFIRM); |
|
} |
|
}], |
|
width: 60, |
|
height: 24 |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
_checkBorder: function (v) { |
|
v = v || {}; |
|
this._checkHour(v.hour); |
|
this._checkMinute(v.minute); |
|
this._checkSecond(v.second); |
|
}, |
|
|
|
_checkHour: function (value) { |
|
this.hour.setDownEnable(BI.parseInt(value) > 0); |
|
this.hour.setUpEnable(BI.parseInt(value) < 23); |
|
}, |
|
|
|
_checkMinute: function (value) { |
|
this.minute.setDownEnable(BI.parseInt(value) > 0); |
|
this.minute.setUpEnable(BI.parseInt(value) < 59); |
|
}, |
|
|
|
_checkSecond: function (value) { |
|
this.second.setDownEnable(BI.parseInt(value) > 0); |
|
this.second.setUpEnable(BI.parseInt(value) < 59); |
|
}, |
|
|
|
_autoSwitch: function (v, type) { |
|
var limit = 0; |
|
var value = v + ""; |
|
switch (type) { |
|
case BI.DynamicDateTimeSelect.HOUR: |
|
limit = 2; |
|
break; |
|
case BI.DynamicDateTimeSelect.MINUTE: |
|
limit = 5; |
|
break; |
|
default: |
|
break; |
|
} |
|
if(value.length === 1 && BI.parseInt(value) > limit) { |
|
value = "0" + value; |
|
} |
|
if (value.length === 2) { |
|
switch (type) { |
|
case BI.DynamicDateTimeSelect.HOUR: |
|
this.hour.isEditing() && this.minute.focus(); |
|
break; |
|
case BI.DynamicDateTimeSelect.MINUTE: |
|
this.minute.isEditing() && this.second.focus(); |
|
break; |
|
case BI.DynamicDateTimeSelect.SECOND: |
|
default: |
|
break; |
|
} |
|
} |
|
return value; |
|
}, |
|
|
|
_formatValueToDoubleDigit: function (v) { |
|
if(BI.isNull(v) || BI.isEmptyString(v)) { |
|
v = 0; |
|
} |
|
var value = BI.parseInt(v); |
|
if(value < 10) { |
|
value = "0" + value; |
|
} |
|
return value; |
|
}, |
|
|
|
_assertValue: function (v) { |
|
v = v || {}; |
|
v.hour = this._formatValueToDoubleDigit(v.hour) || "00"; |
|
v.minute = this._formatValueToDoubleDigit(v.minute) || "00"; |
|
v.second = this._formatValueToDoubleDigit(v.second) || "00"; |
|
return v; |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
hour: BI.parseInt(this.hour.getValue()), |
|
minute: BI.parseInt(this.minute.getValue()), |
|
second: BI.parseInt(this.second.getValue()) |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = this._assertValue(v); |
|
this.hour.setValue(v.hour); |
|
this.minute.setValue(v.minute); |
|
this.second.setValue(v.second); |
|
this._checkBorder(v); |
|
} |
|
|
|
}); |
|
BI.DynamicDateTimeSelect.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.dynamic_date_time_select", BI.DynamicDateTimeSelect); |
|
|
|
BI.extend(BI.DynamicDateTimeSelect, { |
|
HOUR: 1, |
|
MINUTE: 2, |
|
SECOND: 3 |
|
});BI.DynamicDateTimeTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4, |
|
vgap: 2, |
|
yearLength: 4, |
|
yearMonthLength: 6, |
|
yearFullMonthLength: 7, |
|
compareFormat: "%Y-%X-%d %H:%M:%S" |
|
}, |
|
|
|
props: { |
|
extraCls: "bi-date-time-trigger", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 24, |
|
format: "", // 显示的日期格式化方式 |
|
allowEdit: true, // 是否允许编辑 |
|
watermark: "" |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicDateTimeTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.storeTriggerValue = ""; |
|
this.editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
validationChecker: function (v) { |
|
var formatStr = self._getStandardDateStr(v); |
|
var date = formatStr.match(/\d+/g); |
|
!BI.isKey(o.format) && self._autoAppend(v, date); |
|
return self._dateCheck(formatStr) && BI.checkDateLegal(formatStr) && self._checkVoid({ |
|
year: date[0] | 0, |
|
month: date[1] | 0, |
|
day: date[2] | 0 |
|
}); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
hgap: c.hgap, |
|
vgap: c.vgap, |
|
allowBlank: true, |
|
watermark: BI.isKey(o.watermark) ? o.watermark : BI.i18nText("BI-Basic_Unrestricted"), |
|
errorText: function () { |
|
var str = ""; |
|
if (!BI.isKey(o.format)) { |
|
str = self.editor.isEditing() ? BI.i18nText("BI-Basic_Date_Time_Error_Text") : BI.i18nText("BI-Year_Trigger_Invalid_Text"); |
|
} |
|
return str; |
|
}, |
|
title: BI.bind(this._getTitle, this) |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_KEY_DOWN, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_KEY_DOWN, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_FOCUS, function () { |
|
self.storeTriggerValue = self.getKey(); |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_BLUR); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_STOP, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_STOP); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_VALID, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_VALID); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_ERROR); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_CONFIRM, function () { |
|
var value = self.editor.getValue(); |
|
if (BI.isNotNull(value)) { |
|
self.editor.setState(value); |
|
} |
|
|
|
if (BI.isNotEmptyString(value) && !BI.isEqual(self.storeTriggerValue, self.getKey())) { |
|
var formatStr = self._getStandardDateStr(value); |
|
var date = formatStr.match(/\d+/g); |
|
self.storeValue = { |
|
type: BI.DynamicDateCombo.Static, |
|
value: { |
|
year: date[0] | 0, |
|
month: date[1] | 0, |
|
day: date[2] | 0, |
|
hour: date[3] | 0, |
|
minute: date[4] | 0, |
|
second: date[5] | 0 |
|
} |
|
}; |
|
} |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_CONFIRM); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_START, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_START); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.DynamicDateTimeTrigger.EVENT_CHANGE); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [{ |
|
el: this.editor |
|
}, { |
|
el: BI.createWidget(), |
|
width: 24 |
|
}] |
|
}); |
|
|
|
!o.allowEdit && BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.text", |
|
title: BI.bind(this._getTitle, this) |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.setValue(o.value); |
|
}, |
|
|
|
_getTitle: function () { |
|
var storeValue = this.storeValue || {}; |
|
var type = storeValue.type || BI.DynamicDateCombo.Static; |
|
var value = storeValue.value; |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
var date = BI.DynamicDateHelper.getCalculation(value); |
|
var dateStr = BI.print(date, this._getFormatString()); |
|
return BI.isEmptyString(text) ? dateStr : (text + ":" + dateStr); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (BI.isNull(value) || BI.isNull(value.day)) { |
|
return ""; |
|
} |
|
return BI.print(BI.getDate(value.year, (value.month - 1), value.day, value.hour || 0, value.minute || 0, |
|
value.second || 0), this._getFormatString()); |
|
} |
|
}, |
|
|
|
_getStandardDateStr: function (v) { |
|
var c = this._const; |
|
var result = []; |
|
var hasSecond = false; |
|
var formatArray = this._getFormatString().match(/%./g); |
|
BI.each(formatArray, function (idx, v) { |
|
switch (v) { |
|
case "%Y": |
|
case "%y": |
|
result[0] = idx; |
|
break; |
|
case "%X": |
|
case "%x": |
|
result[1] = idx; |
|
break; |
|
case "%d": |
|
case "%e": |
|
result[2] = idx; |
|
break; |
|
case "%S": |
|
hasSecond = true; |
|
break; |
|
default: |
|
break; |
|
} |
|
}); |
|
// 这边不能直接用\d+去切日期, 因为format格式可能是20190607这样的没有分割符的 = = |
|
// 先看一下是否是合法的, 如果合法就变成标准格式的走原来的流程, 不合法不关心 |
|
var date = BI.parseDateTime(v, this._getFormatString()); |
|
if(BI.print(date, this._getFormatString()) === v) { |
|
v = BI.print(date, c.compareFormat); |
|
result = [0, 1, 2]; |
|
} |
|
var dateArray = v.match(/\d+/g) || []; |
|
var newArray = []; |
|
// 处理乱序的年月日 |
|
BI.each(dateArray.slice(0, 3), function (idx) { |
|
newArray[idx] = dateArray[result[idx]]; |
|
}); |
|
// 拼接时分秒和pm |
|
var suffixArray = dateArray.slice(3); |
|
// 时分秒补0 |
|
BI.each(suffixArray, function (idx, v) { |
|
BI.isNumeric(v) && v.length === 1 && (suffixArray[idx] = "0" + v); |
|
}); |
|
// hh:mm |
|
if(suffixArray.length === 2 && !hasSecond) { |
|
suffixArray.push("00"); |
|
} |
|
var suffixString = suffixArray.join(":"); |
|
var dateString = newArray.slice(0, 3).join("-"); |
|
if (BI.isNotEmptyString(suffixString)) { |
|
dateString += " " + suffixString; |
|
} |
|
return dateString; |
|
}, |
|
|
|
_getFormatString: function () { |
|
return this.options.format || this._const.compareFormat; |
|
}, |
|
|
|
_dateCheck: function (date) { |
|
return BI.print(BI.parseDateTime(date, "%Y-%x-%d %H:%M:%S"), "%Y-%x-%d %H:%M:%S") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%d %H:%M:%S"), "%Y-%X-%d %H:%M:%S") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%x-%e %H:%M:%S"), "%Y-%x-%e %H:%M:%S") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%e %H:%M:%S"), "%Y-%X-%e %H:%M:%S") === date || |
|
|
|
BI.print(BI.parseDateTime(date, "%Y-%x-%d"), "%Y-%x-%d") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%d"), "%Y-%X-%d") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%x-%e"), "%Y-%x-%e") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%e"), "%Y-%X-%e") === date; |
|
}, |
|
_checkVoid: function (obj) { |
|
return !BI.checkDateVoid(obj.year, obj.month, obj.day, this.options.min, this.options.max)[0]; |
|
}, |
|
_autoAppend: function (v, dateObj) { |
|
if (BI.isNotNull(dateObj) && BI.checkDateLegal(v)) { |
|
switch (v.length) { |
|
case this._const.yearLength: |
|
if (this._yearCheck(v)) { |
|
this.editor.setValue(v + "-"); |
|
} |
|
break; |
|
case this._const.yearMonthLength: |
|
case this._const.yearFullMonthLength: |
|
var splitMonth = v.split("-")[1]; |
|
if ((BI.isNotNull(splitMonth) && splitMonth.length === 2) || this._monthCheck(v)) { |
|
this.editor.setValue(v + "-"); |
|
} |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
_yearCheck: function (v) { |
|
var date = BI.print(BI.parseDateTime(v, "%Y-%X-%d"), "%Y-%X-%d"); |
|
return BI.print(BI.parseDateTime(v, "%Y"), "%Y") === v && date >= this.options.min && date <= this.options.max; |
|
}, |
|
|
|
_monthCheck: function (v) { |
|
var date = BI.parseDateTime(v, "%Y-%X-%d"); |
|
var dateStr = BI.print(date, "%Y-%X-%d"); |
|
return (date.getMonth() > 0 && (BI.print(BI.parseDateTime(v, "%Y-%X"), "%Y-%X") === v || |
|
BI.print(BI.parseDateTime(v, "%Y-%x"), "%Y-%x") === v)) && dateStr >= this.options.min && dateStr <= this.options.max; |
|
}, |
|
|
|
_setInnerValue: function (date) { |
|
var dateStr = BI.print(date, this._getFormatString()); |
|
this.editor.setState(dateStr); |
|
this.editor.setValue(dateStr); |
|
}, |
|
|
|
_getText: function (obj) { |
|
var value = ""; |
|
var endText = ""; |
|
if(BI.isNotNull(obj.year)) { |
|
if(BI.parseInt(obj.year) !== 0) { |
|
value += Math.abs(obj.year) + BI.i18nText("BI-Basic_Year") + (obj.year < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Year"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.quarter)) { |
|
if(BI.parseInt(obj.quarter) !== 0) { |
|
value += Math.abs(obj.quarter) + BI.i18nText("BI-Basic_Single_Quarter") + (obj.quarter < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Single_Quarter"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.month)) { |
|
if(BI.parseInt(obj.month) !== 0) { |
|
value += Math.abs(obj.month) + BI.i18nText("BI-Basic_Month") + (obj.month < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Month"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.week)) { |
|
if(BI.parseInt(obj.week) !== 0) { |
|
value += Math.abs(obj.week) + BI.i18nText("BI-Basic_Week") + (obj.week < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = getPositionText(BI.i18nText("BI-Basic_Week"), obj.position); |
|
} |
|
if(BI.isNotNull(obj.day)) { |
|
if(BI.parseInt(obj.day) !== 0) { |
|
value += Math.abs(obj.day) + BI.i18nText("BI-Basic_Day") + (obj.day < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
endText = BI.size(obj) === 1 ? getPositionText(BI.i18nText("BI-Basic_Month"), obj.position) : ""; |
|
} |
|
if(BI.isNotNull(obj.workDay) && BI.parseInt(obj.workDay) !== 0) { |
|
value += Math.abs(obj.workDay) + BI.i18nText("BI-Basic_Work_Day") + (obj.workDay < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
return value + endText; |
|
|
|
function getPositionText (baseText, position) { |
|
switch (position) { |
|
case BI.DynamicDateCard.OFFSET.BEGIN: |
|
return baseText + BI.i18nText("BI-Basic_Begin_Start"); |
|
case BI.DynamicDateCard.OFFSET.END: |
|
return baseText + BI.i18nText("BI-Basic_End_Stop"); |
|
case BI.DynamicDateCard.OFFSET.CURRENT: |
|
default: |
|
return BI.i18nText("BI-Basic_Current_Day"); |
|
} |
|
} |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (BI.isNotEmptyString(this.options.min)) { |
|
this.options.min = minDate; |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (BI.isNotEmptyString(this.options.max)) { |
|
this.options.max = maxDate; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
var type, value, self = this; |
|
var date = BI.getDate(); |
|
this.storeValue = v; |
|
if (BI.isNotNull(v)) { |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
this._setInnerValue(date, text); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
if (BI.isNull(value) || BI.isNull(value.day)) { |
|
this.editor.setState(""); |
|
this.editor.setValue(""); |
|
} else { |
|
var dateStr = BI.print(BI.getDate(value.year, (value.month - 1), value.day, value.hour || 0, value.minute || 0, |
|
value.second || 0), this._getFormatString()); |
|
this.editor.setState(dateStr); |
|
this.editor.setValue(dateStr); |
|
} |
|
break; |
|
} |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
} |
|
|
|
}); |
|
|
|
BI.DynamicDateTimeTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.DynamicDateTimeTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicDateTimeTrigger.EVENT_START = "EVENT_START"; |
|
BI.DynamicDateTimeTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.DynamicDateTimeTrigger.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicDateTimeTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DynamicDateTimeTrigger.EVENT_VALID = "EVENT_VALID"; |
|
BI.DynamicDateTimeTrigger.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicDateTimeTrigger.EVENT_TRIGGER_CLICK = "EVENT_TRIGGER_CLICK"; |
|
BI.DynamicDateTimeTrigger.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.shortcut("bi.dynamic_date_time_trigger", BI.DynamicDateTimeTrigger);/** |
|
* Created by roy on 15/9/14. |
|
*/ |
|
BI.SearchEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.SearchEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-search-editor bi-border bi-focus-shadow", |
|
height: 24, |
|
errorText: "", |
|
watermark: BI.i18nText("BI-Basic_Search"), |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
this.options.height -= 2; |
|
BI.SearchEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
watermark: o.watermark, |
|
allowBlank: true, |
|
hgap: 1, |
|
errorText: o.errorText, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
value: o.value |
|
}); |
|
this.clear = BI.createWidget({ |
|
type: "bi.icon_button", |
|
stopEvent: true, |
|
cls: "close-font" |
|
}); |
|
this.clear.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self.setValue(""); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STOPEDIT); |
|
// 从有内容到无内容的清空也是一次change |
|
self.fireEvent(BI.SearchEditor.EVENT_CHANGE); |
|
self.fireEvent(BI.SearchEditor.EVENT_CLEAR); |
|
}); |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: { |
|
type: "bi.icon_label", |
|
cls: "search-font" |
|
}, |
|
width: 24 |
|
}, |
|
{ |
|
el: self.editor |
|
}, |
|
{ |
|
el: this.clear, |
|
width: 24 |
|
} |
|
] |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_BLUR); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_CLICK); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self._checkClear(); |
|
self.fireEvent(BI.SearchEditor.EVENT_CHANGE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.SearchEditor.EVENT_KEY_DOWN, v); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_SPACE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BACKSPACE, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_BACKSPACE); |
|
}); |
|
|
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_VALID); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_ERROR); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_ENTER); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_RESTRICT); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self._checkClear(); |
|
self.fireEvent(BI.SearchEditor.EVENT_EMPTY); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_REMOVE, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_REMOVE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_CONFIRM); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_CHANGE_CONFIRM); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_START); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_PAUSE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.SearchEditor.EVENT_STOP); |
|
}); |
|
|
|
this.clear.invisible(); |
|
}, |
|
|
|
_checkClear: function () { |
|
if (!this.getValue()) { |
|
this.clear.invisible(); |
|
} else { |
|
this.clear.visible(); |
|
} |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
focus: function () { |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
}, |
|
|
|
getValue: function () { |
|
if (this.isValid()) { |
|
return this.editor.getValue(); |
|
} |
|
}, |
|
|
|
getKeywords: function () { |
|
var val = this.editor.getLastChangedValue(); |
|
var keywords = val.match(/[\S]+/g); |
|
if (BI.isEndWithBlank(val)) { |
|
return keywords.concat([" "]); |
|
} |
|
return keywords; |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setValue(v); |
|
if (BI.isKey(v)) { |
|
this.clear.visible(); |
|
} |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
} |
|
}); |
|
BI.SearchEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SearchEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SearchEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SearchEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.SearchEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.SearchEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.SearchEditor.EVENT_BACKSPACE = "EVENT_BACKSPACE"; |
|
BI.SearchEditor.EVENT_CLEAR = "EVENT_CLEAR"; |
|
|
|
BI.SearchEditor.EVENT_START = "EVENT_START"; |
|
BI.SearchEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SearchEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.SearchEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.SearchEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.SearchEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.SearchEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.SearchEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.SearchEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.SearchEditor.EVENT_REMOVE = "EVENT_REMOVE"; |
|
BI.SearchEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
BI.shortcut("bi.search_editor", BI.SearchEditor);/** |
|
* 小号搜索框 |
|
* Created by GUY on 2015/9/29. |
|
* @class BI.SmallSearchEditor |
|
* @extends BI.SearchEditor |
|
*/ |
|
BI.SmallSearchEditor = BI.inherit(BI.SearchEditor, { |
|
_defaultConfig: function () { |
|
var conf = BI.SmallSearchEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-small-search-editor", |
|
height: 20 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SmallSearchEditor.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.small_search_editor", BI.SmallSearchEditor);/** |
|
* guy |
|
* @class BI.TextEditor |
|
* @extends BI.Single |
|
*/ |
|
BI.TextEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.TextEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-text-editor bi-border bi-focus-shadow", |
|
hgap: 4, |
|
vgap: 2, |
|
lgap: 0, |
|
rgap: 0, |
|
tgap: 0, |
|
bgap: 0, |
|
validationChecker: BI.emptyFn, |
|
quitChecker: BI.emptyFn, |
|
allowBlank: false, |
|
watermark: "", |
|
errorText: "", |
|
height: 24 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNumber(o.height)) { |
|
this.element.css({height: o.height - 2}); |
|
} |
|
if (BI.isNumber(o.width)) { |
|
this.element.css({width: o.width - 2}); |
|
} |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height - 2, |
|
hgap: o.hgap, |
|
vgap: o.vgap, |
|
lgap: o.lgap, |
|
rgap: o.rgap, |
|
tgap: o.tgap, |
|
bgap: o.bgap, |
|
value: o.value, |
|
title: o.title, |
|
tipType: o.tipType, |
|
validationChecker: o.validationChecker, |
|
quitChecker: o.quitChecker, |
|
allowBlank: o.allowBlank, |
|
watermark: o.watermark, |
|
errorText: o.errorText |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.editor.on(BI.Editor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_BLUR); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CLICK, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_CLICK); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_CHANGE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_KEY_DOWN, function (v) { |
|
self.fireEvent(BI.TextEditor.EVENT_KEY_DOWN); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_SPACE, function (v) { |
|
self.fireEvent(BI.TextEditor.EVENT_SPACE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_BACKSPACE, function (v) { |
|
self.fireEvent(BI.TextEditor.EVENT_BACKSPACE); |
|
}); |
|
|
|
|
|
this.editor.on(BI.Editor.EVENT_VALID, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_VALID); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_CONFIRM); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_CHANGE_CONFIRM); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_REMOVE, function (v) { |
|
self.fireEvent(BI.TextEditor.EVENT_REMOVE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_START, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_START); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_PAUSE); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_STOP, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_STOP); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_ERROR, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ENTER, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_ENTER); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_RESTRICT, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_RESTRICT); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_EMPTY, function () { |
|
self.fireEvent(BI.TextEditor.EVENT_EMPTY); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [this.editor] |
|
}); |
|
}, |
|
|
|
setWaterMark: function (v) { |
|
this.options.watermark = v; |
|
this.editor.setWaterMark(v); |
|
}, |
|
|
|
focus: function () { |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.editor.setErrorText(text); |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.editor.getErrorText(); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
} |
|
}); |
|
BI.TextEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.TextEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.TextEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.TextEditor.EVENT_CLICK = "EVENT_CLICK"; |
|
BI.TextEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.TextEditor.EVENT_SPACE = "EVENT_SPACE"; |
|
BI.TextEditor.EVENT_BACKSPACE = "EVENT_BACKSPACE"; |
|
|
|
BI.TextEditor.EVENT_START = "EVENT_START"; |
|
BI.TextEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.TextEditor.EVENT_STOP = "EVENT_STOP"; |
|
BI.TextEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.TextEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.TextEditor.EVENT_VALID = "EVENT_VALID"; |
|
BI.TextEditor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.TextEditor.EVENT_ENTER = "EVENT_ENTER"; |
|
BI.TextEditor.EVENT_RESTRICT = "EVENT_RESTRICT"; |
|
BI.TextEditor.EVENT_REMOVE = "EVENT_REMOVE"; |
|
BI.TextEditor.EVENT_EMPTY = "EVENT_EMPTY"; |
|
|
|
BI.shortcut("bi.text_editor", BI.TextEditor);/** |
|
* 小号搜索框 |
|
* Created by GUY on 2015/9/29. |
|
* @class BI.SmallTextEditor |
|
* @extends BI.SearchEditor |
|
*/ |
|
BI.SmallTextEditor = BI.inherit(BI.TextEditor, { |
|
_defaultConfig: function () { |
|
var conf = BI.SmallTextEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-small-text-editor", |
|
height: 20 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SmallTextEditor.superclass._init.apply(this, arguments); |
|
} |
|
}); |
|
BI.shortcut("bi.small_text_editor", BI.SmallTextEditor);/** |
|
* Created by zcf on 2016/9/26. |
|
*/ |
|
BI.IntervalSlider = BI.inherit(BI.Single, { |
|
_constant: { |
|
EDITOR_WIDTH: 58, |
|
EDITOR_R_GAP: 60, |
|
EDITOR_HEIGHT: 30, |
|
SLIDER_WIDTH_HALF: 15, |
|
SLIDER_WIDTH: 30, |
|
SLIDER_HEIGHT: 30, |
|
TRACK_HEIGHT: 24 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-interval-slider bi-slider-track", |
|
digit: false, |
|
unit: "" |
|
}, |
|
|
|
render: function () { |
|
|
|
var self = this; |
|
var c = this._constant; |
|
this.enable = false; |
|
this.valueOne = ""; |
|
this.valueTwo = ""; |
|
this.calculation = new BI.AccurateCalculationModel(); |
|
|
|
// this.backgroundTrack = BI.createWidget({ |
|
// type: "bi.layout", |
|
// cls: "background-track", |
|
// height: c.TRACK_HEIGHT |
|
// }); |
|
this.grayTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "gray-track", |
|
height: 6 |
|
}); |
|
this.blueTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "blue-track bi-high-light-background", |
|
height: 6 |
|
}); |
|
this.track = this._createTrackWrapper(); |
|
|
|
this.labelOne = BI.createWidget({ |
|
type: "bi.sign_text_editor", |
|
cls: "slider-editor-button", |
|
text: this.options.unit, |
|
allowBlank: false, |
|
width: c.EDITOR_WIDTH, |
|
validationChecker: function (v) { |
|
return self._checkValidation(v); |
|
} |
|
}); |
|
this.labelOne.element.hover(function () { |
|
self.labelOne.element.removeClass("bi-border").addClass("bi-border"); |
|
}, function () { |
|
self.labelOne.element.removeClass("bi-border"); |
|
}); |
|
this.labelOne.on(BI.Editor.EVENT_CONFIRM, function () { |
|
var oldValueOne = self.valueOne; |
|
var v = BI.parseFloat(this.getValue()); |
|
self.valueOne = v; |
|
var percent = self._getPercentByValue(v); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1));// 分成1000份 |
|
self._setSliderOnePosition(significantPercent); |
|
self._setBlueTrack(); |
|
self._checkLabelPosition(oldValueOne, self.valueTwo, self.valueOne, self.valueTwo); |
|
self.fireEvent(BI.IntervalSlider.EVENT_CHANGE); |
|
}); |
|
|
|
this.labelTwo = BI.createWidget({ |
|
type: "bi.sign_text_editor", |
|
cls: "slider-editor-button", |
|
text: this.options.unit, |
|
allowBlank: false, |
|
width: c.EDITOR_WIDTH, |
|
validationChecker: function (v) { |
|
return self._checkValidation(v); |
|
} |
|
}); |
|
this.labelTwo.element.hover(function () { |
|
self.labelTwo.element.removeClass("bi-border").addClass("bi-border"); |
|
}, function () { |
|
self.labelTwo.element.removeClass("bi-border"); |
|
}); |
|
this.labelTwo.on(BI.Editor.EVENT_CONFIRM, function () { |
|
var oldValueTwo = self.valueTwo; |
|
var v = BI.parseFloat(this.getValue()); |
|
self.valueTwo = v; |
|
var percent = self._getPercentByValue(v); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setSliderTwoPosition(significantPercent); |
|
self._setBlueTrack(); |
|
self._checkLabelPosition(self.valueOne, oldValueTwo, self.valueOne, self.valueTwo); |
|
self.fireEvent(BI.IntervalSlider.EVENT_CHANGE); |
|
}); |
|
|
|
this.sliderOne = BI.createWidget({ |
|
type: "bi.single_slider_button" |
|
}); |
|
this.sliderTwo = BI.createWidget({ |
|
type: "bi.single_slider_button" |
|
}); |
|
this._draggable(this.sliderOne, true); |
|
this._draggable(this.sliderTwo, false); |
|
this._setVisible(false); |
|
|
|
return { |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.track, |
|
width: "100%", |
|
height: c.TRACK_HEIGHT |
|
}] |
|
}], |
|
hgap: 7, |
|
height: c.TRACK_HEIGHT |
|
}, |
|
top: 23, |
|
left: 0, |
|
width: "100%" |
|
}, |
|
this._createLabelWrapper(), |
|
this._createSliderWrapper() |
|
] |
|
}; |
|
}, |
|
|
|
_rePosBySizeAfterMove: function (size, isLeft) { |
|
var o = this.options; |
|
var percent = size * 100 / (this._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
var v = this._getValueByPercent(significantPercent); |
|
v = this._assertValue(v); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
var oldValueOne = this.valueOne, oldValueTwo = this.valueTwo; |
|
if(isLeft) { |
|
this._setSliderOnePosition(significantPercent); |
|
this.labelOne.setValue(v); |
|
this.valueOne = v; |
|
this._checkLabelPosition(oldValueOne, oldValueTwo, v, this.valueTwo); |
|
}else{ |
|
this._setSliderTwoPosition(significantPercent); |
|
this.labelTwo.setValue(v); |
|
this.valueTwo = v; |
|
this._checkLabelPosition(oldValueOne, oldValueTwo, this.valueOne, v); |
|
} |
|
this._setBlueTrack(); |
|
}, |
|
|
|
_rePosBySizeAfterStop: function (size, isLeft) { |
|
var percent = size * 100 / (this._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
isLeft ? this._setSliderOnePosition(significantPercent) : this._setSliderTwoPosition(significantPercent); |
|
}, |
|
|
|
_draggable: function (widget, isLeft) { |
|
var self = this, o = this.options; |
|
var startDrag = false; |
|
var size = 0, offset = 0, defaultSize = 0; |
|
var mouseMoveTracker = new BI.MouseMoveTracker(function (deltaX) { |
|
if (mouseMoveTracker.isDragging()) { |
|
startDrag = true; |
|
offset += deltaX; |
|
size = optimizeSize(defaultSize + offset); |
|
widget.element.addClass("dragging"); |
|
self._rePosBySizeAfterMove(size, isLeft); |
|
} |
|
}, function () { |
|
if (startDrag === true) { |
|
size = optimizeSize(size); |
|
self._rePosBySizeAfterStop(size, isLeft); |
|
size = 0; |
|
offset = 0; |
|
defaultSize = size; |
|
startDrag = false; |
|
} |
|
widget.element.removeClass("dragging"); |
|
mouseMoveTracker.releaseMouseMoves(); |
|
self.fireEvent(BI.IntervalSlider.EVENT_CHANGE); |
|
}, window); |
|
widget.element.on("mousedown", function (event) { |
|
if(!widget.isEnabled()) { |
|
return; |
|
} |
|
defaultSize = this.offsetLeft; |
|
optimizeSize(defaultSize); |
|
mouseMoveTracker.captureMouseMoves(event); |
|
}); |
|
|
|
function optimizeSize (s) { |
|
return BI.clamp(s, 0, self._getGrayTrackLength()); |
|
} |
|
}, |
|
|
|
_createLabelWrapper: function () { |
|
var c = this._constant; |
|
return { |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.labelOne, |
|
top: 0, |
|
left: "0%" |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.labelTwo, |
|
top: 0, |
|
left: "100%" |
|
}] |
|
}], |
|
rgap: c.EDITOR_R_GAP, |
|
height: c.SLIDER_HEIGHT |
|
}, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}; |
|
}, |
|
|
|
_createSliderWrapper: function () { |
|
var c = this._constant; |
|
return { |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.sliderOne, |
|
top: 0, |
|
left: "0%" |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.sliderTwo, |
|
top: 0, |
|
left: "100%" |
|
}] |
|
}], |
|
hgap: c.SLIDER_WIDTH_HALF, |
|
height: c.SLIDER_HEIGHT |
|
}, |
|
top: 20, |
|
left: 0, |
|
width: "100%" |
|
}; |
|
}, |
|
|
|
_createTrackWrapper: function () { |
|
return BI.createWidget({ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.grayTrack, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: this.blueTrack, |
|
top: 0, |
|
left: 0, |
|
width: "0%" |
|
}] |
|
}], |
|
hgap: 8, |
|
height: 8 |
|
}, |
|
top: 8, |
|
left: 0, |
|
width: "100%" |
|
}] |
|
}); |
|
}, |
|
|
|
_checkValidation: function (v) { |
|
var o = this.options; |
|
var valid = false; |
|
// 像90.这样的既不属于整数又不属于小数,是不合法的值 |
|
var dotText = (v + "").split(".")[1]; |
|
if (BI.isEmptyString(dotText)) { |
|
}else{ |
|
if (BI.isNumeric(v) && !(BI.isNull(v) || v < this.min || v > this.max)) { |
|
// 虽然规定了所填写的小数位数,但是我们认为所有的整数都是满足设置的小数位数的 |
|
// 100等价于100.0 100.00 100.000 |
|
if(o.digit === false || BI.isInteger(v)) { |
|
valid = true; |
|
}else{ |
|
dotText = dotText || ""; |
|
valid = (dotText.length === o.digit); |
|
} |
|
} |
|
} |
|
return valid; |
|
}, |
|
|
|
_checkOverlap: function () { |
|
var labelOneLeft = this.labelOne.element[0].offsetLeft; |
|
var labelTwoLeft = this.labelTwo.element[0].offsetLeft; |
|
if (labelOneLeft <= labelTwoLeft) { |
|
if ((labelTwoLeft - labelOneLeft) < 90) { |
|
this.labelTwo.element.css({top: 40}); |
|
} else { |
|
this.labelTwo.element.css({top: 0}); |
|
} |
|
} else { |
|
if ((labelOneLeft - labelTwoLeft) < 90) { |
|
this.labelTwo.element.css({top: 40}); |
|
} else { |
|
this.labelTwo.element.css({top: 0}); |
|
} |
|
} |
|
}, |
|
|
|
_checkLabelPosition: function (oldValueOne, oldValueTwo, valueOne, valueTwo, isLeft) { |
|
oldValueOne = BI.parseFloat(oldValueOne); |
|
oldValueTwo = BI.parseFloat(oldValueTwo); |
|
valueOne = BI.parseFloat(valueOne); |
|
valueTwo = BI.parseFloat(valueTwo); |
|
if((oldValueOne <= oldValueTwo && valueOne > valueTwo) || (oldValueOne >= oldValueTwo && valueOne < valueTwo)) { |
|
var isSliderOneLeft = BI.parseFloat(this.sliderOne.element[0].style.left) < BI.parseFloat(this.sliderTwo.element[0].style.left); |
|
this._resetLabelPosition(!isSliderOneLeft); |
|
} |
|
}, |
|
|
|
_resetLabelPosition: function(needReverse) { |
|
this.labelOne.element.css({left: needReverse ? "100%" : "0%"}); |
|
this.labelTwo.element.css({left: needReverse ? "0%" : "100%"}); |
|
}, |
|
|
|
_setSliderOnePosition: function (percent) { |
|
this.sliderOne.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setSliderTwoPosition: function (percent) { |
|
this.sliderTwo.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setBlueTrackLeft: function (percent) { |
|
this.blueTrack.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setBlueTrackWidth: function (percent) { |
|
this.blueTrack.element.css({width: percent + "%"}); |
|
}, |
|
|
|
_setBlueTrack: function () { |
|
var percentOne = this._getPercentByValue(this.labelOne.getValue()); |
|
var percentTwo = this._getPercentByValue(this.labelTwo.getValue()); |
|
if (percentOne <= percentTwo) { |
|
this._setBlueTrackLeft(percentOne); |
|
this._setBlueTrackWidth(percentTwo - percentOne); |
|
} else { |
|
this._setBlueTrackLeft(percentTwo); |
|
this._setBlueTrackWidth(percentOne - percentTwo); |
|
} |
|
}, |
|
|
|
_setAllPosition: function (one, two) { |
|
this._setSliderOnePosition(one); |
|
this._setSliderTwoPosition(two); |
|
this._setBlueTrack(); |
|
}, |
|
|
|
_setVisible: function (visible) { |
|
this.sliderOne.setVisible(visible); |
|
this.sliderTwo.setVisible(visible); |
|
this.labelOne.setVisible(visible); |
|
this.labelTwo.setVisible(visible); |
|
}, |
|
|
|
_setErrorText: function () { |
|
var errorText = BI.i18nText("BI-Basic_Please_Enter_Number_Between", this.min, this.max); |
|
this.labelOne.setErrorText(errorText); |
|
this.labelTwo.setErrorText(errorText); |
|
}, |
|
|
|
_getGrayTrackLength: function () { |
|
return this.grayTrack.element[0].scrollWidth; |
|
}, |
|
|
|
// 其中取max-min后保留4为有效数字后的值的小数位数为最终value的精度 |
|
_getValueByPercent: function (percent) {// return (((max-min)*percent)/100+min) |
|
var sub = this.calculation.accurateSubtraction(this.max, this.min); |
|
var mul = this.calculation.accurateMultiplication(sub, percent); |
|
var div = this.calculation.accurateDivisionTenExponent(mul, 2); |
|
if(this.precision < 0) { |
|
var value = BI.parseFloat(this.calculation.accurateAddition(div, this.min)); |
|
var reduceValue = Math.round(this.calculation.accurateDivisionTenExponent(value, -this.precision)); |
|
return this.calculation.accurateMultiplication(reduceValue, Math.pow(10, -this.precision)); |
|
} |
|
return BI.parseFloat(this.calculation.accurateAddition(div, this.min).toFixed(this.precision)); |
|
|
|
}, |
|
|
|
_getPercentByValue: function (v) { |
|
return (v - this.min) * 100 / (this.max - this.min); |
|
}, |
|
|
|
_setDraggableEnable: function (enable) { |
|
this.sliderOne.setEnable(enable); |
|
this.sliderTwo.setEnable(enable); |
|
}, |
|
|
|
_getPrecision: function () { |
|
// 计算每一份值的精度(最大值和最小值的差值保留4为有效数字后的精度) |
|
// 如果差值的整数位数大于4,toPrecision(4)得到的是科学计数法123456 => 1.235e+5 |
|
// 返回非负值: 保留的小数位数 |
|
// 返回负值: 保留的10^n精度中的n |
|
var sub = this.calculation.accurateSubtraction(this.max, this.min); |
|
var pre = sub.toPrecision(4); |
|
// 科学计数法 |
|
var eIndex = pre.indexOf("e"); |
|
var arr = []; |
|
if(eIndex > -1) { |
|
arr = pre.split("e"); |
|
var decimalPartLength = BI.size(arr[0].split(".")[1]); |
|
var sciencePartLength = BI.parseInt(arr[1].substring(1)); |
|
return decimalPartLength - sciencePartLength; |
|
} |
|
arr = pre.split("."); |
|
return arr.length > 1 ? arr[1].length : 0; |
|
|
|
}, |
|
|
|
_assertValue: function (value) { |
|
if(value <= this.min) { |
|
return this.min; |
|
} |
|
if(value >= this.max) { |
|
return this.max; |
|
} |
|
return value; |
|
}, |
|
|
|
_setEnable: function (b) { |
|
BI.IntervalSlider.superclass._setEnable.apply(this, [b]); |
|
if(b) { |
|
this.blueTrack.element.removeClass("disabled-blue-track").addClass("blue-track"); |
|
} else { |
|
this.blueTrack.element.removeClass("blue-track").addClass("disabled-blue-track"); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
if (this.valueOne <= this.valueTwo) { |
|
return {min: this.valueOne, max: this.valueTwo}; |
|
} |
|
return {min: this.valueTwo, max: this.valueOne}; |
|
|
|
}, |
|
|
|
setMinAndMax: function (v) { |
|
var minNumber = BI.parseFloat(v.min); |
|
var maxNumber = BI.parseFloat(v.max); |
|
if ((!isNaN(minNumber)) && (!isNaN(maxNumber)) && (maxNumber >= minNumber )) { |
|
this.min = minNumber; |
|
this.max = maxNumber; |
|
this.valueOne = minNumber; |
|
this.valueTwo = maxNumber; |
|
this.precision = this._getPrecision(); |
|
this._setDraggableEnable(true); |
|
} |
|
if (maxNumber === minNumber) { |
|
this._setDraggableEnable(false); |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
var valueOne = BI.parseFloat(v.min); |
|
var valueTwo = BI.parseFloat(v.max); |
|
valueOne = o.digit === false ? valueOne : BI.parseFloat(valueOne.toFixed(o.digit)); |
|
valueTwo = o.digit === false ? valueTwo : BI.parseFloat(valueTwo.toFixed(o.digit)); |
|
if (!isNaN(valueOne) && !isNaN(valueTwo)) { |
|
if (this._checkValidation(valueOne)) { |
|
this.valueOne = (this.valueOne <= this.valueTwo ? valueOne : valueTwo); |
|
} |
|
if (this._checkValidation(valueTwo)) { |
|
this.valueTwo = (this.valueOne <= this.valueTwo ? valueTwo : valueOne); |
|
} |
|
if (valueOne < this.min) { |
|
this.valueOne = this.min; |
|
} |
|
if (valueTwo > this.max) { |
|
this.valueTwo = this.max; |
|
} |
|
} |
|
}, |
|
|
|
reset: function () { |
|
this._setVisible(false); |
|
this.enable = false; |
|
this.valueOne = ""; |
|
this.valueTwo = ""; |
|
this.min = NaN; |
|
this.max = NaN; |
|
this._setBlueTrackWidth(0); |
|
}, |
|
|
|
populate: function () { |
|
var o = this.options; |
|
if (!isNaN(this.min) && !isNaN(this.max)) { |
|
this.enable = true; |
|
this._setVisible(true); |
|
this._setErrorText(); |
|
if ((BI.isNumeric(this.valueOne) || BI.isNotEmptyString(this.valueOne)) && (BI.isNumeric(this.valueTwo) || BI.isNotEmptyString(this.valueTwo))) { |
|
this.labelOne.setValue(o.digit === false ? this.valueOne : BI.parseFloat(this.valueOne).toFixed(o.digit)); |
|
this.labelTwo.setValue(o.digit === false ? this.valueTwo : BI.parseFloat(this.valueTwo).toFixed(o.digit)); |
|
this._setAllPosition(this._getPercentByValue(this.valueOne), this._getPercentByValue(this.valueTwo)); |
|
} else { |
|
this.labelOne.setValue(this.min); |
|
this.labelTwo.setValue(this.max); |
|
this._setAllPosition(0, 100); |
|
} |
|
this._resetLabelPosition(this.valueOne > this.valueTwo); |
|
} |
|
} |
|
}); |
|
BI.IntervalSlider.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.interval_slider", BI.IntervalSlider);/** |
|
* Created by zcf on 2017/3/1. |
|
* 万恶的IEEE-754 |
|
* 使用字符串精确计算含小数加法、减法、乘法和10的指数倍除法,支持负数 |
|
*/ |
|
BI.AccurateCalculationModel = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.AccurateCalculationModel.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.AccurateCalculationModel.superclass._init.apply(this, arguments); |
|
}, |
|
|
|
_getMagnitude: function (n) { |
|
var magnitude = "1"; |
|
for (var i = 0; i < n; i++) { |
|
magnitude += "0"; |
|
} |
|
return BI.parseInt(magnitude); |
|
}, |
|
|
|
_formatDecimal: function (stringNumber1, stringNumber2) { |
|
if (stringNumber1.numDecimalLength === stringNumber2.numDecimalLength) { |
|
return; |
|
} |
|
var magnitudeDiff = stringNumber1.numDecimalLength - stringNumber2.numDecimalLength; |
|
if (magnitudeDiff > 0) { |
|
var needAddZero = stringNumber2; |
|
} else { |
|
var needAddZero = stringNumber1; |
|
magnitudeDiff = (0 - magnitudeDiff); |
|
} |
|
for (var i = 0; i < magnitudeDiff; i++) { |
|
if (needAddZero.numDecimal === "0" && i === 0) { |
|
continue; |
|
} |
|
needAddZero.numDecimal += "0"; |
|
} |
|
}, |
|
|
|
_stringNumberFactory: function (num) { |
|
var strNum = num.toString(); |
|
var numStrArray = strNum.split("."); |
|
var numInteger = numStrArray[0]; |
|
if (numStrArray.length === 1) { |
|
var numDecimal = "0"; |
|
var numDecimalLength = 0; |
|
} else { |
|
var numDecimal = numStrArray[1]; |
|
var numDecimalLength = numStrArray[1].length; |
|
} |
|
return { |
|
numInteger: numInteger, |
|
numDecimal: numDecimal, |
|
numDecimalLength: numDecimalLength |
|
}; |
|
}, |
|
|
|
_accurateSubtraction: function (num1, num2) {// num1-num2 && num1>num2 |
|
var stringNumber1 = this._stringNumberFactory(num1); |
|
var stringNumber2 = this._stringNumberFactory(num2); |
|
// 整数部分计算 |
|
var integerResult = BI.parseInt(stringNumber1.numInteger) - BI.parseInt(stringNumber2.numInteger); |
|
// 小数部分 |
|
this._formatDecimal(stringNumber1, stringNumber2); |
|
var decimalMaxLength = getDecimalMaxLength(stringNumber1, stringNumber2); |
|
|
|
if (BI.parseInt(stringNumber1.numDecimal) >= BI.parseInt(stringNumber2.numDecimal)) { |
|
var decimalResultTemp = (BI.parseInt(stringNumber1.numDecimal) - BI.parseInt(stringNumber2.numDecimal)).toString(); |
|
var decimalResult = addZero(decimalResultTemp, decimalMaxLength); |
|
} else {// 否则借位 |
|
integerResult--; |
|
var borrow = this._getMagnitude(decimalMaxLength); |
|
var decimalResultTemp = (borrow + BI.parseInt(stringNumber1.numDecimal) - BI.parseInt(stringNumber2.numDecimal)).toString(); |
|
var decimalResult = addZero(decimalResultTemp, decimalMaxLength); |
|
} |
|
var result = integerResult + "." + decimalResult; |
|
return BI.parseFloat(result); |
|
|
|
function getDecimalMaxLength (num1, num2) { |
|
if (num1.numDecimal.length >= num2.numDecimal.length) { |
|
return num1.numDecimal.length; |
|
} |
|
return num2.numDecimal.length; |
|
} |
|
|
|
function addZero (resultTemp, length) { |
|
var diff = length - resultTemp.length; |
|
for (var i = 0; i < diff; i++) { |
|
resultTemp = "0" + resultTemp; |
|
} |
|
return resultTemp; |
|
} |
|
}, |
|
|
|
_accurateAddition: function (num1, num2) {// 加法结合律 |
|
var stringNumber1 = this._stringNumberFactory(num1); |
|
var stringNumber2 = this._stringNumberFactory(num2); |
|
// 整数部分计算 |
|
var integerResult = BI.parseInt(stringNumber1.numInteger) + BI.parseInt(stringNumber2.numInteger); |
|
// 小数部分 |
|
this._formatDecimal(stringNumber1, stringNumber2); |
|
|
|
var decimalResult = (BI.parseInt(stringNumber1.numDecimal) + BI.parseInt(stringNumber2.numDecimal)).toString(); |
|
|
|
if (decimalResult !== "0") { |
|
if (decimalResult.length <= stringNumber1.numDecimal.length) { |
|
decimalResult = addZero(decimalResult, stringNumber1.numDecimal.length); |
|
} else { |
|
integerResult++;// 进一 |
|
decimalResult = decimalResult.slice(1); |
|
} |
|
} |
|
var result = integerResult + "." + decimalResult; |
|
return BI.parseFloat(result); |
|
|
|
function addZero (resultTemp, length) { |
|
var diff = length - resultTemp.length; |
|
for (var i = 0; i < diff; i++) { |
|
resultTemp = "0" + resultTemp; |
|
} |
|
return resultTemp; |
|
} |
|
}, |
|
|
|
_accurateMultiplication: function (num1, num2) {// 乘法分配律 |
|
var stringNumber1 = this._stringNumberFactory(num1); |
|
var stringNumber2 = this._stringNumberFactory(num2); |
|
// 整数部分计算 |
|
var integerResult = BI.parseInt(stringNumber1.numInteger) * BI.parseInt(stringNumber2.numInteger); |
|
// num1的小数和num2的整数 |
|
var dec1Int2 = this._accurateDivisionTenExponent(BI.parseInt(stringNumber1.numDecimal) * BI.parseInt(stringNumber2.numInteger), stringNumber1.numDecimalLength); |
|
// num1的整数和num2的小数 |
|
var int1dec2 = this._accurateDivisionTenExponent(BI.parseInt(stringNumber1.numInteger) * BI.parseInt(stringNumber2.numDecimal), stringNumber2.numDecimalLength); |
|
// 小数*小数 |
|
var dec1dec2 = this._accurateDivisionTenExponent(BI.parseInt(stringNumber1.numDecimal) * BI.parseInt(stringNumber2.numDecimal), (stringNumber1.numDecimalLength + stringNumber2.numDecimalLength)); |
|
|
|
return this._accurateAddition(this._accurateAddition(this._accurateAddition(integerResult, dec1Int2), int1dec2), dec1dec2); |
|
}, |
|
|
|
_accurateDivisionTenExponent: function (num, n) {// num/10^n && n>0 |
|
var stringNumber = this._stringNumberFactory(num); |
|
if (stringNumber.numInteger.length > n) { |
|
var integerResult = stringNumber.numInteger.slice(0, (stringNumber.numInteger.length - n)); |
|
var partDecimalResult = stringNumber.numInteger.slice(-n); |
|
} else { |
|
var integerResult = "0"; |
|
var partDecimalResult = addZero(stringNumber.numInteger, n); |
|
} |
|
var result = integerResult + "." + partDecimalResult + stringNumber.numDecimal; |
|
return BI.parseFloat(result); |
|
|
|
function addZero (resultTemp, length) { |
|
var diff = length - resultTemp.length; |
|
for (var i = 0; i < diff; i++) { |
|
resultTemp = "0" + resultTemp; |
|
} |
|
return resultTemp; |
|
} |
|
}, |
|
|
|
accurateSubtraction: function (num1, num2) { |
|
if (num1 >= 0 && num2 >= 0) { |
|
if (num1 >= num2) { |
|
return this._accurateSubtraction(num1, num2); |
|
} |
|
return -this._accurateSubtraction(num2, num1); |
|
} |
|
if (num1 >= 0 && num2 < 0) { |
|
return this._accurateAddition(num1, -num2); |
|
} |
|
if (num1 < 0 && num2 >= 0) { |
|
return -this._accurateAddition(-num1, num2); |
|
} |
|
if (num1 < 0 && num2 < 0) { |
|
if (num1 >= num2) { |
|
return this._accurateSubtraction(-num2, -num1); |
|
} |
|
return this._accurateSubtraction(-num1, -num2); |
|
} |
|
}, |
|
|
|
accurateAddition: function (num1, num2) { |
|
if (num1 >= 0 && num2 >= 0) { |
|
return this._accurateAddition(num1, num2); |
|
} |
|
if (num1 >= 0 && num2 < 0) { |
|
return this.accurateSubtraction(num1, -num2); |
|
} |
|
if (num1 < 0 && num2 >= 0) { |
|
return this.accurateSubtraction(num2, -num1); |
|
} |
|
if (num1 < 0 && num2 < 0) { |
|
return -this._accurateAddition(-num1, -num2); |
|
} |
|
}, |
|
|
|
accurateMultiplication: function (num1, num2) { |
|
if (num1 >= 0 && num2 >= 0) { |
|
return this._accurateMultiplication(num1, num2); |
|
} |
|
if (num1 >= 0 && num2 < 0) { |
|
return -this._accurateMultiplication(num1, -num2); |
|
} |
|
if (num1 < 0 && num2 >= 0) { |
|
return -this._accurateMultiplication(-num1, num2); |
|
} |
|
if (num1 < 0 && num2 < 0) { |
|
return this._accurateMultiplication(-num1, -num2); |
|
} |
|
}, |
|
|
|
accurateDivisionTenExponent: function (num1, n) { |
|
if (num1 >= 0) { |
|
return this._accurateDivisionTenExponent(num1, n); |
|
} |
|
return -this._accurateDivisionTenExponent(-num1, n); |
|
} |
|
});/** |
|
* Created by roy on 15/8/14. |
|
*/ |
|
BI.DownListCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.DownListCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-down-list-combo", |
|
height: 24, |
|
items: [], |
|
adjustLength: 0, |
|
direction: "bottom", |
|
trigger: "click", |
|
container: null, |
|
stopPropagation: false, |
|
el: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.DownListCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.popupview = BI.createWidget({ |
|
type: "bi.multi_layer_down_list_popup", |
|
items: o.items, |
|
chooseType: o.chooseType, |
|
value: o.value |
|
}); |
|
|
|
this.popupview.on(BI.DownListPopup.EVENT_CHANGE, function (value) { |
|
self.fireEvent(BI.DownListCombo.EVENT_CHANGE, value); |
|
self.downlistcombo.hideView(); |
|
}); |
|
|
|
this.popupview.on(BI.DownListPopup.EVENT_SON_VALUE_CHANGE, function (value, fatherValue) { |
|
self.fireEvent(BI.DownListCombo.EVENT_SON_VALUE_CHANGE, value, fatherValue); |
|
self.downlistcombo.hideView(); |
|
}); |
|
|
|
|
|
this.downlistcombo = BI.createWidget({ |
|
element: this, |
|
type: "bi.combo", |
|
trigger: o.trigger, |
|
isNeedAdjustWidth: false, |
|
container: o.container, |
|
adjustLength: o.adjustLength, |
|
direction: o.direction, |
|
stopPropagation: o.stopPropagation, |
|
el: BI.createWidget(o.el, { |
|
type: "bi.icon_trigger", |
|
extraCls: o.iconCls ? o.iconCls : "pull-down-font", |
|
width: o.width, |
|
height: o.height |
|
}), |
|
popup: { |
|
el: this.popupview, |
|
stopPropagation: o.stopPropagation, |
|
maxHeight: 1000 |
|
} |
|
}); |
|
|
|
this.downlistcombo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.fireEvent(BI.DownListCombo.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
}, |
|
|
|
hideView: function () { |
|
this.downlistcombo.hideView(); |
|
}, |
|
|
|
showView: function (e) { |
|
this.downlistcombo.showView(e); |
|
}, |
|
|
|
populate: function (items) { |
|
this.popupview.populate(items); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popupview.setValue(v); |
|
}, |
|
getValue: function () { |
|
return this.popupview.getValue(); |
|
} |
|
}); |
|
BI.DownListCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.DownListCombo.EVENT_SON_VALUE_CHANGE = "EVENT_SON_VALUE_CHANGE"; |
|
BI.DownListCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
|
|
BI.shortcut("bi.multi_layer_down_list_combo", BI.DownListCombo);/** |
|
* Created by roy on 15/9/8. |
|
* 处理popup中的item分组样式 |
|
* 一个item分组中的成员大于一时,该分组设置为单选,并且默认状态第一个成员设置为已选择项 |
|
*/ |
|
BI.MultiLayerDownListPopup = BI.inherit(BI.Pane, { |
|
constants: { |
|
nextIcon: "pull-right-e-font", |
|
height: 25, |
|
iconHeight: 12, |
|
iconWidth: 12, |
|
hgap: 0, |
|
vgap: 0, |
|
border: 1 |
|
}, |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerDownListPopup.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: "bi-down-list-popup", |
|
items: [], |
|
chooseType: BI.Selection.Multi |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerDownListPopup.superclass._init.apply(this, arguments); |
|
this.singleValues = []; |
|
this.childValueMap = {}; |
|
this.fatherValueMap = {}; |
|
var self = this, o = this.options, children = this._createPopupItems(o.items); |
|
this.popup = BI.createWidget({ |
|
type: "bi.button_tree", |
|
items: BI.createItems(children, |
|
{}, { |
|
adjustLength: -2 |
|
} |
|
), |
|
layouts: [{ |
|
type: "bi.vertical", |
|
hgap: this.constants.hgap, |
|
vgap: this.constants.vgap |
|
}], |
|
value: this._digest(o.value), |
|
chooseType: o.chooseType |
|
}); |
|
|
|
this.popup.on(BI.ButtonTree.EVENT_CHANGE, function (value, object) { |
|
var changedValue = value; |
|
if (BI.isNotNull(self.childValueMap[value])) { |
|
changedValue = self.childValueMap[value]; |
|
var fatherValue = self.fatherValueMap[value]; |
|
var fatherArrayValue = (fatherValue + "").split("_"); |
|
self.fireEvent(BI.MultiLayerDownListPopup.EVENT_SON_VALUE_CHANGE, changedValue, fatherArrayValue.length > 1 ? fatherArrayValue : fatherValue); |
|
} else { |
|
self.fireEvent(BI.MultiLayerDownListPopup.EVENT_CHANGE, changedValue, object); |
|
} |
|
|
|
|
|
if (!BI.contains(self.singleValues, changedValue)) { |
|
var item = self.getValue(); |
|
var result = []; |
|
BI.each(item, function (i, valueObject) { |
|
if (valueObject.value != changedValue) { |
|
result.push(valueObject); |
|
} |
|
}); |
|
self.setValue(result); |
|
} |
|
|
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
items: [this.popup], |
|
vgap: 5 |
|
}); |
|
|
|
}, |
|
_createPopupItems: function (items) { |
|
var self = this, result = []; |
|
BI.each(items, function (i, it) { |
|
var item_done = { |
|
type: "bi.down_list_group", |
|
items: [] |
|
}; |
|
|
|
BI.each(it, function (i, item) { |
|
if (BI.isNotEmptyArray(item.children) && !BI.isEmpty(item.el)) { |
|
item.type = "bi.combo_group"; |
|
item.cls = "down-list-group"; |
|
item.trigger = "hover"; |
|
item.isNeedAdjustWidth = false; |
|
item.el.title = item.el.title || item.el.text; |
|
item.el.type = "bi.down_list_group_item"; |
|
item.el.logic = { |
|
dynamic: true |
|
}; |
|
item.el.height = self.constants.height; |
|
item.el.iconCls2 = self.constants.nextIcon; |
|
item.popup = { |
|
lgap: 1, |
|
el: { |
|
type: "bi.button_tree", |
|
chooseType: 0, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
|
|
}, |
|
innerVGap: 5 |
|
}; |
|
item.el.childValues = []; |
|
BI.each(item.children, function (i, child) { |
|
child = child.el ? BI.extend(child.el, {children: child.children}) : child; |
|
var fatherValue = BI.deepClone(item.el.value); |
|
var childValue = BI.deepClone(child.value); |
|
self.singleValues.push(child.value); |
|
child.type = "bi.down_list_item"; |
|
child.extraCls = " child-down-list-item"; |
|
child.title = child.title || child.text; |
|
child.textRgap = 10; |
|
child.isNeedAdjustWidth = false; |
|
child.logic = { |
|
dynamic: true |
|
}; |
|
child.father = fatherValue; |
|
self.fatherValueMap[self._createChildValue(fatherValue, childValue)] = fatherValue; |
|
self.childValueMap[self._createChildValue(fatherValue, childValue)] = childValue; |
|
child.value = self._createChildValue(fatherValue, childValue); |
|
item.el.childValues.push(child.value); |
|
if (BI.isNotEmptyArray(child.children)) { |
|
child.type = "bi.down_list_group_item"; |
|
self._createChildren(child); |
|
child.height = self.constants.height; |
|
child.iconCls2 = self.constants.nextIcon; |
|
item.el.childValues = BI.concat(item.el.childValues, child.childValues); |
|
} |
|
}); |
|
} else { |
|
item.type = "bi.down_list_item"; |
|
item.title = item.title || item.text; |
|
item.textRgap = 10; |
|
item.isNeedAdjustWidth = false; |
|
item.logic = { |
|
dynamic: true |
|
}; |
|
} |
|
var el_done = {}; |
|
el_done.el = item; |
|
item_done.items.push(el_done); |
|
}); |
|
if (self._isGroup(item_done.items)) { |
|
BI.each(item_done.items, function (i, item) { |
|
self.singleValues.push(item.el.value); |
|
}); |
|
} |
|
|
|
result.push(item_done); |
|
if (self._needSpliter(i, items.length)) { |
|
var spliter_container = BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
el: { |
|
type: "bi.layout", |
|
cls: "bi-down-list-spliter bi-border-top cursor-pointer", |
|
height: 0 |
|
} |
|
|
|
}], |
|
cls: "bi-down-list-spliter-container cursor-pointer", |
|
vgap: 5, |
|
lgap: 10 |
|
}); |
|
result.push(spliter_container); |
|
} |
|
}); |
|
return result; |
|
}, |
|
|
|
_createChildren: function (child) { |
|
var self = this; |
|
child.childValues = []; |
|
BI.each(child.children, function (i, c) { |
|
var fatherValue = BI.deepClone(child.value); |
|
var childValue = BI.deepClone(c.value); |
|
c.type = "bi.down_list_item"; |
|
c.title = c.title || c.text; |
|
c.textRgap = 10; |
|
c.isNeedAdjustWidth = false; |
|
c.logic = { |
|
dynamic: true |
|
}; |
|
c.father = fatherValue; |
|
self.fatherValueMap[self._createChildValue(fatherValue, childValue)] = fatherValue; |
|
self.childValueMap[self._createChildValue(fatherValue, childValue)] = childValue; |
|
c.value = self._createChildValue(fatherValue, childValue); |
|
child.childValues.push(c.value); |
|
}); |
|
}, |
|
|
|
_isGroup: function (i) { |
|
return i.length > 1; |
|
}, |
|
|
|
_needSpliter: function (i, itemLength) { |
|
return i < itemLength - 1; |
|
}, |
|
|
|
_createChildValue: function (fatherValue, childValue) { |
|
var fValue = fatherValue; |
|
if(BI.isArray(fatherValue)) { |
|
fValue = fatherValue.join("_"); |
|
} |
|
return fValue + "_" + childValue; |
|
}, |
|
|
|
_digest: function (valueItem) { |
|
var self = this; |
|
var valueArray = []; |
|
BI.each(valueItem, function (i, item) { |
|
var value; |
|
if (BI.isNotNull(item.childValue)) { |
|
value = self._createChildValue(item.value, item.childValue); |
|
} else { |
|
value = item.value; |
|
} |
|
valueArray.push(value); |
|
} |
|
); |
|
return valueArray; |
|
}, |
|
|
|
_checkValues: function (values) { |
|
var self = this, o = this.options; |
|
var value = []; |
|
BI.each(o.items, function (idx, itemGroup) { |
|
BI.each(itemGroup, function (id, item) { |
|
if(BI.isNotNull(item.children)) { |
|
var childValues = getChildrenValue(item); |
|
var v = joinValue(childValues, values[idx]); |
|
if(BI.isNotEmptyString(v)) { |
|
value.push(v); |
|
} |
|
}else{ |
|
if(item.value === values[idx][0]) { |
|
value.push(values[idx][0]); |
|
} |
|
} |
|
}); |
|
}); |
|
return value; |
|
|
|
function joinValue (sources, targets) { |
|
var value = ""; |
|
BI.some(sources, function (idx, s) { |
|
return BI.some(targets, function (id, t) { |
|
if(s === t) { |
|
value = s; |
|
return true; |
|
} |
|
}); |
|
}); |
|
return value; |
|
} |
|
|
|
function getChildrenValue (item) { |
|
var children = []; |
|
if(BI.isNotNull(item.children)) { |
|
BI.each(item.children, function (idx, child) { |
|
children = BI.concat(children, getChildrenValue(child)); |
|
}); |
|
} else { |
|
children.push(item.value); |
|
} |
|
return children; |
|
} |
|
}, |
|
|
|
populate: function (items) { |
|
BI.MultiLayerDownListPopup.superclass.populate.apply(this, arguments); |
|
var self = this; |
|
self.childValueMap = {}; |
|
self.fatherValueMap = {}; |
|
self.singleValues = []; |
|
var children = self._createPopupItems(items); |
|
var popupItem = BI.createItems(children, |
|
{}, { |
|
adjustLength: -2 |
|
} |
|
); |
|
self.popup.populate(popupItem); |
|
}, |
|
|
|
setValue: function (valueItem) { |
|
this.popup.setValue(this._digest(valueItem)); |
|
}, |
|
|
|
_getValue: function () { |
|
var v = []; |
|
BI.each(this.popup.getAllButtons(), function (i, item) { |
|
i % 2 === 0 && v.push(item.getValue()); |
|
}); |
|
return v; |
|
}, |
|
|
|
getValue: function () { |
|
var self = this, result = []; |
|
var values = this._checkValues(this._getValue()); |
|
BI.each(values, function (i, value) { |
|
var valueItem = {}; |
|
if (BI.isNotNull(self.childValueMap[value])) { |
|
var fartherValue = self.fatherValueMap[value]; |
|
valueItem.childValue = self.childValueMap[value]; |
|
var fatherArrayValue = (fartherValue + "").split("_"); |
|
valueItem.value = fatherArrayValue.length > 1 ? fatherArrayValue : fartherValue; |
|
} else { |
|
valueItem.value = value; |
|
} |
|
result.push(valueItem); |
|
}); |
|
return result; |
|
} |
|
|
|
|
|
}); |
|
|
|
BI.MultiLayerDownListPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiLayerDownListPopup.EVENT_SON_VALUE_CHANGE = "EVENT_SON_VALUE_CHANGE"; |
|
BI.shortcut("bi.multi_layer_down_list_popup", BI.MultiLayerDownListPopup);/** |
|
* @class BI.MultiLayerSelectTreeCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.MultiLayerSelectTreeCombo = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSelectTreeCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-select-tree-combo", |
|
isDefaultInit: false, |
|
height: 24, |
|
text: "", |
|
itemsCreator: BI.emptyFn, |
|
items: [], |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
}, |
|
allowEdit: false, |
|
allowSearchValue: false, |
|
allowInsertValue: false |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
|
|
var combo = (o.itemsCreator === BI.emptyFn) ? this._getSyncConfig() : this._getAsyncConfig(); |
|
|
|
return (!o.allowEdit && o.itemsCreator === BI.emptyFn) ? combo : { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
cls: "trigger-icon-button", |
|
ref: function (_ref) { |
|
self.triggerBtn = _ref; |
|
}, |
|
width: o.height, |
|
height: o.height, |
|
handler: function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
} |
|
}, |
|
right: 0, |
|
bottom: 0, |
|
top: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
_getBaseConfig: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.combo", |
|
container: o.container, |
|
destroyWhenHide: o.destroyWhenHide, |
|
adjustLength: 2, |
|
ref: function (_ref) { |
|
self.combo = _ref; |
|
}, |
|
popup: { |
|
el: { |
|
type: "bi.multilayer_select_tree_popup", |
|
isDefaultInit: o.isDefaultInit, |
|
itemsCreator: o.itemsCreator, |
|
items: o.items, |
|
ref: function (_ref) { |
|
self.trigger && self.trigger.getSearcher().setAdapter(_ref); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiLayerSelectTreePopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(this.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.MultiLayerSelectTreeCombo.EVENT_CHANGE); |
|
} |
|
}], |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
}); |
|
} |
|
}, |
|
value: o.value, |
|
maxHeight: 400, |
|
minHeight: 240 |
|
} |
|
}; |
|
}, |
|
|
|
_getSearchConfig: function() { |
|
var self = this, o = this.options; |
|
return { |
|
el: { |
|
type: "bi.multilayer_select_tree_trigger", |
|
container: o.container, |
|
allowInsertValue: o.allowInsertValue, |
|
allowSearchValue: o.allowSearchValue, |
|
allowEdit: o.allowEdit, |
|
cls: "multilayer-select-tree-trigger", |
|
ref: function (_ref) { |
|
self.trigger = _ref; |
|
}, |
|
items: o.items, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
watermark: o.watermark, |
|
height: o.height - 2, |
|
text: o.text, |
|
value: o.value, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle, |
|
title: o.title, |
|
listeners: [{ |
|
eventName: BI.MultiLayerSelectTreeTrigger.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(this.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.MultiLayerSelectTreeCombo.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSelectTreeTrigger.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSelectTreeTrigger.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSelectTreeTrigger.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSelectTreeTrigger.EVENT_ADD_ITEM, |
|
action: function () { |
|
var value = self.trigger.getSearcher().getKeyword(); |
|
self.combo.setValue([value]); |
|
self.combo.hideView(); |
|
} |
|
}] |
|
}, |
|
toggle: !o.allowEdit, |
|
hideChecker: function (e) { |
|
// 新增传配置container后对应hideChecker的修改 |
|
// IE11下,popover(position: fixed)下放置下拉控件(position: fixed), 滚动的时候会异常卡顿 |
|
// 通过container参数将popup放置于popover之外解决此问题, 其他下拉控件由于元素少或者有分页,所以 |
|
// 卡顿不明显, 先在此做尝试, 并在FineUI特殊处理待解决文档中标记跟踪 |
|
return (o.container && self.trigger.getSearcher().isSearching() && self.trigger.getSearcher().getView().element.find(e.target).length > 0) ? false : self.triggerBtn.element.find(e.target).length === 0; |
|
|
|
}, |
|
listeners: [{ |
|
eventName: BI.Combo.EVENT_AFTER_HIDEVIEW, |
|
action: function () { |
|
self.trigger.stopEditing(); |
|
} |
|
}] |
|
} |
|
}, |
|
|
|
_getSyncConfig: function () { |
|
var o = this.options; |
|
var baseConfig = this._getBaseConfig(); |
|
return BI.extend(baseConfig, o.allowEdit ? this._getSearchConfig() : { |
|
el: { |
|
type: "bi.single_tree_trigger", |
|
text: o.text, |
|
height: o.height, |
|
items: o.items, |
|
value: o.value |
|
} |
|
}); |
|
}, |
|
|
|
_getAsyncConfig: function () { |
|
var config = this._getBaseConfig(); |
|
return BI.extend(config, this._getSearchConfig()); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.combo.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.combo.populate(items); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSelectTreeCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiLayerSelectTreeCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiLayerSelectTreeCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiLayerSelectTreeCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multilayer_select_tree_combo", BI.MultiLayerSelectTreeCombo);/** |
|
* Created by GUY on 2016/1/26. |
|
* |
|
* @class BI.MultiLayerSelectTreeInsertSearchPane |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.MultiLayerSelectTreeInsertSearchPane = BI.inherit(BI.Widget, { |
|
|
|
props: function() { |
|
return { |
|
baseCls: "bi-multilayer-select-tree-popup", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
isDefaultInit: false, |
|
itemsCreator: BI.emptyFn, |
|
items: [], |
|
value: "" |
|
}; |
|
}, |
|
|
|
render: function() { |
|
var self = this, o = this.options; |
|
this.tree = BI.createWidget({ |
|
type: "bi.multilayer_select_level_tree", |
|
isDefaultInit: o.isDefaultInit, |
|
items: o.items, |
|
itemsCreator: o.itemsCreator === BI.emptyFn ? BI.emptyFn : function (op, callback) { |
|
o.itemsCreator(op, function (res) { |
|
callback(res); |
|
self.setKeyword(o.keywordGetter()); |
|
}); |
|
}, |
|
keywordGetter: o.keywordGetter, |
|
value: o.value, |
|
scrollable: null, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSelectLevelTree.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeInsertSearchPane.EVENT_CHANGE); |
|
} |
|
}] |
|
}); |
|
return { |
|
type: "bi.vertical", |
|
scrolly: false, |
|
scrollable: true, |
|
vgap: 5, |
|
items: [{ |
|
type: "bi.text_button", |
|
invisible: true, |
|
text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), |
|
height: 24, |
|
cls: "bi-high-light", |
|
hgap: 5, |
|
ref: function (_ref) { |
|
self.addNotMatchTip = _ref; |
|
}, |
|
handler: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeInsertSearchPane.EVENT_ADD_ITEM, o.keywordGetter()); |
|
} |
|
}, this.tree] |
|
}; |
|
}, |
|
|
|
setKeyword: function (keyword) { |
|
var showTip = BI.isEmptyArray(this.tree.getAllLeaves()); |
|
this.addNotMatchTip.setVisible(showTip); |
|
showTip && this.addNotMatchTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.tree.setValue(v); |
|
}, |
|
|
|
populate: function (items) { |
|
this.tree.populate(items); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSelectTreeInsertSearchPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
BI.MultiLayerSelectTreeInsertSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multilayer_select_tree_insert_search_pane", BI.MultiLayerSelectTreeInsertSearchPane);/** |
|
* guy |
|
* 二级树 |
|
* @class BI.MultiLayerSelectLevelTree |
|
* @extends BI.Pane |
|
*/ |
|
BI.MultiLayerSelectLevelTree = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSelectLevelTree.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-select-level-tree", |
|
isDefaultInit: false, |
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
keywordGetter: BI.emptyFn, |
|
value: "", |
|
scrollable: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
var o = this.options; |
|
BI.MultiLayerSelectLevelTree.superclass._init.apply(this, arguments); |
|
|
|
this.storeValue = o.value; |
|
|
|
this.initTree(this.options.items); |
|
|
|
this.check(); |
|
}, |
|
|
|
_formatItems: function (nodes, layer, pNode) { |
|
var self = this, o = this.options; |
|
var keyword = o.keywordGetter(); |
|
BI.each(nodes, function (i, node) { |
|
var extend = {}; |
|
node.layer = layer; |
|
if (!BI.isKey(node.id)) { |
|
node.id = BI.UUID(); |
|
} |
|
node.keyword = node.keyword || keyword; |
|
extend.pNode = pNode; |
|
if (node.isParent === true || node.parent === true || BI.isNotEmptyArray(node.children)) { |
|
extend.type = "bi.multilayer_select_tree_mid_plus_group_node"; |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.multilayer_select_tree_last_plus_group_node"; |
|
extend.isLastNode = true; |
|
} |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.multilayer_select_tree_first_plus_group_node"; |
|
} |
|
if (i === 0 && i === nodes.length - 1 && !pNode) { // 根 |
|
extend.type = "bi.multilayer_select_tree_plus_group_node"; |
|
} |
|
BI.defaults(node, extend); |
|
self._formatItems(node.children, layer + 1, node); |
|
} else { |
|
extend.type = "bi.multilayer_single_tree_mid_tree_leaf_item"; |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.multilayer_single_tree_first_tree_leaf_item"; |
|
} |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.multilayer_single_tree_last_tree_leaf_item"; |
|
} |
|
BI.defaults(node, extend); |
|
} |
|
}); |
|
return nodes; |
|
}, |
|
|
|
_assertId: function (sNodes) { |
|
BI.each(sNodes, function (i, node) { |
|
node.id = node.id || BI.UUID(); |
|
}); |
|
}, |
|
|
|
// 构造树结构, |
|
initTree: function (nodes) { |
|
var self = this, o = this.options; |
|
var hasNext = false; |
|
this.empty(); |
|
this._assertId(nodes); |
|
this.tree = BI.createWidget({ |
|
type: "bi.custom_tree", |
|
cls: "tree-view display-table", |
|
expander: { |
|
type: "bi.select_tree_expander", |
|
isDefaultInit: o.isDefaultInit, |
|
el: {}, |
|
popup: { |
|
type: "bi.custom_tree" |
|
} |
|
}, |
|
|
|
items: this._formatItems(BI.Tree.transformToTreeFormat(nodes), 0), |
|
itemsCreator: function (op, callback) { |
|
(op.times === 1 && !op.node) && BI.nextTick(function () { |
|
self.loading(); |
|
}); |
|
o.itemsCreator(op, function (ob) { |
|
hasNext = ob.hasNext; |
|
(op.times === 1 && !op.node) && self._populate(ob.items); |
|
callback(self._formatItems(BI.Tree.transformToTreeFormat(ob.items), op.node ? op.node.layer + 1 : 0, op.node)); |
|
self.setValue(self.storeValue); |
|
(op.times === 1 && !op.node) && BI.nextTick(function () { |
|
self.loaded(); |
|
}); |
|
}); |
|
}, |
|
value: o.value, |
|
|
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: o.itemsCreator !== BI.emptyFn, |
|
el: { |
|
type: "bi.button_tree", |
|
chooseType: o.chooseType, |
|
behaviors: o.behaviors, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
} |
|
} |
|
}); |
|
this.tree.on(BI.Controller.EVENT_CHANGE, function (type, value) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.setValue(value); |
|
self.fireEvent(BI.MultiLayerSelectLevelTree.EVENT_CHANGE, arguments); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.adaptive", |
|
element: this, |
|
scrollable: o.scrollable, |
|
items: [this.tree] |
|
}); |
|
}, |
|
|
|
_populate: function () { |
|
BI.MultiLayerSelectLevelTree.superclass.populate.apply(this, arguments); |
|
}, |
|
|
|
populate: function (nodes) { |
|
this._populate(nodes); |
|
BI.isNull(nodes) ? this.tree.populate() : this.tree.populate(this._formatItems(BI.Tree.transformToTreeFormat(nodes), 0)); |
|
}, |
|
|
|
setValue: function (v) { |
|
// getValue依赖于storeValue, 那么不选的时候就不要更新storeValue了 |
|
if(this.options.chooseType === BI.Selection.None) { |
|
} else { |
|
this.storeValue = v; |
|
this.tree.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return BI.isArray(this.storeValue) ? |
|
this.storeValue : BI.isNull(this.storeValue) ? |
|
[] : [this.storeValue]; |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.tree.getAllLeaves(); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.tree.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (id) { |
|
return this.tree.getNodeByValue(id); |
|
} |
|
}); |
|
BI.MultiLayerSelectLevelTree.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.multilayer_select_level_tree", BI.MultiLayerSelectLevelTree);/** |
|
* Created by GUY on 2016/1/26. |
|
* |
|
* @class BI.MultiLayerSelectTreePopup |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.MultiLayerSelectTreePopup = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSelectTreePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-select-tree-popup", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
isDefaultInit: false, |
|
itemsCreator: BI.emptyFn, |
|
items: [], |
|
value: "", |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiLayerSelectTreePopup.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
this.tree = BI.createWidget({ |
|
type: "bi.multilayer_select_level_tree", |
|
isDefaultInit: o.isDefaultInit, |
|
items: o.items, |
|
itemsCreator: o.itemsCreator, |
|
keywordGetter: o.keywordGetter, |
|
value: o.value, |
|
scrollable: null, |
|
onLoaded: function () { |
|
self.tree.check(); |
|
o.onLoaded(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
scrollable: true, |
|
element: this, |
|
vgap: 5, |
|
items: [this.tree] |
|
}); |
|
|
|
this.tree.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.tree.on(BI.MultiLayerSelectLevelTree.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiLayerSelectTreePopup.EVENT_CHANGE); |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.tree.setValue(v); |
|
}, |
|
|
|
populate: function (items) { |
|
this.tree.populate(items); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSelectTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multilayer_select_tree_popup", BI.MultiLayerSelectTreePopup);/** |
|
* Created by Windy on 2018/2/2. |
|
*/ |
|
BI.MultiLayerSelectTreeTrigger = BI.inherit(BI.Trigger, { |
|
|
|
props: function() { |
|
return { |
|
extraCls: "bi-multi-layer-select-tree-trigger bi-border bi-focus-shadow bi-border-radius", |
|
height: 24, |
|
valueFormatter: function (v) { |
|
return v; |
|
}, |
|
itemsCreator: BI.emptyFn, |
|
watermark: BI.i18nText("BI-Basic_Search"), |
|
allowSearchValue: false, |
|
title: BI.bind(this._getShowText, this) |
|
}; |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
if(o.itemsCreator === BI.emptyFn) { |
|
this._initData(); |
|
} |
|
var content = { |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: { |
|
type: "bi.searcher", |
|
ref: function () { |
|
self.searcher = this; |
|
}, |
|
masker: BI.isNotNull(o.container) ? { |
|
offset: {}, |
|
container: o.container |
|
} : { |
|
offset: {} |
|
}, |
|
isAutoSearch: false, |
|
el: { |
|
type: "bi.state_editor", |
|
ref: function () { |
|
self.editor = this; |
|
}, |
|
defaultText: o.text, |
|
text: this._digest(o.value), |
|
value: o.value, |
|
height: o.height, |
|
tipText: "", |
|
watermark: o.watermark, |
|
listeners: [{ |
|
eventName: BI.StateEditor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeTrigger.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.StateEditor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeTrigger.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.StateEditor.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeTrigger.EVENT_SEARCHING); |
|
} |
|
}] |
|
}, |
|
popup: { |
|
type: o.allowInsertValue ? "bi.multilayer_select_tree_insert_search_pane" : "bi.multilayer_select_tree_popup", |
|
itemsCreator: o.itemsCreator === BI.emptyFn ? BI.emptyFn : function (op, callback) { |
|
op.keyword = self.editor.getValue(); |
|
o.itemsCreator(op, callback); |
|
}, |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
cls: "bi-card", |
|
listeners: [{ |
|
eventName: BI.MultiLayerSelectTreeInsertSearchPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
self.options.text = self.getSearcher().getKeyword(); |
|
self.fireEvent(BI.MultiLayerSelectTreeTrigger.EVENT_ADD_ITEM); |
|
} |
|
}], |
|
ref: function (_ref) { |
|
self.popup = _ref; |
|
} |
|
}, |
|
onSearch: function (obj, callback) { |
|
var keyword = obj.keyword; |
|
if(o.itemsCreator === BI.emptyFn) { |
|
callback(self._getSearchItems(keyword)); |
|
o.allowInsertValue && self.popup.setKeyword(keyword); |
|
} else { |
|
callback(); |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSelectTreeTrigger.EVENT_CHANGE); |
|
} |
|
}] |
|
} |
|
}, { |
|
el: { |
|
type: "bi.layout", |
|
width: 24 |
|
}, |
|
width: 24 |
|
} |
|
] |
|
}; |
|
|
|
return o.allowEdit ? content : { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: content, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.layout" |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
_initData: function() { |
|
var o = this.options; |
|
this.tree = new BI.Tree(); |
|
this.nodes = BI.Tree.treeFormat(BI.deepClone(o.items)); |
|
this.tree.initTree(this.nodes); |
|
}, |
|
|
|
_getSearchItems: function(keyword) { |
|
var self = this, o = this.options; |
|
// 把数组搜索换成用BI.tree搜索节点, 搜到了就不再往下搜索 |
|
var items = []; |
|
this.tree.traverse(function (node) { |
|
var find = BI.Func.getSearchResult(self.tree.isRoot(node) ? [] : BI.concat([node.text], (o.allowSearchValue ? [node.value] : [])), keyword); |
|
if(find.find.length > 0 || find.match.length > 0) { |
|
items.push(node); |
|
return true; |
|
} |
|
}); |
|
return this._fillTreeStructure4Search(items, "id"); |
|
}, |
|
|
|
_createJson: function(node, open) { |
|
return { |
|
id: node.id, |
|
pId: node.pId, |
|
text: node.text, |
|
value: node.value, |
|
isParent: BI.isNotEmptyArray(node.children), |
|
open: open |
|
} |
|
}, |
|
|
|
_getChildren: function(node) { |
|
var self = this; |
|
node.children = node.children || []; |
|
var nodes = []; |
|
BI.each(node.children, function (idx, child) { |
|
var children = self._getChildren(child); |
|
nodes = nodes.concat(children); |
|
}); |
|
return node.children.concat(nodes); |
|
}, |
|
|
|
// 将搜索到的节点进行补充,构造成一棵完整的树 |
|
_fillTreeStructure4Search: function (leaves) { |
|
var self = this; |
|
var result = []; |
|
var queue = []; |
|
BI.each(leaves, function (idx, node) { |
|
queue.push({pId: node.pId}); |
|
result.push(node); |
|
result = result.concat(self._getChildren(node)); |
|
}); |
|
while (BI.isNotEmptyArray(queue)) { |
|
var node = queue.pop(); |
|
var pNode = this.tree.search(this.tree.getRoot(), node.pId, "id"); |
|
if (pNode != null) { |
|
pNode.open = true; |
|
queue.push({pId: pNode.pId}); |
|
result.push(pNode); |
|
} |
|
} |
|
return BI.uniqBy(BI.map(result, function (idx, node) { |
|
return self._createJson(node, node.open); |
|
}), "id"); |
|
}, |
|
|
|
_digest: function (v) { |
|
var o = this.options; |
|
if(o.itemsCreator === BI.emptyFn) { |
|
var result = BI.find(o.items, function (i, item) { |
|
return item.value === v; |
|
}); |
|
return BI.isNotNull(result) ? result.text : o.text; |
|
} |
|
return o.valueFormatter(v); |
|
}, |
|
|
|
_getShowText: function () { |
|
return this.editor.getText(); |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this._initData(items); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setState(this._digest(v[0])); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSelectTreeTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiLayerSelectTreeTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiLayerSelectTreeTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiLayerSelectTreeTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiLayerSelectTreeTrigger.EVENT_START = "EVENT_START"; |
|
BI.MultiLayerSelectTreeTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiLayerSelectTreeTrigger.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
BI.shortcut("bi.multilayer_select_tree_trigger", BI.MultiLayerSelectTreeTrigger);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSelectTreeFirstPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSelectTreeFirstPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSelectTreeFirstPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-select-tree-first-plus-group-node bi-list-item-active", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSelectTreeFirstPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = BI.createWidget({ |
|
type: "bi.select_tree_first_plus_group_node", |
|
cls: "bi-list-item-none", |
|
stopPropagation: true, |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
keyword: o.keyword, |
|
open: o.open, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.node.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.setSelected(self.isSelected()); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.node.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.MultiLayerSelectTreeFirstPlusGroupNode.superclass.setSelected.apply(this, arguments); |
|
this.node.setSelected(b); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSelectTreeFirstPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
this.node.setOpened(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_select_tree_first_plus_group_node", BI.MultiLayerSelectTreeFirstPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSelectTreeLastPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSelectTreeLastPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSelectTreeLastPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-select-tree-last-plus-group-node bi-list-item-active", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSelectTreeLastPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = BI.createWidget({ |
|
type: "bi.select_tree_last_plus_group_node", |
|
cls: "bi-list-item-none", |
|
stopPropagation: true, |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
keyword: o.keyword, |
|
open: o.open, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.node.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.setSelected(self.isSelected()); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.node.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.MultiLayerSelectTreeLastPlusGroupNode.superclass.setSelected.apply(this, arguments); |
|
this.node.setSelected(b); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSelectTreeLastPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSelectTreeLastPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
this.node.setOpened(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_select_tree_last_plus_group_node", BI.MultiLayerSelectTreeLastPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSelectTreeMidPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSelectTreeMidPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSelectTreeMidPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-select-tree-mid-plus-group-node bi-list-item-active", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSelectTreeMidPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = BI.createWidget({ |
|
type: "bi.select_tree_mid_plus_group_node", |
|
cls: "bi-list-item-none", |
|
stopPropagation: true, |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
keyword: o.keyword, |
|
open: o.open, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.node.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.setSelected(self.isSelected()); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.node.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.MultiLayerSelectTreeMidPlusGroupNode.superclass.setSelected.apply(this, arguments); |
|
this.node.setSelected(b); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSelectTreeMidPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSelectTreeMidPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
this.node.setOpened(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_select_tree_mid_plus_group_node", BI.MultiLayerSelectTreeMidPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSelectTreePlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSelectTreePlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSelectTreePlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-select-tree-first-plus-group-node bi-list-item-active", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSelectTreePlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = BI.createWidget({ |
|
type: "bi.select_tree_plus_group_node", |
|
cls: "bi-list-item-none", |
|
stopPropagation: true, |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
keyword: o.keyword, |
|
open: o.open, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
this.node.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
self.setSelected(self.isSelected()); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
isSelected: function () { |
|
return this.node.isSelected(); |
|
}, |
|
|
|
setSelected: function (b) { |
|
BI.MultiLayerSelectTreePlusGroupNode.superclass.setSelected.apply(this, arguments); |
|
this.node.setSelected(b); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSelectTreePlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
this.node.setOpened(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_select_tree_plus_group_node", BI.MultiLayerSelectTreePlusGroupNode);/** |
|
* 多层级下拉单选树 |
|
* Created by GUY on 2016/1/26. |
|
* |
|
* @class BI.MultiLayerSingleTreeCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.MultiLayerSingleTreeCombo = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSingleTreeCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-single-tree-combo", |
|
isDefaultInit: false, |
|
height: 24, |
|
text: "", |
|
itemsCreator: BI.emptyFn, |
|
items: [], |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
}, |
|
allowEdit: false, |
|
allowSearchValue: false, |
|
allowInsertValue: false |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
|
|
var combo = (o.itemsCreator === BI.emptyFn) ? this._getSyncConfig() : this._getAsyncConfig(); |
|
|
|
return (!o.allowEdit && o.itemsCreator === BI.emptyFn) ? combo : { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
cls: "trigger-icon-button", |
|
ref: function (_ref) { |
|
self.triggerBtn = _ref; |
|
}, |
|
width: o.height, |
|
height: o.height, |
|
handler: function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
} |
|
}, |
|
right: 0, |
|
bottom: 0, |
|
top: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
_getBaseConfig: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.combo", |
|
container: o.container, |
|
destroyWhenHide: o.destroyWhenHide, |
|
adjustLength: 2, |
|
ref: function (_ref) { |
|
self.combo = _ref; |
|
}, |
|
popup: { |
|
el: { |
|
type: "bi.multilayer_single_tree_popup", |
|
isDefaultInit: o.isDefaultInit, |
|
itemsCreator: o.itemsCreator, |
|
items: o.items, |
|
ref: function (_ref) { |
|
self.trigger && self.trigger.getSearcher().setAdapter(_ref); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiLayerSingleTreePopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(this.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.MultiLayerSingleTreeCombo.EVENT_CHANGE); |
|
} |
|
}], |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
}); |
|
} |
|
}, |
|
value: o.value, |
|
maxHeight: 400, |
|
minHeight: 240 |
|
} |
|
}; |
|
}, |
|
|
|
_getSearchConfig: function() { |
|
var self = this, o = this.options; |
|
return { |
|
el: { |
|
type: "bi.multilayer_single_tree_trigger", |
|
container: o.container, |
|
allowInsertValue: o.allowInsertValue, |
|
allowSearchValue: o.allowSearchValue, |
|
allowEdit: o.allowEdit, |
|
cls: "multilayer-single-tree-trigger", |
|
ref: function (_ref) { |
|
self.trigger = _ref; |
|
}, |
|
watermark: o.watermark, |
|
items: o.items, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
height: o.height - 2, |
|
text: o.text, |
|
value: o.value, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle, |
|
title: o.title, |
|
listeners: [{ |
|
eventName: BI.MultiLayerSingleTreeTrigger.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(this.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.MultiLayerSingleTreeCombo.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSingleTreeTrigger.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSingleTreeTrigger.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSingleTreeTrigger.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSingleTreeTrigger.EVENT_ADD_ITEM, |
|
action: function () { |
|
var value = self.trigger.getSearcher().getKeyword(); |
|
self.combo.setValue([value]); |
|
self.combo.hideView(); |
|
} |
|
}] |
|
}, |
|
toggle: !o.allowEdit, |
|
hideChecker: function (e) { |
|
// 新增传配置container后对应hideChecker的修改 |
|
// IE11下,popover(position: fixed)下放置下拉控件(position: fixed), 滚动的时候会异常卡顿 |
|
// 通过container参数将popup放置于popover之外解决此问题, 其他下拉控件由于元素少或者有分页,所以 |
|
// 卡顿不明显, 先在此做尝试, 并在FineUI特殊处理待解决文档中标记跟踪 |
|
return (o.container && self.trigger.getSearcher().isSearching() && self.trigger.getSearcher().getView().element.find(e.target).length > 0) ? false : self.triggerBtn.element.find(e.target).length === 0 |
|
}, |
|
listeners: [{ |
|
eventName: BI.Combo.EVENT_AFTER_HIDEVIEW, |
|
action: function () { |
|
self.trigger.stopEditing(); |
|
} |
|
}] |
|
} |
|
}, |
|
|
|
_getSyncConfig: function () { |
|
var o = this.options; |
|
var baseConfig = this._getBaseConfig(); |
|
return BI.extend(baseConfig, o.allowEdit ? this._getSearchConfig() : { |
|
el: { |
|
type: "bi.single_tree_trigger", |
|
text: o.text, |
|
height: o.height, |
|
items: o.items, |
|
value: o.value |
|
} |
|
}); |
|
}, |
|
|
|
_getAsyncConfig: function () { |
|
var config = this._getBaseConfig(); |
|
return BI.extend(config, this._getSearchConfig()); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.combo.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.combo.populate(items); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSingleTreeCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiLayerSingleTreeCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiLayerSingleTreeCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiLayerSingleTreeCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multilayer_single_tree_combo", BI.MultiLayerSingleTreeCombo);/** |
|
* Created by GUY on 2016/1/26. |
|
* |
|
* @class BI.MultiLayerSingleTreeInsertSearchPane |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.MultiLayerSingleTreeInsertSearchPane = BI.inherit(BI.Widget, { |
|
|
|
props: function() { |
|
return { |
|
baseCls: "bi-multilayer-single-tree-popup", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
isDefaultInit: false, |
|
itemsCreator: BI.emptyFn, |
|
items: [], |
|
value: "" |
|
}; |
|
}, |
|
|
|
render: function() { |
|
var self = this, o = this.options; |
|
this.tree = BI.createWidget({ |
|
type: "bi.multilayer_single_level_tree", |
|
isDefaultInit: o.isDefaultInit, |
|
items: o.items, |
|
itemsCreator: o.itemsCreator === BI.emptyFn ? BI.emptyFn : function (op, callback) { |
|
o.itemsCreator(op, function (res) { |
|
callback(res); |
|
self.setKeyword(o.keywordGetter()); |
|
}); |
|
}, |
|
keywordGetter: o.keywordGetter, |
|
value: o.value, |
|
scrollable: null, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}, { |
|
eventName: BI.MultiLayerSelectLevelTree.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeInsertSearchPane.EVENT_CHANGE); |
|
} |
|
}] |
|
}); |
|
return { |
|
type: "bi.vertical", |
|
scrolly: false, |
|
scrollable: true, |
|
vgap: 5, |
|
items: [{ |
|
type: "bi.text_button", |
|
invisible: true, |
|
text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), |
|
height: 24, |
|
cls: "bi-high-light", |
|
hgap: 5, |
|
ref: function (_ref) { |
|
self.addNotMatchTip = _ref; |
|
}, |
|
handler: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeInsertSearchPane.EVENT_ADD_ITEM, o.keywordGetter()); |
|
} |
|
}, this.tree] |
|
}; |
|
}, |
|
|
|
setKeyword: function (keyword) { |
|
var showTip = BI.isEmptyArray(this.tree.getAllLeaves()); |
|
this.addNotMatchTip.setVisible(showTip); |
|
showTip && this.addNotMatchTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.tree.setValue(v); |
|
}, |
|
|
|
populate: function (items) { |
|
this.tree.populate(items); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSingleTreeInsertSearchPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
BI.MultiLayerSingleTreeInsertSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multilayer_single_tree_insert_search_pane", BI.MultiLayerSingleTreeInsertSearchPane);/** |
|
* guy |
|
* 二级树 |
|
* @class BI.MultiLayerSingleLevelTree |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiLayerSingleLevelTree = BI.inherit(BI.Pane, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSingleLevelTree.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-single-level-tree", |
|
isDefaultInit: false, |
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
keywordGetter: BI.emptyFn, |
|
chooseType: BI.Selection.Single, |
|
scrollable: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
var o = this.options; |
|
BI.MultiLayerSingleLevelTree.superclass._init.apply(this, arguments); |
|
|
|
this.storeValue = o.value; |
|
|
|
this.initTree(this.options.items); |
|
|
|
this.check(); |
|
}, |
|
|
|
_formatItems: function (nodes, layer, pNode) { |
|
var self = this, o = this.options; |
|
var keyword = o.keywordGetter(); |
|
BI.each(nodes, function (i, node) { |
|
var extend = {}; |
|
node.layer = layer; |
|
if (!BI.isKey(node.id)) { |
|
node.id = BI.UUID(); |
|
} |
|
node.keyword = node.keyword || keyword; |
|
extend.pNode = pNode; |
|
if (node.isParent === true || node.parent === true || BI.isNotEmptyArray(node.children)) { |
|
extend.type = "bi.multilayer_single_tree_mid_plus_group_node"; |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.multilayer_single_tree_last_plus_group_node"; |
|
extend.isLastNode = true; |
|
} |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.multilayer_single_tree_first_plus_group_node"; |
|
} |
|
if (i === 0 && i === nodes.length - 1 && !pNode) { // 根 |
|
extend.type = "bi.multilayer_single_tree_plus_group_node"; |
|
} |
|
BI.defaults(node, extend); |
|
self._formatItems(node.children, layer + 1, node); |
|
} else { |
|
extend.type = "bi.multilayer_single_tree_mid_tree_leaf_item"; |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.multilayer_single_tree_first_tree_leaf_item"; |
|
} |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.multilayer_single_tree_last_tree_leaf_item"; |
|
} |
|
BI.defaults(node, extend); |
|
} |
|
}); |
|
return nodes; |
|
}, |
|
|
|
_assertId: function (sNodes) { |
|
BI.each(sNodes, function (i, node) { |
|
node.id = node.id || BI.UUID(); |
|
}); |
|
}, |
|
|
|
// 构造树结构, |
|
initTree: function (nodes) { |
|
var self = this, o = this.options; |
|
var hasNext = false; |
|
this.empty(); |
|
this._assertId(nodes); |
|
this.tree = BI.createWidget({ |
|
type: "bi.custom_tree", |
|
cls: "tree-view display-table", |
|
expander: { |
|
isDefaultInit: o.isDefaultInit, |
|
el: {}, |
|
popup: { |
|
type: "bi.custom_tree" |
|
} |
|
}, |
|
|
|
items: this._formatItems(BI.Tree.transformToTreeFormat(nodes), 0), |
|
value: o.value, |
|
itemsCreator: function (op, callback) { |
|
(op.times === 1 && !op.node) && BI.nextTick(function () { |
|
self.loading(); |
|
}); |
|
o.itemsCreator(op, function (ob) { |
|
hasNext = ob.hasNext; |
|
(op.times === 1 && !op.node) && self._populate(ob.items); |
|
callback(self._formatItems(BI.Tree.transformToTreeFormat(ob.items), op.node ? op.node.layer + 1 : 0, op.node)); |
|
self.setValue(self.storeValue); |
|
(op.times === 1 && !op.node) && BI.nextTick(function () { |
|
self.loaded(); |
|
}); |
|
}); |
|
}, |
|
|
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: o.itemsCreator !== BI.emptyFn, |
|
el: { |
|
type: "bi.button_tree", |
|
chooseType: o.chooseType, |
|
behaviors: o.behaviors, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
} |
|
} |
|
}); |
|
this.tree.on(BI.Controller.EVENT_CHANGE, function (type, v) { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
if (type === BI.Events.CLICK) { |
|
self.setValue(v); |
|
self.fireEvent(BI.MultiLayerSingleLevelTree.EVENT_CHANGE, v); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.adaptive", |
|
element: this, |
|
scrollable: o.scrollable, |
|
items: [this.tree] |
|
}); |
|
}, |
|
|
|
_populate: function () { |
|
BI.MultiLayerSelectLevelTree.superclass.populate.apply(this, arguments); |
|
}, |
|
|
|
populate: function (nodes) { |
|
this._populate(nodes); |
|
BI.isNull(nodes) ? this.tree.populate() : this.tree.populate(this._formatItems(BI.Tree.transformToTreeFormat(nodes), 0)); |
|
}, |
|
|
|
setValue: function (v) { |
|
// getValue依赖于storeValue, 那么不选的时候就不要更新storeValue了 |
|
if(this.options.chooseType === BI.Selection.None) { |
|
} else { |
|
this.storeValue = v; |
|
this.tree.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return BI.isArray(this.storeValue) ? |
|
this.storeValue : BI.isNull(this.storeValue) ? |
|
[] : [this.storeValue]; |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.tree.getAllLeaves(); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.tree.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (id) { |
|
return this.tree.getNodeByValue(id); |
|
} |
|
}); |
|
BI.MultiLayerSingleLevelTree.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.multilayer_single_level_tree", BI.MultiLayerSingleLevelTree); |
|
/** |
|
* Created by GUY on 2016/1/26. |
|
* |
|
* @class BI.MultiLayerSingleTreePopup |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.MultiLayerSingleTreePopup = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSingleTreePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multilayer-singletree-popup", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
isDefaultInit: false, |
|
itemsCreator: BI.emptyFn, |
|
items: [], |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiLayerSingleTreePopup.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
this.tree = BI.createWidget({ |
|
type: "bi.multilayer_single_level_tree", |
|
isDefaultInit: o.isDefaultInit, |
|
items: o.items, |
|
itemsCreator: o.itemsCreator, |
|
keywordGetter: o.keywordGetter, |
|
value: o.value, |
|
scrollable: null, |
|
onLoaded: function () { |
|
self.tree.check(); |
|
o.onLoaded(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
scrollable: true, |
|
element: this, |
|
vgap: 5, |
|
items: [this.tree] |
|
}); |
|
|
|
this.tree.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.tree.on(BI.MultiLayerSingleLevelTree.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiLayerSingleTreePopup.EVENT_CHANGE); |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.tree.setValue(v); |
|
}, |
|
|
|
populate: function (items) { |
|
this.tree.populate(items); |
|
} |
|
}); |
|
|
|
BI.MultiLayerSingleTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multilayer_single_tree_popup", BI.MultiLayerSingleTreePopup);/** |
|
* Created by Windy on 2018/2/2. |
|
*/ |
|
BI.MultiLayerSingleTreeTrigger = BI.inherit(BI.Trigger, { |
|
|
|
props: function() { |
|
return { |
|
extraCls: "bi-multi-layer-single-tree-trigger bi-border bi-focus-shadow bi-border-radius", |
|
height: 24, |
|
valueFormatter: function (v) { |
|
return v; |
|
}, |
|
itemsCreator: BI.emptyFn, |
|
watermark: BI.i18nText("BI-Basic_Search"), |
|
allowSearchValue: false, |
|
title: BI.bind(this._getShowText, this) |
|
}; |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
if(o.itemsCreator === BI.emptyFn) { |
|
this._initData(); |
|
} |
|
var content = { |
|
type: "bi.htape", |
|
items: [ |
|
{ |
|
el: { |
|
type: "bi.searcher", |
|
ref: function () { |
|
self.searcher = this; |
|
}, |
|
masker: BI.isNotNull(o.container) ? { |
|
offset: {}, |
|
container: o.container |
|
} : { |
|
offset: {} |
|
}, |
|
isAutoSearch: false, |
|
el: { |
|
type: "bi.state_editor", |
|
ref: function () { |
|
self.editor = this; |
|
}, |
|
defaultText: o.text, |
|
text: this._digest(o.value), |
|
value: o.value, |
|
height: o.height, |
|
tipText: "", |
|
watermark: o.watermark, |
|
listeners: [{ |
|
eventName: BI.StateEditor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeTrigger.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.StateEditor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeTrigger.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.StateEditor.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeTrigger.EVENT_SEARCHING); |
|
} |
|
}] |
|
}, |
|
popup: { |
|
type: o.allowInsertValue ? "bi.multilayer_single_tree_insert_search_pane" : "bi.multilayer_single_tree_popup", |
|
itemsCreator: o.itemsCreator === BI.emptyFn ? BI.emptyFn : function (op, callback) { |
|
op.keyword = self.editor.getValue(); |
|
o.itemsCreator(op, callback); |
|
}, |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
cls: "bi-card", |
|
listeners: [{ |
|
eventName: BI.MultiLayerSingleTreeInsertSearchPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
self.options.text = self.getSearcher().getKeyword(); |
|
self.fireEvent(BI.MultiLayerSingleTreeTrigger.EVENT_ADD_ITEM); |
|
} |
|
}], |
|
ref: function (_ref) { |
|
self.popup = _ref; |
|
} |
|
}, |
|
onSearch: function (obj, callback) { |
|
var keyword = obj.keyword; |
|
if(o.itemsCreator === BI.emptyFn) { |
|
callback(self._getSearchItems(keyword)); |
|
o.allowInsertValue && self.popup.setKeyword(keyword); |
|
} else { |
|
callback(); |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiLayerSingleTreeTrigger.EVENT_CHANGE); |
|
} |
|
}] |
|
} |
|
}, { |
|
el: { |
|
type: "bi.layout", |
|
width: 24 |
|
}, |
|
width: 24 |
|
} |
|
] |
|
}; |
|
|
|
return o.allowEdit ? content : { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: content, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.layout" |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
_initData: function() { |
|
var o = this.options; |
|
this.tree = new BI.Tree(); |
|
this.nodes = BI.Tree.treeFormat(BI.deepClone(o.items)); |
|
this.tree.initTree(this.nodes); |
|
}, |
|
|
|
_getSearchItems: function(keyword) { |
|
var self = this, o = this.options; |
|
// 把数组搜索换成用BI.tree搜索节点, 搜到了就不再往下搜索 |
|
var items = []; |
|
this.tree.traverse(function (node) { |
|
var find = BI.Func.getSearchResult(self.tree.isRoot(node) ? [] : BI.concat([node.text], (o.allowSearchValue ? [node.value] : [])), keyword); |
|
if(find.find.length > 0 || find.match.length > 0) { |
|
items.push(node); |
|
return true; |
|
} |
|
}); |
|
return this._fillTreeStructure4Search(items, "id"); |
|
}, |
|
|
|
_createJson: function(node, open) { |
|
return { |
|
id: node.id, |
|
pId: node.pId, |
|
text: node.text, |
|
value: node.value, |
|
isParent: BI.isNotEmptyArray(node.children), |
|
open: open |
|
} |
|
}, |
|
|
|
_getChildren: function(node) { |
|
var self = this; |
|
node.children = node.children || []; |
|
var nodes = []; |
|
BI.each(node.children, function (idx, child) { |
|
var children = self._getChildren(child); |
|
nodes = nodes.concat(children); |
|
}); |
|
return node.children.concat(nodes); |
|
}, |
|
|
|
// 将搜索到的节点进行补充,构造成一棵完整的树 |
|
_fillTreeStructure4Search: function (leaves) { |
|
var self = this; |
|
var result = []; |
|
var queue = []; |
|
BI.each(leaves, function (idx, node) { |
|
queue.push({pId: node.pId}); |
|
result.push(node); |
|
result = result.concat(self._getChildren(node)); |
|
}); |
|
while (BI.isNotEmptyArray(queue)) { |
|
var node = queue.pop(); |
|
var pNode = this.tree.search(this.tree.getRoot(), node.pId, "id"); |
|
if (pNode != null) { |
|
pNode.open = true; |
|
queue.push({pId: pNode.pId}); |
|
result.push(pNode); |
|
} |
|
} |
|
return BI.uniqBy(BI.map(result, function (idx, node) { |
|
return self._createJson(node, node.open); |
|
}), "id"); |
|
}, |
|
|
|
_digest: function (v) { |
|
var o = this.options; |
|
if(o.itemsCreator === BI.emptyFn) { |
|
var result = BI.find(o.items, function (i, item) { |
|
return item.value === v; |
|
}); |
|
return BI.isNotNull(result) ? result.text : o.text; |
|
} |
|
return o.valueFormatter(v); |
|
|
|
}, |
|
|
|
_getShowText: function () { |
|
return this.editor.getText(); |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this._initData(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setState(this._digest(v[0])); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
BI.MultiLayerSingleTreeTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiLayerSingleTreeTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiLayerSingleTreeTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiLayerSingleTreeTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiLayerSingleTreeTrigger.EVENT_START = "EVENT_START"; |
|
BI.MultiLayerSingleTreeTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiLayerSingleTreeTrigger.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
BI.shortcut("bi.multilayer_single_tree_trigger", BI.MultiLayerSingleTreeTrigger);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSingleTreeFirstPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSingleTreeFirstPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSingleTreeFirstPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-single-tree-first-plus-group-node bi-list-item", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreeFirstPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = this._createNode(); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreeFirstPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSingleTreeFirstPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.node)) { |
|
this.node.setOpened(v); |
|
} |
|
}, |
|
|
|
_createNode: function () { |
|
var self = this, o = this.options; |
|
|
|
return BI.createWidget({ |
|
type: "bi.first_plus_group_node", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
open: o.open, |
|
isLastNode: o.isLastNode, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}] |
|
}); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_first_plus_group_node", BI.MultiLayerSingleTreeFirstPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSingleTreeLastPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSingleTreeLastPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSingleTreeLastPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-single-tree-last-plus-group-node bi-list-item", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreeLastPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = this._createNode(); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreeLastPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSingleTreeLastPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.node)) { |
|
this.node.setOpened(v); |
|
} |
|
}, |
|
|
|
_createNode: function () { |
|
var self = this, o = this.options; |
|
|
|
return BI.createWidget({ |
|
type: "bi.last_plus_group_node", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
open: o.open, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}] |
|
}); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_last_plus_group_node", BI.MultiLayerSingleTreeLastPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSingleTreeMidPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.MultiLayerSingleTreeMidPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSingleTreeMidPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-single-tree-mid-plus-group-node bi-list-item", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreeMidPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = this._createNode(); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreeMidPlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSingleTreeMidPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.node)) { |
|
this.node.setOpened(v); |
|
} |
|
}, |
|
|
|
_createNode: function () { |
|
var self = this, o = this.options; |
|
|
|
return BI.createWidget({ |
|
type: "bi.mid_plus_group_node", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
open: o.open, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}] |
|
}); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_mid_plus_group_node", BI.MultiLayerSingleTreeMidPlusGroupNode);/** |
|
*@desc 根节点,既是第一个又是最后一个 |
|
*@author dailer |
|
*@date 2018/09/16 |
|
*/ |
|
BI.MultiLayerSingleTreePlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.MultiLayerSingleTreePlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-multilayer-single-tree-plus-group-node bi-list-item", |
|
layer: 0, // 第几层级 |
|
id: "", |
|
pId: "", |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreePlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.node = this._createNode(); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.node); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.node.doRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.node.unRedMark.apply(this.node, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreePlusGroupNode.superclass.doClick.apply(this, arguments); |
|
this.node.setSelected(this.isSelected()); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.MultiLayerSingleTreePlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.node)) { |
|
this.node.setOpened(v); |
|
} |
|
}, |
|
|
|
_createNode: function () { |
|
var self = this, o = this.options; |
|
|
|
return BI.createWidget({ |
|
type: "bi.plus_group_node", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
open: o.open, |
|
isLastNode: o.isLastNode, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}] |
|
}); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_plus_group_node", BI.MultiLayerSingleTreePlusGroupNode);/** |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSingleTreeFirstTreeLeafItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.MultiLayerSingleTreeFirstTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSingleTreeFirstTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-multilayer-single-tree-first-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
layer: 0, |
|
id: "", |
|
pId: "", |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreeFirstTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.item = BI.createWidget({ |
|
type: "bi.first_tree_leaf_item", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.item.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.item); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.item.doHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.item.unHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreeFirstTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
this.item.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MultiLayerSingleTreeFirstTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
this.item.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_first_tree_leaf_item", BI.MultiLayerSingleTreeFirstTreeLeafItem);/** |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSingleTreeLastTreeLeafItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.MultiLayerSingleTreeLastTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSingleTreeLastTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-multilayer-single-tree-last-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
layer: 0, |
|
id: "", |
|
pId: "", |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreeLastTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.item = BI.createWidget({ |
|
type: "bi.last_tree_leaf_item", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.item.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.item); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.item.doHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.item.unHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreeLastTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
this.item.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MultiLayerSingleTreeLastTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
this.item.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_last_tree_leaf_item", BI.MultiLayerSingleTreeLastTreeLeafItem);/** |
|
* |
|
* Created by GUY on 2016/1/27. |
|
* @class BI.MultiLayerSingleTreeMidTreeLeafItem |
|
* @extends BI.BasicButton |
|
*/ |
|
BI.MultiLayerSingleTreeMidTreeLeafItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiLayerSingleTreeMidTreeLeafItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-multilayer-single-tree-mid-tree-leaf-item bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
layer: 0, |
|
id: "", |
|
pId: "", |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiLayerSingleTreeMidTreeLeafItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.item = BI.createWidget({ |
|
type: "bi.mid_tree_leaf_item", |
|
cls: "bi-list-item-none", |
|
logic: { |
|
dynamic: true |
|
}, |
|
id: o.id, |
|
pId: o.pId, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
py: o.py, |
|
keyword: o.keyword |
|
}); |
|
this.item.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) {// 本身实现click功能 |
|
return; |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
var needBlankLayers = []; |
|
var pNode = o.pNode; |
|
while (pNode) { |
|
if (pNode.isLastNode) { |
|
needBlankLayers.push(pNode.layer) |
|
} |
|
pNode = pNode.pNode; |
|
} |
|
|
|
var items = []; |
|
BI.count(0, o.layer, function (index) { |
|
items.push({ |
|
type: "bi.layout", |
|
cls: BI.contains(needBlankLayers, index) ? "" : "base-line-conn-background", |
|
width: 12, |
|
height: o.height |
|
}); |
|
}); |
|
items.push(this.item); |
|
BI.createWidget({ |
|
type: "bi.td", |
|
element: this, |
|
columnSize: BI.makeArray(o.layer, 12), |
|
items: [items] |
|
}); |
|
}, |
|
|
|
doHighLight: function () { |
|
this.item.doHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.item.unHighLight.apply(this.item, arguments); |
|
}, |
|
|
|
getId: function () { |
|
return this.options.id; |
|
}, |
|
|
|
getPId: function () { |
|
return this.options.pId; |
|
}, |
|
|
|
doClick: function () { |
|
BI.MultiLayerSingleTreeMidTreeLeafItem.superclass.doClick.apply(this, arguments); |
|
this.item.setSelected(this.isSelected()); |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.MultiLayerSingleTreeMidTreeLeafItem.superclass.setSelected.apply(this, arguments); |
|
this.item.setSelected(v); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multilayer_single_tree_mid_tree_leaf_item", BI.MultiLayerSingleTreeMidTreeLeafItem);/** |
|
* |
|
* @class BI.MultiSelectCheckPane |
|
* @extends BI.Widget |
|
*/ |
|
BI.MultiSelectCheckPane = BI.inherit(BI.Widget, { |
|
|
|
constants: { |
|
height: 12, |
|
lgap: 10, |
|
tgap: 10, |
|
bgap: 5 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectCheckPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-check-pane bi-background", |
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
onClickContinueSelect: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectCheckPane.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
|
|
this.storeValue = opts.value || {}; |
|
this.display = BI.createWidget({ |
|
type: "bi.display_selected_list", |
|
items: opts.items, |
|
itemsCreator: function (op, callback) { |
|
op = BI.extend(op || {}, { |
|
selectedValues: self.storeValue.value |
|
}); |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
callback({ |
|
items: BI.map(self.storeValue.value, function (i, v) { |
|
var txt = opts.valueFormatter(v) || v; |
|
return { |
|
text: txt, |
|
value: v, |
|
title: txt |
|
}; |
|
}) |
|
}); |
|
return; |
|
} |
|
opts.itemsCreator(op, callback); |
|
} |
|
}); |
|
|
|
this.continueSelect = BI.createWidget({ |
|
type: "bi.text_button", |
|
text: BI.i18nText("BI-Continue_Select"), |
|
cls: "multi-select-check-selected bi-high-light" |
|
}); |
|
|
|
this.continueSelect.on(BI.TextButton.EVENT_CHANGE, function () { |
|
opts.onClickContinueSelect(); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
height: this.constants.height, |
|
el: { |
|
type: "bi.vertical_adapt", |
|
cls: "multi-select-continue-select", |
|
items: [ |
|
{ |
|
el: { |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Selected_Data") |
|
}, |
|
lgap: this.constants.lgap |
|
}, |
|
{ |
|
el: this.continueSelect, |
|
lgap: this.constants.lgap |
|
}] |
|
}, |
|
tgap: this.constants.tgap |
|
}, { |
|
height: "fill", |
|
el: this.display, |
|
tgap: this.constants.bgap |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
}, |
|
|
|
empty: function () { |
|
this.display.empty(); |
|
}, |
|
|
|
populate: function () { |
|
this.display.populate.apply(this.display, arguments); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.multi_select_check_pane", BI.MultiSelectCheckPane);/** |
|
* |
|
* |
|
* 查看已选弹出层的展示面板 |
|
* @class BI.DisplaySelectedList |
|
* @extends BI.Widget |
|
*/ |
|
BI.DisplaySelectedList = BI.inherit(BI.Pane, { |
|
|
|
constants: { |
|
height: 24, |
|
lgap: 10 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.DisplaySelectedList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-display-list", |
|
itemsCreator: BI.emptyFn, |
|
items: [] |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.DisplaySelectedList.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
|
|
this.hasNext = false; |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.list_pane", |
|
element: this, |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
items: this._createItems(opts.items), |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
layouts: [{ |
|
type: "bi.vertical", |
|
lgap: 10 |
|
}] |
|
}, |
|
itemsCreator: function (options, callback) { |
|
|
|
opts.itemsCreator(options, function (ob) { |
|
self.hasNext = !!ob.hasNext; |
|
callback(self._createItems(ob.items)); |
|
}); |
|
}, |
|
hasNext: function () { |
|
return self.hasNext; |
|
} |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: "bi.icon_text_item", |
|
cls: "cursor-default check-font icon-size-12 display-list-item bi-tips", |
|
once: true, |
|
invalid: true, |
|
selected: true, |
|
height: this.constants.height, |
|
logic: { |
|
dynamic: true |
|
} |
|
}); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
if (arguments.length === 0) { |
|
this.button_group.populate(); |
|
} else { |
|
this.button_group.populate(this._createItems(items)); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.display_selected_list", BI.DisplaySelectedList);/** |
|
* |
|
* @class BI.MultiSelectCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiSelectCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-combo", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
self.numberCounter.setButtonChecked(self.storeValue); |
|
}; |
|
this.storeValue = o.value || {}; |
|
|
|
this._assertValue(this.storeValue); |
|
|
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_trigger", |
|
allowEdit: o.allowEdit, |
|
height: o.height, |
|
text: o.text, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: this.storeValue |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { |
|
self._setStartValue(""); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { |
|
self._setStartValue(""); |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_STOP); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_PAUSE, function () { |
|
if (this.getSearcher().hasMatched()) { |
|
var keyword = this.getSearcher().getKeyword(); |
|
self._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
self.combo.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.populate(); |
|
self._setStartValue(""); |
|
}); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_CLICK_ITEM); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { |
|
// counter的值随点击项的改变而改变, 点击counter的时候不需要setValue(counter会请求刷新计数) |
|
// 只需要更新查看面板的selectedValue用以请求已选数据 |
|
self.numberCounter.updateSelectedValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: !o.allowEdit, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.multi_select_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
}); |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self._defaultState(); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: o.value, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self.populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self._stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: this.storeValue |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.updateSelectedValue(self.storeValue); |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height, |
|
}] |
|
}); |
|
}, |
|
|
|
_itemsCreator4Trigger: function(op, callback) { |
|
var self = this, o = this.options; |
|
o.itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(BI.deepClone(self.getValue())); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
|
|
_stopEditing: function() { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectCombo.REQ_GET_ALL_DATA, |
|
keywords: [this.trigger.getKey()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
self.storeValue.assist && self.storeValue.assist.push(selectedMap[items[i]]); |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
BI.remove(self.storeValue.assist, item); |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
self._adjust(callback); |
|
}); |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
adjust(); |
|
callback(); |
|
function adjust () { |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.MultiSelectCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
BI.remove(self.storeValue.assist, v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.combo.setValue(this.storeValue); |
|
this.numberCounter.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
this.numberCounter.populateSwitcher.apply(this.numberCounter, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectCombo, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiSelectCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.MultiSelectCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_select_combo", BI.MultiSelectCombo);/** |
|
* |
|
* @class BI.MultiSelectNoBarCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiSelectNoBarCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectNoBarCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-combo-no-bar", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectNoBarCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
self.numberCounter.setButtonChecked(self.storeValue); |
|
}; |
|
this.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: o.value || [] |
|
}; |
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_trigger", |
|
height: o.height, |
|
text: o.text, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { |
|
self._setStartValue(""); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { |
|
self._setStartValue(""); |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_STOP); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_CLICK_ITEM); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { |
|
// counter的值随点击项的改变而改变, 点击counter的时候不需要setValue(counter会请求刷新计数) |
|
// 只需要更新查看面板的selectedValue用以请求已选数据 |
|
self.numberCounter.updateSelectedValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: false, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.multi_select_no_bar_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
}); |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self._defaultState(); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value |
|
}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && |
|
self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self.populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self._stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.updateSelectedValue(self.storeValue); |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height |
|
}] |
|
}); |
|
}, |
|
|
|
_itemsCreator4Trigger: function (op, callback) { |
|
var self = this, o = this.options; |
|
o.itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(BI.deepClone(self.storeValue)); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
|
|
_stopEditing: function () { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectNoBarCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest(items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectNoBarCombo.REQ_GET_ALL_DATA, |
|
keywords: [this.trigger.getKey()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
self.storeValue.assist && self.storeValue.assist.push(selectedMap[items[i]]); |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
BI.remove(self.storeValue.assist, item); |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
self._adjust(callback); |
|
}); |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
adjust(); |
|
callback(); |
|
|
|
function adjust() { |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.MultiSelectNoBarCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
BI.remove(self.storeValue.assist, v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: v || [] |
|
}; |
|
this.combo.setValue(this.storeValue); |
|
this.numberCounter.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue.value); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
this.numberCounter.populateSwitcher.apply(this.numberCounter, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectNoBarCombo, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectNoBarCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiSelectNoBarCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectNoBarCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectNoBarCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectNoBarCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.MultiSelectNoBarCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_select_no_bar_combo", BI.MultiSelectNoBarCombo);/** |
|
* |
|
* @class BI.MultiSelectInsertCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiSelectInsertCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectInsertCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-insert-combo", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectInsertCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
self.numberCounter.setButtonChecked(self.storeValue); |
|
}; |
|
this.storeValue = o.value || {}; |
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_insert_trigger", |
|
allowEdit: o.allowEdit, |
|
height: o.height, |
|
text: o.text, |
|
watermark: o.watermark, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: o.value |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_START, function () { |
|
self._setStartValue(""); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_STOP, function () { |
|
self._setStartValue(""); |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_STOP); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_PAUSE, function () { |
|
if (this.getSearcher().hasMatched()) { |
|
self._addItem(assertShowValue); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_ADD_ITEM, function () { |
|
if (!this.getSearcher().hasMatched()) { |
|
self._addItem(assertShowValue); |
|
self._stopEditing(); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_CHANGE, function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_CLICK_ITEM); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { |
|
// counter的值随点击项的改变而改变, 点击counter的时候不需要setValue(counter会请求刷新计数) |
|
// 只需要更新查看面板的selectedValue用以请求已选数据 |
|
self.numberCounter.updateSelectedValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: !o.allowEdit, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
container: o.container, |
|
popup: { |
|
type: "bi.multi_select_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
}); |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self._defaultState(); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: o.value, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && |
|
self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self.populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self._stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: o.value |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.updateSelectedValue(self.storeValue); |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height, |
|
}] |
|
}); |
|
}, |
|
|
|
_itemsCreator4Trigger: function(op, callback) { |
|
var self = this, o = this.options; |
|
o.itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(BI.deepClone(self.getValue())); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
|
|
_addItem: function (assertShowValue) { |
|
var self = this; |
|
var keyword = this.trigger.getSearcher().getKeyword(); |
|
this._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
// 如果在不选的状态下直接把该值添加进来 |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
BI.pushDistinct(self.storeValue.value, keyword); |
|
} |
|
self.combo.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.populate(); |
|
self._setStartValue(""); |
|
}); |
|
}, |
|
|
|
_stopEditing: function() { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertCombo.REQ_GET_ALL_DATA, |
|
keywords: [this.trigger.getKey()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
self.storeValue.assist && self.storeValue.assist.push(selectedMap[items[i]]); |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
BI.remove(self.storeValue.assist, item); |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
self._adjust(callback); |
|
}); |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
adjust(); |
|
callback(); |
|
function adjust () { |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.MultiSelectInsertCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
// value更新的时候assist也需要更新 |
|
BI.remove(self.storeValue.assist, v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.combo.setValue(this.storeValue); |
|
this.numberCounter.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
this.numberCounter.populateSwitcher.apply(this.numberCounter, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectInsertCombo, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectInsertCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectInsertCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiSelectInsertCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectInsertCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectInsertCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.MultiSelectInsertCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_select_insert_combo", BI.MultiSelectInsertCombo);/** |
|
* |
|
* @class BI.MultiSelectInsertCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiSelectInsertNoBarCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectInsertNoBarCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-insert-combo-no-bar", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectInsertNoBarCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
self.numberCounter.setButtonChecked(self.storeValue); |
|
}; |
|
this.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: o.value || [] |
|
}; |
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_insert_trigger", |
|
height: o.height, |
|
text: o.text, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_START, function () { |
|
self._setStartValue(""); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_STOP, function () { |
|
self._setStartValue(""); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_PAUSE, function () { |
|
if (this.getSearcher().hasMatched()) { |
|
self._addItem(assertShowValue); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_ADD_ITEM, function () { |
|
if (!this.getSearcher().hasMatched()) { |
|
self._addItem(assertShowValue); |
|
self._stopEditing(); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_CHANGE, function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { |
|
// counter的值随点击项的改变而改变, 点击counter的时候不需要setValue(counter会请求刷新计数) |
|
// 只需要更新查看面板的selectedValue用以请求已选数据 |
|
self.numberCounter.updateSelectedValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectInsertTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: false, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.multi_select_no_bar_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self._defaultState(); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value |
|
}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && |
|
self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self.populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self._stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
self.fireEvent(BI.MultiSelectInsertNoBarCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: BI.bind(this._itemsCreator4Trigger, this), |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.updateSelectedValue(self.storeValue); |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height |
|
}] |
|
}); |
|
}, |
|
|
|
_itemsCreator4Trigger: function(op, callback) { |
|
var self = this, o = this.options; |
|
o.itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(BI.deepClone(self.storeValue)); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
|
|
_addItem: function (assertShowValue) { |
|
var self = this; |
|
var keyword = this.trigger.getSearcher().getKeyword(); |
|
this._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
// 如果在不选的状态下直接把该值添加进来 |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
BI.pushDistinct(self.storeValue.value, keyword); |
|
} |
|
self.combo.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.populate(); |
|
self._setStartValue(""); |
|
}); |
|
}, |
|
|
|
_stopEditing: function() { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertNoBarCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertNoBarCombo.REQ_GET_ALL_DATA, |
|
keywords: [this.trigger.getKey()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
self.storeValue.assist && self.storeValue.assist.push(selectedMap[items[i]]); |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
BI.remove(self.storeValue.assist, item); |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
self._adjust(callback); |
|
}); |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
adjust(); |
|
callback(); |
|
function adjust () { |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.MultiSelectInsertNoBarCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
BI.remove(self.storeValue.assist, v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: v || [] |
|
}; |
|
this.combo.setValue(this.storeValue); |
|
this.numberCounter.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue.value); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
this.numberCounter.populateSwitcher.apply(this.numberCounter, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectInsertNoBarCombo, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectInsertNoBarCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_select_insert_no_bar_combo", BI.MultiSelectInsertNoBarCombo);/** |
|
* |
|
* 复选下拉框 |
|
* @class BI.MultiSelectInsertTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
|
|
BI.MultiSelectInsertTrigger = BI.inherit(BI.Trigger, { |
|
|
|
constants: { |
|
height: 14, |
|
rgap: 4, |
|
lgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectInsertTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-trigger bi-border bi-border-radius", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
searcher: {}, |
|
switcher: {}, |
|
|
|
adapter: null, |
|
masker: {}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectInsertTrigger.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
if (o.height) { |
|
this.setHeight(o.height - 2); |
|
} |
|
|
|
this.searcher = BI.createWidget(o.searcher, { |
|
type: "bi.multi_select_insert_searcher", |
|
height: o.height, |
|
text: o.text, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
watermark: o.watermark, |
|
popup: {}, |
|
adapter: o.adapter, |
|
masker: o.masker, |
|
value: o.value |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_START, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_START); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_ADD_ITEM, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_ADD_ITEM); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_SEARCHING, arguments); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_BLUR); |
|
}); |
|
this.searcher.on(BI.MultiSelectInsertSearcher.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiSelectInsertTrigger.EVENT_FOCUS); |
|
}); |
|
|
|
this.wrapNumberCounter = BI.createWidget({ |
|
type: "bi.layout" |
|
}); |
|
|
|
this.wrapper = BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [ |
|
{ |
|
el: this.searcher, |
|
width: "fill" |
|
}, { |
|
el: this.wrapNumberCounter, |
|
width: 0 |
|
}, { |
|
el: BI.createWidget(), |
|
width: 24 |
|
}] |
|
}); |
|
|
|
!o.allowEdit && BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.text", |
|
title: function () { |
|
return self.searcher.getState(); |
|
} |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
/** |
|
* 重新调整numberCounter的空白占位符 |
|
*/ |
|
refreshPlaceHolderWidth: function(width) { |
|
this.wrapper.attr("items")[1].width = width; |
|
this.wrapper.resize(); |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.searcher.getKey(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
|
|
BI.MultiSelectInsertTrigger.EVENT_TRIGGER_CLICK = "EVENT_TRIGGER_CLICK"; |
|
BI.MultiSelectInsertTrigger.EVENT_COUNTER_CLICK = "EVENT_COUNTER_CLICK"; |
|
BI.MultiSelectInsertTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectInsertTrigger.EVENT_START = "EVENT_START"; |
|
BI.MultiSelectInsertTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectInsertTrigger.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.MultiSelectInsertTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectInsertTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW = "EVENT_BEFORE_COUNTER_POPUPVIEW"; |
|
BI.MultiSelectInsertTrigger.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
BI.MultiSelectInsertTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectInsertTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
|
|
BI.shortcut("bi.multi_select_insert_trigger", BI.MultiSelectInsertTrigger);/** |
|
* 多选加载数据面板 |
|
* Created by guy on 15/11/2. |
|
* @class BI.MultiSelectLoader |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectLoader = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-loader", |
|
logic: { |
|
dynamic: true |
|
}, |
|
el: { |
|
height: 400 |
|
}, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectLoader.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
var hasNext = false; |
|
|
|
this.storeValue = opts.value || {}; |
|
this._assertValue(this.storeValue); |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.select_list", |
|
logic: opts.logic, |
|
toolbar: { |
|
type: "bi.multi_select_bar", |
|
cls: "bi-list-item-active", |
|
iconWrapperWidth: 36 |
|
}, |
|
el: BI.extend({ |
|
onLoaded: opts.onLoaded, |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
el: { |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
} |
|
}, opts.el), |
|
itemsCreator: function (op, callback) { |
|
var startValue = self._startValue; |
|
self.storeValue && (op = BI.extend(op || {}, { |
|
selectedValues: BI.isKey(startValue) && self.storeValue.type === BI.Selection.Multi |
|
? self.storeValue.value.concat(startValue) : self.storeValue.value |
|
})); |
|
opts.itemsCreator(op, function (ob) { |
|
hasNext = ob.hasNext; |
|
var firstItems = []; |
|
if (op.times === 1 && self.storeValue) { |
|
var json = BI.map(self.storeValue.value, function (i, v) { |
|
var txt = opts.valueFormatter(v) || v; |
|
return { |
|
text: txt, |
|
value: v, |
|
title: txt, |
|
selected: self.storeValue.type === BI.Selection.Multi |
|
}; |
|
}); |
|
if (BI.isKey(self._startValue) && !BI.contains(self.storeValue.value, self._startValue)) { |
|
var txt = opts.valueFormatter(startValue) || startValue; |
|
json.unshift({ |
|
text: txt, |
|
value: startValue, |
|
title: txt, |
|
selected: true |
|
}); |
|
} |
|
firstItems = self._createItems(json); |
|
} |
|
callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || ""); |
|
if (op.times === 1 && self.storeValue) { |
|
BI.isKey(startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, startValue) : BI.pushDistinct(self.storeValue.value, startValue)); |
|
self.setValue(self.storeValue); |
|
} |
|
(op.times === 1) && self._scrollToTop(); |
|
}); |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
}, |
|
value: this.storeValue |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Top), BI.extend({ |
|
scrolly: true, |
|
vgap: 5 |
|
}, opts.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Top, this.button_group) |
|
})))); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button_group.on(BI.SelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectLoader.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: "bi.multi_select_item", |
|
logic: this.options.logic, |
|
cls: "bi-list-item-active", |
|
height: 24, |
|
selected: this.isAllSelected(), |
|
iconWrapperWidth: 36 |
|
}); |
|
}, |
|
|
|
_scrollToTop: function () { |
|
var self = this; |
|
BI.delay(function () { |
|
self.button_group.element.scrollTop(0); |
|
}, 30); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.button_group.isAllSelected(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this._startValue = v; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.button_group.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
arguments[0] = this._createItems(items); |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.button_group.resetHeight(h - 10); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.button_group.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.MultiSelectLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_loader", BI.MultiSelectLoader);/** |
|
* 多选加载数据面板 |
|
* Created by guy on 15/11/2. |
|
* @class BI.MultiSelectNoBarLoader |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectNoBarLoader = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectNoBarLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-loader", |
|
logic: { |
|
dynamic: true |
|
}, |
|
el: { |
|
height: 400 |
|
}, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectNoBarLoader.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
var hasNext = false; |
|
|
|
this.storeValue = opts.value || {}; |
|
this._assertValue(this.storeValue); |
|
|
|
this.button_group = BI.createWidget(BI.extend({ |
|
type: "bi.list_pane", |
|
onLoaded: opts.onLoaded, |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
el: { |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
}, |
|
itemsCreator: function (op, callback) { |
|
var startValue = self._startValue; |
|
self.storeValue && (op = BI.extend(op || {}, { |
|
selectedValues: BI.isKey(startValue) && self.storeValue.type === BI.Selection.Multi |
|
? self.storeValue.value.concat(startValue) : self.storeValue.value |
|
})); |
|
opts.itemsCreator(op, function (ob) { |
|
hasNext = ob.hasNext; |
|
var firstItems = []; |
|
if (op.times === 1 && self.storeValue) { |
|
var json = BI.map(self.storeValue.value, function (i, v) { |
|
var txt = opts.valueFormatter(v) || v; |
|
return { |
|
text: txt, |
|
value: v, |
|
title: txt, |
|
selected: self.storeValue.type === BI.Selection.Multi |
|
}; |
|
}); |
|
if (BI.isKey(self._startValue) && !BI.contains(self.storeValue.value, self._startValue)) { |
|
var txt = opts.valueFormatter(startValue) || startValue; |
|
json.unshift({ |
|
text: txt, |
|
value: startValue, |
|
title: txt, |
|
selected: true |
|
}); |
|
} |
|
firstItems = self._createItems(json); |
|
} |
|
callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || ""); |
|
if (op.times === 1 && self.storeValue) { |
|
BI.isKey(startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, startValue) : BI.pushDistinct(self.storeValue.value, startValue)); |
|
self.setValue(self.storeValue); |
|
} |
|
(op.times === 1) && self._scrollToTop(); |
|
}); |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
}, |
|
value: this.storeValue |
|
}, opts.el)); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
items: [this.button_group], |
|
vgap: 5 |
|
}); |
|
|
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button_group.on(BI.SelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectNoBarLoader.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: "bi.multi_select_item", |
|
cls: "bi-list-item-active", |
|
logic: this.options.logic, |
|
height: 24, |
|
iconWrapperWidth: 36 |
|
}); |
|
}, |
|
|
|
_scrollToTop: function () { |
|
var self = this; |
|
BI.delay(function () { |
|
self.button_group.element.scrollTop(0); |
|
}, 30); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this._startValue = v; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.button_group.setValue(this.storeValue.value); |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: BI.Selection.Multi, |
|
value: this.button_group.getValue() |
|
}; |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
arguments[0] = this._createItems(items); |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.button_group.element.css({"max-height": h + "px"}); |
|
}, |
|
|
|
resetWidth: function () { |
|
|
|
} |
|
}); |
|
|
|
BI.MultiSelectNoBarLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_no_bar_loader", BI.MultiSelectNoBarLoader);/** |
|
* 带加载的多选下拉面板 |
|
* @class BI.MultiSelectPopupView |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectPopupView = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectPopupView.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-popup-view", |
|
maxWidth: "auto", |
|
minWidth: 135, |
|
maxHeight: 400, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectPopupView.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options; |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.multi_select_loader", |
|
itemsCreator: opts.itemsCreator, |
|
valueFormatter: opts.valueFormatter, |
|
onLoaded: opts.onLoaded, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView = BI.createWidget({ |
|
type: "bi.multi_popup_view", |
|
stopPropagation: false, |
|
maxWidth: opts.maxWidth, |
|
minWidth: opts.minWidth, |
|
maxHeight: opts.maxHeight, |
|
element: this, |
|
buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], |
|
el: this.loader, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView.on(BI.MultiPopupView.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectPopupView.EVENT_CHANGE); |
|
}); |
|
this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { |
|
switch (index) { |
|
case 0: |
|
self.fireEvent(BI.MultiSelectPopupView.EVENT_CLICK_CLEAR); |
|
break; |
|
case 1: |
|
self.fireEvent(BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM); |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.loader.isAllSelected(); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this.loader.setStartValue(v); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popupView.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popupView.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.popupView.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.popupView.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.MultiSelectPopupView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; |
|
BI.MultiSelectPopupView.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; |
|
|
|
|
|
BI.shortcut("bi.multi_select_popup_view", BI.MultiSelectPopupView);/** |
|
* 带加载的多选下拉面板 |
|
* @class BI.MultiSelectPopupView |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectNoBarPopupView = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectNoBarPopupView.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-popup-view", |
|
maxWidth: "auto", |
|
minWidth: 135, |
|
maxHeight: 400, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectNoBarPopupView.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options; |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.multi_select_no_bar_loader", |
|
itemsCreator: opts.itemsCreator, |
|
valueFormatter: opts.valueFormatter, |
|
onLoaded: opts.onLoaded, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView = BI.createWidget({ |
|
type: "bi.multi_popup_view", |
|
stopPropagation: false, |
|
maxWidth: opts.maxWidth, |
|
minWidth: opts.minWidth, |
|
maxHeight: opts.maxHeight, |
|
element: this, |
|
buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], |
|
el: this.loader, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView.on(BI.MultiPopupView.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectNoBarPopupView.EVENT_CHANGE); |
|
}); |
|
this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { |
|
switch (index) { |
|
case 0: |
|
self.fireEvent(BI.MultiSelectNoBarPopupView.EVENT_CLICK_CLEAR); |
|
break; |
|
case 1: |
|
self.fireEvent(BI.MultiSelectNoBarPopupView.EVENT_CLICK_CONFIRM); |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this.loader.setStartValue(v); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popupView.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popupView.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.popupView.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.popupView.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.MultiSelectNoBarPopupView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectNoBarPopupView.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; |
|
BI.MultiSelectNoBarPopupView.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; |
|
|
|
|
|
BI.shortcut("bi.multi_select_no_bar_popup_view", BI.MultiSelectNoBarPopupView);/** |
|
* |
|
* 复选下拉框 |
|
* @class BI.MultiSelectTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
|
|
BI.MultiSelectTrigger = BI.inherit(BI.Trigger, { |
|
|
|
constants: { |
|
height: 14, |
|
rgap: 4, |
|
lgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-trigger bi-border bi-border-radius", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
searcher: {}, |
|
switcher: {}, |
|
|
|
adapter: null, |
|
masker: {}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectTrigger.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
if (o.height) { |
|
this.setHeight(o.height - 2); |
|
} |
|
|
|
this.searcher = BI.createWidget(o.searcher, { |
|
type: "bi.multi_select_searcher", |
|
height: o.height, |
|
text: o.text, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
watermark: o.watermark, |
|
popup: {}, |
|
adapter: o.adapter, |
|
masker: o.masker, |
|
value: o.value |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_START, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_START); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_SEARCHING, arguments); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_BLUR); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiSelectTrigger.EVENT_FOCUS); |
|
}); |
|
|
|
this.wrapNumberCounter = BI.createWidget({ |
|
type: "bi.layout" |
|
}); |
|
|
|
this.wrapper = BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [ |
|
{ |
|
el: this.searcher, |
|
width: "fill" |
|
}, { |
|
el: this.wrapNumberCounter, |
|
width: 0 |
|
}, { |
|
el: BI.createWidget(), |
|
width: 24 |
|
}] |
|
}); |
|
|
|
!o.allowEdit && BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.text", |
|
title: function () { |
|
return self.searcher.getState(); |
|
} |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
/** |
|
* 重新调整numberCounter的空白占位符 |
|
*/ |
|
refreshPlaceHolderWidth: function(width) { |
|
this.wrapper.attr("items")[1].width = width; |
|
this.wrapper.resize(); |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.searcher.getKey(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
|
|
BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK = "EVENT_TRIGGER_CLICK"; |
|
BI.MultiSelectTrigger.EVENT_COUNTER_CLICK = "EVENT_COUNTER_CLICK"; |
|
BI.MultiSelectTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectTrigger.EVENT_START = "EVENT_START"; |
|
BI.MultiSelectTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectTrigger.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.MultiSelectTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW = "EVENT_BEFORE_COUNTER_POPUPVIEW"; |
|
BI.MultiSelectTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiSelectTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
|
|
BI.shortcut("bi.multi_select_trigger", BI.MultiSelectTrigger);/** |
|
* |
|
* 在搜索框中输入文本弹出的面板 |
|
* @class BI.MultiSelectSearchInsertPane |
|
* @extends Widget |
|
*/ |
|
|
|
BI.MultiSelectSearchInsertPane = BI.inherit(BI.Widget, { |
|
|
|
constants: { |
|
height: 24, |
|
lgap: 10, |
|
tgap: 5 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectSearchInsertPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-search-pane bi-card", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
keywordGetter: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectSearchInsertPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.tooltipClick = BI.createWidget({ |
|
type: "bi.label", |
|
invisible: true, |
|
text: BI.i18nText("BI-Click_Blank_To_Select"), |
|
cls: "multi-select-toolbar", |
|
height: this.constants.height |
|
}); |
|
|
|
this.addNotMatchTip = BI.createWidget({ |
|
type: "bi.text_button", |
|
invisible: true, |
|
text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), |
|
height: this.constants.height, |
|
cls: "bi-high-light", |
|
hgap: 5, |
|
handler: function () { |
|
self.fireEvent(BI.MultiSelectSearchInsertPane.EVENT_ADD_ITEM, o.keywordGetter()); |
|
} |
|
}); |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.multi_select_search_loader", |
|
keywordGetter: o.keywordGetter, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator.apply(self, [op, function (res) { |
|
callback(res); |
|
self.setKeyword(o.keywordGetter()); |
|
}]); |
|
}, |
|
value: o.value |
|
}); |
|
this.loader.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.resizer = BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
type: "bi.vertical", |
|
items: [this.tooltipClick, this.addNotMatchTip], |
|
height: this.constants.height |
|
}, { |
|
el: this.loader |
|
}] |
|
}); |
|
}, |
|
|
|
setKeyword: function (keyword) { |
|
var btn; |
|
var isMatchTipVisible = this.loader.getAllButtons().length > 0 && (btn = this.loader.getAllButtons()[0]) && (keyword === btn.getValue()); |
|
this.tooltipClick.setVisible(isMatchTipVisible); |
|
this.addNotMatchTip.setVisible(!isMatchTipVisible); |
|
!isMatchTipVisible && this.addNotMatchTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.loader.isAllSelected(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.tooltipClick.isVisible(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.loader.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.loader.getValue(); |
|
}, |
|
|
|
empty: function () { |
|
this.loader.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.loader.populate.apply(this.loader, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiSelectSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
|
|
BI.shortcut("bi.multi_select_search_insert_pane", BI.MultiSelectSearchInsertPane);/** |
|
* 多选加载数据搜索loader面板 |
|
* Created by guy on 15/11/4. |
|
* @class BI.MultiSelectSearchLoader |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectSearchLoader = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectSearchLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-search-loader", |
|
itemsCreator: BI.emptyFn, |
|
keywordGetter: BI.emptyFn, |
|
valueFormatter: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectSearchLoader.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
var hasNext = false; |
|
this.storeValue = BI.deepClone(opts.value); |
|
this.button_group = BI.createWidget({ |
|
type: "bi.select_list", |
|
toolbar: { |
|
type: "bi.multi_select_bar", |
|
cls: "bi-list-item-active", |
|
iconWrapperWidth: 36 |
|
}, |
|
element: this, |
|
logic: { |
|
dynamic: false |
|
}, |
|
value: opts.value, |
|
el: { |
|
tipText: BI.i18nText("BI-No_Select"), |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
el: { |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
} |
|
}, |
|
itemsCreator: function (op, callback) { |
|
self.storeValue && (op = BI.extend(op || {}, { |
|
selectedValues: self.storeValue.value |
|
})); |
|
opts.itemsCreator(op, function (ob) { |
|
var keyword = ob.keyword = opts.keywordGetter(); |
|
hasNext = ob.hasNext; |
|
var firstItems = []; |
|
if (op.times === 1 && self.storeValue) { |
|
var json = self._filterValues(self.storeValue); |
|
firstItems = self._createItems(json); |
|
} |
|
callback(firstItems.concat(self._createItems(ob.items)), keyword); |
|
if (op.times === 1 && self.storeValue) { |
|
self.setValue(self.storeValue); |
|
} |
|
}); |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
} |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button_group.on(BI.SelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectSearchLoader.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: "bi.multi_select_item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
height: 24, |
|
selected: this.isAllSelected(), |
|
cls: "bi-list-item-active", |
|
iconWrapperWidth: 36 |
|
}); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.button_group.isAllSelected(); |
|
}, |
|
|
|
_filterValues: function (src) { |
|
var o = this.options; |
|
var keyword = o.keywordGetter(); |
|
var values = BI.deepClone(src.value) || []; |
|
var newValues = BI.map(values, function (i, v) { |
|
return { |
|
text: o.valueFormatter(v) || v, |
|
value: v |
|
}; |
|
}); |
|
if (BI.isKey(keyword)) { |
|
var search = BI.Func.getSearchResult(newValues, keyword); |
|
values = search.match.concat(search.find); |
|
} |
|
return BI.map(values, function (i, v) { |
|
return { |
|
text: v.text, |
|
title: v.text, |
|
value: v.value, |
|
selected: src.type === BI.Selection.All |
|
}; |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
// 暂存的值一定是新的值,不然v改掉后,storeValue也跟着改了 |
|
this.storeValue = BI.deepClone(v); |
|
this.button_group.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.button_group.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.button_group.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.MultiSelectSearchLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_search_loader", BI.MultiSelectSearchLoader);/** |
|
* |
|
* 在搜索框中输入文本弹出的面板 |
|
* @class BI.MultiSelectSearchPane |
|
* @extends Widget |
|
*/ |
|
|
|
BI.MultiSelectSearchPane = BI.inherit(BI.Widget, { |
|
|
|
constants: { |
|
height: 24, |
|
lgap: 10, |
|
tgap: 5 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectSearchPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-search-pane bi-card", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
keywordGetter: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectSearchPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.tooltipClick = BI.createWidget({ |
|
type: "bi.label", |
|
invisible: true, |
|
text: BI.i18nText("BI-Click_Blank_To_Select"), |
|
cls: "multi-select-toolbar", |
|
height: this.constants.height |
|
}); |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.multi_select_search_loader", |
|
keywordGetter: o.keywordGetter, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator.apply(self, [op, function (res) { |
|
callback(res); |
|
self.setKeyword(o.keywordGetter()); |
|
}]); |
|
}, |
|
value: o.value |
|
}); |
|
this.loader.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.resizer = BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.tooltipClick, |
|
height: 0 |
|
}, { |
|
el: this.loader |
|
}] |
|
}); |
|
this.tooltipClick.setVisible(false); |
|
}, |
|
|
|
setKeyword: function (keyword) { |
|
var btn; |
|
var isVisible = this.loader.getAllButtons().length > 0 && (btn = this.loader.getAllButtons()[0]) && (keyword === btn.getValue()); |
|
if (isVisible !== this.tooltipClick.isVisible()) { |
|
this.tooltipClick.setVisible(isVisible); |
|
this.resizer.attr("items")[0].height = (isVisible ? this.constants.height : 0); |
|
this.resizer.resize(); |
|
} |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.loader.isAllSelected(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.tooltipClick.isVisible(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.loader.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.loader.getValue(); |
|
}, |
|
|
|
empty: function () { |
|
this.loader.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.loader.populate.apply(this.loader, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiSelectSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.multi_select_search_pane", BI.MultiSelectSearchPane);/** |
|
* 查看已选按钮 |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiSelectCheckSelectedButton |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiSelectCheckSelectedButton = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectCheckSelectedButton.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-check-selected-button", |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectCheckSelectedButton.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.text_button", |
|
element: this, |
|
hgap: 4, |
|
text: "0", |
|
textAlign: "center", |
|
textHeight: 16, |
|
cls: "bi-high-light-background count-tip" |
|
}); |
|
this.numberCounter.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.numberCounter.on(BI.TextButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectCheckSelectedButton.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.numberCounter.element.hover(function () { |
|
self.numberCounter.setTag(self.numberCounter.getText()); |
|
self.numberCounter.setText(BI.i18nText("BI-Check_Selected")); |
|
}, function () { |
|
self.numberCounter.setText(self.numberCounter.getTag()); |
|
}); |
|
this.setVisible(false); |
|
if(BI.isNotNull(o.value)){ |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_populate: function (ob) { |
|
var self = this, o = this.options; |
|
if (ob.type === BI.Selection.All) { |
|
o.itemsCreator({ |
|
type: BI.MultiSelectCombo.REQ_GET_DATA_LENGTH |
|
}, function (res) { |
|
var length = res.count - ob.value.length; |
|
BI.nextTick(function () { |
|
self.numberCounter.setText(length); |
|
self.setVisible(length > 0); |
|
}); |
|
}); |
|
return; |
|
} |
|
BI.nextTick(function () { |
|
self.numberCounter.setText(ob.value.length); |
|
self.setVisible(ob.value.length > 0); |
|
}); |
|
}, |
|
|
|
_assertValue: function (ob) { |
|
ob || (ob = {}); |
|
ob.type || (ob.type = BI.Selection.Multi); |
|
ob.value || (ob.value = []); |
|
return ob; |
|
}, |
|
|
|
setValue: function (ob) { |
|
ob = this._assertValue(ob); |
|
this.options.value = ob; |
|
this._populate(ob); |
|
}, |
|
|
|
populate: function () { |
|
this._populate(this._assertValue(this.options.value)); |
|
}, |
|
|
|
getValue: function () { |
|
|
|
} |
|
}); |
|
|
|
BI.MultiSelectCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_check_selected_button", BI.MultiSelectCheckSelectedButton);/** |
|
* 多选输入框 |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiSelectEditor |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectEditor = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectEditor.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-editor", |
|
el: {}, |
|
watermark: BI.i18nText("BI-Basic_Search") |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.state_editor", |
|
element: this, |
|
height: o.height, |
|
watermark: o.watermark, |
|
allowBlank: true, |
|
value: o.value, |
|
defaultText: o.text, |
|
text: o.text, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle, |
|
}); |
|
|
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.editor.on(BI.StateEditor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.MultiSelectEditor.EVENT_PAUSE); |
|
}); |
|
this.editor.on(BI.StateEditor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiSelectEditor.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.StateEditor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiSelectEditor.EVENT_BLUR); |
|
}); |
|
}, |
|
|
|
focus: function () { |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
}, |
|
|
|
setState: function (state) { |
|
this.editor.setState(state); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setValue(v); |
|
}, |
|
|
|
setTipType: function (v) { |
|
this.editor.setTipType(v); |
|
}, |
|
|
|
getValue: function () { |
|
var v = this.editor.getState(); |
|
if (BI.isArray(v) && v.length > 0) { |
|
return v[v.length - 1]; |
|
} |
|
return ""; |
|
|
|
}, |
|
|
|
getState: function () { |
|
return this.editor.getText(); |
|
}, |
|
|
|
getKeywords: function () { |
|
var val = this.editor.getLastChangedValue(); |
|
var keywords = val.match(/[\S]+/g); |
|
if (BI.isEndWithBlank(val)) { |
|
return keywords.concat([" "]); |
|
} |
|
return keywords; |
|
}, |
|
|
|
populate: function (items) { |
|
|
|
} |
|
}); |
|
|
|
BI.MultiSelectEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiSelectEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.shortcut("bi.multi_select_editor", BI.MultiSelectEditor); |
|
/** |
|
* searcher |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiSelectInsertSearcher |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectInsertSearcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectInsertSearcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-searcher", |
|
itemsCreator: BI.emptyFn, |
|
el: {}, |
|
popup: {}, |
|
valueFormatter: BI.emptyFn, |
|
adapter: null, |
|
masker: {}, |
|
text: BI.i18nText("BI-Basic_Please_Select") |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectInsertSearcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.multi_select_editor", |
|
watermark: o.watermark, |
|
height: o.height, |
|
text: o.text, |
|
listeners: [{ |
|
eventName: BI.MultiSelectEditor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectEditor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_BLUR); |
|
} |
|
}] |
|
}); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
element: this, |
|
height: o.height, |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
el: this.editor, |
|
|
|
popup: BI.extend({ |
|
type: "bi.multi_select_search_insert_pane", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
var keyword = self.editor.getValue(); |
|
op.keywords = [keyword]; |
|
this.setKeyword(keyword); |
|
o.itemsCreator(op, callback); |
|
}, |
|
value: o.value, |
|
listeners: [{ |
|
eventName: BI.MultiSelectSearchInsertPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_ADD_ITEM); |
|
} |
|
}] |
|
}, o.popup), |
|
|
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_START, function () { |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_START); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { |
|
if (this.hasMatched()) { |
|
|
|
} |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_SEARCHING, function () { |
|
var keywords = this.getKeywords(); |
|
self.fireEvent(BI.MultiSelectInsertSearcher.EVENT_SEARCHING, keywords); |
|
}); |
|
if (BI.isNotNull(o.value)) { |
|
this.setState(o.value); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.searcher.adjustView(); |
|
}, |
|
|
|
isSearching: function () { |
|
return this.searcher.isSearching(); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getKeyword: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.searcher.hasMatched(); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.searcher.getView() && this.searcher.getView().hasChecked(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setState: function (ob) { |
|
var o = this.options; |
|
ob || (ob = {}); |
|
ob.value || (ob.value = []); |
|
if (ob.type === BI.Selection.All) { |
|
if (ob.value.length === 0) { |
|
this.editor.setState(BI.Selection.All); |
|
} else if (BI.size(ob.assist) <= 20) { |
|
var state = ""; |
|
BI.each(ob.assist, function (i, v) { |
|
if (i === 0) { |
|
state += "" + (o.valueFormatter(v + "") || v); |
|
} else { |
|
state += "," + (o.valueFormatter(v + "") || v); |
|
} |
|
}); |
|
this.editor.setState(state); |
|
} else { |
|
this.editor.setState(BI.Selection.Multi); |
|
} |
|
} else { |
|
if (ob.value.length === 0) { |
|
this.editor.setState(BI.Selection.None); |
|
} else if (BI.size(ob.value) <= 20) { |
|
var state = ""; |
|
BI.each(ob.value, function (i, v) { |
|
if (i === 0) { |
|
state += "" + (o.valueFormatter(v + "") || v); |
|
} else { |
|
state += "," + (o.valueFormatter(v + "") || v); |
|
} |
|
}); |
|
this.editor.setState(state); |
|
} else { |
|
this.editor.setState(BI.Selection.Multi); |
|
} |
|
} |
|
}, |
|
|
|
getState: function() { |
|
return this.editor.getState(); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.setState(ob); |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiSelectInsertSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.MultiSelectInsertSearcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectInsertSearcher.EVENT_START = "EVENT_START"; |
|
BI.MultiSelectInsertSearcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectInsertSearcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.MultiSelectInsertSearcher.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectInsertSearcher.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
BI.MultiSelectInsertSearcher.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectInsertSearcher.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.shortcut("bi.multi_select_insert_searcher", BI.MultiSelectInsertSearcher);/** |
|
* searcher |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiSelectSearcher |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectSearcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectSearcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-searcher", |
|
itemsCreator: BI.emptyFn, |
|
el: {}, |
|
popup: {}, |
|
valueFormatter: BI.emptyFn, |
|
adapter: null, |
|
masker: {}, |
|
text: BI.i18nText("BI-Basic_Please_Select") |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectSearcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.multi_select_editor", |
|
height: o.height, |
|
text: o.text, |
|
watermark: o.watermark, |
|
listeners: [{ |
|
eventName: BI.MultiSelectEditor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectEditor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_BLUR); |
|
} |
|
}] |
|
}); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
element: this, |
|
height: o.height, |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
el: this.editor, |
|
|
|
popup: BI.extend({ |
|
type: "bi.multi_select_search_pane", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
var keyword = self.editor.getValue(); |
|
op.keywords = [keyword]; |
|
this.setKeyword(keyword); |
|
o.itemsCreator(op, callback); |
|
}, |
|
value: o.value |
|
}, o.popup), |
|
|
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_START, function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_START); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { |
|
if (this.hasMatched()) { |
|
|
|
} |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_SEARCHING, function () { |
|
var keywords = this.getKeywords(); |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_SEARCHING, keywords); |
|
}); |
|
if (BI.isNotNull(o.value)) { |
|
this.setState(o.value); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.searcher.adjustView(); |
|
}, |
|
|
|
isSearching: function () { |
|
return this.searcher.isSearching(); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getKeyword: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.searcher.hasMatched(); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.searcher.getView() && this.searcher.getView().hasChecked(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setState: function (ob) { |
|
var o = this.options; |
|
ob || (ob = {}); |
|
ob.value || (ob.value = []); |
|
if (ob.type === BI.Selection.All) { |
|
if (ob.value.length === 0) { |
|
this.editor.setState(BI.Selection.All); |
|
} else if (BI.size(ob.assist) <= 20) { |
|
var state = ""; |
|
BI.each(ob.assist, function (i, v) { |
|
if (i === 0) { |
|
state += "" + (o.valueFormatter(v + "") || v); |
|
} else { |
|
state += "," + (o.valueFormatter(v + "") || v); |
|
} |
|
}); |
|
this.editor.setState(state); |
|
} else { |
|
this.editor.setState(BI.Selection.Multi); |
|
} |
|
} else { |
|
if (ob.value.length === 0) { |
|
this.editor.setState(BI.Selection.None); |
|
} else if (BI.size(ob.value) <= 20) { |
|
var state = ""; |
|
BI.each(ob.value, function (i, v) { |
|
if (i === 0) { |
|
state += "" + (o.valueFormatter(v + "") || v); |
|
} else { |
|
state += "," + (o.valueFormatter(v + "") || v); |
|
} |
|
}); |
|
this.editor.setState(state); |
|
} else { |
|
this.editor.setState(BI.Selection.Multi); |
|
} |
|
} |
|
}, |
|
|
|
getState: function() { |
|
return this.editor.getState(); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.setState(ob); |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiSelectSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.MultiSelectSearcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiSelectSearcher.EVENT_START = "EVENT_START"; |
|
BI.MultiSelectSearcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiSelectSearcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.MultiSelectSearcher.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiSelectSearcher.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiSelectSearcher.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.shortcut("bi.multi_select_searcher", BI.MultiSelectSearcher);/** |
|
* 查看已选switcher |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiSelectCheckSelectedSwitcher |
|
* @extends Widget |
|
*/ |
|
BI.MultiSelectCheckSelectedSwitcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectCheckSelectedSwitcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-check-selected-switcher", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
el: {}, |
|
popup: {}, |
|
adapter: null, |
|
masker: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectCheckSelectedSwitcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.button = BI.createWidget(o.el, { |
|
type: "bi.multi_select_check_selected_button", |
|
itemsCreator: o.itemsCreator, |
|
value: o.value |
|
}); |
|
this.button.on(BI.Events.VIEW, function () { |
|
self.fireEvent(BI.Events.VIEW, arguments); |
|
}); |
|
this.switcher = BI.createWidget({ |
|
type: "bi.switcher", |
|
toggle: false, |
|
element: this, |
|
el: this.button, |
|
popup: BI.extend({ |
|
type: "bi.multi_select_check_pane", |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: o.itemsCreator, |
|
onClickContinueSelect: function () { |
|
self.switcher.hideView(); |
|
}, |
|
ref: function (_ref) { |
|
self.checkPane = _ref; |
|
}, |
|
value: o.value |
|
}, o.popup), |
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.switcher.on(BI.Switcher.EVENT_TRIGGER_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE); |
|
}); |
|
this.switcher.on(BI.Switcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.fireEvent(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
this.switcher.on(BI.Switcher.EVENT_AFTER_POPUPVIEW, function () { |
|
var me = this; |
|
BI.nextTick(function () { |
|
me.populate(); |
|
}); |
|
}); |
|
}, |
|
|
|
adjustView: function () { |
|
this.switcher.adjustView(); |
|
}, |
|
|
|
hideView: function () { |
|
this.switcher.empty(); |
|
this.switcher.hideView(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.switcher.setAdapter(adapter); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.switcher.setValue(v); |
|
}, |
|
|
|
// 与setValue的区别是只更新查看已选面板的的selectedValue, 不会更新按钮的计数 |
|
updateSelectedValue: function (v) { |
|
this.checkPane.setValue(v); |
|
}, |
|
|
|
setButtonChecked: function (v) { |
|
this.button.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
|
|
}, |
|
|
|
populate: function (items) { |
|
this.switcher.populate.apply(this.switcher, arguments); |
|
}, |
|
|
|
populateSwitcher: function () { |
|
this.button.populate.apply(this.button, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE"; |
|
BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.multi_select_check_selected_switcher", BI.MultiSelectCheckSelectedSwitcher);/** |
|
* Created by zcf_1 on 2017/5/2. |
|
*/ |
|
BI.MultiSelectInsertList = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectInsertList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-insert-list", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiSelectInsertList.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
this.storeValue = o.value || {}; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
// self.trigger.setValue(self.storeValue); |
|
}; |
|
|
|
this.adapter = BI.createWidget({ |
|
type: "bi.multi_select_loader", |
|
cls: "popup-multi-select-list bi-border-left bi-border-right bi-border-bottom", |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
logic: { |
|
dynamic: true |
|
}, |
|
// onLoaded: o.onLoaded, |
|
el: {}, |
|
value: o.value |
|
}); |
|
this.adapter.on(BI.MultiSelectLoader.EVENT_CHANGE, function () { |
|
self.storeValue = this.getValue(); |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectInsertList.EVENT_CHANGE); |
|
}); |
|
|
|
this.searcherPane = BI.createWidget({ |
|
type: "bi.multi_select_search_insert_pane", |
|
cls: "bi-border-left bi-border-right bi-border-bottom", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.trigger.getKeyword(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keywords = [self.trigger.getKeyword()]; |
|
this.setKeyword(op.keywords[0]); |
|
o.itemsCreator(op, callback); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectSearchInsertPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
var keyword = self.trigger.getKeyword(); |
|
if (!self.trigger.hasMatched()) { |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
BI.pushDistinct(self.storeValue.value, keyword); |
|
} |
|
self._showAdapter(); |
|
self.adapter.setValue(self.storeValue); |
|
self.adapter.populate(); |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
self.fireEvent(BI.MultiSelectInsertList.EVENT_CHANGE); |
|
} |
|
} |
|
} |
|
}] |
|
}); |
|
this.searcherPane.setVisible(false); |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.searcher", |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
adapter: this.adapter, |
|
popup: this.searcherPane, |
|
height: 200, |
|
masker: false, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_START, |
|
action: function () { |
|
self._showSearcherPane(); |
|
self._setStartValue(""); |
|
this.setValue(BI.deepClone(self.storeValue)); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_STOP, |
|
action: function () { |
|
self._showAdapter(); |
|
self._setStartValue(""); |
|
self.adapter.setValue(self.storeValue); |
|
// 需要刷新回到初始界面,否则搜索的结果不能放在最前面 |
|
self.adapter.populate(); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_PAUSE, |
|
action: function () { |
|
var keyword = this.getKeyword(); |
|
if (this.hasMatched()) { |
|
self._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
BI.pushDistinct(self.storeValue.value, keyword); |
|
} |
|
self._showAdapter(); |
|
self.adapter.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(""); |
|
self.fireEvent(BI.MultiSelectInsertList.EVENT_CHANGE); |
|
}); |
|
} |
|
self._showAdapter(); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_SEARCHING, |
|
action: function () { |
|
var keywords = this.getKeywords(); |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
self.fireEvent(BI.MultiSelectInsertList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectInsertList.EVENT_CHANGE); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectInsertList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}], |
|
value: o.value |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.trigger, |
|
height: 24 |
|
}, { |
|
el: this.adapter, |
|
height: "fill" |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.searcherPane, |
|
top: 30, |
|
bottom: 0, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_showAdapter: function () { |
|
this.adapter.setVisible(true); |
|
this.searcherPane.setVisible(false); |
|
}, |
|
|
|
_showSearcherPane: function () { |
|
this.searcherPane.setVisible(true); |
|
this.adapter.setVisible(false); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
// 和复选下拉框同步,allData做缓存是会爆炸的 |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertList.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
callback(); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertList.REQ_GET_ALL_DATA, |
|
keywords: [self.trigger.getKeyword()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
callback(); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
callback(); |
|
}); |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
callback(); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.adapter.setStartValue(value); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.adapter.isAllSelected(); |
|
}, |
|
|
|
resize: function () { |
|
// this.trigger.getCounter().adjustView(); |
|
// this.trigger.adjustView(); |
|
}, |
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.adapter.setValue(this.storeValue); |
|
this.trigger.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue); |
|
}, |
|
|
|
populate: function () { |
|
this.adapter.populate.apply(this.adapter, arguments); |
|
this.trigger.populate.apply(this.trigger, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectInsertList, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectInsertList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_insert_list", BI.MultiSelectInsertList);/** |
|
* Created by zcf_1 on 2017/5/2. |
|
*/ |
|
BI.MultiSelectInsertNoBarList = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectInsertNoBarList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-insert-list", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiSelectInsertNoBarList.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
this.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: o.value || [] |
|
}; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
// self.trigger.setValue(self.storeValue); |
|
}; |
|
|
|
this.adapter = BI.createWidget({ |
|
type: "bi.multi_select_no_bar_loader", |
|
cls: "popup-multi-select-list bi-border-left bi-border-right bi-border-bottom", |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
logic: { |
|
dynamic: false |
|
}, |
|
// onLoaded: o.onLoaded, |
|
el: {}, |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value || [] |
|
} |
|
}); |
|
this.adapter.on(BI.MultiSelectLoader.EVENT_CHANGE, function () { |
|
self.storeValue = this.getValue(); |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectInsertNoBarList.EVENT_CHANGE); |
|
}); |
|
|
|
this.searcherPane = BI.createWidget({ |
|
type: "bi.multi_select_search_insert_pane", |
|
cls: "bi-border-left bi-border-right bi-border-bottom", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.trigger.getKeyword(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keywords = [self.trigger.getKeyword()]; |
|
this.setKeyword(op.keywords[0]); |
|
o.itemsCreator(op, callback); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectSearchInsertPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
var keyword = self.trigger.getKeyword(); |
|
if (!self.trigger.hasMatched()) { |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
BI.pushDistinct(self.storeValue.value, keyword); |
|
} |
|
self._showAdapter(); |
|
self.adapter.setValue(self.storeValue); |
|
self.adapter.populate(); |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
self.fireEvent(BI.MultiSelectInsertNoBarList.EVENT_CHANGE); |
|
} |
|
} |
|
} |
|
}] |
|
}); |
|
this.searcherPane.setVisible(false); |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.searcher", |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
adapter: this.adapter, |
|
popup: this.searcherPane, |
|
height: 200, |
|
masker: false, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_START, |
|
action: function () { |
|
self._showSearcherPane(); |
|
self._setStartValue(""); |
|
this.setValue(BI.deepClone(self.storeValue)); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_STOP, |
|
action: function () { |
|
self._showAdapter(); |
|
self._setStartValue(""); |
|
self.adapter.setValue(self.storeValue); |
|
// 需要刷新回到初始界面,否则搜索的结果不能放在最前面 |
|
self.adapter.populate(); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_PAUSE, |
|
action: function () { |
|
var keyword = this.getKeyword(); |
|
if (this.hasMatched()) { |
|
self._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
if (self.storeValue.type === BI.Selection.Multi) { |
|
BI.pushDistinct(self.storeValue.value, keyword); |
|
} |
|
self._showAdapter(); |
|
self.adapter.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(""); |
|
self.fireEvent(BI.MultiSelectInsertNoBarList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_SEARCHING, |
|
action: function () { |
|
var keywords = this.getKeywords(); |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
self.fireEvent(BI.MultiSelectInsertNoBarList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectInsertNoBarList.EVENT_CHANGE); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectInsertNoBarList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}], |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value || [] |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.trigger, |
|
height: 24 |
|
}, { |
|
el: this.adapter, |
|
height: "fill" |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.searcherPane, |
|
top: 30, |
|
bottom: 0, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_showAdapter: function () { |
|
this.adapter.setVisible(true); |
|
this.searcherPane.setVisible(false); |
|
}, |
|
|
|
_showSearcherPane: function () { |
|
this.searcherPane.setVisible(true); |
|
this.adapter.setVisible(false); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
// 和复选下拉框同步,allData做缓存是会爆炸的 |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertNoBarList.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
callback(); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
o.itemsCreator({ |
|
type: BI.MultiSelectInsertNoBarList.REQ_GET_ALL_DATA, |
|
keywords: [self.trigger.getKeyword()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
callback(); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
callback(); |
|
}); |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
callback(); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.adapter.setStartValue(value); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.adapter.isAllSelected(); |
|
}, |
|
|
|
resize: function () { |
|
// this.trigger.getCounter().adjustView(); |
|
// this.trigger.adjustView(); |
|
}, |
|
setValue: function (v) { |
|
this.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: v || [] |
|
}; |
|
this.adapter.setValue(this.storeValue); |
|
this.trigger.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue.value); |
|
}, |
|
|
|
populate: function () { |
|
this.adapter.populate.apply(this.adapter, arguments); |
|
this.trigger.populate.apply(this.trigger, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectInsertNoBarList, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectInsertNoBarList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_insert_no_bar_list", BI.MultiSelectInsertNoBarList);/** |
|
* Created by zcf_1 on 2017/5/2. |
|
*/ |
|
BI.MultiSelectList = BI.inherit(BI.Widget, { |
|
_constant: { |
|
EDITOR_HEIGHT: 24 |
|
}, |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-list", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiSelectList.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
this.storeValue = {}; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
// self.trigger.setValue(self.storeValue); |
|
}; |
|
|
|
this.adapter = BI.createWidget({ |
|
type: "bi.multi_select_loader", |
|
cls: "popup-multi-select-list bi-border-left bi-border-right bi-border-bottom", |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
logic: { |
|
dynamic: false |
|
}, |
|
// onLoaded: o.onLoaded, |
|
el: {} |
|
}); |
|
this.adapter.on(BI.MultiSelectLoader.EVENT_CHANGE, function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectList.EVENT_CHANGE); |
|
}); |
|
}); |
|
|
|
this.searcherPane = BI.createWidget({ |
|
type: "bi.multi_select_search_pane", |
|
cls: "bi-border-left bi-border-right bi-border-bottom", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.trigger.getKeyword(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keywords = [self.trigger.getKeyword()]; |
|
this.setKeyword(op.keywords[0]); |
|
o.itemsCreator(op, callback); |
|
} |
|
}); |
|
this.searcherPane.setVisible(false); |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.searcher", |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
adapter: this.adapter, |
|
popup: this.searcherPane, |
|
height: 200, |
|
masker: false, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_START, |
|
action: function () { |
|
self._showSearcherPane(); |
|
self._setStartValue(""); |
|
this.setValue(BI.deepClone(self.storeValue)); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_STOP, |
|
action: function () { |
|
self._showAdapter(); |
|
self._setStartValue(""); |
|
self.adapter.setValue(self.storeValue); |
|
// 需要刷新回到初始界面,否则搜索的结果不能放在最前面 |
|
self.adapter.populate(); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_PAUSE, |
|
action: function () { |
|
var keyword = this.getKeyword(); |
|
if (this.hasMatched()) { |
|
self._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
self._showAdapter(); |
|
self.adapter.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(""); |
|
self.fireEvent(BI.MultiSelectList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_SEARCHING, |
|
action: function () { |
|
var keywords = this.getKeyword(); |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
self.fireEvent(BI.MultiSelectList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectList.EVENT_CHANGE); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
self.fireEvent(BI.MultiSelectList.EVENT_CHANGE); |
|
}); |
|
} |
|
} |
|
}] |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.trigger, |
|
height: this._constant.EDITOR_HEIGHT |
|
}, { |
|
el: this.adapter, |
|
height: "fill" |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.searcherPane, |
|
top: this._constant.EDITOR_HEIGHT, |
|
bottom: 0, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_showAdapter: function () { |
|
this.adapter.setVisible(true); |
|
this.searcherPane.setVisible(false); |
|
}, |
|
|
|
_showSearcherPane: function () { |
|
this.searcherPane.setVisible(true); |
|
this.adapter.setVisible(false); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
// 和复选下拉框同步,allData做缓存是会爆炸的 |
|
o.itemsCreator({ |
|
type: BI.MultiSelectList.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
o.itemsCreator({ |
|
type: BI.MultiSelectList.REQ_GET_ALL_DATA, |
|
keywords: [this.trigger.getKey()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
self._adjust(callback); |
|
}); |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
if (!this._count) { |
|
o.itemsCreator({ |
|
type: BI.MultiSelectList.REQ_GET_DATA_LENGTH |
|
}, function (res) { |
|
self._count = res.count; |
|
adjust(); |
|
callback(); |
|
}); |
|
} else { |
|
adjust(); |
|
callback(); |
|
} |
|
|
|
function adjust () { |
|
if (self.storeValue.type === BI.Selection.All && self.storeValue.value.length >= self._count) { |
|
self.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: [] |
|
}; |
|
} else if (self.storeValue.type === BI.Selection.Multi && self.storeValue.value.length >= self._count) { |
|
self.storeValue = { |
|
type: BI.Selection.All, |
|
value: [] |
|
}; |
|
} |
|
} |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.adapter.setStartValue(value); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.adapter.isAllSelected(); |
|
}, |
|
|
|
resize: function () { |
|
// this.trigger.getCounter().adjustView(); |
|
// this.trigger.adjustView(); |
|
}, |
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.adapter.setValue(this.storeValue); |
|
this.trigger.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue); |
|
}, |
|
|
|
populate: function () { |
|
this.adapter.populate.apply(this.adapter, arguments); |
|
this.trigger.populate.apply(this.trigger, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.MultiSelectList, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.MultiSelectList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_list", BI.MultiSelectList);/** |
|
* Created by zcf_1 on 2017/5/11. |
|
*/ |
|
BI.MultiSelectTree = BI.inherit(BI.Single, { |
|
_constant: { |
|
EDITOR_HEIGHT: 24 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectTree.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-tree", |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiSelectTree.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.storeValue = {value: {}}; |
|
|
|
this.adapter = BI.createWidget({ |
|
type: "bi.multi_select_tree_popup", |
|
itemsCreator: o.itemsCreator |
|
}); |
|
this.adapter.on(BI.MultiSelectTreePopup.EVENT_CHANGE, function () { |
|
if (self.searcher.isSearching()) { |
|
self.storeValue = {value: self.searcherPane.getValue()}; |
|
} else { |
|
self.storeValue = {value: self.adapter.getValue()}; |
|
} |
|
self.setSelectedValue(self.storeValue.value); |
|
self.fireEvent(BI.MultiSelectTree.EVENT_CHANGE); |
|
}); |
|
|
|
// 搜索中的时候用的是parttree,同adapter中的synctree不一样 |
|
this.searcherPane = BI.createWidget({ |
|
type: "bi.multi_tree_search_pane", |
|
cls: "bi-border-left bi-border-right bi-border-bottom", |
|
keywordGetter: function () { |
|
return self.searcher.getKeyword(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keyword = self.searcher.getKeyword(); |
|
o.itemsCreator(op, callback); |
|
} |
|
}); |
|
this.searcherPane.setVisible(false); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback({ |
|
keyword: self.searcher.getKeyword() |
|
}); |
|
}, |
|
adapter: this.adapter, |
|
popup: this.searcherPane, |
|
masker: false, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_START, |
|
action: function () { |
|
self._showSearcherPane(); |
|
// self.storeValue = {value: self.adapter.getValue()}; |
|
// self.searcherPane.setSelectedValue(self.storeValue.value); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_STOP, |
|
action: function () { |
|
self._showAdapter(); |
|
// self.storeValue = {value: self.searcherPane.getValue()}; |
|
// self.adapter.setSelectedValue(self.storeValue.value); |
|
BI.nextTick(function () { |
|
self.adapter.populate(); |
|
}); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function () { |
|
if (self.searcher.isSearching()) { |
|
self.storeValue = {value: self.searcherPane.getValue()}; |
|
} else { |
|
self.storeValue = {value: self.adapter.getValue()}; |
|
} |
|
self.setSelectedValue(self.storeValue.value); |
|
self.fireEvent(BI.MultiSelectTree.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_PAUSE, |
|
action: function () { |
|
self._showAdapter(); |
|
} |
|
}] |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.searcher, |
|
height: this._constant.EDITOR_HEIGHT |
|
}, { |
|
el: this.adapter, |
|
height: "fill" |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.searcherPane, |
|
top: this._constant.EDITOR_HEIGHT, |
|
bottom: 0, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
|
|
}, |
|
|
|
_showAdapter: function () { |
|
this.adapter.setVisible(true); |
|
this.searcherPane.setVisible(false); |
|
}, |
|
|
|
_showSearcherPane: function () { |
|
this.searcherPane.setVisible(true); |
|
this.adapter.setVisible(false); |
|
}, |
|
|
|
resize: function () { |
|
|
|
}, |
|
|
|
setSelectedValue: function (v) { |
|
this.storeValue.value = v || {}; |
|
this.adapter.setSelectedValue(v); |
|
this.searcherPane.setSelectedValue(v); |
|
this.searcher.setValue({ |
|
value: v || {} |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.adapter.setValue(v); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
updateValue: function (v) { |
|
this.adapter.updateValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue.value; |
|
}, |
|
|
|
populate: function () { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
this.adapter.populate.apply(this.adapter, arguments); |
|
} |
|
}); |
|
BI.MultiSelectTree.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_tree", BI.MultiSelectTree);/** |
|
* Created by zcf on 2016/12/21. |
|
*/ |
|
BI.MultiSelectTreePopup = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiSelectTreePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-tree-popup bi-border-left bi-border-right bi-border-bottom", |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.MultiSelectTreePopup.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.popup = BI.createWidget({ |
|
type: "bi.async_tree", |
|
element: this, |
|
itemsCreator: o.itemsCreator |
|
}); |
|
this.popup.on(BI.TreeView.EVENT_AFTERINIT, function () { |
|
self.fireEvent(BI.MultiSelectTreePopup.EVENT_AFTER_INIT); |
|
}); |
|
this.popup.on(BI.TreeView.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectTreePopup.EVENT_CHANGE); |
|
}); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.popup.hasChecked(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v || (v = {}); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
setSelectedValue: function (v) { |
|
v || (v = {}); |
|
this.popup.setSelectedValue(v); |
|
}, |
|
|
|
updateValue: function (v) { |
|
this.popup.updateValue(v); |
|
this.popup.refresh(); |
|
}, |
|
|
|
populate: function (config) { |
|
this.popup.stroke(config); |
|
} |
|
|
|
}); |
|
BI.MultiSelectTreePopup.EVENT_AFTER_INIT = "EVENT_AFTER_INIT"; |
|
BI.MultiSelectTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_select_tree_popup", BI.MultiSelectTreePopup);/** |
|
* |
|
* @class BI.MultiTreeCheckPane |
|
* @extends BI.Pane |
|
*/ |
|
BI.MultiTreeCheckPane = BI.inherit(BI.Pane, { |
|
|
|
constants: { |
|
height: 25, |
|
lgap: 10, |
|
tgap: 5 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreeCheckPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-check-pane bi-background", |
|
onClickContinueSelect: BI.emptyFn, |
|
el: { |
|
type: "bi.display_tree" |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreeCheckPane.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
|
|
this.selectedValues = {}; |
|
|
|
var continueSelect = BI.createWidget({ |
|
type: "bi.text_button", |
|
text: BI.i18nText("BI-Continue_Select"), |
|
cls: "multi-tree-check-selected" |
|
}); |
|
continueSelect.on(BI.TextButton.EVENT_CHANGE, function () { |
|
opts.onClickContinueSelect(); |
|
BI.nextTick(function () { |
|
self.empty(); |
|
}); |
|
}); |
|
|
|
var backToPopup = BI.createWidget({ |
|
type: "bi.left", |
|
cls: "multi-tree-continue-select", |
|
items: [ |
|
{ |
|
el: { |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Selected_Data") |
|
}, |
|
lgap: this.constants.lgap, |
|
tgap: this.constants.tgap |
|
}, |
|
{ |
|
el: continueSelect, |
|
lgap: this.constants.lgap, |
|
tgap: this.constants.tgap |
|
}] |
|
}); |
|
|
|
this.display = BI.createWidget(opts.el, { |
|
type: "bi.display_tree", |
|
cls: "bi-multi-tree-display", |
|
itemsCreator: function (op, callback) { |
|
op.type = BI.TreeView.REQ_TYPE_GET_SELECTED_DATA; |
|
opts.itemsCreator(op, callback); |
|
}, |
|
value: (opts.value || {}).value |
|
}); |
|
|
|
this.display.on(BI.Events.AFTERINIT, function () { |
|
self.fireEvent(BI.Events.AFTERINIT); |
|
}); |
|
|
|
this.display.on(BI.TreeView.EVENT_INIT, function () { |
|
backToPopup.setVisible(false); |
|
}); |
|
|
|
this.display.on(BI.TreeView.EVENT_AFTERINIT, function () { |
|
backToPopup.setVisible(true); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
height: this.constants.height, |
|
el: backToPopup |
|
}, { |
|
height: "fill", |
|
el: this.display |
|
}] |
|
}); |
|
|
|
}, |
|
|
|
empty: function () { |
|
this.display.empty(); |
|
}, |
|
|
|
populate: function (configs) { |
|
this.display.stroke(configs); |
|
}, |
|
|
|
setValue: function (v) { |
|
v || (v = {}); |
|
this.display.setSelectedValue(v.value); |
|
}, |
|
|
|
getValue: function () { |
|
|
|
} |
|
}); |
|
|
|
BI.MultiTreeCheckPane.EVENT_CONTINUE_CLICK = "EVENT_CONTINUE_CLICK"; |
|
|
|
|
|
BI.shortcut("bi.multi_tree_check_pane", BI.MultiTreeCheckPane);/** |
|
* |
|
* @class BI.MultiTreeCombo |
|
* @extends BI.Single |
|
*/ |
|
|
|
BI.MultiTreeCombo = BI.inherit(BI.Single, { |
|
|
|
constants: { |
|
offset: { |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreeCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-combo", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreeCombo.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
var isInit = false; |
|
var want2showCounter = false; |
|
|
|
this.storeValue = {value: o.value || {}}; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_trigger", |
|
allowEdit: o.allowEdit, |
|
height: o.height, |
|
valueFormatter: o.valueFormatter, |
|
text: o.text, |
|
watermark: o.watermark, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: this.constants.offset |
|
}, |
|
searcher: { |
|
type: "bi.multi_tree_searcher", |
|
itemsCreator: o.itemsCreator |
|
}, |
|
value: {value: o.value || {}} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: !o.allowEdit, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.multi_tree_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiTreePopup.EVENT_AFTERINIT, |
|
action: function () { |
|
self.numberCounter.adjustView(); |
|
isInit = true; |
|
if (want2showCounter === true) { |
|
showCounter(); |
|
} |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CHANGE, |
|
action: function () { |
|
change = true; |
|
var val = { |
|
type: BI.Selection.Multi, |
|
value: this.hasChecked() ? this.getValue() : {} |
|
}; |
|
self.trigger.getSearcher().setState(val); |
|
self.numberCounter.setButtonChecked(val); |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self.combo.hideView(); |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
clear = true; |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: {value: o.value || {}}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && |
|
self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
var change = false; |
|
var clear = false; // 标识当前是否点击了清空 |
|
|
|
var isSearching = function () { |
|
return self.trigger.getSearcher().isSearching(); |
|
}; |
|
|
|
var isPopupView = function () { |
|
return self.combo.isViewVisible(); |
|
}; |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
this.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { |
|
self.storeValue = {value: this.getValue()}; |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
if (isPopupView()) { |
|
self.combo.populate(); |
|
} |
|
}); |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_STOP); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
function showCounter () { |
|
if (isSearching()) { |
|
self.storeValue = {value: self.trigger.getValue()}; |
|
} else if (isPopupView()) { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
} |
|
self.trigger.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
} |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { |
|
self.combo.toggle(); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { |
|
var checked = this.getSearcher().hasChecked(); |
|
var val = { |
|
type: BI.Selection.Multi, |
|
value: checked ? {1: 1} : {} |
|
}; |
|
this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); |
|
self.numberCounter.setButtonChecked(val); |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_CLICK_ITEM); |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
if (isSearching()) { |
|
return; |
|
} |
|
if (change === true) { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
change = false; |
|
} |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
self.populate(); |
|
|
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { |
|
if (isSearching()) { |
|
self._stopEditing(); |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_CONFIRM); |
|
} else { |
|
if (isPopupView()) { |
|
self._stopEditing(); |
|
self.storeValue = {value: self.combo.getValue()}; |
|
if (clear === true) { |
|
self.storeValue = {value: {}}; |
|
} |
|
self.fireEvent(BI.MultiTreeCombo.EVENT_CONFIRM); |
|
} |
|
} |
|
clear = false; |
|
change = false; |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
el: { |
|
type: "bi.multi_tree_check_selected_button" |
|
}, |
|
popup: { |
|
type: "bi.multi_tree_check_pane" |
|
}, |
|
masker: { |
|
offset: this.constants.offset |
|
}, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
value: {value: o.value || {}} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
if (want2showCounter === false) { |
|
want2showCounter = true; |
|
} |
|
if (isInit === true) { |
|
want2showCounter = null; |
|
showCounter(); |
|
} |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height, |
|
}] |
|
}); |
|
}, |
|
|
|
_stopEditing: function() { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue.value = v || {}; |
|
this.combo.setValue({ |
|
value: v || {} |
|
}); |
|
this.numberCounter.setValue({ |
|
value: v || {} |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue.value); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiTreeCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiTreeCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiTreeCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiTreeCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiTreeCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.MultiTreeCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_tree_combo", BI.MultiTreeCombo);/** |
|
* 可以往当前选中节点下添加新值的下拉树 |
|
* @class BI.MultiTreeInsertCombo |
|
* @extends BI.Single |
|
*/ |
|
|
|
BI.MultiTreeInsertCombo = BI.inherit(BI.Single, { |
|
|
|
constants: { |
|
offset: { |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreeInsertCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-insert-combo", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreeInsertCombo.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
var isInit = false; |
|
var want2showCounter = false; |
|
|
|
this.storeValue = {value: o.value || {}}; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_trigger", |
|
allowEdit: o.allowEdit, |
|
height: o.height, |
|
valueFormatter: o.valueFormatter, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: this.constants.offset |
|
}, |
|
searcher: { |
|
type: "bi.multi_tree_searcher", |
|
text: o.text, |
|
watermark: o.watermark, |
|
itemsCreator: o.itemsCreator, |
|
popup: { |
|
type: "bi.multi_tree_search_insert_pane", |
|
listeners: [{ |
|
eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
self.storeValue.value[self.trigger.getSearcher().getKeyword()] = {}; |
|
self._assertShowValue(); |
|
// setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
self._stopEditing(); |
|
} |
|
}] |
|
} |
|
}, |
|
value: {value: o.value || {}} |
|
|
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: !o.allowEdit, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.multi_tree_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiTreePopup.EVENT_AFTERINIT, |
|
action: function () { |
|
self.numberCounter.adjustView(); |
|
isInit = true; |
|
if (want2showCounter === true) { |
|
showCounter(); |
|
} |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CHANGE, |
|
action: function () { |
|
change = true; |
|
var val = { |
|
type: BI.Selection.Multi, |
|
value: this.hasChecked() ? this.getValue() : {} |
|
}; |
|
self.trigger.getSearcher().setState(val); |
|
self.numberCounter.setButtonChecked(val); |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CLICK_ITEM, self.combo.getValue()); |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self.combo.hideView(); |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
clear = true; |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: {value: o.value || {}}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && |
|
self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
var change = false; |
|
var clear = false; // 标识当前是否点击了清空 |
|
|
|
var isSearching = function () { |
|
return self.trigger.getSearcher().isSearching(); |
|
}; |
|
|
|
var isPopupView = function () { |
|
return self.combo.isViewVisible(); |
|
}; |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
this.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { |
|
self.storeValue = {value: this.getValue()}; |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
if (isPopupView()) { |
|
self.combo.populate(); |
|
} |
|
}); |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_STOP); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
function showCounter () { |
|
if (isSearching()) { |
|
self.storeValue = {value: self.trigger.getValue()}; |
|
} else if (isPopupView()) { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
} |
|
self.trigger.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
} |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { |
|
self.combo.toggle(); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { |
|
var checked = this.getSearcher().hasChecked(); |
|
var val = { |
|
type: BI.Selection.Multi, |
|
value: checked ? {1: 1} : {} |
|
}; |
|
this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); |
|
self.numberCounter.setButtonChecked(val); |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CLICK_ITEM, self.combo.getValue()); |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
if (isSearching()) { |
|
return; |
|
} |
|
if (change === true) { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
change = false; |
|
} |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
self.populate(); |
|
|
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { |
|
if (isSearching()) { |
|
self._stopEditing(); |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); |
|
} else { |
|
if (isPopupView()) { |
|
self._stopEditing(); |
|
self.storeValue = {value: self.combo.getValue()}; |
|
if (clear === true) { |
|
self.storeValue = {value: {}}; |
|
} |
|
self.fireEvent(BI.MultiTreeInsertCombo.EVENT_CONFIRM); |
|
} |
|
} |
|
clear = false; |
|
change = false; |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
el: { |
|
type: "bi.multi_tree_check_selected_button" |
|
}, |
|
popup: { |
|
type: "bi.multi_tree_check_pane" |
|
}, |
|
itemsCreator: o.itemsCreator, |
|
masker: { |
|
offset: this.constants.offset |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
value: o.value |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
if (want2showCounter === false) { |
|
want2showCounter = true; |
|
} |
|
if (isInit === true) { |
|
want2showCounter = null; |
|
showCounter(); |
|
} |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height, |
|
}] |
|
}); |
|
}, |
|
|
|
_assertShowValue: function () { |
|
this.trigger.getSearcher().setState(this.storeValue); |
|
this.numberCounter.setButtonChecked(this.storeValue); |
|
}, |
|
|
|
_stopEditing: function() { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue.value = v || {}; |
|
this.combo.setValue({ |
|
value: v || {} |
|
}); |
|
this.numberCounter.setValue({ |
|
value: v || {} |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue.value); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiTreeInsertCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiTreeInsertCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiTreeInsertCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiTreeInsertCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.MultiTreeInsertCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiTreeInsertCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_tree_insert_combo", BI.MultiTreeInsertCombo);/** |
|
* 选中节点不影响父子节点状态的下拉树 |
|
* @class BI.MultiTreeListCombo |
|
* @extends BI.Single |
|
*/ |
|
|
|
BI.MultiTreeListCombo = BI.inherit(BI.Single, { |
|
|
|
constants: { |
|
offset: { |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreeListCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-list-combo", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
allowEdit: true, |
|
allowInsertValue: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreeListCombo.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
var isInit = false; |
|
var want2showCounter = false; |
|
|
|
this.storeValue = {value: o.value || []}; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.multi_select_trigger", |
|
allowEdit: o.allowEdit, |
|
text: o.text, |
|
watermark: o.watermark, |
|
height: o.height, |
|
valueFormatter: o.valueFormatter, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: this.constants.offset |
|
}, |
|
searcher: { |
|
type: "bi.multi_list_tree_searcher", |
|
itemsCreator: o.itemsCreator, |
|
popup: { |
|
type: o.allowInsertValue ? "bi.multi_tree_search_insert_pane" : "bi.multi_tree_search_pane", |
|
el: { |
|
type: "bi.list_part_tree" |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
self.storeValue.value.unshift([self.trigger.getSearcher().getKeyword()]); |
|
self._assertShowValue(); |
|
// setValue以更新paras.value, 之后从search popup中拿到的就能有add的值了 |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
self._stopEditing(); |
|
} |
|
}] |
|
} |
|
}, |
|
switcher: { |
|
el: { |
|
type: "bi.multi_tree_check_selected_button" |
|
}, |
|
popup: { |
|
type: "bi.multi_tree_check_pane", |
|
el: { |
|
type: "bi.list_display_tree" |
|
}, |
|
itemsCreator: o.itemsCreator |
|
} |
|
}, |
|
value: {value: o.value || {}} |
|
|
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: !o.allowEdit, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.multi_tree_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
self.numberCounter.setAdapter(this); |
|
}, |
|
el: { |
|
type: "bi.list_async_tree" |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiTreePopup.EVENT_AFTERINIT, |
|
action: function () { |
|
self.numberCounter.adjustView(); |
|
isInit = true; |
|
if (want2showCounter === true) { |
|
showCounter(); |
|
} |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CHANGE, |
|
action: function () { |
|
change = true; |
|
var val = { |
|
type: BI.Selection.Multi, |
|
value: this.hasChecked() ? this.getValue() : [] |
|
}; |
|
self.trigger.getSearcher().setState(val); |
|
self.numberCounter.setButtonChecked(val); |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_CLICK_ITEM, self.combo.getValue()); |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self.combo.hideView(); |
|
} |
|
}, { |
|
eventName: BI.MultiTreePopup.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
clear = true; |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.numberCounter.adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: {value: o.value || {}}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0 && |
|
self.numberCounter.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
var change = false; |
|
var clear = false; // 标识当前是否点击了清空 |
|
|
|
var isSearching = function () { |
|
return self.trigger.getSearcher().isSearching(); |
|
}; |
|
|
|
var isPopupView = function () { |
|
return self.combo.isViewVisible(); |
|
}; |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
this.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { |
|
self.storeValue = {value: this.getValue()}; |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
if (isPopupView()) { |
|
self.combo.populate(); |
|
} |
|
}); |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_STOP); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
function showCounter () { |
|
if (isSearching()) { |
|
self.storeValue = {value: self.trigger.getValue()}; |
|
} else if (isPopupView()) { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
} |
|
self.trigger.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
} |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_TRIGGER_CLICK, function () { |
|
self.combo.toggle(); |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function () { |
|
var checked = this.getSearcher().hasChecked(); |
|
var val = { |
|
type: BI.Selection.Multi, |
|
value: checked ? {1: 1} : {} |
|
}; |
|
this.getSearcher().setState(checked ? BI.Selection.Multi : BI.Selection.None); |
|
self.numberCounter.setButtonChecked(val); |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_CLICK_ITEM, self.combo.getValue()); |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
if (isSearching()) { |
|
return; |
|
} |
|
if (change === true) { |
|
self.storeValue = {value: self.combo.getValue()}; |
|
change = false; |
|
} |
|
self.combo.setValue(self.storeValue); |
|
self.numberCounter.setValue(self.storeValue); |
|
self.populate(); |
|
|
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_HIDEVIEW, function () { |
|
if (isSearching()) { |
|
self.trigger.stopEditing(); |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); |
|
} else { |
|
if (isPopupView()) { |
|
self._stopEditing(); |
|
self.storeValue = {value: self.combo.getValue()}; |
|
if (clear === true) { |
|
self.storeValue = {value: []}; |
|
} |
|
self.fireEvent(BI.MultiTreeListCombo.EVENT_CONFIRM); |
|
} |
|
} |
|
clear = false; |
|
change = false; |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.numberCounter.hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.numberCounter = BI.createWidget({ |
|
type: "bi.multi_select_check_selected_switcher", |
|
el: { |
|
type: "bi.multi_tree_check_selected_button" |
|
}, |
|
popup: { |
|
type: "bi.multi_tree_check_pane" |
|
}, |
|
itemsCreator: o.itemsCreator, |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
value: o.value |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
if (want2showCounter === false) { |
|
want2showCounter = true; |
|
} |
|
if (isInit === true) { |
|
want2showCounter = null; |
|
showCounter(); |
|
} |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
self.trigger.refreshPlaceHolderWidth((b === true ? self.numberCounter.element.outerWidth() + 8 : 0)); |
|
}); |
|
}); |
|
|
|
this.trigger.element.click(function (e) { |
|
if (self.trigger.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.vertical_adapt", |
|
items: [this.numberCounter] |
|
}, |
|
right: o.height, |
|
top: 0, |
|
height: o.height, |
|
}] |
|
}); |
|
}, |
|
|
|
_assertShowValue: function () { |
|
this.trigger.getSearcher().setState(this.storeValue); |
|
this.numberCounter.setButtonChecked(this.storeValue); |
|
}, |
|
|
|
_stopEditing: function() { |
|
this.trigger.stopEditing(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this._stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue.value = v || []; |
|
this.combo.setValue({ |
|
value: v || [] |
|
}); |
|
this.numberCounter.setValue({ |
|
value: v || [] |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue.value); |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiTreeListCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.MultiTreeListCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.MultiTreeListCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiTreeListCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.MultiTreeListCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiTreeListCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.multi_tree_list_combo", BI.MultiTreeListCombo);/** |
|
* 带加载的多选下拉面板 |
|
* @class BI.MultiTreePopup |
|
* @extends BI.Pane |
|
*/ |
|
BI.MultiTreePopup = BI.inherit(BI.Pane, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-popup", |
|
maxWidth: "auto", |
|
minWidth: 140, |
|
maxHeight: 400, |
|
onLoaded: BI.emptyFn, |
|
el: { |
|
type: "bi.async_tree" |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreePopup.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options, v = opts.value; |
|
|
|
this.selectedValues = {}; |
|
|
|
this.tree = BI.createWidget(opts.el, { |
|
type: "bi.async_tree", |
|
height: 400, |
|
cls: "popup-view-tree", |
|
itemsCreator: opts.itemsCreator, |
|
onLoaded: opts.onLoaded, |
|
value: v.value || {} |
|
}); |
|
|
|
this.popupView = BI.createWidget({ |
|
type: "bi.multi_popup_view", |
|
element: this, |
|
stopPropagation: false, |
|
maxWidth: opts.maxWidth, |
|
minWidth: opts.minWidth, |
|
maxHeight: opts.maxHeight, |
|
buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], |
|
el: this.tree |
|
}); |
|
|
|
this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { |
|
switch (index) { |
|
case 0: |
|
self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CLEAR); |
|
break; |
|
case 1: |
|
self.fireEvent(BI.MultiTreePopup.EVENT_CLICK_CONFIRM); |
|
break; |
|
} |
|
}); |
|
|
|
this.tree.on(BI.TreeView.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiTreePopup.EVENT_CHANGE); |
|
}); |
|
|
|
this.tree.on(BI.TreeView.EVENT_AFTERINIT, function () { |
|
self.fireEvent(BI.MultiTreePopup.EVENT_AFTERINIT); |
|
}); |
|
|
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v || (v = {}); |
|
this.tree.setSelectedValue(v.value); |
|
}, |
|
|
|
populate: function (config) { |
|
this.tree.stroke(config); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.tree.hasChecked(); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.popupView.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.popupView.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.MultiTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiTreePopup.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; |
|
BI.MultiTreePopup.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; |
|
BI.MultiTreePopup.EVENT_AFTERINIT = "EVENT_AFTERINIT"; |
|
|
|
|
|
BI.shortcut("bi.multi_tree_popup_view", BI.MultiTreePopup);/** |
|
* 查看已选按钮 |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiTreeCheckSelectedButton |
|
* @extends BI.Single |
|
*/ |
|
BI.MultiTreeCheckSelectedButton = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreeCheckSelectedButton.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-check-selected-button", |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreeCheckSelectedButton.superclass._init.apply(this, arguments); |
|
var self = this; |
|
this.indicator = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "check-font trigger-check-selected icon-size-12", |
|
width: 15, |
|
height: 15, |
|
stopPropagation: true |
|
}); |
|
|
|
this.checkSelected = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "trigger-check-selected", |
|
invisible: true, |
|
hgap: 4, |
|
text: BI.i18nText("BI-Check_Selected"), |
|
textAlign: "center", |
|
textHeight: 15 |
|
}); |
|
this.checkSelected.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.checkSelected.on(BI.TextButton.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiSelectCheckSelectedButton.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.horizontal", |
|
element: this, |
|
items: [this.indicator, this.checkSelected] |
|
}); |
|
|
|
this.element.hover(function () { |
|
self.indicator.setVisible(false); |
|
self.checkSelected.setVisible(true); |
|
}, function () { |
|
self.indicator.setVisible(true); |
|
self.checkSelected.setVisible(false); |
|
}); |
|
this.setVisible(false); |
|
}, |
|
|
|
setValue: function (v) { |
|
v || (v = {}); |
|
var show = BI.size(v.value) > 0; |
|
this.setVisible(show); |
|
} |
|
}); |
|
|
|
BI.MultiTreeCheckSelectedButton.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.multi_tree_check_selected_button", BI.MultiTreeCheckSelectedButton);/** |
|
* |
|
* 在搜索框中输入文本弹出的面板 |
|
* @class BI.MultiTreeSearchInsertPane |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.MultiTreeSearchInsertPane = BI.inherit(BI.Widget, { |
|
|
|
constants: { |
|
height: 24, |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-multi-tree-search-insert-pane bi-card", |
|
itemsCreator: BI.emptyFn, |
|
keywordGetter: BI.emptyFn, |
|
el: { |
|
type: "bi.part_tree" |
|
} |
|
}, |
|
|
|
render: function () { |
|
var self = this, opts = this.options; |
|
|
|
return { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.text_button", |
|
invisible: true, |
|
ref: function (_ref) { |
|
self.addTip = _ref; |
|
}, |
|
text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), |
|
height: this.constants.height, |
|
cls: "bi-high-light", |
|
handler: function () { |
|
self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM, opts.keywordGetter()); |
|
} |
|
}, |
|
top: 5, |
|
left: 0, |
|
right: 0 |
|
}, { |
|
el: BI.extend({ |
|
type: "bi.part_tree", |
|
tipText: BI.i18nText("BI-No_Select"), |
|
itemsCreator: function (op, callback) { |
|
op.keyword = opts.keywordGetter(); |
|
opts.itemsCreator(op, function (res) { |
|
callback(res); |
|
self.setKeyword(opts.keywordGetter(), res.items); |
|
}); |
|
}, |
|
ref: function (_ref) { |
|
self.partTree = _ref; |
|
}, |
|
value: opts.value, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}, { |
|
eventName: BI.TreeView.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiTreeSearchInsertPane.EVENT_CHANGE); |
|
} |
|
}] |
|
}, opts.el), |
|
left: 0, |
|
top: 0, |
|
bottom: 0, |
|
right: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
setKeyword: function (keyword, nodes) { |
|
var isAddTipVisible = BI.isEmptyArray(nodes); |
|
this.addTip.setVisible(isAddTipVisible); |
|
this.partTree.setVisible(!isAddTipVisible); |
|
isAddTipVisible && this.addTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.partTree.hasChecked(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.setSelectedValue(v.value); |
|
}, |
|
|
|
setSelectedValue: function (v) { |
|
v || (v = {}); |
|
this.partTree.setSelectedValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.partTree.getValue(); |
|
}, |
|
|
|
empty: function () { |
|
this.partTree.empty(); |
|
}, |
|
|
|
populate: function (op) { |
|
this.partTree.stroke.apply(this.partTree, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiTreeSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.MultiTreeSearchInsertPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; |
|
BI.MultiTreeSearchInsertPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; |
|
BI.MultiTreeSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
|
|
BI.shortcut("bi.multi_tree_search_insert_pane", BI.MultiTreeSearchInsertPane);/** |
|
* |
|
* 在搜索框中输入文本弹出的面板 |
|
* @class BI.MultiTreeSearchPane |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.MultiTreeSearchPane = BI.inherit(BI.Pane, { |
|
|
|
props: { |
|
baseCls: "bi-multi-tree-search-pane bi-card", |
|
itemsCreator: BI.emptyFn, |
|
keywordGetter: BI.emptyFn |
|
}, |
|
|
|
render: function () { |
|
var self = this, opts = this.options; |
|
|
|
return BI.extend({ |
|
type: "bi.part_tree", |
|
element: this, |
|
tipText: BI.i18nText("BI-No_Select"), |
|
itemsCreator: function (op, callback) { |
|
op.keyword = opts.keywordGetter(); |
|
opts.itemsCreator(op, callback); |
|
}, |
|
value: opts.value, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}, { |
|
eventName: BI.TreeView.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.MultiTreeSearchPane.EVENT_CHANGE); |
|
} |
|
}], |
|
ref: function (_ref) { |
|
self.partTree = _ref; |
|
} |
|
}, opts.el); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.partTree.hasChecked(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.setSelectedValue(v.value); |
|
}, |
|
|
|
setSelectedValue: function (v) { |
|
v || (v = {}); |
|
this.partTree.setSelectedValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.partTree.getValue(); |
|
}, |
|
|
|
empty: function () { |
|
this.partTree.empty(); |
|
}, |
|
|
|
populate: function (op) { |
|
this.partTree.stroke.apply(this.partTree, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiTreeSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.MultiTreeSearchPane.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; |
|
BI.MultiTreeSearchPane.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; |
|
|
|
BI.shortcut("bi.multi_tree_search_pane", BI.MultiTreeSearchPane);/** |
|
* searcher |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiListTreeSearcher |
|
* @extends Widget |
|
*/ |
|
BI.MultiListTreeSearcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiListTreeSearcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-searcher", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: function (v) { |
|
return v; |
|
}, |
|
popup: {}, |
|
|
|
adapter: null, |
|
masker: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiListTreeSearcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.multi_select_editor", |
|
height: o.height, |
|
text: o.text, |
|
watermark: o.watermark, |
|
el: { |
|
type: "bi.simple_state_editor", |
|
height: o.height |
|
} |
|
}); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
element: this, |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback({ |
|
keyword: self.editor.getValue() |
|
}); |
|
}, |
|
el: this.editor, |
|
|
|
popup: BI.extend({ |
|
type: "bi.multi_tree_search_pane", |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keyword = self.editor.getValue(); |
|
o.itemsCreator(op, callback); |
|
}, |
|
value: o.value |
|
}, o.popup), |
|
|
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_START, function () { |
|
self.fireEvent(BI.MultiListTreeSearcher.EVENT_START); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { |
|
if (this.hasMatched()) { |
|
|
|
} |
|
self.fireEvent(BI.MultiListTreeSearcher.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.MultiListTreeSearcher.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiListTreeSearcher.EVENT_CHANGE, arguments); |
|
}); |
|
if (BI.isNotNull(o.value)) { |
|
this.setState(o.value); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.searcher.adjustView(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
isSearching: function () { |
|
return this.searcher.isSearching(); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getKeyword: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.searcher.hasMatched(); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.searcher.getView() && this.searcher.getView().hasChecked(); |
|
}, |
|
|
|
setState: function (ob) { |
|
var o = this.options; |
|
ob || (ob = {}); |
|
ob.value || (ob.value = []); |
|
var count = 0; |
|
if (BI.isNumber(ob)) { |
|
this.editor.setState(ob); |
|
} else if (BI.size(ob.value) === 0) { |
|
this.editor.setState(BI.Selection.None); |
|
} else { |
|
var text = ""; |
|
BI.each(ob.value, function (idx, path) { |
|
var childValue = BI.last(path); |
|
text += (o.valueFormatter(childValue + "") || childValue) + "; "; |
|
count++; |
|
}); |
|
|
|
if (count > 20) { |
|
this.editor.setState(BI.Selection.Multi); |
|
} else { |
|
this.editor.setState(text); |
|
} |
|
} |
|
}, |
|
|
|
getState: function() { |
|
return this.editor.getState(); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.setState(ob); |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiListTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.MultiListTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiListTreeSearcher.EVENT_START = "EVENT_START"; |
|
BI.MultiListTreeSearcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiListTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.shortcut("bi.multi_list_tree_searcher", BI.MultiListTreeSearcher);/** |
|
* searcher |
|
* Created by guy on 15/11/3. |
|
* @class BI.MultiTreeSearcher |
|
* @extends Widget |
|
*/ |
|
BI.MultiTreeSearcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.MultiTreeSearcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-tree-searcher", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: function (v) { |
|
return v; |
|
}, |
|
popup: {}, |
|
|
|
adapter: null, |
|
masker: {}, |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.MultiTreeSearcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.multi_select_editor", |
|
watermark: o.watermark, |
|
height: o.height, |
|
el: { |
|
type: "bi.simple_state_editor", |
|
text: o.text, |
|
height: o.height |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectEditor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectEditor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.MultiSelectSearcher.EVENT_BLUR); |
|
} |
|
}] |
|
}); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
element: this, |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback({ |
|
keyword: self.editor.getValue() |
|
}); |
|
}, |
|
el: this.editor, |
|
|
|
popup: BI.extend({ |
|
type: "bi.multi_tree_search_pane", |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keyword = self.editor.getValue(); |
|
o.itemsCreator(op, callback); |
|
}, |
|
value: o.value |
|
}, o.popup), |
|
|
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_START, function () { |
|
self.fireEvent(BI.MultiTreeSearcher.EVENT_START); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { |
|
if (this.hasMatched()) { |
|
|
|
} |
|
self.fireEvent(BI.MultiTreeSearcher.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.MultiTreeSearcher.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.MultiTreeSearcher.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_SEARCHING, function () { |
|
var keywords = this.getKeywords(); |
|
self.fireEvent(BI.MultiTreeSearcher.EVENT_SEARCHING, keywords); |
|
}); |
|
if (BI.isNotNull(o.value)) { |
|
this.setState(o.value); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.searcher.adjustView(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
isSearching: function () { |
|
return this.searcher.isSearching(); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getKeyword: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.searcher.hasMatched(); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.searcher.getView() && this.searcher.getView().hasChecked(); |
|
}, |
|
|
|
setState: function (ob) { |
|
var o = this.options; |
|
ob || (ob = {}); |
|
ob.value || (ob.value = {}); |
|
var count = 0; |
|
if (BI.isNumber(ob)) { |
|
this.editor.setState(ob); |
|
} else if (BI.size(ob.value) === 0) { |
|
this.editor.setState(BI.Selection.None); |
|
} else { |
|
var text = ""; |
|
BI.each(ob.value, function (name, children) { |
|
var childNodes = getChildrenNode(children); |
|
text += (o.valueFormatter(name + "") || name) + (childNodes === "" ? "" : (":" + childNodes)) + "; "; |
|
if (childNodes === "") { |
|
count++; |
|
} |
|
}); |
|
|
|
if (count > 20) { |
|
this.editor.setState(BI.Selection.Multi); |
|
} else { |
|
this.editor.setState(text); |
|
} |
|
} |
|
|
|
function getChildrenNode (ob) { |
|
var text = ""; |
|
var index = 0, size = BI.size(ob); |
|
BI.each(ob, function (name, children) { |
|
index++; |
|
var childNodes = getChildrenNode(children); |
|
text += (o.valueFormatter(name + "") || name) + (childNodes === "" ? "" : (":" + childNodes)) + (index === size ? "" : ","); |
|
if (childNodes === "") { |
|
count++; |
|
} |
|
}); |
|
return text; |
|
} |
|
}, |
|
|
|
getState: function() { |
|
return this.editor.getState(); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.setState(ob); |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
} |
|
}); |
|
|
|
BI.MultiTreeSearcher.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.MultiTreeSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.MultiTreeSearcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.MultiTreeSearcher.EVENT_START = "EVENT_START"; |
|
BI.MultiTreeSearcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.MultiTreeSearcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.shortcut("bi.multi_tree_searcher", BI.MultiTreeSearcher);/** |
|
* Created by windy on 2017/3/13. |
|
* 数值微调器 |
|
*/ |
|
BI.NumberEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.NumberEditor.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-number-editor bi-border bi-focus-shadow", |
|
validationChecker: function () { |
|
return true; |
|
}, |
|
valueFormatter: function (v) { |
|
return v; |
|
}, |
|
value: 0, |
|
allowBlank: false, |
|
errorText: "", |
|
step: 1 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.NumberEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height - 2, |
|
allowBlank: o.allowBlank, |
|
value: o.valueFormatter(o.value), |
|
validationChecker: o.validationChecker, |
|
errorText: o.errorText |
|
}); |
|
this.editor.on(BI.TextEditor.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.NumberEditor.EVENT_CHANGE); |
|
}); |
|
this.editor.on(BI.TextEditor.EVENT_ERROR, function () { |
|
o.value = BI.parseFloat(this.getLastValidValue()); |
|
}); |
|
this.editor.on(BI.TextEditor.EVENT_VALID, function () { |
|
o.value = BI.parseFloat(this.getValue()); |
|
}); |
|
this.editor.on(BI.TextEditor.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.NumberEditor.EVENT_CONFIRM); |
|
}); |
|
this.topBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
forceNotSelected: true, |
|
trigger: "lclick,", |
|
cls: "add-up-font top-button bi-border-left bi-list-item-active2 icon-size-12" |
|
}); |
|
this.topBtn.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self._finetuning(o.step); |
|
self.fireEvent(BI.NumberEditor.EVENT_CHANGE); |
|
self.fireEvent(BI.NumberEditor.EVENT_CONFIRM); |
|
}); |
|
this.bottomBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
trigger: "lclick,", |
|
forceNotSelected: true, |
|
cls: "minus-down-font bottom-button bi-border-left bi-list-item-active2 icon-size-12" |
|
}); |
|
this.bottomBtn.on(BI.IconButton.EVENT_CHANGE, function () { |
|
self._finetuning(-o.step); |
|
self.fireEvent(BI.NumberEditor.EVENT_CHANGE); |
|
self.fireEvent(BI.NumberEditor.EVENT_CONFIRM); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.htape", |
|
height: o.height - 2, |
|
element: this, |
|
items: [this.editor, { |
|
el: { |
|
type: "bi.grid", |
|
columns: 1, |
|
rows: 2, |
|
items: [{ |
|
column: 0, |
|
row: 0, |
|
el: this.topBtn |
|
}, { |
|
column: 0, |
|
row: 1, |
|
el: this.bottomBtn |
|
}] |
|
}, |
|
width: 23 |
|
}] |
|
}); |
|
}, |
|
|
|
focus: function () { |
|
this.editor.focus(); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
// 微调 |
|
_finetuning: function (add) { |
|
var v = BI.parseFloat(this.getValue()); |
|
this.setValue(BI.add(v, add)); |
|
}, |
|
|
|
setUpEnable: function (v) { |
|
this.topBtn.setEnable(!!v); |
|
}, |
|
|
|
setDownEnable: function (v) { |
|
this.bottomBtn.setEnable(!!v); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.options.value; |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
o.value = v; |
|
this.editor.setValue(o.valueFormatter(v)); |
|
} |
|
|
|
}); |
|
BI.NumberEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.NumberEditor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.number_editor", BI.NumberEditor);// 小于号的值为:0,小于等于号的值为:1 |
|
// closeMIn:最小值的符号,closeMax:最大值的符号 |
|
/** |
|
* Created by roy on 15/9/17. |
|
* |
|
*/ |
|
BI.NumberInterval = BI.inherit(BI.Single, { |
|
constants: { |
|
typeError: "typeBubble", |
|
numberError: "numberBubble", |
|
signalError: "signalBubble", |
|
editorWidth: 114, |
|
columns: 5, |
|
width: 24, |
|
rows: 1, |
|
numberErrorCls: "number-error", |
|
border: 1, |
|
less: 0, |
|
less_equal: 1, |
|
numTip: "", |
|
adjustYOffset: 2 |
|
}, |
|
_defaultConfig: function () { |
|
var conf = BI.NumberInterval.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-number-interval" + ((BI.isIE() && BI.getIEVersion() < 10) ? " hack" : ""), |
|
height: 24, |
|
validation: "valid", |
|
closeMin: true, |
|
allowBlank: true, |
|
watermark: BI.i18nText("BI-Basic_Unrestricted") |
|
}); |
|
}, |
|
_init: function () { |
|
var self = this, c = this.constants, o = this.options; |
|
BI.NumberInterval.superclass._init.apply(this, arguments); |
|
this.smallEditor = BI.createWidget({ |
|
type: "bi.number_interval_single_editor", |
|
height: o.height - 2, |
|
watermark: o.watermark, |
|
allowBlank: o.allowBlank, |
|
value: o.min, |
|
level: "warning", |
|
tipType: "success", |
|
title: function () { |
|
return self.smallEditor && self.smallEditor.getValue(); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
validationChecker: function (v) { |
|
if (!BI.isNumeric(v)) { |
|
self.smallEditorBubbleType = c.typeError; |
|
return false; |
|
} |
|
return true; |
|
}, |
|
cls: "number-interval-small-editor bi-border" |
|
}); |
|
|
|
this.smallTip = BI.createWidget({ |
|
type: "bi.label", |
|
text: o.numTip, |
|
height: o.height - 2, |
|
invisible: true |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this.smallEditor.element, |
|
items: [{ |
|
el: this.smallTip, |
|
top: 0, |
|
right: 5 |
|
}] |
|
}); |
|
|
|
this.bigEditor = BI.createWidget({ |
|
type: "bi.number_interval_single_editor", |
|
height: o.height - 2, |
|
watermark: o.watermark, |
|
allowBlank: o.allowBlank, |
|
value: o.max, |
|
title: function () { |
|
return self.bigEditor && self.bigEditor.getValue(); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
validationChecker: function (v) { |
|
if (!BI.isNumeric(v)) { |
|
self.bigEditorBubbleType = c.typeError; |
|
return false; |
|
} |
|
return true; |
|
}, |
|
cls: "number-interval-big-editor bi-border" |
|
}); |
|
|
|
this.bigTip = BI.createWidget({ |
|
type: "bi.label", |
|
text: o.numTip, |
|
height: o.height - 2, |
|
invisible: true |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this.bigEditor.element, |
|
items: [{ |
|
el: this.bigTip, |
|
top: 0, |
|
right: 5 |
|
}] |
|
}); |
|
this.smallCombo = BI.createWidget({ |
|
type: "bi.icon_combo", |
|
cls: "number-interval-small-combo bi-border-top bi-border-bottom bi-border-right", |
|
height: o.height - 2, |
|
items: [{ |
|
text: "(" + BI.i18nText("BI-Less_Than") + ")", |
|
iconCls: "less-font", |
|
value: 0 |
|
}, { |
|
text: "(" + BI.i18nText("BI-Less_And_Equal") + ")", |
|
value: 1, |
|
iconCls: "less-equal-font" |
|
}] |
|
}); |
|
if (o.closeMin === true) { |
|
this.smallCombo.setValue(1); |
|
} else { |
|
this.smallCombo.setValue(0); |
|
} |
|
this.bigCombo = BI.createWidget({ |
|
type: "bi.icon_combo", |
|
cls: "number-interval-big-combo bi-border-top bi-border-bottom bi-border-left", |
|
height: o.height - 2, |
|
items: [{ |
|
text: "(" + BI.i18nText("BI-Less_Than") + ")", |
|
iconCls: "less-font", |
|
value: 0 |
|
}, { |
|
text: "(" + BI.i18nText("BI-Less_And_Equal") + ")", |
|
value: 1, |
|
iconCls: "less-equal-font" |
|
}] |
|
}); |
|
if (o.closeMax === true) { |
|
this.bigCombo.setValue(1); |
|
} else { |
|
this.bigCombo.setValue(0); |
|
} |
|
this.label = BI.createWidget({ |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Basic_Value"), |
|
textHeight: o.height - c.border * 2, |
|
width: c.width - c.border * 2, |
|
height: o.height - c.border * 2, |
|
level: "warning", |
|
tipType: "warning" |
|
}); |
|
this.left = BI.createWidget({ |
|
type: "bi.htape", |
|
items: [{ |
|
el: self.smallEditor |
|
}, { |
|
el: self.smallCombo, |
|
width: c.width - c.border |
|
}] |
|
|
|
}); |
|
this.right = BI.createWidget({ |
|
type: "bi.htape", |
|
items: [{ |
|
el: self.bigCombo, |
|
width: c.width - c.border |
|
}, { |
|
el: self.bigEditor, |
|
// BI-23883 间距考虑边框 |
|
lgap: 1 |
|
}] |
|
}); |
|
|
|
|
|
BI.createWidget({ |
|
element: self, |
|
type: "bi.center", |
|
hgap: 15, |
|
height: o.height, |
|
items: [ |
|
{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.left, |
|
left: -15, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.right, |
|
left: 0, |
|
right: -15, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
} |
|
] |
|
}); |
|
|
|
BI.createWidget({ |
|
element: self, |
|
type: "bi.horizontal_auto", |
|
items: [ |
|
self.label |
|
] |
|
}); |
|
|
|
|
|
self._setValidEvent(self.bigEditor, c.bigEditor); |
|
self._setValidEvent(self.smallEditor, c.smallEditor); |
|
self._setErrorEvent(self.bigEditor, c.bigEditor); |
|
self._setErrorEvent(self.smallEditor, c.smallEditor); |
|
self._setBlurEvent(self.bigEditor); |
|
self._setBlurEvent(self.smallEditor); |
|
self._setFocusEvent(self.bigEditor); |
|
self._setFocusEvent(self.smallEditor); |
|
self._setComboValueChangedEvent(self.bigCombo); |
|
self._setComboValueChangedEvent(self.smallCombo); |
|
self._setEditorValueChangedEvent(self.bigEditor); |
|
self._setEditorValueChangedEvent(self.smallEditor); |
|
|
|
self._checkValidation(); |
|
}, |
|
|
|
_checkValidation: function () { |
|
var self = this, c = this.constants, o = this.options; |
|
self._setTitle(""); |
|
BI.Bubbles.hide(c.typeError); |
|
BI.Bubbles.hide(c.numberError); |
|
BI.Bubbles.hide(c.signalError); |
|
if (!self.smallEditor.isValid() || !self.bigEditor.isValid()) { |
|
self.element.removeClass("number-error"); |
|
o.validation = "invalid"; |
|
return c.typeError; |
|
} |
|
if (BI.isEmptyString(self.smallEditor.getValue()) || BI.isEmptyString(self.bigEditor.getValue())) { |
|
self.element.removeClass("number-error"); |
|
o.validation = "valid"; |
|
return ""; |
|
} |
|
var smallValue = parseFloat(self.smallEditor.getValue()), bigValue = parseFloat(self.bigEditor.getValue()), |
|
bigComboValue = self.bigCombo.getValue(), smallComboValue = self.smallCombo.getValue(); |
|
if (bigComboValue[0] === c.less_equal && smallComboValue[0] === c.less_equal) { |
|
if (smallValue > bigValue) { |
|
self.element.addClass("number-error"); |
|
o.validation = "invalid"; |
|
return c.numberError; |
|
} |
|
self.element.removeClass("number-error"); |
|
o.validation = "valid"; |
|
return ""; |
|
|
|
} |
|
if (smallValue > bigValue) { |
|
self.element.addClass("number-error"); |
|
o.validation = "invalid"; |
|
return c.numberError; |
|
} else if (smallValue === bigValue) { |
|
self.element.addClass("number-error"); |
|
o.validation = "invalid"; |
|
return c.signalError; |
|
} |
|
self.element.removeClass("number-error"); |
|
o.validation = "valid"; |
|
return ""; |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
_setTitle: function (v) { |
|
this.label.setTitle(v); |
|
}, |
|
|
|
_setFocusEvent: function (w) { |
|
var self = this, c = this.constants; |
|
w.on(BI.NumberIntervalSingleEidtor.EVENT_FOCUS, function () { |
|
self._setTitle(""); |
|
switch (self._checkValidation()) { |
|
case c.typeError: |
|
BI.Bubbles.show(c.typeError, BI.i18nText("BI-Numerical_Interval_Input_Data"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
break; |
|
case c.numberError: |
|
BI.Bubbles.show(c.numberError, BI.i18nText("BI-Numerical_Interval_Number_Value"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
break; |
|
case c.signalError: |
|
BI.Bubbles.show(c.signalError, BI.i18nText("BI-Numerical_Interval_Signal_Value"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
break; |
|
default : |
|
return; |
|
} |
|
|
|
}); |
|
}, |
|
_setBlurEvent: function (w) { |
|
var c = this.constants, self = this; |
|
w.on(BI.NumberIntervalSingleEidtor.EVENT_BLUR, function () { |
|
BI.Bubbles.hide(c.typeError); |
|
BI.Bubbles.hide(c.numberError); |
|
BI.Bubbles.hide(c.signalError); |
|
switch (self._checkValidation()) { |
|
case c.typeError: |
|
self._setTitle(BI.i18nText("BI-Numerical_Interval_Input_Data")); |
|
break; |
|
case c.numberError: |
|
self._setTitle(BI.i18nText("BI-Numerical_Interval_Number_Value")); |
|
break; |
|
case c.signalError: |
|
self._setTitle(BI.i18nText("BI-Numerical_Interval_Signal_Value")); |
|
break; |
|
default: |
|
self._setTitle(""); |
|
} |
|
}); |
|
}, |
|
|
|
_setErrorEvent: function (w) { |
|
var c = this.constants, self = this; |
|
w.on(BI.NumberIntervalSingleEidtor.EVENT_ERROR, function () { |
|
self._checkValidation(); |
|
BI.Bubbles.show(c.typeError, BI.i18nText("BI-Numerical_Interval_Input_Data"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
self.fireEvent(BI.NumberInterval.EVENT_ERROR); |
|
}); |
|
}, |
|
|
|
|
|
_setValidEvent: function (w) { |
|
var self = this, c = this.constants; |
|
w.on(BI.NumberIntervalSingleEidtor.EVENT_VALID, function () { |
|
switch (self._checkValidation()) { |
|
case c.numberError: |
|
BI.Bubbles.show(c.numberError, BI.i18nText("BI-Numerical_Interval_Number_Value"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
self.fireEvent(BI.NumberInterval.EVENT_ERROR); |
|
break; |
|
case c.signalError: |
|
BI.Bubbles.show(c.signalError, BI.i18nText("BI-Numerical_Interval_Signal_Value"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
self.fireEvent(BI.NumberInterval.EVENT_ERROR); |
|
break; |
|
default: |
|
self.fireEvent(BI.NumberInterval.EVENT_VALID); |
|
} |
|
}); |
|
}, |
|
|
|
|
|
_setEditorValueChangedEvent: function (w) { |
|
var self = this, c = this.constants; |
|
w.on(BI.NumberIntervalSingleEidtor.EVENT_CHANGE, function () { |
|
switch (self._checkValidation()) { |
|
case c.typeError: |
|
BI.Bubbles.show(c.typeError, BI.i18nText("BI-Numerical_Interval_Input_Data"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
break; |
|
case c.numberError: |
|
BI.Bubbles.show(c.numberError, BI.i18nText("BI-Numerical_Interval_Number_Value"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
break; |
|
case c.signalError: |
|
BI.Bubbles.show(c.signalError, BI.i18nText("BI-Numerical_Interval_Signal_Value"), self, { |
|
offsetStyle: "left", |
|
adjustYOffset: c.adjustYOffset |
|
}); |
|
break; |
|
default : |
|
break; |
|
} |
|
self.fireEvent(BI.NumberInterval.EVENT_CHANGE); |
|
}); |
|
w.on(BI.NumberIntervalSingleEidtor.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.NumberInterval.EVENT_CONFIRM); |
|
}); |
|
}, |
|
|
|
_setComboValueChangedEvent: function (w) { |
|
var self = this, c = this.constants; |
|
w.on(BI.IconCombo.EVENT_CHANGE, function () { |
|
switch (self._checkValidation()) { |
|
case c.typeError: |
|
self._setTitle(BI.i18nText("BI-Numerical_Interval_Input_Data")); |
|
self.fireEvent(BI.NumberInterval.EVENT_ERROR); |
|
break; |
|
case c.numberError: |
|
self._setTitle(BI.i18nText("BI-Numerical_Interval_Number_Value")); |
|
self.fireEvent(BI.NumberInterval.EVENT_ERROR); |
|
break; |
|
case c.signalError: |
|
self._setTitle(BI.i18nText("BI-Numerical_Interval_Signal_Value")); |
|
self.fireEvent(BI.NumberInterval.EVENT_ERROR); |
|
break; |
|
default : |
|
self.fireEvent(BI.NumberInterval.EVENT_CHANGE); |
|
self.fireEvent(BI.NumberInterval.EVENT_CONFIRM); |
|
self.fireEvent(BI.NumberInterval.EVENT_VALID); |
|
} |
|
}); |
|
}, |
|
|
|
isStateValid: function () { |
|
return this.options.validation === "valid"; |
|
}, |
|
|
|
setMinEnable: function (b) { |
|
this.smallEditor.setEnable(b); |
|
}, |
|
|
|
setCloseMinEnable: function (b) { |
|
this.smallCombo.setEnable(b); |
|
}, |
|
|
|
setMaxEnable: function (b) { |
|
this.bigEditor.setEnable(b); |
|
}, |
|
|
|
setCloseMaxEnable: function (b) { |
|
this.bigCombo.setEnable(b); |
|
}, |
|
|
|
showNumTip: function () { |
|
this.smallTip.setVisible(true); |
|
this.bigTip.setVisible(true); |
|
}, |
|
|
|
hideNumTip: function () { |
|
this.smallTip.setVisible(false); |
|
this.bigTip.setVisible(false); |
|
}, |
|
|
|
setNumTip: function (numTip) { |
|
this.smallTip.setText(numTip); |
|
this.bigTip.setText(numTip); |
|
}, |
|
|
|
getNumTip: function () { |
|
return this.smallTip.getText(); |
|
}, |
|
|
|
setValue: function (data) { |
|
data = data || {}; |
|
var self = this, combo_value; |
|
if (BI.isNumeric(data.min) || BI.isEmptyString(data.min)) { |
|
self.smallEditor.setValue(data.min); |
|
} |
|
|
|
if (!BI.isNotNull(data.min)) { |
|
self.smallEditor.setValue(""); |
|
} |
|
|
|
if (BI.isNumeric(data.max) || BI.isEmptyString(data.max)) { |
|
self.bigEditor.setValue(data.max); |
|
} |
|
|
|
if (!BI.isNotNull(data.max)) { |
|
self.bigEditor.setValue(""); |
|
} |
|
|
|
if (!BI.isNull(data.closeMin)) { |
|
if (data.closeMin === true) { |
|
combo_value = 1; |
|
} else { |
|
combo_value = 0; |
|
} |
|
self.smallCombo.setValue(combo_value); |
|
} |
|
|
|
if (!BI.isNull(data.closeMax)) { |
|
if (data.closeMax === true) { |
|
combo_value = 1; |
|
} else { |
|
combo_value = 0; |
|
} |
|
self.bigCombo.setValue(combo_value); |
|
} |
|
|
|
this._checkValidation(); |
|
}, |
|
|
|
|
|
getValue: function () { |
|
var self = this, value = {}, minComboValue = self.smallCombo.getValue(), maxComboValue = self.bigCombo.getValue(); |
|
value.min = self.smallEditor.getValue(); |
|
value.max = self.bigEditor.getValue(); |
|
if (minComboValue[0] === 0) { |
|
value.closeMin = false; |
|
} else { |
|
value.closeMin = true; |
|
} |
|
|
|
if (maxComboValue[0] === 0) { |
|
value.closeMax = false; |
|
} else { |
|
value.closeMax = true; |
|
} |
|
return value; |
|
}, |
|
|
|
destroyed: function () { |
|
var c = this.constants; |
|
BI.Bubbles.remove(c.typeError); |
|
BI.Bubbles.remove(c.numberError); |
|
BI.Bubbles.remove(c.signalError); |
|
} |
|
}); |
|
BI.NumberInterval.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.NumberInterval.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.NumberInterval.EVENT_VALID = "EVENT_VALID"; |
|
BI.NumberInterval.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.shortcut("bi.number_interval", BI.NumberInterval);BI.NumberIntervalSingleEidtor = BI.inherit(BI.Single, { |
|
props: { |
|
baseCls: "bi-number-interval-single-editor", |
|
tipType: "success", |
|
title: "" |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
|
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.editor", |
|
ref: function (_ref) { |
|
self.editor = _ref; |
|
}, |
|
height: o.height - 2, |
|
watermark: o.watermark, |
|
allowBlank: o.allowBlank, |
|
value: o.value, |
|
quitChecker: o.quitChecker, |
|
validationChecker: o.validationChecker, |
|
listeners: [{ |
|
eventName: BI.Editor.EVENT_ERROR, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_ERROR, arguments); |
|
} |
|
}, { |
|
eventName: BI.Editor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_FOCUS, arguments); |
|
} |
|
}, { |
|
eventName: BI.Editor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_BLUR, arguments); |
|
} |
|
}, { |
|
eventName: BI.Editor.EVENT_VALID, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_VALID, arguments); |
|
} |
|
}, { |
|
eventName: BI.Editor.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_CHANGE, arguments); |
|
} |
|
}, { |
|
eventName: BI.Editor.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_CONFIRM, arguments); |
|
} |
|
}, { |
|
eventName: BI.Editor.EVENT_CHANGE_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.NumberIntervalSingleEidtor.EVENT_CHANGE_CONFIRM, arguments); |
|
} |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
return this.editor.setValue(v); |
|
} |
|
}); |
|
|
|
BI.NumberIntervalSingleEidtor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.NumberIntervalSingleEidtor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.NumberIntervalSingleEidtor.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.NumberIntervalSingleEidtor.EVENT_VALID = "EVENT_VALID"; |
|
BI.NumberIntervalSingleEidtor.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.NumberIntervalSingleEidtor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.NumberIntervalSingleEidtor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.number_interval_single_editor", BI.NumberIntervalSingleEidtor);/** |
|
* |
|
* @class BI.SearchMultiTextValueCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.SearchMultiTextValueCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SearchMultiTextValueCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-combo bi-search-multi-text-value-combo", |
|
height: 24, |
|
items: [] |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SearchMultiTextValueCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, self._startValue) : BI.pushDistinct(self.storeValue.value, self._startValue)); |
|
self._updateAllValue(); |
|
self._checkError(); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
self.trigger.getCounter().setButtonChecked(self.storeValue); |
|
}; |
|
this.storeValue = BI.deepClone(o.value || {}); |
|
this._updateAllValue(); |
|
|
|
this._assertValue(this.storeValue); |
|
this._checkError(); |
|
|
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.search_multi_select_trigger", |
|
text: o.text, |
|
height: o.height, |
|
// adapter: this.popup, |
|
masker: { |
|
offset: { |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 25 |
|
} |
|
}, |
|
allValueGetter: function () { |
|
return self.allValue; |
|
}, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
self._itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(BI.deepClone(self.getValue())); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
value: this.storeValue, |
|
warningTitle: o.warningTitle |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_START, function () { |
|
self._setStartValue(""); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_STOP, function () { |
|
self._setStartValue(""); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_PAUSE, function () { |
|
if (this.getSearcher().hasMatched()) { |
|
var keyword = this.getSearcher().getKeyword(); |
|
self._join({ |
|
type: BI.Selection.Multi, |
|
value: [keyword] |
|
}, function () { |
|
self.combo.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self._populate(); |
|
self._setStartValue(""); |
|
}); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(""); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_CHANGE, function (value, obj) { |
|
if (obj instanceof BI.MultiSelectBar) { |
|
self._joinAll(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} else { |
|
self._join(this.getValue(), function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW, function () { |
|
this.getCounter().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.MultiSelectTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
toggle: false, |
|
container: o.container, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.search_multi_select_popup_view", |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.MultiSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
}); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CONFIRM, |
|
action: function () { |
|
self._defaultState(); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectPopupView.EVENT_CLICK_CLEAR, |
|
action: function () { |
|
self.setValue(); |
|
self._defaultState(); |
|
} |
|
}], |
|
itemsCreator: BI.bind(self._itemsCreator, this), |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.trigger.getCounter().adjustView(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
value: o.value, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0; |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self._populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self.trigger.stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
/** |
|
* 在存在标红的情况,如果popover没有发生改变就确认需要同步trigger的值,否则对外value值和trigger样式不统一 |
|
*/ |
|
assertShowValue(); |
|
self.fireEvent(BI.SearchMultiTextValueCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "multi-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
self.trigger.getCounter().hideView(); |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this._checkError(); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
var o = this.options; |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
BI.remove(val.value, function (idx, value) { |
|
return !BI.contains(BI.map(o.items, "value"), value); |
|
}); |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
this._itemsCreator({ |
|
type: BI.SearchMultiTextValueCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Multi ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_joinAll: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this.requesting = true; |
|
this._itemsCreator({ |
|
type: BI.SearchMultiTextValueCombo.REQ_GET_ALL_DATA, |
|
keywords: [this.trigger.getKey()] |
|
}, function (ob) { |
|
var items = BI.map(ob.items, "value"); |
|
if (self.storeValue.type === res.type) { |
|
var change = false; |
|
var map = self._makeMap(self.storeValue.value); |
|
BI.each(items, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (self.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
var selectedMap = self._makeMap(self.storeValue.value); |
|
var notSelectedMap = self._makeMap(res.value); |
|
var newItems = []; |
|
BI.each(items, function (i, item) { |
|
if (BI.isNotNull(selectedMap[items[i]])) { |
|
self.storeValue.assist && self.storeValue.assist.push(selectedMap[items[i]]); |
|
delete selectedMap[items[i]]; |
|
} |
|
if (BI.isNull(notSelectedMap[items[i]])) { |
|
BI.remove(self.storeValue.assist, item); |
|
newItems.push(item); |
|
} |
|
}); |
|
self.storeValue.value = newItems.concat(BI.values(selectedMap)); |
|
self._adjust(callback); |
|
}); |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
if (!this._count) { |
|
this._itemsCreator({ |
|
type: BI.SearchMultiTextValueCombo.REQ_GET_DATA_LENGTH |
|
}, function (res) { |
|
self._count = res.count; |
|
adjust(); |
|
callback(); |
|
}); |
|
} else { |
|
adjust(); |
|
callback(); |
|
|
|
} |
|
|
|
function adjust () { |
|
if (self.storeValue.type === BI.Selection.All && self.storeValue.value.length >= self._count) { |
|
self.storeValue = { |
|
type: BI.Selection.Multi, |
|
value: [] |
|
}; |
|
} else if (self.storeValue.type === BI.Selection.Multi && self.storeValue.value.length >= self._count) { |
|
self.storeValue = { |
|
type: BI.Selection.All, |
|
value: [] |
|
}; |
|
} |
|
self._updateAllValue(); |
|
self._checkError(); |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.SearchMultiTextValueCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_join: function (res, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(res); |
|
this._assertValue(this.storeValue); |
|
if (this.storeValue.type === res.type) { |
|
var map = this._makeMap(this.storeValue.value); |
|
BI.each(res.value, function (i, v) { |
|
if (!map[v]) { |
|
self.storeValue.value.push(v); |
|
BI.remove(self.storeValue.assist, v); |
|
map[v] = v; |
|
} |
|
}); |
|
var change = false; |
|
BI.each(res.assist, function (i, v) { |
|
if (BI.isNotNull(map[v])) { |
|
change = true; |
|
self.storeValue.assist && self.storeValue.assist.push(map[v]); |
|
delete map[v]; |
|
} |
|
}); |
|
change && (this.storeValue.value = BI.values(map)); |
|
self._adjust(callback); |
|
return; |
|
} |
|
this._joinAll(res, callback); |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
_getItemsByTimes: function (items, times) { |
|
var res = []; |
|
for (var i = (times - 1) * 100; items[i] && i < times * 100; i++) { |
|
res.push(items[i]); |
|
} |
|
return res; |
|
}, |
|
|
|
_hasNextByTimes: function (items, times) { |
|
return times * 100 < items.length; |
|
}, |
|
|
|
_itemsCreator: function (options, callback) { |
|
var self = this, o = this.options; |
|
var items = o.items; |
|
var keywords = (options.keywords || []).slice(); |
|
if (options.keyword) { |
|
keywords.push(options.keyword); |
|
} |
|
BI.each(keywords, function (i, kw) { |
|
var search = BI.Func.getSearchResult(items, kw); |
|
items = search.match.concat(search.find); |
|
}); |
|
if (options.selectedValues) {// 过滤 |
|
var filter = BI.makeObject(options.selectedValues, true); |
|
items = BI.filter(items, function (i, ob) { |
|
return !filter[ob.value]; |
|
}); |
|
} |
|
if (options.type == BI.MultiSelectCombo.REQ_GET_ALL_DATA) { |
|
callback({ |
|
items: items |
|
}); |
|
return; |
|
} |
|
if (options.type == BI.MultiSelectCombo.REQ_GET_DATA_LENGTH) { |
|
callback({count: items.length}); |
|
return; |
|
} |
|
callback({ |
|
items: self._getItemsByTimes(items, options.times), |
|
hasNext: self._hasNextByTimes(items, options.times) |
|
}); |
|
}, |
|
|
|
_checkError: function () { |
|
var v = this.storeValue.value || []; |
|
if(BI.isNotEmptyArray(v)) { |
|
v = BI.isArray(v) ? v : [v]; |
|
var result = BI.find(this.allValue, function (idx, value) { |
|
return !BI.contains(v, value); |
|
}); |
|
if (BI.isNull(result)) { |
|
BI.isNotNull(this.trigger) && (this.trigger.setTipType("success")); |
|
this.element.removeClass("combo-error"); |
|
} else { |
|
BI.isNotNull(this.trigger) && (this.trigger.setTipType("warning")); |
|
this.element.addClass("combo-error"); |
|
} |
|
} else { |
|
if(v.length === this.allValue.length){ |
|
BI.isNotNull(this.trigger) && (this.trigger.setTipType("success")); |
|
this.element.removeClass("combo-error"); |
|
}else { |
|
BI.isNotNull(this.trigger) && (this.trigger.setTipType("warning")); |
|
this.element.addClass("combo-error"); |
|
} |
|
} |
|
}, |
|
|
|
_updateAllValue: function () { |
|
this.storeValue = this.storeValue || {}; |
|
this.allValue = BI.deepClone(this.storeValue.value || []); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = BI.deepClone(v || {}); |
|
this._updateAllValue(); |
|
this._assertValue(this.storeValue); |
|
this.combo.setValue(this.storeValue); |
|
this._checkError(); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue); |
|
}, |
|
|
|
_populate: function () { |
|
this._count = null; |
|
this.combo.populate(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this._populate(); |
|
} |
|
}); |
|
|
|
BI.extend(BI.SearchMultiTextValueCombo, { |
|
REQ_GET_DATA_LENGTH: 1, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.SearchMultiTextValueCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.search_multi_text_value_combo", BI.SearchMultiTextValueCombo); |
|
BI.SearchMultiSelectTrigger = BI.inherit(BI.Trigger, { |
|
|
|
constants: { |
|
height: 14, |
|
rgap: 4, |
|
lgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SearchMultiSelectTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-trigger bi-border", |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
searcher: {}, |
|
switcher: {}, |
|
|
|
adapter: null, |
|
masker: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SearchMultiSelectTrigger.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
if (o.height) { |
|
this.setHeight(o.height - 2); |
|
} |
|
|
|
this.searcher = BI.createWidget(o.searcher, { |
|
type: "bi.search_multi_select_searcher", |
|
height: o.height, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
allValueGetter: o.allValueGetter, |
|
popup: {}, |
|
adapter: o.adapter, |
|
masker: o.masker, |
|
value: o.value, |
|
text: o.text, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_START, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_START); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_SEARCHING, arguments); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.MultiSelectSearcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_CHANGE, arguments); |
|
}); |
|
this.numberCounter = BI.createWidget(o.switcher, { |
|
type: "bi.multi_select_check_selected_switcher", |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: o.itemsCreator, |
|
adapter: o.adapter, |
|
masker: o.masker, |
|
value: o.value |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_TRIGGER_CHANGE, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_COUNTER_CLICK); |
|
}); |
|
this.numberCounter.on(BI.MultiSelectCheckSelectedSwitcher.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.fireEvent(BI.SearchMultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW); |
|
}); |
|
|
|
var wrapNumberCounter = BI.createWidget({ |
|
type: "bi.right_vertical_adapt", |
|
hgap: 4, |
|
items: [{ |
|
el: this.numberCounter |
|
}] |
|
}); |
|
|
|
var wrapper = BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [ |
|
{ |
|
el: this.searcher, |
|
width: "fill" |
|
}, { |
|
el: wrapNumberCounter, |
|
width: 0 |
|
}, { |
|
el: BI.createWidget(), |
|
width: 24 |
|
}] |
|
}); |
|
|
|
this.numberCounter.on(BI.Events.VIEW, function (b) { |
|
BI.nextTick(function () {// 自动调整宽度 |
|
wrapper.attr("items")[1].width = (b === true ? self.numberCounter.element.outerWidth() + 8 : 0); |
|
wrapper.resize(); |
|
}); |
|
}); |
|
|
|
this.element.click(function (e) { |
|
if (self.element.find(e.target).length > 0) { |
|
self.numberCounter.hideView(); |
|
} |
|
}); |
|
}, |
|
|
|
getCounter: function () { |
|
return this.numberCounter; |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
this.numberCounter.hideView(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
this.numberCounter.setAdapter(adapter); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.searcher.setValue(ob); |
|
this.numberCounter.setValue(ob); |
|
}, |
|
|
|
setTipType: function (v) { |
|
this.searcher.setTipType(v); |
|
}, |
|
|
|
getKey: function () { |
|
return this.searcher.getKey(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
|
|
BI.SearchMultiSelectTrigger.EVENT_TRIGGER_CLICK = "EVENT_TRIGGER_CLICK"; |
|
BI.SearchMultiSelectTrigger.EVENT_COUNTER_CLICK = "EVENT_COUNTER_CLICK"; |
|
BI.SearchMultiSelectTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SearchMultiSelectTrigger.EVENT_START = "EVENT_START"; |
|
BI.SearchMultiSelectTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.SearchMultiSelectTrigger.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SearchMultiSelectTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.SearchMultiSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW = "EVENT_BEFORE_COUNTER_POPUPVIEW"; |
|
|
|
BI.shortcut("bi.search_multi_select_trigger", BI.SearchMultiSelectTrigger); |
|
/** |
|
* 多选加载数据面板 |
|
* Created by guy on 15/11/2. |
|
* @class BI.SearchMultiSelectLoader |
|
* @extends Widget |
|
*/ |
|
BI.SearchMultiSelectLoader = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SearchMultiSelectLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-loader", |
|
logic: { |
|
dynamic: true |
|
}, |
|
el: { |
|
height: 400 |
|
}, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SearchMultiSelectLoader.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
var hasNext = false; |
|
|
|
this.storeValue = opts.value || {}; |
|
this._assertValue(this.storeValue); |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.select_list", |
|
element: this, |
|
logic: opts.logic, |
|
el: BI.extend({ |
|
onLoaded: opts.onLoaded, |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
el: { |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_MULTI, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
} |
|
}, opts.el), |
|
itemsCreator: function (op, callback) { |
|
var startValue = self._startValue; |
|
self.storeValue && (op = BI.extend(op || {}, { |
|
selectedValues: BI.isKey(startValue) && self.storeValue.type === BI.Selection.Multi |
|
? self.storeValue.value.concat(startValue) : self.storeValue.value |
|
})); |
|
opts.itemsCreator(op, function (ob) { |
|
hasNext = ob.hasNext; |
|
var firstItems = []; |
|
if (op.times === 1 && self.storeValue) { |
|
var json = BI.map(self.storeValue.value, function (i, v) { |
|
var txt = opts.valueFormatter(v) || v; |
|
return { |
|
text: txt, |
|
value: v, |
|
title: txt, |
|
selected: self.storeValue.type === BI.Selection.Multi |
|
}; |
|
}); |
|
if (BI.isKey(self._startValue) && !BI.contains(self.storeValue.value, self._startValue)) { |
|
var txt = opts.valueFormatter(startValue) || startValue; |
|
json.unshift({ |
|
text: txt, |
|
value: startValue, |
|
title: txt, |
|
selected: true |
|
}); |
|
} |
|
firstItems = self._createItems(json); |
|
} |
|
callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || ""); |
|
if (op.times === 1 && self.storeValue) { |
|
BI.isKey(startValue) && (self.storeValue.type === BI.Selection.All ? BI.remove(self.storeValue.value, startValue) : BI.pushDistinct(self.storeValue.value, startValue)); |
|
self.setValue(self.storeValue); |
|
} |
|
(op.times === 1) && self._scrollToTop(); |
|
}); |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
}, |
|
value: this.storeValue |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button_group.on(BI.SelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SearchMultiSelectLoader.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: "bi.multi_select_item", |
|
logic: this.options.logic, |
|
cls: "bi-list-item-active", |
|
height: 24, |
|
selected: this.isAllSelected(), |
|
iconWrapperWidth: 36 |
|
}); |
|
}, |
|
|
|
_scrollToTop: function () { |
|
var self = this; |
|
BI.delay(function () { |
|
self.button_group.element.scrollTop(0); |
|
}, 30); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.button_group.isAllSelected(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
val || (val = {}); |
|
val.type || (val.type = BI.Selection.Multi); |
|
val.value || (val.value = []); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this._startValue = v; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v || {}; |
|
this._assertValue(this.storeValue); |
|
this.button_group.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
arguments[0] = this._createItems(items); |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.button_group.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.button_group.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.SearchMultiSelectLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.search_multi_select_loader", BI.SearchMultiSelectLoader);BI.SearchMultiSelectPopupView = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SearchMultiSelectPopupView.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-popup-view", |
|
maxWidth: "auto", |
|
minWidth: 135, |
|
maxHeight: 400, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SearchMultiSelectPopupView.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options; |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.search_multi_select_loader", |
|
itemsCreator: opts.itemsCreator, |
|
valueFormatter: opts.valueFormatter, |
|
onLoaded: opts.onLoaded, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView = BI.createWidget({ |
|
type: "bi.multi_popup_view", |
|
stopPropagation: false, |
|
maxWidth: opts.maxWidth, |
|
minWidth: opts.minWidth, |
|
maxHeight: opts.maxHeight, |
|
element: this, |
|
buttons: [BI.i18nText("BI-Basic_Clears"), BI.i18nText("BI-Basic_Sure")], |
|
el: this.loader, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView.on(BI.MultiPopupView.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SearchMultiSelectPopupView.EVENT_CHANGE); |
|
}); |
|
this.popupView.on(BI.MultiPopupView.EVENT_CLICK_TOOLBAR_BUTTON, function (index) { |
|
switch (index) { |
|
case 0: |
|
self.fireEvent(BI.SearchMultiSelectPopupView.EVENT_CLICK_CLEAR); |
|
break; |
|
case 1: |
|
self.fireEvent(BI.SearchMultiSelectPopupView.EVENT_CLICK_CONFIRM); |
|
break; |
|
} |
|
}); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.loader.isAllSelected(); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this.loader.setStartValue(v); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popupView.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popupView.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.popupView.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.popupView.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.SearchMultiSelectPopupView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SearchMultiSelectPopupView.EVENT_CLICK_CONFIRM = "EVENT_CLICK_CONFIRM"; |
|
BI.SearchMultiSelectPopupView.EVENT_CLICK_CLEAR = "EVENT_CLICK_CLEAR"; |
|
|
|
|
|
BI.shortcut("bi.search_multi_select_popup_view", BI.SearchMultiSelectPopupView);BI.SearchMultiSelectSearcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SearchMultiSelectSearcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-searcher", |
|
itemsCreator: BI.emptyFn, |
|
el: {}, |
|
popup: {}, |
|
valueFormatter: BI.emptyFn, |
|
adapter: null, |
|
masker: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SearchMultiSelectSearcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.multi_select_editor", |
|
height: o.height, |
|
text: o.text, |
|
tipType: o.tipType, |
|
warningTitle: o.warningTitle |
|
}); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
element: this, |
|
height: o.height, |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
el: this.editor, |
|
|
|
popup: BI.extend({ |
|
type: "bi.multi_select_search_pane", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
var keyword = self.editor.getValue(); |
|
op.keywords = [keyword]; |
|
this.setKeyword(keyword); |
|
o.itemsCreator(op, callback); |
|
}, |
|
value: o.value |
|
}, o.popup), |
|
|
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_START, function () { |
|
self.fireEvent(BI.SearchMultiSelectSearcher.EVENT_START); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { |
|
if (this.hasMatched()) { |
|
|
|
} |
|
self.fireEvent(BI.SearchMultiSelectSearcher.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.SearchMultiSelectSearcher.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SearchMultiSelectSearcher.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_SEARCHING, function () { |
|
var keywords = this.getKeywords(); |
|
self.fireEvent(BI.SearchMultiSelectSearcher.EVENT_SEARCHING, keywords); |
|
}); |
|
if(BI.isNotNull(o.value)) { |
|
this.setState(o.value); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.searcher.adjustView(); |
|
}, |
|
|
|
isSearching: function () { |
|
return this.searcher.isSearching(); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getKeyword: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.searcher.hasMatched(); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.searcher.getView() && this.searcher.getView().hasChecked(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setState: function (obj) { |
|
var o = this.options; |
|
var ob = {}; |
|
ob.type = obj.type; |
|
ob.value = o.allValueGetter() || []; |
|
ob.assist = obj.assist; |
|
if (ob.type === BI.Selection.All) { |
|
if (ob.value.length === 0) { |
|
this.editor.setState(BI.Selection.All); |
|
} else if (BI.size(ob.assist) <= 20) { |
|
var state = ""; |
|
BI.each(ob.assist, function (i, v) { |
|
if (i === 0) { |
|
state += "" + (o.valueFormatter(v + "") || v); |
|
} else { |
|
state += "," + (o.valueFormatter(v + "") || v); |
|
} |
|
}); |
|
this.editor.setState(state); |
|
} else { |
|
this.editor.setState(BI.Selection.Multi); |
|
} |
|
} else { |
|
if (ob.value.length === 0) { |
|
this.editor.setState(BI.Selection.None); |
|
} else if (BI.size(ob.value) <= 20) { |
|
var state = ""; |
|
BI.each(ob.value, function (i, v) { |
|
if (i === 0) { |
|
state += "" + (o.valueFormatter(v + "") || v); |
|
} else { |
|
state += "," + (o.valueFormatter(v + "") || v); |
|
} |
|
}); |
|
this.editor.setState(state); |
|
} else { |
|
this.editor.setState(BI.Selection.Multi); |
|
} |
|
} |
|
}, |
|
|
|
setTipType: function (v) { |
|
this.editor.setTipType(v); |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.setState(ob); |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
} |
|
}); |
|
|
|
BI.SearchMultiSelectSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.SearchMultiSelectSearcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SearchMultiSelectSearcher.EVENT_START = "EVENT_START"; |
|
BI.SearchMultiSelectSearcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.SearchMultiSelectSearcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SearchMultiSelectSearcher.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.shortcut("bi.search_multi_select_searcher", BI.SearchMultiSelectSearcher); |
|
/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.SelectTreeFirstPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.SelectTreeFirstPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.SelectTreeFirstPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-select-tree-first-plus-group-node bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SelectTreeFirstPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.first_tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.SelectTreeFirstPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.select_tree_first_plus_group_node", BI.SelectTreeFirstPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.SelectTreeLastPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.SelectTreeLastPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.SelectTreeLastPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-select-tree-last-plus-group-node bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SelectTreeLastPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.last_tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.SelectTreeLastPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.select_tree_last_plus_group_node", BI.SelectTreeLastPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.SelectTreeMidPlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.SelectTreeMidPlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.SelectTreeMidPlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-select-tree-mid-plus-group-node bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SelectTreeMidPlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.mid_tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.SelectTreeMidPlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.select_tree_mid_plus_group_node", BI.SelectTreeMidPlusGroupNode);/** |
|
* 加号表示的组节点 |
|
* Created by GUY on 2015/9/6. |
|
* @class BI.SelectTreePlusGroupNode |
|
* @extends BI.NodeButton |
|
*/ |
|
BI.SelectTreePlusGroupNode = BI.inherit(BI.NodeButton, { |
|
_defaultConfig: function () { |
|
var conf = BI.SelectTreePlusGroupNode.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-select-tree-plus-group-node bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
id: "", |
|
pId: "", |
|
readonly: true, |
|
open: false, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SelectTreePlusGroupNode.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.checkbox = BI.createWidget({ |
|
type: "bi.tree_node_checkbox", |
|
stopPropagation: true |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
value: o.value, |
|
keyword: o.keyword, |
|
py: o.py |
|
}); |
|
this.checkbox.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.triggerExpand(); |
|
} else { |
|
self.triggerCollapse(); |
|
} |
|
} |
|
}); |
|
var type = BI.LogicFactory.createLogicTypeByDirection(BI.Direction.Left); |
|
var items = BI.LogicFactory.createLogicItemsByDirection(BI.Direction.Left, { |
|
width: 24, |
|
el: this.checkbox |
|
}, this.text); |
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(type, BI.extend(o.logic, { |
|
items: items |
|
})))); |
|
}, |
|
|
|
isOnce: function () { |
|
return true; |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.NodeButton.superclass.doClick.apply(this, arguments); |
|
}, |
|
|
|
setOpened: function (v) { |
|
BI.SelectTreePlusGroupNode.superclass.setOpened.apply(this, arguments); |
|
if (BI.isNotNull(this.checkbox)) { |
|
this.checkbox.setSelected(v); |
|
} |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.select_tree_plus_group_node", BI.SelectTreePlusGroupNode);/** |
|
* @class BI.SelectTreeCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.SelectTreeCombo = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SelectTreeCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-tree-combo", |
|
height: 24, |
|
text: "", |
|
items: [], |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SelectTreeCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.single_tree_trigger", |
|
text: o.text, |
|
height: o.height, |
|
items: o.items, |
|
value: o.value |
|
}); |
|
|
|
this.popup = BI.createWidget({ |
|
type: "bi.select_level_tree", |
|
items: o.items, |
|
value: o.value |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
element: this, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.popup.on(BI.SingleTreePopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.combo.populate(items); |
|
} |
|
}); |
|
|
|
|
|
BI.shortcut("bi.select_tree_combo", BI.SelectTreeCombo);/** |
|
* @class BI.SelectTreeExpander |
|
* @extends BI.Widget |
|
*/ |
|
BI.SelectTreeExpander = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SelectTreeExpander.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-tree-expander", |
|
trigger: "", |
|
toggle: true, |
|
direction: "bottom", |
|
isDefaultInit: true, |
|
el: {}, |
|
popup: {} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SelectTreeExpander.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.trigger = BI.createWidget(o.el); |
|
this.trigger.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
if (this.isSelected()) { |
|
self.expander.setValue([]); |
|
} |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.expander = BI.createWidget({ |
|
type: "bi.expander", |
|
element: this, |
|
trigger: o.trigger, |
|
toggle: o.toggle, |
|
direction: o.direction, |
|
isDefaultInit: o.isDefaultInit, |
|
el: this.trigger, |
|
popup: o.popup |
|
}); |
|
this.expander.on(BI.Controller.EVENT_CHANGE, function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.trigger.setSelected(false); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.expander.getAllLeaves(); |
|
}, |
|
|
|
setValue: function (v) { |
|
if (BI.contains(v, this.trigger.getValue())) { |
|
this.trigger.setSelected(true); |
|
this.expander.setValue([]); |
|
} else { |
|
this.trigger.setSelected(false); |
|
this.expander.setValue(v); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
if (this.trigger.isSelected()) { |
|
return [this.trigger.getValue()]; |
|
} |
|
return this.expander.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.expander.populate(items); |
|
} |
|
}); |
|
|
|
BI.shortcut("bi.select_tree_expander", BI.SelectTreeExpander);/** |
|
* @class BI.SelectTreePopup |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.SelectTreePopup = BI.inherit(BI.Pane, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SelectTreePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-level-tree", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
items: [], |
|
value: "" |
|
}); |
|
}, |
|
|
|
_formatItems: function (nodes, layer, pNode) { |
|
var self = this; |
|
BI.each(nodes, function (i, node) { |
|
var extend = {layer: layer}; |
|
node.id = node.id || BI.UUID(); |
|
extend.pNode = pNode; |
|
if (node.isParent === true || node.parent === true || BI.isNotEmptyArray(node.children)) { |
|
extend.type = "bi.select_tree_mid_plus_group_node"; |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.select_tree_last_plus_group_node"; |
|
extend.isLastNode = true; |
|
} |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.select_tree_first_plus_group_node" |
|
} |
|
if (i === 0 && i === nodes.length - 1) { // 根 |
|
extend.type = "bi.select_tree_plus_group_node"; |
|
} |
|
BI.defaults(node, extend); |
|
self._formatItems(node.children, layer + 1, node); |
|
} else { |
|
extend.type = "bi.mid_tree_leaf_item"; |
|
if (i === 0 && !pNode) { |
|
extend.type = "bi.first_tree_leaf_item" |
|
} |
|
if (i === nodes.length - 1) { |
|
extend.type = "bi.last_tree_leaf_item"; |
|
} |
|
BI.defaults(node, extend); |
|
} |
|
}); |
|
return nodes; |
|
}, |
|
|
|
_init: function () { |
|
BI.SelectTreePopup.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
this.tree = BI.createWidget({ |
|
type: "bi.level_tree", |
|
expander: { |
|
type: "bi.select_tree_expander", |
|
isDefaultInit: true |
|
}, |
|
items: this._formatItems(BI.Tree.transformToTreeFormat(o.items), 0), |
|
value: o.value, |
|
chooseType: BI.Selection.Single |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
vgap: 5, |
|
items: [this.tree] |
|
}); |
|
|
|
this.tree.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.tree.on(BI.LevelTree.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SelectTreePopup.EVENT_CHANGE); |
|
}); |
|
|
|
this.check(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.tree.setValue(v); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.SelectTreePopup.superclass.populate.apply(this, arguments); |
|
this.tree.populate(this._formatItems(BI.Tree.transformToTreeFormat(items))); |
|
} |
|
}); |
|
|
|
BI.SelectTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.select_level_tree", BI.SelectTreePopup);/** |
|
* 单选加载数据搜索loader面板 |
|
* Created by guy on 15/11/4. |
|
* @class BI.SingleSelectSearchLoader |
|
* @extends Widget |
|
*/ |
|
BI.SingleSelectSearchLoader = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectSearchLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-search-loader", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
keywordGetter: BI.emptyFn, |
|
valueFormatter: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectSearchLoader.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
var hasNext = false; |
|
|
|
this.button_group = BI.createWidget({ |
|
type: "bi.single_select_list", |
|
allowNoSelect: opts.allowNoSelect, |
|
element: this, |
|
logic: { |
|
dynamic: false |
|
}, |
|
value: opts.value, |
|
el: { |
|
tipText: BI.i18nText("BI-No_Select"), |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
el: { |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
} |
|
}, |
|
itemsCreator: function (op, callback) { |
|
self.storeValue && (op = BI.extend(op || {}, { |
|
selectedValues: [self.storeValue] |
|
})); |
|
opts.itemsCreator(op, function (ob) { |
|
var keyword = ob.keyword = opts.keywordGetter(); |
|
hasNext = ob.hasNext; |
|
var firstItems = []; |
|
if (op.times === 1 && BI.isNotNull(self.storeValue)) { |
|
var json = self._filterValues(self.storeValue); |
|
firstItems = self._createItems(json); |
|
} |
|
callback(firstItems.concat(self._createItems(ob.items)), keyword || ""); |
|
if (op.times === 1 && self.storeValue) { |
|
self.setValue(self.storeValue); |
|
} |
|
}); |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
} |
|
}); |
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button_group.on(BI.SingleSelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SingleSelectSearchLoader.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: this.options.allowNoSelect ? "bi.single_select_item" : "bi.single_select_combo_item", |
|
cls: "bi-list-item-active", |
|
logic: { |
|
dynamic: false |
|
}, |
|
height: 25, |
|
selected: false |
|
}); |
|
}, |
|
|
|
_filterValues: function (src) { |
|
var o = this.options; |
|
var keyword = o.keywordGetter(); |
|
var values = src || []; |
|
var newValues = BI.map(BI.isArray(values) ? values : [values], function (i, v) { |
|
return { |
|
text: o.valueFormatter(v) || v, |
|
value: v |
|
}; |
|
}); |
|
if (BI.isKey(keyword)) { |
|
var search = BI.Func.getSearchResult(newValues, keyword); |
|
values = search.match.concat(search.find); |
|
} |
|
return BI.map(values, function (i, v) { |
|
return { |
|
text: v.text, |
|
title: v.text, |
|
value: v.value, |
|
selected: false |
|
}; |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
// 暂存的值一定是新的值,不然v改掉后,storeValue也跟着改了 |
|
this.storeValue = v; |
|
this.button_group.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.button_group.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.button_group.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.SingleSelectSearchLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_search_loader", BI.SingleSelectSearchLoader);/** |
|
* |
|
* 在搜索框中输入文本弹出的面板 |
|
* @class BI.SingleSelectSearchInsertPane |
|
* @extends Widget |
|
*/ |
|
|
|
BI.SingleSelectSearchInsertPane = BI.inherit(BI.Widget, { |
|
|
|
constants: { |
|
height: 25, |
|
lgap: 10, |
|
tgap: 5 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectSearchInsertPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-search-pane bi-card", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
keywordGetter: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectSearchInsertPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.tooltipClick = BI.createWidget({ |
|
type: "bi.label", |
|
invisible: true, |
|
text: BI.i18nText("BI-Click_Blank_To_Select"), |
|
cls: "multi-select-toolbar", |
|
height: this.constants.height |
|
}); |
|
|
|
this.addNotMatchTip = BI.createWidget({ |
|
type: "bi.text_button", |
|
invisible: true, |
|
text: BI.i18nText("BI-Basic_Click_To_Add_Text", ""), |
|
height: this.constants.height, |
|
cls: "bi-high-light", |
|
hgap: 5, |
|
handler: function () { |
|
self.fireEvent(BI.SingleSelectSearchInsertPane.EVENT_ADD_ITEM, o.keywordGetter()); |
|
} |
|
}); |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.single_select_search_loader", |
|
allowNoSelect: o.allowNoSelect, |
|
keywordGetter: o.keywordGetter, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator.apply(self, [op, function (res) { |
|
callback(res); |
|
self.setKeyword(o.keywordGetter()); |
|
}]); |
|
}, |
|
value: o.value |
|
}); |
|
this.loader.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.resizer = BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
type: "bi.vertical", |
|
items: [this.tooltipClick, this.addNotMatchTip], |
|
height: this.constants.height |
|
}, { |
|
el: this.loader |
|
}] |
|
}); |
|
}, |
|
|
|
setKeyword: function (keyword) { |
|
var btn; |
|
var isMatchTipVisible = this.loader.getAllButtons().length > 0 && (btn = this.loader.getAllButtons()[0]) && (keyword === btn.getValue()); |
|
this.tooltipClick.setVisible(isMatchTipVisible); |
|
this.addNotMatchTip.setVisible(!isMatchTipVisible); |
|
!isMatchTipVisible && this.addNotMatchTip.setText(BI.i18nText("BI-Basic_Click_To_Add_Text", keyword)); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.tooltipClick.isVisible(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.loader.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.loader.getValue(); |
|
}, |
|
|
|
empty: function () { |
|
this.loader.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.loader.populate.apply(this.loader, arguments); |
|
} |
|
}); |
|
|
|
BI.SingleSelectSearchInsertPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SingleSelectSearchInsertPane.EVENT_ADD_ITEM = "EVENT_ADD_ITEM"; |
|
|
|
BI.shortcut("bi.single_select_search_insert_pane", BI.SingleSelectSearchInsertPane);/** |
|
* |
|
* 在搜索框中输入文本弹出的面板 |
|
* @class BI.SingleSelectSearchPane |
|
* @extends Widget |
|
*/ |
|
|
|
BI.SingleSelectSearchPane = BI.inherit(BI.Widget, { |
|
|
|
constants: { |
|
height: 25, |
|
lgap: 10, |
|
tgap: 5 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectSearchPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-search-pane bi-card", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
keywordGetter: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectSearchPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.tooltipClick = BI.createWidget({ |
|
type: "bi.label", |
|
invisible: true, |
|
text: BI.i18nText("BI-Click_Blank_To_Select"), |
|
cls: "multi-select-toolbar", |
|
height: this.constants.height |
|
}); |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.single_select_search_loader", |
|
allowNoSelect: o.allowNoSelect, |
|
keywordGetter: o.keywordGetter, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator.apply(self, [op, function (res) { |
|
callback(res); |
|
self.setKeyword(o.keywordGetter()); |
|
}]); |
|
}, |
|
value: o.value |
|
}); |
|
this.loader.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.resizer = BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.tooltipClick, |
|
height: 0 |
|
}, { |
|
el: this.loader |
|
}] |
|
}); |
|
this.tooltipClick.setVisible(false); |
|
}, |
|
|
|
setKeyword: function (keyword) { |
|
var btn; |
|
var isVisible = this.loader.getAllButtons().length > 0 && (btn = this.loader.getAllButtons()[0]) && (keyword === btn.getValue()); |
|
if (isVisible !== this.tooltipClick.isVisible()) { |
|
this.tooltipClick.setVisible(isVisible); |
|
this.resizer.attr("items")[0].height = (isVisible ? this.constants.height : 0); |
|
this.resizer.resize(); |
|
} |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.tooltipClick.isVisible(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.loader.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.loader.getValue(); |
|
}, |
|
|
|
empty: function () { |
|
this.loader.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.loader.populate.apply(this.loader, arguments); |
|
} |
|
}); |
|
|
|
BI.SingleSelectSearchPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
BI.shortcut("bi.single_select_search_pane", BI.SingleSelectSearchPane);/** |
|
* |
|
* @class BI.SingleSelectCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.SingleSelectCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-combo", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue = self._startValue); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
}; |
|
this.storeValue = o.value; |
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.single_select_trigger", |
|
height: o.height, |
|
// adapter: this.popup, |
|
allowNoSelect: o.allowNoSelect, |
|
allowEdit: o.allowEdit, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(self.getValue()); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
text: o.text, |
|
value: this.storeValue |
|
}); |
|
|
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_START, function () { |
|
self._setStartValue(); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_STOP, function () { |
|
self._setStartValue(); |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_STOP); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_PAUSE, function () { |
|
if (this.getSearcher().hasMatched()) { |
|
var keyword = this.getSearcher().getKeyword(); |
|
self.combo.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.populate(); |
|
self._setStartValue(); |
|
} |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_CHANGE, function (value, obj) { |
|
self.storeValue = this.getValue(); |
|
assertShowValue(); |
|
self._defaultState(); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
toggle: false, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.single_select_popup_view", |
|
allowNoSelect: o.allowNoSelect, |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.SingleSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
self._defaultState(); |
|
}); |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_CLICK_ITEM); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0; |
|
}, |
|
value: o.value |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self.populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self.trigger.stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "single-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) {}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.SingleSelectCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
if (!this._count) { |
|
o.itemsCreator({ |
|
type: BI.SingleSelectCombo.REQ_GET_DATA_LENGTH |
|
}, function (res) { |
|
self._count = res.count; |
|
adjust(); |
|
callback(); |
|
}); |
|
} else { |
|
adjust(); |
|
callback(); |
|
|
|
} |
|
|
|
function adjust () { |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.SingleSelectCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this._assertValue(this.storeValue); |
|
this.combo.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
populate: function () { |
|
this._count = null; |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.SingleSelectCombo, { |
|
REQ_GET_DATA_LENGTH: 0, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.SingleSelectCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SingleSelectCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SingleSelectCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.SingleSelectCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.SingleSelectCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.SingleSelectCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.single_select_combo", BI.SingleSelectCombo); |
|
/** |
|
* |
|
* @class BI.SingleSelectInsertCombo |
|
* @extends BI.Single |
|
*/ |
|
BI.SingleSelectInsertCombo = BI.inherit(BI.Single, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectInsertCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-combo", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectInsertCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue = self._startValue); |
|
self.trigger.getSearcher().setState(self.storeValue); |
|
}; |
|
this.storeValue = o.value; |
|
// 标记正在请求数据 |
|
this.requesting = false; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.single_select_trigger", |
|
height: o.height, |
|
allowNoSelect: o.allowNoSelect, |
|
allowEdit: o.allowEdit, |
|
// adapter: this.popup, |
|
valueFormatter: o.valueFormatter, |
|
itemsCreator: function (op, callback) { |
|
o.itemsCreator(op, function (res) { |
|
if (op.times === 1 && BI.isNotNull(op.keywords)) { |
|
// 预防trigger内部把当前的storeValue改掉 |
|
self.trigger.setValue(self.getValue()); |
|
} |
|
callback.apply(self, arguments); |
|
}); |
|
}, |
|
text: o.text, |
|
value: this.storeValue, |
|
searcher: { |
|
popup: { |
|
type: "bi.single_select_search_insert_pane", |
|
listeners: [{ |
|
eventName: BI.SingleSelectSearchInsertPane.EVENT_ADD_ITEM, |
|
action: function () { |
|
if (!self.trigger.getSearcher().hasMatched()) { |
|
self.storeValue = self.trigger.getSearcher().getKeyword(); |
|
assertShowValue(); |
|
self._defaultState(); |
|
} |
|
} |
|
}] |
|
} |
|
} |
|
}); |
|
|
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_FOCUS); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_BLUR); |
|
}); |
|
|
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_START, function () { |
|
self._setStartValue(); |
|
this.getSearcher().setValue(self.storeValue); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_STOP, function () { |
|
self._setStartValue(); |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_STOP); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_PAUSE, function () { |
|
if (this.getSearcher().hasMatched()) { |
|
var keyword = this.getSearcher().getKeyword(); |
|
self.storeValue = keyword; |
|
self.combo.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.populate(); |
|
self._setStartValue(); |
|
} |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_SEARCHING, function (keywords) { |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.combo.populate(); |
|
self._setStartValue(); |
|
} else { |
|
self.combo.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_SEARCHING); |
|
}); |
|
|
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_CHANGE, function (value, obj) { |
|
self.storeValue = this.getValue(); |
|
assertShowValue(); |
|
self._defaultState(); |
|
}); |
|
this.trigger.on(BI.SingleSelectTrigger.EVENT_COUNTER_CLICK, function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
toggle: false, |
|
el: this.trigger, |
|
adjustLength: 1, |
|
popup: { |
|
type: "bi.single_select_popup_view", |
|
allowNoSelect: o.allowNoSelect, |
|
ref: function () { |
|
self.popup = this; |
|
self.trigger.setAdapter(this); |
|
}, |
|
listeners: [{ |
|
eventName: BI.SingleSelectPopupView.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self._adjust(function () { |
|
assertShowValue(); |
|
self._defaultState(); |
|
}); |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_CLICK_ITEM); |
|
} |
|
}], |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
onLoaded: function () { |
|
BI.nextTick(function () { |
|
self.combo.adjustWidth(); |
|
self.combo.adjustHeight(); |
|
self.trigger.getSearcher().adjustView(); |
|
}); |
|
} |
|
}, |
|
hideChecker: function (e) { |
|
return triggerBtn.element.find(e.target).length === 0; |
|
}, |
|
value: o.value |
|
}); |
|
|
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
this.setValue(self.storeValue); |
|
BI.nextTick(function () { |
|
self.populate(); |
|
}); |
|
}); |
|
// 当退出的时候如果还在处理请求,则等请求结束后再对外发确定事件 |
|
this.wants2Quit = false; |
|
this.combo.on(BI.Combo.EVENT_AFTER_HIDEVIEW, function () { |
|
// important:关闭弹出时又可能没有退出编辑状态 |
|
self.trigger.stopEditing(); |
|
if (self.requesting === true) { |
|
self.wants2Quit = true; |
|
} else { |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
var triggerBtn = BI.createWidget({ |
|
type: "bi.trigger_icon_button", |
|
width: o.height, |
|
height: o.height, |
|
cls: "single-select-trigger-icon-button" |
|
}); |
|
triggerBtn.on(BI.TriggerIconButton.EVENT_CHANGE, function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.combo, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: triggerBtn, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
this.combo.hideView(); |
|
}, |
|
|
|
_assertValue: function (val) { |
|
}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
this.requesting = true; |
|
o.itemsCreator({ |
|
type: BI.SingleSelectInsertCombo.REQ_GET_ALL_DATA, |
|
keywords: keywords |
|
}, function (ob) { |
|
var values = BI.map(ob.items, "value"); |
|
digest(values); |
|
}); |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
self._adjust(callback); |
|
} |
|
}, |
|
|
|
_adjust: function (callback) { |
|
var self = this, o = this.options; |
|
adjust(); |
|
callback(); |
|
|
|
function adjust () { |
|
if (self.wants2Quit === true) { |
|
self.fireEvent(BI.SingleSelectInsertCombo.EVENT_CONFIRM); |
|
self.wants2Quit = false; |
|
} |
|
self.requesting = false; |
|
} |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.popup.setStartValue(value); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this._assertValue(this.storeValue); |
|
this.combo.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
populate: function () { |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.SingleSelectInsertCombo, { |
|
REQ_GET_DATA_LENGTH: 0, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.SingleSelectInsertCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SingleSelectInsertCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SingleSelectInsertCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.SingleSelectInsertCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.SingleSelectInsertCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.SingleSelectInsertCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
|
|
BI.shortcut("bi.single_select_insert_combo", BI.SingleSelectInsertCombo);BI.SingleSelectComboItem = BI.inherit(BI.BasicButton, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectComboItem.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-single-select-radio-item", |
|
logic: { |
|
dynamic: false |
|
}, |
|
height: 24 |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSelectComboItem.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.radio = BI.createWidget({ |
|
type: "bi.radio" |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.label", |
|
cls: "list-item-text", |
|
textAlign: "left", |
|
whiteSpace: "nowrap", |
|
textHeight: o.height, |
|
height: o.height, |
|
hgap: o.hgap, |
|
text: o.text, |
|
keyword: o.keyword, |
|
value: o.value, |
|
py: o.py |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, { |
|
items: BI.LogicFactory.createLogicItemsByDirection("left", { |
|
type: "bi.center_adapt", |
|
items: [this.radio], |
|
width: 26 |
|
}, this.text) |
|
})))); |
|
}, |
|
|
|
doRedMark: function () { |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doClick: function () { |
|
BI.SingleSelectComboItem.superclass.doClick.apply(this, arguments); |
|
this.radio.setSelected(this.isSelected()); |
|
if (this.isValid()) { |
|
this.fireEvent(BI.SingleSelectComboItem.EVENT_CHANGE, this.isSelected(), this); |
|
} |
|
}, |
|
|
|
setSelected: function (v) { |
|
BI.SingleSelectComboItem.superclass.setSelected.apply(this, arguments); |
|
this.radio.setSelected(v); |
|
|
|
} |
|
}); |
|
BI.SingleSelectComboItem.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_combo_item", BI.SingleSelectComboItem);/** |
|
* 选择列表 |
|
* |
|
* Created by GUY on 2015/11/1. |
|
* @class BI.SingleSelectList |
|
* @extends BI.Widget |
|
*/ |
|
BI.SingleSelectList = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-select-list", |
|
direction: BI.Direction.Top, // toolbar的位置 |
|
logic: { |
|
dynamic: true |
|
}, |
|
items: [], |
|
itemsCreator: BI.emptyFn, |
|
hasNext: BI.emptyFn, |
|
onLoaded: BI.emptyFn, |
|
el: { |
|
type: "bi.list_pane" |
|
}, |
|
allowNoSelect: false |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSelectList.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.list = BI.createWidget(o.el, { |
|
type: "bi.list_pane", |
|
items: o.items, |
|
itemsCreator: function (op, callback) { |
|
op.times === 1 && self.toolbar && self.toolbar.setVisible(false); |
|
o.itemsCreator(op, function (items) { |
|
callback.apply(self, arguments); |
|
if (op.times === 1) { |
|
self.toolbar && self.toolbar.setVisible(items && items.length > 0); |
|
self.toolbar && self.toolbar.setEnable(items && items.length > 0); |
|
} |
|
}); |
|
}, |
|
onLoaded: o.onLoaded, |
|
hasNext: o.hasNext, |
|
value: o.value |
|
}); |
|
|
|
this.list.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) { |
|
if (type === BI.Events.CLICK) { |
|
self.fireEvent(BI.SingleSelectList.EVENT_CHANGE, value, obj); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
BI.createWidget(BI.extend({ |
|
element: this |
|
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({ |
|
scrolly: true |
|
}, o.logic, { |
|
items: o.allowNoSelect ? BI.LogicFactory.createLogicItemsByDirection(o.direction, { |
|
type: "bi.single_select_item", |
|
cls: "bi-list-item-active", |
|
height: 24, |
|
forceNotSelected: true, |
|
text: BI.i18nText("BI-Basic_No_Select"), |
|
ref: function (_ref) { |
|
self.toolbar = _ref; |
|
}, |
|
listeners: [{ |
|
eventName: BI.Controller.EVENT_CHANGE, |
|
action: function (type) { |
|
if (type === BI.Events.CLICK) { |
|
self.list.setValue(); |
|
self.fireEvent(BI.SingleSelectList.EVENT_CHANGE); |
|
} |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
} |
|
}] |
|
}, this.list) : BI.LogicFactory.createLogicItemsByDirection(o.direction, this.list) |
|
})))); |
|
|
|
}, |
|
|
|
hasPrev: function () { |
|
return this.list.hasPrev(); |
|
}, |
|
|
|
hasNext: function () { |
|
return this.list.hasNext(); |
|
}, |
|
|
|
prependItems: function (items) { |
|
this.list.prependItems.apply(this.list, arguments); |
|
}, |
|
|
|
addItems: function (items) { |
|
this.list.addItems.apply(this.list, arguments); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.list.setValue([v]); |
|
}, |
|
|
|
getValue: function () { |
|
return this.list.getValue()[0]; |
|
}, |
|
|
|
empty: function () { |
|
this.list.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.list.populate.apply(this.list, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.list.resetHeight ? this.list.resetHeight(h) : |
|
this.list.element.css({"max-height": h + "px"}); |
|
}, |
|
|
|
setNotSelectedValue: function () { |
|
this.list.setNotSelectedValue.apply(this.list, arguments); |
|
}, |
|
|
|
getNotSelectedValue: function () { |
|
return this.list.getNotSelectedValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.list.getAllButtons(); |
|
}, |
|
|
|
getAllLeaves: function () { |
|
return this.list.getAllLeaves(); |
|
}, |
|
|
|
getSelectedButtons: function () { |
|
return this.list.getSelectedButtons(); |
|
}, |
|
|
|
getNotSelectedButtons: function () { |
|
return this.list.getNotSelectedButtons(); |
|
}, |
|
|
|
getIndexByValue: function (value) { |
|
return this.list.getIndexByValue(value); |
|
}, |
|
|
|
getNodeById: function (id) { |
|
return this.list.getNodeById(id); |
|
}, |
|
|
|
getNodeByValue: function (value) { |
|
return this.list.getNodeByValue(value); |
|
} |
|
}); |
|
BI.SingleSelectList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_list", BI.SingleSelectList);/** |
|
* 单选加载数据面板 |
|
* Created by guy on 15/11/2. |
|
* @class BI.SingleSelectLoader |
|
* @extends Widget |
|
*/ |
|
BI.SingleSelectLoader = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectLoader.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-loader", |
|
logic: { |
|
dynamic: true |
|
}, |
|
el: { |
|
height: 400 |
|
}, |
|
allowNoSelect: false, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectLoader.superclass._init.apply(this, arguments); |
|
|
|
var self = this, opts = this.options; |
|
var hasNext = false; |
|
this.storeValue = opts.value; |
|
this.button_group = BI.createWidget({ |
|
type: "bi.single_select_list", |
|
allowNoSelect: opts.allowNoSelect, |
|
logic: opts.logic, |
|
el: BI.extend({ |
|
onLoaded: opts.onLoaded, |
|
el: { |
|
type: "bi.loader", |
|
isDefaultInit: false, |
|
logic: { |
|
dynamic: true, |
|
scrolly: true |
|
}, |
|
el: { |
|
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE, |
|
behaviors: { |
|
redmark: function () { |
|
return true; |
|
} |
|
}, |
|
layouts: [{ |
|
type: "bi.vertical" |
|
}] |
|
} |
|
} |
|
}, opts.el), |
|
itemsCreator: function (op, callback) { |
|
var startValue = self._startValue; |
|
BI.isNotNull(self.storeValue) && (op = BI.extend(op || {}, { |
|
selectedValues: [self.storeValue] |
|
})); |
|
opts.itemsCreator(op, function (ob) { |
|
hasNext = ob.hasNext; |
|
var firstItems = []; |
|
if (op.times === 1 && BI.isNotNull(self.storeValue)) { |
|
var json = BI.map([self.storeValue], function (i, v) { |
|
var txt = opts.valueFormatter(v) || v; |
|
return { |
|
text: txt, |
|
value: v, |
|
title: txt, |
|
selected: true |
|
}; |
|
}); |
|
firstItems = self._createItems(json); |
|
} |
|
callback(firstItems.concat(self._createItems(ob.items)), ob.keyword || ""); |
|
if (op.times === 1 && self.storeValue) { |
|
BI.isKey(startValue) && (self.storeValue = startValue); |
|
self.setValue(self.storeValue); |
|
} |
|
(op.times === 1) && self._scrollToTop(); |
|
}); |
|
}, |
|
hasNext: function () { |
|
return hasNext; |
|
}, |
|
value: this.storeValue |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
items: [this.button_group], |
|
vgap: 5 |
|
}); |
|
|
|
this.button_group.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.button_group.on(BI.SingleSelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SingleSelectLoader.EVENT_CHANGE, arguments); |
|
}); |
|
}, |
|
|
|
_createItems: function (items) { |
|
return BI.createItems(items, { |
|
type: this.options.allowNoSelect ? "bi.single_select_item" : "bi.single_select_combo_item", |
|
logic: this.options.logic, |
|
cls: "bi-list-item-active", |
|
height: 24, |
|
selected: false |
|
}); |
|
}, |
|
|
|
_scrollToTop: function () { |
|
var self = this; |
|
BI.delay(function () { |
|
self.button_group.element.scrollTop(0); |
|
}, 30); |
|
}, |
|
|
|
_assertValue: function (val) {}, |
|
|
|
setStartValue: function (v) { |
|
this._startValue = v; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this._assertValue(this.storeValue); |
|
this.button_group.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return this.button_group.getValue(); |
|
}, |
|
|
|
getAllButtons: function () { |
|
return this.button_group.getAllButtons(); |
|
}, |
|
|
|
empty: function () { |
|
this.button_group.empty(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.button_group.populate.apply(this.button_group, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.button_group.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.button_group.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.SingleSelectLoader.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_loader", BI.SingleSelectLoader); |
|
/** |
|
* 带加载的单选下拉面板 |
|
* @class BI.SingleSelectPopupView |
|
* @extends Widget |
|
*/ |
|
BI.SingleSelectPopupView = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectPopupView.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-popup-view", |
|
allowNoSelect: false, |
|
maxWidth: "auto", |
|
minWidth: 135, |
|
maxHeight: 400, |
|
valueFormatter: BI.emptyFn, |
|
itemsCreator: BI.emptyFn, |
|
onLoaded: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectPopupView.superclass._init.apply(this, arguments); |
|
var self = this, opts = this.options; |
|
|
|
this.loader = BI.createWidget({ |
|
type: "bi.single_select_loader", |
|
allowNoSelect: opts.allowNoSelect, |
|
itemsCreator: opts.itemsCreator, |
|
valueFormatter: opts.valueFormatter, |
|
onLoaded: opts.onLoaded, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView = BI.createWidget({ |
|
type: "bi.popup_view", |
|
stopPropagation: false, |
|
maxWidth: opts.maxWidth, |
|
minWidth: opts.minWidth, |
|
maxHeight: opts.maxHeight, |
|
element: this, |
|
el: this.loader, |
|
value: opts.value |
|
}); |
|
|
|
this.popupView.on(BI.MultiPopupView.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SingleSelectPopupView.EVENT_CHANGE); |
|
}); |
|
}, |
|
|
|
setStartValue: function (v) { |
|
this.loader.setStartValue(v); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.popupView.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popupView.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.popupView.populate.apply(this.popupView, arguments); |
|
}, |
|
|
|
resetHeight: function (h) { |
|
this.popupView.resetHeight(h); |
|
}, |
|
|
|
resetWidth: function (w) { |
|
this.popupView.resetWidth(w); |
|
} |
|
}); |
|
|
|
BI.SingleSelectPopupView.EVENT_CHANGE = "EVENT_CHANGE"; |
|
|
|
|
|
BI.shortcut("bi.single_select_popup_view", BI.SingleSelectPopupView);/** |
|
* |
|
* 单选下拉框 |
|
* @class BI.SingleSelectTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
|
|
BI.SingleSelectTrigger = BI.inherit(BI.Trigger, { |
|
|
|
constants: { |
|
height: 14, |
|
rgap: 4, |
|
lgap: 4 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-trigger bi-border bi-border-radius", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn, |
|
searcher: {}, |
|
switcher: {}, |
|
|
|
adapter: null, |
|
masker: {}, |
|
allowEdit: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectTrigger.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
if (o.height) { |
|
this.setHeight(o.height - 2); |
|
} |
|
|
|
this.searcher = BI.createWidget(o.searcher, { |
|
type: "bi.single_select_searcher", |
|
allowNoSelect: o.allowNoSelect, |
|
text: o.text, |
|
height: o.height, |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
popup: {}, |
|
adapter: o.adapter, |
|
masker: o.masker, |
|
value: o.value |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_START, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_START); |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_SEARCHING, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_SEARCHING, arguments); |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_FOCUS); |
|
}); |
|
this.searcher.on(BI.SingleSelectSearcher.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SingleSelectTrigger.EVENT_BLUR, arguments); |
|
}); |
|
|
|
var wrapper = BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
items: [ |
|
{ |
|
el: this.searcher, |
|
width: "fill" |
|
}, { |
|
el: BI.createWidget(), |
|
width: 24 |
|
}] |
|
}); |
|
|
|
!o.allowEdit && BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.text", |
|
title: function () { |
|
return self.searcher.getState(); |
|
} |
|
}, |
|
left: 0, |
|
right: 24, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
getSearcher: function () { |
|
return this.searcher; |
|
}, |
|
|
|
stopEditing: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.searcher.setValue(v); |
|
}, |
|
|
|
getKey: function () { |
|
return this.searcher.getKey(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
} |
|
}); |
|
|
|
BI.SingleSelectTrigger.EVENT_TRIGGER_CLICK = "EVENT_TRIGGER_CLICK"; |
|
BI.SingleSelectTrigger.EVENT_COUNTER_CLICK = "EVENT_COUNTER_CLICK"; |
|
BI.SingleSelectTrigger.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SingleSelectTrigger.EVENT_START = "EVENT_START"; |
|
BI.SingleSelectTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.SingleSelectTrigger.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SingleSelectTrigger.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.SingleSelectTrigger.EVENT_BEFORE_COUNTER_POPUPVIEW = "EVENT_BEFORE_COUNTER_POPUPVIEW"; |
|
BI.SingleSelectTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SingleSelectTrigger.EVENT_BLUR = "EVENT_BLUR"; |
|
|
|
BI.shortcut("bi.single_select_trigger", BI.SingleSelectTrigger);/** |
|
* @author: Teller |
|
* @createdAt: 2018/3/28 |
|
* @Description |
|
*/ |
|
BI.SingleSelectInsertList = BI.inherit(BI.Single, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectInsertList.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-multi-select-insert-list", |
|
allowNoSelect: false, |
|
itemsCreator: BI.emptyFn, |
|
valueFormatter: BI.emptyFn |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSelectInsertList.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
this.storeValue = o.value; |
|
|
|
var assertShowValue = function () { |
|
BI.isKey(self._startValue) && (self.storeValue = self._startValue); |
|
// self.trigger.setValue(self.storeValue); |
|
}; |
|
|
|
this.adapter = BI.createWidget({ |
|
type: "bi.single_select_loader", |
|
allowNoSelect: o.allowNoSelect, |
|
cls: "popup-single-select-list bi-border-left bi-border-right bi-border-bottom", |
|
itemsCreator: o.itemsCreator, |
|
valueFormatter: o.valueFormatter, |
|
logic: { |
|
dynamic: true |
|
}, |
|
// onLoaded: o.onLoaded, |
|
el: {}, |
|
value: o.value |
|
}); |
|
this.adapter.on(BI.SingleSelectLoader.EVENT_CHANGE, function () { |
|
self.storeValue = this.getValue(); |
|
assertShowValue(); |
|
self.fireEvent(BI.SingleSelectInsertList.EVENT_CHANGE); |
|
}); |
|
|
|
this.searcherPane = BI.createWidget({ |
|
type: "bi.single_select_search_pane", |
|
allowNoSelect: o.allowNoSelect, |
|
cls: "bi-border-left bi-border-right bi-border-bottom", |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.trigger.getKeyword(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
op.keywords = [self.trigger.getKeyword()]; |
|
this.setKeyword(op.keywords[0]); |
|
o.itemsCreator(op, callback); |
|
} |
|
}); |
|
this.searcherPane.setVisible(false); |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.searcher", |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
adapter: this.adapter, |
|
popup: this.searcherPane, |
|
height: 200, |
|
masker: false, |
|
value: o.value, |
|
listeners: [{ |
|
eventName: BI.Searcher.EVENT_START, |
|
action: function () { |
|
self._showSearcherPane(); |
|
self._setStartValue(); |
|
this.setValue(BI.deepClone(self.storeValue)); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_STOP, |
|
action: function () { |
|
self._showAdapter(); |
|
self._setStartValue(); |
|
self.adapter.setValue(self.storeValue); |
|
// 需要刷新回到初始界面,否则搜索的结果不能放在最前面 |
|
self.adapter.populate(); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_PAUSE, |
|
action: function () { |
|
var keyword = this.getKeyword(); |
|
self.storeValue = keyword; |
|
self._showAdapter(); |
|
self.adapter.setValue(self.storeValue); |
|
self._setStartValue(keyword); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(); |
|
self.fireEvent(BI.SingleSelectInsertList.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_SEARCHING, |
|
action: function () { |
|
var keywords = this.getKeyword(); |
|
var last = BI.last(keywords); |
|
keywords = BI.initial(keywords || []); |
|
if (keywords.length > 0) { |
|
self._joinKeywords(keywords, function () { |
|
if (BI.isEndWithBlank(last)) { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
self.adapter.populate(); |
|
self._setStartValue(); |
|
} else { |
|
self.adapter.setValue(self.storeValue); |
|
assertShowValue(); |
|
} |
|
}); |
|
} |
|
} |
|
}, { |
|
eventName: BI.Searcher.EVENT_CHANGE, |
|
action: function () { |
|
self.storeValue = this.getValue(); |
|
self.fireEvent(BI.SingleSelectInsertList.EVENT_CHANGE); |
|
} |
|
}] |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vtape", |
|
element: this, |
|
items: [{ |
|
el: this.trigger, |
|
height: 24 |
|
}, { |
|
el: this.adapter, |
|
height: "fill" |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.searcherPane, |
|
top: 24, |
|
bottom: 0, |
|
left: 0, |
|
right: 0 |
|
}] |
|
}); |
|
}, |
|
|
|
_showAdapter: function () { |
|
this.adapter.setVisible(true); |
|
this.searcherPane.setVisible(false); |
|
}, |
|
|
|
_showSearcherPane: function () { |
|
this.searcherPane.setVisible(true); |
|
this.adapter.setVisible(false); |
|
}, |
|
|
|
_defaultState: function () { |
|
this.trigger.stopEditing(); |
|
}, |
|
|
|
_assertValue: function () {}, |
|
|
|
_makeMap: function (values) { |
|
return BI.makeObject(values || []); |
|
}, |
|
|
|
_joinKeywords: function (keywords, callback) { |
|
var self = this, o = this.options; |
|
this._assertValue(this.storeValue); |
|
if (!this._allData) { |
|
o.itemsCreator({ |
|
type: BI.SingleSelectInsertList.REQ_GET_ALL_DATA |
|
}, function (ob) { |
|
self._allData = BI.map(ob.items, "value"); |
|
digest(self._allData); |
|
}); |
|
} else { |
|
digest(this._allData); |
|
} |
|
|
|
function digest (items) { |
|
var selectedMap = self._makeMap(items); |
|
BI.each(keywords, function (i, val) { |
|
if (BI.isNotNull(selectedMap[val])) { |
|
self.storeValue.type === BI.Selection.Single ? BI.pushDistinct(self.storeValue.value, val) : BI.remove(self.storeValue.value, val); |
|
} |
|
}); |
|
callback(); |
|
} |
|
}, |
|
|
|
_setStartValue: function (value) { |
|
this._startValue = value; |
|
this.adapter.setStartValue(value); |
|
}, |
|
|
|
isAllSelected: function () { |
|
return this.adapter.isAllSelected(); |
|
}, |
|
|
|
resize: function () { |
|
// this.trigger.getCounter().adjustView(); |
|
// this.trigger.adjustView(); |
|
}, |
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.adapter.setValue(this.storeValue); |
|
this.trigger.setValue(this.storeValue); |
|
}, |
|
|
|
getValue: function () { |
|
return BI.deepClone(this.storeValue); |
|
}, |
|
|
|
populate: function () { |
|
this._count = null; |
|
this._allData = null; |
|
this.adapter.populate.apply(this.adapter, arguments); |
|
this.trigger.populate.apply(this.trigger, arguments); |
|
} |
|
}); |
|
|
|
BI.extend(BI.SingleSelectInsertList, { |
|
REQ_GET_DATA_LENGTH: 0, |
|
REQ_GET_ALL_DATA: -1 |
|
}); |
|
|
|
BI.SingleSelectInsertList.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_select_insert_list", BI.SingleSelectInsertList); |
|
/** |
|
* 单选输入框 |
|
* Created by guy on 15/11/3. |
|
* @class BI.SingleSelectEditor |
|
* @extends Widget |
|
*/ |
|
BI.SingleSelectEditor = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectEditor.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-editor", |
|
el: {}, |
|
text: BI.i18nText("BI-Basic_Please_Select") |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.state_editor", |
|
element: this, |
|
height: o.height, |
|
watermark: BI.i18nText("BI-Basic_Search"), |
|
allowBlank: true, |
|
value: o.value, |
|
defaultText: o.text, |
|
text: o.text, |
|
}); |
|
|
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.editor.on(BI.StateEditor.EVENT_PAUSE, function () { |
|
self.fireEvent(BI.SingleSelectEditor.EVENT_PAUSE); |
|
}); |
|
this.editor.on(BI.StateEditor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.SingleSelectEditor.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.StateEditor.EVENT_BLUR, function () { |
|
self.fireEvent(BI.SingleSelectEditor.EVENT_BLUR); |
|
}); |
|
}, |
|
|
|
focus: function () { |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
}, |
|
|
|
setState: function (state) { |
|
this.editor.setState(state); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
var v = this.editor.getState(); |
|
if (BI.isArray(v) && v.length > 0) { |
|
return v[v.length - 1]; |
|
} |
|
return ""; |
|
|
|
}, |
|
|
|
getKeywords: function () { |
|
var val = this.editor.getLastChangedValue(); |
|
var keywords = val.match(/[\S]+/g); |
|
if (BI.isEndWithBlank(val)) { |
|
return keywords.concat([" "]); |
|
} |
|
return keywords; |
|
}, |
|
|
|
populate: function (items) { |
|
|
|
} |
|
}); |
|
|
|
BI.SingleSelectEditor.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SingleSelectEditor.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SingleSelectEditor.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.shortcut("bi.single_select_editor", BI.SingleSelectEditor);/** |
|
* searcher |
|
* Created by guy on 15/11/3. |
|
* @class BI.SingleSelectSearcher |
|
* @extends Widget |
|
*/ |
|
BI.SingleSelectSearcher = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSelectSearcher.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-select-searcher", |
|
itemsCreator: BI.emptyFn, |
|
el: {}, |
|
popup: {}, |
|
valueFormatter: BI.emptyFn, |
|
adapter: null, |
|
masker: {}, |
|
allowNoSelect: false |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleSelectSearcher.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget(o.el, { |
|
type: "bi.single_select_editor", |
|
height: o.height, |
|
text: o.text, |
|
listeners: [{ |
|
eventName: BI.SingleSelectEditor.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.SingleSelectEditor.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_BLUR); |
|
} |
|
}] |
|
}); |
|
|
|
this.searcher = BI.createWidget({ |
|
type: "bi.searcher", |
|
element: this, |
|
height: o.height, |
|
isAutoSearch: false, |
|
isAutoSync: false, |
|
onSearch: function (op, callback) { |
|
callback(); |
|
}, |
|
el: this.editor, |
|
|
|
popup: BI.extend({ |
|
type: "bi.single_select_search_pane", |
|
allowNoSelect: o.allowNoSelect, |
|
valueFormatter: o.valueFormatter, |
|
keywordGetter: function () { |
|
return self.editor.getValue(); |
|
}, |
|
itemsCreator: function (op, callback) { |
|
var keyword = self.editor.getValue(); |
|
op.keywords = [keyword]; |
|
this.setKeyword(keyword); |
|
o.itemsCreator(op, callback); |
|
}, |
|
value: o.value |
|
}, o.popup), |
|
|
|
adapter: o.adapter, |
|
masker: o.masker |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_START, function () { |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_START); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_PAUSE, function () { |
|
if (this.hasMatched()) { |
|
|
|
} |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_PAUSE); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_STOP, function () { |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_STOP); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_CHANGE, arguments); |
|
}); |
|
this.searcher.on(BI.Searcher.EVENT_SEARCHING, function () { |
|
var keywords = this.getKeywords(); |
|
self.fireEvent(BI.SingleSelectSearcher.EVENT_SEARCHING, keywords); |
|
}); |
|
|
|
if(BI.isNotNull(o.value)){ |
|
this.setState(o.value); |
|
} |
|
}, |
|
|
|
adjustView: function () { |
|
this.searcher.adjustView(); |
|
}, |
|
|
|
isSearching: function () { |
|
return this.searcher.isSearching(); |
|
}, |
|
|
|
stopSearch: function () { |
|
this.searcher.stopSearch(); |
|
}, |
|
|
|
getKeyword: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
hasMatched: function () { |
|
return this.searcher.hasMatched(); |
|
}, |
|
|
|
hasChecked: function () { |
|
return this.searcher.getView() && this.searcher.getView().hasChecked(); |
|
}, |
|
|
|
setAdapter: function (adapter) { |
|
this.searcher.setAdapter(adapter); |
|
}, |
|
|
|
setState: function (v) { |
|
var o = this.options; |
|
if (BI.isNull(v)) { |
|
this.editor.setState(BI.Selection.None); |
|
} else { |
|
this.editor.setState(o.valueFormatter(v + "") || (v + "")); |
|
} |
|
}, |
|
|
|
setValue: function (ob) { |
|
this.setState(ob); |
|
this.searcher.setValue(ob); |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.searcher.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this.searcher.populate.apply(this.searcher, arguments); |
|
} |
|
}); |
|
|
|
BI.SingleSelectSearcher.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.SingleSelectSearcher.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.SingleSelectSearcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.SingleSelectSearcher.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SingleSelectSearcher.EVENT_START = "EVENT_START"; |
|
BI.SingleSelectSearcher.EVENT_STOP = "EVENT_STOP"; |
|
BI.SingleSelectSearcher.EVENT_PAUSE = "EVENT_PAUSE"; |
|
BI.SingleSelectSearcher.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.shortcut("bi.single_select_searcher", BI.SingleSelectSearcher); |
|
BI.SignTextEditor = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
var conf = BI.SignTextEditor.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
baseCls: (conf.baseCls || "") + " bi-sign-initial-editor", |
|
validationChecker: BI.emptyFn, |
|
text: "", |
|
height: 24 |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SignTextEditor.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.editor = BI.createWidget({ |
|
type: "bi.editor", |
|
height: o.height, |
|
hgap: 4, |
|
vgap: 2, |
|
value: o.value, |
|
validationChecker: o.validationChecker, |
|
allowBlank: false |
|
}); |
|
this.text = BI.createWidget({ |
|
type: "bi.text_button", |
|
cls: "sign-editor-text", |
|
title: function () { |
|
return self.getValue(); |
|
}, |
|
textAlign: o.textAlign, |
|
height: o.height, |
|
hgap: 4, |
|
handler: function () { |
|
self._showInput(); |
|
self.editor.focus(); |
|
self.editor.selectAll(); |
|
} |
|
}); |
|
this.text.on(BI.TextButton.EVENT_CHANGE, function () { |
|
BI.nextTick(function () { |
|
self.fireEvent(BI.SignTextEditor.EVENT_CLICK_LABEL); |
|
}); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: this.text, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}); |
|
this.editor.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CONFIRM, function () { |
|
self._showHint(); |
|
self._checkText(); |
|
self.fireEvent(BI.SignTextEditor.EVENT_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_CHANGE_CONFIRM, function () { |
|
self._showHint(); |
|
self._checkText(); |
|
self.fireEvent(BI.SignTextEditor.EVENT_CHANGE_CONFIRM, arguments); |
|
}); |
|
this.editor.on(BI.Editor.EVENT_ERROR, function () { |
|
self._checkText(); |
|
}); |
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
scrolly: false, |
|
element: this, |
|
items: [this.editor] |
|
}); |
|
this._showHint(); |
|
self._checkText(); |
|
}, |
|
|
|
_checkText: function () { |
|
var o = this.options; |
|
BI.nextTick(BI.bind(function () { |
|
if (this.editor.getValue() === "") { |
|
this.text.setValue(o.watermark || ""); |
|
this.text.element.addClass("bi-water-mark"); |
|
} else { |
|
var v = this.editor.getValue(); |
|
v = (BI.isEmpty(v) || v == o.text) ? o.text : v + o.text; |
|
this.text.setValue(v); |
|
this.text.element.removeClass("bi-water-mark"); |
|
} |
|
}, this)); |
|
}, |
|
|
|
_showInput: function () { |
|
this.editor.visible(); |
|
this.text.invisible(); |
|
}, |
|
|
|
_showHint: function () { |
|
this.editor.invisible(); |
|
this.text.visible(); |
|
}, |
|
|
|
setTitle: function (title) { |
|
this.text.setTitle(title); |
|
}, |
|
|
|
setWarningTitle: function (title) { |
|
this.text.setWarningTitle(title); |
|
}, |
|
|
|
focus: function () { |
|
this._showInput(); |
|
this.editor.focus(); |
|
}, |
|
|
|
blur: function () { |
|
this.editor.blur(); |
|
this._showHint(); |
|
this._checkText(); |
|
}, |
|
|
|
doRedMark: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
unRedMark: function () { |
|
this.text.unRedMark.apply(this.text, arguments); |
|
}, |
|
|
|
doHighLight: function () { |
|
if (this.editor.getValue() === "" && BI.isKey(this.options.watermark)) { |
|
return; |
|
} |
|
this.text.doHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
unHighLight: function () { |
|
this.text.unHighLight.apply(this.text, arguments); |
|
}, |
|
|
|
isValid: function () { |
|
return this.editor.isValid(); |
|
}, |
|
|
|
setErrorText: function (text) { |
|
this.editor.setErrorText(text); |
|
}, |
|
|
|
getErrorText: function () { |
|
return this.editor.getErrorText(); |
|
}, |
|
|
|
isEditing: function () { |
|
return this.editor.isEditing(); |
|
}, |
|
|
|
getLastValidValue: function () { |
|
return this.editor.getLastValidValue(); |
|
}, |
|
|
|
getLastChangedValue: function () { |
|
return this.editor.getLastChangedValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.editor.setValue(v); |
|
this._checkText(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
getState: function () { |
|
return this.text.getValue(); |
|
}, |
|
|
|
setState: function (v) { |
|
var o = this.options; |
|
this._showHint(); |
|
v = (BI.isEmpty(v) || v == o.text) ? o.text : v + o.text; |
|
this.text.setValue(v); |
|
} |
|
}); |
|
BI.SignTextEditor.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.SignTextEditor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM"; |
|
BI.SignTextEditor.EVENT_CLICK_LABEL = "EVENT_CLICK_LABEL"; |
|
|
|
BI.shortcut("bi.sign_text_editor", BI.SignTextEditor);/** |
|
* Created by zcf on 2016/9/22. |
|
*/ |
|
BI.SliderIconButton = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-single-slider-button" |
|
}, |
|
|
|
constants: { |
|
LARGE_SIZE: 16, |
|
NORMAL_SIZE: 12, |
|
LARGE_OFFSET: 4, |
|
NORMAL_OFFSET: 6 |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
return { |
|
type: "bi.absolute", |
|
ref: function () { |
|
self.wrapper = this; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.text_button", |
|
cls: "slider-button bi-high-light-border", |
|
ref: function () { |
|
self.slider = this; |
|
} |
|
} |
|
}] |
|
}; |
|
} |
|
}); |
|
BI.shortcut("bi.single_slider_button", BI.SliderIconButton);/** |
|
* Created by zcf on 2016/9/22. |
|
*/ |
|
BI.SingleSlider = BI.inherit(BI.Single, { |
|
_constant: { |
|
EDITOR_WIDTH: 90, |
|
EDITOR_HEIGHT: 30, |
|
SLIDER_WIDTH_HALF: 15, |
|
SLIDER_WIDTH: 30, |
|
SLIDER_HEIGHT: 30, |
|
TRACK_HEIGHT: 24, |
|
TRACK_GAP_HALF: 7, |
|
TRACK_GAP: 14 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-single-slider bi-slider-track", |
|
digit: false, |
|
unit: "" |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
var c = this._constant; |
|
this.enable = false; |
|
this.value = ""; |
|
|
|
this.grayTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "gray-track", |
|
height: 6 |
|
}); |
|
this.blueTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "blue-track bi-high-light-background", |
|
height: 6 |
|
}); |
|
this.track = this._createTrackWrapper(); |
|
|
|
this.slider = BI.createWidget({ |
|
type: "bi.single_slider_button" |
|
}); |
|
this._draggable(this.slider); |
|
var sliderVertical = BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [this.slider] |
|
}], |
|
hgap: c.SLIDER_WIDTH_HALF, |
|
height: c.SLIDER_HEIGHT |
|
}); |
|
// 这边其实是有问题的,拖拽区域是个圆,在圆的边缘拖拽后放开,这边计算出来的蓝条宽度实际上会比放开时长一点或者短一点 |
|
sliderVertical.element.click(function (e) { |
|
if (self.enable && self.isEnabled() && sliderVertical.element[0] === e.originalEvent.target) { |
|
var offset = e.clientX - self.element.offset().left - c.SLIDER_WIDTH_HALF; |
|
var trackLength = self.track.element[0].scrollWidth - c.TRACK_GAP; |
|
var percent = 0; |
|
if (offset < 0) { |
|
percent = 0; |
|
} |
|
if (offset > 0 && offset < trackLength) { |
|
percent = offset * 100 / self._getGrayTrackLength(); |
|
} |
|
if (offset >= trackLength) { |
|
percent = 100; |
|
} |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setAllPosition(significantPercent); |
|
var v = self._getValueByPercent(significantPercent); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
self.label.setValue(v); |
|
self.value = v; |
|
self.fireEvent(BI.SingleSlider.EVENT_CHANGE); |
|
} |
|
}); |
|
this.label = BI.createWidget({ |
|
type: "bi.sign_text_editor", |
|
cls: "slider-editor-button", |
|
text: o.unit, |
|
width: c.EDITOR_WIDTH - 2, |
|
allowBlank: false, |
|
textAlign: "center", |
|
validationChecker: function (v) { |
|
return self._checkValidation(v); |
|
} |
|
}); |
|
this.label.element.hover(function () { |
|
self.label.element.removeClass("bi-border").addClass("bi-border"); |
|
}, function () { |
|
self.label.element.removeClass("bi-border"); |
|
}); |
|
this.label.on(BI.SignEditor.EVENT_CONFIRM, function () { |
|
var v = BI.parseFloat(this.getValue()); |
|
var percent = self._getPercentByValue(v); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setAllPosition(significantPercent); |
|
this.setValue(v); |
|
self.value = v; |
|
self.fireEvent(BI.SingleSlider.EVENT_CHANGE); |
|
}); |
|
this._setVisible(false); |
|
return { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.track, |
|
width: "100%", |
|
height: c.TRACK_HEIGHT |
|
}] |
|
}], |
|
hgap: c.TRACK_GAP_HALF, |
|
height: c.TRACK_HEIGHT |
|
}, |
|
top: 23, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: sliderVertical, |
|
top: 20, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.horizontal_auto", |
|
items: [this.label] |
|
}], |
|
height: c.EDITOR_HEIGHT |
|
}, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}] |
|
}; |
|
}, |
|
|
|
_draggable: function (widget) { |
|
var self = this, o = this.options; |
|
var startDrag = false; |
|
var size = 0, offset = 0, defaultSize = 0; |
|
var mouseMoveTracker = new BI.MouseMoveTracker(function (deltaX) { |
|
if (mouseMoveTracker.isDragging()) { |
|
startDrag = true; |
|
offset += deltaX; |
|
size = optimizeSize(defaultSize + offset); |
|
widget.element.addClass("dragging"); |
|
var percent = size * 100 / (self._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1));// 直接对计算出来的百分数保留到小数点后一位,相当于分成了1000份。 |
|
self._setBlueTrack(significantPercent); |
|
self._setLabelPosition(significantPercent); |
|
self._setSliderPosition(significantPercent); |
|
var v = self._getValueByPercent(significantPercent); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
self.label.setValue(v); |
|
self.value = v; |
|
} |
|
}, function () { |
|
if (startDrag === true) { |
|
size = optimizeSize(size); |
|
var percent = size * 100 / (self._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setSliderPosition(significantPercent); |
|
size = 0; |
|
offset = 0; |
|
defaultSize = size; |
|
startDrag = false; |
|
} |
|
widget.element.removeClass("dragging"); |
|
mouseMoveTracker.releaseMouseMoves(); |
|
self.fireEvent(BI.SingleSlider.EVENT_CHANGE); |
|
}, window); |
|
widget.element.on("mousedown", function (event) { |
|
if(!widget.isEnabled()) { |
|
return; |
|
} |
|
defaultSize = this.offsetLeft; |
|
optimizeSize(defaultSize); |
|
mouseMoveTracker.captureMouseMoves(event); |
|
}); |
|
|
|
function optimizeSize (s) { |
|
return BI.clamp(s, 0, self._getGrayTrackLength()); |
|
} |
|
}, |
|
|
|
_createTrackWrapper: function () { |
|
return BI.createWidget({ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.grayTrack, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: this.blueTrack, |
|
top: 0, |
|
left: 0, |
|
width: "0%" |
|
}] |
|
}], |
|
hgap: 8, |
|
height: 8 |
|
}, |
|
top: 8, |
|
left: 0, |
|
width: "100%" |
|
}] |
|
}); |
|
}, |
|
|
|
_checkValidation: function (v) { |
|
var o = this.options; |
|
var valid = false; |
|
if (BI.isNumeric(v) && !(BI.isNull(v) || v < this.min || v > this.max)) { |
|
if(o.digit === false) { |
|
valid = true; |
|
}else{ |
|
var dotText = (v + "").split(".")[1] || ""; |
|
valid = (dotText.length === o.digit); |
|
} |
|
} |
|
return valid; |
|
}, |
|
|
|
_setBlueTrack: function (percent) { |
|
this.blueTrack.element.css({width: percent + "%"}); |
|
}, |
|
|
|
_setLabelPosition: function (percent) { |
|
// this.label.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setSliderPosition: function (percent) { |
|
this.slider.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setAllPosition: function (percent) { |
|
this._setSliderPosition(percent); |
|
this._setLabelPosition(percent); |
|
this._setBlueTrack(percent); |
|
}, |
|
|
|
_setVisible: function (visible) { |
|
this.slider.setVisible(visible); |
|
this.label.setVisible(visible); |
|
}, |
|
|
|
_getGrayTrackLength: function () { |
|
return this.grayTrack.element[0].scrollWidth; |
|
}, |
|
|
|
_getValueByPercent: function (percent) { |
|
var thousandth = BI.parseInt(percent * 10); |
|
return (((this.max - this.min) * thousandth) / 1000 + this.min); |
|
}, |
|
|
|
_getPercentByValue: function (v) { |
|
return (v - this.min) * 100 / (this.max - this.min); |
|
}, |
|
|
|
getValue: function () { |
|
return this.value; |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
v = BI.parseFloat(v); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
if ((!isNaN(v))) { |
|
if (this._checkValidation(v)) { |
|
this.value = v; |
|
} |
|
if (v > this.max) { |
|
this.value = this.max; |
|
} |
|
if (v < this.min) { |
|
this.value = this.min; |
|
} |
|
} |
|
}, |
|
|
|
_setEnable: function (b) { |
|
BI.SingleSlider.superclass._setEnable.apply(this, [b]); |
|
if(b) { |
|
this.blueTrack.element.removeClass("disabled-blue-track").addClass("blue-track"); |
|
} else { |
|
this.blueTrack.element.removeClass("blue-track").addClass("disabled-blue-track"); |
|
} |
|
}, |
|
|
|
setMinAndMax: function (v) { |
|
var minNumber = BI.parseFloat(v.min); |
|
var maxNumber = BI.parseFloat(v.max); |
|
if ((!isNaN(minNumber)) && (!isNaN(maxNumber)) && (maxNumber > minNumber )) { |
|
this.min = minNumber; |
|
this.max = maxNumber; |
|
} |
|
}, |
|
|
|
reset: function () { |
|
this._setVisible(false); |
|
this.enable = false; |
|
this.value = ""; |
|
this.min = 0; |
|
this.max = 0; |
|
this._setBlueTrack(0); |
|
|
|
}, |
|
|
|
populate: function () { |
|
if (!isNaN(this.min) && !isNaN(this.max)) { |
|
this._setVisible(true); |
|
this.enable = true; |
|
this.label.setErrorText(BI.i18nText("BI-Basic_Please_Enter_Number_Between", this.min, this.max)); |
|
if (BI.isNumeric(this.value) || BI.isNotEmptyString(this.value)) { |
|
this.label.setValue(this.value); |
|
this._setAllPosition(this._getPercentByValue(this.value)); |
|
} else { |
|
this.label.setValue(this.max); |
|
this._setAllPosition(100); |
|
} |
|
} |
|
} |
|
}); |
|
BI.SingleSlider.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_slider", BI.SingleSlider);/** |
|
* Created by Urthur on 2017/9/12. |
|
*/ |
|
BI.SingleSliderLabel = BI.inherit(BI.Single, { |
|
_constant: { |
|
EDITOR_WIDTH: 90, |
|
EDITOR_HEIGHT: 20, |
|
HEIGHT: 20, |
|
SLIDER_WIDTH_HALF: 15, |
|
SLIDER_WIDTH: 30, |
|
SLIDER_HEIGHT: 30, |
|
TRACK_HEIGHT: 24, |
|
TRACK_GAP_HALF: 7, |
|
TRACK_GAP: 14 |
|
}, |
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleSliderLabel.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-slider-label bi-slider-track", |
|
digit: false, |
|
unit: "" |
|
}); |
|
}, |
|
_init: function () { |
|
BI.SingleSliderLabel.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
var c = this._constant; |
|
this.enable = false; |
|
this.value = ""; |
|
|
|
this.grayTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "gray-track", |
|
height: 6 |
|
}); |
|
this.blueTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "blue-track bi-high-light-background", |
|
height: 6 |
|
}); |
|
this.track = this._createTrackWrapper(); |
|
|
|
this.slider = BI.createWidget({ |
|
type: "bi.single_slider_button" |
|
}); |
|
this._draggable(this.slider); |
|
var sliderVertical = BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [this.slider] |
|
}], |
|
hgap: c.SLIDER_WIDTH_HALF, |
|
height: c.SLIDER_HEIGHT |
|
}); |
|
sliderVertical.element.click(function (e) { |
|
if (self.enable && self.isEnabled() && sliderVertical.element[0] === e.originalEvent.target) { |
|
var offset = e.clientX - self.element.offset().left - c.SLIDER_WIDTH_HALF; |
|
var trackLength = self.track.element[0].scrollWidth - c.TRACK_GAP; |
|
var percent = 0; |
|
if (offset < 0) { |
|
percent = 0; |
|
} |
|
if (offset > 0 && offset < trackLength) { |
|
percent = offset * 100 / self._getGrayTrackLength(); |
|
} |
|
if (offset >= trackLength) { |
|
percent = 100; |
|
} |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setAllPosition(significantPercent); |
|
var v = self._getValueByPercent(significantPercent); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
self.label.setText(v + o.unit); |
|
self.value = v; |
|
self.fireEvent(BI.SingleSliderLabel.EVENT_CHANGE); |
|
} |
|
}); |
|
this.label = BI.createWidget({ |
|
type: "bi.label", |
|
height: c.HEIGHT, |
|
width: c.EDITOR_WIDTH - 2 |
|
}); |
|
|
|
this._setVisible(false); |
|
BI.createWidget({ |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.track, |
|
width: "100%", |
|
height: c.TRACK_HEIGHT |
|
}] |
|
}], |
|
hgap: c.TRACK_GAP_HALF, |
|
height: c.TRACK_HEIGHT |
|
}, |
|
top: 13, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: sliderVertical, |
|
top: 10, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.horizontal_auto", |
|
items: [this.label] |
|
}], |
|
height: c.EDITOR_HEIGHT |
|
}, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}] |
|
}); |
|
}, |
|
|
|
_draggable: function (widget) { |
|
var self = this, o = this.options; |
|
var startDrag = false; |
|
var size = 0, offset = 0, defaultSize = 0; |
|
var mouseMoveTracker = new BI.MouseMoveTracker(function (deltaX) { |
|
if (mouseMoveTracker.isDragging()) { |
|
startDrag = true; |
|
offset += deltaX; |
|
size = optimizeSize(defaultSize + offset); |
|
widget.element.addClass("dragging"); |
|
var percent = size * 100 / (self._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1));// 直接对计算出来的百分数保留到小数点后一位,相当于分成了1000份。 |
|
self._setBlueTrack(significantPercent); |
|
self._setLabelPosition(significantPercent); |
|
self._setSliderPosition(significantPercent); |
|
var v = self._getValueByPercent(significantPercent); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
self.label.setValue(v + o.unit); |
|
self.value = v; |
|
self.fireEvent(BI.SingleSliderLabel.EVENT_CHANGE); |
|
} |
|
}, function () { |
|
if (startDrag === true) { |
|
size = optimizeSize(size); |
|
var percent = size * 100 / (self._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setSliderPosition(significantPercent); |
|
size = 0; |
|
offset = 0; |
|
defaultSize = size; |
|
startDrag = false; |
|
} |
|
widget.element.removeClass("dragging"); |
|
mouseMoveTracker.releaseMouseMoves(); |
|
self.fireEvent(BI.SingleSliderLabel.EVENT_CHANGE); |
|
}, window); |
|
widget.element.on("mousedown", function (event) { |
|
if(!widget.isEnabled()) { |
|
return; |
|
} |
|
defaultSize = this.offsetLeft; |
|
optimizeSize(defaultSize); |
|
mouseMoveTracker.captureMouseMoves(event); |
|
}); |
|
|
|
function optimizeSize (s) { |
|
return BI.clamp(s, 0, self._getGrayTrackLength()); |
|
} |
|
}, |
|
|
|
_createTrackWrapper: function () { |
|
return BI.createWidget({ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.grayTrack, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: this.blueTrack, |
|
top: 0, |
|
left: 0, |
|
width: "0%" |
|
}] |
|
}], |
|
hgap: 8, |
|
height: 8 |
|
}, |
|
top: 8, |
|
left: 0, |
|
width: "100%" |
|
}] |
|
}); |
|
}, |
|
|
|
_checkValidation: function (v) { |
|
return BI.isNumeric(v) && !(BI.isNull(v) || v < this.min || v > this.max); |
|
}, |
|
|
|
_setBlueTrack: function (percent) { |
|
this.blueTrack.element.css({width: percent + "%"}); |
|
}, |
|
|
|
_setLabelPosition: function (percent) { |
|
// this.label.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setSliderPosition: function (percent) { |
|
this.slider.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setAllPosition: function (percent) { |
|
this._setSliderPosition(percent); |
|
this._setLabelPosition(percent); |
|
this._setBlueTrack(percent); |
|
}, |
|
|
|
_setVisible: function (visible) { |
|
this.slider.setVisible(visible); |
|
this.label.setVisible(visible); |
|
}, |
|
|
|
_getGrayTrackLength: function () { |
|
return this.grayTrack.element[0].scrollWidth; |
|
}, |
|
|
|
_getValueByPercent: function (percent) { |
|
var thousandth = BI.parseInt(percent * 10); |
|
return (((this.max - this.min) * thousandth) / 1000 + this.min); |
|
}, |
|
|
|
_getPercentByValue: function (v) { |
|
return (v - this.min) * 100 / (this.max - this.min); |
|
}, |
|
|
|
_setEnable: function (b) { |
|
BI.SingleSliderLabel.superclass._setEnable.apply(this, [b]); |
|
if(b) { |
|
this.blueTrack.element.removeClass("disabled-blue-track").addClass("blue-track"); |
|
} else { |
|
this.blueTrack.element.removeClass("blue-track").addClass("disabled-blue-track"); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.value; |
|
}, |
|
|
|
setValue: function (v) { |
|
var o = this.options; |
|
v = BI.parseFloat(v); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
if ((!isNaN(v))) { |
|
if (this._checkValidation(v)) { |
|
this.value = v; |
|
} |
|
if (v > this.max) { |
|
this.value = this.max; |
|
} |
|
if (v < this.min) { |
|
this.value = this.min; |
|
} |
|
} |
|
}, |
|
|
|
setMinAndMax: function (v) { |
|
var minNumber = BI.parseFloat(v.min); |
|
var maxNumber = BI.parseFloat(v.max); |
|
if ((!isNaN(minNumber)) && (!isNaN(maxNumber)) && (maxNumber > minNumber )) { |
|
this.min = minNumber; |
|
this.max = maxNumber; |
|
} |
|
}, |
|
|
|
reset: function () { |
|
this._setVisible(false); |
|
this.enable = false; |
|
this.value = ""; |
|
this.min = 0; |
|
this.max = 0; |
|
this._setBlueTrack(0); |
|
}, |
|
|
|
populate: function () { |
|
var o = this.options; |
|
if (!isNaN(this.min) && !isNaN(this.max)) { |
|
this._setVisible(true); |
|
this.enable = true; |
|
if (BI.isNumeric(this.value) || BI.isNotEmptyString(this.value)) { |
|
this.label.setValue(this.value + o.unit); |
|
this._setAllPosition(this._getPercentByValue(this.value)); |
|
} else { |
|
this.label.setValue(this.max + o.unit); |
|
this._setAllPosition(100); |
|
} |
|
} |
|
} |
|
}); |
|
BI.SingleSliderLabel.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_slider_label", BI.SingleSliderLabel);/** |
|
* normal single slider |
|
* Created by Young on 2017/6/21. |
|
*/ |
|
BI.SingleSliderNormal = BI.inherit(BI.Single, { |
|
|
|
_constant: { |
|
HEIGHT: 28, |
|
SLIDER_WIDTH_HALF: 15, |
|
SLIDER_WIDTH: 30, |
|
SLIDER_HEIGHT: 30, |
|
TRACK_HEIGHT: 24, |
|
TRACK_GAP_HALF: 7, |
|
TRACK_GAP: 14 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-single-slider-normal bi-slider-track", |
|
minMax: { |
|
min: 0, |
|
max: 100 |
|
} |
|
// color: "#3f8ce8" |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
var c = this._constant; |
|
var track = this._createTrack(); |
|
this.slider = BI.createWidget({ |
|
type: "bi.single_slider_button" |
|
}); |
|
this._draggable(this.slider); |
|
|
|
var sliderVertical = BI.createWidget({ |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [this.slider] |
|
}], |
|
hgap: c.SLIDER_WIDTH_HALF, |
|
height: c.SLIDER_HEIGHT |
|
}); |
|
sliderVertical.element.click(function (e) { |
|
if (self.enable && self.isEnabled() && sliderVertical.element[0] === e.originalEvent.target) { |
|
var offset = e.clientX - self.element.offset().left - c.SLIDER_WIDTH_HALF; |
|
var trackLength = self.track.element[0].scrollWidth - c.TRACK_GAP; |
|
var percent = 0; |
|
if (offset < 0) { |
|
percent = 0; |
|
} |
|
if (offset > 0 && offset < trackLength) { |
|
percent = offset * 100 / self._getGrayTrackLength(); |
|
} |
|
if (offset >= trackLength) { |
|
percent = 100; |
|
} |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setAllPosition(significantPercent); |
|
var v = self._getValueByPercent(significantPercent); |
|
self.value = v; |
|
self.fireEvent(BI.SingleSlider.EVENT_CHANGE); |
|
} |
|
}); |
|
|
|
return { |
|
type: "bi.absolute", |
|
element: this, |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: track, |
|
width: "100%", |
|
height: c.TRACK_HEIGHT |
|
}] |
|
}], |
|
hgap: c.TRACK_GAP_HALF, |
|
height: c.TRACK_HEIGHT |
|
}, |
|
top: 3, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: sliderVertical, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}] |
|
}; |
|
}, |
|
|
|
_draggable: function (widget) { |
|
var self = this, o = this.options; |
|
var startDrag = false; |
|
var size = 0, offset = 0, defaultSize = 0; |
|
var mouseMoveTracker = new BI.MouseMoveTracker(function (deltaX) { |
|
if (mouseMoveTracker.isDragging()) { |
|
startDrag = true; |
|
offset += deltaX; |
|
size = optimizeSize(defaultSize + offset); |
|
widget.element.addClass("dragging"); |
|
var percent = size * 100 / (self._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1));// 直接对计算出来的百分数保留到小数点后一位,相当于分成了1000份。 |
|
self._setBlueTrack(significantPercent); |
|
self._setSliderPosition(significantPercent); |
|
var v = self._getValueByPercent(significantPercent); |
|
v = o.digit === false ? v : v.toFixed(o.digit); |
|
self.value = v; |
|
self.fireEvent(BI.SingleSliderNormal.EVENT_DRAG, v); |
|
} |
|
}, function () { |
|
if (startDrag === true) { |
|
size = optimizeSize(size); |
|
var percent = size * 100 / (self._getGrayTrackLength()); |
|
var significantPercent = BI.parseFloat(percent.toFixed(1)); |
|
self._setSliderPosition(significantPercent); |
|
size = 0; |
|
offset = 0; |
|
defaultSize = size; |
|
startDrag = false; |
|
} |
|
widget.element.removeClass("dragging"); |
|
mouseMoveTracker.releaseMouseMoves(); |
|
self.fireEvent(BI.SingleSlider.EVENT_CHANGE); |
|
}, window); |
|
widget.element.on("mousedown", function (event) { |
|
if(!widget.isEnabled()) { |
|
return; |
|
} |
|
defaultSize = this.offsetLeft; |
|
optimizeSize(defaultSize); |
|
mouseMoveTracker.captureMouseMoves(event); |
|
}); |
|
|
|
function optimizeSize (s) { |
|
return BI.clamp(s, 0, self._getGrayTrackLength()); |
|
} |
|
}, |
|
|
|
_createTrack: function () { |
|
var self = this; |
|
var c = this._constant; |
|
this.grayTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "gray-track", |
|
height: 6 |
|
}); |
|
this.blueTrack = BI.createWidget({ |
|
type: "bi.layout", |
|
cls: "blue-track bi-high-light-background", |
|
height: 6 |
|
}); |
|
if (this.options.color) { |
|
this.blueTrack.element.css({"background-color": this.options.color}); |
|
} |
|
|
|
return { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: this.grayTrack, |
|
top: 0, |
|
left: 0, |
|
width: "100%" |
|
}, { |
|
el: this.blueTrack, |
|
top: 0, |
|
left: 0, |
|
width: "0%" |
|
}] |
|
}], |
|
hgap: 8, |
|
height: 8 |
|
}, |
|
top: 8, |
|
left: 0, |
|
width: "100%" |
|
}], |
|
ref: function (ref) { |
|
self.track = ref; |
|
} |
|
}; |
|
}, |
|
|
|
_checkValidation: function (v) { |
|
return !(BI.isNull(v) || v < this.min || v > this.max); |
|
}, |
|
|
|
_setBlueTrack: function (percent) { |
|
this.blueTrack.element.css({width: percent + "%"}); |
|
}, |
|
|
|
_setSliderPosition: function (percent) { |
|
this.slider.element.css({left: percent + "%"}); |
|
}, |
|
|
|
_setAllPosition: function (percent) { |
|
this._setSliderPosition(percent); |
|
this._setBlueTrack(percent); |
|
}, |
|
|
|
_setVisible: function (visible) { |
|
this.slider.setVisible(visible); |
|
}, |
|
|
|
_getGrayTrackLength: function () { |
|
return this.grayTrack.element[0].scrollWidth; |
|
}, |
|
|
|
_getValueByPercent: function (percent) { |
|
var thousandth = BI.parseInt(percent * 10); |
|
return (((this.max - this.min) * thousandth) / 1000 + this.min); |
|
}, |
|
|
|
_getPercentByValue: function (v) { |
|
return (v - this.min) * 100 / (this.max - this.min); |
|
}, |
|
|
|
_setEnable: function (b) { |
|
BI.SingleSliderNormal.superclass._setEnable.apply(this, [b]); |
|
if(b) { |
|
this.blueTrack.element.removeClass("disabled-blue-track").addClass("blue-track"); |
|
} else { |
|
this.blueTrack.element.removeClass("blue-track").addClass("disabled-blue-track"); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.value; |
|
}, |
|
|
|
setValue: function (v) { |
|
var value = BI.parseFloat(v); |
|
if ((!isNaN(value))) { |
|
if (this._checkValidation(value)) { |
|
this.value = value; |
|
} |
|
if (value > this.max) { |
|
this.value = this.max; |
|
} |
|
if (value < this.min) { |
|
this.value = this.min; |
|
} |
|
} |
|
}, |
|
|
|
setMinAndMax: function (v) { |
|
var minNumber = BI.parseFloat(v.min); |
|
var maxNumber = BI.parseFloat(v.max); |
|
if ((!isNaN(minNumber)) && (!isNaN(maxNumber)) && (maxNumber > minNumber )) { |
|
this.min = minNumber; |
|
this.max = maxNumber; |
|
} |
|
}, |
|
|
|
reset: function () { |
|
this._setVisible(false); |
|
this.enable = false; |
|
this.value = ""; |
|
this.min = 0; |
|
this.max = 0; |
|
this._setBlueTrack(0); |
|
}, |
|
|
|
populate: function () { |
|
if (!isNaN(this.min) && !isNaN(this.max)) { |
|
this._setVisible(true); |
|
this.enable = true; |
|
if (BI.isNumeric(this.value) || BI.isNotEmptyString(this.value)) { |
|
this._setAllPosition(this._getPercentByValue(this.value)); |
|
} else { |
|
this._setAllPosition(100); |
|
} |
|
} |
|
} |
|
}); |
|
BI.SingleSliderNormal.EVENT_DRAG = "EVENT_DRAG"; |
|
BI.shortcut("bi.single_slider_normal", BI.SingleSliderNormal);/** |
|
* @class BI.SingleTreeCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.SingleTreeCombo = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleTreeCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-tree-combo", |
|
trigger: {}, |
|
height: 24, |
|
text: "", |
|
items: [], |
|
value: "", |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleTreeCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.trigger = BI.createWidget(BI.extend({ |
|
type: "bi.single_tree_trigger", |
|
text: o.text, |
|
height: o.height, |
|
items: o.items, |
|
value: o.value |
|
}, o.trigger)); |
|
|
|
this.popup = BI.createWidget({ |
|
type: "bi.single_level_tree", |
|
items: o.items, |
|
value: o.value |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
element: this, |
|
adjustLength: 2, |
|
el: this.trigger, |
|
popup: { |
|
el: this.popup |
|
} |
|
}); |
|
|
|
this.combo.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.fireEvent(BI.SingleTreeCombo.EVENT_BEFORE_POPUPVIEW, arguments); |
|
}); |
|
|
|
this.popup.on(BI.SingleTreePopup.EVENT_CHANGE, function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.SingleTreeCombo.EVENT_CHANGE); |
|
}); |
|
}, |
|
|
|
populate: function (items) { |
|
this.combo.populate(items); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.trigger.setValue(v); |
|
this.popup.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.popup.getValue(); |
|
} |
|
}); |
|
|
|
BI.SingleTreeCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.SingleTreeCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.single_tree_combo", BI.SingleTreeCombo);/** |
|
* @class BI.SingleTreePopup |
|
* @extends BI.Pane |
|
*/ |
|
|
|
BI.SingleTreePopup = BI.inherit(BI.Pane, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleTreePopup.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-level-tree", |
|
tipText: BI.i18nText("BI-No_Selected_Item"), |
|
items: [], |
|
value: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleTreePopup.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
this.tree = BI.createWidget({ |
|
type: "bi.level_tree", |
|
expander: { |
|
isDefaultInit: true |
|
}, |
|
items: o.items, |
|
value: o.value, |
|
chooseType: BI.Selection.Single |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.vertical", |
|
element: this, |
|
vgap: 5, |
|
items: [this.tree] |
|
}); |
|
|
|
this.tree.on(BI.Controller.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
}); |
|
|
|
this.tree.on(BI.LevelTree.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.SingleTreePopup.EVENT_CHANGE); |
|
}); |
|
|
|
this.check(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.tree.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.tree.setValue(v); |
|
}, |
|
|
|
populate: function (items) { |
|
BI.SingleTreePopup.superclass.populate.apply(this, arguments); |
|
this.tree.populate(items); |
|
} |
|
}); |
|
|
|
BI.SingleTreePopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.single_level_tree", BI.SingleTreePopup);/** |
|
* @class BI.SingleTreeTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
|
|
BI.SingleTreeTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.SingleTreeTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-single-tree-trigger", |
|
height: 24, |
|
text: "", |
|
items: [], |
|
value: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.SingleTreeTrigger.superclass._init.apply(this, arguments); |
|
|
|
var self = this, o = this.options; |
|
|
|
this.trigger = BI.createWidget({ |
|
type: "bi.select_text_trigger", |
|
element: this, |
|
text: o.text, |
|
items: o.items, |
|
height: o.height, |
|
value: o.value |
|
}); |
|
}, |
|
|
|
_checkTitle: function () { |
|
var self = this, val = this.getValue(); |
|
BI.any(this.options.items, function (i, item) { |
|
if (BI.contains(val, item.value)) { |
|
self.trigger.setTitle(item.text || item.value); |
|
return true; |
|
} |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
v = BI.isArray(v) ? v : [v]; |
|
this.options.value = v; |
|
this.trigger.setValue(v); |
|
this._checkTitle(); |
|
}, |
|
|
|
getValue: function () { |
|
return this.options.value || []; |
|
}, |
|
|
|
populate: function (items) { |
|
BI.SingleTreeTrigger.superclass.populate.apply(this, arguments); |
|
this.trigger.populate(items); |
|
} |
|
|
|
}); |
|
|
|
BI.shortcut("bi.single_tree_trigger", BI.SingleTreeTrigger);/** |
|
* @class BI.TextValueDownListCombo |
|
* @extend BI.Widget |
|
*/ |
|
BI.TextValueDownListCombo = BI.inherit(BI.Widget, { |
|
_defaultConfig: function () { |
|
return BI.extend(BI.TextValueDownListCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-text-value-down-list-combo", |
|
height: 24, |
|
attributes: { |
|
tabIndex: 0 |
|
} |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TextValueDownListCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this._createValueMap(); |
|
|
|
var value; |
|
if(BI.isNotNull(o.value)) { |
|
value = this._digest(o.value); |
|
} |
|
this.trigger = BI.createWidget({ |
|
type: "bi.down_list_select_text_trigger", |
|
cls: "text-value-down-list-trigger", |
|
height: o.height, |
|
items: o.items, |
|
text: o.text, |
|
value: value |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.down_list_combo", |
|
element: this, |
|
chooseType: BI.Selection.Single, |
|
adjustLength: 2, |
|
height: o.height, |
|
el: this.trigger, |
|
value: BI.isNull(value) ? [] : [value], |
|
items: BI.deepClone(o.items) |
|
}); |
|
|
|
this.combo.on(BI.DownListCombo.EVENT_CHANGE, function () { |
|
var currentVal = self.combo.getValue()[0].value; |
|
if (currentVal !== self.value) { |
|
self.setValue(currentVal); |
|
self.fireEvent(BI.TextValueDownListCombo.EVENT_CHANGE); |
|
} |
|
}); |
|
|
|
this.combo.on(BI.DownListCombo.EVENT_SON_VALUE_CHANGE, function () { |
|
var currentVal = self.combo.getValue()[0].childValue; |
|
if (currentVal !== self.value) { |
|
self.setValue(currentVal); |
|
self.fireEvent(BI.TextValueDownListCombo.EVENT_CHANGE); |
|
} |
|
}); |
|
}, |
|
|
|
_createValueMap: function () { |
|
var self = this; |
|
this.valueMap = {}; |
|
BI.each(BI.flatten(this.options.items), function (idx, item) { |
|
if (BI.has(item, "el")) { |
|
BI.each(item.children, function (id, it) { |
|
self.valueMap[it.value] = {value: item.el.value, childValue: it.value}; |
|
}); |
|
} else { |
|
self.valueMap[item.value] = {value: item.value}; |
|
} |
|
}); |
|
}, |
|
|
|
_digest: function (v) { |
|
this.value = v; |
|
return this.valueMap[v]; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = this._digest(v); |
|
this.combo.setValue([v]); |
|
this.trigger.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
var v = this.combo.getValue()[0]; |
|
return [v.childValue || v.value]; |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = BI.flatten(items); |
|
this.combo.populate(items); |
|
this._createValueMap(); |
|
} |
|
}); |
|
BI.TextValueDownListCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.text_value_down_list_combo", BI.TextValueDownListCombo);/** |
|
* 选择字段trigger, downlist专用 |
|
* 显示形式为 父亲值(儿子值) |
|
* |
|
* @class BI.DownListSelectTextTrigger |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DownListSelectTextTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.DownListSelectTextTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-down-list-select-text-trigger", |
|
height: 24, |
|
text: "" |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.DownListSelectTextTrigger.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.select_text_trigger", |
|
element: this, |
|
height: o.height, |
|
items: this._formatItemArray(o.items), |
|
text: o.text, |
|
value: BI.isNull(o.value) ? "" : o.value.childValue || o.value.value |
|
}); |
|
}, |
|
|
|
_formatItemArray: function () { |
|
var sourceArray = BI.flatten(BI.deepClone(this.options.items)); |
|
var targetArray = []; |
|
BI.each(sourceArray, function (idx, item) { |
|
if(BI.has(item, "el")) { |
|
BI.each(item.children, function (id, it) { |
|
it.text = item.el.text + "(" + it.text + ")"; |
|
}); |
|
targetArray = BI.concat(targetArray, item.children); |
|
}else{ |
|
targetArray.push(item); |
|
} |
|
}); |
|
return targetArray; |
|
}, |
|
|
|
setValue: function (vals) { |
|
this.trigger.setValue(vals.childValue || vals.value); |
|
}, |
|
|
|
populate: function (items) { |
|
this.trigger.populate(this._formatItemArray(items)); |
|
} |
|
}); |
|
BI.shortcut("bi.down_list_select_text_trigger", BI.DownListSelectTextTrigger);!(function () { |
|
BI.TimePopup = BI.inherit(BI.Widget, { |
|
props: { |
|
baseCls: "bi-date-time-popup", |
|
height: 68 |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
|
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
el: { |
|
type: "bi.center_adapt", |
|
cls: "bi-split-top", |
|
items: [{ |
|
type: "bi.dynamic_date_time_select", |
|
value: o.value, |
|
ref: function (_ref) { |
|
self.timeSelect = _ref; |
|
} |
|
}] |
|
}, |
|
hgap: 10, |
|
height: 44 |
|
}, { |
|
el: { |
|
type: "bi.grid", |
|
items: [[{ |
|
type: "bi.text_button", |
|
cls: "bi-high-light bi-split-top", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Clears"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.TimePopup.BUTTON_CLEAR_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-left bi-split-right bi-high-light bi-split-top", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Now"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.TimePopup.BUTTON_NOW_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-high-light bi-split-top", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_OK"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.TimePopup.BUTTON_OK_EVENT_CHANGE); |
|
} |
|
}] |
|
}]] |
|
}, |
|
height: 24 |
|
}] |
|
}; |
|
}, |
|
|
|
setValue: function (value) { |
|
if (this._checkValueValid(value)) { |
|
this.timeSelect.setValue(); |
|
} else { |
|
this.timeSelect.setValue({ |
|
hour: value.hour, |
|
minute: value.minute, |
|
second: value.second |
|
}); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.timeSelect.getValue(); |
|
}, |
|
|
|
_checkValueValid: function (value) { |
|
return BI.isNull(value) || BI.isEmptyObject(value) || BI.isEmptyString(value); |
|
} |
|
}); |
|
BI.TimePopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.TimePopup.BUTTON_CLEAR_EVENT_CHANGE = "BUTTON_CLEAR_EVENT_CHANGE"; |
|
BI.TimePopup.BUTTON_NOW_EVENT_CHANGE = "BUTTON_NOW_EVENT_CHANGE"; |
|
BI.TimePopup.CALENDAR_EVENT_CHANGE = "CALENDAR_EVENT_CHANGE"; |
|
BI.shortcut("bi.time_popup", BI.TimePopup); |
|
})();/** |
|
* 时间选择 |
|
* qcc |
|
* 2019/2/28 |
|
*/ |
|
|
|
!(function () { |
|
BI.TimeCombo = BI.inherit(BI.Single, { |
|
constants: { |
|
popupHeight: 80, |
|
popupWidth: 240, |
|
comboAdjustHeight: 1, |
|
border: 1 |
|
}, |
|
props: { |
|
baseCls: "bi-time-combo bi-border bi-border-radius bi-focus-shadow", |
|
width: 78, |
|
height: 22, |
|
format: "", |
|
allowEdit: false |
|
}, |
|
|
|
render: function () { |
|
var self = this, opts = this.options; |
|
this.storeTriggerValue = ""; |
|
this.storeValue = opts.value; |
|
|
|
var popup = { |
|
type: "bi.time_popup", |
|
value: opts.value, |
|
listeners: [{ |
|
eventName: BI.TimePopup.BUTTON_CLEAR_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(); |
|
self.hidePopupView(); |
|
self.fireEvent(BI.TimeCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.TimePopup.BUTTON_OK_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.hidePopupView(); |
|
self.fireEvent(BI.TimeCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.TimePopup.BUTTON_NOW_EVENT_CHANGE, |
|
action: function () { |
|
self._setNowTime(); |
|
} |
|
}], |
|
ref: function (_ref) { |
|
self.popup = _ref; |
|
} |
|
}; |
|
return { |
|
type: "bi.htape", |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.combo", |
|
container: opts.container, |
|
toggle: false, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: { |
|
type: "bi.time_trigger", |
|
height: opts.height, |
|
allowEdit: opts.allowEdit, |
|
watermark: opts.watermark, |
|
format: opts.format, |
|
value: opts.value, |
|
ref: function (_ref) { |
|
self.trigger = _ref; |
|
}, |
|
listeners: [{ |
|
eventName: "EVENT_KEY_DOWN", |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} |
|
self.fireEvent(BI.TimeCombo.EVENT_KEY_DOWN, arguments); |
|
} |
|
}, { |
|
eventName: "EVENT_STOP", |
|
action: function () { |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
} |
|
}, { |
|
eventName: "EVENT_FOCUS", |
|
action: function () { |
|
self.storeTriggerValue = self.trigger.getKey(); |
|
if (!self.combo.isViewVisible()) { |
|
self.combo.showView(); |
|
} |
|
self.fireEvent("EVENT_FOCUS"); |
|
} |
|
}, { |
|
eventName: "EVENT_BLUR", |
|
action: function () { |
|
self.fireEvent("EVENT_BLUR"); |
|
} |
|
}, { |
|
eventName: "EVENT_ERROR", |
|
action: function () { |
|
var date = BI.getDate(); |
|
self.storeValue = { |
|
hour: date.getHours(), |
|
minute: date.getMinutes(), |
|
second: date.getSeconds() |
|
}; |
|
self.fireEvent("EVENT_ERROR"); |
|
} |
|
}, { |
|
eventName: "EVENT_VALID", |
|
action: function () { |
|
self.fireEvent("EVENT_VALID"); |
|
} |
|
}, { |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}, { |
|
eventName: "EVENT_CONFIRM", |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
return; |
|
} |
|
var dateStore = self.storeTriggerValue; |
|
var dateObj = self.trigger.getKey(); |
|
if (BI.isNotEmptyString(dateObj) && !BI.isEqual(dateObj, dateStore)) { |
|
self.storeValue = self.trigger.getValue(); |
|
self.setValue(self.trigger.getValue()); |
|
} else if (BI.isEmptyString(dateObj)) { |
|
self.storeValue = null; |
|
self.trigger.setValue(); |
|
} |
|
self.fireEvent("EVENT_CONFIRM"); |
|
} |
|
}] |
|
}, |
|
adjustLength: this.constants.comboAdjustHeight, |
|
popup: { |
|
el: popup, |
|
width: this.constants.popupWidth, |
|
stopPropagation: false |
|
}, |
|
hideChecker: function (e) { |
|
return self.triggerBtn.element.find(e.target).length === 0; |
|
}, |
|
listeners: [{ |
|
eventName: BI.Combo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
self.popup.setValue(self.storeValue); |
|
self.fireEvent(BI.TimeCombo.EVENT_BEFORE_POPUPVIEW); |
|
} |
|
}], |
|
ref: function (_ref) { |
|
self.combo = _ref; |
|
} |
|
}, |
|
top: 0, |
|
left: 0, |
|
right: 22, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button time-font icon-size-16", |
|
width: 22, |
|
height: 22, |
|
listeners: [{ |
|
eventName: BI.IconButton.EVENT_CHANGE, |
|
action: function () { |
|
if (self.combo.isViewVisible()) { |
|
// self.combo.hideView(); |
|
} else { |
|
self.combo.showView(); |
|
} |
|
} |
|
}], |
|
ref: function (_ref) { |
|
self.triggerBtn = _ref; |
|
} |
|
}, |
|
top: 0, |
|
right: 0 |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.trigger.setValue(v); |
|
}, |
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
hidePopupView: function () { |
|
this.combo.hideView(); |
|
}, |
|
|
|
_setNowTime: function () { |
|
var date = BI.getDate(); |
|
var nowTome = { |
|
hour: date.getHours(), |
|
minute: date.getMinutes(), |
|
second: date.getSeconds() |
|
}; |
|
this.setValue(nowTome); |
|
this.hidePopupView(); |
|
this.fireEvent(BI.TimeCombo.EVENT_CONFIRM); |
|
} |
|
}); |
|
|
|
BI.TimeCombo.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.TimeCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.TimeCombo.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.TimeCombo.EVENT_VALID = "EVENT_VALID"; |
|
BI.TimeCombo.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.TimeCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.time_combo", BI.TimeCombo); |
|
})();!(function () { |
|
BI.TimeTrigger = BI.inherit(BI.Trigger, { |
|
|
|
_const: { |
|
COMPARE_FORMAT: "%H:%M:%S", |
|
COMPLETE_COMPARE_FORMAT: "%Y-%M-%d %H:%M:%S %P", |
|
FORMAT_ARRAY: [ |
|
"%H:%M:%S", // HH:mm:ss |
|
"%I:%M:%S", // hh:mm:ss |
|
"%l:%M:%S", // h:mm:ss |
|
"%k:%M:%S", // H:mm:ss |
|
"%l:%M:%S %p", // h:mm:ss a |
|
"%l:%M:%S %P", // h:mm:ss a |
|
"%H:%M:%S %p", // HH:mm:ss a |
|
"%H:%M:%S %P", // HH:mm:ss a |
|
"%l:%M", // h:mm |
|
"%k:%M", // H:mm |
|
"%I:%M", // hh:mm |
|
"%H:%M", // HH:mm |
|
"%M:%S" // mm:ss |
|
], |
|
DEFAULT_DATE_STRING: "2000-01-01", |
|
DEFAULT_HOUR: "00" |
|
}, |
|
|
|
props: { |
|
extraCls: "bi-time-trigger", |
|
value: {}, |
|
format: "", |
|
allowEdit: false |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
this.storeTriggerValue = ""; |
|
this.storeValue = o.value; |
|
return { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: { |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
validationChecker: function (v) { |
|
return self._dateCheck(v); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
ref: function (_ref) { |
|
self.editor = _ref; |
|
}, |
|
value: this._formatValue(o.value), |
|
hgap: 4, |
|
allowBlank: true, |
|
watermark: BI.isKey(o.watermark) ? o.watermark : BI.i18nText("BI-Basic_Unrestricted"), |
|
title: BI.bind(this._getTitle, this), |
|
listeners: [{ |
|
eventName: "EVENT_KEY_DOWN", |
|
action: function () { |
|
self.fireEvent("EVENT_KEY_DOWN", arguments); |
|
} |
|
}, { |
|
eventName: "EVENT_FOCUS", |
|
action: function () { |
|
self.storeTriggerValue = self.getKey(); |
|
self.fireEvent("EVENT_FOCUS"); |
|
} |
|
}, { |
|
eventName: "EVENT_BLUR", |
|
action: function () { |
|
self.fireEvent("EVENT_BLUR"); |
|
} |
|
}, { |
|
eventName: "EVENT_STOP", |
|
action: function () { |
|
self.fireEvent("EVENT_STOP"); |
|
} |
|
}, { |
|
eventName: "EVENT_VALID", |
|
action: function () { |
|
self.fireEvent("EVENT_VALID"); |
|
} |
|
}, { |
|
eventName: "EVENT_ERROR", |
|
action: function () { |
|
self.fireEvent("EVENT_ERROR"); |
|
} |
|
}, { |
|
eventName: "EVENT_CONFIRM", |
|
action: function () { |
|
var value = self.editor.getValue(); |
|
if (BI.isNotNull(value)) { |
|
self.editor.setState(value); |
|
} |
|
if (BI.isNotEmptyString(value) && !BI.isEqual(self.storeTriggerValue, self.getKey())) { |
|
var date = value.match(/\d+/g); |
|
self.storeValue = { |
|
hour: date[0] | 0, |
|
minute: date[1] | 0, |
|
second: date[2] | 0 |
|
}; |
|
} |
|
self.fireEvent("EVENT_CONFIRM"); |
|
} |
|
}, { |
|
eventName: "EVENT_START", |
|
action: function () { |
|
self.fireEvent("EVENT_START"); |
|
} |
|
}, { |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.text", |
|
invisible: o.allowEdit, |
|
cls: "show-text", |
|
title: BI.bind(this._getTitle, this), |
|
hgap: 4 |
|
}, |
|
left: 0, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
_dateCheck: function (date) { |
|
var c = this._const; |
|
var self = this; |
|
return BI.any(c.FORMAT_ARRAY, function (idx, format) { |
|
return BI.print(BI.parseDateTime(c.DEFAULT_DATE_STRING + " " + self._getCompleteHMS(date, format), c.COMPLETE_COMPARE_FORMAT), format) === date; |
|
}); |
|
}, |
|
|
|
_getCompleteHMS: function (str, format) { |
|
var c = this._const; |
|
switch (format) { |
|
case "%M:%S": |
|
str = c.DEFAULT_HOUR + ":" + str; |
|
break; |
|
default: |
|
break; |
|
} |
|
return str; |
|
}, |
|
|
|
_getTitle: function () { |
|
var storeValue = this.storeValue || {}; |
|
var date = BI.getDate(); |
|
return BI.print(BI.getDate(date.getFullYear(), 0, 1, storeValue.hour, storeValue.minute, storeValue.second), this._getFormatString()); |
|
}, |
|
|
|
_getFormatString: function () { |
|
return this.options.format || this._const.COMPARE_FORMAT; |
|
}, |
|
|
|
_formatValue: function (v) { |
|
var now = BI.getDate(); |
|
return BI.isNotEmptyObject(v) ? BI.print(BI.getDate(now.getFullYear(), now.getMonth(), now.getDay(), v.hour, v.minute, v.second), this._getFormatString()) : ""; |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.editor.setValue(this._formatValue(v)); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
} |
|
|
|
}); |
|
BI.shortcut("bi.time_trigger", BI.TimeTrigger); |
|
})();/** |
|
* Created by Baron on 2015/10/19. |
|
*/ |
|
BI.DateInterval = BI.inherit(BI.Single, { |
|
constants: { |
|
height: 24, |
|
width: 24, |
|
lgap: 15, |
|
offset: 0, |
|
timeErrorCls: "time-error" |
|
}, |
|
_defaultConfig: function () { |
|
var conf = BI.DateInterval.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-date-interval", |
|
minDate: "1900-01-01", |
|
maxDate: "2099-12-31" |
|
}); |
|
}, |
|
_init: function () { |
|
var self = this, o = this.options; |
|
BI.DateInterval.superclass._init.apply(this, arguments); |
|
|
|
o.value = o.value || {}; |
|
this.left = this._createCombo(o.value.start); |
|
this.right = this._createCombo(o.value.end); |
|
this.label = BI.createWidget({ |
|
type: "bi.label", |
|
height: this.constants.height, |
|
width: this.constants.width, |
|
text: "-" |
|
}); |
|
BI.createWidget({ |
|
element: self, |
|
type: "bi.center", |
|
height: this.constants.height, |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.left, |
|
left: this.constants.offset, |
|
right: this.constants.width / 2, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.right, |
|
left: this.constants.width / 2, |
|
right: this.constants.offset, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.horizontal_auto", |
|
element: this, |
|
items: [ |
|
self.label |
|
] |
|
}); |
|
}, |
|
|
|
_createCombo: function (v) { |
|
var self = this, o = this.options; |
|
var combo = BI.createWidget({ |
|
type: "bi.dynamic_date_combo", |
|
behaviors: o.behaviors, |
|
value: v |
|
}); |
|
combo.on(BI.DynamicDateCombo.EVENT_ERROR, function () { |
|
self._clearTitle(); |
|
BI.Bubbles.hide("error"); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.DateInterval.EVENT_ERROR); |
|
}); |
|
|
|
combo.on(BI.DynamicDateCombo.EVENT_VALID, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
BI.Bubbles.show("error", BI.i18nText("BI-Time_Interval_Error_Text"), self, { |
|
offsetStyle: "center" |
|
}); |
|
self.fireEvent(BI.DateInterval.EVENT_ERROR); |
|
} else { |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
} |
|
}); |
|
|
|
combo.on(BI.DynamicDateCombo.EVENT_FOCUS, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
BI.Bubbles.show("error", BI.i18nText("BI-Time_Interval_Error_Text"), self, { |
|
offsetStyle: "center" |
|
}); |
|
self.fireEvent(BI.DateInterval.EVENT_ERROR); |
|
} else { |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
} |
|
}); |
|
|
|
// combo.on(BI.DynamicDateCombo.EVENT_BEFORE_POPUPVIEW, function () { |
|
// self.left.hidePopupView(); |
|
// self.right.hidePopupView(); |
|
// }); |
|
|
|
combo.on(BI.DynamicDateCombo.EVENT_CONFIRM, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.DateInterval.EVENT_ERROR); |
|
}else{ |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.DateInterval.EVENT_CHANGE); |
|
} |
|
}); |
|
return combo; |
|
}, |
|
_dateCheck: function (date) { |
|
return BI.print(BI.parseDateTime(date, "%Y-%x-%d"), "%Y-%x-%d") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%d"), "%Y-%X-%d") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%x-%e"), "%Y-%x-%e") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%e"), "%Y-%X-%e") === date; |
|
}, |
|
_checkVoid: function (obj) { |
|
var o = this.options; |
|
return !BI.checkDateVoid(obj.year, obj.month, obj.day, o.minDate, o.maxDate)[0]; |
|
}, |
|
_check: function (smallDate, bigDate) { |
|
var smallObj = smallDate.match(/\d+/g), bigObj = bigDate.match(/\d+/g); |
|
return this._dateCheck(smallDate) && BI.checkDateLegal(smallDate) && this._checkVoid({ |
|
year: smallObj[0], |
|
month: smallObj[1], |
|
day: smallObj[2] |
|
}) && this._dateCheck(bigDate) && BI.checkDateLegal(bigDate) && this._checkVoid({ |
|
year: bigObj[0], |
|
month: bigObj[1], |
|
day: bigObj[2] |
|
}); |
|
}, |
|
_compare: function (smallDate, bigDate) { |
|
smallDate = BI.print(BI.parseDateTime(smallDate, "%Y-%X-%d"), "%Y-%X-%d"); |
|
bigDate = BI.print(BI.parseDateTime(bigDate, "%Y-%X-%d"), "%Y-%X-%d"); |
|
return BI.isNotNull(smallDate) && BI.isNotNull(bigDate) && smallDate > bigDate; |
|
}, |
|
_setTitle: function (v) { |
|
this.left.setTitle(v); |
|
this.right.setTitle(v); |
|
this.label.setTitle(v); |
|
}, |
|
_clearTitle: function () { |
|
this.left.setTitle(""); |
|
this.right.setTitle(""); |
|
this.label.setTitle(""); |
|
}, |
|
setValue: function (date) { |
|
date = date || {}; |
|
this.left.setValue(date.start); |
|
this.right.setValue(date.end); |
|
}, |
|
getValue: function () { |
|
return {start: this.left.getValue(), end: this.right.getValue()}; |
|
} |
|
}); |
|
BI.DateInterval.EVENT_VALID = "EVENT_VALID"; |
|
BI.DateInterval.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DateInterval.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.date_interval", BI.DateInterval);/** |
|
* Created by Baron on 2015/10/19. |
|
*/ |
|
BI.TimeInterval = BI.inherit(BI.Single, { |
|
constants: { |
|
height: 24, |
|
width: 24, |
|
lgap: 15, |
|
offset: 0, |
|
timeErrorCls: "time-error" |
|
}, |
|
_defaultConfig: function () { |
|
var conf = BI.TimeInterval.superclass._defaultConfig.apply(this, arguments); |
|
return BI.extend(conf, { |
|
extraCls: "bi-time-interval", |
|
minDate: "1900-01-01", |
|
maxDate: "2099-12-31" |
|
}); |
|
}, |
|
_init: function () { |
|
var self = this, o = this.options; |
|
BI.TimeInterval.superclass._init.apply(this, arguments); |
|
|
|
o.value = o.value || {}; |
|
this.left = this._createCombo(o.value.start); |
|
this.right = this._createCombo(o.value.end); |
|
this.label = BI.createWidget({ |
|
type: "bi.label", |
|
height: this.constants.height, |
|
width: this.constants.width, |
|
text: "-" |
|
}); |
|
BI.createWidget({ |
|
element: self, |
|
type: "bi.center", |
|
height: this.constants.height, |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.left, |
|
left: this.constants.offset, |
|
right: this.constants.width / 2, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.right, |
|
left: this.constants.width / 2, |
|
right: this.constants.offset, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.horizontal_auto", |
|
element: this, |
|
items: [ |
|
self.label |
|
] |
|
}); |
|
}, |
|
|
|
_createCombo: function (v) { |
|
var self = this, o = this.options; |
|
var combo = BI.createWidget({ |
|
type: "bi.dynamic_date_time_combo", |
|
behaviors: o.behaviors, |
|
value: v |
|
}); |
|
combo.on(BI.DynamicDateTimeCombo.EVENT_ERROR, function () { |
|
self._clearTitle(); |
|
BI.Bubbles.hide("error"); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.TimeInterval.EVENT_ERROR); |
|
}); |
|
|
|
combo.on(BI.DynamicDateTimeCombo.EVENT_VALID, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self.left.isValid() && self.right.isValid() && self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
BI.Bubbles.show("error", BI.i18nText("BI-Time_Interval_Error_Text"), self, { |
|
offsetStyle: "center" |
|
}); |
|
self.fireEvent(BI.TimeInterval.EVENT_ERROR); |
|
} else { |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
} |
|
}); |
|
|
|
combo.on(BI.DynamicDateTimeCombo.EVENT_FOCUS, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self.left.isValid() && self.right.isValid() && self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
BI.Bubbles.show("error", BI.i18nText("BI-Time_Interval_Error_Text"), self, { |
|
offsetStyle: "center" |
|
}); |
|
self.fireEvent(BI.TimeInterval.EVENT_ERROR); |
|
} else { |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
} |
|
}); |
|
|
|
// 不知道干啥的,先注释掉 |
|
// combo.on(BI.DynamicDateTimeCombo.EVENT_BEFORE_POPUPVIEW, function () { |
|
// self.left.hidePopupView(); |
|
// self.right.hidePopupView(); |
|
// }); |
|
|
|
combo.on(BI.DynamicDateTimeCombo.EVENT_CONFIRM, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self.left.isValid() && self.right.isValid() && self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.TimeInterval.EVENT_ERROR); |
|
}else{ |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.TimeInterval.EVENT_CHANGE); |
|
} |
|
}); |
|
return combo; |
|
}, |
|
_dateCheck: function (date) { |
|
return BI.print(BI.parseDateTime(date, "%Y-%x-%d %H:%M:%S"), "%Y-%x-%d %H:%M:%S") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%d %H:%M:%S"), "%Y-%X-%d %H:%M:%S") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%x-%e %H:%M:%S"), "%Y-%x-%e %H:%M:%S") === date || |
|
BI.print(BI.parseDateTime(date, "%Y-%X-%e %H:%M:%S"), "%Y-%X-%e %H:%M:%S") === date; |
|
}, |
|
_checkVoid: function (obj) { |
|
var o = this.options; |
|
return !BI.checkDateVoid(obj.year, obj.month, obj.day, o.minDate, o.maxDate)[0]; |
|
}, |
|
_check: function (smallDate, bigDate) { |
|
var smallObj = smallDate.match(/\d+/g), bigObj = bigDate.match(/\d+/g); |
|
return this._dateCheck(smallDate) && BI.checkDateLegal(smallDate) && this._checkVoid({ |
|
year: smallObj[0], |
|
month: smallObj[1], |
|
day: smallObj[2] |
|
}) && this._dateCheck(bigDate) && BI.checkDateLegal(bigDate) && this._checkVoid({ |
|
year: bigObj[0], |
|
month: bigObj[1], |
|
day: bigObj[2] |
|
}); |
|
}, |
|
_compare: function (smallDate, bigDate) { |
|
smallDate = BI.print(BI.parseDateTime(smallDate, "%Y-%X-%d %H:%M:%S"), "%Y-%X-%d %H:%M:%S"); |
|
bigDate = BI.print(BI.parseDateTime(bigDate, "%Y-%X-%d %H:%M:%S"), "%Y-%X-%d %H:%M:%S"); |
|
return BI.isNotNull(smallDate) && BI.isNotNull(bigDate) && smallDate > bigDate; |
|
}, |
|
_setTitle: function (v) { |
|
this.left.setTitle(v); |
|
this.right.setTitle(v); |
|
this.label.setTitle(v); |
|
}, |
|
_clearTitle: function () { |
|
this.left.setTitle(""); |
|
this.right.setTitle(""); |
|
this.label.setTitle(""); |
|
}, |
|
setValue: function (date) { |
|
date = date || {}; |
|
this.left.setValue(date.start); |
|
this.right.setValue(date.end); |
|
}, |
|
getValue: function () { |
|
return {start: this.left.getValue(), end: this.right.getValue()}; |
|
} |
|
}); |
|
BI.TimeInterval.EVENT_VALID = "EVENT_VALID"; |
|
BI.TimeInterval.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.TimeInterval.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.time_interval", BI.TimeInterval);/** |
|
* 时间区间 |
|
* qcc |
|
* 2019/2/28 |
|
*/ |
|
|
|
!(function () { |
|
BI.TimePeriods = BI.inherit(BI.Single, { |
|
constants: { |
|
height: 24, |
|
width: 24, |
|
lgap: 15, |
|
offset: 0 |
|
}, |
|
props: { |
|
extraCls: "bi-time-interval", |
|
value: {} |
|
}, |
|
render: function () { |
|
var self = this, o = this.options; |
|
|
|
return { |
|
type: "bi.absolute", |
|
height: this.constants.height, |
|
items: [{ |
|
el: { |
|
type: "bi.horizontal_auto", |
|
items: [{ |
|
type: "bi.label", |
|
height: this.constants.height, |
|
width: this.constants.width, |
|
text: "-", |
|
ref: function (_ref) { |
|
self.label = _ref; |
|
} |
|
}] |
|
}, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}, { |
|
el: { |
|
type: "bi.center", |
|
height: this.constants.height, |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: BI.extend({ |
|
ref: function (_ref) { |
|
self.left = _ref; |
|
} |
|
}, this._createCombo(o.value.start)), |
|
left: this.constants.offset, |
|
right: this.constants.width / 2, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: BI.extend({ |
|
ref: function (_ref) { |
|
self.right = _ref; |
|
} |
|
}, this._createCombo(o.value.end)), |
|
left: this.constants.width / 2, |
|
right: this.constants.offset, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}] |
|
}, |
|
top: 0, |
|
left: 0, |
|
right: 0, |
|
bottom: 0 |
|
}] |
|
}; |
|
}, |
|
|
|
_createCombo: function (v) { |
|
var self = this; |
|
return { |
|
type: "bi.time_combo", |
|
value: v, |
|
listeners: [{ |
|
eventName: BI.TimeCombo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
self.left.hidePopupView(); |
|
self.right.hidePopupView(); |
|
} |
|
}, { |
|
eventName: BI.TimeCombo.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.TimePeriods.EVENT_CHANGE); |
|
} |
|
}, { |
|
eventName: BI.TimeCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.TimePeriods.EVENT_CONFIRM); |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
setValue: function (date) { |
|
date = date || {}; |
|
this.left.setValue(date.start); |
|
this.right.setValue(date.end); |
|
}, |
|
getValue: function () { |
|
return {start: this.left.getValue(), end: this.right.getValue()}; |
|
} |
|
}); |
|
BI.TimePeriods.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.TimePeriods.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.time_periods", BI.TimePeriods); |
|
})();/** |
|
* 年份展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.YearCard |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DynamicYearCard = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-year-card" |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Multi_Date_Relative_Current_Time"), |
|
textAlign: "left", |
|
height: 24 |
|
}, { |
|
type: "bi.dynamic_date_param_item", |
|
ref: function () { |
|
self.item = this; |
|
}, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}], |
|
vgap: 10, |
|
hgap: 10 |
|
}; |
|
}, |
|
|
|
_createValue: function (type, v) { |
|
return { |
|
dateType: type, |
|
value: Math.abs(v), |
|
offset: v > 0 ? 1 : 0 |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {year: 0}; |
|
this.item.setValue(this._createValue(BI.DynamicDateCard.TYPE.YEAR, v.year)); |
|
}, |
|
|
|
getValue: function () { |
|
var value = this.item.getValue(); |
|
return { |
|
year: (value.offset === 0 ? -value.value : value.value) |
|
}; |
|
} |
|
}); |
|
BI.DynamicYearCard.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_year_card", BI.DynamicYearCard);/** |
|
* 年份展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.StaticYearCard |
|
* @extends BI.Trigger |
|
*/ |
|
BI.StaticYearCard = BI.inherit(BI.Widget, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.StaticYearCard.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-year-card", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31" // 最大日期 |
|
}); |
|
}, |
|
|
|
_createYearCalendar: function (v) { |
|
var o = this.options, y = this._year; |
|
|
|
var calendar = BI.createWidget({ |
|
type: "bi.year_calendar", |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max, |
|
logic: { |
|
dynamic: true |
|
}, |
|
year: y + v * 12 |
|
}); |
|
calendar.setValue(this._year); |
|
return calendar; |
|
}, |
|
|
|
_init: function () { |
|
BI.StaticYearCard.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
|
|
this.selectedYear = this._year = BI.getDate().getFullYear(); |
|
|
|
this.backBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "pre-page-h-font", |
|
width: 25, |
|
height: 25, |
|
value: -1, |
|
listeners: [{ |
|
eventName: BI.IconButton.EVENT_CHANGE, |
|
action: function () { |
|
self.navigation.setSelect(self.navigation.getSelect() - 1); |
|
self._checkLeftValid(); |
|
self._checkRightValid(); |
|
} |
|
}] |
|
}); |
|
|
|
this.preBtn = BI.createWidget({ |
|
type: "bi.icon_button", |
|
cls: "next-page-h-font", |
|
width: 25, |
|
height: 25, |
|
value: 1, |
|
listeners: [{ |
|
eventName: BI.IconButton.EVENT_CHANGE, |
|
action: function () { |
|
self.navigation.setSelect(self.navigation.getSelect() + 1); |
|
self._checkLeftValid(); |
|
self._checkRightValid(); |
|
} |
|
}] |
|
}); |
|
|
|
this.navigation = BI.createWidget({ |
|
type: "bi.navigation", |
|
direction: "top", |
|
element: this, |
|
single: true, |
|
logic: { |
|
dynamic: true |
|
}, |
|
tab: { |
|
type: "bi.htape", |
|
cls: "bi-split-top bi-split-bottom", |
|
height: 30, |
|
items: [{ |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [self.backBtn] |
|
}, |
|
width: 25 |
|
}, { |
|
type: "bi.layout" |
|
}, { |
|
el: { |
|
type: "bi.center_adapt", |
|
items: [self.preBtn] |
|
}, |
|
width: 25 |
|
}] |
|
}, |
|
cardCreator: BI.bind(this._createYearCalendar, this), |
|
|
|
afterCardShow: function () { |
|
this.setValue(self.selectedYear); |
|
var calendar = this.getSelectedCard(); |
|
self.backBtn.setEnable(!calendar.isFrontYear()); |
|
self.preBtn.setEnable(!calendar.isFinalYear()); |
|
} |
|
}); |
|
|
|
this.navigation.on(BI.Navigation.EVENT_CHANGE, function () { |
|
self.selectedYear = this.getValue(); |
|
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); |
|
self.fireEvent(BI.StaticYearCard.EVENT_CHANGE, self.selectedYear); |
|
}); |
|
|
|
if(BI.isKey(o.value)){ |
|
this.setValue(o.value); |
|
} |
|
}, |
|
|
|
_checkLeftValid: function () { |
|
var o = this.options; |
|
var valid = true; |
|
this.backBtn.setEnable(valid); |
|
return valid; |
|
}, |
|
|
|
_checkRightValid: function () { |
|
var o = this.options; |
|
var valid = true; |
|
this.preBtn.setEnable(valid); |
|
return valid; |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
year: this.selectedYear |
|
}; |
|
}, |
|
|
|
setValue: function (obj) { |
|
var o = this.options; |
|
obj = obj || {}; |
|
var v = obj.year; |
|
if (BI.checkDateVoid(v, 1, 1, o.min, o.max)[0]) { |
|
v = BI.getDate().getFullYear(); |
|
this.selectedYear = ""; |
|
this.navigation.setSelect(BI.YearCalendar.getPageByYear(v)); |
|
this.navigation.setValue(""); |
|
} else { |
|
this.selectedYear = BI.parseInt(v); |
|
this.navigation.setSelect(BI.YearCalendar.getPageByYear(v)); |
|
this.navigation.setValue(this.selectedYear); |
|
} |
|
this._checkLeftValid(); |
|
this._checkRightValid(); |
|
} |
|
}); |
|
BI.StaticYearCard.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.static_year_card", BI.StaticYearCard);BI.DynamicYearCombo = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-year-combo bi-border bi-focus-shadow", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 22 |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicYearCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.storeValue = o.value; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.dynamic_year_trigger", |
|
min: o.min, |
|
max: o.max, |
|
height: o.height, |
|
value: o.value || "" |
|
}); |
|
this.trigger.on(BI.DynamicYearTrigger.EVENT_KEY_DOWN, function () { |
|
if (self.combo.isViewVisible()) { |
|
self.combo.hideView(); |
|
} |
|
}); |
|
this.trigger.on(BI.DynamicYearTrigger.EVENT_FOCUS, function () { |
|
self.storeTriggerValue = this.getKey(); |
|
}); |
|
this.trigger.on(BI.DynamicYearTrigger.EVENT_START, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearTrigger.EVENT_STOP, function () { |
|
self.combo.showView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearTrigger.EVENT_ERROR, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearTrigger.EVENT_CONFIRM, function () { |
|
if (self.combo.isViewVisible()) { |
|
return; |
|
} |
|
if (this.getKey() && this.getKey() !== self.storeTriggerValue) { |
|
self.storeValue = self.trigger.getValue(); |
|
self.setValue(self.storeValue); |
|
} else if (!this.getKey()) { |
|
self.storeValue = null; |
|
self.setValue(); |
|
} |
|
self._checkDynamicValue(self.storeValue); |
|
self.fireEvent(BI.DynamicYearCombo.EVENT_CONFIRM); |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: this.trigger, |
|
popup: { |
|
minWidth: 85, |
|
stopPropagation: false, |
|
el: { |
|
type: "bi.dynamic_year_popup", |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicYearPopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearPopup.BUTTON_CLEAR_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearPopup.BUTTON_lABEL_EVENT_CHANGE, |
|
action: function () { |
|
var date = BI.getDate(); |
|
self.setValue({type: BI.DynamicYearCombo.Static, value: {year: date.getFullYear()}}); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearPopup.BUTTON_OK_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}], |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}, |
|
value: o.value || "" |
|
} |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.popup.setValue(self.storeValue); |
|
self.fireEvent(BI.DynamicYearCombo.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
ref: function () { |
|
self.comboWrapper = this; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-change-h-font", |
|
width: 24, |
|
height: 24, |
|
ref: function () { |
|
self.changeIcon = this; |
|
} |
|
}, |
|
width: 24 |
|
}, this.combo] |
|
}); |
|
this._checkDynamicValue(o.value); |
|
}, |
|
|
|
_checkDynamicValue: function (v) { |
|
var type = null; |
|
if (BI.isNotNull(v)) { |
|
type = v.type; |
|
} |
|
switch (type) { |
|
case BI.DynamicYearCombo.Dynamic: |
|
this.changeIcon.setVisible(true); |
|
this.comboWrapper.attr("items")[0].width = 24; |
|
this.comboWrapper.resize(); |
|
break; |
|
default: |
|
this.comboWrapper.attr("items")[0].width = 0; |
|
this.comboWrapper.resize(); |
|
this.changeIcon.setVisible(false); |
|
break; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.trigger.setValue(v); |
|
this._checkDynamicValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
} |
|
|
|
}); |
|
BI.DynamicYearCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicYearCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.dynamic_year_combo", BI.DynamicYearCombo); |
|
|
|
BI.extend(BI.DynamicYearCombo, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});/** |
|
* 年份展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.DynamicYearPopup |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DynamicYearPopup = BI.inherit(BI.Widget, { |
|
constants: { |
|
tabHeight: 30, |
|
buttonHeight: 24 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-year-popup", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期, |
|
width: 180, |
|
height: 240 |
|
}, |
|
|
|
render: function () { |
|
var self = this, opts = this.options, c = this.constants; |
|
this.storeValue = {type: BI.DynamicYearCombo.Static}; |
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
el: this._getTabJson() |
|
}, { |
|
el: { |
|
type: "bi.grid", |
|
items: [[{ |
|
type: "bi.text_button", |
|
cls: "bi-split-top bi-high-light", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Clear"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearPopup.BUTTON_CLEAR_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
textHeight: c.buttonHeight - 1, |
|
cls: "bi-split-left bi-split-right bi-high-light bi-split-top", |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Current_Year"), |
|
ref: function () { |
|
self.textButton = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearPopup.BUTTON_lABEL_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-top bi-high-light", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_OK"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearPopup.BUTTON_OK_EVENT_CHANGE); |
|
} |
|
}] |
|
}]] |
|
}, |
|
height: 24 |
|
}] |
|
}; |
|
}, |
|
|
|
_setInnerValue: function () { |
|
if (this.dateTab.getSelect() === BI.DynamicDateCombo.Static) { |
|
this.textButton.setValue(BI.i18nText("BI-Basic_Current_Year")); |
|
this.textButton.setEnable(true); |
|
} else { |
|
var date = BI.DynamicDateHelper.getCalculation(this.dynamicPane.getValue()); |
|
date = BI.print(date, "%Y"); |
|
this.textButton.setValue(date); |
|
this.textButton.setEnable(false); |
|
} |
|
}, |
|
|
|
_getTabJson: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
tab: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: this.constants.tabHeight, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Basic_Year_Fen"), |
|
value: BI.DynamicYearCombo.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicYearCombo.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}) |
|
}, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicYearCombo.Dynamic: |
|
return { |
|
type: "bi.dynamic_year_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self._setInnerValue(self.year, v); |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
case BI.DynamicYearCombo.Static: |
|
default: |
|
return { |
|
type: "bi.static_year_card", |
|
behaviors: o.behaviors, |
|
min: self.options.min, |
|
max: self.options.max, |
|
listeners: [{ |
|
eventName: BI.StaticYearCard.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearPopup.EVENT_CHANGE); |
|
} |
|
}], |
|
ref: function () { |
|
self.year = this; |
|
} |
|
}; |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Tab.EVENT_CHANGE, |
|
action: function () { |
|
var v = self.dateTab.getSelect(); |
|
switch (v) { |
|
case BI.DynamicYearCombo.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.year.setValue({year: date.getFullYear()}); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicYearCombo.Dynamic: |
|
default: |
|
if(self.storeValue && self.storeValue.type === BI.DynamicYearCombo.Dynamic) { |
|
self.dynamicPane.setValue(self.storeValue.value); |
|
}else{ |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
} |
|
self._setInnerValue(); |
|
break; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
var self = this; |
|
var type, value; |
|
v = v || {}; |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
this.year.setValue(value); |
|
this.textButton.setValue(BI.i18nText("BI-Basic_Current_Year")); |
|
this.textButton.setEnable(true); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: this.dateTab.getSelect(), |
|
value: this.dateTab.getValue() |
|
}; |
|
} |
|
|
|
}); |
|
BI.DynamicYearPopup.BUTTON_CLEAR_EVENT_CHANGE = "BUTTON_CLEAR_EVENT_CHANGE"; |
|
BI.DynamicYearPopup.BUTTON_lABEL_EVENT_CHANGE = "BUTTON_lABEL_EVENT_CHANGE"; |
|
BI.DynamicYearPopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.DynamicYearPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_year_popup", BI.DynamicYearPopup);BI.DynamicYearTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4, |
|
vgap: 2 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.DynamicYearTrigger.superclass._defaultConfig.apply(this, arguments), { |
|
extraCls: "bi-year-trigger", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 24 |
|
}); |
|
}, |
|
|
|
beforeInit: function (callback) { |
|
var o = this.options; |
|
o.title = BI.bind(this._titleCreator, this); |
|
callback(); |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicYearTrigger.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options, c = this._const; |
|
this.editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
validationChecker: function (v) { |
|
return v === "" || (BI.isPositiveInteger(v) && !BI.checkDateVoid(v, 1, 1, o.min, o.max)[0]); |
|
}, |
|
quitChecker: function (v) { |
|
return false; |
|
}, |
|
hgap: c.hgap, |
|
vgap: c.vgap, |
|
watermark: BI.i18nText("BI-Basic_Unrestricted"), |
|
allowBlank: true, |
|
errorText: function () { |
|
return BI.i18nText("BI-Year_Trigger_Invalid_Text"); |
|
} |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_KEY_DOWN, function () { |
|
self.fireEvent(BI.DynamicYearTrigger.EVENT_KEY_DOWN, arguments); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.DynamicYearTrigger.EVENT_FOCUS); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_STOP, function () { |
|
self.fireEvent(BI.DynamicYearTrigger.EVENT_STOP); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_CONFIRM, function () { |
|
var value = self.editor.getValue(); |
|
if (BI.isNotNull(value)) { |
|
self.editor.setValue(value); |
|
} |
|
if (BI.isNotEmptyString(value)) { |
|
self.storeValue = { |
|
type: BI.DynamicDateCombo.Static, |
|
value: { |
|
year: value |
|
} |
|
}; |
|
} |
|
|
|
self.fireEvent(BI.DynamicYearTrigger.EVENT_CONFIRM); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_SPACE, function () { |
|
if (self.editor.isValid()) { |
|
self.editor.blur(); |
|
} |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_START, function () { |
|
self.fireEvent(BI.DynamicYearTrigger.EVENT_START); |
|
}); |
|
this.editor.on(BI.SignEditor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.DynamicYearTrigger.EVENT_ERROR); |
|
}); |
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [{ |
|
el: this.editor |
|
}, { |
|
el: { |
|
type: "bi.text_button", |
|
baseCls: "bi-trigger-year-text", |
|
text: BI.i18nText("BI-Multi_Date_Year"), |
|
width: o.height |
|
}, |
|
width: o.height |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
width: o.height |
|
}, |
|
width: o.height |
|
}] |
|
}); |
|
this.setValue(o.value); |
|
}, |
|
|
|
_getText: function (obj) { |
|
var value = ""; |
|
if(BI.isNotNull(obj.year) && BI.parseInt(obj.year) !== 0) { |
|
value += Math.abs(obj.year) + BI.i18nText("BI-Basic_Year") + (obj.year < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
return value; |
|
}, |
|
|
|
_setInnerValue: function (date, text) { |
|
var dateStr = BI.print(date, "%Y"); |
|
this.editor.setState(dateStr); |
|
this.editor.setValue(dateStr); |
|
}, |
|
|
|
_titleCreator: function () { |
|
var storeValue = this.storeValue || {}; |
|
var type = storeValue.type || BI.DynamicDateCombo.Static; |
|
var value = storeValue.value; |
|
if(!this.editor.isValid()) { |
|
return ""; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
var date = BI.getDate(); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
var dateStr = BI.print(date, "%Y"); |
|
return BI.isEmptyString(text) ? dateStr : (text + ":" + dateStr); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
value = value || {}; |
|
return value.year; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
var type, value; |
|
var date = BI.getDate(); |
|
this.storeValue = v; |
|
if (BI.isNotNull(v)) { |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
this._setInnerValue(date, text); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
value = value || {}; |
|
this.editor.setState(value.year); |
|
this.editor.setValue(value.year); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
getKey: function () { |
|
return this.editor.getValue() | 0; |
|
} |
|
}); |
|
BI.DynamicYearTrigger.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.DynamicYearTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicYearTrigger.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicYearTrigger.EVENT_START = "EVENT_START"; |
|
BI.DynamicYearTrigger.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicYearTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.shortcut("bi.dynamic_year_trigger", BI.DynamicYearTrigger);/** |
|
* 年月展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.YearCard |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DynamicYearMonthCard = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-year-month-card" |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Multi_Date_Relative_Current_Time"), |
|
textAlign: "left", |
|
height: 24 |
|
}, { |
|
type: "bi.dynamic_date_param_item", |
|
ref: function () { |
|
self.year = this; |
|
}, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}, { |
|
type: "bi.dynamic_date_param_item", |
|
dateType: BI.DynamicDateCard.TYPE.MONTH, |
|
ref: function () { |
|
self.month = this; |
|
}, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}], |
|
vgap: 10, |
|
hgap: 10 |
|
}; |
|
}, |
|
|
|
_createValue: function (type, v) { |
|
return { |
|
dateType: type, |
|
value: Math.abs(v), |
|
offset: v > 0 ? 1 : 0 |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {year: 0, month: 0}; |
|
this.year.setValue(this._createValue(BI.DynamicDateCard.TYPE.YEAR, v.year)); |
|
this.month.setValue(this._createValue(BI.DynamicDateCard.TYPE.MONTH, v.month)); |
|
}, |
|
|
|
getValue: function () { |
|
var year = this.year.getValue(); |
|
var month = this.month.getValue(); |
|
return { |
|
year: (year.offset === 0 ? -year.value : year.value), |
|
month: (month.offset === 0 ? -month.value : month.value) |
|
}; |
|
} |
|
}); |
|
BI.DynamicYearMonthCard.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_year_month_card", BI.DynamicYearMonthCard);BI.StaticYearMonthCard = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-static-year-month-card", |
|
behaviors: {} |
|
}, |
|
|
|
_createMonths: function () { |
|
var self = this; |
|
// 纵向排列月 |
|
var month = [1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12]; |
|
var items = []; |
|
items.push(month.slice(0, 2)); |
|
items.push(month.slice(2, 4)); |
|
items.push(month.slice(4, 6)); |
|
items.push(month.slice(6, 8)); |
|
items.push(month.slice(8, 10)); |
|
items.push(month.slice(10, 12)); |
|
return BI.map(items, function (i, item) { |
|
return BI.map(item, function (j, td) { |
|
return { |
|
type: "bi.text_item", |
|
cls: "bi-list-item-select", |
|
textAlign: "center", |
|
whiteSpace: "nowrap", |
|
once: false, |
|
forceSelected: true, |
|
height: 23, |
|
width: 38, |
|
value: td, |
|
text: td, |
|
ref: function (_ref) { |
|
self.monthMap[j === 0 ? i : i + 6] = _ref; |
|
} |
|
}; |
|
}); |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
this.monthMap = {}; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.year_picker", |
|
min: o.min, |
|
max: o.max, |
|
ref: function () { |
|
self.yearPicker = this; |
|
}, |
|
behaviors: o.behaviors, |
|
height: 30, |
|
listeners: [{ |
|
eventName: BI.YearPicker.EVENT_CHANGE, |
|
action: function () { |
|
var value = this.getValue(); |
|
self._checkMonthStatus(value); |
|
self.setValue({ |
|
year: value, |
|
month: self.selectedMonth |
|
}); |
|
} |
|
}] |
|
}, { |
|
type: "bi.button_group", |
|
cls: "bi-split-top", |
|
behaviors: o.behaviors, |
|
ref: function () { |
|
self.month = this; |
|
}, |
|
items: this._createMonths(), |
|
layouts: [BI.LogicFactory.createLogic("table", BI.extend({ |
|
dynamic: true |
|
}, { |
|
columns: 2, |
|
rows: 6, |
|
columnSize: [1 / 2, 1 / 2], |
|
rowSize: 25 |
|
})), { |
|
type: "bi.center_adapt", |
|
vgap: 1, |
|
hgap: 2 |
|
}], |
|
value: o.value, |
|
listeners: [{ |
|
eventName: BI.ButtonGroup.EVENT_CHANGE, |
|
action: function () { |
|
self.selectedYear = self.yearPicker.getValue(); |
|
self.selectedMonth = this.getValue()[0]; |
|
self.fireEvent(BI.StaticYearMonthCard.EVENT_CHANGE); |
|
} |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
mounted: function() { |
|
this._checkMonthStatus(this.selectedYear); |
|
}, |
|
|
|
_checkMonthStatus: function (year) { |
|
var o = this.options; |
|
var minDate = BI.parseDateTime(o.min, "%Y-%X-%d"), maxDate = BI.parseDateTime(o.max, "%Y-%X-%d"); |
|
var minYear = minDate.getFullYear(), maxYear = maxDate.getFullYear(); |
|
var minMonth = 0; var maxMonth = 11; |
|
minYear === year && (minMonth = minDate.getMonth()); |
|
maxYear === year && (maxMonth = maxDate.getMonth()); |
|
var yearInvalid = year < minYear || year > maxYear; |
|
BI.each(this.monthMap, function (month, obj) { |
|
var monthInvalid = month < minMonth || month > maxMonth; |
|
obj.setEnable(!yearInvalid && !monthInvalid); |
|
}); |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (this.options.min !== minDate) { |
|
this.options.min = minDate; |
|
this.yearPicker.setMinDate(minDate); |
|
this._checkMonthStatus(this.selectedYear); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (this.options.max !== maxDate) { |
|
this.options.max = maxDate; |
|
this.yearPicker.setMaxDate(maxDate); |
|
this._checkMonthStatus(this.selectedYear); |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
year: this.selectedYear, |
|
month: this.selectedMonth |
|
}; |
|
}, |
|
|
|
setValue: function (obj) { |
|
var o = this.options; |
|
var newObj = {}; |
|
newObj.year = obj.year || 0; |
|
newObj.month = obj.month || 0; |
|
if (newObj.year === 0 || newObj.month === 0 || BI.checkDateVoid(newObj.year, newObj.month, 1, o.min, o.max)[0]) { |
|
var year = newObj.year || BI.getDate().getFullYear(); |
|
this.selectedYear = year; |
|
this.selectedMonth = ""; |
|
this.yearPicker.setValue(year); |
|
this.month.setValue(); |
|
} else { |
|
this.selectedYear = BI.parseInt(newObj.year); |
|
this.selectedMonth = BI.parseInt(newObj.month); |
|
this.yearPicker.setValue(this.selectedYear); |
|
this.month.setValue(this.selectedMonth); |
|
} |
|
} |
|
}); |
|
BI.StaticYearMonthCard.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.static_year_month_card", BI.StaticYearMonthCard); |
|
BI.DynamicYearMonthCombo = BI.inherit(BI.Single, { |
|
|
|
props: { |
|
baseCls: "bi-year-month-combo bi-border bi-focus-shadow", |
|
behaviors: {}, |
|
minDate: "1900-01-01", // 最小日期 |
|
maxDate: "2099-12-31", // 最大日期 |
|
height: 22 |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicYearMonthCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.storeValue = o.value; |
|
this.storeTriggerValue = ""; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.dynamic_year_month_trigger", |
|
min: o.minDate, |
|
max: o.maxDate, |
|
height: o.height, |
|
value: o.value || "" |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_KEY_DOWN, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_START, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_STOP, function () { |
|
self.combo.showView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_ERROR, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_ERROR); |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_VALID, function () { |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_VALID); |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_CONFIRM, function () { |
|
// 没看出来干啥的,先去掉 |
|
// if (self.combo.isViewVisible()) { |
|
// return; |
|
// } |
|
var dateStore = self.storeTriggerValue; |
|
var dateObj = self.trigger.getKey(); |
|
if (BI.isNotEmptyString(dateObj) && !BI.isEqual(dateObj, dateStore)) { |
|
self.storeValue = self.trigger.getValue(); |
|
self.setValue(self.trigger.getValue()); |
|
} |
|
self._checkDynamicValue(self.storeValue); |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_CONFIRM); |
|
}); |
|
this.trigger.on(BI.DynamicYearMonthTrigger.EVENT_FOCUS, function () { |
|
self.storeTriggerValue = self.trigger.getKey(); |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_FOCUS); |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: this.trigger, |
|
popup: { |
|
minWidth: 100, |
|
stopPropagation: false, |
|
el: { |
|
type: "bi.dynamic_year_month_popup", |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicYearMonthPopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearMonthPopup.BUTTON_CLEAR_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearMonthPopup.BUTTON_lABEL_EVENT_CHANGE, |
|
action: function () { |
|
var date = BI.getDate(); |
|
self.setValue({type: BI.DynamicYearMonthCombo.Static, value: {year: date.getFullYear(), month: date.getMonth() + 1}}); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearMonthPopup.BUTTON_OK_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}], |
|
behaviors: o.behaviors, |
|
min: o.minDate, |
|
max: o.maxDate |
|
}, |
|
value: o.value || "" |
|
} |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.popup.setValue(self.storeValue); |
|
self.fireEvent(BI.DynamicYearMonthCombo.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
ref: function () { |
|
self.comboWrapper = this; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-change-h-font", |
|
width: 24, |
|
height: 24, |
|
ref: function () { |
|
self.changeIcon = this; |
|
} |
|
}, |
|
width: 24 |
|
}, this.combo] |
|
}); |
|
this._checkDynamicValue(o.value); |
|
}, |
|
|
|
_checkDynamicValue: function (v) { |
|
var type = null; |
|
if (BI.isNotNull(v)) { |
|
type = v.type; |
|
} |
|
switch (type) { |
|
case BI.DynamicYearMonthCombo.Dynamic: |
|
this.changeIcon.setVisible(true); |
|
this.comboWrapper.attr("items")[0].width = 24; |
|
this.comboWrapper.resize(); |
|
break; |
|
default: |
|
this.comboWrapper.attr("items")[0].width = 0; |
|
this.comboWrapper.resize(); |
|
this.changeIcon.setVisible(false); |
|
break; |
|
} |
|
}, |
|
|
|
hideView: function () { |
|
this.combo.hideView(); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.trigger.setValue(v); |
|
this._checkDynamicValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
getKey: function () { |
|
return this.trigger.getKey(); |
|
}, |
|
|
|
isValid: function () { |
|
return this.trigger.isValid(); |
|
} |
|
|
|
}); |
|
BI.DynamicYearMonthCombo.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicYearMonthCombo.EVENT_VALID = "EVENT_VALID"; |
|
BI.DynamicYearMonthCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicYearMonthCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicYearMonthCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.dynamic_year_month_combo", BI.DynamicYearMonthCombo); |
|
|
|
BI.extend(BI.DynamicYearMonthCombo, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});/** |
|
* 年月 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.DynamicYearMonthPopup |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DynamicYearMonthPopup = BI.inherit(BI.Widget, { |
|
constants: { |
|
tabHeight: 30, |
|
buttonHeight: 24 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-year-month-popup", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期, |
|
width: 180, |
|
height: 240 |
|
}, |
|
|
|
render: function () { |
|
var self = this, opts = this.options, c = this.constants; |
|
this.storeValue = {type: BI.DynamicYearMonthCombo.Static}; |
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
el: this._getTabJson() |
|
}, { |
|
el: { |
|
type: "bi.grid", |
|
items: [[{ |
|
type: "bi.text_button", |
|
cls: "bi-split-top bi-high-light", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Clear"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearMonthPopup.BUTTON_CLEAR_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-left bi-split-right bi-high-light bi-split-top", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Current_Month"), |
|
ref: function () { |
|
self.textButton = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearMonthPopup.BUTTON_lABEL_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-top bi-high-light", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_OK"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearMonthPopup.BUTTON_OK_EVENT_CHANGE); |
|
} |
|
}] |
|
}]] |
|
}, |
|
height: 24 |
|
}] |
|
}; |
|
}, |
|
|
|
_setInnerValue: function () { |
|
if (this.dateTab.getSelect() === BI.DynamicDateCombo.Static) { |
|
this.textButton.setValue(BI.i18nText("BI-Basic_Current_Month")); |
|
this.textButton.setEnable(true); |
|
} else { |
|
var date = BI.DynamicDateHelper.getCalculation(this.dynamicPane.getValue()); |
|
date = BI.print(date, "%Y-%x"); |
|
this.textButton.setValue(date); |
|
this.textButton.setEnable(false); |
|
} |
|
}, |
|
|
|
_getTabJson: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
tab: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: this.constants.tabHeight, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Basic_Year_Month"), |
|
value: BI.DynamicYearCombo.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicYearCombo.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}) |
|
}, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicYearCombo.Dynamic: |
|
return { |
|
type: "bi.dynamic_year_month_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self._setInnerValue(self.year, v); |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
case BI.DynamicYearCombo.Static: |
|
default: |
|
return { |
|
type: "bi.static_year_month_card", |
|
behaviors: o.behaviors, |
|
min: self.options.min, |
|
max: self.options.max, |
|
listeners: [{ |
|
eventName: BI.StaticYearMonthCard.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearMonthPopup.EVENT_CHANGE); |
|
} |
|
}], |
|
ref: function () { |
|
self.year = this; |
|
} |
|
}; |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Tab.EVENT_CHANGE, |
|
action: function () { |
|
var v = self.dateTab.getSelect(); |
|
switch (v) { |
|
case BI.DynamicYearCombo.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.year.setValue({year: date.getFullYear(), month: date.getMonth() + 1}); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicYearCombo.Dynamic: |
|
default: |
|
if(self.storeValue && self.storeValue.type === BI.DynamicYearCombo.Dynamic) { |
|
self.dynamicPane.setValue(self.storeValue.value); |
|
}else{ |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
} |
|
self._setInnerValue(); |
|
break; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
setMinDate: function (minDate) { |
|
if (this.options.min !== minDate) { |
|
this.options.min = minDate; |
|
this.year.setMinDate(minDate); |
|
} |
|
}, |
|
|
|
setMaxDate: function (maxDate) { |
|
if (this.options.max !== maxDate) { |
|
this.options.max = maxDate; |
|
this.year.setMaxDate(maxDate); |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
var self = this; |
|
var type, value; |
|
v = v || {}; |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
this.year.setValue(value); |
|
this.textButton.setValue(BI.i18nText("BI-Basic_Current_Month")); |
|
this.textButton.setEnable(true); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: this.dateTab.getSelect(), |
|
value: this.dateTab.getValue() |
|
}; |
|
} |
|
|
|
}); |
|
BI.DynamicYearMonthPopup.BUTTON_CLEAR_EVENT_CHANGE = "BUTTON_CLEAR_EVENT_CHANGE"; |
|
BI.DynamicYearMonthPopup.BUTTON_lABEL_EVENT_CHANGE = "BUTTON_lABEL_EVENT_CHANGE"; |
|
BI.DynamicYearMonthPopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.DynamicYearMonthPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_year_month_popup", BI.DynamicYearMonthPopup);BI.DynamicYearMonthTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4, |
|
vgap: 2 |
|
}, |
|
|
|
props: { |
|
extraCls: "bi-year-month-trigger", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 22 |
|
}, |
|
|
|
beforeInit: function (callback) { |
|
var o = this.options; |
|
o.title = BI.bind(this._titleCreator, this); |
|
callback(); |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicYearMonthTrigger.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
|
|
this.yearEditor = this._createEditor(true); |
|
this.monthEditor = this._createEditor(false); |
|
|
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [{ |
|
type: "bi.center", |
|
items: [{ |
|
type: "bi.htape", |
|
items: [this.yearEditor, { |
|
el: { |
|
type: "bi.text_button", |
|
text: BI.i18nText("BI-Multi_Date_Year"), |
|
width: o.height |
|
}, |
|
width: o.height |
|
}] |
|
}, { |
|
type: "bi.htape", |
|
items: [this.monthEditor, { |
|
el: { |
|
type: "bi.text_button", |
|
text: BI.i18nText("BI-Multi_Date_Month"), |
|
width: o.height |
|
}, |
|
width: o.height}] |
|
}] |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
width: o.height |
|
}, |
|
width: o.height |
|
}] |
|
}); |
|
this.setValue(o.value); |
|
}, |
|
|
|
_createEditor: function (isYear) { |
|
var self = this, o = this.options, c = this._const; |
|
var minDate = BI.parseDateTime(o.min, "%Y-%X-%d"); |
|
var editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
validationChecker: function (v) { |
|
if(isYear) { |
|
return v === "" || (BI.isPositiveInteger(v) && !BI.checkDateVoid(v, v === minDate.getFullYear() ? minDate.getMonth() + 1 : 1, 1, o.min, o.max)[0]); |
|
} |
|
return v === "" || ((BI.isPositiveInteger(v) && v >= 1 && v <= 12) && !BI.checkDateVoid(BI.getDate().getFullYear(), v, 1, o.min, o.max)[0]); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
watermark: BI.i18nText("BI-Basic_Unrestricted"), |
|
errorText: function (v) { |
|
return BI.i18nText("BI-Year_Trigger_Invalid_Text"); |
|
}, |
|
hgap: c.hgap, |
|
vgap: c.vgap, |
|
allowBlank: true |
|
}); |
|
editor.on(BI.SignEditor.EVENT_KEY_DOWN, function () { |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_KEY_DOWN); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_FOCUS); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_STOP, function () { |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_STOP); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_CONFIRM, function () { |
|
self._doEditorConfirm(editor); |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_CONFIRM); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_SPACE, function () { |
|
if (editor.isValid()) { |
|
editor.blur(); |
|
} |
|
}); |
|
editor.on(BI.SignEditor.EVENT_START, function () { |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_START); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_ERROR); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_VALID, function () { |
|
var year = self.yearEditor.getValue(); |
|
var month = self.monthEditor.getValue(); |
|
if(BI.isNotEmptyString(year) && BI.isNotEmptyString(month)) { |
|
if(BI.isPositiveInteger(year) && month >= 1 && month <= 12 && !BI.checkDateVoid(year, month, 1, o.min, o.max)[0]) { |
|
self.fireEvent(BI.DynamicYearMonthTrigger.EVENT_VALID); |
|
} |
|
} |
|
}); |
|
editor.on(BI.SignEditor.EVENT_CHANGE, function () { |
|
if(isYear) { |
|
self._autoSwitch(editor); |
|
} |
|
}); |
|
|
|
return editor; |
|
}, |
|
|
|
_titleCreator: function () { |
|
var storeValue = this.storeValue || {}; |
|
var type = storeValue.type || BI.DynamicDateCombo.Static; |
|
var value = storeValue.value; |
|
if(!this.monthEditor.isValid() || !this.yearEditor.isValid()) { |
|
return ""; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
var date = BI.getDate(); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
var dateStr = BI.print(date, "%Y-%x"); |
|
return BI.isEmptyString(text) ? dateStr : (text + ":" + dateStr); |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
value = value || {}; |
|
return this._getStaticTitle(value); |
|
} |
|
}, |
|
|
|
_doEditorConfirm: function (editor) { |
|
var value = editor.getValue(); |
|
if (BI.isNotNull(value)) { |
|
editor.setValue(value); |
|
} |
|
var monthValue = this.monthEditor.getValue(); |
|
this.storeValue = { |
|
type: BI.DynamicDateCombo.Static, |
|
value: { |
|
year: this.yearEditor.getValue(), |
|
month: BI.isEmptyString(this.monthEditor.getValue()) ? "" : monthValue |
|
} |
|
}; |
|
}, |
|
|
|
_yearCheck: function (v) { |
|
var date = BI.print(BI.parseDateTime(v, "%Y-%X-%d"), "%Y-%X-%d"); |
|
return BI.print(BI.parseDateTime(v, "%Y"), "%Y") === v && date >= this.options.min && date <= this.options.max; |
|
}, |
|
|
|
_autoSwitch: function (editor) { |
|
var v = editor.getValue(); |
|
if (BI.isNotEmptyString(v) && BI.checkDateLegal(v)) { |
|
if (v.length === 4 && this._yearCheck(v)) { |
|
this._doEditorConfirm(editor); |
|
this.fireEvent(BI.DynamicYearMonthTrigger.EVENT_CONFIRM); |
|
this.monthEditor.focus(); |
|
} |
|
} |
|
}, |
|
|
|
_getText: function (obj) { |
|
var value = ""; |
|
if(BI.isNotNull(obj.year) && BI.parseInt(obj.year) !== 0) { |
|
value += Math.abs(obj.year) + BI.i18nText("BI-Basic_Year") + (obj.year < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
if(BI.isNotNull(obj.month) && BI.parseInt(obj.month) !== 0) { |
|
value += Math.abs(obj.month) + BI.i18nText("BI-Basic_Month") + (obj.month < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
return value; |
|
}, |
|
|
|
_setInnerValue: function (date, text) { |
|
this.yearEditor.setValue(date.getFullYear()); |
|
this.monthEditor.setValue(date.getMonth() + 1); |
|
}, |
|
|
|
_getStaticTitle: function (value) { |
|
value = value || {}; |
|
var hasYear = !(BI.isNull(value.year) || BI.isEmptyString(value.year)); |
|
var hasMonth = !(BI.isNull(value.month) || BI.isEmptyString(value.month)); |
|
switch ((hasYear << 1) | hasMonth) { |
|
// !hasYear && !hasMonth |
|
case 0: |
|
return ""; |
|
// !hasYear && hasMonth |
|
case 1: |
|
return value.month; |
|
// hasYear && !hasMonth |
|
case 2: |
|
return value.year; |
|
// hasYear && hasMonth |
|
case 3: |
|
default: |
|
return value.year + "-" + value.month; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
var type, value; |
|
var date = BI.getDate(); |
|
this.storeValue = v; |
|
if (BI.isNotNull(v)) { |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
} |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
var text = this._getText(value); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
this._setInnerValue(date, text); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
value = value || {}; |
|
var month = BI.isNull(value.month) ? null : value.month; |
|
this.yearEditor.setValue(value.year); |
|
this.monthEditor.setValue(month); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
getKey: function () { |
|
return this.yearEditor.getValue() + "-" + this.monthEditor.getValue(); |
|
}, |
|
|
|
isValid: function () { |
|
return this.yearEditor.isValid() && this.monthEditor.isValid(); |
|
} |
|
}); |
|
BI.DynamicYearMonthTrigger.EVENT_VALID = "EVENT_VALID"; |
|
BI.DynamicYearMonthTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicYearMonthTrigger.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicYearMonthTrigger.EVENT_START = "EVENT_START"; |
|
BI.DynamicYearMonthTrigger.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicYearMonthTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.DynamicYearMonthTrigger.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.shortcut("bi.dynamic_year_month_trigger", BI.DynamicYearMonthTrigger);BI.YearMonthInterval = BI.inherit(BI.Single, { |
|
constants: { |
|
height: 24, |
|
width: 25, |
|
lgap: 15, |
|
offset: -15, |
|
timeErrorCls: "time-error" |
|
}, |
|
|
|
props: { |
|
extraCls: "bi-year-month-interval", |
|
minDate: "1900-01-01", |
|
maxDate: "2099-12-31" |
|
}, |
|
|
|
_init: function () { |
|
var self = this, o = this.options; |
|
BI.YearMonthInterval.superclass._init.apply(this, arguments); |
|
|
|
o.value = o.value || {}; |
|
this.left = this._createCombo(o.value.start); |
|
this.right = this._createCombo(o.value.end); |
|
this.label = BI.createWidget({ |
|
type: "bi.label", |
|
height: this.constants.height, |
|
width: this.constants.width, |
|
text: "-" |
|
}); |
|
BI.createWidget({ |
|
element: self, |
|
type: "bi.center", |
|
hgap: 15, |
|
height: this.constants.height, |
|
items: [{ |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.left, |
|
left: this.constants.offset, |
|
right: 0, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}, { |
|
type: "bi.absolute", |
|
items: [{ |
|
el: self.right, |
|
left: 0, |
|
right: this.constants.offset, |
|
top: 0, |
|
bottom: 0 |
|
}] |
|
}] |
|
}); |
|
BI.createWidget({ |
|
type: "bi.horizontal_auto", |
|
element: this, |
|
items: [ |
|
self.label |
|
] |
|
}); |
|
}, |
|
|
|
_createCombo: function (v) { |
|
var self = this, o = this.options; |
|
var combo = BI.createWidget({ |
|
type: "bi.dynamic_year_month_combo", |
|
behaviors: o.behaviors, |
|
value: v, |
|
listeners: [{ |
|
eventName: BI.DynamicYearMonthCombo.EVENT_BEFORE_POPUPVIEW, |
|
action: function () { |
|
self.fireEvent(BI.YearMonthInterval.EVENT_BEFORE_POPUPVIEW); |
|
} |
|
}] |
|
}); |
|
combo.on(BI.DynamicYearMonthCombo.EVENT_ERROR, function () { |
|
self._clearTitle(); |
|
BI.Bubbles.hide("error"); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.YearMonthInterval.EVENT_ERROR); |
|
}); |
|
|
|
combo.on(BI.DynamicYearMonthCombo.EVENT_VALID, function () { |
|
self._checkValid(); |
|
}); |
|
|
|
combo.on(BI.DynamicYearMonthCombo.EVENT_FOCUS, function () { |
|
self._checkValid(); |
|
}); |
|
|
|
combo.on(BI.DynamicYearMonthCombo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.left.hideView(); |
|
self.right.hideView(); |
|
}); |
|
|
|
combo.on(BI.DynamicYearMonthCombo.EVENT_CONFIRM, function () { |
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self.left.isValid() && self.right.isValid() && self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.YearMonthInterval.EVENT_ERROR); |
|
}else{ |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
self.fireEvent(BI.YearMonthInterval.EVENT_CHANGE); |
|
} |
|
}); |
|
return combo; |
|
}, |
|
|
|
|
|
_dateCheck: function (date) { |
|
return BI.print(BI.parseDateTime(date, "%Y-%x"), "%Y-%x") === date || BI.print(BI.parseDateTime(date, "%Y-%X"), "%Y-%X") === date; |
|
}, |
|
|
|
|
|
// 判是否在最大最小之间 |
|
_checkVoid: function (obj) { |
|
var o = this.options; |
|
return !BI.checkDateVoid(obj.year, obj.month, 1, o.minDate, o.maxDate)[0]; |
|
}, |
|
|
|
// 判格式合法 |
|
_check: function (smallDate, bigDate) { |
|
var smallObj = smallDate.match(/\d+/g), bigObj = bigDate.match(/\d+/g); |
|
|
|
var smallDate4Check = ""; |
|
if (BI.isNotNull(smallObj)) { |
|
smallDate4Check = (smallObj[0] || "") + "-" + (smallObj[1] || 1); |
|
} |
|
|
|
var bigDate4Check = ""; |
|
if (BI.isNotNull(bigObj)) { |
|
bigDate4Check = (bigObj[0] || "") + "-" + (bigObj[1] || 1); |
|
} |
|
|
|
return this._dateCheck(smallDate4Check) && BI.checkDateLegal(smallDate) && this._checkVoid({ |
|
year: smallObj[0], |
|
month: smallObj[1], |
|
day: 1 |
|
}) && this._dateCheck(bigDate4Check) && BI.checkDateLegal(bigDate) && this._checkVoid({ |
|
year: bigObj[0], |
|
month: bigObj[1], |
|
day: 1 |
|
}); |
|
}, |
|
|
|
_compare: function (smallDate, bigDate) { |
|
smallDate = BI.print(BI.parseDateTime(smallDate, "%Y-%X"), "%Y-%X"); |
|
bigDate = BI.print(BI.parseDateTime(bigDate, "%Y-%X"), "%Y-%X"); |
|
return BI.isNotNull(smallDate) && BI.isNotNull(bigDate) && smallDate > bigDate; |
|
}, |
|
_setTitle: function (v) { |
|
this.setTitle(v); |
|
}, |
|
_clearTitle: function () { |
|
this.setTitle(""); |
|
}, |
|
_checkValid: function () { |
|
var self = this; |
|
|
|
BI.Bubbles.hide("error"); |
|
var smallDate = self.left.getKey(), bigDate = self.right.getKey(); |
|
if (self.left.isValid() && self.right.isValid() && self._check(smallDate, bigDate) && self._compare(smallDate, bigDate)) { |
|
self._setTitle(BI.i18nText("BI-Time_Interval_Error_Text")); |
|
self.element.addClass(self.constants.timeErrorCls); |
|
BI.Bubbles.show("error", BI.i18nText("BI-Time_Interval_Error_Text"), self, { |
|
offsetStyle: "center" |
|
}); |
|
self.fireEvent(BI.YearMonthInterval.EVENT_ERROR); |
|
} else { |
|
self._clearTitle(); |
|
self.element.removeClass(self.constants.timeErrorCls); |
|
} |
|
}, |
|
setValue: function (date) { |
|
date = date || {}; |
|
this.left.setValue(date.start); |
|
this.right.setValue(date.end); |
|
|
|
this._checkValid(); |
|
}, |
|
getValue: function () { |
|
return {start: this.left.getValue(), end: this.right.getValue()}; |
|
} |
|
}); |
|
BI.YearMonthInterval.EVENT_VALID = "EVENT_VALID"; |
|
BI.YearMonthInterval.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.YearMonthInterval.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.YearMonthInterval.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.year_month_interval", BI.YearMonthInterval); |
|
/** |
|
* 年季度展示面板 |
|
* |
|
* Created by GUY on 2015/9/2. |
|
* @class BI.YearCard |
|
* @extends BI.Trigger |
|
*/ |
|
BI.DynamicYearQuarterCard = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-year-month-card" |
|
}, |
|
|
|
render: function () { |
|
var self = this; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.label", |
|
text: BI.i18nText("BI-Multi_Date_Relative_Current_Time"), |
|
textAlign: "left", |
|
height: 24 |
|
}, { |
|
type: "bi.dynamic_date_param_item", |
|
ref: function () { |
|
self.year = this; |
|
}, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}, { |
|
type: "bi.dynamic_date_param_item", |
|
dateType: BI.DynamicDateCard.TYPE.QUARTER, |
|
ref: function () { |
|
self.quarter = this; |
|
}, |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self.fireEvent("EVENT_CHANGE"); |
|
} |
|
}] |
|
}], |
|
vgap: 10, |
|
hgap: 10 |
|
}; |
|
}, |
|
|
|
_createValue: function (type, v) { |
|
return { |
|
dateType: type, |
|
value: Math.abs(v), |
|
offset: v > 0 ? 1 : 0 |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
v = v || {year: 0, month: 0}; |
|
this.year.setValue(this._createValue(BI.DynamicDateCard.TYPE.YEAR, v.year)); |
|
this.quarter.setValue(this._createValue(BI.DynamicDateCard.TYPE.QUARTER, v.quarter)); |
|
}, |
|
|
|
getValue: function () { |
|
var year = this.year.getValue(); |
|
var quarter = this.quarter.getValue(); |
|
return { |
|
year: (year.offset === 0 ? -year.value : year.value), |
|
quarter: (quarter.offset === 0 ? -quarter.value : quarter.value) |
|
}; |
|
} |
|
}); |
|
BI.DynamicYearQuarterCard.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_year_quarter_card", BI.DynamicYearQuarterCard);BI.StaticYearQuarterCard = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-static-year-quarter-card", |
|
behaviors: {} |
|
}, |
|
|
|
_createQuarter: function () { |
|
|
|
var items = [{ |
|
text: BI.Date._QN[1], |
|
value: 1 |
|
}, { |
|
text: BI.Date._QN[2], |
|
value: 2 |
|
}, { |
|
text: BI.Date._QN[3], |
|
value: 3 |
|
}, { |
|
text: BI.Date._QN[4], |
|
value: 4 |
|
}]; |
|
return BI.map(items, function (j, item) { |
|
return BI.extend(item, { |
|
type: "bi.text_item", |
|
cls: "bi-list-item-select", |
|
textAlign: "center", |
|
whiteSpace: "nowrap", |
|
once: false, |
|
forceSelected: true, |
|
height: 24 |
|
}); |
|
}); |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.vertical", |
|
items: [{ |
|
type: "bi.year_picker", |
|
ref: function () { |
|
self.yearPicker = this; |
|
}, |
|
behaviors: o.behaviors, |
|
height: 30, |
|
listeners: [{ |
|
eventName: BI.YearPicker.EVENT_CHANGE, |
|
action: function () { |
|
var value = this.getValue(); |
|
self.setValue({ |
|
year: value, |
|
quarter: self.selectedQuarter |
|
}); |
|
} |
|
}] |
|
}, { |
|
type: "bi.button_group", |
|
behaviors: o.behaviors, |
|
ref: function () { |
|
self.quarter = this; |
|
}, |
|
items: this._createQuarter(), |
|
layouts: [{ |
|
type: "bi.vertical", |
|
vgap: 10 |
|
}], |
|
value: o.value, |
|
listeners: [{ |
|
eventName: BI.ButtonGroup.EVENT_CHANGE, |
|
action: function () { |
|
self.selectedYear = self.yearPicker.getValue(); |
|
self.selectedQuarter = this.getValue()[0]; |
|
self.fireEvent(BI.StaticYearQuarterCard.EVENT_CHANGE); |
|
} |
|
}] |
|
}] |
|
}; |
|
}, |
|
|
|
|
|
getValue: function () { |
|
return { |
|
year: this.selectedYear, |
|
quarter: this.selectedQuarter |
|
}; |
|
}, |
|
|
|
setValue: function (obj) { |
|
var o = this.options; |
|
var newObj = {}; |
|
newObj.year = obj.year || 0; |
|
newObj.quarter = obj.quarter || 0; |
|
if (newObj.quarter === 0 || newObj.year === 0 || BI.checkDateVoid(newObj.year, newObj.quarter, 1, o.min, o.max)[0]) { |
|
var year = newObj.year || BI.getDate().getFullYear(); |
|
this.selectedYear = year; |
|
this.selectedQuarter = ""; |
|
this.yearPicker.setValue(year); |
|
this.quarter.setValue(); |
|
} else { |
|
this.selectedYear = BI.parseInt(newObj.year); |
|
this.selectedQuarter = BI.parseInt(newObj.quarter); |
|
this.yearPicker.setValue(this.selectedYear); |
|
this.quarter.setValue(this.selectedQuarter); |
|
} |
|
} |
|
}); |
|
BI.StaticYearQuarterCard.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.static_year_quarter_card", BI.StaticYearQuarterCard); |
|
BI.DynamicYearQuarterCombo = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-year-quarter-combo bi-border bi-focus-shadow", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 22 |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicYearQuarterCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.storeValue = o.value; |
|
self.storeTriggerValue = ""; |
|
this.trigger = BI.createWidget({ |
|
type: "bi.dynamic_year_quarter_trigger", |
|
min: o.min, |
|
max: o.max, |
|
height: o.height, |
|
value: o.value || "" |
|
}); |
|
this.trigger.on(BI.DynamicYearQuarterTrigger.EVENT_KEY_DOWN, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearQuarterTrigger.EVENT_START, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearQuarterTrigger.EVENT_STOP, function () { |
|
self.combo.showView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearQuarterTrigger.EVENT_ERROR, function () { |
|
self.combo.isViewVisible() && self.combo.hideView(); |
|
}); |
|
this.trigger.on(BI.DynamicYearQuarterTrigger.EVENT_CONFIRM, function () { |
|
// 没看出来干啥的,先去掉 |
|
// if (self.combo.isViewVisible()) { |
|
// return; |
|
// } |
|
var dateStore = self.storeTriggerValue; |
|
var dateObj = self.trigger.getKey(); |
|
if (BI.isNotEmptyString(dateObj) && !BI.isEqual(dateObj, dateStore)) { |
|
self.storeValue = self.trigger.getValue(); |
|
self.setValue(self.trigger.getValue()); |
|
} |
|
self._checkDynamicValue(self.storeValue); |
|
self.fireEvent(BI.DynamicYearQuarterCombo.EVENT_CONFIRM); |
|
}); |
|
this.trigger.on(BI.DynamicYearQuarterTrigger.EVENT_FOCUS, function () { |
|
self.storeTriggerValue = self.trigger.getKey(); |
|
}); |
|
|
|
this.combo = BI.createWidget({ |
|
type: "bi.combo", |
|
container: o.container, |
|
isNeedAdjustHeight: false, |
|
isNeedAdjustWidth: false, |
|
el: this.trigger, |
|
popup: { |
|
minWidth: 85, |
|
stopPropagation: false, |
|
el: { |
|
type: "bi.dynamic_year_quarter_popup", |
|
ref: function () { |
|
self.popup = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.DynamicYearQuarterPopup.EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearQuarterCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearQuarterPopup.BUTTON_CLEAR_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicYearQuarterCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearQuarterPopup.BUTTON_lABEL_EVENT_CHANGE, |
|
action: function () { |
|
var date = BI.getDate(); |
|
self.setValue({type: BI.DynamicYearMonthCombo.Static, value: {year: date.getFullYear(), quarter: BI.getQuarter(date)}}); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}, { |
|
eventName: BI.DynamicYearQuarterPopup.BUTTON_OK_EVENT_CHANGE, |
|
action: function () { |
|
self.setValue(self.popup.getValue()); |
|
self.combo.hideView(); |
|
self.fireEvent(BI.DynamicDateCombo.EVENT_CONFIRM); |
|
} |
|
}], |
|
behaviors: o.behaviors, |
|
min: o.min, |
|
max: o.max |
|
}, |
|
value: o.value || "" |
|
} |
|
}); |
|
this.combo.on(BI.Combo.EVENT_BEFORE_POPUPVIEW, function () { |
|
self.popup.setValue(self.storeValue); |
|
self.fireEvent(BI.DynamicYearQuarterCombo.EVENT_BEFORE_POPUPVIEW); |
|
}); |
|
|
|
BI.createWidget({ |
|
type: "bi.htape", |
|
element: this, |
|
ref: function () { |
|
self.comboWrapper = this; |
|
}, |
|
items: [{ |
|
el: { |
|
type: "bi.icon_button", |
|
cls: "bi-trigger-icon-button date-change-h-font", |
|
width: 24, |
|
height: 24, |
|
ref: function () { |
|
self.changeIcon = this; |
|
} |
|
}, |
|
width: 24 |
|
}, this.combo] |
|
}); |
|
this._checkDynamicValue(o.value); |
|
}, |
|
|
|
_checkDynamicValue: function (v) { |
|
var type = null; |
|
if (BI.isNotNull(v)) { |
|
type = v.type; |
|
} |
|
switch (type) { |
|
case BI.DynamicYearQuarterCombo.Dynamic: |
|
this.changeIcon.setVisible(true); |
|
this.comboWrapper.attr("items")[0].width = 24; |
|
this.comboWrapper.resize(); |
|
break; |
|
default: |
|
this.comboWrapper.attr("items")[0].width = 0; |
|
this.comboWrapper.resize(); |
|
this.changeIcon.setVisible(false); |
|
break; |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
this.trigger.setValue(v); |
|
this._checkDynamicValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
} |
|
|
|
}); |
|
BI.DynamicYearQuarterCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicYearQuarterCombo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW"; |
|
BI.shortcut("bi.dynamic_year_quarter_combo", BI.DynamicYearQuarterCombo); |
|
|
|
BI.extend(BI.DynamicYearQuarterCombo, { |
|
Static: 1, |
|
Dynamic: 2 |
|
});BI.DynamicYearQuarterPopup = BI.inherit(BI.Widget, { |
|
constants: { |
|
tabHeight: 30, |
|
buttonHeight: 24 |
|
}, |
|
|
|
props: { |
|
baseCls: "bi-year-quarter-popup", |
|
behaviors: {}, |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期, |
|
width: 180, |
|
height: 240 |
|
}, |
|
|
|
render: function () { |
|
var self = this, opts = this.options, c = this.constants; |
|
this.storeValue = {type: BI.DynamicYearQuarterCombo.Static}; |
|
return { |
|
type: "bi.vtape", |
|
items: [{ |
|
el: this._getTabJson() |
|
}, { |
|
el: { |
|
type: "bi.grid", |
|
items: [[{ |
|
type: "bi.text_button", |
|
cls: "bi-split-top bi-high-light", |
|
shadow: true, |
|
textHeight: c.buttonHeight - 1, |
|
text: BI.i18nText("BI-Basic_Clear"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearQuarterPopup.BUTTON_CLEAR_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-left bi-split-right bi-high-light bi-split-top", |
|
textHeight: c.buttonHeight - 1, |
|
shadow: true, |
|
text: BI.i18nText("BI-Basic_Current_Quarter"), |
|
ref: function () { |
|
self.textButton = this; |
|
}, |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearQuarterPopup.BUTTON_lABEL_EVENT_CHANGE); |
|
} |
|
}] |
|
}, { |
|
type: "bi.text_button", |
|
cls: "bi-split-top bi-high-light", |
|
shadow: true, |
|
textHeight: c.buttonHeight - 1, |
|
text: BI.i18nText("BI-Basic_OK"), |
|
listeners: [{ |
|
eventName: BI.TextButton.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearQuarterPopup.BUTTON_OK_EVENT_CHANGE); |
|
} |
|
}] |
|
}]] |
|
}, |
|
height: 24 |
|
}] |
|
}; |
|
}, |
|
|
|
_setInnerValue: function () { |
|
if (this.dateTab.getSelect() === BI.DynamicYearQuarterCombo.Static) { |
|
this.textButton.setValue(BI.i18nText("BI-Basic_Current_Quarter")); |
|
this.textButton.setEnable(true); |
|
} else { |
|
var date = BI.DynamicDateHelper.getCalculation(this.dynamicPane.getValue()); |
|
date = BI.print(date, "%Y-%Q"); |
|
this.textButton.setValue(date); |
|
this.textButton.setEnable(false); |
|
} |
|
}, |
|
|
|
_getTabJson: function () { |
|
var self = this, o = this.options; |
|
return { |
|
type: "bi.tab", |
|
ref: function () { |
|
self.dateTab = this; |
|
}, |
|
tab: { |
|
type: "bi.linear_segment", |
|
cls: "bi-split-bottom", |
|
height: this.constants.tabHeight, |
|
items: BI.createItems([{ |
|
text: BI.i18nText("BI-Basic_Year_Quarter"), |
|
value: BI.DynamicYearQuarterCombo.Static |
|
}, { |
|
text: BI.i18nText("BI-Basic_Dynamic_Title"), |
|
value: BI.DynamicYearQuarterCombo.Dynamic |
|
}], { |
|
textAlign: "center" |
|
}) |
|
}, |
|
cardCreator: function (v) { |
|
switch (v) { |
|
case BI.DynamicYearQuarterCombo.Dynamic: |
|
return { |
|
type: "bi.dynamic_year_quarter_card", |
|
listeners: [{ |
|
eventName: "EVENT_CHANGE", |
|
action: function () { |
|
self._setInnerValue(self.year, v); |
|
} |
|
}], |
|
ref: function () { |
|
self.dynamicPane = this; |
|
} |
|
}; |
|
case BI.DynamicYearQuarterCombo.Static: |
|
default: |
|
return { |
|
type: "bi.static_year_quarter_card", |
|
behaviors: o.behaviors, |
|
min: self.options.min, |
|
max: self.options.max, |
|
listeners: [{ |
|
eventName: BI.DynamicYearCard.EVENT_CHANGE, |
|
action: function () { |
|
self.fireEvent(BI.DynamicYearQuarterPopup.EVENT_CHANGE); |
|
} |
|
}], |
|
ref: function () { |
|
self.year = this; |
|
} |
|
}; |
|
} |
|
}, |
|
listeners: [{ |
|
eventName: BI.Tab.EVENT_CHANGE, |
|
action: function () { |
|
var v = self.dateTab.getSelect(); |
|
switch (v) { |
|
case BI.DynamicYearQuarterCombo.Static: |
|
var date = BI.DynamicDateHelper.getCalculation(self.dynamicPane.getValue()); |
|
self.year.setValue({year: date.getFullYear(), quarter: BI.getQuarter(date)}); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicYearQuarterCombo.Dynamic: |
|
default: |
|
if(self.storeValue && self.storeValue.type === BI.DynamicYearQuarterCombo.Dynamic) { |
|
self.dynamicPane.setValue(self.storeValue.value); |
|
}else{ |
|
self.dynamicPane.setValue({ |
|
year: 0 |
|
}); |
|
} |
|
self._setInnerValue(); |
|
break; |
|
} |
|
} |
|
}] |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
this.storeValue = v; |
|
var self = this; |
|
var type, value; |
|
v = v || {}; |
|
type = v.type || BI.DynamicDateCombo.Static; |
|
value = v.value || v; |
|
this.dateTab.setSelect(type); |
|
switch (type) { |
|
case BI.DynamicDateCombo.Dynamic: |
|
this.dynamicPane.setValue(value); |
|
self._setInnerValue(); |
|
break; |
|
case BI.DynamicDateCombo.Static: |
|
default: |
|
this.year.setValue(value); |
|
this.textButton.setValue(BI.i18nText("BI-Basic_Current_Quarter")); |
|
this.textButton.setEnable(true); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return { |
|
type: this.dateTab.getSelect(), |
|
value: this.dateTab.getValue() |
|
}; |
|
} |
|
|
|
}); |
|
BI.DynamicYearQuarterPopup.BUTTON_CLEAR_EVENT_CHANGE = "BUTTON_CLEAR_EVENT_CHANGE"; |
|
BI.DynamicYearQuarterPopup.BUTTON_lABEL_EVENT_CHANGE = "BUTTON_lABEL_EVENT_CHANGE"; |
|
BI.DynamicYearQuarterPopup.BUTTON_OK_EVENT_CHANGE = "BUTTON_OK_EVENT_CHANGE"; |
|
BI.DynamicYearQuarterPopup.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.dynamic_year_quarter_popup", BI.DynamicYearQuarterPopup);BI.DynamicYearQuarterTrigger = BI.inherit(BI.Trigger, { |
|
_const: { |
|
hgap: 4, |
|
vgap: 2 |
|
}, |
|
|
|
props: { |
|
extraCls: "bi-year-quarter-trigger", |
|
min: "1900-01-01", // 最小日期 |
|
max: "2099-12-31", // 最大日期 |
|
height: 22 |
|
}, |
|
|
|
_init: function () { |
|
BI.DynamicYearQuarterTrigger.superclass._init.apply(this, arguments); |
|
var o = this.options; |
|
|
|
this.yearEditor = this._createEditor(true); |
|
this.quarterEditor = this._createEditor(false); |
|
|
|
BI.createWidget({ |
|
element: this, |
|
type: "bi.htape", |
|
items: [{ |
|
type: "bi.center", |
|
items: [{ |
|
type: "bi.htape", |
|
items: [this.yearEditor, { |
|
el: { |
|
type: "bi.text_button", |
|
text: BI.i18nText("BI-Multi_Date_Year"), |
|
width: o.height |
|
}, |
|
width: o.height |
|
}] |
|
}, { |
|
type: "bi.htape", |
|
items: [this.quarterEditor, { |
|
el: { |
|
type: "bi.text_button", |
|
text: BI.i18nText("BI-Multi_Date_Quarter"), |
|
width: 24 |
|
}, |
|
width: 24}] |
|
}] |
|
}, { |
|
el: { |
|
type: "bi.trigger_icon_button", |
|
width: o.height |
|
}, |
|
width: o.height |
|
}] |
|
}); |
|
this.setValue(o.value); |
|
}, |
|
|
|
_createEditor: function (isYear) { |
|
var self = this, o = this.options, c = this._const; |
|
var editor = BI.createWidget({ |
|
type: "bi.sign_editor", |
|
height: o.height, |
|
validationChecker: function (v) { |
|
if(isYear) { |
|
return v === "" || (BI.isPositiveInteger(v) && !BI.checkDateVoid(v, 1, 1, o.min, o.max)[0]); |
|
} |
|
return v === "" || ((BI.isPositiveInteger(v) && v >= 1 && v <= 4) && !BI.checkDateVoid(BI.getDate().getFullYear(), v, 1, o.min, o.max)[0]); |
|
}, |
|
quitChecker: function () { |
|
return false; |
|
}, |
|
errorText: function (v) { |
|
return BI.i18nText("BI-Year_Trigger_Invalid_Text"); |
|
}, |
|
watermark: BI.i18nText("BI-Basic_Unrestricted"), |
|
hgap: c.hgap, |
|
vgap: c.vgap, |
|
title: "", |
|
allowBlank: true |
|
}); |
|
editor.on(BI.SignEditor.EVENT_KEY_DOWN, function () { |
|
self.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_KEY_DOWN); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_FOCUS, function () { |
|
self.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_FOCUS); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_STOP, function () { |
|
self.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_STOP); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_CONFIRM, function () { |
|
self._doEditorConfirm(editor); |
|
self.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_CONFIRM); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_SPACE, function () { |
|
if (editor.isValid()) { |
|
editor.blur(); |
|
} |
|
}); |
|
editor.on(BI.SignEditor.EVENT_START, function () { |
|
self.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_START); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_ERROR, function () { |
|
self.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_ERROR); |
|
}); |
|
editor.on(BI.SignEditor.EVENT_CHANGE, function () { |
|
if(isYear) { |
|
self._autoSwitch(editor); |
|
} |
|
}); |
|
|
|
return editor; |
|
}, |
|
|
|
_doEditorConfirm: function (editor) { |
|
var value = editor.getValue(); |
|
if (BI.isNotNull(value)) { |
|
editor.setValue(value); |
|
} |
|
var quarterValue = this.quarterEditor.getValue(); |
|
this.storeValue = { |
|
type: BI.DynamicYearQuarterCombo.Static, |
|
value: { |
|
year: this.yearEditor.getValue(), |
|
quarter: BI.isEmptyString(this.quarterEditor.getValue()) ? "" : quarterValue |
|
} |
|
}; |
|
this.setTitle(this._getStaticTitle(this.storeValue.value)); |
|
}, |
|
|
|
_yearCheck: function (v) { |
|
var date = BI.print(BI.parseDateTime(v, "%Y-%X-%d"), "%Y-%X-%d"); |
|
return BI.print(BI.parseDateTime(v, "%Y"), "%Y") === v && date >= this.options.min && date <= this.options.max; |
|
}, |
|
|
|
_autoSwitch: function (editor) { |
|
var v = editor.getValue(); |
|
if (BI.isNotEmptyString(v) && BI.checkDateLegal(v)) { |
|
if (v.length === 4 && this._yearCheck(v)) { |
|
this._doEditorConfirm(editor); |
|
this.fireEvent(BI.DynamicYearQuarterTrigger.EVENT_CONFIRM); |
|
this.quarterEditor.focus(); |
|
} |
|
} |
|
}, |
|
|
|
_getStaticTitle: function (value) { |
|
value = value || {}; |
|
var hasYear = !(BI.isNull(value.year) || BI.isEmptyString(value.year)); |
|
var hasMonth = !(BI.isNull(value.quarter) || BI.isEmptyString(value.quarter)); |
|
switch ((hasYear << 1) | hasMonth) { |
|
// !hasYear && !hasMonth |
|
case 0: |
|
return ""; |
|
// !hasYear && hasMonth |
|
case 1: |
|
return value.quarter; |
|
// hasYear && !hasMonth |
|
case 2: |
|
return value.year; |
|
// hasYear && hasMonth |
|
case 3: |
|
default: |
|
return value.year + "-" + value.quarter; |
|
} |
|
}, |
|
|
|
_getText: function (obj) { |
|
var value = ""; |
|
if(BI.isNotNull(obj.year) && BI.parseInt(obj.year) !== 0) { |
|
value += Math.abs(obj.year) + BI.i18nText("BI-Basic_Year") + (obj.year < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
if(BI.isNotNull(obj.quarter) && BI.parseInt(obj.quarter) !== 0) { |
|
value += Math.abs(obj.quarter) + BI.i18nText("BI-Basic_Single_Quarter") + (obj.quarter < 0 ? BI.i18nText("BI-Basic_Front") : BI.i18nText("BI-Basic_Behind")); |
|
} |
|
return value; |
|
}, |
|
|
|
_setInnerValue: function (date, text) { |
|
var dateStr = BI.print(date, "%Y-%Q"); |
|
this.yearEditor.setValue(date.getFullYear()); |
|
this.quarterEditor.setValue(BI.getQuarter(date)); |
|
this.setTitle(BI.isEmptyString(text) ? dateStr : (text + ":" + dateStr)); |
|
}, |
|
|
|
setValue: function (v) { |
|
var type, value; |
|
var date = BI.getDate(); |
|
this.storeValue = v; |
|
if (BI.isNotNull(v)) { |
|
type = v.type || BI.DynamicYearQuarterCombo.Static; |
|
value = v.value || v; |
|
} |
|
switch (type) { |
|
case BI.DynamicYearQuarterCombo.Dynamic: |
|
var text = this._getText(value); |
|
date = BI.DynamicDateHelper.getCalculation(value); |
|
this._setInnerValue(date, text); |
|
break; |
|
case BI.DynamicYearQuarterCombo.Static: |
|
default: |
|
value = value || {}; |
|
var quarter = BI.isNull(value.quarter) ? null : value.quarter; |
|
this.yearEditor.setValue(value.year); |
|
this.yearEditor.setTitle(value.year); |
|
this.quarterEditor.setValue(quarter); |
|
this.quarterEditor.setTitle(quarter); |
|
this.setTitle(this._getStaticTitle(value)); |
|
break; |
|
} |
|
}, |
|
|
|
getValue: function () { |
|
return this.storeValue; |
|
}, |
|
|
|
getKey: function () { |
|
return this.yearEditor.getValue() + "-" + this.quarterEditor.getValue(); |
|
} |
|
}); |
|
BI.DynamicYearQuarterTrigger.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.DynamicYearQuarterTrigger.EVENT_ERROR = "EVENT_ERROR"; |
|
BI.DynamicYearQuarterTrigger.EVENT_START = "EVENT_START"; |
|
BI.DynamicYearQuarterTrigger.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.DynamicYearQuarterTrigger.EVENT_STOP = "EVENT_STOP"; |
|
BI.DynamicYearQuarterTrigger.EVENT_KEY_DOWN = "EVENT_KEY_DOWN"; |
|
BI.shortcut("bi.dynamic_year_quarter_trigger", BI.DynamicYearQuarterTrigger);/** |
|
* 简单的复选下拉框控件, 适用于数据量少的情况, 与valuechooser的区别是allvaluechooser setValue和getValue返回的是所有值 |
|
* 封装了字段处理逻辑 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.AbstractAllValueChooser |
|
* @extends BI.Widget |
|
*/ |
|
BI.AbstractAllValueChooser = BI.inherit(BI.Widget, { |
|
|
|
_const: { |
|
perPage: 100 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.AbstractAllValueChooser.superclass._defaultConfig.apply(this, arguments), { |
|
width: 200, |
|
height: 30, |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_valueFormatter: function (v) { |
|
var text = v; |
|
if (BI.isNotNull(this.items)) { |
|
BI.some(this.items, function (i, item) { |
|
// 把value都换成字符串 |
|
// 需要考虑到value也可能是数字 |
|
if (item.value === v || item.value + "" === v) { |
|
text = item.text; |
|
return true; |
|
} |
|
}); |
|
} |
|
return text; |
|
}, |
|
|
|
_itemsCreator: function (options, callback) { |
|
var self = this, o = this.options; |
|
if (!o.cache || !this.items) { |
|
o.itemsCreator({}, function (items) { |
|
self.items = items; |
|
call(items); |
|
}); |
|
} else { |
|
call(this.items); |
|
} |
|
function call (items) { |
|
var keywords = (options.keywords || []).slice(); |
|
if (options.keyword) { |
|
keywords.push(options.keyword); |
|
} |
|
var resultItems = items; |
|
if(BI.isNotEmptyArray(keywords)) { |
|
resultItems = []; |
|
BI.each(keywords, function (i, kw) { |
|
var search = BI.Func.getSearchResult(items, kw); |
|
resultItems = resultItems.concat(search.match).concat(search.find); |
|
}); |
|
resultItems = BI.uniq(resultItems); |
|
} |
|
if (options.selectedValues) {// 过滤 |
|
var filter = BI.makeObject(options.selectedValues, true); |
|
resultItems = BI.filter(resultItems, function (i, ob) { |
|
return !filter[ob.value]; |
|
}); |
|
} |
|
if (options.type === BI.MultiSelectCombo.REQ_GET_ALL_DATA) { |
|
callback({ |
|
items: resultItems |
|
}); |
|
return; |
|
} |
|
if (options.type === BI.MultiSelectCombo.REQ_GET_DATA_LENGTH) { |
|
callback({count: resultItems.length}); |
|
return; |
|
} |
|
callback({ |
|
items: resultItems, |
|
hasNext: false |
|
}); |
|
} |
|
} |
|
});/** |
|
* 简单的复选下拉框控件, 适用于数据量少的情况, 与valuechooser的区别是allvaluechooser setValue和getValue返回的是所有值 |
|
* 封装了字段处理逻辑 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.AllValueChooserCombo |
|
* @extends BI.AbstractAllValueChooser |
|
*/ |
|
BI.AllValueChooserCombo = BI.inherit(BI.AbstractAllValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.AllValueChooserCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-all-value-chooser-combo", |
|
width: 200, |
|
height: 24, |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.AllValueChooserCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this.items = o.items; |
|
} |
|
this.combo = BI.createWidget({ |
|
type: "bi.multi_select_combo", |
|
text: o.text, |
|
element: this, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height, |
|
value: { |
|
type: BI.Selection.Multi, |
|
value: o.value || [] |
|
} |
|
}); |
|
|
|
this.combo.on(BI.MultiSelectCombo.EVENT_CONFIRM, function () { |
|
self.fireEvent(BI.AllValueChooserCombo.EVENT_CONFIRM); |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue({ |
|
type: BI.Selection.Multi, |
|
value: v || [] |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.combo.getValue() || {}; |
|
if (val.type === BI.Selection.All) { |
|
return val.assist; |
|
} |
|
return val.value || []; |
|
}, |
|
|
|
populate: function (items) { |
|
// 直接用combo的populate不会作用到AbstractValueChooser上 |
|
this.items = items; |
|
this.combo.populate.apply(this, arguments); |
|
} |
|
}); |
|
BI.AllValueChooserCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.all_value_chooser_combo", BI.AllValueChooserCombo);/** |
|
* 简单的复选面板, 适用于数据量少的情况, 与valuechooser的区别是allvaluechooser setValue和getValue返回的是所有值 |
|
* 封装了字段处理逻辑 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.AllValueChooserPane |
|
* @extends BI.AbstractAllValueChooser |
|
*/ |
|
BI.AllValueChooserPane = BI.inherit(BI.AbstractAllValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.AllValueChooserPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-all-value-chooser-pane", |
|
width: 200, |
|
height: 30, |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.AllValueChooserPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this.items = o.items; |
|
} |
|
this.list = BI.createWidget({ |
|
type: "bi.multi_select_list", |
|
element: this, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height |
|
}); |
|
|
|
this.list.on(BI.MultiSelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.AllValueChooserPane.EVENT_CHANGE); |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.list.setValue({ |
|
type: BI.Selection.Multi, |
|
value: v || [] |
|
}); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.list.getValue() || {}; |
|
if (val.type === BI.Selection.All) { |
|
return val.assist; |
|
} |
|
return val.value || []; |
|
}, |
|
|
|
populate: function (items) { |
|
// 直接用combo的populate不会作用到AbstractValueChooser上 |
|
this.items = items; |
|
this.list.populate.apply(this.list, arguments); |
|
} |
|
}); |
|
BI.AllValueChooserPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.all_value_chooser_pane", BI.AllValueChooserPane);BI.AllValueMultiTextValueCombo = BI.inherit(BI.Widget, { |
|
|
|
props: { |
|
baseCls: "bi-all-value-multi-text-value-combo", |
|
width: 200, |
|
height: 24, |
|
items: [] |
|
}, |
|
|
|
render: function () { |
|
var self = this, o = this.options; |
|
var value = this._digestValue(o.value); |
|
return { |
|
type: "bi.search_multi_text_value_combo", |
|
text: o.text, |
|
height: o.height, |
|
items: o.items, |
|
value: value, |
|
numOfPage: 100, |
|
valueFormatter: o.valueFormatter, |
|
warningTitle: o.warningTitle, |
|
listeners: [{ |
|
eventName: BI.SearchMultiTextValueCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.AllValueMultiTextValueCombo.EVENT_CONFIRM); |
|
} |
|
}], |
|
ref: function () { |
|
self.combo = this; |
|
} |
|
}; |
|
}, |
|
|
|
setValue: function (v) { |
|
var value = this._digestValue(v); |
|
this.combo.setValue(value); |
|
}, |
|
|
|
getValue: function () { |
|
var obj = this.combo.getValue() || {}; |
|
obj.value = obj.value || []; |
|
if(obj.type === BI.Selection.All) { |
|
var values = []; |
|
BI.each(this.options.items, function (idx, item) { |
|
!BI.contains(obj.value, item.value) && values.push(item.value); |
|
}); |
|
return values; |
|
} |
|
return obj.value || []; |
|
}, |
|
|
|
populate: function (items) { |
|
this.options.items = items; |
|
this.combo.populate.apply(this, arguments); |
|
}, |
|
|
|
_digestValue: function (v) { |
|
return { |
|
type: BI.Selection.Multi, |
|
value: v || [] |
|
}; |
|
} |
|
}); |
|
BI.AllValueMultiTextValueCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.all_value_multi_text_value_combo", BI.AllValueMultiTextValueCombo); |
|
BI.AbstractTreeValueChooser = BI.inherit(BI.Widget, { |
|
|
|
_const: { |
|
perPage: 100 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.AbstractTreeValueChooser.superclass._defaultConfig.apply(this, arguments), { |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
open: false |
|
}); |
|
}, |
|
|
|
_valueFormatter: function (v) { |
|
var text = v; |
|
if (BI.isNotNull(this.items)) { |
|
BI.some(this.items, function (i, item) { |
|
if (item.value === v || item.value + "" === v) { |
|
text = item.text; |
|
return true; |
|
} |
|
}); |
|
} |
|
return text; |
|
}, |
|
|
|
_initData: function (items) { |
|
this.items = items; |
|
var nodes = BI.Tree.treeFormat(items); |
|
this.tree = new BI.Tree(); |
|
this.tree.initTree(nodes); |
|
}, |
|
|
|
_itemsCreator: function (options, callback) { |
|
var self = this, o = this.options; |
|
if (!this.items) { |
|
o.itemsCreator({}, function (items) { |
|
self._initData(items); |
|
call(); |
|
}); |
|
} else { |
|
call(); |
|
} |
|
|
|
function call() { |
|
switch (options.type) { |
|
case BI.TreeView.REQ_TYPE_INIT_DATA: |
|
self._reqInitTreeNode(options, callback); |
|
break; |
|
case BI.TreeView.REQ_TYPE_ADJUST_DATA: |
|
self._reqAdjustTreeNode(options, callback); |
|
break; |
|
case BI.TreeView.REQ_TYPE_SELECT_DATA: |
|
self._reqSelectedTreeNode(options, callback); |
|
break; |
|
case BI.TreeView.REQ_TYPE_GET_SELECTED_DATA: |
|
self._reqDisplayTreeNode(options, callback); |
|
break; |
|
default : |
|
self._reqTreeNode(options, callback); |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
_reqDisplayTreeNode: function (op, callback) { |
|
var self = this; |
|
var result = []; |
|
var selectedValues = op.selectedValues; |
|
|
|
if (selectedValues == null || BI.isEmpty(selectedValues)) { |
|
callback({}); |
|
return; |
|
} |
|
|
|
doCheck([], this.tree.getRoot(), selectedValues); |
|
|
|
callback({ |
|
items: result |
|
}); |
|
|
|
function doCheck(parentValues, node, selected) { |
|
if (selected == null || BI.isEmpty(selected)) { |
|
BI.each(node.getChildren(), function (i, child) { |
|
var newParents = BI.clone(parentValues); |
|
newParents.push(child.value); |
|
var llen = self._getChildCount(newParents); |
|
createOneJson(child, node.id, llen); |
|
doCheck(newParents, child, {}); |
|
}); |
|
return; |
|
} |
|
BI.each(selected, function (k) { |
|
var node = self._getTreeNode(parentValues, k); |
|
// 找不到就是新增值 |
|
if(BI.isNull(node)) { |
|
createOneJson({ |
|
id: BI.UUID(), |
|
text: k, |
|
value: k |
|
}, BI.UUID(), 0); |
|
} else { |
|
var newParents = BI.clone(parentValues); |
|
newParents.push(node.value); |
|
createOneJson(node, node.parent && node.parent.id, getCount(selected[k], newParents)); |
|
doCheck(newParents, node, selected[k]); |
|
} |
|
}); |
|
} |
|
|
|
function getCount(jo, parentValues) { |
|
if (jo == null) { |
|
return 0; |
|
} |
|
if (BI.isEmpty(jo)) { |
|
return self._getChildCount(parentValues); |
|
} |
|
|
|
return BI.size(jo); |
|
} |
|
|
|
function createOneJson(node, pId, llen) { |
|
result.push({ |
|
id: node.id, |
|
pId: pId, |
|
text: node.text + (llen > 0 ? ("(" + BI.i18nText("BI-Basic_Altogether") + llen + BI.i18nText("BI-Basic_Count") + ")") : ""), |
|
value: node.value, |
|
open: true |
|
}); |
|
} |
|
}, |
|
|
|
_reqSelectedTreeNode: function (op, callback) { |
|
var self = this; |
|
var selectedValues = BI.deepClone(op.selectedValues); |
|
var notSelectedValue = op.notSelectedValue || {}; |
|
var keyword = op.keyword || ""; |
|
var parentValues = op.parentValues || []; |
|
|
|
if (selectedValues == null || BI.isEmpty(selectedValues)) { |
|
callback({}); |
|
return; |
|
} |
|
|
|
dealWithSelectedValues(selectedValues); |
|
callback(selectedValues); |
|
|
|
|
|
function dealWithSelectedValues(selectedValues) { |
|
var p = parentValues.concat(notSelectedValue); |
|
// 存储的值中存在这个值就把它删掉 |
|
// 例如选中了中国-江苏-南京, 取消中国或江苏或南京 |
|
if (canFindKey(selectedValues, p)) { |
|
// 如果搜索的值在父亲链中 |
|
if (isSearchValueInParent(p)) { |
|
// 例如选中了 中国-江苏, 搜索江苏, 取消江苏 |
|
// 例如选中了 中国-江苏, 搜索江苏, 取消中国 |
|
self._deleteNode(selectedValues, p); |
|
} else { |
|
var searched = []; |
|
var find = search(parentValues, notSelectedValue, [], searched); |
|
if (find && BI.isNotEmptyArray(searched)) { |
|
BI.each(searched, function (i, arr) { |
|
var node = self._getNode(selectedValues, arr); |
|
if (node) { |
|
// 例如选中了 中国-江苏-南京,搜索南京,取消中国 |
|
self._deleteNode(selectedValues, arr); |
|
} else { |
|
// 例如选中了 中国-江苏,搜索南京,取消中国 |
|
expandSelectedValue(selectedValues, arr, BI.last(arr)); |
|
} |
|
}); |
|
} |
|
} |
|
} |
|
|
|
// 存储的值中不存在这个值,但父亲节点是全选的情况 |
|
// 例如选中了中国-江苏,取消南京 |
|
// important 选中了中国-江苏,取消了江苏,但是搜索的是南京 |
|
if (isChild(selectedValues, p)) { |
|
var result = [], find = false; |
|
// 如果parentValues中有匹配的值,说明搜索结果不在当前值下 |
|
if (isSearchValueInParent(p)) { |
|
find = true; |
|
} else { |
|
// 从当前值开始搜 |
|
find = search(parentValues, notSelectedValue, result); |
|
p = parentValues; |
|
} |
|
|
|
if (find === true) { |
|
// 去掉点击的节点之后的结果集 |
|
expandSelectedValue(selectedValues, p, notSelectedValue); |
|
// 添加去掉搜索的结果集 |
|
if (result.length > 0) { |
|
BI.each(result, function (i, strs) { |
|
self._buildTree(selectedValues, strs); |
|
}); |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
function expandSelectedValue(selectedValues, parents, notSelectedValue) { |
|
var next = selectedValues; |
|
var childrenCount = []; |
|
var path = []; |
|
// 去掉点击的节点之后的结果集 |
|
BI.some(parents, function (i, v) { |
|
var t = next[v]; |
|
if (t == null) { |
|
if (i === 0) { |
|
return true; |
|
} |
|
if (BI.isEmpty(next)) { |
|
var split = parents.slice(0, i); |
|
var expanded = self._getChildren(split); |
|
path.push(split); |
|
childrenCount.push(expanded.length); |
|
// 如果只有一个值且取消的就是这个值 |
|
if (i === parents.length - 1 && expanded.length === 1 && expanded[0].value === notSelectedValue) { |
|
for (var j = childrenCount.length - 1; j >= 0; j--) { |
|
if (childrenCount[j] === 1) { |
|
self._deleteNode(selectedValues, path[j]); |
|
} else { |
|
break; |
|
} |
|
} |
|
} else { |
|
BI.each(expanded, function (m, child) { |
|
if (i === parents.length - 1 && child.value === notSelectedValue) { |
|
return true; |
|
} |
|
next[child.value] = {}; |
|
}); |
|
} |
|
next = next[v]; |
|
} else { |
|
return true; |
|
// next = {}; |
|
// next[v] = {}; |
|
} |
|
} else { |
|
next = t; |
|
} |
|
}); |
|
} |
|
|
|
function search(parents, current, result, searched) { |
|
var newParents = BI.clone(parents); |
|
newParents.push(current); |
|
if (self._isMatch(parents, current, keyword)) { |
|
searched && searched.push(newParents); |
|
return true; |
|
} |
|
|
|
var children = self._getChildren(newParents); |
|
|
|
var notSearch = []; |
|
var can = false; |
|
|
|
BI.each(children, function (i, child) { |
|
if (search(newParents, child.value, result, searched)) { |
|
can = true; |
|
} else { |
|
notSearch.push(child.value); |
|
} |
|
}); |
|
if (can === true) { |
|
BI.each(notSearch, function (i, v) { |
|
var next = BI.clone(newParents); |
|
next.push(v); |
|
result.push(next); |
|
}); |
|
} |
|
return can; |
|
} |
|
|
|
function isSearchValueInParent(parentValues) { |
|
for (var i = 0, len = parentValues.length; i < len; i++) { |
|
if (self._isMatch(parentValues.slice(0, i), parentValues[i], keyword)) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
function canFindKey(selectedValues, parents) { |
|
var t = selectedValues; |
|
for (var i = 0; i < parents.length; i++) { |
|
var v = parents[i]; |
|
t = t[v]; |
|
if (t == null) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
function isChild(selectedValues, parents) { |
|
var t = selectedValues; |
|
for (var i = 0; i < parents.length; i++) { |
|
var v = parents[i]; |
|
if (!BI.has(t, v)) { |
|
return false; |
|
} |
|
t = t[v]; |
|
if (BI.isEmpty(t)) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
}, |
|
|
|
_reqAdjustTreeNode: function (op, callback) { |
|
var self = this; |
|
var result = []; |
|
var selectedValues = op.selectedValues; |
|
if (selectedValues == null || BI.isEmpty(selectedValues)) { |
|
callback({}); |
|
return; |
|
} |
|
BI.each(selectedValues, function (k, v) { |
|
result.push([k]); |
|
}); |
|
|
|
dealWithSelectedValues(selectedValues, []); |
|
|
|
var jo = {}; |
|
BI.each(result, function (i, strs) { |
|
self._buildTree(jo, strs); |
|
}); |
|
callback(jo); |
|
|
|
function dealWithSelectedValues(selected, parents) { |
|
if (selected == null || BI.isEmpty(selected)) { |
|
return true; |
|
} |
|
var can = true; |
|
BI.each(selected, function (k, v) { |
|
var p = BI.clone(parents); |
|
p.push(k); |
|
if (!dealWithSelectedValues(selected[k], p)) { |
|
BI.each(selected[k], function (nk, nv) { |
|
var t = BI.clone(p); |
|
t.push(nk); |
|
result.push(t); |
|
}); |
|
can = false; |
|
} |
|
}); |
|
return can && isAllSelected(selected, parents); |
|
} |
|
|
|
function isAllSelected(selected, parents) { |
|
return BI.isEmpty(selected) || self._getChildCount(parents) === BI.size(selected); |
|
} |
|
}, |
|
|
|
_reqInitTreeNode: function (op, callback) { |
|
var self = this; |
|
var result = []; |
|
var keyword = op.keyword || ""; |
|
var selectedValues = op.selectedValues; |
|
var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 |
|
var output = search(); |
|
BI.nextTick(function () { |
|
callback({ |
|
hasNext: output.length > self._const.perPage, |
|
items: result, |
|
lastSearchValue: BI.last(output) |
|
}); |
|
}); |
|
|
|
function search() { |
|
var children = self._getChildren([]); |
|
var start = children.length; |
|
if (lastSearchValue !== "") { |
|
for (var j = 0, len = start; j < len; j++) { |
|
if (children[j].value === lastSearchValue) { |
|
start = j + 1; |
|
break; |
|
} |
|
} |
|
} else { |
|
start = 0; |
|
} |
|
var output = []; |
|
for (var i = start, len = children.length; i < len; i++) { |
|
if (output.length < self._const.perPage) { |
|
var find = nodeSearch(1, [], children[i].value, false, result); |
|
} else if (output.length === self._const.perPage) { |
|
var find = nodeSearch(1, [], children[i].value, false, []); |
|
} |
|
if (find[0] === true) { |
|
output.push(children[i].value); |
|
} |
|
if (output.length > self._const.perPage) { |
|
break; |
|
} |
|
} |
|
|
|
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加 |
|
if (op.times === 1) { |
|
var nodes = self._getAddedValueNode([], selectedValues); |
|
result = BI.concat(BI.filter(nodes, function (idx, node) { |
|
var find = BI.Func.getSearchResult([node.text || node.value], keyword); |
|
return find.find.length > 0 || find.match.length > 0; |
|
}), result); |
|
} |
|
return output; |
|
} |
|
|
|
function nodeSearch(deep, parentValues, current, isAllSelect, result) { |
|
if (self._isMatch(parentValues, current, keyword)) { |
|
var checked = isAllSelect || isSelected(parentValues, current); |
|
createOneJson(parentValues, current, false, checked, !isAllSelect && isHalf(parentValues, current), true, result); |
|
return [true, checked]; |
|
} |
|
var newParents = BI.clone(parentValues); |
|
newParents.push(current); |
|
var children = self._getChildren(newParents); |
|
|
|
var can = false, checked = false; |
|
|
|
var isCurAllSelected = isAllSelect || isAllSelected(parentValues, current); |
|
BI.each(children, function (i, child) { |
|
var state = nodeSearch(deep + 1, newParents, child.value, isCurAllSelected, result); |
|
if (state[1] === true) { |
|
checked = true; |
|
} |
|
if (state[0] === true) { |
|
can = true; |
|
} |
|
}); |
|
if (can === true) { |
|
checked = isCurAllSelected || (isSelected(parentValues, current) && checked); |
|
createOneJson(parentValues, current, true, checked, false, false, result); |
|
} |
|
return [can, checked]; |
|
} |
|
|
|
function createOneJson(parentValues, value, isOpen, checked, half, flag, result) { |
|
var node = self._getTreeNode(parentValues, value); |
|
result.push({ |
|
id: node.id, |
|
pId: node.pId, |
|
text: node.text, |
|
value: node.value, |
|
title: node.title, |
|
isParent: node.getChildrenLength() > 0, |
|
open: isOpen, |
|
checked: checked, |
|
halfCheck: half, |
|
flag: flag |
|
}); |
|
} |
|
|
|
function isHalf(parentValues, value) { |
|
var find = findSelectedObj(parentValues); |
|
if (find == null) { |
|
return null; |
|
} |
|
return BI.any(find, function (v, ob) { |
|
if (v === value) { |
|
if (ob != null && !BI.isEmpty(ob)) { |
|
return true; |
|
} |
|
} |
|
}); |
|
} |
|
|
|
function isAllSelected(parentValues, value) { |
|
var find = findSelectedObj(parentValues); |
|
if (find == null) { |
|
return null; |
|
} |
|
return BI.any(find, function (v, ob) { |
|
if (v === value) { |
|
if (ob != null && BI.isEmpty(ob)) { |
|
return true; |
|
} |
|
} |
|
}); |
|
} |
|
|
|
function isSelected(parentValues, value) { |
|
var find = findSelectedObj(parentValues); |
|
if (find == null) { |
|
return false; |
|
} |
|
return BI.any(find, function (v) { |
|
if (v === value) { |
|
return true; |
|
} |
|
}); |
|
} |
|
|
|
function findSelectedObj(parentValues) { |
|
var find = selectedValues; |
|
if (find == null) { |
|
return null; |
|
} |
|
BI.every(parentValues, function (i, v) { |
|
find = find[v]; |
|
if (find == null) { |
|
return false; |
|
} |
|
return true; |
|
}); |
|
return find; |
|
} |
|
}, |
|
|
|
_reqTreeNode: function (op, callback) { |
|
var self = this, o = this.options; |
|
var result = []; |
|
var times = op.times; |
|
var checkState = op.checkState || {}; |
|
var parentValues = op.parentValues || []; |
|
var selectedValues = op.selectedValues || {}; |
|
var valueMap = {}; |
|
// if (judgeState(parentValues, selectedValues, checkState)) { |
|
valueMap = dealWithSelectedValue(parentValues, selectedValues); |
|
// } |
|
var nodes = this._getChildren(parentValues); |
|
for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { |
|
var state = getCheckState(nodes[i].value, parentValues, valueMap, checkState); |
|
result.push({ |
|
id: nodes[i].id, |
|
pId: nodes[i].pId, |
|
value: nodes[i].value, |
|
text: nodes[i].text, |
|
times: 1, |
|
isParent: nodes[i].getChildrenLength() > 0, |
|
checked: state[0], |
|
halfCheck: state[1], |
|
open: o.open |
|
}); |
|
} |
|
// 如果指定节点全部打开 |
|
if (o.open) { |
|
var allNodes = []; |
|
// 获取所有节点 |
|
BI.each(nodes, function (idx, node) { |
|
allNodes = BI.concat(allNodes, self._getAllChildren(parentValues.concat([node.value]))); |
|
}); |
|
BI.each(allNodes, function (idx, node) { |
|
var valueMap = dealWithSelectedValue(node.parentValues, selectedValues); |
|
// REPORT-24409 fix: 设置节点全部展开,添加的节点没有给状态 |
|
var parentCheckState = {}; |
|
var find = BI.find(result, function (idx, pNode) { |
|
return pNode.id === node.pId; |
|
}); |
|
if (find) { |
|
parentCheckState.checked = find.halfCheck ? false : find.checked; |
|
parentCheckState.half = find.halfCheck; |
|
} |
|
var state = getCheckState(node.value, node.parentValues, valueMap, parentCheckState); |
|
result.push({ |
|
id: node.id, |
|
pId: node.pId, |
|
value: node.value, |
|
text: node.text, |
|
times: 1, |
|
isParent: node.getChildrenLength() > 0, |
|
checked: state[0], |
|
halfCheck: state[1], |
|
open: self.options.open |
|
}); |
|
}); |
|
} |
|
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加 |
|
if (parentValues.length === 0 && times === 1) { |
|
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); |
|
} |
|
BI.nextTick(function () { |
|
callback({ |
|
items: result, |
|
hasNext: nodes.length > times * self._const.perPage |
|
}); |
|
}); |
|
|
|
function judgeState(parentValues, selected_value, checkState) { |
|
var checked = checkState.checked, half = checkState.half; |
|
if (parentValues.length > 0 && !checked) { |
|
return false; |
|
} |
|
return (parentValues.length === 0 || (checked && half) && !BI.isEmpty(selected_value)); |
|
} |
|
|
|
function dealWithSelectedValue(parentValues, selectedValues) { |
|
var valueMap = {}; |
|
BI.each(parentValues, function (i, v) { |
|
selectedValues = selectedValues[v] || {}; |
|
}); |
|
BI.each(selectedValues, function (value, obj) { |
|
if (BI.isNull(obj)) { |
|
valueMap[value] = [0, 0]; |
|
return; |
|
} |
|
if (BI.isEmpty(obj)) { |
|
valueMap[value] = [2, 0]; |
|
return; |
|
} |
|
var nextNames = {}; |
|
BI.each(obj, function (t, o) { |
|
if (BI.isNull(o) || BI.isEmpty(o)) { |
|
nextNames[t] = true; |
|
} |
|
}); |
|
// valueMap的数组第一个参数为不选: 0, 半选: 1, 全选:2, 第二个参数为改节点下选中的子节点个数(子节点全选或者不存在) |
|
valueMap[value] = [1, BI.size(nextNames)]; |
|
}); |
|
return valueMap; |
|
} |
|
|
|
function getCheckState(current, parentValues, valueMap, checkState) { |
|
// 节点本身的checked和half优先级最高 |
|
var checked = checkState.checked, half = checkState.half; |
|
var tempCheck = false, halfCheck = false; |
|
if (BI.has(valueMap, current)) { |
|
// 可能是半选 |
|
if (valueMap[current][0] === 1) { |
|
var values = BI.clone(parentValues); |
|
values.push(current); |
|
var childCount = self._getChildCount(values); |
|
if (childCount > 0 && childCount !== valueMap[current][1]) { |
|
halfCheck = true; |
|
} |
|
} else if (valueMap[current][0] === 2) { |
|
tempCheck = true; |
|
} |
|
} |
|
var check; |
|
if (!checked && !halfCheck && !tempCheck) { |
|
// 当节点自身是不选的,且通过selectedValues没有得到全选, 则check状态取决于valueMap |
|
check = BI.has(valueMap, current); |
|
} else { |
|
// 不是上面那种情况就先看在节点没有带有明确半选的时候,通过节点自身的checked和valueMap的状态能都得到选中信息 |
|
check = ((tempCheck || checked) && !half) || BI.has(valueMap, current); |
|
} |
|
return [check, halfCheck]; |
|
} |
|
}, |
|
|
|
_getAddedValueNode: function (parentValues, selectedValues) { |
|
var nodes = this._getChildren(parentValues); |
|
return BI.map(BI.difference(BI.keys(selectedValues), BI.map(nodes, "value")), function (idx, v) { |
|
return { |
|
id: BI.UUID(), |
|
pId: nodes.length > 0 ? nodes[0].pId : BI.UUID(), |
|
value: v, |
|
text: v, |
|
times: 1, |
|
isParent: false, |
|
checked: true, |
|
halfCheck: false |
|
}; |
|
}); |
|
}, |
|
|
|
_getNode: function (selectedValues, parentValues) { |
|
var pNode = selectedValues; |
|
for (var i = 0, len = parentValues.length; i < len; i++) { |
|
if (pNode == null) { |
|
return null; |
|
} |
|
pNode = pNode[parentValues[i]]; |
|
} |
|
return pNode; |
|
}, |
|
|
|
_deleteNode: function (selectedValues, values) { |
|
var name = values[values.length - 1]; |
|
var p = values.slice(0, values.length - 1); |
|
var pNode = this._getNode(selectedValues, p); |
|
if (pNode != null && pNode[name]) { |
|
delete pNode[name]; |
|
// 递归删掉空父节点 |
|
while (p.length > 0 && BI.isEmpty(pNode)) { |
|
name = p[p.length - 1]; |
|
p = p.slice(0, p.length - 1); |
|
pNode = this._getNode(selectedValues, p); |
|
if (pNode != null) { |
|
delete pNode[name]; |
|
} |
|
} |
|
} |
|
}, |
|
|
|
_buildTree: function (jo, values) { |
|
var t = jo; |
|
BI.each(values, function (i, v) { |
|
if (!BI.has(t, v)) { |
|
t[v] = {}; |
|
} |
|
t = t[v]; |
|
}); |
|
}, |
|
|
|
_isMatch: function (parentValues, value, keyword) { |
|
var o = this.options; |
|
var node = this._getTreeNode(parentValues, value); |
|
if (!node) { |
|
return false; |
|
} |
|
var find = BI.Func.getSearchResult([node.text || node.value], keyword); |
|
if(o.allowSearchValue && node.value) { |
|
var valueFind = BI.Func.getSearchResult([node.value], keyword); |
|
return valueFind.find.length > 0 || valueFind.match.length > 0 || |
|
find.find.length > 0 || find.match.length > 0; |
|
} |
|
return find.find.length > 0 || find.match.length > 0; |
|
}, |
|
|
|
_getTreeNode: function (parentValues, v) { |
|
var self = this; |
|
var findParentNode; |
|
var index = 0; |
|
this.tree.traverse(function (node) { |
|
if (self.tree.isRoot(node)) { |
|
return; |
|
} |
|
if (index > parentValues.length) { |
|
return false; |
|
} |
|
if (index === parentValues.length && node.value === v) { |
|
findParentNode = node; |
|
return false; |
|
} |
|
if (node.value === parentValues[index]) { |
|
index++; |
|
return; |
|
} |
|
return true; |
|
}); |
|
return findParentNode; |
|
}, |
|
|
|
_getChildren: function (parentValues) { |
|
if (parentValues.length > 0) { |
|
var value = BI.last(parentValues); |
|
var parent = this._getTreeNode(parentValues.slice(0, parentValues.length - 1), value); |
|
} else { |
|
var parent = this.tree.getRoot(); |
|
} |
|
return parent.getChildren(); |
|
}, |
|
|
|
_getAllChildren: function(parentValues) { |
|
var children = this._getChildren(parentValues); |
|
var nodes = [].concat(children); |
|
BI.each(nodes, function (idx, node) { |
|
node.parentValues = parentValues; |
|
}); |
|
var queue = BI.map(children, function (idx, node) { |
|
return { |
|
parentValues: parentValues, |
|
value: node.value |
|
}; |
|
}); |
|
while (BI.isNotEmptyArray(queue)) { |
|
var node = queue.shift(); |
|
var pValues = (node.parentValues).concat(node.value); |
|
var childNodes = this._getChildren(pValues); |
|
BI.each(childNodes, function (idx, node) { |
|
node.parentValues = pValues; |
|
}); |
|
queue = queue.concat(childNodes); |
|
nodes = nodes.concat(childNodes); |
|
} |
|
return nodes; |
|
}, |
|
|
|
_getChildCount: function (parentValues) { |
|
return this._getChildren(parentValues).length; |
|
} |
|
});BI.AbstractListTreeValueChooser = BI.inherit(BI.AbstractTreeValueChooser, { |
|
|
|
_reqDisplayTreeNode: function (op, callback) { |
|
var self = this; |
|
var result = {}; |
|
var selectedValues = op.selectedValues; |
|
|
|
if (selectedValues == null || BI.isEmpty(selectedValues)) { |
|
callback({}); |
|
return; |
|
} |
|
|
|
doCheck([], this.tree.getRoot(), selectedValues); |
|
|
|
callback({ |
|
items: BI.values(result) |
|
}); |
|
|
|
function doCheck(parentValues, node, selected) { |
|
BI.each(selected, function (idx, path) { |
|
BI.each(path, function (id, value) { |
|
var nodeValue = value; |
|
var node = self._getTreeNode(path.slice(0, id), nodeValue); |
|
// 找不到就是新增值 |
|
if (BI.isNull(node)) { |
|
createOneJson({ |
|
id: BI.UUID(), |
|
text: nodeValue, |
|
value: nodeValue, |
|
isLeaf: true |
|
}, BI.UUID()); |
|
} else { |
|
if(!BI.has(result, node.id)) { |
|
createOneJson(node, node.parent && node.parent.id); |
|
} |
|
result[node.id].isLeaf !== true && (result[node.id].isLeaf = id === path.length - 1); |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
function createOneJson(node, pId) { |
|
result[node.id] = { |
|
id: node.id, |
|
pId: pId, |
|
text: node.text, |
|
value: node.value, |
|
open: true, |
|
isLeaf: node.isLeaf |
|
}; |
|
} |
|
}, |
|
|
|
_reqInitTreeNode: function (op, callback) { |
|
var self = this; |
|
var result = []; |
|
var keyword = op.keyword || ""; |
|
var selectedValues = op.selectedValues; |
|
var lastSearchValue = op.lastSearchValue || ""; // 一次请求100个,但是搜索是拿全部的,lastSearchValue是上一次遍历到的节点索引 |
|
var output = search(); |
|
BI.nextTick(function () { |
|
callback({ |
|
hasNext: output.length > self._const.perPage, |
|
items: result, |
|
lastSearchValue: BI.last(output) |
|
}); |
|
}); |
|
|
|
function search() { |
|
var children = self._getChildren([]); |
|
var start = children.length; |
|
if (lastSearchValue !== "") { |
|
for (var j = 0, len = start; j < len; j++) { |
|
if (children[j].value === lastSearchValue) { |
|
start = j + 1; |
|
break; |
|
} |
|
} |
|
} else { |
|
start = 0; |
|
} |
|
var output = []; |
|
for (var i = start, len = children.length; i < len; i++) { |
|
if (output.length < self._const.perPage) { |
|
var find = nodeSearch(1, [], children[i].value, result); |
|
} else if (output.length === self._const.perPage) { |
|
var find = nodeSearch(1, [], children[i].value, []); |
|
} |
|
if (find[0] === true) { |
|
output.push(children[i].value); |
|
} |
|
if (output.length > self._const.perPage) { |
|
break; |
|
} |
|
} |
|
|
|
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加 |
|
if (op.times === 1) { |
|
var nodes = self._getAddedValueNode([], selectedValues); |
|
result = BI.concat(BI.filter(nodes, function (idx, node) { |
|
var find = BI.Func.getSearchResult([node.text || node.value], keyword); |
|
return find.find.length > 0 || find.match.length > 0; |
|
}), result); |
|
} |
|
return output; |
|
} |
|
|
|
function nodeSearch(deep, parentValues, current, result) { |
|
if (self._isMatch(parentValues, current, keyword)) { |
|
var checked = isSelected(parentValues, current); |
|
createOneJson(parentValues, current, false, checked, true, result); |
|
return [true, checked]; |
|
} |
|
var newParents = BI.clone(parentValues); |
|
newParents.push(current); |
|
var children = self._getChildren(newParents); |
|
|
|
var can = false, checked = false; |
|
|
|
BI.each(children, function (i, child) { |
|
var state = nodeSearch(deep + 1, newParents, child.value, result); |
|
if (state[1] === true) { |
|
checked = true; |
|
} |
|
if (state[0] === true) { |
|
can = true; |
|
} |
|
}); |
|
if (can === true) { |
|
checked = isSelected(parentValues, current); |
|
createOneJson(parentValues, current, true, checked, false, result); |
|
} |
|
return [can, checked]; |
|
} |
|
|
|
function createOneJson(parentValues, value, isOpen, checked, flag, result) { |
|
var node = self._getTreeNode(parentValues, value); |
|
result.push({ |
|
id: node.id, |
|
pId: node.pId, |
|
text: node.text, |
|
value: node.value, |
|
title: node.title, |
|
isParent: node.getChildrenLength() > 0, |
|
open: isOpen, |
|
checked: checked, |
|
halfCheck: false, |
|
flag: flag |
|
}); |
|
} |
|
|
|
function isHalf(parentValues, value) { |
|
var find = findSelectedObj(parentValues); |
|
if (find == null) { |
|
return null; |
|
} |
|
return BI.any(find, function (v, ob) { |
|
if (v === value) { |
|
if (ob != null && !BI.isEmpty(ob)) { |
|
return true; |
|
} |
|
} |
|
}); |
|
} |
|
|
|
function isAllSelected(parentValues, value) { |
|
var find = findSelectedObj(parentValues); |
|
if (find == null) { |
|
return null; |
|
} |
|
return BI.any(find, function (v, ob) { |
|
if (v === value) { |
|
if (ob != null && BI.isEmpty(ob)) { |
|
return true; |
|
} |
|
} |
|
}); |
|
} |
|
|
|
function isSelected(parentValues, value) { |
|
return BI.any(selectedValues, function (idx, array) { |
|
return BI.isEqual(parentValues, array.slice(0, parentValues.length)) && BI.last(array) === value; |
|
}); |
|
} |
|
|
|
function findSelectedObj(parentValues) { |
|
var find = selectedValues; |
|
if (find == null) { |
|
return null; |
|
} |
|
BI.every(parentValues, function (i, v) { |
|
find = find[v]; |
|
if (find == null) { |
|
return false; |
|
} |
|
return true; |
|
}); |
|
return find; |
|
} |
|
}, |
|
|
|
_reqTreeNode: function (op, callback) { |
|
var self = this, o = this.options; |
|
var result = []; |
|
var times = op.times; |
|
var parentValues = op.parentValues || []; |
|
var selectedValues = op.selectedValues || []; |
|
var valueMap = dealWithSelectedValue(parentValues, selectedValues); |
|
var nodes = this._getChildren(parentValues); |
|
for (var i = (times - 1) * this._const.perPage; nodes[i] && i < times * this._const.perPage; i++) { |
|
var checked = BI.has(valueMap, nodes[i].value); |
|
result.push({ |
|
id: nodes[i].id, |
|
pId: nodes[i].pId, |
|
value: nodes[i].value, |
|
text: nodes[i].text, |
|
times: 1, |
|
isParent: nodes[i].getChildrenLength() > 0, |
|
checked: checked, |
|
halfCheck: false, |
|
open: o.open |
|
}); |
|
} |
|
// 如果指定节点全部打开 |
|
if (o.open) { |
|
var allNodes = []; |
|
// 获取所有节点 |
|
BI.each(nodes, function (idx, node) { |
|
allNodes = BI.concat(allNodes, self._getAllChildren(parentValues.concat([node.value]))); |
|
}); |
|
BI.each(allNodes, function (idx, node) { |
|
var valueMap = dealWithSelectedValue(node.parentValues, selectedValues); |
|
var checked = BI.has(valueMap, node.value); |
|
result.push({ |
|
id: node.id, |
|
pId: node.pId, |
|
value: node.value, |
|
text: node.text, |
|
times: 1, |
|
isParent: node.getChildrenLength() > 0, |
|
checked: checked, |
|
halfCheck: false, |
|
open: o.open |
|
}); |
|
}); |
|
} |
|
// 深层嵌套的比较麻烦,这边先实现的是在根节点添加 |
|
if (parentValues.length === 0 && times === 1) { |
|
result = BI.concat(self._getAddedValueNode(parentValues, selectedValues), result); |
|
} |
|
BI.nextTick(function () { |
|
callback({ |
|
items: result, |
|
hasNext: nodes.length > times * self._const.perPage |
|
}); |
|
}); |
|
|
|
function dealWithSelectedValue(parentValues, selectedValues) { |
|
var valueMap = {}; |
|
BI.each(selectedValues, function (idx, v) { |
|
if (BI.isEqual(parentValues, v.slice(0, parentValues.length))) { |
|
valueMap[BI.last(v)] = [2, 0]; |
|
} |
|
}); |
|
return valueMap; |
|
} |
|
}, |
|
|
|
_getAddedValueNode: function (parentValues, selectedValues) { |
|
var nodes = this._getChildren(parentValues); |
|
var values = BI.flatten(BI.filter(selectedValues, function (idx, array) { |
|
return array.length === 1; |
|
})); |
|
return BI.map(BI.difference(values, BI.map(nodes, "value")), function (idx, v) { |
|
return { |
|
id: BI.UUID(), |
|
pId: nodes.length > 0 ? nodes[0].pId : BI.UUID(), |
|
value: v, |
|
text: v, |
|
times: 1, |
|
isParent: false, |
|
checked: true, |
|
halfCheck: false |
|
}; |
|
}); |
|
} |
|
});/** |
|
* 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.ListTreeValueChooserInsertCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.ListTreeValueChooserInsertCombo = BI.inherit(BI.AbstractListTreeValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.ListTreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-list-tree-value-chooser-insert-combo", |
|
width: 200, |
|
height: 24, |
|
items: null, |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ListTreeValueChooserInsertCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this._initData(o.items); |
|
} |
|
this.combo = BI.createWidget({ |
|
type: "bi.multi_tree_list_combo", |
|
element: this, |
|
text: o.text, |
|
value: o.value, |
|
watermark: o.watermark, |
|
allowInsertValue: o.allowInsertValue, |
|
allowEdit: o.allowEdit, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height, |
|
listeners: [{ |
|
eventName: BI.MultiTreeListCombo.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeListCombo.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeListCombo.EVENT_STOP, |
|
action: function () { |
|
self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_STOP); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeListCombo.EVENT_CLICK_ITEM, |
|
action: function () { |
|
self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeListCombo.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeListCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.combo.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this._initData(items); |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.ListTreeValueChooserInsertCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.ListTreeValueChooserInsertCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.ListTreeValueChooserInsertCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.ListTreeValueChooserInsertCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.ListTreeValueChooserInsertCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.ListTreeValueChooserInsertCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.list_tree_value_chooser_insert_combo", BI.ListTreeValueChooserInsertCombo);/** |
|
* 简单的复选下拉树控件, 适用于数据量少的情况, 可以自增值 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.TreeValueChooserInsertCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.TreeValueChooserInsertCombo = BI.inherit(BI.AbstractTreeValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.TreeValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-tree-value-chooser-insert-combo", |
|
width: 200, |
|
height: 24, |
|
items: null, |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TreeValueChooserInsertCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this._initData(o.items); |
|
} |
|
this.combo = BI.createWidget({ |
|
type: "bi.multi_tree_insert_combo", |
|
allowEdit: o.allowEdit, |
|
text: o.text, |
|
value: o.value, |
|
watermark: o.watermark, |
|
element: this, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height, |
|
listeners: [{ |
|
eventName: BI.MultiTreeInsertCombo.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeInsertCombo.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeInsertCombo.EVENT_STOP, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_STOP); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeInsertCombo.EVENT_CLICK_ITEM, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeInsertCombo.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeInsertCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserInsertCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.combo.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this._initData(items); |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.TreeValueChooserInsertCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.TreeValueChooserInsertCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.TreeValueChooserInsertCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.TreeValueChooserInsertCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.TreeValueChooserInsertCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.TreeValueChooserInsertCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.tree_value_chooser_insert_combo", BI.TreeValueChooserInsertCombo);/** |
|
* 简单的复选下拉树控件, 适用于数据量少的情况 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.TreeValueChooserCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.TreeValueChooserCombo = BI.inherit(BI.AbstractTreeValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.TreeValueChooserCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-tree-value-chooser-combo", |
|
width: 200, |
|
height: 24, |
|
items: null, |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TreeValueChooserCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this._initData(o.items); |
|
} |
|
this.combo = BI.createWidget({ |
|
type: "bi.multi_tree_combo", |
|
text: o.text, |
|
allowEdit: o.allowEdit, |
|
value: o.value, |
|
watermark: o.watermark, |
|
element: this, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height, |
|
listeners: [{ |
|
eventName: BI.MultiTreeCombo.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeCombo.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeCombo.EVENT_STOP, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_STOP); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeCombo.EVENT_CLICK_ITEM, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeCombo.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiTreeCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.TreeValueChooserCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.combo.getValue(); |
|
}, |
|
|
|
populate: function (items) { |
|
this._initData(items); |
|
this.combo.populate.apply(this.combo, arguments); |
|
} |
|
}); |
|
|
|
BI.TreeValueChooserCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.TreeValueChooserCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.TreeValueChooserCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.TreeValueChooserCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.TreeValueChooserCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.TreeValueChooserCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.shortcut("bi.tree_value_chooser_combo", BI.TreeValueChooserCombo);/** |
|
* 简单的树面板, 适用于数据量少的情况 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.TreeValueChooserPane |
|
* @extends BI.AbstractTreeValueChooser |
|
*/ |
|
BI.TreeValueChooserPane = BI.inherit(BI.AbstractTreeValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.TreeValueChooserPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-tree-value-chooser-pane", |
|
items: null, |
|
itemsCreator: BI.emptyFn |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.TreeValueChooserPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.pane = BI.createWidget({ |
|
type: "bi.multi_select_tree", |
|
element: this, |
|
itemsCreator: BI.bind(this._itemsCreator, this) |
|
}); |
|
|
|
this.pane.on(BI.MultiSelectTree.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.TreeValueChooserPane.EVENT_CHANGE); |
|
}); |
|
if (BI.isNotNull(o.items)) { |
|
this._initData(o.items); |
|
this.populate(); |
|
} |
|
}, |
|
|
|
setSelectedValue: function (v) { |
|
this.pane.setSelectedValue(v); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.pane.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
return this.pane.getValue(); |
|
}, |
|
|
|
populate: function () { |
|
this.pane.populate.apply(this.pane, arguments); |
|
} |
|
}); |
|
BI.TreeValueChooserPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.tree_value_chooser_pane", BI.TreeValueChooserPane);/** |
|
* 简单的复选下拉框控件, 适用于数据量少的情况 |
|
* 封装了字段处理逻辑 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.AbstractValueChooser |
|
* @extends BI.Widget |
|
*/ |
|
BI.AbstractValueChooser = BI.inherit(BI.Widget, { |
|
|
|
_const: { |
|
perPage: 100 |
|
}, |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.AbstractValueChooser.superclass._defaultConfig.apply(this, arguments), { |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_valueFormatter: function (v) { |
|
var text = v; |
|
if (BI.isNotNull(this.items)) { |
|
BI.some(this.items, function (i, item) { |
|
// 把value都换成字符串 |
|
if (item.value === v || item.value + "" === v) { |
|
text = item.text; |
|
return true; |
|
} |
|
}); |
|
} |
|
return text; |
|
}, |
|
|
|
_getItemsByTimes: function (items, times) { |
|
var res = []; |
|
for (var i = (times - 1) * this._const.perPage; items[i] && i < times * this._const.perPage; i++) { |
|
res.push(items[i]); |
|
} |
|
return res; |
|
}, |
|
|
|
_hasNextByTimes: function (items, times) { |
|
return times * this._const.perPage < items.length; |
|
}, |
|
|
|
_itemsCreator: function (options, callback) { |
|
var self = this, o = this.options; |
|
if (!o.cache || !this.items) { |
|
o.itemsCreator({}, function (items) { |
|
self.items = items; |
|
call(items); |
|
}); |
|
} else { |
|
call(this.items); |
|
} |
|
function call (items) { |
|
var keywords = (options.keywords || []).slice(); |
|
var resultItems = items; |
|
if(BI.isNotEmptyArray(keywords)) { |
|
resultItems = []; |
|
BI.each(keywords, function (i, kw) { |
|
var search = BI.Func.getSearchResult(items, kw); |
|
resultItems = resultItems.concat(search.match).concat(search.find); |
|
}); |
|
resultItems = BI.uniq(resultItems); |
|
} |
|
if (options.selectedValues) {// 过滤 |
|
var filter = BI.makeObject(options.selectedValues, true); |
|
resultItems = BI.filter(resultItems, function (i, ob) { |
|
return !filter[ob.value]; |
|
}); |
|
} |
|
if (options.type === BI.MultiSelectCombo.REQ_GET_ALL_DATA) { |
|
callback({ |
|
items: resultItems |
|
}); |
|
return; |
|
} |
|
if (options.type === BI.MultiSelectCombo.REQ_GET_DATA_LENGTH) { |
|
callback({count: resultItems.length}); |
|
return; |
|
} |
|
callback({ |
|
items: self._getItemsByTimes(resultItems, options.times), |
|
hasNext: self._hasNextByTimes(resultItems, options.times) |
|
}); |
|
} |
|
} |
|
});/** |
|
* 简单的复选下拉框控件, 适用于数据量少的情况 |
|
* 封装了字段处理逻辑 |
|
*/ |
|
BI.ValueChooserInsertCombo = BI.inherit(BI.AbstractValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.ValueChooserInsertCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-value-chooser-insert-combo", |
|
width: 200, |
|
height: 24, |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ValueChooserInsertCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this.items = o.items; |
|
} |
|
this.combo = BI.createWidget({ |
|
type: "bi.multi_select_insert_combo", |
|
element: this, |
|
allowEdit: o.allowEdit, |
|
text: o.text, |
|
value: o.value, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height, |
|
listeners: [{ |
|
eventName: BI.MultiSelectCombo.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserInsertCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserInsertCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_STOP, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserInsertCombo.EVENT_STOP); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_CLICK_ITEM, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserInsertCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserInsertCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserInsertCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.combo.getValue() || {}; |
|
return { |
|
type: val.type, |
|
value: val.value |
|
}; |
|
}, |
|
|
|
populate: function (items) { |
|
// 直接用combo的populate不会作用到AbstractValueChooser上 |
|
this.items = items; |
|
this.combo.populate.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.ValueChooserInsertCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.ValueChooserInsertCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.ValueChooserInsertCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.ValueChooserInsertCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.ValueChooserInsertCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.ValueChooserInsertCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.value_chooser_insert_combo", BI.ValueChooserInsertCombo);/** |
|
* 简单的复选下拉框控件, 适用于数据量少的情况 |
|
* 封装了字段处理逻辑 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.ValueChooserCombo |
|
* @extends BI.Widget |
|
*/ |
|
BI.ValueChooserCombo = BI.inherit(BI.AbstractValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.ValueChooserCombo.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-value-chooser-combo", |
|
width: 200, |
|
height: 24, |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ValueChooserCombo.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
if (BI.isNotNull(o.items)) { |
|
this.items = o.items; |
|
} |
|
this.combo = BI.createWidget({ |
|
type: "bi.multi_select_combo", |
|
element: this, |
|
allowEdit: o.allowEdit, |
|
text: o.text, |
|
value: o.value, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this), |
|
width: o.width, |
|
height: o.height, |
|
listeners: [{ |
|
eventName: BI.MultiSelectCombo.EVENT_FOCUS, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserCombo.EVENT_FOCUS); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_BLUR, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserCombo.EVENT_BLUR); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_STOP, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserCombo.EVENT_STOP); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_CLICK_ITEM, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserCombo.EVENT_CLICK_ITEM); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_SEARCHING, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserCombo.EVENT_SEARCHING); |
|
} |
|
}, { |
|
eventName: BI.MultiSelectCombo.EVENT_CONFIRM, |
|
action: function () { |
|
self.fireEvent(BI.ValueChooserCombo.EVENT_CONFIRM); |
|
} |
|
}] |
|
}); |
|
}, |
|
|
|
setValue: function (v) { |
|
this.combo.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.combo.getValue() || {}; |
|
return { |
|
type: val.type, |
|
value: val.value |
|
}; |
|
}, |
|
|
|
populate: function (items) { |
|
// 直接用combo的populate不会作用到AbstractValueChooser上 |
|
this.items = items; |
|
this.combo.populate.apply(this, arguments); |
|
} |
|
}); |
|
|
|
BI.ValueChooserCombo.EVENT_BLUR = "EVENT_BLUR"; |
|
BI.ValueChooserCombo.EVENT_FOCUS = "EVENT_FOCUS"; |
|
BI.ValueChooserCombo.EVENT_STOP = "EVENT_STOP"; |
|
BI.ValueChooserCombo.EVENT_SEARCHING = "EVENT_SEARCHING"; |
|
BI.ValueChooserCombo.EVENT_CLICK_ITEM = "EVENT_CLICK_ITEM"; |
|
BI.ValueChooserCombo.EVENT_CONFIRM = "EVENT_CONFIRM"; |
|
BI.shortcut("bi.value_chooser_combo", BI.ValueChooserCombo);/** |
|
* 简单的复选面板, 适用于数据量少的情况 |
|
* 封装了字段处理逻辑 |
|
* |
|
* Created by GUY on 2015/10/29. |
|
* @class BI.ValueChooserPane |
|
* @extends BI.Widget |
|
*/ |
|
BI.ValueChooserPane = BI.inherit(BI.AbstractValueChooser, { |
|
|
|
_defaultConfig: function () { |
|
return BI.extend(BI.ValueChooserPane.superclass._defaultConfig.apply(this, arguments), { |
|
baseCls: "bi-value-chooser-pane", |
|
items: null, |
|
itemsCreator: BI.emptyFn, |
|
cache: true |
|
}); |
|
}, |
|
|
|
_init: function () { |
|
BI.ValueChooserPane.superclass._init.apply(this, arguments); |
|
var self = this, o = this.options; |
|
this.list = BI.createWidget({ |
|
type: "bi.multi_select_list", |
|
element: this, |
|
value: o.value, |
|
itemsCreator: BI.bind(this._itemsCreator, this), |
|
valueFormatter: BI.bind(this._valueFormatter, this) |
|
}); |
|
|
|
this.list.on(BI.MultiSelectList.EVENT_CHANGE, function () { |
|
self.fireEvent(BI.ValueChooserPane.EVENT_CHANGE); |
|
}); |
|
if (BI.isNotNull(o.items)) { |
|
this.items = o.items; |
|
this.list.populate(); |
|
} |
|
}, |
|
|
|
setValue: function (v) { |
|
this.list.setValue(v); |
|
}, |
|
|
|
getValue: function () { |
|
var val = this.list.getValue() || {}; |
|
return { |
|
type: val.type, |
|
value: val.value |
|
}; |
|
}, |
|
|
|
populate: function (items) { |
|
// 直接用combo的populate不会作用到AbstractValueChooser上 |
|
items && (this.items = items); |
|
this.list.populate.apply(this.list, arguments); |
|
} |
|
}); |
|
BI.ValueChooserPane.EVENT_CHANGE = "EVENT_CHANGE"; |
|
BI.shortcut("bi.value_chooser_pane", BI.ValueChooserPane);;(function () { |
|
function initWatch (vm, watch) { |
|
vm._watchers || (vm._watchers = []); |
|
for (var key in watch) { |
|
var handler = watch[key]; |
|
if (BI.isArray(handler)) { |
|
for (var i = 0; i < handler.length; i++) { |
|
vm._watchers.push(createWatcher(vm, key, handler[i])); |
|
} |
|
} else { |
|
vm._watchers.push(createWatcher(vm, key, handler)); |
|
} |
|
} |
|
} |
|
|
|
function createWatcher(vm, keyOrFn, cb, options) { |
|
if (BI.isPlainObject(cb)) { |
|
options = cb; |
|
cb = cb.handler; |
|
} |
|
options = options || {}; |
|
return Fix.watch(vm.model, keyOrFn, _.bind(cb, vm), BI.extend(options, { |
|
store: vm.store |
|
})); |
|
} |
|
|
|
var target = null; |
|
var targetStack = []; |
|
|
|
function pushTarget (_target) { |
|
if (target) targetStack.push(target); |
|
Fix.Model.target = target = _target; |
|
} |
|
|
|
function popTarget () { |
|
Fix.Model.target = target = targetStack.pop(); |
|
} |
|
|
|
var context = null; |
|
var contextStack = []; |
|
|
|
function pushContext (_context) { |
|
if (context) contextStack.push(context); |
|
Fix.Model.context = context = _context; |
|
} |
|
|
|
function popContext () { |
|
Fix.Model.context = context = contextStack.pop(); |
|
} |
|
|
|
var oldWatch = Fix.watch; |
|
Fix.watch = function (model, expOrFn, cb, options) { |
|
if (BI.isPlainObject(cb)) { |
|
options = cb; |
|
cb = cb.handler; |
|
} |
|
if (typeof cb === "string") { |
|
cb = model[cb]; |
|
} |
|
return oldWatch.call(this, model, expOrFn, function () { |
|
options && options.store && pushTarget(options.store); |
|
try { |
|
var res = cb.apply(this, arguments); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
options && options.store && popTarget(); |
|
return res; |
|
}, options); |
|
}; |
|
|
|
function findStore (widget) { |
|
if (target != null) { |
|
return target; |
|
} |
|
widget = widget || context; |
|
var p = widget; |
|
while (p) { |
|
if (p instanceof Fix.Model || p.store || p.__cacheStore) { |
|
break; |
|
} |
|
p = p._parent || (p.options && p.options.element); |
|
} |
|
if (p) { |
|
if (p instanceof Fix.Model) { |
|
return widget.__cacheStore = p; |
|
} |
|
widget.__cacheStore = p.store || p.__cacheStore; |
|
return p.__cacheStore || p.store; |
|
} |
|
} |
|
|
|
var _create = BI.createWidget; |
|
BI.createWidget = function (item, options, context) { |
|
var pushed = false; |
|
if (BI.isWidget(options)) { |
|
pushContext(options); |
|
pushed = true; |
|
} else if (context != null) { |
|
pushContext(context); |
|
pushed = true; |
|
} |
|
var result = _create.apply(this, arguments); |
|
// try { |
|
// var result = _create.apply(this, arguments); |
|
// } catch (e) { |
|
// console.error(e); |
|
// } |
|
pushed && popContext(); |
|
return result; |
|
}; |
|
|
|
_.each(["populate", "addItems", "prependItems"], function (name) { |
|
var old = BI.Loader.prototype[name]; |
|
BI.Loader.prototype[name] = function () { |
|
pushContext(this); |
|
try { |
|
var result = old.apply(this, arguments); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
popContext(); |
|
return result; |
|
}; |
|
}); |
|
|
|
function createStore () { |
|
var needPop = false; |
|
if (_global.Fix && this._store) { |
|
var store = findStore(this.options.context || this.options.element); |
|
if (store) { |
|
pushTarget(store); |
|
needPop = true; |
|
} |
|
this.store = this._store(); |
|
this.store && (this.store._widget = this); |
|
needPop && popTarget(); |
|
needPop = false; |
|
pushTarget(this.store); |
|
if (this.store instanceof Fix.Model) { |
|
this.model = this.store.model; |
|
} else { |
|
this.model = this.store; |
|
} |
|
needPop = true; |
|
} |
|
return needPop; |
|
} |
|
|
|
var _init = BI.Widget.prototype._init; |
|
BI.Widget.prototype._init = function () { |
|
var self = this; |
|
var needPop = createStore.call(this); |
|
try { |
|
_init.apply(this, arguments); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
needPop && popTarget(); |
|
}; |
|
|
|
var _render = BI.Widget.prototype._render; |
|
BI.Widget.prototype._render = function () { |
|
var needPop = false; |
|
if (_global.Fix && this._store) { |
|
needPop = true; |
|
pushTarget(this.store); |
|
initWatch(this, this.watch); |
|
} |
|
_render.apply(this, arguments); |
|
// try { |
|
// _render.apply(this, arguments); |
|
// } catch (e) { |
|
// console.error(e); |
|
// } |
|
needPop && popTarget(); |
|
}; |
|
|
|
var unMount = BI.Widget.prototype.__d; |
|
BI.Widget.prototype.__d = function () { |
|
try { |
|
unMount.apply(this, arguments); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
this.store && BI.isFunction(this.store.destroy) && this.store.destroy(); |
|
BI.each(this._watchers, function (i, unwatches) { |
|
unwatches = BI.isArray(unwatches) ? unwatches : [unwatches]; |
|
BI.each(unwatches, function (j, unwatch) { |
|
unwatch(); |
|
}); |
|
}); |
|
this._watchers && (this._watchers = []); |
|
if (this.store) { |
|
this.store._parent && (this.store._parent = null); |
|
this.store._widget && (this.store._widget = null); |
|
this.store = null; |
|
} |
|
delete this.__cacheStore; |
|
}; |
|
|
|
_.each(["_mount"], function (name) { |
|
var old = BI.Widget.prototype[name]; |
|
old && (BI.Widget.prototype[name] = function () { |
|
this.store && pushTarget(this.store); |
|
try { |
|
var res = old.apply(this, arguments); |
|
} catch (e) { |
|
console.error(e); |
|
} |
|
this.store && popTarget(); |
|
return res; |
|
}); |
|
}); |
|
|
|
if (BI.isIE9Below && BI.isIE9Below()) { |
|
_.each(["each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min", |
|
"sortBy", "groupBy", "indexBy", "countBy", "partition", |
|
"keys", "allKeys", "values", "pairs", "invert", |
|
"mapObject", "findKey", "pick", "omit", "tap"], function (name) { |
|
var old = BI[name]; |
|
BI[name] = function (obj, fn, context) { |
|
return typeof fn === "function" ? old(obj, function (key, value) { |
|
if (!(key in Fix.$$skipArray)) { |
|
return fn.apply(this, arguments); |
|
} |
|
}, context) : old.apply(this, arguments); |
|
}; |
|
}); |
|
BI.isEmpty = function (ob) { |
|
if (BI.isPlainObject(ob) && ob.__ob__) { |
|
return BI.keys(ob).length === 0; |
|
} |
|
return _.isEmpty(ob); |
|
}; |
|
BI.keys = function (ob) { |
|
var keys = _.keys(ob); |
|
var nKeys = []; |
|
for (var i = 0; i < keys.length; i++) { |
|
if (!(keys[i] in Fix.$$skipArray)) { |
|
nKeys.push(keys[i]); |
|
} |
|
} |
|
return nKeys; |
|
}; |
|
BI.values = function (ob) { |
|
var keys = BI.keys(obj); |
|
var length = keys.length; |
|
var values = []; |
|
for (var i = 0; i < length; i++) { |
|
values[i] = obj[keys[i]]; |
|
} |
|
return values; |
|
}; |
|
BI.extend = function () { |
|
var args = Array.prototype.slice.call(arguments); |
|
if (args.length < 1) { |
|
return {}; |
|
} |
|
var object = args[0]; |
|
var i = 1; |
|
while (i < args.length) { |
|
BI.each(args[i], function (key, v) { |
|
object[key] = v; |
|
}); |
|
i++; |
|
} |
|
return object; |
|
}; |
|
BI.size = function (ob) { |
|
if (BI.isPlainObject(ob) && ob.__ob__) { |
|
return BI.keys(ob).length; |
|
} |
|
return _.size(ob); |
|
}; |
|
BI.isEmptyObject = function (ob) { |
|
return BI.size(ob) === 0; |
|
}; |
|
BI.deepClone = function (ob) { |
|
return Fix.toJSON(ob); |
|
}; |
|
} |
|
BI.watch = Fix.watch; |
|
}()); |
|
|
|
//# sourceMappingURL=fineui_without_jquery_polyfill.js.map |