Can a variable be passed as an element id in javascript - javascript

I'm trying to get some AJAX running with Django using jQuery. The problem is that the ID of the element I'm trying to change isn't set in stone, it's a Django template variable so it is different for each element in the table, but I want to use AJAX to change that element. I'm passing the dictionary from a Django view to JavaScript via simplejson, the pertinent objects being ID and model (not real variable names, just wanted to make it obvious what I am trying to do). Some pseudo code (third line, wrote it like python because I don't know how to do this in JavaScript):
var quantity_update = function(msg, elem) {
var response_obj = eval('(' + msg + ')');
var newtotal = document.getElementById("%s, %s"); % (response_obj.id, response_obj.model)
subtotal.innerHTML = "<td>"+response_obj.subtotal+"</td>";
Is something like this possible, and if so how?

Javascript doesn't have fancy string formatting (%s), but you can use plain string concatenation, just like you can in Python:
var id = response_obj.id + ', ' + resonse_obj.model
You don't need to worry about the string being generated dinamically. It is still a string after all and getElementById accepts it the same way .
You probably shouldn't be doing the eval() yourself to parse the JSON. I'm pretty sure you can have JQuery do that for you when you do the AJAX request.

If your element ID is not set in stone, you might want to identify the element using other means. Many JS framework such as jQuery supports identification via CSS Selector. For example you can identify the element you want to change by combination of its tag and class.
For documentation on the available selector you should read jQuery Selector Documentation

You can totally pass jquery css selectors as variables. Simple example:
var elementId = $('td').eq(0).attr('id'),
myElement = $('#'+elementId);
In this example, we grab the ID of the first TD in your document, find its id, and use that to get "myElement"
You may find it helpful to review the "selectors" section of the jQuery documentation (api.jquery.com) to review all your options for finding an element. In my example I also am using the jquery.eq() method, which filters a list of selectors (in this case all the TDs) to a specific one.

Related

How to get element from HTML stored in variable

I am running an API to retrieve email from external system. I managed to get HTML code from the returned JSON and store it in a variable. Now, I would like to run some further operations on this HTML - for example get all elements with
[data-type="whatever"].
It would be easy in html document:
var x = document.querySelectorAll('[data-type="whatever"]');
However the HTML document I want to work with is stored in the variable so the code I write in API does not recognise it as a document. How can I do it? Any suggestions with vanilla JS?
You can try something like this.
let rawDoc = '<html><head><title>Working with elements</title></head><body><div id="div1">The text above has been created dynamically.</div></body></html>'
let doc = document.createElement('html');
doc.innerHTML = rawDoc;
let div1 = doc.querySelector('#div1');
console.log(div1)
What if you use innerHTML? or maybe I don't fully understand the question.
Since you are working without a document you have 2 options.
1. Use regex to get what you need (something like /<.+>.+ data-type="whatever".+<\/.+>/gi) should do (but for an exact match you may need to make something better).
2. Insert the html in a hidden part of the dom and select what you need from it (like in Zohir answer - he provided a good example).
I used following code with angular to store whole html content in a variable and pass it as argument to call API.
var htmlBody = $('<div/>').append($('#htmlBody').clone()).html();
This might work for you as i was working on sending email to pass invoice template so try this.

textContent returns undefined

I have a table in which I want to extract the text of the active item. I do this with the following code:
var addedWorkout = $("#custDropDownMenuA").find(".dropdown-item.active");
console.log(addedWorkout);
addedWorkout = addedWorkout.textContent;
console.log(addedWorkout);
The problem is that I keep getting undefined. I checked the console and it indeed finds the element I want without fail.
I am relatively new to Javascript, but after over an hour of Googling I could not find the issue and I don't understand why. I know that I can get the text element if I hardcore it using the following line:
document.querySelector("#selectiona1").textContent
but not with:
$("#selectiona1").textContent
What is the difference between these 2? I read that textContent is part of the DOM, to my understanding it relates to objects and according to my console i think it is an object. I made some crazy attempts like putting the object I got into the querySelector, but nothing works.
With this line:
var addedWorkout = $("#custDropDownMenuA").find(".dropdown-item.active");
you're using jQuery to select the .dropdown-item.active inside #custDropDownMenuA, and when you select with jQuery, you get a jQuery object in response. So, addedWorkout is a jQuery object, and jQuery objects generally do not have the same properties/methods as standard HTMLElements. (querySelector is the vanilla Javascript method to retrieve an element)
Either select the [0]th item in the jQuery collection to get to the first matching element:
var addedWorkout = $("#custDropDownMenuA").find(".dropdown-item.active")[0];
Or use the jQuery method to get the text of the first matching element, which is .text():
var addedWorkoutText = addedWorkout.text();
(note the use of a new variable - you will likely find it easier to read and debug code when you create new variables rather than reassigning old ones, when possible)
Your var 'addedWorkout' is a Jquery object, not a html element.
To show the text use:
addedWorkout.text();
Alternatively, you can change the 'addedWorkout' to a html element by adding the index [0], like this:
addedWorkout[0].textContent;

jQuery single line code optmization for getting and setting for the same input element

I'm using PHPStorm and have the following js code
$('#id'.val($('#id'.attr('default'));
The idea is to reset the value of a input field to it's default which is set in default attribute of the input element.
Now the IDE is suggesting me to avoid duplicate selectors.
Though it is working I'm interested in finding out what is the best way to optimize this code line?
Not exactly what you asked for but more future proof using data and not an attribute. You could even store complex data or other information in there as well like "originalvalue" or "lastchangedvalue" etc.
Storing in an attribute is fine however I prefer to store things like this in the data of the element like:
<myelementtag id="myid" data-defaultvalue="defaultvalue" />
You then access it like:
$('#myid').data("defaultvalue");
For example:
var myElement = $('#myid');
myElement.value = myElement.data('defaultvalue');
Want to reset the default?
var mynewdefault = "mynewvalue";
myElement.data('defaultvalue', mynewdefault);
Since you asked only one selector and one line code, please use like this as stated in jQuery documentation (middle section):
$("#id").val(function(index,value) {
return $(this).attr('default');
});
or if you want to avoid $(this):
$("#id").val(function (index, value) {
return this.getAttribute('default');
});
JSFiddle
And yes, as other members have pointed out, it would be better if you use data attribute (data-defaultValue) instead.
This is a more compact solution:
var id = $('#id');
id.val(id.attr('default'));
You really don't need to use $(...) every time.
Store your jQuery element in a variable:
var $id = $('#id');
$id.val($id.attr('default'));

Use dynamic element ID in #{rich:clientId()} function

We can get element by static ID using rich:clientId() function as follows
document.getElementById('#{rich:clientId(JSF_ID)}').click();
However, I need to use a dynamic ID which takes the form of var + "_ID" where var can be employee, student, etc and thus resulting in employee_ID, student_ID as actual ID.
I tried as follows:
dynamicID = var + '_ID';
document.getElementById('#{rich:clientId(dynamicID)}').click();
However, it didn't work. How can I achieve this?
It looks like you are setting dynamicID via JavaScript, am I right?
If yes, the EL-expression #{rich:clientId(dynamicID)} cannot be evaluated as EL on the server during the rendering of the page since the dynamicID is only available on the client (=browser) when the page has already been built up on the server and sent to the browser.
Where does var come from? How is it applied to the component with the dynamicID? Can't you use the same approach for the getElementById?
For concatenating a variable with a constant in JSF on server-side, see the following already answered post Concatenate strings in JSF/JSP EL and Javascript. Basically it gives you a how-to in creation of an own concatenation function for jsp/jsf. Works pretty need.
As a hint: you can use #{rich:element(JSF_ID)} instead of document.getElementById('#{rich:clientId(JSF_ID)}') to keep the source readeable - it will render identical results.
Good luck...

Can JQuery and Javascript be mixed together?

I am wondering if I could use query and javascript together so I could select an element by class with the javascript and then use javascript to work on that element. Sorry if that didn't make sense. Here is an example:
$('.nav_flag').src = "images/flags/"+userCountryLower+".gif";
Would that work, if not how do I get an element by class using regular javascript. Thanks!
EDIT:I know JQUERY is JavaScript but I was wondering if I could mix jquery selectors and javascript 'controller'-for a loss of a better word
To answer your question as asked, there are several ways to take a jQuery object, i.e., what is returned by $('some selector'), and get a reference to the underlying DOM element(s).
You can access the individual DOM elements like array elements:
// update the src of the first matching element:
$(".nav_flag")[0].src = "images/flags/"+userCountryLower+".gif";
// if you're going to access more than one you should cache the jQuery object in
// a variable, not keep selecting the same thing via the $() function:
var navFlgEls = $(".nav_flag");
for (var i = 0; i < navFlgEls.length; i++) { ... }
But you wouldn't manually loop through the elements when you can use jQuery's .each() method, noting that within the callback function you provide this will be set to the current DOM element:
$(".nav_flag").each(function() {
this.src = "images/flags/"+userCountryLower+".gif";
});
However, jQuery provides a way to set attributes with one line of code:
$(".nav_flag").attr("src", "images/flags/"+userCountryLower+".gif");
To answer the second part of your question, doing the same thing without jQuery, you can use .getElementsByClassname() or .querySelectorAll() if you don't care about supporting older browsers.
jQuery IS Javascript. You can mix and match them together. But you better know what you're doing.
In this case, you probably want to use .attr function to set value of attribute.
Use .attr() in jQuery, rather than mix the two here.
$('.nav_flag').attr('src', "images/flags/"+userCountryLower+".gif");
In many instances, it is fine to mix jQuery with plain JavaScript, but if you have already included the jQuery library, you might as well make use of it. Unless, that is, you have an operation which in jQuery would be more computationally expensive than the same operation in plain JavaScript.
You can do it with jQuery too:
$('.nav_flag').attr("src", "images/flags/"+userCountryLower+".gif");
keep in mind that jQuery is simply a library built upon javascript.
for any jQuery object, selecting its elements by subscription will return the corresponding dom element.
e.g.
$('#foo')[0] // is equivalent to document.getElementById('foo');
You need to add an index to the jQuery object to get the native Javascript object. Change:
$('.nav_flag').src = "images/flags/"+userCountryLower+".gif";
To:
$('.nav_flag')[0].src = "images/flags/"+userCountryLower+".gif";
To get elements by class name in Javascript you can use:
document.getElementsByClassName( 'nav_flag' )[0].src = "images/flags/"+userCountryLower+".gif";
To answer your question, you could use .toArray() to convert the jQuery object into an array of standard DOM elements. Then either get the first element or loop through the array to set all the elements with the class.
However, you could do this easier with pure jquery with attr or prop depending on the version:
$('.nav_flag').attr("src", "images/flags/"+userCountryLower+".gif");
Or use pure javascript:
if (navFlagElements = document.getElementsByClassName("nav_flag") && navFlagElements.length > 0) {
navFlagElements[0].src = "images/flags/"+userCountryLower+".gif"
}

Categories

Resources