jQuery Incorporating a variable within a selector - javascript

I've tried adding a variable within the selector, but no dice. I've tried a couple of different ways.
Ex1:
function makeDerp() {
var num = 1;
$("myDiv" + num).append("<h1>derp</h1>");
}
Ex2:
function makeDerp() {
var num = 1;
var thing = $("myDiv" + num);
thing.append("<h1>derp</h1>");
}
Ex3:
function makeDerp() {
var num = 1;
var thing = "$('myDiv" + num + "')";
thing.append("<h1>derp</h1>");
}
On all 3, I get nada. Any ideas? Something with my syntax or am I missing a step?

Your first and second examples will work fine. The problem is your selector, which is currently looking for an element of type myDiv. I'm guessing you meant it to be an id selector (perhaps a class selector, or something else entirely, but the idea is the same):
$("#myDiv" + num).append("<h1>derp</h1>");
Your third example will not work. thing contains a string literal, and that won't have an append method so you'll get a TypeError.

I'm assuming you're using either a class or id selector, in which case you're missing said symbol. Try:
$('#myDiv' + num);

Related

JS/jQuery - How can I a number from an element ID and use it as a variable in functions?

Basically, I want one function to act on multiple elements individually depending on which one is clicked.
I have 3 of these functions that do the same thing:
$("#morelink1, #pic1").click(function() {
var imgHeight = $(".pic").height();
var image = $('#more1').parent('.content').siblings(
'.image');
if ($('#more1').is(":visible")) {
$("#more1").slideUp(200, "linear");
image.height(contHeight);
showtext1();
$("#closemore1").hide();
} else {
$("#more1").slideDown(200, "linear");
image.height(imgHeight);
hidebutton1();
hidetext1();
}
});
As you can see, the names of the IDs I am working with in this function all end in "1." I duplicated this function for 2 and 3.
Instead of duplicating, there must be a way to extract the number from #morelink1, make it a variable, and append the number to the ID in the function.
I'd like to have something like:
var NUMBER = [get the number from the ID of the element that was clicked];
$("#morelink + NUMBER, #pic + NUMBER").click(function() {
I also have functions built into this function - showtext1(), hidebutton1(), and hidetext1(). Those are also duplicated with just the number changed. I'd like to be able to do the same thing with those within this function. Would it be something like showtext(NUMBER)?
I have looked around and can't seem to figure out a way to do this.
Are there other ways to do this, like passing a number to the function?
Instead, just modify your selector to use the "starts with" operator instead of specifying the id completely:
$("[id^='morelink'], [id^='pic']").click(function() {
That would match every element where the id value starts with 'morelink' or 'pic', regardless of what the rest of the id is.
If you still need that value inside the click handler, you can parse it from the id of the current element.
var idString = $(this).attr('id');
// use whatever logic you define to parse the number value.
// for example, maybe a regular expression which matches only numeric characters?
If you could share your whole code, it would help. From my understanding, it should be something along these lines:
// Append click event to elements whose id starts with morelink or pic.
$('[id^="morelink"], id^=["pic"]').click(function() {
// Get id of current clicked element.
var id = $(this).attr('id');
// Use RegExp to extract number.
var number = id.match(/[\d]+/)[0];
// Your functions starting.
var imgHeight = $(".pic").height(); //should this be pic + NUMBER?
var image = $('#more' + number).parent('.content').siblings('.image');
if ($('#more' + number).is(":visible")) {
$('#more' + number).slideUp(200, "linear");
image.height(contHeight);
// Executes selectMore1(); if number = 1
window['showtext' + number]();
$("#closemore" + number).hide();
} else {
$("#more" + number).slideDown(200, "linear");
image.height(imgHeight);
// Executes hidebutton1(); if number = 1
window['hidebutton' + number]();
// Executes hidetext1(); if number = 1
window['hidetext' + number]();
}
});
However, I don't think hidebutton1() should exist, but hidebutton(number). That's why I asked for the whole code to really understand what you meant by creating multiple functions at the moment.
If you know the prefix for variable names, suffix with the number(s) you want. Then plug into the jQuery selector. I've done that before, if direct plug in like $(YourNewVariableForID) won't work, then try $("#" + eval(YourNewVariableForID)).

Can I set two different values to an element using getElementById?

Can't I use getElementById twice in javascript file? I want to use it twice because, I want to set a default value to the element with that particular id and then on calling a function i need to change the default value. Can I do this?
Have a look at my code:
function DefaultValue(){
var default = 10.23
var update = document.getElementById('idSpnRWA');
update.innerHTML = default;
}
function setValue(){
var set = 23.56;
var finalUpdate = document.getElementById('idSpnRWA');
finalUpdate.innerHTML = set;
}
I have given a very basic code to make you understand if this way is possible?
In short: yes, you can call getElementById as many times as you want.
Please note however, that default is a reserved word in JavaScript.
Also, you're forgetting to add ; after each line.
Try this (note I renamed the default variable, and added ; where needed.
HTML
<div id="idSpnRWA"></div>
JavaScript
function DefaultValue() {
var dflt = 10.23;
var update = document.getElementById('idSpnRWA');
update.innerHTML = dflt;
}
function setValue() {
var set = 23.56;
var finalUpdate = document.getElementById('idSpnRWA');
finalUpdate.innerHTML = set;
}
DefaultValue();
setValue();
Working Fiddle: http://jsfiddle.net/9e75vnm3/
Of course you can use document.getElementById many times.
But element with a specific id can be only once at your page.
Yes you can use getElementById as many time as you want.
Problem in your code is that you are adding inner html as 10.23% which is not allowed. '%' is consider as a modulo operator. if you want to display in html than you have to concat it as string
function DefaultValue() {
var update = document.getElementById('idSpnRWA');
update.innerHTML = 10.23 + '%';
}
function setValue() {
var finalUpdate = document.getElementById('idSpnRWA');
finalUpdate.innerHTML = 23.56 + '%';
}
DefaultValue();
<div id='idSpnRWA'></div>
You cannot have the same HTML id attribute more than once on a page, but you can get anything as many times as you want, as long as it's not undefined. Of course, this means you can call document.getElementById('idSpnRWA') as many times as you want. You'll want to put percentages in quotes when assigning to .innerHTML, as % is the modulo operator. Better yet, use HTML entities. Element.innerHTML = '10.23&#037';
thank you so much for answering my question. I finally found the solution. it is,
update.value= default;
finalUpdate.value = set;
innerHTML can't be used there. If i use .value, the code is actually working fine.

Using eval to assign a variable to a method. How else should I do it?

I am using a method to accept a portion of an element's ID and use that to determine which url path I need to pass to a method. In my case this is used by a click event on a button that could be attached to any one of a number of grids so I need to know which grid I am on in order to know what data to reload:
jQuery('.reset').click(function(e) {
e.preventDefault();
jQuery('#' + grid_id + '_mnf').toggle();
jQuery('#' + grid_id + '_mnfall > .instance').each(function () {
jQuery(this).removeAttr("checked");
});
var url = eval(grid_id + '_url');
jQuery('#foo').setGridParam({url:url}).trigger('reloadGrid');
});
The possible urls are defined as variables so I have something like:
var foo_url = url_path + '?input=moduleone&param=1';
var bar_url = url_path + '?input=moduleone&param=2';
This means that in the setGridParam method above the url value will be one of these vars. If I simply do:
var url = grid_id + '_url'; //note I'm not using eval here
The value passed to setGridParam will not work.
If I don't use eval like I do above the url will not work. Why? What is going on here? What else should I do since "eval is evil"?
In my mind, without using eval, I am passing the url like:
jQuery('#foo').setGridParam({url:foo_url}).trigger('reloadGrid');
but this fails so apparently eval is required here?
Because I am sure this is too rigid and clunky of a way to do this and in case anyone wants to see it (and perhaps suggest how I am doing this wrong?), here is how I am getting that grid_id:
// ex. id='foo_filter'
var source = $(this).parent().parent().attr('id').split('_');
var parsed_source = source.splice(1, source.length + 1);
grid_id_portion = '';
for (var i = 0; i < parsed_source.length; i++) {
grid_id += parsed_source[i];
if(i < parsed_source.length - 1){
grid_id += '_';
}
}
Some issues I see... I have to define the urls as variables for each grid. This is quite inflexible, yes? Those urls are pretty similar as well so defining a bunch of them seems inefficient. Also, what if someone crafts a special chunk of code to insert as the ID that I am breaking apart to pass to eval. That could be bad news, yes? Any suggestions on how to improve on this would be greatly appreciated.
Use a map to store URLs, not local variables.
var URLs = {
foo: url_path + '?input=moduleone&param=1',
bar: url_path + '?input=moduleone&param=2'
};
jQuery('.reset').click(function() {
//do stuff...
var url = URLs[grid_id];
jQuery('#foo').setGridParam({url:url}).trigger('reloadGrid');
});

Javascript Shorthand for getElementById

Is there any shorthand for the JavaScript document.getElementById? Or is there any way I can define one? It gets repetitive retyping that over and over.
var $ = function( id ) { return document.getElementById( id ); };
$( 'someID' )
Here I used $, but you can use any valid variable name.
var byId = function( id ) { return document.getElementById( id ); };
byId( 'someID' )
To save an extra character you could pollute the String prototype like this:
pollutePrototype(String, '绎', {
configurable: false, // others must fail
get: function() {
return document.getElementById(this);
},
set: function(element) {
element.id = this;
}
});
function pollutePrototype(buildIn, name, descr) {
var oldDescr = Object.getOwnPropertyDescriptor(buildIn.prototype, name);
if (oldDescr && !oldDescr.configurable) {
console.error('Unable to replace ' + buildIn.name + '.prototype.' + name + '!');
} else {
if (oldDescr) {
console.warn('Replacing ' + buildIn.name + '.prototype.' + name + ' might cause unexpected behaviour.');
}
Object.defineProperty(buildIn.prototype, name, descr);
}
}
It works in some browsers and you can access elements this way:
document.body.appendChild(
'footer'.绎 = document.createElement('div')
);
'footer'.绎.textContent = 'btw nice browser :)';
I have chosen the name of the property almost randomly. If you actually wanted to use this shorthand I would suggest coming up with something easier to type.
You can easily create shorthand easily yourself:
function getE(id){
return document.getElementById(id);
}
id's are saved to the window.
HTML
<div id='logo'>logo</div>
JS
logo.innerHTML;
is the same as writing:
document.getElementById( 'logo' ).innerHtml;
I don't suggest using the former method as it is not common practice.
A quick alternative to contribute:
HTMLDocument.prototype.e = document.getElementById
Then just do:
document.e('id');
There's a catch, it doesn't work in browsers that don't let you extend prototypes (e.g. IE6).
(Shorthand for not only getting element by ID, but also getting element by class :P)
I use something like
function _(s){
if(s.charAt(0)=='#')return [document.getElementById(s.slice(1))];
else if(s.charAt(0)=='.'){
var b=[],a=document.getElementsByTagName("*");
for(i=0;i<a.length;i++)if(a[i].className.split(' ').indexOf(s.slice(1))>=0)b.push(a[i]);
return b;
}
}
Usage : _(".test") returns all elements with class name test, and _("#blah") returns an element with id blah.
<script>
var _ = function(eId)
{
return getElementById(eId);
}
</script>
<script>
var myDiv = _('id');
</script>
There are several good answers here and several are dancing around jQuery-like syntax, but not one mentions actually using jQuery. If you're not against trying it, check out jQuery. It let's you select elements super easy like this..
By ID:
$('#elementId')
By CSS class:
$('.className')
By element type:
$('a') // all anchors on page
$('inputs') // all inputs on page
$('p a') // all anchors within paragaphs on page
There's none built-in.
If you don't mind polluting the global namespace, why not:
function $e(id) {
return document.getElementById(id);
}
EDIT - I changed the function name to be something unusual, but short and not otherwise clashing with jQuery or anything else that uses a bare $ sign.
I frequently use:
var byId='getElementById'
var byClass='getElementsByClass'
var byTag='getElementsByTag'
var mydiv=document[byId]('div')
/* as document["getElementById"] === document.getElementById */
I think it's better than a external function (e.g. $() or byId()) because you can do things like this:
var link=document[byId]('list')[byClass]('li')[0][byTag]('a')[0]
Btw, don't use jQuery for this, jQuery is much, much slower than document.getElementById(), an external function like $() or byId(), or my method: http://jsperf.com/document-getelementbyid-vs-jquery/5
Yes, it gets repetitive to use the same function over and over each time with a different argument:
var myImage = document.getElementById("myImage");
var myDiv = document.getElementById("myDiv");
So a nice thing would be a function that takes all those arguments at the same time:
function getElementsByIds(/* id1, id2, id3, ... */) {
var elements = {};
for (var i = 0; i < arguments.length; i++) {
elements[arguments[i]] = document.getElementById(arguments[i]);
}
return elements;
}
Then you would have references to all your elements stored in one object:
var el = getElementsByIds("myImage", "myDiv");
el.myImage.src = "test.gif";
But you would still have to list all those ids.
You could simplify it even more if you want all elements with ids:
function getElementsWithIds() {
var elements = {};
var elementList = document.querySelectorAll("[id]");
for (var i = 0; i < elementList.length; i++) {
elements[elementList[i].id] = elementList[i];
}
return elements;
}
But it would be pretty expensive to call this function if you have many elements.
So, theoretically, if you would use the with keyword you could write code like this:
with (getElementsByIds('myButton', 'myImage', 'myTextbox')) {
myButton.onclick = function() {
myImage.src = myTextbox.value;
};
}
But I don't want to promote the use of with. Probably there's a better way to do it.
Well, you could create a shorthand function, that's what I do.
function $(element) {
return document.getElementById(element);
}
and then when you wanted to get it, you just do
$('yourid')
Also, another useful trick that I found, is that if you want to get the value or innerHTML of an item ID, you can make functions like this:
function $val(el) {
return $(el).value;
}
function $inner(el) {
return $(el).innerHTML;
}
Hope you like it!
I actually made a kind of mini javascript library based on this whole idea.
Here it is.
If this is on your own site, consider using a library like jQuery to give you this and many other useful shorthands that also abstract away browser differences. Personally, if I wrote enough code to be bothered by the longhand, I would include jQuery.
In jQuery, the syntax would be $("#someid"). If you then want the actual DOM element and not the jQuery wrapper, it's $("#someid")[0], but you could most likely do whatever you're after with the jQuery wrapper.
Or, if you're using this in a browser developer console, research their built-in utilities. As someone else mentioned, the Chrome JavaScript console includes a $("someid") method, and you can also click an element in the developer tools "Elements" view and then reference it with $0 from the console. The previously selected element becomes $1 and so on.
If the only issue here is typing, maybe you should just get yourself a JavaScript editor with intellisense.
If the purpose is to get shorter code, then you could consider a JavaScript library like jQuery, or you can just write your own shorthand functions, like:
function byId(string) {return document.getElementById(string);}
I used to do the above for better performance. What I learnt last year is that with compression techniques the server does it automatically for you, so my shortening technique was actually making my code heavier. Now I am just happy with typing the whole document.getElementById.
If you are asking for a shorthand function...
<!DOCTYPE html>
<html>
<body>
The content of the body element is displayed in your browser.
<div id="d1">DIV</div>
<script>
var d=document;
d.g=document.getElementById;
d.g("d1").innerHTML = "catch";
</script>
</body>
</html>
or
<!DOCTYPE html>
<html>
<body>
The content of the body element is displayed in your browser.
<div id="d1">DIV</div>
<script>
var w=window;
w["d1"].innerHTML = "catch2";
</script>
</body>
Arrow functions make is shorter.
var $id = (id) => document.getElementById(id);
wrap the document.querySelectorAll ... a jquery like select
function $(selector){
var s = document.querySelectorAll(selector);
return s.length > 1 ? s : s[0];
}
// usage: $('$myId')
Well, if the id of the element does not compete with any properties of the global object, you don't have to use any function.
myDiv.appendChild(document.createTextNode("Once I was myDiv. "));
myDiv.id = "yourDiv";
yourDiv.appendChild(document.createTextNode("But now I'm yourDiv."));
edit: But you don't want to make use of this 'feature'.
Another wrapper:
const IDS = new Proxy({}, {
get: function(target, id) {
return document.getElementById(id); } });
IDS.camelCaseId.style.color = 'red';
IDS['dash-id'].style.color = 'blue';
<div id="camelCaseId">div 1</div>
<div id="dash-id">div 2</div>
This, in case you don't want to use the unthinkable, see above.
You can use a wrapper function like :
const byId = (id) => document.getElementById(id);
Or
Assign document.getElementById to a variable by binding it with document object.
const byId = document.getElementById.bind(document);
Note: In second approach, If you don't bind document.getElementById with document you'll get error :
Uncaught TypeError: Illegal invocation
What Function.bind does is it creates a new function with its this keyword set to value that you provide as argument to Function.bind.
Read docs for Function.bind
const $id = id => document.getElementById(id);
...
$id('header')
I just use: function id(id) {return document.getElementById(id);}", called by id(target id).action;
It works for me in Chrome, Edge & Firefox, though not in Safari or Opera.
I wrote this yesterday and found it quite useful.
function gid(id, attribute) {
var x = 'document.getElementById("'+id+'")';
if(attribute) x += '.'+attribute;
eval('x =' + x);
return x;
}
This is how you use it.
// Get element by ID
var node = gid('someID'); //returns <p id='someID' class='style'>Hello World</p>
// returns 'Hello World'
// var getText = document.GetElementById('someID').innerText;
var getText = gid('someID', 'innerText');
// Get parent node
var parentNode = gid('someID', 'parentNode');

In Javascript or jQuery, how do I detect if a specific tag exists or not?

Given the following strings:
htmlStr1 = "<img>test1</img>";
htmlStr2 = "<div>test2</div>";
I'd like to know if there's a way to write a function just to detect for the "img" tag (for example). So if both of these strings are passed to it, and it should not do anything if the 2nd string is passed to it.
so for example, you'd run a function like:
result1 = checkIfTagExists(htmlStr1, "img");
result2 = checkIfTagExists(htmlStr2, "img");
alert(result1); // should output "true" or "1" or whatever
alert(result2); // should output "false" or do nothing
I would use a speedy RegExp for this, no need to use any jQuery selectors when not needed.
function checkIfTagExists(str, tag) {
return new RegExp('<'+tag+'[^>]*>','g').test(str);
}
If this is more of an example of functionality you are looking for and not the exact situation you'd use it in, the jQuery has selector may be helpful.
Related question with example.
For this situation you would do:
var str1ContainsImg = $(htmlStr1 + ":has(img)").length > 1;
var str2ContainsImg = $(htmlStr2 + ":has(img)").length > 1;
Edit: As tvanfosson pointed out in the comments, if your img tag doesn't have a closing tag ( <img src='' /> ),this exact solution wouldn't work. If that's an issue, you can check the tag name of the first element returned like this:
var htmlStr3 = "<img src='' />";
var containsEmptyImg = $(htmlStr3 + ":has(img)").length > 1 ||
$(htmlStr3 + ":has(img)")[0].tagName.toUpperCase() == 'IMG';
Wrap this in an if statement and you are good to go
jQuery(jQuery(htmlStr1)).find('img').size() > 0
This will be easier if the strings are in the innerHTML of an element:
function checkIfTagExists(element, tagName) {
return element.getElementsByTagName(tagName).length > 0;
}
A regex check would probably be insufficient (see RegEx match open tags except XHTML self-contained tags) :)
If you really do just have the strings, you can create an element from the string, and set the innerHTML to the string, then do the above check on that new element. This is what the $(tagName, htmlContext) would be doing.
This might have a bit of overhead, but it should be robust enough for use with any given string or the innerHTML of any element.
function getTagCountFromString(string, tag) {
var count = 0;
tag = tag.toLowerCase();
$(string).each(function(idx, el){
if(el.nodeType === 1) {
if(el.tagName && el.tagName.toLowerCase() === tag) {
count++;
}
if(el.childNodes.length > 0) {
try {
count += getTagCountFromString(el.innerHTML, tag);
} catch (ex) { }
}
}
});
return count;
}
getTagCountFromString('<img src=""/><a href=""/>', 'img'); //returns 1
Then to get a boolean value you could check if the count is not equal to 0 or make a helper function which does it for you.
in straight javascript:
function checkIfTagExists(src, tag) {
var re = "<"+tag + ">\.+<\\/"+tag+">";
return new RegExp(re).test(src);
}

Categories