I am pretty confident that this can be done but my efforts so far have failed. I have a loop generated series of divs that have id=x0, x1, x2 etc.... Depending on context the html of one or more div(s) will be reset. In the case where two divs will have the same value, and the id is a known number I would easily do:
$('#x3, #x7').html('new value');
How to set this when the id number is a variable? I first tried:
$('#x'+(location-2), '#x'+(location+3)).html('new value'); // doesn't throw a console error
// but doesn't work
I tried numerous permutations involving quotes, escaped quotes, brackets {}, [], () - in combination with quotes, etc. etc. hair pulling etc.
To keep the project moving I am declaring multiple replacements which is no great extra load but it would be tidier to have a single call -- and, I always look to learn.
Seems like a common class would be a better solution to this, but to answer your question, you didn't concatenate properly:
$('#x' + (location-2) + ', #x' + (location+3)).html('new value');
jsFiddle example
And you also may run into issues using location as a variable name as it's a property of the Window object.
Just create an array of selectors and then join them:
var selectors = [
'#x' + (location - 2),
'#x' + (location + 3)
];
var jointSelector = selectors.join(',');
After concation it should look like '#x3, #x7'. But here you are not concating the comma. That is the mistake you are doing.
$('#x' + (location-2) + ', #x' + (location+3)).html('new value');
you miss the apostrophe
$("#x"+(location-2)+",#x"+(location+3)).html('new value')
Related
I Tried this code to get multiple value in href but it does not work. any problem on this one ?
Print
You are missing a + sign between a string and a value.
The error is between this two
document.getElementById('CUS_CODE_MX').value '&AGE='
Correct format
document.getElementById('CUS_CODE_MX').value + '&AGE='
Every time you join a value and a string, you need a + sign
Even if you are joining two strings
'Hello'+ 'World'
Pliss avoid long js as an inline atribute. I will recommend you call a function as the onclick attribute.
Hope this helps :)
Print
It's better to use external script for that rather than inline format. And just add missing + to your code. Also, using variables would clean up the code.
function func() {
var CUS_CODE_MX = document.getElementById('CUS_CODE_MX').value;
var AGEID = document.getElementById('AGEID').value;
this.href = 'printsales.php?CUSTOMERID='+CUS_CODE_MX+'&AGE='+AGEID;
}
Print
First post here, so please be gentle ;-)
I've been learning coding over the last couple of weeks by making a dummy page, and been implementing what i learn on it incrementaly as i progress, hence it's a mixed bag where the functionality/code is according to when i wrote it, based on pure html/CSS, inline javascript, external javascript, and finally jquery.
So i mostly wrapped it up and i'm now cleaning up the mess, and part of my mission is to cull functions and lines of codes, and in one of them i'm kind of stuck.
The before was 30 buttons calling to 30 different functions onclick like so:
function cell3() {
document.getElementById('base3').src='images/1/3/' + x + '.png';
document.getElementById('base3b').src='images/1/3/' + x + '.png';
document.getElementById('v2base3').src='images/2/3/' + x + '.png';
document.getElementById('v2base3b').src='images/2/3/' + x + '.png';
document.getElementById('cell3').style.backgroundColor= x ;
}
Where a global variable (x) defines the folder paths for images to replace the images within some divs when clicking the button (cell3). It also changes the bGroung color of it. Sorry if the naming is a bit confusing...
So i'm removing all 30 functions and the 30 onclick calls with this bit of jquery:
$('button').click(function(){
var eyeD = $(this).attr("id");
var newURLa = 'images/1/' + eyeD + '/' + x + '.png';
var newURLb = 'images/2/' + eyeD + '/' + x + '.png';
$('base' + eyeD).attr('src', newURLa);
$('base' + eyeD + 'b').attr('src', newURLa);
$('v2base' + eyeD).attr('src', newURLb);
$('v2base' + eyeD + 'b').attr('src', newURLb);
$(this).css( "background-color", x );
document.getElementsByid('check').innerhtml = eyeD;
});
For that to 'work' i changed the button's names from 'cell1', 'cell2, etc. to '1', '2', etc.
Now the thing is, when clicking on the buttons the var 'eyeD' takes the value from the button ok. ('1', '2', etc.). The elements ID's are formed correctly ('base1', 'base2'... 'base1b', base2b'...), and the URL's are formed correctly. (The last line in the code is a p element that displays values so i could try to troubleshoot it) The background color also changes as expected. But the images do not get replaced.
Tried adding commas to the resulting URL's in case it was a syntax issue, but nothing happens. i even went freestyle and tried it with the =url() on it, different commas in different places, etc. So basically scraping the barrel here. Also wrote a url without variables to see if that would work, but still nothing. Also getting no errors when looking at the console.
It's probably a basic 'DOH!' thing, but right now i have a mental block...
Also, is there a way to keep the original naming and just retrieve the numbering part of the ID's? Thought about using the [4] identifier to get the 5th digit, but that won't work when running double digit numbers. (10, 11, etc)
Thanks!
Your jQuery lines accessing the elements are missing the # sign.
Change these...
$('base' + eyeD).attr('src', newURLa);
To this...
$('#base' + eyeD).attr('src', newURLa);
Also, your last line where you use plain JS, can be done in jQuery as well with less code.
document.getElementsByid('check').innerhtml = eyeD;
To...
$("#check").html(eyeD);
However, you should always use distinct ID's for elements. If you need to use multiple elements at the same time, use a class instead.
$(".check").html(eyeD);
You're grabbing an element incorrectly.
Either Grab an element by it's class name like so:
$('.v2base' + eyeD + 'b').attr('src', newURLb);
Or by its ID:
$('#v2base' + eyeD + 'b').attr('src', newURLb);
Problem solved!! It was indeed calling the id with the hash, but also it has to be called with double quotation marks. Single inverted commas won't work.
So the working format is
$("#v2base" + eyeD + "b")
but it won't work like so
$('#v2base' + eyeD + 'b')
Thanks everyone, it's been emotional
Say I have the following element:
<div class='selector' data-object='{"primary_key":123, "foreign_key":456}'></div>
If I run the following, I can see the object in the console.
console.log($('.selector').data('object'));
I can even access data like any other object.
console.log($('selector').data('object').primary_key); //returns 123
Is there a way to select this element based on data in this attribute? The following does not work.
$('.selector[data-object.foreign_key=456]');
I can loop over all instances of the selector
var foreign_key = 456;
$('.selector').each(function () {
if ($(this).data('object').foreign_key == foreign_key) {
// do something
}
});
but this seems inefficient. Is there a better way to do this? Is this loop actually slower than using a selector?
You can try the contains selector:
var key_var = 456;
$(".selector[data-object*='foreign_key:" + key_var + "']");
I think that you may gain a little speed here over the loop in your example because in your example jQuery is JSON parsing the value of the attribute. In this case it's most likely using the JS native string.indexOf(). The potential downside here would be that formatting will be very important. If you end up with an extra space character between the colon and the key value, the *= will break.
Another potential downside is that the above will also match the following:
<div class='selector' data-object="{primary_key:123, foreign_key:4562}"></div>
The key is clearly different but will still match the pattern. You can include the closing bracket } in the matching string:
$(".selector[data-object*='foreign_key:" + key_var + "}']");
But then again, formatting becomes a key issue. A hybrid approach could be taken:
var results = $(".selector[data-object*='" + foreign_key + "']").filter(function () {
return ($(this).data('object').foreign_key == foreign_key)
});
This will narrow the result to only elements that have the number sequence then make sure it is the exact value with the filter.
With a "contains" attribute selector.
$('selector[data-object*="foreign_key:456"]')
I have a function that uses each to go over each element in a set and renumber them after one is removed from the DOM.
Right now that function looks like this:
renumber_items = function(){
$(".item_set").each(function(index){
$(this).find('legend').html("Item " + (index+1));
});
};
I remember reading somewhere that find is a really inefficient operation, so I was wondering if there's a way to combine the 'legend' selector into a compound selector with this.
If there is only one legend per .item_set this will abbreviate things a bit:
renumber_items = function(){
$(".item_set legend").html(function(index){
return "Item " + (index+1);
});
};
.html can take a function and the result is stored.
If there is more than one legend per .item_set you will need to retain an outer each to keep the numbers sequential for each set.
Generally if you have speed issues, on a function called many times, and the jQuery selector result is on a fixed set of elements, you just archive the search to a variable once at page load and reuse that:
var $legends = $(".item_set legend");
renumber_items = function(){
$legends.html(function(index){
return "Item " + (index+1);
});
};
Maybe you can try with .filter(). As others say, it shouldn't be such a performance issue as long as you're not using it all the time. Consider labeling all the items you want to find/filter, so that you can get them all in one JQuery selector at once, and you don't have to go filtering everything after. Else you can use (as commented out by #Regent):
renumber_items = function(){
$(".item_set legend").each(function(index){
$(this).html("Item " + (index+1));
});
};
You can replace:
$(this).find('legend')
with:
$('legend', this)
The second argument sets the context in which jQuery searches for 'legend'.
If it is omitted, the context defaults to be document.
I am trying to work out some performance problems with some JavaScript I've been working on for a few days. One of the pieces of the functions is below:
var removeAddress = function(pk) {
var startTime = new Date();
jQuery('.add_driver select.primary_address:has(option[value=' + pk + ']:selected)').each(function(c, o) {
console.log("Shouldn't get here yet...");
showInputs(o);
});
console.log('removeAddress1: ', (new Date() - startTime) / 1000);
jQuery('.add_driver select.primary_address option[value=' + pk + ']').remove();
console.log('removeAddress2: ', (new Date() - startTime) / 1000);
};
This code is quite peppy in Firefox:
removeAddress1: 0.004
removeAddress2: 0.023
But in IE8 it is another story:
LOG: removeAddress1: 0.203
LOG: removeAddress2: 0.547
The form in question is a 20-person in put form with first name, last name, and 5 address fields. I've also put in a drop down for selecting other addresses already existing in the form (.primary_address). This code is removing an address from the primary address select boxes.
I'm trying to nail down why this is taking so long, and the only thing which stands out is the option[value=????] section. This was the most practical way to find the elements in question, so I ran with it. Is there something about these two selectors which is causing IE to lose its lunch?
The option element is always temperamental. Perhaps it's simpler to just get all the SELECT elements and then simply query their values. The selected OPTION always will give its value property to the SELECT as well. So:
jQuery('.add_driver select.primary_address').filter(function() {
return $(this).value === pk;
});
jQuery('.add_driver select.primary_address[value='+pk+']');
Maybe one of those will be faster - not sure if the second will work.
You can likely speed this up a lot by breaking down your uber-selector string.
To start, begin with an id, or even better a cached element. Then get your select elements using .children(). Instead of using the :has selector use .has(). Methods are generally faster than complex selector syntax because jQ doesn't have to parts a string to figure out what you mean. Then, as Rafael said, you can skip the :selected and just look at the value of the matched select's.
formElem = document.getElementById('formId');
jQuery('.add_driver', formElem)
.children('select.primary_address')
.has('[value=' + pk + ']')
.each(...);
Passing formElem as the second arg uses it as the context for the search so jQ doesn't have to start at the root.
To .remove() the elements either cache the jQuery object from above or chain it on after the .each() so you don't have to reselect everything again.
Maybe precompute $('formId .add_driver select') outside of the removeAddress function, then reuse that so the removeAddress() doesn't have to enumerate so many elements.