Caching a control on a JavaScript page - javascript

I have a control on a javascript page. I can access this by id, but what I want to do is cache the control since I'm referencing it in a few places. How can I cache this control with say an id=TestControl

You can create a variable1 and safe a reference to the element (control) in it:
var testControl = document.getElementById("TestControl");
Ensure ou run that code after the element has been created (for instance, put the script tag at the end of the document, just before the closing </body> tag).
If you do that at the top level of your code, for instance:
// Scoping function to avoid creating globals
(function() {
var testControl = document.getElementById("TestControl");
// Your code here
})();
...all of your code will have access to the variable.
1 In fact, the browser has already done that for you by creating an automatic global called TestControl, but I never advocate using automatic globals. The global namespace is just too crowded, too easy to get bitten by conflicts.

The problem was that code needed to go in a $(document).ready() function. I was trying to reference it before the document loaded. Thank you for your very fast response!

Related

Create Multiple Instances Of Same Script

I am currently building a website that uses windows to load in new content via ajax. These windows are allowed to contain the same page as in another window using the same javascript. Currently I assign a unique id to the new window which it then stores for later use.
Once the code is loaded in, all the ids in that window are converted by adding on to them a unique_id. ie "box" becomes "box_win1". I then send this id to the javascript by assigning it to a variable so it can be used in document.ready function.
The pseudo code for the window is like the following:
document.ready{
var temp_id=id+1;
$("#mybox" + temp_id).val("abc")
//run some startup stuff
}
I am just wondering is there a better way to do this. As I find if I open to many new windows all at once the temp_id conflicts and goes to the wrong window.
I would like to some how create an instance of the code but I am not sure how. I cannot use global functions however as that may cause naming conflicts.
put this into a function
function callMe (){
var temp_id=id+1;
$("#mybox" + temp_id).val("abc")
//run some startup stuff
}
you can use callMe() anywhere then

Raphael and "global" variables

I'm trying to work with Raphael for some SVG stuff and tried, well, with my limited knowledge, to build something beautiful ;)
I have 3 files:
1x html file and 2xjs files
html file: with an onload function ( + header,body and stuff)
window.onload=function()
{
init();
}
js File1: has the init function and a function to load js files (e.g. Raphael) and a callback to proceed after the file is loaded
function init()
{
getScripts(initTool)
}
function getScripts(callback)
{
$.when($.getScript(scripts[raphael]).then(callback)
}
function initTool()
{
$('body').append("<div id='tool'></div>");
tool=Raphael("tool",5000,5000);
$('body').append("<a href='javascript:void(0)' onclick='newElement'>New element</a>")
}
js File2: Here I have the function newElement which should add (for this example) a single path to the svg element created by Rapahel
function newElement()
{
tool.path("M10,20L30,40");
}
Unfortunately the path does not show up and I have no idea why. I tried referencing the "tool" variable before the onload in case it it related to global/local variables (wild guessing) but this also does not work. changing id's to "tool" to "tool2" for the svg element also does not work.
What else could it be? Where is my (possibly obvious) blind spot?
SHould callback not be declared as a parameter here?
function getScripts(callback)
{
$.when($.getScript(scripts[raphael]).then(callback)
}
To be honest with you I've written quite a bit of javascript and I don't quite grok variables scopes fully yet. However, when calling functions you should use parenthesis to indicate that it should be executed (there are a couple of times when you reference them without parenthesis, but that is beyond the scope of this answer).
So...
$('body').append("<a href='javascript:void(0)' onclick='newElement()'>New element</a>")
But this isn't enough to make it work, you should also declare your function like this:
var newElement = function() {
tool.path("M10,20L30,40");
}
Here is a working solution: http://jsfiddle.net/vAjG2/
(perhaps somebody can expand on why these changes are needed, I don't grasp them myself).
The problem has nothing to do with variable scope. You just need parentheses following the function name in your inline event handler. Rewrite the last line as:
$('body').append("New element")
and you'll be up and running.
However, inline event handlers are frowned upon for a whole variety of reasons. As quirksmode says: "Although the inline event registration model is ancient and reliable, it has one serious drawback. It requires you to write JavaScript behavior code in your XHTML structure layer, where it doesn't belong."
A much cleaner way to do this would separate out the markup and the script, e.g.:
<div id='tool'></div>
<a id="mylink" href='#'>New element</a>
<script>
var tool = Raphael("tool",500,500);
$('#mylink').on("click", function() {
tool.path("M10,20L30,40");
});
</script>
See this jsfiddle for this code in action.
Lastly, as a helpful hint, I would advise running your code on document ready, instead of window load, especially you're using jquery,. Document ready happens when the DOM is first constructed. Window load waits for all assets to be fully loaded, which can take awhile, and typically isn't necessary. It's long considered a best practice.

How should I store my javascript variables?

I am currently coding in this way:
<script type="text/javascript">
var linkObj;
Is this a safe way to store data? My concern is what if a jQuery or other plug-in was to also use the variable linkObj. Also if I declare my variable like this then can it also be seen by other functions in scripts located in other js files that I include?
$(document).ready(function(){
var linkObj;
});
as long as you use the var keyword, any variable defined in that scope won't be accessible by other plugins.
I you declare a variable this way it will be accessible to all scripts running on the page.
If you just want to use it locally, wrap it in a function:
(function() {var linkObj; ... })()
However, this way nothing outside of the function will be able to access it.
If you want to explicitly share certain variables between different scripts, you could also use an object as a namespace:
var myProject = {}
myProject.linkObj = ...
This will minimize how many global names you have to rely on.
Wrap it in a closure:
<script type="text/javascript">
(function() {
var linkObj;
// Rest of your code
})();
</script>
This way no script outside your own will have access to linkObj.
Is this a safe way to store data?
This is not storing data per se, it's only declaring a variable in a script block in what I assume is an HTML page. When you reload the page in the future, it will not hold previous values.
My concern is what if a jQuery or other plug-in was to also use the variable linkObj.
That's a valid concern, like others have pointed out. However, you would expect plugins not to rely on scope outside the plug-in. This shouldn't impact a lot as good plug-in design would likely prevent this from happening.
Also if I declare my variable like this then can it also be seen by other functions in scripts located in other js files that I include?
Yes. As long as their execution is triggered after your script block gets loaded. This normally follows the order in which your script declaration appears in the page. Or regardless of the order they appear on the page if they are executed, for example, after the jQuery DOM 'ready' event.
It's common to hear that is good to avoid 'global namespace pollution', which relates to this concern. To accomplish that you can use a function to contain code, and directly invoke that function in your script block.
(function () {
var a = 1; // the scope is within the function
alert('The variable a is equal to: ' + a);
}) (); // the parenthesis invoke the function immediately

send data to JS file without using global variables

I need to send data in a HTML page to a script file that is loaded in that page. The simplest way i can think of is to use a global variable which is defined in the page and accessed in the script file.
We all know global state is bad, so i started thinking about the options available for passing data from HTML page to script file without using global state. I cant find (or think of) any.
I am curious whether this is possible. Any ideas?
It really depends what you're doing. In general, I wouldn't advise this methodology, but it's something to consider depending on your circumstances. For the sake of this example, I'll assume you're using jQuery (if not, replace the document.ready with whatever you want to use for onDOMReadyStateChange monitoring).
In the HTML:
<script type='text/json-data' id='some_data_set'>
{ 'foo': 'bar', 'baz': 1 }
</script>
In the JavaScript:
$(function() {
var myData = JSON.parse($('script#some_data_set').html());
// YOUR CODE GOES HERE
});
Nope. All the javascript scope starts from a global level, therefore you must have at least one global reference to your data.
Let's say you wanted to store a list of products and events:
var myGlobalData = { "products":<products>, "events":<events> };
Where <products> and <events> are two different data blocks.
If you're paranoid on global objects, you can simply delete the reference point (thus it's contents) after you finished using it, as follows:
delete window.myGlobalData;
One option is to scope your data. For example, in JS file you can define an object like:
var processor = {
function setData(o) { // do stuff
}
};
Then in your HTML you know that the data is scoped to the processor. So you can do something like:
processor.setData({someData});

Javascript executing when jQuery not ready

The following scenario is a problem I am having. I came to the conclusion that jQuery must not be ready when Javascript is executing by observing this scenario.
Scenario:
I have a Java application which injects Javascript script tags into the currently loaded DOM page. The following Java code runs inline Javascript which inserts jquery.js and myCode.js. myCode.js holds my Javascript codes.
browser.executeJavaScript("var head= document.getElementsByTagName('head')[0];" +
"var script= document.createElement('script');script.type= 'text/javascript';script.src= 'jquery.js';head.appendChild(script);" +
"var script4= document.createElement('script');script4.type= 'text/javascript';script4.src= 'http://myCode.js';head.appendChild(script4);");
In this Java application, I also have a buttonListener that fires a function in myCode.js in ActionPerformed();
executedJS = browser.executeJavaScript("replaceAllLinks()");
The problem that is encountered is nullPointerException at the above line when button is clicked. Accomodating for null case results in endless loop without any changes.
while(executedJS == null) browser.executeJavaScript("replaceAllLinks()");
The cause of the problem was pinpointed down to when jQuery functions, methods are present inside replaceAllLinks(); javascript function. when jQuery, methods were absent, no problems could be observed. There was not one instance of nullPointerException raised.
The only possible underlying issue would be that somehow jQuery library is not fully loaded while replaceAllLinks(); is being executed. If jQuery methods and functions were not in use, it doesn't matter and everything runs okay.
My question is then, how can I make sure that jQuery is fully loaded and available for use?
Every script relying on jQuery should be contained inside a DOM ready function. Such a function normally takes this form:
$(document).ready(function() {
/* code here */
});
and a shortcut to achieve the same thing would be:
$(function() {
/* code here */
});
Here's the documentation for further information on the ready method:
http://api.jquery.com/ready/
Declare some global variable at the end jquery.js, e.g.
window.jQueryIsLoaded=true;
and check this variable before using jQuery.
<edit>Forget this, see Salman A's comment below, should be the right answer.</edit>

Categories