PageSourceSearch

https://www.homesofmerit.com/wp-content/plugins//mfh/js/jquery.onmutate.js?ver=7.0.2

js homesofmerit.com collected 2026-09-29 17:06:04 UTC 14,677 bytes, 412 lines download raw bytes

1/*!
2 * jQuery onMutate plugin v1.4
3 * http://jquery.com/
4 *
5 * Copyright 2016 CROmetrics
6 * Released under the MIT license
7 * https://github.com/eclecto/jQuery-onCreate/blob/master/LICENSE
8 *
9 * Date: 2016-08-23T13:12Z
10 */
11
12/* global define, module, setTimeout */
13
14(function (factory) {
15    'use strict';
16    if (typeof define === 'function' && define.amd) {
17        define(['jquery'], factory);
18    } else if (typeof exports !== 'undefined') {
19        module.exports = factory;
20    } else {
21        factory(jQuery);
22    }
23
24}(function ($, MutationObserver) {
25    if (!$) $ = ($.fn.jquery ? $ : jQuery);
26    if (!MutationObserver) MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver || false;
27    var cbid = 0;
28
29    // Uncomment this to easily test the setInterval fallback.
30    // MutationObserver = false;
31
32    // Constants for mutation types.
33    var CREATE = 'create',
34        MODIFY = 'modify',
35        TEXT = 'text';
36
37    // Observer class.
38    function Observer(mutcallback) {
39        var realObserver;
40
41        // MutationObserver.observe() polyfill
42        this.observe = function (element, init) {
43            if (MutationObserver) {
44                realObserver = realObserver || new MutationObserver(mutcallback);
45                realObserver.observe(element, init);
46            } else {
47                realObserver = setInterval(mutcallback, 50);
48            }
49        };
50
51        // MutationObserver.disconnect() polyfill
52        this.disconnect = function () {
53            if (realObserver) {
54                if (MutationObserver) {
55                    realObserver.disconnect();
56                } else {
57                    clearInterval(realObserver);
58                }
59            }
60        };
61    }
62
63    // Callback class to wrap a callback and its properties
64    function Callback(callback, conditions, multi) {
65        this.callback = callback;
66        this.conditions = conditions;
67        this.multi = multi || false;
68        this.cbid = cbid++;
69        this.processed = $([]);
70    }
71
72    // Create a map of an element's attributes so we can poll for changes (non-MutationObserver browsers)
73    function attributeMap(element) {
74        var map = {};
75
76        if (element.attributes) {
77            $.each(element.attributes, function (index, attr) {
78                map[attr.name] = attr.value;
79            });
80        }
81
82        return map;
83    }
84
85    // Returns a set of MutationRecord-like objects by comparing two attribute maps.
86    function mapCompare(map1, map2) {
87        var mutations = [];
88        $.each(map1, function (key, value) {
89            if (typeof (map2[key]) === 'undefined' || value !== map2[key]) {
90                mutations.push({
91                    attributeName: key
92                });
93            }
94        });
95        $.each(map2, function (key) {
96            if (typeof (map1[key]) === 'undefined') {
97                mutations.push({
98                    attributeName: key
99                });
100            }
101        });
102        return mutations;
103    }
104
105    // Check attributes
106    function checkAttrs(mutation, $el, callback) {
107        var attrname = mutation.attributeName,
108            attrval = $el.attr(attrname),
109            conditions = callback.conditions || false,
110            attrs = conditions ? conditions[0] : false,
111            match = conditions && conditions[1] ? conditions[1] : false;
112        // If no attrs are set or the mutation affects one of the targeted attributes
113        if (!attrs || attrs.indexOf(attrname) > -1) {
114            if (match) {
115                return (attrval.search(match) >= 0);
116            } else {
117                return true;
118            }
119        }
120        return false;
121    }
122
123
124    // Possible methods to invoke with $().on[Create|Modify|Text]()
125    var methods = {
126        // Attach observers.
127        attach: function (options) {
128            var type = options.type,
129                callback = options.callback,
130                multi = options.multi || false,
131                conditions = options.conditions;
132
133            // Get/initiate the element's onMutate data.
134            if(!this.data('onMutate')) this.data('onMutate', {
135                create: {
136                    callbacks: [],
137                    ignore: false
138                },
139                modify: {
140                    callbacks: [],
141                    ignore: false
142                },
143                text: {
144                    callbacks: [],
145                    ignore: false
146                }
147            });
148            var om = this.data('onMutate')[type],
149                callbacks = om.callbacks,
150                // Add the callback to the array of callbacks for the current type.
151                newcb = new Callback(callback, conditions, multi);
152            callbacks.unshift(newcb);
153
154            // Store the element's current text or attributes if needed.
155            if (!MutationObserver && type === MODIFY) {
156                om.attributeMap = attributeMap(this[0]);
157            }
158            if (type === TEXT) om.text = this.text();
159
160            var $this = this,
161                i, changematch;
162
163            // Define our callback for when a mutation is detected.
164            var mutcallback = om.mutcallback = om.mutcallback || function (mutations) {
165                callbacks = om.callbacks; // Refresh the callback list.
166                // Ignore any DOM changes that this callback makes to prevent infinite loops.
167                if (!om.ignore) {
168                    om.ignore = true;
169                } else {
170                    return;
171                }
172
173                var newmap, newtext;
174                if (type === MODIFY) newmap = attributeMap($this[0]);
175                if (type === TEXT) newtext = $this.text();
176
177                for (i = callbacks.length - 1; i >= 0; i--) {
178                    var selected = (type === CREATE ? $(callbacks[i].conditions, $this) : $this);
179                    var proc = callbacks[i].processed;
180                    var elements = selected.not(proc);
181
182                    // Validate changed attributes for modify observers.
183                    if (type === MODIFY) {
184                        changematch = false;
185                        if (!MutationObserver) {
186                            mutations = mapCompare(newmap, om.attributeMap);
187                        }
188                        for (var j = 0; j < mutations.length; j++) {
189                            changematch = changematch || checkAttrs(mutations[j], $this, callbacks[i]);
190                        }
191                    }
192
193                    // Compare the text contents of the element to its original text.
194                    if (type === TEXT) {
195                        changematch = false;
196                        var cond = callbacks[i].conditions;
197                        if (newtext !== om.text) {
198                            if (cond) {
199                                changematch = newtext.search(cond) > -1;
200                            } else {
201                                changematch = true;
202                            }
203                        }
204                    }
205
206                    if (elements.length > 0 && (type === CREATE || changematch)) {
207                        if (type === CREATE) proc = proc.add(elements);
208                        callbacks[i].processed = proc;
209                        callbacks[i].callback.call($this, elements);
210                        // Remove callback from the list if it only runs once.
211                        if (!callbacks[i].multi) {
212                            callbacks.splice(i, 1);
213                        }
214                    }
215                    // Update the current values, accounting for any changes the callback(s) might have made.
216                    if (type === MODIFY) om.attributeMap = attributeMap($this[0]);
217                    if (type === TEXT) om.text = $this.text();
218                }
219
220                // We've safely iterated through the callbacks, so don't ignore this master Callback anymore.
221                // Additional mutation events apparently fire after this entire function, so we set ignore to false with an extremely small delay.
222                if (om.ignore) setTimeout(function () {
223                    om.ignore = false;
224                }, 1);
225                if (callbacks.length === 0) {
226                    if (observer) {
227                        observer.disconnect();
228                    } else {
229                        return true;
230                    }
231                }
232            };
233            // Sanity Check: If this is a create listener, run the callback on initialization to see if there is already a valid element.
234            if (type === CREATE && mutcallback()) {
235                return this;
236            }
237
238            var observer = om.observer = om.observer || new Observer(mutcallback),
239                init;
240            switch (type) {
241                case CREATE:
242                    init = {
243                        childList: true,
244                        subtree: true
245                    };
246                    break;
247                case MODIFY:
248                    init = {
249                        attributes: true
250                    };
251                    if (conditions) {
252                        init.attributeFilter = conditions[0].split(' ');
253                    }
254                    break;
255                case TEXT:
256                    init = {
257                        childList: true,
258                        characterData: true,
259                        subtree: true
260                    };
261                    break;
262            }
263            observer.observe($this[0], init);
264            return this;
265        },
266
267        // Detach observers.
268        detach: function (options) {
269            if (!this.data('onMutate')) return this;
270
271            var type = options.type,
272                om = this.data('onMutate')[type],
273                callbacks = om.callbacks,
274                callback = options.callback;
275            if (callback) {
276                for (var i = callbacks.length - 1; i >= 0; i--) {
277                    if (callbacks[i].callback.prototype.cbid === callback.prototype.cbid) {
278                        callbacks.splice(i, i + 1);
279                    }
280                }
281            } else {
282                om.callbacks = [];
283            }
284            if (!callbacks.length) {
285                om.observer.disconnect();
286            }
287            return this;
288        }
289    };
290
291    $.fn.extend({
292        // $(parent).onCreate(selector, callback[, multi]);
293        onCreate: function () {
294
295            var args = Array.prototype.slice.call(arguments);
296
297            // Invalid argument
298            if (typeof (args[0]) !== 'string') {
299                return this;
300            }
301
302            if (args[0] === 'detach') {
303                return methods.detach.call(this, {
304                    type: CREATE,
305                    callback: args[1]
306                });
307            } else
308            // Default init functionality.
309            if (typeof (args[0]) === 'string' && typeof (args[1]) === 'function') {
310                return methods.attach.call(this, {
311                    type: CREATE,
312                    conditions: args[0],
313                    callback: args[1],
314                    multi: args[2]
315                });
316            } else {
317                return this;
318            }
319        },
320
321        // onModify. Usage: .onModify([attributes[, match,]] callback, multi)
322        onModify: function () {
323
324            var args = Array.prototype.slice.call(arguments),
325                method;
326            if (methods[args[0]]) {
327                method = args.shift();
328            } else {
329                method = 'attach';
330            }
331
332            if (typeof (args[0]) === 'function') {
333                return methods[method].call(this, {
334                    type: MODIFY,
335                    callback: args[0],
336                    multi: args[1]
337                });
338            } else if (typeof (args[0]) === 'string') {
339                if (typeof (args[1]) === 'function') {
340                    return methods[method].call(this, {
341                        type: MODIFY,
342                        conditions: [args[0]],
343                        callback: args[1],
344                        multi: args[2]
345                    });
346                } else if (typeof (args[1]) === 'string' || args[1] instanceof RegExp) {
347                    return methods[method].call(this, {
348                        type: MODIFY,
349                        conditions: [args[0], args[1]],
350                        callback: args[2],
351                        multi: args[3]
352                    });
353                }
354            } else if (method === 'attach') {
355                return this;
356            } else {
357                methods[method].call(this, {
358                    type: MODIFY
359                });
360            }
361        },
362
363        // onText. Usage: onText([match,] callback, multi);
364        onText: function () {
365            if (this.length === 0) {
366                return this;
367            }
368
369            var args = Array.prototype.slice.call(arguments),
370                method;
371
372            if (methods[args[0]]) {
373                method = args.shift();
374            } else {
375                method = 'attach';
376            }
377
378            if (typeof (args[0]) === 'function') {
379                return methods[method].call(this, {
380                    type: TEXT,
381                    callback: args[0],
382                    multi: args[1]
383                });
384            } else if (typeof (args[0]) === 'string' || args[0] instanceof RegExp && typeof (args[1]) === 'function') {
385                return methods[method].call(this, {
386                    type: TEXT,
387                    conditions: args[0],
388                    callback: args[1],
389                    multi: args[2]
390                });
391            } else if (method === 'attach') {
392                return this;
393            } else {
394                methods[method].call(this, {
395                    type: TEXT
396                });
397            }
398        },
399
400        // onText. Usage: onMutate(type, ...);
401        onMutate: function () {
402            var args = Array.prototype.slice.call(arguments),
403                type = args.shift(),
404                typeMethod = 'on' + type.charAt(0).toUpperCase() + type.slice(1).toLowerCase();
405            if ($.fn[typeMethod]) $.fn[typeMethod].apply(this, args);
406        }
407    });
408    // Use $.onCreate as a shortcut to onCreate at the document level.
409    $.onCreate = function (selector, callback, multi) {
410        $(document).onCreate(selector, callback, multi);
411    };
412}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.