<commit_before>(function(window, factory) {
	var dom = factory(window, window.document);
	window.dom = dom;
	if(typeof module == 'object' && module.exports){
		module.exports = dom;
	}
}(typeof window != 'undefined' ? window : this , function(window, document) {
	'use strict';
	var slice = [].slice;
	var dom = function(elements){

		if(typeof elements == 'string'){
			return dom.q(elements);
		}
		if(!this){
			return new dom(elements);
		}

		if(!Array.isArray(elements)){
			if(!elements){
				elements = [];
			} else if(elements.nodeName || !('length' in elements) || elements == window){
				elements = [elements];
			} else {
				elements = slice.call(elements);
			}
		}

		this.elements = elements;
		this.length = this.elements.length || 0;
	};
	var fn = dom.prototype;
	var tween = function(element, endProps, options){

		var easing, isStopped, isJumpToEnd, bezierArgs, requestID;
		var start = Date.now();
		var elementStyle = element.style;
		var startProps = {};
		var stop = function(clearQueue, jumpToEnd){
			isStopped = true;
			if(jumpToEnd){
				isJumpToEnd = true;
			}
			step();
			cancelAnimationFrame(requestID);
		};

		var step = function() {
			var prop, value, eased;
			var pos = (Date.now() - start) / options.duration;

			if(pos > 1 || isJumpToEnd){
				pos = 1;
			}

			if(!isStopped){
				eased = easing(pos);

				for(prop in startProps){
					value = (endProps[prop] - startProps[prop]) * eased + startProps[prop];

					if(prop in elementStyle){
						elementStyle[prop] = value +'px';
					} else {
						element[prop] = value;
					}
				}
			}

			if(pos < 1){
				if(!isStopped){
					requestID = requestAnimationFrame(step);
				} else if(options.always){
					options.always.call(element);
				}
			} else{
				if(element._rbTweenStop){
					delete element._rbTweenStop;
				}
				if(options.complete && !isStopped){
					options.complete.call(element);
				}
				if(options.always){
					options.always.call(element);
				}
			}
		};

		tween.getStartValues(element, elementStyle, startProps, endProps);

		options = Object.assign({duration: 400, easing: 'ease'}, options || {});

		if(window.BezierEasing && !BezierEasing.css[options.easing] && (bezierArgs = options.easing.match(/([0-9\.]+)/g)) && bezierArgs.length == 4){
			bezierArgs = bezierArgs.map(function(str){
				return parseFloat(str);
			});
			BezierEasing.css[options.easing] = BezierEasing.apply(this, bezierArgs);
		}

		easing = window.BezierEasing && (BezierEasing.css[options.easing] || BezierEasing.css.ease) || function(pos){
				return pos;
			};

		element._rbTweenStop = stop;

		requestID = requestAnimationFrame(step);
	};

	tween.getStartValues = function(element, elementStyle, startProps, endProps){
		var prop;
		for(prop in endProps){
			if(prop in elementStyle){
				startProps[prop] = parseFloat(getComputedStyle(element).getPropertyValue(prop));
			} else {
				startProps[prop] = element[prop];
			}
		}
	};

	dom.fn = dom.prototype;

	dom.q = function(sel, context){
		return new dom( (context || document).querySelectorAll(sel) );
	};

	dom.Event = function(type, options){
		var event;
		if(!options){
			options = {};
		}

		if(options.bubbles == null){
			options.bubbles = true;
		}
		event = new CustomEvent(type, options);

		if(!event.isDefaultPrevented){
			event.isDefaultPrevented = function(){
				return event.defaultPrevented;
			};
		}

		return event;
	};

	fn.find = function(sel){
		var array = [];
		this.elements.forEach(function(elem){
			var i, len;
			var elements = elem.querySelectorAll(sel);
			for(i = 0, len = elements.length; i < len; i++){
				if(array.indexOf(elements[i]) == -1){
					array.push(elements[i]);
				}
			}
		});

		return new dom( array );
	};

	fn.closest = function(sel){
		var array = [];
		this.elements.forEach(function(elem){
			var element = elem.closest(sel);
			if(array.indexOf(element) == -1){
				array.push(element);
			}
		});
		return new dom( array );
	};

	fn.get = function(number){
		return arguments.length ? this.elements[number] : this.elements;
	};

	[['on', 'addEventListener'], ['off', 'removeEventListener']].forEach(function(action){
		dom.fn[action[0]] = function(type, sel, fn, capture){
			var useFn;
			if(typeof sel == 'function'){
				capture = fn;
				fn = sel;
				sel = null;
			}

			if(sel){
				if(!fn[sel]){
					fn[sel] = function(e){
						e.delegateTarget = e.target.closest(sel);
						if(!e.delegateTarget){return;}
						return fn.apply(this, arguments);
					};
				}
				useFn = fn[sel];
			} else {
				useFn = fn;
			}

			this.elements.forEach(function(elem){
				elem[action[1]](type, useFn, capture || false);
			});

			return this;
		};
	});

	fn.css = function(style, pseudo){
		var elem;
		if(typeof style == 'string'){
			elem = this.elements[0];
			return elem && getComputedStyle(elem, pseudo).getPropertyValue(style);
		}
		this.elements.forEach(function(elem){
			var prop;
			var eStyle = elem.style;
			for(prop in style){
				eStyle[prop] = style[prop];
			}
		});
		return this;
	};

	fn.prop = function(props){
		var elem;
		if(typeof props == 'string'){
			elem = this.elements[0];
			return elem && elem[props];
		}
		this.elements.forEach(function(elem){
			var prop;
			for(prop in props){
				elem[prop] = props[prop];
			}
		});
		return this;
	};

	fn.attr = function(attrs){
		var elem;
		if(typeof attrs == 'string'){
			elem = this.elements[0];
			return elem && elem.getAttribute(attrs);
		}
		this.elements.forEach(function(elem){
			var attr;
			for(attr in attrs){
				elem.setAttribute(attr, attrs[attr]);
			}
		});
		return this;
	};

	fn.removeAttr = function(attr){
		this.elements.forEach(function(elem){
			elem.removeAttribute(attr);
		});
		return this;
	};

	['add', 'remove'].forEach(function(action){
		fn[action + 'Class'] =  function(cl){
			this.elements.forEach(function(elem){
				elem.classList[action](cl);
			});
			return this;
		};
	});

	fn.is = function(sel){
		return this.elements.some(function(elem){
			return elem.matches(sel);
		});
	};

	fn.html = function(html){
		var elem;
		var isString = typeof html == 'string';
		if(!arguments.length){
			elem = this.elements[0];
			return elem && elem.innerHTML || '';
		}
		this.elements.forEach(function(elem){
			if(isString){
				elem.innerHTML = html;
			} else {
				elem.innerHTML = '';
				elem.appendChild(html);
			}
		});
		return this;
	};

	fn.before = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			var parentElement;
			if (isString){
				elem.insertAdjacentHTML('beforebegin', html);
			} else {
				parentElement = elem.parentNode;
				if(parentElement){
					parentElement.insertBefore(html, elem);
				}
			}
		});
		return this;
	};

	fn.prepend = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			if (isString){
				elem.insertAdjacentHTML('afterbegin', html);
			} else {
				elem.insertBefore(html, elem.firstChild);
			}
		});
		return this;
	};

	fn.append = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			if (isString){
				elem.insertAdjacentHTML('beforeend', html);
			} else {
				elem.insertBefore(html, null);
			}
		});
		return this;
	};

	fn.after = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			var parentElement;
			if (isString){
				elem.insertAdjacentHTML('afterend', html);
			} else {
				parentElement = elem.parentNode;
				if(parentElement){
					parentElement.insertBefore(html, elem.nextElementSibling);
				}
			}
		});
		return this;
	};

	fn.each = function(cb){
		this.elements.forEach(function(elem, index){
			cb.call(elem, index, elem);
		});
		return this;
	};

	fn.trigger = function(type, options){
		var firstEvent;

		if(typeof type == 'object'){
			firstEvent = type;
			type = firstEvent.type;
		}

		if(!options){
			options = {};
		}

		if(options.bubbles == null){
			options.bubbles = true;
		}

		this.elements.forEach(function(elem){
			var event = firstEvent || new CustomEvent(type, options);
			firstEvent = null;
			elem.dispatchEvent(event);
		});

		return this;
	};

	fn.animate = function(endProps, options){
		this.elements.forEach(function(elem){
			tween(elem, endProps, options);
		});
		return this;
	};

	fn.stop = function(clearQueue, jumpToEnd){
		this.elements.forEach(function(elem) {
			if (elem._rbTweenStop) {
				elem._rbTweenStop(clearQueue, jumpToEnd);
			}
		});
		return this;
	};

	//new array or returns array
	['map', 'filter'].forEach(function(name){
		fn[name] = function(fn){
			var sel;

			if(typeof fn == 'string'){
				sel = fn;
				fn = function(){
					return this.matches(sel);
				};
			}
			return new dom(this.elements[name](function(elem, index){
				return fn.call(elem, index, elem);
			}));
		};
	});

	['every', 'findIndex', 'includes', 'indexOf', 'lastIndexOf', 'some'].forEach(function(name){
		fn[name] = function(){
			return this.elements[name].apply(this.elements, arguments);
		};
	});

	return dom;
}));
<commit_msg>fix instanceof dom<commit_after>(function(window, factory) {
	var dom = factory(window, window.document);
	window.dom = dom;
	if(typeof module == 'object' && module.exports){
		module.exports = dom;
	}
}(typeof window != 'undefined' ? window : this , function(window, document) {
	'use strict';
	var slice = [].slice;
	var dom = function(elements){

		if(typeof elements == 'string'){
			return dom.q(elements);
		}
		if(!(this instanceof dom)){
			return new dom(elements);
		}

		if(!Array.isArray(elements)){
			if(!elements){
				elements = [];
			} else if(elements.nodeName || !('length' in elements) || elements == window){
				elements = [elements];
			} else {
				elements = slice.call(elements);
			}
		}

		this.elements = elements;
		this.length = this.elements.length || 0;
	};
	var fn = dom.prototype;
	var tween = function(element, endProps, options){

		var easing, isStopped, isJumpToEnd, bezierArgs, requestID;
		var start = Date.now();
		var elementStyle = element.style;
		var startProps = {};
		var stop = function(clearQueue, jumpToEnd){
			isStopped = true;
			if(jumpToEnd){
				isJumpToEnd = true;
			}
			step();
			cancelAnimationFrame(requestID);
		};

		var step = function() {
			var prop, value, eased;
			var pos = (Date.now() - start) / options.duration;

			if(pos > 1 || isJumpToEnd){
				pos = 1;
			}

			if(!isStopped){
				eased = easing(pos);

				for(prop in startProps){
					value = (endProps[prop] - startProps[prop]) * eased + startProps[prop];

					if(prop in elementStyle){
						elementStyle[prop] = value +'px';
					} else {
						element[prop] = value;
					}
				}
			}

			if(pos < 1){
				if(!isStopped){
					requestID = requestAnimationFrame(step);
				} else if(options.always){
					options.always.call(element);
				}
			} else{
				if(element._rbTweenStop){
					delete element._rbTweenStop;
				}
				if(options.complete && !isStopped){
					options.complete.call(element);
				}
				if(options.always){
					options.always.call(element);
				}
			}
		};

		tween.getStartValues(element, elementStyle, startProps, endProps);

		options = Object.assign({duration: 400, easing: 'ease'}, options || {});

		if(window.BezierEasing && !BezierEasing.css[options.easing] && (bezierArgs = options.easing.match(/([0-9\.]+)/g)) && bezierArgs.length == 4){
			bezierArgs = bezierArgs.map(function(str){
				return parseFloat(str);
			});
			BezierEasing.css[options.easing] = BezierEasing.apply(this, bezierArgs);
		}

		easing = window.BezierEasing && (BezierEasing.css[options.easing] || BezierEasing.css.ease) || function(pos){
				return pos;
			};

		element._rbTweenStop = stop;

		requestID = requestAnimationFrame(step);
	};

	tween.getStartValues = function(element, elementStyle, startProps, endProps){
		var prop;
		for(prop in endProps){
			if(prop in elementStyle){
				startProps[prop] = parseFloat(getComputedStyle(element).getPropertyValue(prop));
			} else {
				startProps[prop] = element[prop];
			}
		}
	};

	dom.fn = dom.prototype;

	dom.q = function(sel, context){
		return new dom( (context || document).querySelectorAll(sel) );
	};

	dom.Event = function(type, options){
		var event;
		if(!options){
			options = {};
		}

		if(options.bubbles == null){
			options.bubbles = true;
		}
		event = new CustomEvent(type, options);

		if(!event.isDefaultPrevented){
			event.isDefaultPrevented = function(){
				return event.defaultPrevented;
			};
		}

		return event;
	};

	fn.find = function(sel){
		var array = [];
		this.elements.forEach(function(elem){
			var i, len;
			var elements = elem.querySelectorAll(sel);
			for(i = 0, len = elements.length; i < len; i++){
				if(array.indexOf(elements[i]) == -1){
					array.push(elements[i]);
				}
			}
		});

		return new dom( array );
	};

	fn.closest = function(sel){
		var array = [];
		this.elements.forEach(function(elem){
			var element = elem.closest(sel);
			if(array.indexOf(element) == -1){
				array.push(element);
			}
		});
		return new dom( array );
	};

	fn.get = function(number){
		return arguments.length ? this.elements[number] : this.elements;
	};

	[['on', 'addEventListener'], ['off', 'removeEventListener']].forEach(function(action){
		dom.fn[action[0]] = function(type, sel, fn, capture){
			var useFn;
			if(typeof sel == 'function'){
				capture = fn;
				fn = sel;
				sel = null;
			}

			if(sel){
				if(!fn[sel]){
					fn[sel] = function(e){
						e.delegateTarget = e.target.closest(sel);
						if(!e.delegateTarget){return;}
						return fn.apply(this, arguments);
					};
				}
				useFn = fn[sel];
			} else {
				useFn = fn;
			}

			this.elements.forEach(function(elem){
				elem[action[1]](type, useFn, capture || false);
			});

			return this;
		};
	});

	fn.css = function(style, pseudo){
		var elem;
		if(typeof style == 'string'){
			elem = this.elements[0];
			return elem && getComputedStyle(elem, pseudo).getPropertyValue(style);
		}
		this.elements.forEach(function(elem){
			var prop;
			var eStyle = elem.style;
			for(prop in style){
				eStyle[prop] = style[prop];
			}
		});
		return this;
	};

	fn.prop = function(props){
		var elem;
		if(typeof props == 'string'){
			elem = this.elements[0];
			return elem && elem[props];
		}
		this.elements.forEach(function(elem){
			var prop;
			for(prop in props){
				elem[prop] = props[prop];
			}
		});
		return this;
	};

	fn.attr = function(attrs){
		var elem;
		if(typeof attrs == 'string'){
			elem = this.elements[0];
			return elem && elem.getAttribute(attrs);
		}
		this.elements.forEach(function(elem){
			var attr;
			for(attr in attrs){
				elem.setAttribute(attr, attrs[attr]);
			}
		});
		return this;
	};

	fn.removeAttr = function(attr){
		this.elements.forEach(function(elem){
			elem.removeAttribute(attr);
		});
		return this;
	};

	['add', 'remove'].forEach(function(action){
		fn[action + 'Class'] =  function(cl){
			this.elements.forEach(function(elem){
				elem.classList[action](cl);
			});
			return this;
		};
	});

	fn.is = function(sel){
		return this.elements.some(function(elem){
			return elem.matches(sel);
		});
	};

	fn.html = function(html){
		var elem;
		var isString = typeof html == 'string';
		if(!arguments.length){
			elem = this.elements[0];
			return elem && elem.innerHTML || '';
		}
		this.elements.forEach(function(elem){
			if(isString){
				elem.innerHTML = html;
			} else {
				elem.innerHTML = '';
				elem.appendChild(html);
			}
		});
		return this;
	};

	fn.before = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			var parentElement;
			if (isString){
				elem.insertAdjacentHTML('beforebegin', html);
			} else {
				parentElement = elem.parentNode;
				if(parentElement){
					parentElement.insertBefore(html, elem);
				}
			}
		});
		return this;
	};

	fn.prepend = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			if (isString){
				elem.insertAdjacentHTML('afterbegin', html);
			} else {
				elem.insertBefore(html, elem.firstChild);
			}
		});
		return this;
	};

	fn.append = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			if (isString){
				elem.insertAdjacentHTML('beforeend', html);
			} else {
				elem.insertBefore(html, null);
			}
		});
		return this;
	};

	fn.after = function(html){
		var isString = typeof html == 'string';
		this.elements.forEach(function(elem){
			var parentElement;
			if (isString){
				elem.insertAdjacentHTML('afterend', html);
			} else {
				parentElement = elem.parentNode;
				if(parentElement){
					parentElement.insertBefore(html, elem.nextElementSibling);
				}
			}
		});
		return this;
	};

	fn.each = function(cb){
		this.elements.forEach(function(elem, index){
			cb.call(elem, index, elem);
		});
		return this;
	};

	fn.trigger = function(type, options){
		var firstEvent;

		if(typeof type == 'object'){
			firstEvent = type;
			type = firstEvent.type;
		}

		if(!options){
			options = {};
		}

		if(options.bubbles == null){
			options.bubbles = true;
		}

		this.elements.forEach(function(elem){
			var event = firstEvent || new CustomEvent(type, options);
			firstEvent = null;
			elem.dispatchEvent(event);
		});

		return this;
	};

	fn.animate = function(endProps, options){
		this.elements.forEach(function(elem){
			tween(elem, endProps, options);
		});
		return this;
	};

	fn.stop = function(clearQueue, jumpToEnd){
		this.elements.forEach(function(elem) {
			if (elem._rbTweenStop) {
				elem._rbTweenStop(clearQueue, jumpToEnd);
			}
		});
		return this;
	};

	//new array or returns array
	['map', 'filter'].forEach(function(name){
		fn[name] = function(fn){
			var sel;

			if(typeof fn == 'string'){
				sel = fn;
				fn = function(){
					return this.matches(sel);
				};
			}
			return new dom(this.elements[name](function(elem, index){
				return fn.call(elem, index, elem);
			}));
		};
	});

	['every', 'findIndex', 'includes', 'indexOf', 'lastIndexOf', 'some'].forEach(function(name){
		fn[name] = function(){
			return this.elements[name].apply(this.elements, arguments);
		};
	});

	return dom;
}));
<|endoftext|>


<commit_before>// Turn on a global notification. Set this to `true` to show
// the message in NotificationComponent to all users.
export const showGlobalNotification = () => true

export const isAnonymousUserSignInEnabled = () => false

export const isVariousAdSizesEnabled = () => false

export const isSearchPageEnabled = () =>
  process.env.REACT_APP_FEATURE_FLAG_SEARCH_PAGE_ENABLED === 'true'

export const shouldRedirectSearchToThirdParty = () =>
  process.env.REACT_APP_FEATURE_FLAG_REDIRECT_SEARCH_TO_THIRD_PARTY === 'true'

export const showBingJSAds = () =>
  process.env.REACT_APP_FEATURE_FLAG_BING_JS_ADS === 'true'

export const isBingJSAdsProductionMode = () =>
  process.env.REACT_APP_FEATURE_FLAG_BING_JS_ADS_PRODUCTION_MODE === 'true'

export const showSearchIntroductionMessage = () => false

export const isGAMDevEnvironment = () =>
  process.env.REACT_APP_GAM_DEV_ENVIRONMENT === 'true'

export const showVideoAds = () => true
<commit_msg>End January Charity Spotlight voting<commit_after>// Turn on a global notification. Set this to `true` to show
// the message in NotificationComponent to all users.
export const showGlobalNotification = () => false

export const isAnonymousUserSignInEnabled = () => false

export const isVariousAdSizesEnabled = () => false

export const isSearchPageEnabled = () =>
  process.env.REACT_APP_FEATURE_FLAG_SEARCH_PAGE_ENABLED === 'true'

export const shouldRedirectSearchToThirdParty = () =>
  process.env.REACT_APP_FEATURE_FLAG_REDIRECT_SEARCH_TO_THIRD_PARTY === 'true'

export const showBingJSAds = () =>
  process.env.REACT_APP_FEATURE_FLAG_BING_JS_ADS === 'true'

export const isBingJSAdsProductionMode = () =>
  process.env.REACT_APP_FEATURE_FLAG_BING_JS_ADS_PRODUCTION_MODE === 'true'

export const showSearchIntroductionMessage = () => false

export const isGAMDevEnvironment = () =>
  process.env.REACT_APP_GAM_DEV_ENVIRONMENT === 'true'

export const showVideoAds = () => true
<|endoftext|>


<commit_before>define(["avalon"], function(avalon) {
    var defaults = {
        ghosting: false, //是否影子拖动，动态生成一个元素，拖动此元素，当拖动结束时，让原元素到达此元素的位置上,
        delay: 0,
        axis: "xy",
        started: true,
        start: avalon.noop,
        beforeStart: avalon.noop,
        drag: avalon.noop,
        beforeStop: avalon.noop,
        stop: avalon.noop,
        scrollPlugin: true,
        scrollSensitivity: 20,
        scrollSpeed: 20
    }
    var body
    var ua = navigator.userAgent;
    var isAndroid = /Android/i.test(ua);
    var isBlackBerry = /BlackBerry/i.test(ua)
    var isWindowPhone = /IEMobile/i.test(ua)
    var isIOS = /iPhone|iPad|iPod/i.test(ua)
    var isMobile = isAndroid || isBlackBerry || isWindowPhone || isIOS
    if (!isMobile) {
        var dragstart = "mousedown"
        var drag = "mousemove"
        var dragstop = "mouseup"
    } else {
        dragstart = "touchstart"
        drag = "touchmove"
        dragstop = "touchend"
    }
   function filterData(obj, prefix) {
            var result = {}
            for (var i in obj) {
                if (i.indexOf(prefix) === 0) {
                    result[  i.replace(prefix, "").replace(/\w/, function(a) {
                        return a.toLowerCase()
                    }) ] = obj[i]
                }
            }
            return result
        }
    var draggable = avalon.bindingHandlers.draggable = function(data, vmodels) {
        var args = data.value.match(avalon.rword)
        var ID = args ? args[0].trim() : null, model
        if (ID && ID != "$") {
            model = avalon.vmodels[ID]//如果指定了此VM的ID
            if (!model) {
                data.remove = false
                return
            }
        }
        if (!model) {
            model = vmodels.length ? vmodels[0].$model : {}
        }
        var opts = args && args.length == 2 ? args[1] : null //options在model中的名字
        var vmOptions = {}
        if (model && opts && typeof model[opts] === "object") {
            vmOptions = model[opts]
            if (vmOptions.$model) {
                vmOptions = vmOptions.$model
            }
        }
        var element = data.element
        var $element = avalon(element)
        var options = avalon.mix({}, defaults, model, vmOptions, filterData($element.data(),"drag"));
        //修正drag,stop为函数
        "drag,stop,start,beforeStart,beforeStop".replace(avalon.rword, function(name) {
            var method = options[name]
            if (typeof method === "string") {
                if (typeof model[method] === "function") {
                    options[name] = model[method]
                } else {
                    options[name] = avalon.noop
                }
            }
        })

        if (options.axis !== "" && !/^(x|y|xy)$/.test(options.axis)) {
            options.axis = "xy"
        }
        body = document.body //因为到这里时，肯定已经domReady

        $element.bind(dragstart, function(e) {
            var data = avalon.mix({}, options, {
                element: element,
                $element: $element,
                pageX: getPosition(e, "X"), //相对于页面的坐标, 会改动
                pageY: getPosition(e, "Y"), //相对于页面的坐标，会改动
                marginLeft: parseFloat($element.css("marginLeft")) || 0,
                marginTop: parseFloat($element.css("marginTop")) || 0
            })

            data.startPageX = data.pageX//一次拖放只赋值一次
            data.startPageY = data.pageY//一次拖放只赋值一次
            options.axis.replace(/./g, function(a) {
                data["drag" + a.toUpperCase() ] = true
            })
            if (!data.dragX && !data.dragY) {
                data.started = false
            }
            //在处理手柄拖动前做些事情
            if (typeof options.beforeStart === "function") {
                options.beforeStart.call(data.element, e, data)
            }

            if (data.handle && model) {// 实现手柄拖动
                var handle = model[data.handle]
                if (typeof handle === "function") {
                    var checked = handle.call(element, e, data)//要求返回一节点
                    if (checked && checked.nodeType === 1) {
                        if (!element.contains(checked)) {
                            return // 不能返回 false，这会阻止文本被选择
                        }
                    } else {
                        return
                    }
                }
            }
            fixUserSelect()
            var position = $element.css("position")
            //如果原元素没有被定位
            if (!/^(?:r|a|f)/.test(position)) {
                element.style.position = "relative";
                element.style.top = "0px"
                element.style.left = "0px"
            }

            if (options.delay && isFinite(options.delay)) {
                data.started = false;
                setTimeout(function() {
                    data.started = true
                }, options.delay)
            }
            var startOffset = $element.offset()
            if (options.ghosting) {
                var clone = element.cloneNode(true)
                avalon(clone).css("opacity", .7).width(element.offsetWidth).height(element.offsetHeight)
                data.clone = clone
                if (position !== "fixed") {
                    clone.style.position = "absolute"
                    clone.style.top = startOffset.top - data.marginTop + "px"
                    clone.style.left = startOffset.left - data.marginLeft + "px"
                }
                body.appendChild(clone)
            }
            var target = avalon(data.clone || data.element)
            //拖动前相对于offsetParent的坐标
            data.startLeft = parseFloat(target.css("left"))
            data.startTop = parseFloat(target.css("top"))

            //拖动后相对于offsetParent的坐标
            //如果是影子拖动，代理元素是绝对定位时，它与原元素的top, left是不一致的，因此当结束拖放时，不能直接将改变量赋给原元素
            data.endLeft = parseFloat($element.css("left")) - data.startLeft
            data.endTop = parseFloat($element.css("top")) - data.startTop

            data.clickX = data.pageX - startOffset.left //鼠标点击的位置与目标元素左上角的距离
            data.clickY = data.pageY - startOffset.top //鼠标点击的位置与目标元素左上角的距离
            setContainment(options, data)//修正containment
            draggable.dragData = data//决定有东西在拖动
            "start,drag,beforeStop,stop".replace(avalon.rword, function(name) {
                draggable[name] = [options[name]]
            })
            draggable.plugin.call("start", e, data)
        })

    }
    var xy2prop = {
        "X": "Left",
        "Y": "Top"
    }
    //插件系统
    draggable.dragData = {}
    draggable.start = []
    draggable.drag = []
    draggable.stop = []
    draggable.beforeStop = []
    draggable.plugin = {
        add: function(name, set) {
            for (var i in set) {
                var fn = set[i]
                if (typeof fn === "function" && Array.isArray(draggable[i])) {
                    fn.isPlugin = true
                    fn.pluginName = name + "Plugin"
                    draggable[i].push(fn)
                }
            }
        },
        call: function(name, e, data) {
            var array = draggable[name]
            if (Array.isArray(array)) {
                array.forEach(function(fn) {
                    //用户回调总会执行，插件要看情况
                    if (typeof fn.pluginName === "undefined" ? true : data[fn.pluginName]) {
                        fn.call(data.element, e, data)
                    }
                })
            }
            if (name === "stop") {
                for (var i in draggable) {
                    array = draggable[i]
                    if (Array.isArray(array)) {
                        array.forEach(function(fn) {
                            if (!fn.isPlugin) {// 用户回调都是一次性的，插件的方法永远放在列队中
                                avalon.Array.remove(array, fn)
                            }
                        })
                    }
                }
            }
        }
    }

    function getPosition(e, pos) {
        var page = "page" + pos
        return isMobile ? e.changedTouches[0][page] : e[page]
    }

    function setPosition(e, element, data, pos, end) {
        var page = getPosition(e, pos)
        if (data.containment) {
            var min = pos === "X" ? data.containment[0] : data.containment[1]
            var max = pos === "X" ? data.containment[2] : data.containment[3]
            var check = page - (pos === "X" ? data.clickX : data.clickY)
            if (check < min) {
                page += Math.abs(min - check)
            } else if (check > max) {
                page -= Math.abs(max - check)
            }
        }
        data["page" + pos] = page//重设pageX, pageY
        var Prop = xy2prop[pos]
        var prop = Prop.toLowerCase()

        var number = data["start" + Prop] + page - data["startPage" + pos] + (end ? data["end" + Prop] : 0)
        data[prop] = number
        if (data["drag" + pos]) {//保存top, left
            element.style[ prop ] = number + "px"
        }
    }

    var styleEl = document.createElement("style")

    var cssText = "*{ -webkit-touch-callout: none!important;-webkit-user-select: none!important;-khtml-user-select: none!important;" +
            "-moz-user-select: none!important;-ms-user-select: none!important;user-select: none!important;}"
    var fixUserSelect = function() {
        body.appendChild(styleEl)
        //如果不插入DOM树，styleEl.styleSheet为null
        if (typeof styleEl.styleSheet === "object") {
            styleEl.styleSheet.cssText = cssText
        } else {
            styleEl.appendChild(document.createTextNode(cssText))
        }
    }
    var restoreUserSelect = function() {
        try {
            styleEl.innerHTML = ""
        } catch (e) {
            styleEl.styleSheet.cssText = ""
        }
        body.removeChild(styleEl)
    }
    if (window.VBArray && !("msUserSelect" in document.documentElement.style)) {
        var _ieSelectBack;//fix IE6789
        function returnFalse() {
            return false;
        }
        fixUserSelect = function() {
            _ieSelectBack = body.onselectstart;
            body.onselectstart = returnFalse;
        }
        restoreUserSelect = function() {
            body.onselectstart = _ieSelectBack;
        }
    }
    //统一处理拖动的事件
    avalon(document).bind(drag, function(e) {
        var data = draggable.dragData
        if (data.started === true) {
            //fix touchmove bug;
            //IE 在 img 上拖动时默认不能拖动（不触发 mousemove，mouseup 事件，mouseup 后接着触发 mousemove ...）
            //防止 html5 draggable 元素的拖放默认行为 (选中文字拖放)
            e.preventDefault();
            //使用document.selection.empty()来清除选择，会导致捕获失败
            var element = data.clone || data.element
            setPosition(e, element, data, "X")
            setPosition(e, element, data, "Y")
            draggable.plugin.call("drag", e, data)
        }

    })

    //统一处理拖动结束的事件
    avalon(document).bind(dragstop, function(e) {
        var data = draggable.dragData
        if (data.started === true) {
            restoreUserSelect()
            var element = data.element
            draggable.plugin.call("beforeStop", e, data)
            if (data.dragX) {
                setPosition(e, element, data, "X", true)
            }
            if (data.dragY) {
                setPosition(e, element, data, "Y", true)
            }
            if (data.clone) {
                body.removeChild(data.clone)
            }
            draggable.plugin.call("stop", e, data)
            draggable.dragData = {}
        }
    })

    function getWindow(node) {
        return node.window && node.document ? node : node.nodeType === 9 ? node.defaultView || node.parentWindow : false;
    }
    function setContainment(o, data) {
        if (!o.containment) {
            if (Array.isArray(data.containment)) {
                return
            }
            data.containment = null;
            return;
        }

        if (o.containment === "window") {
            var $window = avalon(window)
            //左， 上， 右， 下
            data.containment = [
                $window.scrollLeft(),
                $window.scrollTop(),
                $window.scrollLeft() + $window.width() - data.marginLeft,
                $window.scrollTop() + $window.height() - data.marginTop
            ];
            return;
        }

        if (o.containment === "document") {
            data.containment = [
                0,
                0,
                avalon(document).width() - data.marginLeft,
                avalon(document).height() - data.marginTop
            ];
            return;
        }

        if (Array.isArray(o.containment)) {
            data.containment = o.containment;
            return;
        }

        if (o.containment === "parent" || o.containment.charAt(0) === "#") {
            var elem
            if (o.containment === "parent") {
                elem = data.element.parentNode;
            } else {
                elem = document.getElementById(o.containment.slice(1))
            }
            if (elem) {
                var $offset = avalon(elem).offset()

                data.containment = [
                    $offset.left,
                    $offset.top,
                    Math.floor($offset.left + elem.offsetWidth - data.marginLeft - data.$element.width()),
                    Math.floor($offset.top + elem.offsetHeight - data.marginTop - data.$element.height())
                ]

            }
        }
    }

    return avalon
})
/*
 ms-draggable="VMID?" , VMID为一个VM的ID,可选
 下面这些全部可用data-drag-*进行配置
 drag 为VM中一个方法名
 stop 为VM中一个方法名
 start  为VM中一个方法名
 handle  要求为VM中的一个函数，它会重置data.handle为一个元素节点，如果事件源位于data.handle的里面或等于它则继续进行操作
 ghosting: false, //是否影子拖动，动态生成一个元素，拖动此元素，当拖动结束时，让原元素到达此元素的位置上,
 delay: 0, 延迟时间
 axis: "xy" "x", "y" 决定只能垂直拖动，还是水平拖动，还是任意拖动
 containment： 拖动范围，#id值， "window", "document", "parent", "[0, 0, 400, 300]"

item {{$index}}

 avalon.require("avalon.draggable", function() {
 avalon.define("xxx", function(vm) {
 vm.array = avalon.range(0, 10)
 vm.drag = function(e, data) {
 console.log(e.pageX + " : " + e.pageY)
 }
 vm.stop = function(e, data) {
 console.log("done")
 }
 })
 avalon.scan()
 })
 *
 */<commit_msg>update draggable<commit_after>define(["avalon"], function(avalon) {
    var defaults = {
        ghosting: false, //是否影子拖动，动态生成一个元素，拖动此元素，当拖动结束时，让原元素到达此元素的位置上,
        delay: 0,
        axis: "xy",
        started: true,
        start: avalon.noop,
        beforeStart: avalon.noop,
        drag: avalon.noop,
        beforeStop: avalon.noop,
        stop: avalon.noop,
        scrollPlugin: true,
        scrollSensitivity: 20,
        scrollSpeed: 20
    }
    var body
    var ua = navigator.userAgent;
    var isAndroid = /Android/i.test(ua);
    var isBlackBerry = /BlackBerry/i.test(ua)
    var isWindowPhone = /IEMobile/i.test(ua)
    var isIOS = /iPhone|iPad|iPod/i.test(ua)
    var isMobile = isAndroid || isBlackBerry || isWindowPhone || isIOS
    if (!isMobile) {
        var dragstart = "mousedown"
        var drag = "mousemove"
        var dragstop = "mouseup"
    } else {
        dragstart = "touchstart"
        drag = "touchmove"
        dragstop = "touchend"
    }
    function filterData(obj, prefix) {
        var result = {}
        for (var i in obj) {
            if (i.indexOf(prefix) === 0) {
                result[  i.replace(prefix, "").replace(/\w/, function(a) {
                    return a.toLowerCase()
                }) ] = obj[i]
            }
        }
        return result
    }
    var draggable = avalon.bindingHandlers.draggable = function(data, vmodels) {
        var args = data.value.match(avalon.rword)
        var ID = args ? args[0].trim() : null, model, vmOptions
        var opts = args[1]
        if (ID && ID != "$") {
            model = avalon.vmodels[ID]//如果指定了此VM的ID
            if (!model) {
                data.remove = false
                return
            }
        }
        if (!model) {//如果使用$或绑定值为空，那么就默认取最近一个VM，没有拉倒
            model = vmodels.length ? vmodels[0] : null
        }
        var fnObj = model || {}
        if (opts && model && typeof model[opts] === "object") {//如果指定了配置对象，并且有VM
            vmOptions = model[opts]
            if (vmOptions.$model) {
                vmOptions = vmOptions.$model
            }
            fnObj = vmOptions
        }
        var element = data.element
        var $element = avalon(element)
        var options = avalon.mix({}, defaults, vmOptions || {}, filterData($element.data(), "drag"));
        //修正drag,stop为函数
        "drag,stop,start,beforeStart,beforeStop".replace(avalon.rword, function(name) {
            var method = options[name]
            if (typeof method === "string") {
                if (typeof fnObj[method] === "function") {

                    options[name] = fnObj[method]
                } else {
                    options[name] = avalon.noop
                }
            }
        })
        if (options.axis !== "" && !/^(x|y|xy)$/.test(options.axis)) {
            options.axis = "xy"
        }
        body = document.body //因为到这里时，肯定已经domReady

        $element.bind(dragstart, function(e) {
            var data = avalon.mix({}, options, {
                element: element,
                $element: $element,
                pageX: getPosition(e, "X"), //相对于页面的坐标, 会改动
                pageY: getPosition(e, "Y"), //相对于页面的坐标，会改动
                marginLeft: parseFloat($element.css("marginLeft")) || 0,
                marginTop: parseFloat($element.css("marginTop")) || 0
            })

            data.startPageX = data.pageX//一次拖放只赋值一次
            data.startPageY = data.pageY//一次拖放只赋值一次
            options.axis.replace(/./g, function(a) {
                data["drag" + a.toUpperCase() ] = true
            })
            if (!data.dragX && !data.dragY) {
                data.started = false
            }
            //在处理手柄拖动前做些事情
            if (typeof options.beforeStart === "function") {
                options.beforeStart.call(data.element, e, data)
            }

            if (data.handle && fnObj) {// 实现手柄拖动
                var handle = fnObj[data.handle]
                if (typeof handle === "function") {
                    var checked = handle.call(element, e, data)//要求返回一节点
                    if (checked && checked.nodeType === 1) {
                        if (!element.contains(checked)) {
                            return // 不能返回 false，这会阻止文本被选择
                        }
                    } else {
                        return
                    }
                }
            }
            fixUserSelect()
            var position = $element.css("position")
            //如果原元素没有被定位
            if (!/^(?:r|a|f)/.test(position)) {
                element.style.position = "relative";
                element.style.top = "0px"
                element.style.left = "0px"
            }

            if (options.delay && isFinite(options.delay)) {
                data.started = false;
                setTimeout(function() {
                    data.started = true
                }, options.delay)
            }
            var startOffset = $element.offset()
            if (options.ghosting) {
                var clone = element.cloneNode(true)
                avalon(clone).css("opacity", .7).width(element.offsetWidth).height(element.offsetHeight)
                data.clone = clone
                if (position !== "fixed") {
                    clone.style.position = "absolute"
                    clone.style.top = startOffset.top - data.marginTop + "px"
                    clone.style.left = startOffset.left - data.marginLeft + "px"
                }
                body.appendChild(clone)
            }
            var target = avalon(data.clone || data.element)
            //拖动前相对于offsetParent的坐标
            data.startLeft = parseFloat(target.css("left"))
            data.startTop = parseFloat(target.css("top"))

            //拖动后相对于offsetParent的坐标
            //如果是影子拖动，代理元素是绝对定位时，它与原元素的top, left是不一致的，因此当结束拖放时，不能直接将改变量赋给原元素
            data.endLeft = parseFloat($element.css("left")) - data.startLeft
            data.endTop = parseFloat($element.css("top")) - data.startTop

            data.clickX = data.pageX - startOffset.left //鼠标点击的位置与目标元素左上角的距离
            data.clickY = data.pageY - startOffset.top //鼠标点击的位置与目标元素左上角的距离
            setContainment(options, data)//修正containment
            draggable.dragData = data//决定有东西在拖动
            "start,drag,beforeStop,stop".replace(avalon.rword, function(name) {
                draggable[name] = [options[name]]
            })
            draggable.plugin.call("start", e, data)
        })

    }
    var xy2prop = {
        "X": "Left",
        "Y": "Top"
    }
    //插件系统
    draggable.dragData = {}
    draggable.start = []
    draggable.drag = []
    draggable.stop = []
    draggable.beforeStop = []
    draggable.plugin = {
        add: function(name, set) {
            for (var i in set) {
                var fn = set[i]
                if (typeof fn === "function" && Array.isArray(draggable[i])) {
                    fn.isPlugin = true
                    fn.pluginName = name + "Plugin"
                    draggable[i].push(fn)
                }
            }
        },
        call: function(name, e, data) {
            var array = draggable[name]
            if (Array.isArray(array)) {
                array.forEach(function(fn) {
                    //用户回调总会执行，插件要看情况
                    if (typeof fn.pluginName === "undefined" ? true : data[fn.pluginName]) {
                        fn.call(data.element, e, data)
                    }
                })
            }
            if (name === "stop") {
                for (var i in draggable) {
                    array = draggable[i]
                    if (Array.isArray(array)) {
                        array.forEach(function(fn) {
                            if (!fn.isPlugin) {// 用户回调都是一次性的，插件的方法永远放在列队中
                                avalon.Array.remove(array, fn)
                            }
                        })
                    }
                }
            }
        }
    }

    function getPosition(e, pos) {
        var page = "page" + pos
        return isMobile ? e.changedTouches[0][page] : e[page]
    }

    function setPosition(e, element, data, pos, end) {
        var page = getPosition(e, pos)
        if (data.containment) {
            var min = pos === "X" ? data.containment[0] : data.containment[1]
            var max = pos === "X" ? data.containment[2] : data.containment[3]
            var check = page - (pos === "X" ? data.clickX : data.clickY)
            if (check < min) {
                page += Math.abs(min - check)
            } else if (check > max) {
                page -= Math.abs(max - check)
            }
        }
        data["page" + pos] = page//重设pageX, pageY
        var Prop = xy2prop[pos]
        var prop = Prop.toLowerCase()

        var number = data["start" + Prop] + page - data["startPage" + pos] + (end ? data["end" + Prop] : 0)
        data[prop] = number
        if (data["drag" + pos]) {//保存top, left
            element.style[ prop ] = number + "px"
        }
    }

    var styleEl = document.createElement("style")

    var cssText = "*{ -webkit-touch-callout: none!important;-webkit-user-select: none!important;-khtml-user-select: none!important;" +
            "-moz-user-select: none!important;-ms-user-select: none!important;user-select: none!important;}"
    var fixUserSelect = function() {
        body.appendChild(styleEl)
        //如果不插入DOM树，styleEl.styleSheet为null
        if (typeof styleEl.styleSheet === "object") {
            styleEl.styleSheet.cssText = cssText
        } else {
            styleEl.appendChild(document.createTextNode(cssText))
        }
    }
    var restoreUserSelect = function() {
        try {
            styleEl.innerHTML = ""
        } catch (e) {
            styleEl.styleSheet.cssText = ""
        }
        body.removeChild(styleEl)
    }
    if (window.VBArray && !("msUserSelect" in document.documentElement.style)) {
        var _ieSelectBack;//fix IE6789
        function returnFalse() {
            return false;
        }
        fixUserSelect = function() {
            _ieSelectBack = body.onselectstart;
            body.onselectstart = returnFalse;
        }
        restoreUserSelect = function() {
            body.onselectstart = _ieSelectBack;
        }
    }
    //统一处理拖动的事件
    avalon(document).bind(drag, function(e) {
        var data = draggable.dragData
        if (data.started === true) {
            //fix touchmove bug;
            //IE 在 img 上拖动时默认不能拖动（不触发 mousemove，mouseup 事件，mouseup 后接着触发 mousemove ...）
            //防止 html5 draggable 元素的拖放默认行为 (选中文字拖放)
            e.preventDefault();
            //使用document.selection.empty()来清除选择，会导致捕获失败
            var element = data.clone || data.element
            setPosition(e, element, data, "X")
            setPosition(e, element, data, "Y")
            draggable.plugin.call("drag", e, data)
        }

    })

    //统一处理拖动结束的事件
    avalon(document).bind(dragstop, function(e) {
        var data = draggable.dragData
        if (data.started === true) {
            restoreUserSelect()
            var element = data.element
            draggable.plugin.call("beforeStop", e, data)
            if (data.dragX) {
                setPosition(e, element, data, "X", true)
            }
            if (data.dragY) {
                setPosition(e, element, data, "Y", true)
            }
            if (data.clone) {
                body.removeChild(data.clone)
            }
            draggable.plugin.call("stop", e, data)
            draggable.dragData = {}
        }
    })

    function getWindow(node) {
        return node.window && node.document ? node : node.nodeType === 9 ? node.defaultView || node.parentWindow : false;
    }
    function setContainment(o, data) {
        if (!o.containment) {
            if (Array.isArray(data.containment)) {
                return
            }
            data.containment = null;
            return;
        }

        if (o.containment === "window") {
            var $window = avalon(window)
            //左， 上， 右， 下
            data.containment = [
                $window.scrollLeft(),
                $window.scrollTop(),
                $window.scrollLeft() + $window.width() - data.marginLeft,
                $window.scrollTop() + $window.height() - data.marginTop
            ];
            return;
        }

        if (o.containment === "document") {
            data.containment = [
                0,
                0,
                avalon(document).width() - data.marginLeft,
                avalon(document).height() - data.marginTop
            ];
            return;
        }

        if (Array.isArray(o.containment)) {
            data.containment = o.containment;
            return;
        }

        if (o.containment === "parent" || o.containment.charAt(0) === "#") {
            var elem
            if (o.containment === "parent") {
                elem = data.element.parentNode;
            } else {
                elem = document.getElementById(o.containment.slice(1))
            }
            if (elem) {
                var $offset = avalon(elem).offset()

                data.containment = [
                    $offset.left,
                    $offset.top,
                    Math.floor($offset.left + elem.offsetWidth - data.marginLeft - data.$element.width()),
                    Math.floor($offset.top + elem.offsetHeight - data.marginTop - data.$element.height())
                ]

            }
        }
    }

    return avalon
})
/*
 ms-draggable="VMID?" , VMID为一个VM的ID,可选
 下面这些全部可用data-drag-*进行配置
 drag 为VM中一个方法名
 stop 为VM中一个方法名
 start  为VM中一个方法名
 handle  要求为VM中的一个函数，它会重置data.handle为一个元素节点，如果事件源位于data.handle的里面或等于它则继续进行操作
 ghosting: false, //是否影子拖动，动态生成一个元素，拖动此元素，当拖动结束时，让原元素到达此元素的位置上,
 delay: 0, 延迟时间
 axis: "xy" "x", "y" 决定只能垂直拖动，还是水平拖动，还是任意拖动
 containment： 拖动范围，#id值， "window", "document", "parent", "[0, 0, 400, 300]"

item {{$index}}

 avalon.require("avalon.draggable", function() {
 avalon.define("xxx", function(vm) {
 vm.array = avalon.range(0, 10)
 vm.drag = function(e, data) {
 console.log(e.pageX + " : " + e.pageY)
 }
 vm.stop = function(e, data) {
 console.log("done")
 }
 })
 avalon.scan()
 })
 *
 */<|endoftext|>


<commit_before>/**
 * @file AutoCompleteFilter component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';
import classNames from 'classnames';
import isNumber from 'lodash/isNumber';

import TextField from '../TextField';
import Popup from '../Popup';
import List from '../List';
import DynamicRenderList from '../DynamicRenderList';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import DropdownCalculation from '../_vendors/DropdownCalculation';
import Valid from '../_vendors/Valid';

class AutoCompleteFilter extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.triggerEl = null;

        this.state = {
            tempSelectIndex: null,
            value: props.value,
            filter: props.filterInitValue,
            popupVisible: false,
            isAbove: false,
            listData: props.data
        };

    }

    filterData = (filter = this.state.filter, data = this.props.data) => {

        const {minFilterLength} = this.props;

        if (!filter || filter.length < minFilterLength) {
            return data;
        }

        const {valueField, displayField, renderer, filterCallback} = this.props;

        if (filterCallback) {
            return filterCallback(filter, data);
        }

        return data.filter(item => {

            if (!item) {
                return false;
            }

            if (renderer) {
                return renderer(item).toString().toUpperCase().includes(filter.toUpperCase());
            }

            if (typeof item === 'object') {

                const itemDisplay = Util.getTextByDisplayField(item, displayField, valueField);

                if (itemDisplay) {
                    return itemDisplay.toString().toUpperCase().includes(filter.toUpperCase());
                }

            }

            return item.toString().toUpperCase().includes(filter.toUpperCase());

        });

    };

    filterFocusHandler = (...args) => {

        if (this.props.disabled) {
            return;
        }

        const {onFocus} = this.props,
            {filter} = this.state,
            state = {
                filterFocused: true,
                tempSelectIndex: null
            };

        onFocus && onFocus(...args);

        if (filter) {
            state.popupVisible = true;
        }

        this.setState(state);

    };

    filterBlurHandler = (...args) => {
        const {disabled, onBlur} = this.props;
        !disabled && onBlur && onBlur(...args);
    };

    filterKeyDownHandler = e => {

        const {useDynamicRenderList} = this.props,
            {tempSelectIndex, listData} = this.state,
            listEl = useDynamicRenderList ? this.refs.dynamicRenderList : this.refs.list;
        let state = null;

        if (e.keyCode === 38 || e.keyCode === 40) {

            state = {};

            let index = isNumber(tempSelectIndex) && tempSelectIndex > -1 ? tempSelectIndex : -1;

            if (e.keyCode === 38) { // up
                index--;
            } else if (e.keyCode === 40) { // down
                index++;
            }

            state.tempSelectIndex = Valid.range(index, 0, listData.length - 1);

        }

        this.setState(state, () => {

            const {onFilterKeyDown} = this.props;
            onFilterKeyDown && onFilterKeyDown(e);

            listEl && listEl.adjustScroll();

        });

    };

    filterPressEnterHandler = (e, filter) => {

        const {autoClose} = this.props,
            state = {};

        if (autoClose) {
            state.popupVisible = false;
        }

        this.setState(state, () => {

            const {onFilterPressEnter} = this.props;
            onFilterPressEnter && onFilterPressEnter(filter);

            this.update();

        });

    };

    filterChangeHandler = filter => {

        const {data, minFilterLength} = this.props,
            state = {
                filter,
                popupVisible: !!filter && filter.length >= minFilterLength,
                tempSelectIndex: null
            };

        if (!filter) {
            state.listData = data;
            state.value = null;
        } else {
            state.listData = this.filterData(filter);
        }

        this.setState(state, () => {

            const {onFilterChange} = this.props;
            onFilterChange && onFilterChange(filter);

            this.refs.popup && this.refs.popup.resetPosition();

        });

    };

    closePopup = () => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onPopupClosed} = this.props;
            onPopupClosed && onPopupClosed();
        });
    };

    popupRenderHandler = popupEl => {

        const isAbove = DropdownCalculation.isAbove(this.autoCompleteFilterEl, this.triggerEl, findDOMNode(popupEl));

        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    };

    itemClickHandler = value => {

        const {autoClose, valueField, displayField, renderer} = this.props,
            filter = renderer ? renderer(value) : Util.getTextByDisplayField(value, displayField, valueField),
            state = {
                tempSelectIndex: null,
                value,
                filter,
                listData: this.filterData(filter)
            },
            isChanged = this.state.value != value;

        if (autoClose) {
            state.popupVisible = false;
        }

        this.setState(state, () => {
            const {onItemClick, onChange} = this.props;
            onItemClick && onItemClick(value);
            isChanged && onChange && onChange(value);
        });

    };

    update = () => {

        const {displayField, valueField, renderer} = this.props,
            {filter, tempSelectIndex, listData} = this.state;
        let state = null;

        if (filter && listData && listData.length > 0) {

            state = {};

            const index = isNumber(tempSelectIndex) && tempSelectIndex > -1 ? tempSelectIndex : -1;

            state.value = index > -1 ? listData[index] : null;

            if (index > -1) {
                state.filter = renderer ?
                    renderer(state.value)
                    :
                    Util.getTextByDisplayField(state.value, displayField, valueField);
            }

            state.listData = this.filterData(state.filter);

        }

        state && this.setState(state, () => {
            const {onFilterChange, onChange} = this.props;
            onFilterChange && onFilterChange(state.filter);
            onChange && onChange(state.value);
        });

    };

    componentDidMount() {
        this.autoCompleteFilterEl = this.refs.autoCompleteFilter;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {
                className, popupClassName, style, popupStyle, theme, popupTheme, name, placeholder,
                disabled, iconCls, rightIconCls, valueField, displayField, descriptionField, position,
                noMatchedPopupVisible, noMatchedMsg, popupChildren, renderer, resetPositionWait,
                useDynamicRenderList, listHeight, itemHeight, scrollBuffer,
                onFilterClear, onMouseOver, onMouseOut
            } = this.props,
            {isAbove, tempSelectIndex, value, filter, popupVisible, listData} = this.state,

            emptyEl = [{
                itemRenderer() {
                    return (

                            {
                                noMatchedMsg ?
                                    noMatchedMsg
                                    :

                                        No matched value.

                            }

                    );
                },
                disableTouchRipple: true
            }],

            isAboveFinally = position === Position.TOP || position === Position.TOP_LEFT
                || position === Position.TOP_RIGHT || (!position && isAbove),
            isEmpty = !listData || listData.length < 1,

            wrapperClassName = classNames('auto-complete-filter', {
                [className]: className
            }),
            triggerClassName = classNames('auto-complete-filter-trigger',
                isEmpty && !noMatchedPopupVisible ? '' : (popupVisible ? ' activated' : ''),
                isAboveFinally ? ' above' : ' blow'),
            autoCompletePopupClassName = classNames('auto-complete-filter-popup',
                isAboveFinally ? ' above' : ' blow', {
                    [popupClassName]: popupClassName
                }),
            autoCompletePopupStyle = Object.assign({
                width: this.triggerEl && getComputedStyle(this.triggerEl).width
            }, popupStyle);

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <TextField ref="trigger"
                           className={triggerClassName}
                           theme={theme}
                           value={filter}
                           placeholder={placeholder}
                           disabled={disabled}
                           iconCls={iconCls}
                           rightIconCls={rightIconCls}
                           onFocus={this.filterFocusHandler}
                           onBlur={this.filterBlurHandler}
                           onMouseOver={onMouseOver}
                           onMouseOut={onMouseOut}
                           onChange={this.filterChangeHandler}
                           onKeyDown={this.filterKeyDownHandler}
                           onPressEnter={this.filterPressEnterHandler}
                           onClear={onFilterClear}
                           onRightIconClick={this.filterPressEnterHandler}/>

                {
                    isEmpty && !noMatchedPopupVisible ?
                        null
                        :
                        <Popup ref="popup"
                               className={autoCompletePopupClassName}
                               style={autoCompletePopupStyle}
                               theme={popupTheme}
                               visible={popupVisible}
                               triggerEl={this.triggerEl}
                               hasTriangle={false}
                               position={position ? position : (isAbove ? Position.TOP_LEFT : Position.BOTTOM_LEFT)}
                               resetPositionWait={resetPositionWait}
                               onRender={this.popupRenderHandler}
                               onRequestClose={this.closePopup}>

                            {
                                isEmpty ?
                                    <List className="auto-complete-filter-list"
                                          theme={popupTheme}
                                          data={emptyEl}/>
                                    :
                                    (
                                        useDynamicRenderList ?
                                            <DynamicRenderList ref="dynamicRenderList"
                                                               className="auto-complete-filter-list"
                                                               theme={popupTheme}
                                                               data={listData}
                                                               value={listData[tempSelectIndex]}
                                                               valueField={valueField}
                                                               displayField={displayField}
                                                               descriptionField={descriptionField}
                                                               renderer={renderer}
                                                               listHeight={listHeight}
                                                               itemHeight={itemHeight}
                                                               scrollBuffer={scrollBuffer}
                                                               onItemClick={this.itemClickHandler}/>
                                            :
                                            <List ref="list"
                                                  className="auto-complete-filter-list"
                                                  theme={popupTheme}
                                                  data={listData}
                                                  value={listData[tempSelectIndex]}
                                                  valueField={valueField}
                                                  displayField={displayField}
                                                  descriptionField={descriptionField}
                                                  renderer={renderer}
                                                  onItemClick={this.itemClickHandler}/>
                                    )
                            }

                            {popupChildren}

                        </Popup>
                }

        );
    }

}

AutoCompleteFilter.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The name of the auto complete.
     */
    name: PropTypes.string,

    /**
     * The placeholder of the field.
     */
    placeholder: PropTypes.string,

    /**
     * Children passed into the List.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            itemRenderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onClick: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * If true, the auto complete will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the popup list automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    minFilterLength: PropTypes.number,

    /**
     * Callback function fired when filter changed.
     */
    filterCallback: PropTypes.func,

    /**
     * Use this property to display an icon.
     */
    iconCls: PropTypes.string,

    /**
     * Use this property to display an icon.
     */
    rightIconCls: PropTypes.string,

    /**
     * The visiblity of no matched popup.
     */
    noMatchedPopupVisible: PropTypes.bool,

    /**
     * The message of no matched value.
     */
    noMatchedMsg: PropTypes.string,

    popupChildren: PropTypes.any,

    filterInitValue: PropTypes.string,

    useDynamicRenderList: PropTypes.bool,
    resetPositionWait: PropTypes.number,
    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * The function that trigger when filter changes.
     */
    onFilterChange: PropTypes.func,

    /**
     * The function that trigger when press enter.
     */
    onFilterPressEnter: PropTypes.func,

    /**
     * The function that trigger when filter cleared.
     */
    onFilterClear: PropTypes.func,

    /**
     * The function that trigger when value changed.
     */
    onChange: PropTypes.func,

    /**
     * The function that trigger when touch-tap the list items.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when AutoCompleteFilter get focus.
     */
    onFocus: PropTypes.func,

    /**
     * Callback function fired when AutoCompleteFilter lose focus.
     */
    onBlur: PropTypes.func,

    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onPopupClosed: PropTypes.func

};

AutoCompleteFilter.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    data: [],
    disabled: false,
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    autoClose: false,
    minFilterLength: 1,
    iconCls: null,
    rightIconCls: 'fas fa-search',
    noMatchedPopupVisible: true,
    filterInitValue: '',
    useDynamicRenderList: false,
    resetPositionWait: 250

};

export default AutoCompleteFilter;
<commit_msg>update AutoCompleteFilter<commit_after>/**
 * @file AutoCompleteFilter component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';
import classNames from 'classnames';
import isNumber from 'lodash/isNumber';

import TextField from '../TextField';
import Popup from '../Popup';
import List from '../List';
import DynamicRenderList from '../DynamicRenderList';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import DropdownCalculation from '../_vendors/DropdownCalculation';
import Valid from '../_vendors/Valid';

class AutoCompleteFilter extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.triggerEl = null;

        this.state = {
            tempSelectIndex: null,
            value: props.value,
            filter: props.filterInitValue,
            popupVisible: false,
            isAbove: false,
            listData: props.data
        };

    }

    filterData = (filter = this.state.filter, data = this.props.data) => {

        const {minFilterLength} = this.props;

        if (!filter || filter.length < minFilterLength) {
            return data;
        }

        const {valueField, displayField, renderer, filterCallback} = this.props;

        if (filterCallback) {
            return filterCallback(filter, data);
        }

        return data.filter(item => {

            if (!item) {
                return false;
            }

            if (renderer) {
                return renderer(item).toString().toUpperCase().includes(filter.toUpperCase());
            }

            if (typeof item === 'object') {

                const itemDisplay = Util.getTextByDisplayField(item, displayField, valueField);

                if (itemDisplay) {
                    return itemDisplay.toString().toUpperCase().includes(filter.toUpperCase());
                }

            }

            return item.toString().toUpperCase().includes(filter.toUpperCase());

        });

    };

    filterFocusHandler = (...args) => {

        if (this.props.disabled) {
            return;
        }

        const {onFocus} = this.props,
            {filter} = this.state,
            state = {
                filterFocused: true,
                tempSelectIndex: null
            };

        onFocus && onFocus(...args);

        if (filter) {
            state.popupVisible = true;
        }

        this.setState(state);

    };

    filterBlurHandler = (...args) => {
        const {disabled, onBlur} = this.props;
        !disabled && onBlur && onBlur(...args);
    };

    filterKeyDownHandler = e => {

        const {useDynamicRenderList} = this.props,
            {tempSelectIndex, listData} = this.state,
            listEl = useDynamicRenderList ? this.refs.dynamicRenderList : this.refs.list;
        let state = null;

        if (e.keyCode === 38 || e.keyCode === 40) {

            state = {};

            let index = isNumber(tempSelectIndex) && tempSelectIndex > -1 ? tempSelectIndex : -1;

            if (e.keyCode === 38) { // up
                index--;
            } else if (e.keyCode === 40) { // down
                index++;
            }

            state.tempSelectIndex = Valid.range(index, 0, listData.length - 1);

        }

        this.setState(state, () => {

            const {onFilterKeyDown} = this.props;
            onFilterKeyDown && onFilterKeyDown(e);

            listEl && listEl.adjustScroll();

        });

    };

    filterPressEnterHandler = (e, filter) => {

        const {autoClose} = this.props,
            state = {};

        if (autoClose) {
            state.popupVisible = false;
        }

        this.setState(state, () => {

            const {onFilterPressEnter} = this.props;
            onFilterPressEnter && onFilterPressEnter(filter);

            this.update();

        });

    };

    filterChangeHandler = filter => {

        const {data, minFilterLength} = this.props,
            state = {
                filter,
                popupVisible: !!filter && filter.length >= minFilterLength,
                tempSelectIndex: null
            };

        if (!filter) {
            state.listData = data;
            state.value = null;
        } else {
            state.listData = this.filterData(filter);
        }

        this.setState(state, () => {

            const {onFilterChange} = this.props;
            onFilterChange && onFilterChange(filter);

            this.refs.popup && this.refs.popup.resetPosition();

        });

    };

    closePopup = () => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onPopupClosed} = this.props;
            onPopupClosed && onPopupClosed();
        });
    };

    popupRenderHandler = popupEl => {

        const isAbove = DropdownCalculation.isAbove(this.autoCompleteFilterEl, this.triggerEl, findDOMNode(popupEl));

        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    };

    itemClickHandler = value => {

        const {autoClose, valueField, displayField, renderer} = this.props,
            filter = renderer ? renderer(value) : Util.getTextByDisplayField(value, displayField, valueField),
            state = {
                tempSelectIndex: null,
                value,
                filter,
                listData: this.filterData(filter)
            },
            isChanged = this.state.value != value;

        if (autoClose) {
            state.popupVisible = false;
        }

        this.setState(state, () => {
            const {onItemClick, onChange} = this.props;
            onItemClick && onItemClick(value);
            isChanged && onChange && onChange(value);
        });

    };

    update = () => {

        const {displayField, valueField, renderer} = this.props,
            {filter, tempSelectIndex, listData} = this.state;
        let state = null;

        if (filter && listData && listData.length > 0) {

            state = {};

            const index = isNumber(tempSelectIndex) && tempSelectIndex > -1 ? tempSelectIndex : -1;

            state.value = index > -1 ? listData[index] : null;

            if (index > -1) {
                state.filter = renderer ?
                    renderer(state.value)
                    :
                    Util.getTextByDisplayField(state.value, displayField, valueField);
            }

            state.listData = this.filterData(state.filter);

        }

        state && this.setState(state, () => {
            const {onFilterChange, onChange} = this.props;
            onFilterChange && onFilterChange(state.filter);
            onChange && onChange(state.value);
        });

    };

    componentDidMount() {
        this.autoCompleteFilterEl = this.refs.autoCompleteFilter;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {
                className, popupClassName, style, popupStyle, theme, popupTheme, name, placeholder,
                disabled, iconCls, rightIconCls, valueField, displayField, descriptionField, position,
                noMatchedPopupVisible, noMatchedMsg, popupChildren, renderer, resetPopPositionWait,
                useDynamicRenderList, listHeight, itemHeight, scrollBuffer,
                onFilterClear, onMouseOver, onMouseOut
            } = this.props,
            {isAbove, tempSelectIndex, value, filter, popupVisible, listData} = this.state,

            emptyEl = [{
                itemRenderer() {
                    return (

                            {
                                noMatchedMsg ?
                                    noMatchedMsg
                                    :

                                        No matched value.

                            }

                    );
                },
                disableTouchRipple: true
            }],

            isAboveFinally = position === Position.TOP || position === Position.TOP_LEFT
                || position === Position.TOP_RIGHT || (!position && isAbove),
            isEmpty = !listData || listData.length < 1,

            wrapperClassName = classNames('auto-complete-filter', {
                [className]: className
            }),
            triggerClassName = classNames('auto-complete-filter-trigger',
                isEmpty && !noMatchedPopupVisible ? '' : (popupVisible ? ' activated' : ''),
                isAboveFinally ? ' above' : ' blow'),
            autoCompletePopupClassName = classNames('auto-complete-filter-popup',
                isAboveFinally ? ' above' : ' blow', {
                    [popupClassName]: popupClassName
                }),
            autoCompletePopupStyle = Object.assign({
                width: this.triggerEl && getComputedStyle(this.triggerEl).width
            }, popupStyle);

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <TextField ref="trigger"
                           className={triggerClassName}
                           theme={theme}
                           value={filter}
                           placeholder={placeholder}
                           disabled={disabled}
                           iconCls={iconCls}
                           rightIconCls={rightIconCls}
                           onFocus={this.filterFocusHandler}
                           onBlur={this.filterBlurHandler}
                           onMouseOver={onMouseOver}
                           onMouseOut={onMouseOut}
                           onChange={this.filterChangeHandler}
                           onKeyDown={this.filterKeyDownHandler}
                           onPressEnter={this.filterPressEnterHandler}
                           onClear={onFilterClear}
                           onRightIconClick={this.filterPressEnterHandler}/>

                {
                    isEmpty && !noMatchedPopupVisible ?
                        null
                        :
                        <Popup ref="popup"
                               className={autoCompletePopupClassName}
                               style={autoCompletePopupStyle}
                               theme={popupTheme}
                               visible={popupVisible}
                               triggerEl={this.triggerEl}
                               hasTriangle={false}
                               position={position ? position : (isAbove ? Position.TOP_LEFT : Position.BOTTOM_LEFT)}
                               resetPositionWait={resetPopPositionWait}
                               onRender={this.popupRenderHandler}
                               onRequestClose={this.closePopup}>

                            {
                                isEmpty ?
                                    <List className="auto-complete-filter-list"
                                          theme={popupTheme}
                                          data={emptyEl}/>
                                    :
                                    (
                                        useDynamicRenderList ?
                                            <DynamicRenderList ref="dynamicRenderList"
                                                               className="auto-complete-filter-list"
                                                               theme={popupTheme}
                                                               data={listData}
                                                               value={listData[tempSelectIndex]}
                                                               valueField={valueField}
                                                               displayField={displayField}
                                                               descriptionField={descriptionField}
                                                               renderer={renderer}
                                                               listHeight={listHeight}
                                                               itemHeight={itemHeight}
                                                               scrollBuffer={scrollBuffer}
                                                               onItemClick={this.itemClickHandler}/>
                                            :
                                            <List ref="list"
                                                  className="auto-complete-filter-list"
                                                  theme={popupTheme}
                                                  data={listData}
                                                  value={listData[tempSelectIndex]}
                                                  valueField={valueField}
                                                  displayField={displayField}
                                                  descriptionField={descriptionField}
                                                  renderer={renderer}
                                                  onItemClick={this.itemClickHandler}/>
                                    )
                            }

                            {popupChildren}

                        </Popup>
                }

        );
    }

}

AutoCompleteFilter.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The name of the auto complete.
     */
    name: PropTypes.string,

    /**
     * The placeholder of the field.
     */
    placeholder: PropTypes.string,

    /**
     * Children passed into the List.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            itemRenderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onClick: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * If true, the auto complete will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the popup list automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    minFilterLength: PropTypes.number,

    /**
     * Callback function fired when filter changed.
     */
    filterCallback: PropTypes.func,

    /**
     * Use this property to display an icon.
     */
    iconCls: PropTypes.string,

    /**
     * Use this property to display an icon.
     */
    rightIconCls: PropTypes.string,

    /**
     * The visiblity of no matched popup.
     */
    noMatchedPopupVisible: PropTypes.bool,

    /**
     * The message of no matched value.
     */
    noMatchedMsg: PropTypes.string,

    popupChildren: PropTypes.any,

    filterInitValue: PropTypes.string,

    useDynamicRenderList: PropTypes.bool,
    resetPopPositionWait: PropTypes.number,
    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * The function that trigger when filter changes.
     */
    onFilterChange: PropTypes.func,

    /**
     * The function that trigger when press enter.
     */
    onFilterPressEnter: PropTypes.func,

    /**
     * The function that trigger when filter cleared.
     */
    onFilterClear: PropTypes.func,

    /**
     * The function that trigger when value changed.
     */
    onChange: PropTypes.func,

    /**
     * The function that trigger when touch-tap the list items.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when AutoCompleteFilter get focus.
     */
    onFocus: PropTypes.func,

    /**
     * Callback function fired when AutoCompleteFilter lose focus.
     */
    onBlur: PropTypes.func,

    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onPopupClosed: PropTypes.func

};

AutoCompleteFilter.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    data: [],
    disabled: false,
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    autoClose: false,
    minFilterLength: 1,
    iconCls: null,
    rightIconCls: 'fas fa-search',
    noMatchedPopupVisible: true,
    filterInitValue: '',
    useDynamicRenderList: false,
    resetPopPositionWait: 250

};

export default AutoCompleteFilter;
<|endoftext|>


<commit_before>/*global angular*/

/*
 * An HTTP Plugin for PhoneGap.
 */

var exec = require('cordova/exec');

var http = {
    useBasicAuth: function(username, password, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "useBasicAuth", [username, password]);
    },
    setHeader: function(header, value, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "setHeader", [header, value]);
    },
    enableSSLPinning: function(enable, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "enableSSLPinning", [enable]);
    },
    acceptAllCerts: function(allow, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "acceptAllCerts", [allow]);
    },
    post: function(url, params, headers, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "post", [url, params, headers]);
    },
    postJson: function(url, json, headers, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "postJson", [url, json, headers]);
    },
    get: function(url, params, headers, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "get", [url, params, headers]);
    },
    uploadFile: function(url, params, headers, filePath, name, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "uploadFile", [url, params, headers, filePath, name]);
    },
    downloadFile: function(url, params, headers, filePath, success, failure) {
        /*
         *
         * Licensed to the Apache Software Foundation (ASF) under one
         * or more contributor license agreements.  See the NOTICE file
         * distributed with this work for additional information
         * regarding copyright ownership.  The ASF licenses this file
         * to you under the Apache License, Version 2.0 (the
         * "License"); you may not use this file except in compliance
         * with the License.  You may obtain a copy of the License at
         *
         *   http://www.apache.org/licenses/LICENSE-2.0
         *
         * Unless required by applicable law or agreed to in writing,
         * software distributed under the License is distributed on an
         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         * KIND, either express or implied.  See the License for the
         * specific language governing permissions and limitations
         * under the License.
         *
         * Modified by Andrew Stephan for Sync OnSet
         *
        */
        var win = function(result) {
            var entry = new (require('org.apache.cordova.file.FileEntry'))();
            entry.isDirectory = false;
            entry.isFile = true;
            entry.name = result.file.name;
            entry.fullPath = result.file.fullPath;
            success(entry);
        };
        return exec(win, failure, "CordovaHttpPlugin", "downloadFile", [url, params, headers, filePath]);
    }
};

module.exports = http;

if (typeof angular !== "undefined") {
    angular.module('cordovaHTTP', []).factory('cordovaHTTP', function($timeout, $q) {
        function makePromise(fn, args, async) {
            var deferred = $q.defer();

            var success = function(response) {
                if (async) {
                    $timeout(function() {
                        deferred.resolve(response);
                    });
                } else {
                    deferred.resolve(response);
                }
            };

            var fail = function(response) {
                if (async) {
                    $timeout(function() {
                        deferred.reject(response);
                    });
                } else {
                    deferred.reject(response);
                }
            };

            args.push(success);
            args.push(fail);

            fn.apply(http, args);

            return deferred.promise;
        }

        var cordovaHTTP = {
            useBasicAuth: function(username, password) {
                return makePromise(http.useBasicAuth, [username, password]);
            },
            setHeader: function(header, value) {
                return makePromise(http.setHeader, [header, value]);
            },
            enableSSLPinning: function(enable) {
                return makePromise(http.enableSSLPinning, [enable]);
            },
            acceptAllCerts: function(allow) {
                return makePromise(http.acceptAllCerts, [allow]);
            },
            post: function(url, params, headers) {
                return makePromise(http.post, [url, params, headers], true);
            },
            postJson: function(url, json, headers) {
                return makePromise(http.postJson, [url, json, headers], true);
            },
            get: function(url, params, headers) {
                return makePromise(http.get, [url, params, headers], true);
            },
            uploadFile: function(url, params, headers, filePath, name) {
                return makePromise(http.uploadFile, [url, params, headers, filePath, name], true);
            },
            downloadFile: function(url, params, headers, filePath) {
                return makePromise(http.downloadFile, [url, params, headers, filePath], true);
            }
        };
        return cordovaHTTP;
    });
} else {
    window.cordovaHTTP = http;
}
<commit_msg>removed angular capability<commit_after>/*global angular*/

/*
 * An HTTP Plugin for PhoneGap.
 */

var exec = require('cordova/exec');

var http = {
    useBasicAuth: function(username, password, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "useBasicAuth", [username, password]);
    },
    setHeader: function(header, value, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "setHeader", [header, value]);
    },
    enableSSLPinning: function(enable, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "enableSSLPinning", [enable]);
    },
    acceptAllCerts: function(allow, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "acceptAllCerts", [allow]);
    },
    post: function(url, params, headers, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "post", [url, params, headers]);
    },
    postJson: function(url, json, headers, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "postJson", [url, json, headers]);
    },
    get: function(url, params, headers, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "get", [url, params, headers]);
    },
    uploadFile: function(url, params, headers, filePath, name, success, failure) {
        return exec(success, failure, "CordovaHttpPlugin", "uploadFile", [url, params, headers, filePath, name]);
    },
    downloadFile: function(url, params, headers, filePath, success, failure) {
        /*
         *
         * Licensed to the Apache Software Foundation (ASF) under one
         * or more contributor license agreements.  See the NOTICE file
         * distributed with this work for additional information
         * regarding copyright ownership.  The ASF licenses this file
         * to you under the Apache License, Version 2.0 (the
         * "License"); you may not use this file except in compliance
         * with the License.  You may obtain a copy of the License at
         *
         *   http://www.apache.org/licenses/LICENSE-2.0
         *
         * Unless required by applicable law or agreed to in writing,
         * software distributed under the License is distributed on an
         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         * KIND, either express or implied.  See the License for the
         * specific language governing permissions and limitations
         * under the License.
         *
         * Modified by Andrew Stephan for Sync OnSet
         *
        */
        var win = function(result) {
            var entry = new (require('org.apache.cordova.file.FileEntry'))();
            entry.isDirectory = false;
            entry.isFile = true;
            entry.name = result.file.name;
            entry.fullPath = result.file.fullPath;
            success(entry);
        };
        return exec(win, failure, "CordovaHttpPlugin", "downloadFile", [url, params, headers, filePath]);
    }
};

module.exports = http;

if (true) {
    angular.module('cordovaHTTP', []).factory('cordovaHTTP', function($timeout, $q) {
        function makePromise(fn, args, async) {
            var deferred = $q.defer();

            var success = function(response) {
                if (async) {
                    $timeout(function() {
                        deferred.resolve(response);
                    });
                } else {
                    deferred.resolve(response);
                }
            };

            var fail = function(response) {
                if (async) {
                    $timeout(function() {
                        deferred.reject(response);
                    });
                } else {
                    deferred.reject(response);
                }
            };

            args.push(success);
            args.push(fail);

            fn.apply(http, args);

            return deferred.promise;
        }

        var cordovaHTTP = {
            useBasicAuth: function(username, password) {
                return makePromise(http.useBasicAuth, [username, password]);
            },
            setHeader: function(header, value) {
                return makePromise(http.setHeader, [header, value]);
            },
            enableSSLPinning: function(enable) {
                return makePromise(http.enableSSLPinning, [enable]);
            },
            acceptAllCerts: function(allow) {
                return makePromise(http.acceptAllCerts, [allow]);
            },
            post: function(url, params, headers) {
                return makePromise(http.post, [url, params, headers], true);
            },
            postJson: function(url, json, headers) {
                return makePromise(http.postJson, [url, json, headers], true);
            },
            get: function(url, params, headers) {
                return makePromise(http.get, [url, params, headers], true);
            },
            uploadFile: function(url, params, headers, filePath, name) {
                return makePromise(http.uploadFile, [url, params, headers, filePath, name], true);
            },
            downloadFile: function(url, params, headers, filePath) {
                return makePromise(http.downloadFile, [url, params, headers, filePath], true);
            }
        };
        return cordovaHTTP;
    });
} else {
    window.cordovaHTTP = http;
}
<|endoftext|>