Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing properties hidden by __defineGetter__/__defineSetter__ in JavaScript

I am trying to define a custom setter for the innerHTML property. Unfortunately, i am unable to access the underlying property after i define the setter function:

$('body')[0].__defineSetter__("innerHTML",
  function (val) {
    alert("Setting to: " + val);
    this.innerHTML = val;
});

This snippet fills the call stack because the assignment calls the setter recursively. Apparenly innerHTML is already an overloaded property in IE8 and you can simply save the older get/set pair and use it inside the new property descriptor. Taken from MSDN:

var innerHTMLdescriptor = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
Object.defineProperty(Element.prototype, 'innerHTML',
  { set: function(htmlVal) {
      var safeHTML = toStaticHTML(htmlVal);
      innerHTMLdescriptor.set.call(this, safeHTML);
    }
});

However, this seems to be not the case for Chrome, where getOwnPropertyDescriptor returns undefined for innerHTML. In this case, how do I access the underlying property?

Bonus question: how do I ensure that all objects created in the future have this special innerHTML behaviour? Is it possible to use DOM prototypes for this? It seems that overloading a function is not what i need here. Perhaps it is possible to overload the DOM constructor and add a call __defineGetter__/defineProperty but it looks like support for constructors is not common so I'd like to know if there is any alternative.

like image 804
BruceBerry Avatar asked Nov 13 '22 22:11

BruceBerry


1 Answers

All you need is a separate datastore property to store the actual value, much like with other languages that use getters and setters. You can use closures to make them hidden.

var _innerHTML = "";

this.__defineSetter__( "innerHTML",
    function (val) {
        alert("Setting to: " + val);
        _innerHTML = val;
    } );

this.__defineGetter__( "innerHTML",
    function () {
        return _innerHTML;
    } );

However, I've found that using getters and setters on existing DOM properties often simply won't work, due to the special handling of these properties internally. For example, it won't work with the value property of a text input. I'd expect innerHTML to be in the same boat.

like image 191
devios1 Avatar answered Dec 20 '22 10:12

devios1