152 lines
4.1 KiB
JavaScript
152 lines
4.1 KiB
JavaScript
/**
|
|
|
|
* ngModelOptions v1.0.1: ngModelOptions for AngularJS 1.2
|
|
|
|
*
|
|
|
|
* @author Fergal Doyle
|
|
|
|
* @url https://github.com/fergaldoyle/modelOptions
|
|
|
|
* @license MIT
|
|
|
|
*/
|
|
|
|
|
|
|
|
angular.module("modelOptions", []).directive("ngModelOptions", function () {
|
|
|
|
return {
|
|
|
|
priority: 1,
|
|
|
|
restrict: "A",
|
|
|
|
//require: "ngModel",
|
|
|
|
require: ['ngModel'/*, '^?select'*/],
|
|
|
|
link: function (scope, elm, attr, ctrls) {
|
|
|
|
|
|
|
|
function apply() {
|
|
|
|
|
|
|
|
var value;
|
|
|
|
|
|
|
|
switch (tagType) {
|
|
|
|
case "inputradio":
|
|
|
|
if (attr.ngValue) {
|
|
|
|
value = scope.$eval(attr.ngValue);
|
|
|
|
} else {
|
|
|
|
value = elm.val();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "inputcheckbox":
|
|
|
|
value = elm.prop("checked");
|
|
|
|
break;
|
|
|
|
case "select":
|
|
|
|
value = getSelectOption();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
value = elm.val();
|
|
|
|
|
|
|
|
if (!attr.ngTrim || attr.ngTrim.toLowerCase() !== "false") {
|
|
|
|
value = value.replace(/^\s+|\s+$/g, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
scope.$apply(function () {
|
|
|
|
ctrls[0].$setViewValue(value);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getSelectOption() {
|
|
|
|
|
|
|
|
if (!attr.ngOptions) {
|
|
|
|
throw "Must have ng-options";
|
|
|
|
}
|
|
|
|
|
|
|
|
var match = attr.ngOptions.match(NG_OPTIONS_REGEXP),
|
|
|
|
track = match[8],
|
|
|
|
valuesName = match[7],
|
|
|
|
values = scope.$eval(valuesName),
|
|
|
|
index,
|
|
|
|
val = elm.val();
|
|
|
|
|
|
|
|
// if track by is specified
|
|
|
|
// use the track by value as
|
|
|
|
// a key to find the index
|
|
|
|
if (track) {
|
|
|
|
angular.forEach(values, function (item, i) {
|
|
|
|
if (item[track.replace(/^.*?\./, "")] == val) {
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
index = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
// value is a property of an object
|
|
|
|
if (/.*\..*/.test(match[1])) {
|
|
|
|
return scope.$eval(match[1].replace(/^.*?\./, valuesName + "[" + index + "]."));
|
|
|
|
} else { // value is an object
|
|
|
|
return values[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var timer,
|
|
|
|
NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
|
|
|
|
tagType = elm[0].nodeName.toLowerCase() + (attr.type || ""),
|
|
|
|
defaultEvents = [],
|
|
|
|
defaults = {
|
|
|
|
debounce: 0,
|
|
|
|
updateOn: "default"
|
|
|
|
},
|
|
|
|
options = angular.extend(defaults, scope.$eval(attr.ngModelOptions)),
|
|
|
|
multiDebounce = typeof options.debounce === "object",
|
|
|
|
updateOnSplit = options.updateOn.split(" ");
|
|
|
|
|
|
|
|
if (tagType === "inputtext" || tagType === "textarea") {
|
|
|
|
defaultEvents = ["keydown", "input", "change"];
|
|
|
|
} else if (tagType === "inputradio" || tagType === "inputcheckbox") {
|
|
|
|
defaultEvents = ["click"];
|
|
|
|
} else if (tagType === "select") {
|
|
|
|
defaultEvents = ["change"];
|
|
|
|
} else {
|
|
|
|
defaultEvents = ["keydown", "input", "change"];
|
|
|
|
}
|
|
|
|
|
|
|
|
// unbind default events to prevent automatic model updates
|
|
|
|
angular.forEach(defaultEvents, function (event) {
|
|
|
|
// ie8 does not support some events
|
|
|
|
// use try catch to mask this
|
|
|
|
try { elm.off(event); } catch (e) { }
|
|
|
|
});
|
|
|
|
|
|
|
|
// default events
|
|
|
|
if (options.updateOn.match(/default/i)) {
|
|
|
|
elm.on(defaultEvents.join(" "), function (e) {
|
|
|
|
var delay = options.debounce["default"] || options.debounce || 0;
|
|
|
|
clearTimeout(timer);
|
|
|
|
timer = setTimeout(function () {
|
|
|
|
apply();
|
|
|
|
}, delay);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// the other events if specified
|
|
|
|
angular.forEach(updateOnSplit, function (event) {
|
|
|
|
if (event === "default") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// debounce option can be number or object
|
|
|
|
var deb;
|
|
|
|
if (multiDebounce) {
|
|
|
|
deb = options.debounce[event];
|
|
|
|
} else {
|
|
|
|
deb = options.debounce;
|
|
|
|
}
|
|
|
|
|
|
|
|
var delay = deb;
|
|
|
|
if (typeof delay === "undefined") {
|
|
|
|
delay = options.debounce["default"] || 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
elm.on(event, function (e) {
|
|
|
|
clearTimeout(timer);
|
|
|
|
timer = setTimeout(function () {
|
|
|
|
apply();
|
|
|
|
}, delay);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}); |