Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #26554 > unrolled thread

Dynamically add/remove code in browsers

Started by"Leonardo Azpurua" <leonardo@exmvps.org>
First post2015-01-12 05:22 -0430
Last post2015-01-13 20:50 +0100
Articles 10 — 4 participants

Back to article view | Back to comp.lang.javascript


Contents

  Dynamically add/remove code in browsers "Leonardo Azpurua" <leonardo@exmvps.org> - 2015-01-12 05:22 -0430
    Re: Dynamically add/remove code in browsers Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 17:21 +0100
      Re: Dynamically add/remove code in browsers Joao Rodrigues <groups_jr-1@yahoo.com.br> - 2015-01-12 16:44 -0200
        Re: Dynamically add/remove code in browsers Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 22:01 +0100
          Re: Dynamically add/remove code in browsers Joao Rodrigues <groups_jr-1@yahoo.com> - 2015-01-12 22:06 -0200
            Re: Dynamically add/remove code in browsers Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-13 01:11 +0100
      Re: Dynamically add/remove code in browsers "Leonardo Azpurua" <leonardo@exmvps.org> - 2015-01-12 15:21 -0430
        Re: Dynamically add/remove code in browsers Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 22:03 +0100
      Re: Dynamically add/remove code in browsers Joao Rodrigues <groups_jr-1@yahoo.com.br> - 2015-01-13 12:17 -0200
        Re: Dynamically add/remove code in browsers Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-13 20:50 +0100

#26554 — Dynamically add/remove code in browsers

From"Leonardo Azpurua" <leonardo@exmvps.org>
Date2015-01-12 05:22 -0430
SubjectDynamically add/remove code in browsers
Message-ID<m905b3$90j$1@dont-email.me>
Hi,

I am planning to implement a Web interface for a rich/fat client Windows 
business system.

In its current implementation, the system allows searching whenever the Id 
of an entity is required, and new entities can be created "in-line" by 
provided a valid, non-existant id.

Now, in some forms, there may several kinds of entitites (items, customers, 
payment conditions, pricing profiles, salesmen).

It doesn't sound practical to clutter the basic HTML page with all the divs, 
code and controls required to manage all the possible creations.

So I am trying to find a way to dynamically add a DIV, give it a "standard 
look", populate it with input controls, show it as a sort of modal dialog, 
close it and restore the browser to its original state.

As for code, this is a very basic test of an approach:

  var sc;

  function addHandler() {
      var el = document.getElementById("test");
      sc = document.createElement("script");
      sc.id = "dynScript";
      sc.type = "text/javascript";
      // the value assigned to the script will be a rather large chunk of 
code imported by an httpRequest
      sc.text = "function handleClick() { window.alert('Test clicked') }";
      document.getElementsByTagName("head")[0].appendChild(sc);
      el.onclick = handleClick;
  }

  function removeHandler() {
      var el = document.getElementById("test");
      el.onclick = null;
      document.getElementsByTagName("head")[0].removeChild(sc);
      sc = null;
  }

That is:
  On Creation:
    Have the document create an SCRIPT element, and append it to the HEAD 
element (is this necessary?).
    Assign the functions to the event handlers of the appropriate controls 
(this would be handled by the new code itself)
  On Disposing
    Remove all the event handlers
    Remove the SCRIPT element from the document
    Dispose of the script element itself.

Does this sound like a right approach, or am I totally missing it?

[toc] | [next] | [standalone]


#26557

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 17:21 +0100
Message-ID<11460823.sCPipJV62P@PointedEars.de>
In reply to#26554
Leonardo Azpurua wrote:

>   var sc;
> 
>   function addHandler() {
>       var el = document.getElementById("test");
>       sc = document.createElement("script");
>       sc.id = "dynScript";
>       sc.type = "text/javascript";
>       // the value assigned to the script will be a rather large chunk of
> code imported by an httpRequest
>       sc.text = "function handleClick() { window.alert('Test clicked') }";

You should not clutter the global namespace.  Any global handleClick() 
function in the document or in memory will be overwritten/shadowed by that 
code.  Consider instead a user-defined globally accessible object that you 
use as namespace:

  var leo = {};

(“leo” then refers to that object.)

And in the script to be loaded:

  leo.handleClick = function () { window.alert('Test clicked') };

It may even be better if you have a property for each use-case.  Otherwise 
you would fill heap memory with inaccessible Function instances as the same 
property’s value is replaced.  Also consider JSONP.

In any case, you should move the part that inserts the “script” element to a 
separate function/method.

>       document.getElementsByTagName("head")[0].appendChild(sc);
>       el.onclick = handleClick;

You cannot assume that the script has been loaded and executed once you 
inserted the “script” element in the document.

You need to listen to and handle the “load” event of the “script” element:

  sc.onload = function () {
    el.onclick = handleClick;
  };

But it is presently unknown to me where this feature now standardized in 
HTML5 is supported.  Thus, it may be necessary to use setTimeout()-based 
polling to determine if execution has reached the end of the loaded script 
before you continue.

Also, you can use the “document.head” property if it is available:

  (document.head || document.getElementsByTagName("head")[0])
    .appendChild(sc);

It might be easier to use the backwards-compatible “document.body” property 
instead:

  document.body.appendChild(sc);

>   }
> 
>   function removeHandler() {
>       var el = document.getElementById("test");
>       el.onclick = null;
>       document.getElementsByTagName("head")[0].removeChild(sc);

If you are accessing the “script” element by object reference, so it does 
not need an ID.

> Does this sound like a right approach,

Only if the script you are loading is large and you can ensure that you can 
determine when execution has reached the end of the script.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#26559

FromJoao Rodrigues <groups_jr-1@yahoo.com.br>
Date2015-01-12 16:44 -0200
Message-ID<m914le$e0f$1@speranza.aioe.org>
In reply to#26557
On 12/01/2015 14:21, Thomas 'PointedEars' Lahn wrote:
> Leonardo Azpurua wrote:
> 
>>   var sc;
>>
>>   function addHandler() {
>>       var el = document.getElementById("test");
>>       sc = document.createElement("script");
>>       sc.id = "dynScript";
>>       sc.type = "text/javascript";
>>       // the value assigned to the script will be a rather large chunk of
>> code imported by an httpRequest
>>       sc.text = "function handleClick() { window.alert('Test clicked') }";
> 
> You should not clutter the global namespace.  Any global handleClick() 
> function in the document or in memory will be overwritten/shadowed by that 
> code.  Consider instead a user-defined globally accessible object that you 
> use as namespace:
> 
>   var leo = {};
> 
> (“leo” then refers to that object.)
> 
> And in the script to be loaded:
> 
>   leo.handleClick = function () { window.alert('Test clicked') };
> 
> It may even be better if you have a property for each use-case.  Otherwise 
> you would fill heap memory with inaccessible Function instances as the same 
> property’s value is replaced.  Also consider JSONP.
> 
> In any case, you should move the part that inserts the “script” element to a 
> separate function/method.
> 
>>       document.getElementsByTagName("head")[0].appendChild(sc);
>>       el.onclick = handleClick;
> 
> You cannot assume that the script has been loaded and executed once you 
> inserted the “script” element in the document.
> 
> You need to listen to and handle the “load” event of the “script” element:
> 
>   sc.onload = function () {
>     el.onclick = handleClick;
>   };
> 
> But it is presently unknown to me where this feature now standardized in 
> HTML5 is supported.  Thus, it may be necessary to use setTimeout()-based 
> polling to determine if execution has reached the end of the loaded script 
> before you continue.
> 
> Also, you can use the “document.head” property if it is available:
> 
>   (document.head || document.getElementsByTagName("head")[0])
>     .appendChild(sc);
> 
> It might be easier to use the backwards-compatible “document.body” property 
> instead:
> 
>   document.body.appendChild(sc);
> 
>>   }
>>
>>   function removeHandler() {
>>       var el = document.getElementById("test");
>>       el.onclick = null;
>>       document.getElementsByTagName("head")[0].removeChild(sc);
> 

ACK.


> If you are accessing the “script” element by object reference, so it does 
> not need an ID.
> 

However, what if there are other scripts in the document? And what if
the new script element already exists? Then, an ID would be of great
value to optimization.

All those questions would be better addressed by the following approach:
<http://calendar.perfplanet.com/2014/the-pain-of-duplicate-scripts/>

  (function(d, s, id){
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) {return;}
    js = d.createElement(s); js.id = id;
    //js.src = "//localhost/test.js";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'dynScript'));


-- 
Joao Rodrigues

[toc] | [prev] | [next] | [standalone]


#26562

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 22:01 +0100
Message-ID<28422568.EsDYu13dd2@PointedEars.de>
In reply to#26559
Joao Rodrigues wrote:

> On 12/01/2015 14:21, Thomas 'PointedEars' Lahn wrote:
>> If you are accessing the “script” element by object reference, so it does
>> not need an ID.
> 
> However, what if there are other scripts in the document?

Then a dynamically inserted “script” element with an ID would be an 
additional problem because IDs must be unique.

> And what if the new script element already exists? Then, an ID would be of
> great value to optimization.

On the contrary.  You would need to determine if the ID was already used by 
an element and try a different one until you find an unused one.  And for 
what?  If you have a reference to the object that represents the “script” 
element that you inserted before, you can simply reuse that reference (if 
you think you need to remove it).  No ID necessary, and no 
document.getElementById() calls necessary.

> All those questions would be better addressed by the following approach:
> <http://calendar.perfplanet.com/2014/the-pain-of-duplicate-scripts/>
> 
>   (function(d, s, id){
>     var js, fjs = d.getElementsByTagName(s)[0];
>     if (d.getElementById(id)) {return;}
>     js = d.createElement(s); js.id = id;
>     //js.src = "//localhost/test.js";
>     fjs.parentNode.insertBefore(js, fjs);
>   }(document, 'script', 'dynScript'));

This code is addressing a different use-case, and it is adressing it most 
poorly.  Do not believe everything you read.

Please trim your quotes to the relevant minimum.
 
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#26564

FromJoao Rodrigues <groups_jr-1@yahoo.com>
Date2015-01-12 22:06 -0200
Message-ID<m91nhq$lrd$1@speranza.aioe.org>
In reply to#26562
On 01/12/2015 07:01 PM, Thomas 'PointedEars' Lahn wrote:
> Joao Rodrigues wrote:
> 
>> On 12/01/2015 14:21, Thomas 'PointedEars' Lahn wrote:
>>> If you are accessing the “script” element by object reference, so it does
>>> not need an ID.
>>
>> However, what if there are other scripts in the document?
> 
> Then a dynamically inserted “script” element with an ID would be an 
> additional problem because IDs must be unique.

Oops. In fact, I was pondering your suggestion about using
document.getElementsByTagName("head")[0], instead of
document.getElementsByTagName("script")[0].


>> And what if the new script element already exists? Then, an ID would be of
>> great value to optimization.
> 
> On the contrary.  You would need to determine if the ID was already used by 
> an element 

Exactly!

> and try a different one until you find an unused one.  And for 
> what?  If you have a reference to the object that represents the “script” 
> element that you inserted before, you can simply reuse that reference (if 
> you think you need to remove it).  No ID necessary, and no 
> document.getElementById() calls necessary.

The intention was to avoid duplicate scripts, not to reuse the same script:

  if (document.getElementById(id)) { return; }


-- 
Joao Rodrigues

[toc] | [prev] | [next] | [standalone]


#26565

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-13 01:11 +0100
Message-ID<3245187.AuqfBu7pZh@PointedEars.de>
In reply to#26564
Joao Rodrigues wrote:

> On 01/12/2015 07:01 PM, Thomas 'PointedEars' Lahn wrote:
>> Joao Rodrigues wrote:
>>> On 12/01/2015 14:21, Thomas 'PointedEars' Lahn wrote:
>>>> If you are accessing the “script” element by object reference, so it
>>>> does not need an ID.
>>> However, what if there are other scripts in the document?
>> Then a dynamically inserted “script” element with an ID would be an
>> additional problem because IDs must be unique.
> 
> Oops. In fact, I was pondering your suggestion about using
> document.getElementsByTagName("head")[0], instead of
> document.getElementsByTagName("script")[0].

I have not suggested such a nonsense.

>>> And what if the new script element already exists? Then, an ID would be
>>> of great value to optimization.
>> On the contrary.  You would need to determine if the ID was already used
>> by an element
> 
> Exactly!

Which is unnecessary in this case and most other cases.  Objects have built-
in identity.

>> and try a different one until you find an unused one.  And for
>> what?  If you have a reference to the object that represents the “script”
>> element that you inserted before, you can simply reuse that reference (if
>> you think you need to remove it).  No ID necessary, and no
>> document.getElementById() calls necessary.
> 
> The intention was to avoid duplicate scripts, not to reuse the same
> script:
> 
>   if (document.getElementById(id)) { return; }

AISB, a different use-case.  And handled most poorly.
 
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#26561

From"Leonardo Azpurua" <leonardo@exmvps.org>
Date2015-01-12 15:21 -0430
Message-ID<m918e3$3p9$1@dont-email.me>
In reply to#26557
"Thomas 'PointedEars' Lahn" <PointedEars@web.de> escribió en el mensaje 
news:11460823.sCPipJV62P@PointedEars.de...
>> Does this sound like a right approach,
>
> Only if the script you are loading is large and you can ensure that you 
> can
> determine when execution has reached the end of the script.

Thank you very much.

A most precise answer and useful comments.


[toc] | [prev] | [next] | [standalone]


#26563

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 22:03 +0100
Message-ID<1465696.yEcSgFpU9U@PointedEars.de>
In reply to#26561
Leonardo Azpurua wrote:
 
> Thank you very much.
> 
> A most precise answer and useful comments.

You are welcome.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#26568

FromJoao Rodrigues <groups_jr-1@yahoo.com.br>
Date2015-01-13 12:17 -0200
Message-ID<m939de$tpk$1@speranza.aioe.org>
In reply to#26557
Thomas Lahn wrote:

> You cannot assume that the script has been loaded and executed once you 
> inserted the “script” element in the document.
> 
> You need to listen to and handle the “load” event of the “script” element:
> 
>   sc.onload = function () {
>     el.onclick = handleClick;
>   };
> 
> But it is presently unknown to me where this feature now standardized in 
> HTML5 is supported.  Thus, it may be necessary to use setTimeout()-based 
> polling to determine if execution has reached the end of the loaded script 
> before you continue.

onload is not supported in IE8 and below. So, in this case, one could
use the readystatechange event. E.g.:

// IE8 and below
if (sc.readyState) {
  sc.onreadystatechange = function () {
    if (sc.readyState == "loaded" || sc.readyState == "complete") {
      script.onreadystatechange = null;
      el.onclick = handleClick;
    }
  };
} else { // FF, Chrome, Safari, Opera, etc.
  sc.onload = function () {
    el.onclick = handleClick;
  };
}

An alternate method would be XMLHttpRequest() which works in all modern
browsers. A caveat is the same-origin policy, which prevents downloading
the script from CDNs for instance.

> 
> Also, you can use the “document.head” property if it is available:
> 
>   (document.head || document.getElementsByTagName("head")[0])
>     .appendChild(sc);
> 
> It might be easier to use the backwards-compatible “document.body” property 
> instead:
> 
>   document.body.appendChild(sc);
> 

document.body.appendChild(sc) could be problematic in older versions of
IE. See
<http://www.nczonline.net/blog/2008/03/17/the-dreaded-operation-aborted-error/>

-- 
Joao Rodrigues

[toc] | [prev] | [next] | [standalone]


#26576

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-13 20:50 +0100
Message-ID<2895506.0IJ30mozXU@PointedEars.de>
In reply to#26568
Joao Rodrigues wrote:

> Thomas Lahn wrote:
>> Also, you can use the “document.head” property if it is available:
>> 
>>   (document.head || document.getElementsByTagName("head")[0])
>>     .appendChild(sc);
>> 
>> It might be easier to use the backwards-compatible “document.body”
>> property instead:
>> 
>>   document.body.appendChild(sc);
> 
> document.body.appendChild(sc) could be problematic in older versions of
> IE. See
> <http://www.nczonline.net/blog/2008/03/17/the-dreaded-operation-aborted-error/>

That does not apply here:

,-<http://support2.microsoft.com/kb/927917/en-us>
| 
| […]
| This problem occurs because a child container HTML element contains script 
| that tries to modify the parent container element of the child container. 
| The script tries to modify the parent container element by using either 
| the innerHTML method or the appendChild method.

Also:

| Answer: Internet Explorer 7 cannot display a particular element on a Web 
| page on that Web site.
| 
| […]
| How do I fix this problem?
| 
| The easiest way for you to fix the problem is to upgrade to Internet 
| Explorer 8. This problem no longer occurs in Internet Explorer 8.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web