remove appended script javascript
Asked Answered
S

9

11

how can I remove my appended script because it causes some problems in my app.

This is my code to get my script

var nowDate = new Date().getTime();
var url = val.redirect_uri + "notify.js?nocache=" + nowDate + "&callback=dummy";
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);

Then I have an auto load function, that causes to create another element script.

I want to get rid of the previous element that was appended before another element is added.

Spawn answered 22/2, 2012 at 7:2 Comment(14)
Simply setting script.src=''; , or removing the script node: script.removeNode(true);.Amersfoort
@Amersfoort does that remove all my scripts? Or only the appended script?Spawn
Only the script which id is script. Usually you use it like this: document.getElementById('script').src='';Amersfoort
Well, I tested this my answer, it is not working properly. The node is removed, but the actual script remains in memory. I've changed src to the same to reload scripts in my many applications, but this trick doesn't seem to work when removing them.Amersfoort
@Amersfoort well thanks anyways. Anymore suggestions?Spawn
Not much, I searched the issue from web, this seems to be quite difficult. Maybe you can find something, I started googling with keywords "remove script", and there were plenty of hits...Amersfoort
Well, Not adding the scripts again sounds like a better idea then remove it...Batfish
But I want to load the script again.Spawn
Why?! So you could remove it right afterward...???Batfish
You can use jquery.getScript() , the usage of this function is like that whenever you need the script it gets loadedAlbrecht
@KunalVashist, I don't see jQuery tagged or mentioned anywhere in the OP.Fulk
@Batfish I use this for a JSONP call, that needs to add script because of callbacks.Spawn
By looking the code what i feel is that you can use a flag if flag is 1 load the script else not. and checking of the flag depends on cookie. Set flag=1 initially "Means you can set the cookie by using the current time stamp which will be unique, On refreshing of the page check that cookie time stamp or cookie . if cookie is not present create cookie and load the script and at end set flag =0 ,else if that cookie is present i.e flag to 0 hence no loading of the script". I think it will workAlbrecht
@KunalVashist Thanks! But correct me if I'm wrong, it seems you have the same concept in the answer below in a different way. Its really hard to explain, but I want to load my script because its a jsonp call. I'm not going to use a function on the called script but I used it to get data on it. And how can I get data on it if I'm not going to load my script. No loading of script is not an option in my case.Spawn
A
3

I did some more tests, and before you'll get a correct answer to your question (hope there is a one) you can try this:

<button onclick="foo()">ShowHTML</button>
<script>
(function foo(){
    var b=function moo(){
        var c=document.getElementsByTagName('script');
        alert(document.body.innerHTML);
        c[0].parentElement.removeChild(c[0]);
        alert(document.body.innerHTML);
    }
    var a=setTimeout(b,1000);
    b=null;
})();
foo=null;
</script>

This is just a test code, but it contains an idea, how you possible could solve the problem. It removes <sript> from the DOM, and the last line destroys all functionality of the script.

(The code also has a little detail, which shows, that setTimeout will do eval(), no matter how it is argumented...?)

Amersfoort answered 27/2, 2012 at 20:38 Comment(1)
@Robin Carlo Catacutan Thanks for accepting. I suppose you have noticed, that if you define global variables in closures, they will remain despite of nullifying closured function. And setIntervals will continue for ever...Amersfoort
P
14

Basically you can remove script tag by using a function similar to this one:

function removeJS(filename){
 var tags = document.getElementsByTagName('script');
 for (var i = tags.length; i >= 0; i--){ //search backwards within nodelist for matching elements to remove
  if (tags[i] && tags[i].getAttribute('src') != null && tags[i].getAttribute('src').indexOf(filename) != -1)
   tags[i].parentNode.removeChild(tags[i]); //remove element by calling parentNode.removeChild()
 }
}

Note, it use filename parameter to identify target script to remove. Also please note that target script could be already executed at the time you're trying to remove it.

Pique answered 27/2, 2012 at 18:12 Comment(3)
The script is still in the memory. Still functioning.Spawn
As I mentioned in my post - this is expected behavior in case when you're trying to remove it after it was executed. You need to stop it by using javascript and then remove then.Pique
Yes, you're right. What I've searched so far is that, it is called as memory leaks.Spawn
F
5

I would simply check to see if you've already added the script. Adding it and then removing is adds unnecessary complexity. Something like this should work:

var scriptAdded = false;

if(scriptAdded == false) {
    document.body.appendChild(script);
    scriptAdded = true;
}
Fulk answered 27/2, 2012 at 13:26 Comment(4)
As the OP says code refreshes every one minute, I believe the variable scriptAdded will be false everytime.Passably
Maybe the script added by OP is a JSONP call?Chary
@ShashankKadne, that part confused me a bit as well. I assumed that it was some type of AJAX refresh since the OP also indicated that they are getting 30 instances of the script added (one per refresh). Unless they post more code, I'm sticking to my original answer :)Fulk
Yes, its a JSONP call. I think this does not solve my problem.Spawn
A
3

I did some more tests, and before you'll get a correct answer to your question (hope there is a one) you can try this:

<button onclick="foo()">ShowHTML</button>
<script>
(function foo(){
    var b=function moo(){
        var c=document.getElementsByTagName('script');
        alert(document.body.innerHTML);
        c[0].parentElement.removeChild(c[0]);
        alert(document.body.innerHTML);
    }
    var a=setTimeout(b,1000);
    b=null;
})();
foo=null;
</script>

This is just a test code, but it contains an idea, how you possible could solve the problem. It removes <sript> from the DOM, and the last line destroys all functionality of the script.

(The code also has a little detail, which shows, that setTimeout will do eval(), no matter how it is argumented...?)

Amersfoort answered 27/2, 2012 at 20:38 Comment(1)
@Robin Carlo Catacutan Thanks for accepting. I suppose you have noticed, that if you define global variables in closures, they will remain despite of nullifying closured function. And setIntervals will continue for ever...Amersfoort
S
3

just add an id to the script element when you create it.

this way you don't have to iterate over all 'script' tags that match your source. instead, just do

const script = document.createElement("script");

script.src = "SOME_SCRIPT";
script.id = 'SOME_ID';

document.body.append(script);

and then to remove

const scriptElem = document.getElementById('SOME_ID'); 
scriptElem.remove()

some dude explains here why its ok to add id to script tags https://mcmap.net/q/269822/-giving-the-script-tag-an-id

Shult answered 26/1, 2021 at 13:11 Comment(0)
H
2

What you can do is remove the script immediately after it has been loaded:

var nowDate = new Date().getTime();
var url = val.redirect_uri + "notify.js?nocache=" + nowDate + "&callback=dummy";
var script = document.createElement('script');
script.src = url;
script.onload = function( evt ) {
    document.body.removeChild ( this );
}
document.body.appendChild(script);

Anyway I think it is a better idea to append the script to the header (where all the other scripts reside) than to the body.

Hosbein answered 19/3, 2013 at 9:56 Comment(0)
M
1

In case of JSONP and your use of jQuery, why not take full advantage of jQuery's JSONP loading facilities, which do the post-clean-up for you? Loading JSONP resource like this, doesn't leave a trace in the DOM:

$.ajax({ url: 'http://example.com/', dataType: 'jsonp' })

The <script> tag used for loading is removed instantly as soon it's loaded. If the loading is a success. On the other hand, failed requests don't get cleared automatically and you have to do that yourself with something like this:

$('head script[src*="callback="]').remove();

called at the right time. It removes all pending JSONP <script> tags.

Muster answered 27/2, 2012 at 22:18 Comment(2)
Thanks. But I have to stick to my classic script, since I have too many of these and the deadline is near. Well I gonna put this on my mind for the future needs. Thanks for stating this to me, really helpful.Spawn
Understood. Still think you can use the removal line to get rid of your previous <script> if you target it to locate "notify.js" in the src like this: $('head script[src*="notify.js"]').remove();Muster
M
0

Well,
I got the same need, because of ajax calls triggered by event. Some calls being the earliest may return later, then overwriting document populated by the last call.

removeChild(scriptEl) doesn't work. Changing src attribute doesn't work either.

If jsonp is your only way out, and if you have control of the server response, you can let those appended to discriminate return on the callback.

Just pass a timestamp parameter, then check it on the callback

//callback
function dummy(res, ts) {
 if(YAHOO.util.Selector.query('script[id='scriptIdPrefix+ts+']').length>0) {
     do your job
 } else {
     do nothing
 }
}

//add script
var scriptIdPrefix='myScriptId';
function ajaxCall() {
    var timestamp = new Date().getTime();
    var scriptId = scriptIdPrefix+timestamp;
    //remove the previous script el
    s=YAHOO.util.Selector.query('script[id^='+scriptIdPrefix+']');
    if(s.length>0) {
        document.body.removeChild(s[0]);
    }
    var script = document.createElement('SCRIPT');
    script.id = scriptId;
    script.type = 'text/javascript';
    script.src = 'http://server/notify.js&callback=dummy&ts='+timestamp;
    document.body.appendChild(script);

}

Assemble the result of the server notify.js accordingly:

dummy([{"datax":"x","datay":"y"}], 1369838562792)

In this way you will have just one script element like this with parametric id

<script id="myScriptId1369838562792" type="text/javascript"  
src="http://server/notify.js?callback=dummy&ts=1369838562792"></script>
Metatarsus answered 29/5, 2013 at 15:1 Comment(0)
F
0

easiest way.

document.scripts.s16483498357511596685.remove();

Fran answered 18/3, 2019 at 14:5 Comment(0)
P
-2
var flag1=0,flag2=0;
$(window).resize(function(){
    if ($(window).width() < 480){
        flag1++;
        console.log(flag1);
        flag2=0;  
    }
    else 
        if($(window).width() > 480){
            flag2++;
            console.log(flag2);
            flag1=0;
        }   
    if(flag1==1){
        $("body").append("<script class='abc' src='custom.js'/>");
    }
    else
        if(flag2==1){
            $(".abc").remove();
        }
});
Peeress answered 26/7, 2017 at 6:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.