You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
8.8 KiB
268 lines
8.8 KiB
4 years ago
|
/**
|
||
|
* Input(TODO resize)
|
||
|
* @param {type} $
|
||
|
* @param {type} window
|
||
|
* @param {type} document
|
||
|
* @returns {undefined}
|
||
|
*/
|
||
|
(function($, window, document) {
|
||
|
var CLASS_ICON = $.className('icon');
|
||
|
var CLASS_ICON_CLEAR = $.className('icon-clear');
|
||
|
var CLASS_ICON_SPEECH = $.className('icon-speech');
|
||
|
var CLASS_ICON_SEARCH = $.className('icon-search');
|
||
|
var CLASS_ICON_PASSWORD = $.className('icon-eye');
|
||
|
var CLASS_INPUT_ROW = $.className('input-row');
|
||
|
var CLASS_PLACEHOLDER = $.className('placeholder');
|
||
|
var CLASS_TOOLTIP = $.className('tooltip');
|
||
|
var CLASS_HIDDEN = $.className('hidden');
|
||
|
var CLASS_FOCUSIN = $.className('focusin');
|
||
|
var SELECTOR_ICON_CLOSE = '.' + CLASS_ICON_CLEAR;
|
||
|
var SELECTOR_ICON_SPEECH = '.' + CLASS_ICON_SPEECH;
|
||
|
var SELECTOR_ICON_PASSWORD = '.' + CLASS_ICON_PASSWORD;
|
||
|
var SELECTOR_PLACEHOLDER = '.' + CLASS_PLACEHOLDER;
|
||
|
var SELECTOR_TOOLTIP = '.' + CLASS_TOOLTIP;
|
||
|
|
||
|
var findRow = function(target) {
|
||
|
for (; target && target !== document; target = target.parentNode) {
|
||
|
if (target.classList && target.classList.contains(CLASS_INPUT_ROW)) {
|
||
|
return target;
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
};
|
||
|
var Input = function(element, options) {
|
||
|
this.element = element;
|
||
|
this.options = options || {
|
||
|
actions: 'clear'
|
||
|
};
|
||
|
if (~this.options.actions.indexOf('slider')) { //slider
|
||
|
this.sliderActionClass = CLASS_TOOLTIP + ' ' + CLASS_HIDDEN;
|
||
|
this.sliderActionSelector = SELECTOR_TOOLTIP;
|
||
|
} else { //clear,speech,search
|
||
|
if (~this.options.actions.indexOf('clear')) {
|
||
|
this.clearActionClass = CLASS_ICON + ' ' + CLASS_ICON_CLEAR + ' ' + CLASS_HIDDEN;
|
||
|
this.clearActionSelector = SELECTOR_ICON_CLOSE;
|
||
|
}
|
||
|
if (~this.options.actions.indexOf('speech')) { //only for 5+
|
||
|
this.speechActionClass = CLASS_ICON + ' ' + CLASS_ICON_SPEECH;
|
||
|
this.speechActionSelector = SELECTOR_ICON_SPEECH;
|
||
|
}
|
||
|
if (~this.options.actions.indexOf('search')) {
|
||
|
this.searchActionClass = CLASS_PLACEHOLDER;
|
||
|
this.searchActionSelector = SELECTOR_PLACEHOLDER;
|
||
|
}
|
||
|
if (~this.options.actions.indexOf('password')) {
|
||
|
this.passwordActionClass = CLASS_ICON + ' ' + CLASS_ICON_PASSWORD;
|
||
|
this.passwordActionSelector = SELECTOR_ICON_PASSWORD;
|
||
|
}
|
||
|
}
|
||
|
this.init();
|
||
|
};
|
||
|
Input.prototype.init = function() {
|
||
|
this.initAction();
|
||
|
this.initElementEvent();
|
||
|
};
|
||
|
Input.prototype.initAction = function() {
|
||
|
var self = this;
|
||
|
|
||
|
var row = self.element.parentNode;
|
||
|
if (row) {
|
||
|
if (self.sliderActionClass) {
|
||
|
self.sliderAction = self.createAction(row, self.sliderActionClass, self.sliderActionSelector);
|
||
|
} else {
|
||
|
if (self.searchActionClass) {
|
||
|
self.searchAction = self.createAction(row, self.searchActionClass, self.searchActionSelector);
|
||
|
self.searchAction.addEventListener('tap', function(e) {
|
||
|
$.focus(self.element);
|
||
|
e.stopPropagation();
|
||
|
});
|
||
|
}
|
||
|
if (self.speechActionClass) {
|
||
|
self.speechAction = self.createAction(row, self.speechActionClass, self.speechActionSelector);
|
||
|
self.speechAction.addEventListener('click', $.stopPropagation);
|
||
|
self.speechAction.addEventListener('tap', function(event) {
|
||
|
self.speechActionClick(event);
|
||
|
});
|
||
|
}
|
||
|
if (self.clearActionClass) {
|
||
|
self.clearAction = self.createAction(row, self.clearActionClass, self.clearActionSelector);
|
||
|
self.clearAction.addEventListener('tap', function(event) {
|
||
|
self.clearActionClick(event);
|
||
|
});
|
||
|
}
|
||
|
if (self.passwordActionClass) {
|
||
|
self.passwordAction = self.createAction(row, self.passwordActionClass, self.passwordActionSelector);
|
||
|
self.passwordAction.addEventListener('tap', function(event) {
|
||
|
self.passwordActionClick(event);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
Input.prototype.createAction = function(row, actionClass, actionSelector) {
|
||
|
var action = row.querySelector(actionSelector);
|
||
|
if (!action) {
|
||
|
var action = document.createElement('span');
|
||
|
action.className = actionClass;
|
||
|
if (actionClass === this.searchActionClass) {
|
||
|
action.innerHTML = '<span class="' + CLASS_ICON + ' ' + CLASS_ICON_SEARCH + '"></span><span>' + this.element.getAttribute('placeholder') + '</span>';
|
||
|
this.element.setAttribute('placeholder', '');
|
||
|
if (this.element.value.trim()) {
|
||
|
row.classList.add($.className('active'));
|
||
|
}
|
||
|
}
|
||
|
row.insertBefore(action, this.element.nextSibling);
|
||
|
}
|
||
|
return action;
|
||
|
};
|
||
|
Input.prototype.initElementEvent = function() {
|
||
|
var element = this.element;
|
||
|
|
||
|
if (this.sliderActionClass) {
|
||
|
var tooltip = this.sliderAction;
|
||
|
var timer = null;
|
||
|
var showTip = function() { //每次重新计算是因为控件可能被隐藏,初始化时计算是不正确的
|
||
|
tooltip.classList.remove(CLASS_HIDDEN);
|
||
|
var offsetLeft = element.offsetLeft;
|
||
|
var width = element.offsetWidth - 28;
|
||
|
var tooltipWidth = tooltip.offsetWidth;
|
||
|
var distince = Math.abs(element.max - element.min);
|
||
|
var scaleWidth = (width / distince) * Math.abs(element.value - element.min);
|
||
|
tooltip.style.left = (14 + offsetLeft + scaleWidth - tooltipWidth / 2) + 'px';
|
||
|
tooltip.innerText = element.value;
|
||
|
if (timer) {
|
||
|
clearTimeout(timer);
|
||
|
}
|
||
|
timer = setTimeout(function() {
|
||
|
tooltip.classList.add(CLASS_HIDDEN);
|
||
|
}, 1000);
|
||
|
};
|
||
|
element.addEventListener('input', showTip);
|
||
|
element.addEventListener('tap', showTip);
|
||
|
element.addEventListener($.EVENT_MOVE, function(e) {
|
||
|
e.stopPropagation();
|
||
|
});
|
||
|
} else {
|
||
|
if (this.clearActionClass) {
|
||
|
var action = this.clearAction;
|
||
|
if (!action) {
|
||
|
return;
|
||
|
}
|
||
|
$.each(['keyup', 'change', 'input', 'focus', 'cut', 'paste'], function(index, type) {
|
||
|
(function(type) {
|
||
|
element.addEventListener(type, function() {
|
||
|
action.classList[element.value.trim() ? 'remove' : 'add'](CLASS_HIDDEN);
|
||
|
});
|
||
|
})(type);
|
||
|
});
|
||
|
element.addEventListener('blur', function() {
|
||
|
action.classList.add(CLASS_HIDDEN);
|
||
|
});
|
||
|
}
|
||
|
if (this.searchActionClass) {
|
||
|
element.addEventListener('focus', function() {
|
||
|
element.parentNode.classList.add($.className('active'));
|
||
|
});
|
||
|
element.addEventListener('blur', function() {
|
||
|
if (!element.value.trim()) {
|
||
|
element.parentNode.classList.remove($.className('active'));
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
Input.prototype.setPlaceholder = function(text) {
|
||
|
if (this.searchActionClass) {
|
||
|
var placeholder = this.element.parentNode.querySelector(SELECTOR_PLACEHOLDER);
|
||
|
placeholder && (placeholder.getElementsByTagName('span')[1].innerText = text);
|
||
|
} else {
|
||
|
this.element.setAttribute('placeholder', text);
|
||
|
}
|
||
|
};
|
||
|
Input.prototype.passwordActionClick = function(event) {
|
||
|
if (this.element.type === 'text') {
|
||
|
this.element.type = 'password';
|
||
|
} else {
|
||
|
this.element.type = 'text';
|
||
|
}
|
||
|
this.passwordAction.classList.toggle($.className('active'));
|
||
|
event.preventDefault();
|
||
|
};
|
||
|
Input.prototype.clearActionClick = function(event) {
|
||
|
var self = this;
|
||
|
self.element.value = '';
|
||
|
$.focus(self.element);
|
||
|
self.clearAction.classList.add(CLASS_HIDDEN);
|
||
|
event.preventDefault();
|
||
|
};
|
||
|
Input.prototype.speechActionClick = function(event) {
|
||
|
if (window.plus) {
|
||
|
var self = this;
|
||
|
var oldValue = self.element.value;
|
||
|
self.element.value = '';
|
||
|
document.body.classList.add(CLASS_FOCUSIN);
|
||
|
plus.speech.startRecognize({
|
||
|
engine: 'iFly'
|
||
|
}, function(s) {
|
||
|
self.element.value += s;
|
||
|
$.focus(self.element);
|
||
|
plus.speech.stopRecognize();
|
||
|
$.trigger(self.element, 'recognized', {
|
||
|
value: self.element.value
|
||
|
});
|
||
|
if (oldValue !== self.element.value) {
|
||
|
$.trigger(self.element, 'change');
|
||
|
$.trigger(self.element, 'input');
|
||
|
}
|
||
|
// document.body.classList.remove(CLASS_FOCUSIN);
|
||
|
}, function(e) {
|
||
|
document.body.classList.remove(CLASS_FOCUSIN);
|
||
|
});
|
||
|
} else {
|
||
|
alert('only for 5+');
|
||
|
}
|
||
|
event.preventDefault();
|
||
|
};
|
||
|
$.fn.input = function(options) {
|
||
|
var inputApis = [];
|
||
|
this.each(function() {
|
||
|
var inputApi = null;
|
||
|
var actions = [];
|
||
|
var row = findRow(this.parentNode);
|
||
|
if (this.type === 'range' && row.classList.contains($.className('input-range'))) {
|
||
|
actions.push('slider');
|
||
|
} else {
|
||
|
var classList = this.classList;
|
||
|
if (classList.contains($.className('input-clear'))) {
|
||
|
actions.push('clear');
|
||
|
}
|
||
|
if (!($.os.android && $.os.stream) && classList.contains($.className('input-speech'))) {
|
||
|
actions.push('speech');
|
||
|
}
|
||
|
if (classList.contains($.className('input-password'))) {
|
||
|
actions.push('password');
|
||
|
}
|
||
|
if (this.type === 'search' && row.classList.contains($.className('search'))) {
|
||
|
actions.push('search');
|
||
|
}
|
||
|
}
|
||
|
var id = this.getAttribute('data-input-' + actions[0]);
|
||
|
if (!id) {
|
||
|
id = ++$.uuid;
|
||
|
inputApi = $.data[id] = new Input(this, {
|
||
|
actions: actions.join(',')
|
||
|
});
|
||
|
for (var i = 0, len = actions.length; i < len; i++) {
|
||
|
this.setAttribute('data-input-' + actions[i], id);
|
||
|
}
|
||
|
} else {
|
||
|
inputApi = $.data[id];
|
||
|
}
|
||
|
inputApis.push(inputApi);
|
||
|
});
|
||
|
return inputApis.length === 1 ? inputApis[0] : inputApis;
|
||
|
};
|
||
|
$.ready(function() {
|
||
|
$($.classSelector('.input-row input')).input();
|
||
|
});
|
||
|
})(mui, window, document);
|