Global variable is not changing on button press (scope issue) - javascript

I have a declared variable and jQuery code telling a button to store a form's value as the value of that variable and execute a function.
var verb = "";
$( "#submit" ).click(function() {
verb = $('#enter').val();
teConjugate();
});
In the teConjugate() function, I have placed a lot of functions and variables using the "verb" variable that I want to use outside the teConjugate() function. However, when I declare these functions and variables globally, they use the globally declared "verb" (which is an empty string). I've done research and I know that it has something to do with the rendering of the page (as console.log does not raise the same issues).
The only thing I've thought of is putting said functions and variables in to a initialize function which executes on button click, to reduce the hassle of copy pasting everything. However, this did not work either.
Is there any solution? Any help would be appreciated.
JSbin with the dilemma.
As one can see, there are a lot of variables and functions that would be more useful outside the function.

There is nothing wrong with what you have shown here (see this fiddle). I suspect it is something to do with your teConjugate(); function.

Related

Removed JavaScript is still executable

If I have the following JavaScript code:
<script id="someJS">
var boom = 'boom';
function example(){
alert(boom);
}
</script>
and then do:
$('#someJS').remove();
I can still call example() even though that JavaScript function is no longer inside the DOM... How can I remove it?
I don't want to null the actual function(s) and variables with: boom = null; example = null; as I don't always know what is inside the JavaScript file. For example the function names, variables, etc. I need to be able to remove the entirity of what was inside that script tag.
Update: For those that wanted to know the user case for this:
Basically in an app I am working on, we have custom JavaScript added for certain clients that when a button is clicked e.g. save, then checks if certain functions exist and then runs them. However because this save button is generic it means that that the custom code gets called all the time after it's added even if it's no longer relevant.
The solution we have come up with (someone had posted this as an answer but they removed it for some reason) was to namespace it all like:
DynamicJS = {
boom: 'boom',
example: function(message) {
alert(message);
}
}
And then we can just do: delete DyanmicJS;
Which removes all the functions and variables inside this namespace from the global scope, effectively binning off what the script file added.
Although I am sure this is not a perfect solution as if you had event listeners inside the file, I'm sure they would still exist!
How can I remove it? I don't want to null the actual function, as I don't always know what is inside the JS file.
You can't. Script code is executed, creates things in the JavaScript environment, and is completely disconnected from the script element that loaded it. Other than completely reloading that environment, if you don't know what the code did, you can't undo it.
Even if you could infer some of what the code did (for instance, by making a list of globals before and after), while you could remove new globals you detected (or at least set them to null or undefined, since delete doesn't work wiith globals added via function declarations or var), that doesn't tell you what event handlers, web workers, etc. the code may have hooked up.
$('#someJS').remove(); only removes the script element from the page.
By the time the element is removed, the script has already been interpreted, which means example has been added to the global scope.
To properly remove that function you could do this:
window.example = null;
However, apparently you don't want to do this, and this will result in a load of errors if there's script elsewhere that actually uses example.
An alternative could be to assign an empty function to it:
window.example = function(){};
This will prevent the "removal" from resulting in errors.
(Aside from the function not returning values when that may be expected)
Once the function has been processed, it is now part of the window's executable list of functions - regardless of if you remove the original source or not.
To remove the function entirely, try:
window['example'] = null;
However, based on your last comment:
I don't want to null the actual function, as I don't always know what is inside the JS file.
It sounds like you want to maintain reference to the function but not have it executable directly? If that's the case, you can store a reference to it and remove the original:
var _exampleBackup = window['example'];
window['example'] = null;
To call it, you can now use:
_exampleBackup();
And to restore it, if you need to:
window['example'] = _exampleBackup;
example();
That function is still in the window.
Code that you put inside a script tag will be ran when the element is created and has no value (roughly) by itself anymore. Removing the tag will not affect the document and the impact it had on it (generally).
To remove the function you need to remove the example property on the window object, which is how the function will be defined, running the code above.
$('#someJS').remove();does nothing more than removing the text from the DOM, but does nothing to the actual function (nor the file), since it is parsed and executed.
In order to delete the function, you could either set it to null or simply overwrite it with example=function(){};
JavaScript Hoisting
There is a concept in JavaScript called Hoisting. In this phase, compiler parse all JavaScript code and declares variables and function at the beginning of scope. In your case, function example and variable boom is already declared and kept in memory. When you run that method, interpreter will call that method and interpret it instead of interpreting actual JavaScript code. You are deleting script block after it went in memory. And thats why it is still executable.
Approaches to do this
1) Use object oriented approach. Add your method in a object, and when you want to delete it, delete that property by using delete.
2) Create one variable which holds a function which contains your code to execute, and set that variable undefined when you want.

Javascript function implementation

I have code like this :
(function() {
$(document).ready(function() {
//event handlers
$('.project-delete').on('click', function() {
deleteProject($(this));
});
$('.keyword-delete').on('click', function() {
deleteKeyword($(this));
});
this.deleteKeyword = function(model) {
}
}).call(this);
I am curious if this is a good approach since I was learning JS recently and as far as I understand this function will have global scope, doesn't it ? since .call(this) is passing window object to this closure then I think it is not the best option ? Is there something I am missing ? Does changing .call(this) to just () change anything ?
EDIT:So is it OK to just pass window object to that closure ? Wouldn't it better to pass just a empty object or jQuery object ?
Assuming this function is defined in the global scope, the deleteKeyword function will have also have global scope since this in the context of the parent function is basically window (which has been passed in as this from outside; in the global scope this === window).
If you change .call(this) to just (), this is still window inside the function. This is because when you call a function via a simple function-call, this is set to the global object, which is window.
If you want a different value for this, you will need to pass in something else via .call or .apply.
For more information about the behavior of this, take a look here.
"as far as I understand this function will have global scope, doesn't it?"
"Scope" is about what variables a function has access to (i.e., its own local variables, plus locals declared in any functions that it might be nested inside, plus global variables), and that has nothing to do with the value of this. Scope depends on where the function declaration is, but this depends on how the function is called.
"since .call(this) is passing window object to this closure"
We can't tell that just from the code shown. Presumably you mean that that block of code is not nested inside some other function, so then yes, this would be window. But if that code was ever pasted inside some other function then that this might have some other value depending on how that other function was called.
"Does changing .call(this) to just () change anything?"
If you use just () that will mean that inside the function this will be window. Whether that changes anything depends on whether the this in .call(this) was window in the first place - as I already mentioned above, if that block were nested inside some other function this could be something else. Having said that, for the code shown if this was anything other than window I think your code would break. Because you declare a function like this:
this.deleteKeyword = function(model) {...}
...and then inside the second click handler you call what I assume is meant to be the same function without using this:
deleteKeyword($(this));
The only way that will work is if this is window and the deleteKeyword() function is thus global. If this were any other object the function would be a property of that other object and thus not accessible directly as deleteKeyword(). But unless you specifically want deleteKeyword() to be accessible from other code not shown there is no reason to create it as a property of this at all. Just declare it with var:
var deleteKeyword = function(...
...and then it will be accessible only inside that function and the ones nested in it such as your click handler. And the .call() at the end of your function would be redundant since the function wouldn't ever actually use this.
"so isn't it a better option to apply jQuery object (or maybe just empty object) to it to increase performance? Wouldn't it increase performance if this would point to local scope? Since window object is very slow."
Well as I already said, "scope" and the value of this are unrelated concepts. I'm not sure why you are worrying about performance for that code. But if you were to apply jQuery or an empty object with .call(jQuery) or .call({}) the code would not work as explained above.

Returning a variable to use within another function in JQuery

I'm making an image gallery, when I click a button I can scroll through to the next image.
I also have the option to 'jump' to a specific image. This all works fine.
However, if I scroll regularly to image 3, then jump to image 7. Once I click the next button, I don't go to image 8 as I would like to - I go to image 4. Because there are two separate functions, and I can't/ don't know how to pass the variable between them. I understand I can use a global variable outside of both functions, but this seems to be discouraged.
Here's an example:
var i = 0;
// i is a global variable
$("#next_button").click(function(){
$(".all_images").eq(i).show();
i++;
});
This would correctly increment through all of my images.
$(".thumbnails").click(function(){
var x = $(this).index();
$(".all_images:visible").hide();
$(".all_images").eq(x).show();
i = x;
});
This shows the image relative to the thumbnail I have clicked.
So, how do I use the 'i' variable from the first function in the second function? This has always confused me. It just seems simpler to use a global variable so each function can change the value of i and use it when necessary. Please enlighten me.
Also, as I understand it's possible to wrap JQuery code in a regular JavaScript functions. It seems, however, that my code doesn't work when I wrap a JQuery .click in a regular JavaScript function (ie my_Function(){ ....$("#something").click.... }
Can anybody explain what I am doing wrong?
You have two options as in most programming languages:
Use a global variable (higher scope),
Pass by reference.
However, you can't really escaoe creating some kind of global variable (object or primitive) so I would suggest you make an object (maybe even key-value) that holdes all your program parameters.
In order to do this you could use the .data method like this to assign data to an arbitrary element:
setter :
$('body').data('myvar','value');
getter:
$('body').data('myvar');
see: http://api.jquery.com/jQuery.data/
In order to pass by reference, you need to pass a object instead of a primitive.
See following link(s) for more details:
Pass Variables by Reference in Javascript
http://snook.ca/archives/javascript/javascript_pass
jQuery's .click - pass parameters to user function

global.getElementById('...') is null or not an object

In my project, I have designed a JavaScript page to render HTML data but I'm getting the above error. My code is:
global.getElementById('divPartnerGrid').innerHTML = "<table width='100%'><tr><td align='middle' style='vertical-align:middle; position:centre;'><img src='../Content/images/ajax-loader(2).gif'/></td></tr><tr><td align='middle' style='vertical-align:middle; position:centre;'>"+loadingLabel+"...</td></tr></table>"
While running the project,it will break at this line. Can anyone please let me know, what caused this error to come?
I donĀ“t know what global is either but the getElementById method is defined on the document so you probably simply want
document.getElementById('divPartnerGrid').innerHTML = "...";
replace global with document, even if global is a variable you created that points to window (or this in the global scope), you still need a document in which you want to search for elements.
Also, make sure the page is loaded before this script runs: you can't get an element if it's not loaded yet
You have probably copied the global thing from an example that has encapsulated the global variable while you haven't done the same.
This is done in the following example where the document (which is probably what you want to use as others have pointed out) where document is sent in to the self envoking function so that global inside that scope would actually refer to document.
;(function(global) {
global.getElementById(/* */);
})(document);
This is typical for libraries that could be used on the server where the global value may be different from the one in a browser.

How can I get to the parent scope of my inline javascript callback function?

I have something similar to this
function testfunction(runthis)
{
runthis();
}
function main()
{
var z = 15;
testfunction(function(){ alert(z); });
}
However it doesn't think z is in the same scope as my inline function. Without adding additional parameters to testfunction or my inline function, is there any way for my inline function to belong to the same scope as main? I'm trying to make callback functions work.
Edit: the above I imagine is a crappy example because it seems to be working. However the instance here http://pastebin.com/A1pq8dJR does not work unless I add .call(this,parameters) and manually set the scope (although I'm not exactly sure what this is doing). I would have thought this used there would refer to the scope imageLoaded has, but it is referring to the scope of imageBoxCreate? Could anyone explain why it wont work without that and why doing this fixed it?
If you just invoke a global function in javascript, the this object will be the top level window global object. If you invoke a function using the dot operator on an object, then this will be that object when the function runs. When you use function.call, you are explicitly specifying which object should be this. I think you are likely just making some scope mistakes with how you use this and var, but your code is long enough and involved enough that I'm not going to spend the time to debug it for you. If you can isolate you issue with a smaller code sample, folks should be able to help more easily.

Categories

Resources