How to write a var to apply script on multiple pages? - javascript

I want to apply the same script on multiple pages, but I need to store some var inside, which may not be present on particular pages.
window.onorientationchange = function () {
var $t1 = $(".test1")[0];
var $t2 = $(".test2")[0];
var $t3 = $(".test3")[0];
var $t4 = $(".test4")[0];
var $t5 = $(".test5")[0];
// do some stuff
}
I want to store this code in .js file and then apply it across several pages, the problem is that some of this var's are not present on particular pages, how do I make it universal?
Also
If I add lines like:
if (window.matchMedia("(orientation: portrait)").matches) {
if ($t1.is(":empty") && $t2.is(":visible")) {}}
inside mentioned event listener, how do I deal with an "empty" var's, which is not defined on the previous step?

Several things.
Based on your variable naming, it looks like you are expecting $t1 to be a jQuery object.
However, when you try to access an element by index [0], you are returning the first element that matched the selector, no longer wrapped as a jQuery object.
What you want is to use the .eq(0) function to access the element by index, so a jQuery object is returned
https://api.jquery.com/eq/
var $t1 = $(".test1").eq(0);
At that point, you can use the .length test to check if your $t1 contains any elements
window.onorientationchange = function () {
var $t1 = $(".test1").eq(0);
// ...
if($t1.length){
// do stuff with $t1
}
}

Related

Null check for every variable that invokes a function?

I have a single javascript where I have declared all my variables in the
$(document).ready(function(){
//variables
});
The values of these variables are initialized as well and mostly they are HTML elements. The elements are determined using the ids via document.GetElementById(). Some of these elements exists only in a different page which is not loaded in the browser yet. This results in null error when the variables holding the elements are used for a different purpose.
var container_element = document.getElementById('unique-id');
var count = container_element.getElementsByTagName("div").length;
Since the element with "unique-id" is present in another page which is not loaded in the browser, the second line would return an error because container_element is null. To fix this, I changed the code to
var container_element = document.getElementById('unique-id');
if(container_element) {
var count = container_element.getElementsByTagName("div").length;
}
Is this is the only way to handle such a thing? Should I have to do a null check for every function that I invoke via a variable or is there any other solution or standard / best practice?
You need a guard like that any time the element may or may not exist as of when you use getElementById. You can use the if you've shown, or
var container_element = document.getElementById('unique-id');
var count = !container_element ? 0 : container_element.getElementsByTagName("div").length;
or similar.
Another option is to react to the exception:
var container_element = document.getElementById('unique-id');
var count;
try {
count = container_element.getElementsByTagName("div").length;
} catch (e) {
count = 0;
}
I notice you're using jQuery but not using it in that code. Which is too bad, because if you were, jQuery's set-based nature would mean you didn't need the guard:
var container_element = $('#unique-id');
var count = container_element.find("div").length;
Even though container_element is an empty set, you can call methods on it. Most jQuery methods provide intelligent handling of empty sets. For instance, using find on an empty set returns a (new) empty set, as above.
You still have the option to know whether the element exists (more in this question's answers):
if (container_element[0])
// or
if (container_element.length)

Function stored in a global variable doesn't run when called

I'm a noob and also new to this site, so let me know if there are things I should do to improve this post. Anyway, I have a function that is re-used frequently in my site, so I stored it in a global variable and want to call it when a certain button is clicked.
The code looks like this (see below). My problem is that although I can confirm that the button click tries to call the function, it is clearly never actually called (none of my alerts fire and the changes to the text fields are not saved). All of this is contained in the $(document).read(function...
Have I made a dumb mistake somewhere, or is there something I'm doing clearly wrong?
$(document).ready(function () {
//Description:
//Global wrapper variable that contains all global functions. These include:
// 1. saveAll: Saves all values not stored in session data to hidden fields - this includes
// all added ingredient information. This allows us to manually pass values between
// client and server to save to db and also means we can eliminate Null values in table
// storage using a manual delimiter.
//----------------------------------------------------------------------------------------------
var Global = (function () {
return {
saveAll: function () {
alert("entering save");
//start by creating an array and initializing the length of the for loop
var saveValues = [];
var numVals = $('#HidRowCt').val();
alert("numVals: " + numVals);
//Now loop through each ingredient row and create a string containing all textbox values
//in this case, we'll do so by creating an array and then combining the values with a custom delimiter
//the strings will then be saved, one by one, into the saveValues array, which will be serialized as a JSON object,
//stored in a hidden field, and passed to the server
for (i = 1; i < numVals; i++) {
var TxtIngName = $('#TxtIngName' + i).val();
var TxtIngNumUnits = $('#TxtIngNumUnits' + i).val();
var SelIngUnits = $('#SelIngUnits' + i).val();
//make temporary array and string
var saveArr = new Array(TxtIngName, TxtIngNumUnits, SelIngUnits);
var saveStr = saveArr.join("-||-");
saveValues.push(saveStr);
}
alert("Save Values: " + saveValues);
//this will automatically escape quotes, delimited with ","
var jsoncvt = JSON.stringify(saveValues);
$("#HidSave").val(jsoncvt);
}
};
});
//----------------------------------------------------------------------------------------------
//Description:
//Hijack the click event for the save button. Saves values not saved in session data.
//
//Functions:
// Global.saveAll()
//----------------------------------------------------------------------------------------------
$("#SaveChanges").data.clickEvent = $("#SaveChanges").attr('onClick'); //save onclick event locally
$("#SaveChanges").removeAttr('onClick'); //and remove the onclick event
$('#SaveChanges').on('click', function (event) {
Global.saveAll();
//eval($("#SaveChanges").data.clickEvent); //now go ahead with the click event
});
Well, I never figured out why this didn't work, but....
I just removed the global variable and created a separate function for saveAll() and it works. Interestingly, I have a second application using the same code that uses the Global.saveAll (with the same innards) and works fine, so I must have something unusual in one of my earlier lines.
Thanks for your suggestions!
Try setting window.Global = ..., since declaring var Global sets the scope to be within the ready closure.
Then you should be able to use it later.
I just removed the global variable and created a separate function for saveAll() and it works.

How to use a jQuery variable that was just made inside a namespace?

I created a namespace to hold variables so that 2 different functions could use them. My first variable uses jQuery and works fine. The second tries to use the variable established in the previous line and fails. It's undefined.
example:
varHolder = {
buildStep4: $('#buildStep4'),
jetSpan: buildStep4.find('#jetSpan')
};
Is there a way to do this properly?
You can capture the value, but use a function to keep it scoped so it doesn't exist after you've created your object.
varHolder = (function() {
var buildStep4 = $('#buildStep4');
return {
buildStep4: buildStep4,
jetSpan: buildStep4.find('#jetSpan')
}
})();
You could also build your object piecemeal:
varHolder = {};
varHolder.buildStep4 = $('#buildStep4');
varHolder.jetSpan = varHolder.buildStep4.find('#jetSpan');
Ids can't be duplicated inside a valid HTML document so it make no sense to provide context to an id selector, you can simply do
jetSpan: $('#jetSpan')

jQuery data() with multiple parameters?

I want to add data variables to an element before causing a specific behavior, but this may require adding more than one data parameter. How can I accomplish this?
$("#dlg_box").data("r_redirect","index.php").dialog("open");
You can do it like this:
var data = $("#dlg_box").data();
data.r_redirect = "index.php";
data.foo = "bar";
$("#dlg_box").dialog("open");
This was taken from here.
To retrieve your values:
$("#dlg_box").data("r_redirect");
$("#dlg_box").data("foo");
JQuery's data() method also takes an JS Object as a parameter. So you might think of passing {"r_redirect": "index.php", "whatEver": "youWant" ...} etc to pass multiple values match your requirement.
Ultimately, the data() method converts your parameters into an Object. So whether you pass an Object or Key and Value separately should not matter
There are different ways to attach data to a jQuery dialog. If you need to attach multiple Data, I recomend using .data("myData", { /* OBJECT */ }, however you can also use inline string and array data. As far as why yours won't work, with so little code to go on, it could be numerous things. However, I've attached a working example of a Dialog with "params" or data for you to take example from. If you post more of your header code tho, I have a feeling we might find a syntax error or a lack of "doc ready" included. Just some thoughts. Anyway, my example:
jsFiddle
$(function() {
// Set the dialog to not open on load and clear all changes made when closed
$("#dlg").dialog({
autoOpen: false,
modal: true,
close: function(e) {
$(this).children("input").nextAll("p").remove();
}
}) // next i call for my first inner button which will show you how to get "attached" data
.children("#attached").on("click", function(e) {
var dlgData = $("#dlg").data("myData");
$(this).after($("<p />").text(dlgData.data1 + " " + dlgData.data2));
}) // finally, the button that will get the string data that was added in the HTML
.next("#inline").on("click", function(e) {
var dlgData = $("#dlg").data("inline");
$(this).after($("<p />").text(dlgData));
});
// simply open our dialog
$("button").on("click", function(e) {
// HERE data is ATTCHED to our dialog just before opening
$("#dlg").data("myData", { data1: "Hello", data2: "world" }).dialog("open")
});
});
$('#Dialog').data('data1', data1).data('data2', data2).dialog('open');
While Initializing the dialog get the values following:
var data1 = $(this).data('data1');
var data2 = $(this).data('data2');
There are some rules you should be aware of before using this!
ADDING
Adding variables using the object returned from $('.selector').data() works because the data object passes by reference, so anywhere you add a property, it gets added. If you call data() on another element, it gets changed. It is what it is what it is...
Adding an object places a object inside of the data object, as well as "extends the data previously stored with that element." - http://api.jquery.com/data/#entry-longdesc
That means that adding an obj to dataObj becomes
dataObj === { /*previous data*/, obj : { } }
Adding an array does not extend the data previously stored, but doesn't behave the same as a simple value either...
USING
If you have simple values stored, you can place them into variables and do what you want with them without changing the data object.
however
if you are using an object or array to store data on an element, beware!
Just because you store it to a variable does not mean you are not changing data value.
Just because you pass it to a function does not mean you are not changing data values!
It is what it is what it is.. unless it's simple.. then it's just a copy. :p
var data = $("#id").data(); // Get a reference to the data object
data.r_redirect = "index.php"; // Add a string value
data.num = 0; // Add a integer value
data.arr = [0,1,2]; // Add an array
data.obj = { a : "b" }; // Add an object
// but here is where the fun starts!
var r_redirectString = data.r_redirect; // returns "index.php", as expected.. cool
r_redirectString = "changed" // change the value and the compare :
data.r_redirect == r_redirectString // returns false, the values are different
var oArr = data.arr; // Now lets copy this array
oArr.push(3); // and modify it.
data.arr == oArr // should be false? Nope. returns true.
// arrays are passed by reference.
// but..
var oObj = data.obj // what about objects?
oObj["key"] = "value"; // modify the variable and
data.obj["key"] == oObj["key"] // it returns true, too!
So, resources..
What's the best way to store multiple values for jQuery's $.data()?
https://stackoverflow.com/a/5759883/1257652

Javascript class initialization and jQuery DOM in memory

Which is the best way between:
var myClass = function() {
this.myContainer = function(){ return $(".container");}
this.mySubContainer = function(){ return this.myContainer().find(".sub"); }
}
AND
var myClass = function() {
this.myContainer = $(".container");
this.mySubContainer = this.myContainer.find(".sub");
}
Is there any concrete differences?
The memory problem arose when I have seen that my web page, that has enough javascript ( about 150KB of mine + libs ) takes more then 300-400MB of RAM. I'm trying to find out the problem and I don't know if this could be one of them.
function myClass{
this.myContainer = function(){ return $(".container");}
this.mySubContainer = function(){ return this.myContainer().find(".sub"); }
}
Here you will need to call it something like myClassInstance.myContainer() and that means jquery will search for .container element(s) any time you are using that function. Plus, it will create 2 additional closures any time you will create new instance of your class. And that will take some additional memory.
function myClass{
this.myContainer = $(".container");
this.mySubContainer = this.myContainer.find(".sub");
}
Here you will have myContainer pointing to an object which already contains all links to DOM nodes. jQuery will not search DOM any time you use myClassInstance.myContainer
So, second approach is better if you do not want to slow down your app. But first approach could be usefull if your DOM is frequently modified. But I do not beleave you have it modified so frequently that you may need to use second approach.
If there is a single variable you are trying to assign , then the second approach looks cleaner..
Yes they are different.
MODEL 1:
In the first model, myContainer is a function variable.It does not contain the jQuery object.You cannot call any of jQuery's methods on the objet. To actually get the jQuery object you will have to say
var obj = this.myContainer() or this.myContainer.call()
MODEL 2:
The second model stores the actual jQuery object.
try alerting this.myContainer in both models, u will seee the difference.
Yes this is different. after you fix your syntax error :
function myClass(){... // the parentheses
1st
When you create a new object var obj = new myClass(), you are creating two functions, and the jquery object is not returned until you call it
var container = obj.myContainer();
2nd
As soon as the object is initialized the dom is accessed and you have your objects cached for later use;
var container = obj.myContainer;

Categories