Skip to content

Commit 219d0d2

Browse files
Silic0nS0ldieralexweissman
authored andcommitted
ufForm can handle DOM changes.
1 parent be6741f commit 219d0d2

3 files changed

Lines changed: 133 additions & 18 deletions

File tree

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
A simple jQuery function that can add listeners on attribute change.
3+
http://meetselva.github.io/attrchange/
4+
5+
About License:
6+
Copyright (C) 2013-2014 Selvakumar Arumugam
7+
You may use attrchange plugin under the terms of the MIT Licese.
8+
https://github.com/meetselva/attrchange/blob/master/MIT-License.txt
9+
*/
10+
(function($) {
11+
function isDOMAttrModifiedSupported() {
12+
var p = document.createElement('p');
13+
var flag = false;
14+
15+
if (p.addEventListener) {
16+
p.addEventListener('DOMAttrModified', function() {
17+
flag = true
18+
}, false);
19+
} else if (p.attachEvent) {
20+
p.attachEvent('onDOMAttrModified', function() {
21+
flag = true
22+
});
23+
} else { return false; }
24+
p.setAttribute('id', 'target');
25+
return flag;
26+
}
27+
28+
function checkAttributes(chkAttr, e) {
29+
if (chkAttr) {
30+
var attributes = this.data('attr-old-value');
31+
32+
if (e.attributeName.indexOf('style') >= 0) {
33+
if (!attributes['style'])
34+
attributes['style'] = {}; //initialize
35+
var keys = e.attributeName.split('.');
36+
e.attributeName = keys[0];
37+
e.oldValue = attributes['style'][keys[1]]; //old value
38+
e.newValue = keys[1] + ':'
39+
+ this.prop("style")[$.camelCase(keys[1])]; //new value
40+
attributes['style'][keys[1]] = e.newValue;
41+
} else {
42+
e.oldValue = attributes[e.attributeName];
43+
e.newValue = this.attr(e.attributeName);
44+
attributes[e.attributeName] = e.newValue;
45+
}
46+
47+
this.data('attr-old-value', attributes); //update the old value object
48+
}
49+
}
50+
51+
//initialize Mutation Observer
52+
var MutationObserver = window.MutationObserver
53+
|| window.WebKitMutationObserver;
54+
55+
$.fn.attrchange = function(a, b) {
56+
if (typeof a == 'object') {//core
57+
var cfg = {
58+
trackValues : false,
59+
callback : $.noop
60+
};
61+
//backward compatibility
62+
if (typeof a === "function") { cfg.callback = a; } else { $.extend(cfg, a); }
63+
64+
if (cfg.trackValues) { //get attributes old value
65+
this.each(function(i, el) {
66+
var attributes = {};
67+
for ( var attr, i = 0, attrs = el.attributes, l = attrs.length; i < l; i++) {
68+
attr = attrs.item(i);
69+
attributes[attr.nodeName] = attr.value;
70+
}
71+
$(this).data('attr-old-value', attributes);
72+
});
73+
}
74+
75+
if (MutationObserver) { //Modern Browsers supporting MutationObserver
76+
var mOptions = {
77+
subtree : false,
78+
attributes : true,
79+
attributeOldValue : cfg.trackValues
80+
};
81+
var observer = new MutationObserver(function(mutations) {
82+
mutations.forEach(function(e) {
83+
var _this = e.target;
84+
//get new value if trackValues is true
85+
if (cfg.trackValues) {
86+
e.newValue = $(_this).attr(e.attributeName);
87+
}
88+
if ($(_this).data('attrchange-status') === 'connected') { //execute if connected
89+
cfg.callback.call(_this, e);
90+
}
91+
});
92+
});
93+
94+
return this.data('attrchange-method', 'Mutation Observer').data('attrchange-status', 'connected')
95+
.data('attrchange-obs', observer).each(function() {
96+
observer.observe(this, mOptions);
97+
});
98+
} else if (isDOMAttrModifiedSupported()) { //Opera
99+
//Good old Mutation Events
100+
return this.data('attrchange-method', 'DOMAttrModified').data('attrchange-status', 'connected').on('DOMAttrModified', function(event) {
101+
if (event.originalEvent) { event = event.originalEvent; }//jQuery normalization is not required
102+
event.attributeName = event.attrName; //property names to be consistent with MutationObserver
103+
event.oldValue = event.prevValue; //property names to be consistent with MutationObserver
104+
if ($(this).data('attrchange-status') === 'connected') { //disconnected logically
105+
cfg.callback.call(this, event);
106+
}
107+
});
108+
} else if ('onpropertychange' in document.body) { //works only in IE
109+
return this.data('attrchange-method', 'propertychange').data('attrchange-status', 'connected').on('propertychange', function(e) {
110+
e.attributeName = window.event.propertyName;
111+
//to set the attr old value
112+
checkAttributes.call($(this), cfg.trackValues, e);
113+
if ($(this).data('attrchange-status') === 'connected') { //disconnected logically
114+
cfg.callback.call(this, e);
115+
}
116+
});
117+
}
118+
return this;
119+
} else if (typeof a == 'string' && $.fn.attrchange.hasOwnProperty('extensions') &&
120+
$.fn.attrchange['extensions'].hasOwnProperty(a)) { //extensions/options
121+
return $.fn.attrchange['extensions'][a].call(this, b);
122+
}
123+
}
124+
})(jQuery);

app/sprinkles/core/assets/local/core/js/uf-form.js

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@
176176
}
177177
});
178178

179+
// Detect changes to element attributes
180+
this.$element.attrchange({
181+
callback: $.proxy(function (event) {
182+
this.element = event.target;
183+
}, this)
184+
});
185+
179186
return this;
180187
}
181188

@@ -261,21 +268,4 @@
261268
$.error( 'Method ' + methodOrOptions + ' does not exist.' );
262269
}
263270
};
264-
})(jQuery, window, document);
265-
266-
267-
268-
269-
270-
271-
272-
273-
274-
275-
276-
277-
278-
279-
280-
281-
271+
})(jQuery, window, document);

app/sprinkles/core/bundle.config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"vendor/fastclick/lib/fastclick.js",
1212
"vendor/select2/dist/js/select2.full.js",
1313
"vendor/clipboard/dist/clipboard.js",
14+
"local/core/js/attrchange.js",
1415
"local/core/js/AdminLTE.js",
1516
"local/core/js/AdminLTE-custom.js",
1617
"local/core/js/fortress-jqueryvalidation-methods.js",

0 commit comments

Comments
 (0)