Storing Jquery reference - javascript

Is it possible to store the reference to an element in an array or object without having a unique ID on the element?
I am having trouble with storing a subtable in another table so I can reference it later. I get the table by class with this code:
$(this).parent('tr').parent().find('.tableSomeTable');
Is the only solution to have unique id's on each element and use the .selector method?
More of my code. Abit simplified.
var rows = [];
var historyLoad;
$(document).on("click", '.details-control', function (e) {
var t = $(this);
var tr = t.closest('tr');
var row = t.parent().parent().parent().DataTable().row(tr);
var id = t.closest('tr').attr('id');
var object = {
id: id,
btnHistory: t.parent('tr').next().find('#btnHistory'),
tblHistory: t.parent('tr').parent().find('.tableHistory'),
historyLoad: historyLoad
};
if ($.inArray(id, rows) > -1) {
loadData = false;
}
else {
loadData = true;
loadHistory(object);
rows.push(object);
}
};
Here is where I am having trouble retrieving the correct elements. And I also want to save the ajaxHistory element to my object (which is working fine).
This code is not working, but if I change it to $(result.btnHistory.btnHistory.selector) I get the object. But this doesn't seem to work very good with multiple rows.
function loadHistory(result) {
result.ajaxHistory = $.ajax({
...
beforeSend: function () {
$(result.btnHistory).html(<loading txt>);
$(result.tblHistory).find('tbody').html(<loading txt>);
},
....
success: function (data) {
if (data.TotalRecordCount > 0) {
$(result.tblHistory).find('tbody').html('');
$.each(data.Records, function (e, o) {
$(result.tblHistory).find('tbody').append(<data>)
});
}
else {
$(result.tblHistory).find('tbody').html(<txt no records>);
}
$(result.btnHistory).html(<txt loading done>));
},

First off, if you are trying to find the parent table, try
var $myObj = $(this).closest('table.tableSomeTable');
instead of navigating parents.
As far as storing the jQuery reference, define a variable and then store it. The above will store the object in $myObj but that is locally scoped. If you need a global variable then define it globally and just assign it here. If you want to define it as a property within an object then define it that way. It really comes down to a scope question at this point.
EDIT: Just saw your added content.
First off, don't name it 'object'. This may run into key word issues. Use var myObj or similar instead. Next, object.btnHistory is a reference to a jQuery object. So, when you pass it to loadHistory, you do not need to apply the $(...) again. Just use the reference directly: result.btnHistory.html(...). A good habit to get into is prepending you jQuery variables with $ so you remember it is already a jQuery variable.

The .find() method returns a jQuery object. So the answer is, yes, you can store this return object in a variable:
var $yourObject = $(this).parent('tr').parent().find('.tableSomeTable');

Related

efficiently creating variables when a checkbox is checked and using these variables later in the code

below is the information I need help with.
$(document).ready(function(){
$('.checkboxes :checkbox').click(function(){
if($(this).is(':checked')){
console.log(this.id + this.checked)
i want to set a variable with the samename of the id of the checked box
so if showItems was checked i would have a variable
var showItems = true;
I want this so I could see if showItems is checked which would alow me to perform the proper functions
i think i could do something like this
if($this.id = "withones"){
var withones = true;//on
}
if($this.id = "withoutOnes"){
var withoutOnes = true;//on
}
etc.
i feel like the above is a rookie way to code. lets say i have alot of checkboxes and it also looks like im repeating myself. I tried putting the ids in an array and loop through them but I got the html element in the console when i clicked on the box. I would like for someone to tell me if there is a more efficient way to set up these variables. and if so show me please.
Also I'm new to programming so thanks for your help so far. but I was also thinking about another problem. if I set up these variables here and I want to set up another function somewhere else to perform mathematical operations perse. i want that function to be able to evaluate the value of the withones and withoutOnes variables so I would like to do something like this in the function
function add(){
if(withones){ //true|| false
return 2 + 2;
}
if (withoutOnes) {
return 'blah'
};
}
I have had problems in the past trying to test the values that are set outside the function. I think i tried setting it in the arguments. but it just didn't read. If you could also show me an example of using the variables some where else in the code like discussed above that will be helpful . I forgot to mention that the value of the variable will change when the user clicks on the box. either to true or false. I think my problem in the past is that when the box is checked and then uncheck I had a problem changing the variable especially when it is being used in a separate function
}
});
});
You can have an object with your vars and add vars to that object dinamically:
var oVars = {}
// adding a var
oVars[nameVar] = valueVar
// accessing the var
oVars[nameVar]
You can capture the id with the attr() or you can just change the value of the checkbox with val() method in jQuery like this: FIDDLE
$(document).ready(function () {
$('.checkboxes').change(function (event) {
if ($(this).is(':checked')) {
var captureId = $(this).attr('id');
$(this).val(true);
alert($(this).val());
}
else {$(this).val(false);
alert($(this).val());}
});
});
Note that you can evaluate later all the checkboxes with one button and collect the value false or true from them. Why would you go through all of the complications with changing values of variables.
The other two answers are correct, though it sounds like you're wanting to know generally how to manage a big list of checkboxes with differing methods depending on type. It could look like this:
function multiply(this_object){
if((this_object.is(':checked')) && (this_object.attr("with") == 1))
return "with withone and checked";
else
return "is not both";
}
$(document).ready(function(){
$('.checkboxes').click(function(){
var this_object = $(this);
alert(multiply(this_object));
});
});
There should be no need to store all of the values in a variable unless you are passing all of them to another page - eg., via AJAX. Just reference them straight from the source field. If you need other info stored alongside, make a new attribute on the field - like the "with" one that I made for this example. See this Fiddle: http://jsfiddle.net/6ug6gL97/
your question is quite broad; so I’ll try to do my best to give you some kind of answer. First of all I’d use variables of global scope when declaring variables: withones and withoutOnes. Secondly, you wanted to avoid repetition in your code. Well, for that purpose I’d use JavaScript Arrays. In an array, you can add your variables as objects. In an object you can have your ids and other data “packed” neatly in the array, which in turn helps your code to become efficient.
Below is an array with objects:
objectArray = [{
id: "withones",
checked: false,
method: function () {
return 2 + 2;
}
}, {
id: "withoutOnes",
checked: false,
method: function () {
return 'blah';
}
}];
The above array can be used in your $('.checkboxes :checkbox').click(function() handler and add() function to avoid repetition. The updated code is below where jQuery's each() method is used for looping Array elements.
The last a bit of your question was related to add() function. Well, this was the tricky bit of your question, and I tried to use a callback function hopefully in the right way to execute your functions from the array. In the add method I tried to follow this answer: https://stackoverflow.com/a/13343452/2048391
About the last bit I’m not 100% sure did I use a callback function in the right way; so I hope someone more familiar with these tricky JavaScript functions can correct me, if something needs to be changed –thanks.
objectArray = [{
id: "withones",
checked: false,
method: function () {
return 2 + 2;
}
}, {
id: "withoutOnes",
checked: false,
method: function () {
return 'blah';
}
}];
$(document).ready(function () {
$('.checkboxes :checkbox').click(function () {
var id = this.id;
var checkedValue = this.checked;
$.each(objectArray, function (index, object) {
if (object.id === id) {
object.checked = checkedValue;
}
});
add();
});
function add() {
// clear results
$("#addResults").text("");
$.each(objectArray, function (index, object) {
if (object.checked === true) {
var returnValue = createCallback(object.method)
$("#addResults").append(returnValue + "<br>");
console.log(returnValue);
}
});
}
function createCallback(method) {
return method();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="checkboxes">
<input type="checkbox" id="withones"></input>
<label>With Ones</label>
<br>
<input type="checkbox" id="withoutOnes"></input>
<label>Without Ones</label>
</div>
<div id="addResults">
</div>

Getting "This" into a namespace in Javascript

I'm sure this should be a simple question but I'm still learning so here it goes:
I have some code to run a function on click to assign the clicked element's ID to a variable but I don't know how to pass the "this.id" value to the namespace without making a global variable (which I thought was bad).
<script>
fsa = (function() {
function GetTemplateLoc() {
templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc();
});
</script>
and HTML with random picture:
<img id="template-1" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
<img id="template-2" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
The following would work:
var fsa = (function() {
function GetTemplateLoc() {
var templateId = this.id;
alert(templateId);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', fsa.GetTemplateLoc);
jQuery generally calls functions you pass as event handlers with this set to the DOM object the event is associated with.
In this case it will call GetTemplateLoc() with this set to either .template element, so you can use this directly in the function and don't need to pass any parameters.
Important tip: Always declare variables using var. JavaScript has no automatic function-local scope for variables, i.e. every variable declared without var is global, no matter where you declare it. In other words, forgetting var counts as a bug.
Try this : You can directly use this.id to pass id of the clicked element where this refers to the instance of clicked element.
<script>
fsa = (function() {
function GetTemplateLoc(templateId ) {
//templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc(this.id);
});
</script>
If you're able to use jQuery within the GetTemplateLoc function, you could do something like this:
var fsa = (function() {
function GetTemplateLoc($trigger) {
var templateId = $trigger.attr('id'),
templateId2 = $($trigger.siblings('.template')[0]).attr('id');
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc($(this));
});
You can set GetTemplateLoc to expect a jQuery object as a parameter (the dollar sign at the beginning of $trigger can be used to distinguish it as a jQuery object rather than any other data type, it's not necessary but can help clarify things sometimes).
templateId will store the value of the clicked image's ID, and templateId2 will store the value of the other image's ID. I also added a space between the two variables in the alert.
If you can't use jQuery within GetTemplateLoc, you could do something like this:
var fsa = (function() {
function GetTemplateLoc(trigger) {
var templateId = trigger.id;
var templateId2 = trigger.nextElementSibling == null ? trigger.previousElementSibling.id : trigger.nextElementSibling.id;
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
This time, the .template that triggered the event is passed into GetTemplateLoc, but this time it's not a jQuery object. templateId is assigned to the trigger's ID and then templateId2 is assigned in a ternary. First, the nextElementSibling of trigger is checked to see if it's null. If it is, we know that trigger is the second of the two .template elements. Therefore we can set templateId2 to the ID of trigger's previous sibling. If trigger's nextElementSibling is not null, then we know that trigger is the first template and we populate templateId2 with the ID of nextElementSibling. This exact method will only work with two .template's, if there are more you'll need some additional/different logic, probably to retrieve all .template IDs and then loop through them to add them to the alert message. Hope this helps.

'alert' an object property on click

I have a constructor which I then make the object library_science1 with:
function librarytech(humanity,food,wood,metal,wealth)
{
this.humanity=humanity;
this.food=food;
this.wood=wood;
this.metal=metal;
this.wealth=wealth;
}
var library_science1=new librarytech(0,200,200,0,0);
I have this as a click function:
$("[id^='library_']").click(function() {
var idd = this.id;
alert(idd);
});
where the html is simply
<span id='library_science1'></span>
The code above works fine, alerting 'library_science1' nicely... it even works when I use the alert to directly pull one of the objects properties.
$("[id^='library_']").click(function() {
alert(library_science1.food);
});
But I have many library_[SOMETHING] objects, corresponding each to there own
<span id="library_[SOMETHING]"></span> line.
I'm trying to pull the objects properties depending on which one is clicked. Such as:
$("[id^='library_']").click(function() {
alert(this.id.food);
});
or
$("[id^='library_']").click(function() {
var x = this.id;
alert(x.food);
});
The end purpose being that I can ultimately do things like:
foodamount -= this.id.food
Why isn't this working :/ :(
simply because you are accessing an object in your first example and not a DOM object as in other, if their obejtos are global so you can access
alert(window[this.id].food);
or
alert(eval(this.id + ".food"));
I made a test here using eval() and this works:
$("[id^='library_']").click(function() {
alert(eval(this.id).food);
});
$("[id^='library_']").click(function() {
var x = eval(this.id);
alert(x.food);
});

Bind Javascript Objects to HTML elements

I just want to share an experience with you all. So my problem was, that I came across the problem of binding javascript back-end objects to HTML front-end elements. Now, i have searched through google and read some stackoverflow articles about this problem, and many posts answer to this is to use jQuery.data(), however in my first attempts I did not succeed because there was something I did not know about jQuery's object creation method. My problem was that, I wanted to retrieve the stored data outside of the scope where i stored this, and jQuery always(i think) returns a new object reference when i write jQuery('selectorID'). So for example:
var ref1 = $('#myID');
var ref2 = $('#myID');
if(ref1 == ref2)
{
alert(true);
}
else
{
alert(false);
}
Will always alert false. However replacing the jQuery method with javascript's built-in getElementById() we will get the same reference! Hence the following code will always alert true!
var ref1 = document.getElementById("myID");
var ref2 = document.getElementById("myID");
if(ref1 == ref2)
{
alert(true);
}
else
{
alert(false);
}
The little morale of my story is that if you want to globally bind javascript objects to HTML elements and are thinking about using jQuery's data() method, store the data on the reference returned by javascript's built-in getElementById(). That way, whereever you retrieve the reference with getElementByID, you will always get the same reference and can get the data from it using jQuery's data() method.
My Questions:
Is my logic of thinking ok?
Is there a better way to globally bind javascript objects to HTML elements?
Whatever the reason behind the code you mention not working was, it was decidedly not the fact that jQuery gives you a new collection for every query. Given the HTML:
<div id="somediv"> foo bar </div>
the following Javascript works as expected:
var $ref1 = $('#somediv');
var $ref2 = $('#somediv');
console.log("$ref1:", $ref1);
console.log("$ref2:", $ref2);
// compare the collections / references
console.log("$ref1 == $ref2:", $ref1 == $ref2); // => false
console.log("$ref1 === $ref2", $ref1 === $ref2); // => false
// compare the referred DOM elements themselves
console.log("$ref1[0] == $ref2[0]:", $ref1[0] == $ref2[0]); // => true
console.log("$ref1[0] === $ref2[0]", $ref1[0] === $ref2[0]); // => true
$ref1.data('somedata', 'SOMEDATA');
console.log('$ref1->somedata:', $ref1.data('somedata')); // => SOMEDATA
console.log('$ref2->somedata:', $ref2.data('somedata')); // => SOMEDATA
The way I do it is something like this.
var ref1 = $('a');
var ref2 = $('div');
var equal = ref1.length === ref2.length;
if (equal) {
$.each(ref1, function(i) {
equal = equal && ref1[i] === ref2[i];
if (!equal) {
return false;
}
});
}
if (equal) {
alert(true);
} else {
alert(false);
}
ref1[0] === ref2[0] // Should return true
I think jQuery's instances are unique, so you can compare its matched items, which should be just one element when you reference an ID.
You could do something like this:
var ref1 = $('#myID')[0];
var ref2 = $('#myID')[0];
I dive into jQuery's source code, and find the constructor of jQuery. As follow:
// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
}
Whenever you use ref2 = $('#myID') to retrive a corresponding jQuery element, jQuery will create a new object to you. So the == will return false to you coz' the two element is completely different to js object engine.
Seems getElementById method is more fit your need. But I don't know how js engine perform its getElementById method.

jQuery global selection "cache"

I don't think I'm the first one to run into this issue but I haven't find a way to search for this without getting results that have nothing to do with the issue.
I adopted the not so extended good practice of "caching" repetitive jQuery selections into vars like var element = $('#element'); to prevent "DOM pool searching" for every repeated use of the element
The problem I'm having is that now I'm doing this caching inside a function. Something like:
function functionname (id) {
var id = $('#'+id);
//extra stuff
}
I'm not expert in variables scopes but I'm not being able to do
functionname ('some-div-id');
some-div-id.dialog('open');
So I'm pretty sure it's because the variable created inside the function is not accesible outside the function itself.
Then I came up with
function functionname (id) {
window.id = $('#'+id);
//extra stuff
}
but if I try to do window.some-div-id.dialog('open'); I get TypeError: 'undefined' is not a function
What am I missing? I'm sure it's a small dumb thing but I'm missing it just in front of my eyes.
Thanks
EDIT
Thanks everyone but you're missing something.
The code suggestions are missing the fact that the inside "global" variable name is dynamic:
var CACHEobject = {};
function doSomething (NAMEHERE) { //note the function parameter
CACHEobject.NAMEHERE = $('#'+NAMEHERE);
}
So the idea is that the function creates a javascript variable with the same name that the #element_id. If I pass a name to the function it should select the html id with that name and "cache it" to a global variable with the same name:
doSomething('myDialogOne'); doSomething('myDialogTwo');
so I can later do
CACHEobject.myDialogOne.dialog('open'); CACHEobject.myBox.dialog('close');
This is what you want (based off the edit):
var CACHEobject = {};
function doSomething(id) {
CACHEobject[id] = $('#' + id);
}
Your idea is fine. Just set up an object for that. Here's an example using STASH as the caching object:
<html>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
var STASH = {};
$(document).ready(function(){
// stash your elements
STASH.item = $('#item');
STASH.otherItem = $('#otherItem');
// do stuff to them
STASH.item.css({
color: '#f00'
}); // sets #item to red
alert(STASH.otherItem.text()); // alerts foo
});
</script>
<style></style>
<body>
<div id="item">bar</div>
<div id="otherItem">foo</div>
</body>
</html>
window.some-div-id.dialog('open');
is interpreted as:
window.some - div - id.dialog('open');
i.e. subtracting, which causes three undefined variables, one of which is id.dialog which causes an error when trying to be executed as a function.
For special characters, use:
window["some-div-id"].dialog('open');
And to define:
window[id] = $("#" + id);
Anyhow, I would not advise you to use global variables. You'd better overwrite the jQuery function to implement caching (using an object with the selector as key and the matched element as value).
You could just declare the variable outside the function.
var $foo;
function some_function(id) {
$foo = $('#' + id);
}
function setDialog(selector) {
window.$dialogElem = $(selector);
//window.dialogSelector = selector;
}
var id= 'mensajes';
setDialog('#'+id);
window.$dialogElem.dialog();
//$(window.dialogSelector).dialog();
commented stuff is an alternative that takes less memory. But why the hell use window?? check this fiddle for various simple techniques.

Categories

Resources