Greetings readers, stylized form elements on the sites are now firmly established in the realities of modern design and who would not say that, in many cases they look really nice.
Many of you have already got the chosen type of plug-ins and other good, some of them are very well written. In this article I will not talk about the next plugin, but just want to draw your attention to one of the ways to expand the capabilities of the plug-in, maybe it will help someone.
I am in favor of connecting plug-ins for styling forms, we must continue to work with the elements of the forms in the native style and not depend on the stylization plug-in. Practically, I haven’t seen a single plug-in (I can’t say a single one) see the correct processing of changing the behavior of elements when the attributes of DOM elements change, namely the processing of changes to the
disabled attribute (
min, max, maxlength ), I always had to consider ap plug-ins, the layout of the element and so on, and this is inconvenient if you in the future want to change the plugin or layout. As an option - think in advance and make wrappers for everything and work with them as with an internal api. But there is an alternative path.
After examining the problem with attributes, it involuntarily comes to mind - “should we not begin to detect changes in the attributes of an element?” Drawing attention to
MutationObserver and after consulting with
caniuse , I understand that it’s time: crome, firefox has long been supported, the new IE11 too, android slowly creeps, ios fully supports already. The result is the following code (
jsFiddle )
var MO = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver); var observer = new MO(function(){ console.log("disabled changed") }); observer.observe(document.querySelector("id"), { attributes: true, attributeFilter: ["disabled"] });
It is good only to overcome IE, but everything is bad here ... The first
step is - well, there is
DOMAttrModified , as well as for very old
propertychange .
Of course they do, they even work, but not in our case: the events on the zadizabil element do not rush. From here we get an interesting picture: when adding the disabled attribute, the events are silent as partisans, and when they are deleted, they quietly prokidyvayutsya. I would call it a bug rather than a standard behavior, since the event is different and chopping off everything in the bud is bad, but what to do. However, this does not prevent us from writing a mini workaround for this problem (
jsFiddle )
')
var AttributeObserver = function(element, callback, attribute){ var MO = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver); if (MO) { var observer = new MO(callback); observer.observe(element, { attributes: true, attributeFilter: [attribute] }); } else { if (!AttributeObserver.__timer) { AttributeObserver.__observed = [] AttributeObserver.__timer = setInterval(function(){ for (var i = 0; i < AttributeObserver.__observed.length; i++) { var o = AttributeObserver.__observed[i]; if (o.element.hasAttribute(o.attribute) !== o.flag) { callback() } o.flag = o.element.hasAttribute(o.attribute) } }, 500) AttributeObserver.__observed.push({ element: element, attribute: attribute, flag: element.hasAttribute(attribute) }) } } }
Anticipating the perturbations of some individuals about setInterval I will explain: no, this is not a hack, setInterval is quite a working construction of the language, which, with a reasonable approach, does not introduce chaos and brakes, if you look at the real situation, then a reasonable interval would be 500-1000ms, and if you allow that on the page there are usually 10-20 controls, and even if 100 to check their attribute is not a problem.
Also this method is applicable for cases if you need to respond to changes in maxlength, min, max and other attributes that can influence the behavior of custom controls. The same min, max attributes for range input, if you work with the native range input and make a fallback for browsers without support, will look good with a similar approach to monitoring attributes and this can solve many problems - you work with input in the native way, and the plugin picks up the changes. This is the option I would like to consider now, because here we have an important problem - we are not working with disabled elements, which means we can upgrade our solution (
jsFiddle )
var AttributeObserver = function(element, callback, attribute){ var MO = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver); if (MO) { var observer = new MO(callback); observer.observe(element, { attributes: true, attributeFilter: [attribute] }); } else if (element.addEventListener) { element.addEventListener('DOMAttrModified', function(e){ if (e.attrName == attribute) { callback() } }, false); } else if ("onpropertychange" in document) { element.attachEvent ('onpropertychange', function(e){ if (e.attrName == attribute) { callback() } }); } }
PS I would like to add that the code does not pretend to be the title of a ready-made plug-in, but rather simply demonstrates one of the possible approaches.