I have a javascript function that changes a user preference, if they want weights to be metric or in imperial.
On my page I print out the weight, IE:
This is some description:
This product weights <b>200 KG</b>
Blah blah
I need to make it so that Javascript changes the weight measurement for all weights on the page, and am not sure the best way to tackle this. Can you create your own tags, or tag properties?
Thanks for any suggestions, JQuery is fine.
I'd recommend using strong rather than b, but the below will work for either of them.
Edit: Better solution than using a class, with working example, below.
Tag the weights with a class, e.g.:
This product weighs <strong class='weight'>200 KG</strong>
Then in your JavaScript, you can switch like so:
$('.weight').each(function() {
var $this = $(this);
var original = $this.text();
var converted = /* ...convert the weight here... */;
$this.text(converted);
});
Obviously you can condense that a bit, kept it verbose for clarity.
Better solution:
Tag the elements with the original weight (the one you store in your database) as a data-weight attribute, e.g.:
This product weighs <strong data-weight='200'>200 KG</strong>
Then convert from that value:
$('[data-weight]').each(function() {
var $this = $(this);
var value = $this.attr("data-weight");
if (usingMetric) {
$this.text(value + " KG");
}
else {
value = parseFloat(value) * 2.20462262; // Convert to imperial
$this.text(value.toFixed(2) + " lbs");
}
});
Working example: http://jsbin.com/icure3
Attributes in the form data-xyz will pass validation as of HTML5; prior to HTML5 they are technically invalid, but harmless. But if you prefer a version that doesn't use data-weight, you can do it with classes instead: http://jsbin.com/icure3/2 (inspired by Reigel's answer to Tom's other question).
If you see a delay when switching between metric and imperial on slower browsers (I'm looking at you, Microsoft), you can help jQuery's selector engine optimize by giving it more context than just "[data-weight]". jQuery's engine supports nearly all of CSS3. For instance, if you always use the data-weight attribute only one one kind of tag (say, strong tags), change the selector to "strong[data-weight]" so the selector engine knows it can optimize for just one specific tag name. Similarly, if all of these are inside some container (e.g., a div with the ID "productList" for instance), you can help the engine out even more ("#productList strong[data-weight]") so it can ignore anything outside that div. I've kept it completely general above. But probably only bother if the page is big and complex enough that you see a performance issue.
Final thought: To throw a bone to browsers with JavaScript disabled, you might include both values in a title attribute as well, e.g.:
This product weighs <strong title='200 KG / 441 lbs' data-weight='200'>200 KG</strong>
...so it shows up as a tooltip on browsers that do that. I included that in the example above.
I would add a class .weight and use this to target all the weights..
$('.weight').each(function(){...})
If you want to change the innerHTML you can use the html() method directly
$('.weight').html(function(idx, oldhtml){
// you can use the oldhtml to extract info and create the new text here..
$(this).html( ../*you new html here*/.. ); // replace existing with new html ..
})
HTML:
<b class="weight">200 KG</b>
Javascript:
$("#UnitChangeButton").click(function() {
$('.weight').each(function(){
txt = $(this).text();
newTxt = convert(txt);
$(this).text(newTxt);
});
});
You need to implement the convert function. You can store the state (metric or imperial) in a javascript variable.
Related
So I have this JS script:
<script>
function getCheckedProperty(obj,args)
{
if(document.getElementById("<%=checkbox1.ClientID %>").checked)
return true;
else
return false;
}
</script>
This only works for checkBox1. I want to be able to pass control id from parameters, so that it can return value of passed control. Also, please, respond with the usage.
<asp:CustomValidator runat="server" ClientValidationFunction="getCheckedProperty()></asp:CustomValidator>
TIY. SRJ.
Check this question it might have your answer.
if I get it right you want to get ids dynamically for example checkbox1, checkbox2,...
You can add the dynamic part to the id like this:
for (var i = 1; i < n; i++) {
var id = "checkbox" + i;
var ch = document.getElementById(id);
if (ch.checked == false)
return false;
}
return true;
Unfortantly, this is a real problem. The control name(s) are generated at runtime, and ALSO THIS:
document.getElementById("<%=checkbox1.ClientID %>")
So at page render time, the .net pre-processor will SWAP out the <% %> at render time.
this is also why you can't say have the js code in a external library and expect this to work.
However, your DEAD OBVIOUS question remains. Stuff a name into a simple variable and use that to get the control. After all, we can't and would not want to HARD code the value as per above, and it would be beyond silly to assume we ONLY have a means to HARD code references to controls.
So, you want of course this:
var MyControl = 'Checkbox1';
var ckBox = document.getElementById(MyControl);
if (ckBox.checked)
alert('Check box ' + MyControl + ' is checked!');
else
alert('Check box ' + MyControl + ' is UN-checked');
Now in fact the ABOVE can and will work if you force the control name generation as static.
so, here is the markup:
<asp:CheckBox ID="CheckBox1" runat="server" ClientIDMode="Static" />
So, if you ARE able and ARE willing to use ClientIDMode static, then the .net processing will NOT re-name your control. As a result you can do this:
var MyControl = 'Checkbox1';
var ckBox = document.getElementById(MyControl);
Or, even this (as HARD coded)
var ckBox = document.getElementById('CheckBox1');
Or even this:
var ckbox2 = document.getElementById(<%= CheckBox1.ClientID %>);
Now, the last one above? Well, we ARE useing the .net pre-processor to swap out the name - but it will still work - and clientID will not be changed - but the pre-processor is STILL involved.
AGAIN: the <%= 'SomeControlName.ClientID%> ONLY works because this expression is SWAPPED out at runtime by the .net web page pre-processor. This occures BEFORE the js code is run.
So you can NOT use a variable in the above <%=%> expressions since the js code HAS NOT even run and the new js code has not even been generated at this point in time.
In effect, you would (have to) do a PAGE search for the control. If you can NOT adopt ClientIdMode="static", then you MUST SEARCH the page.
You can write your OWN search routines - kind of like adopting a nice road to world poverty, or you bite the bullet, and adopt a library that WILL do the heavy lifting for you.
So, without using (forcing) StaticID on the control? then you now have to accept the BIG HUGE LARGE MASSIVE decision and introduce jQuery into your application.
jQuery is able to scour and search and look and loop and find that control for you on the web page. This is a cost not without processing cost, and not without a big speed penalty.
So, without staticID's, then you can adopt jquery and do this:
<script src="Scripts/jquery-3.5.1.js"></script>
<script>
// so if you decide and adopt jQuery, then it can do the searching for you
// BUT YOU ARE now adopting and committing to a whole new js library
// so, with jQuery we cna do this:
function jstest2(){
var ckbox2 = $('#CheckBox1');
var ckboxdom = ckbox2[0];
alert('status of check box = ' + ckboxdom.checked);
// of course the above is STILL hard code
// get control by runtime or NON hard code
// get (search) for check box based on control name in
// a variable
var MyCheckBox = 'CheckBox1';
var ckbox3 = $('#' + MyCheckBox);
var ckboxdom3 = ckbox3[0];
alert('status of check box = ' + ckboxdom3.checked);
</script>
I found after doing a nuget of jQuery, the fans on my laptop became too hot to even keep on my lap. But, things did settle down, and eventually the VS editors caught up, and things did settle down.
Also keep in mind that you have to re-learn how to reference a simple control.
eg:
<script>
function getbox() {
var tbox = document.getElementById('TextBox1');
alert(tbox.value);
// jQuery example
var tbox2 = $('#TextBox1');
alert(tbox2.val());
}
</script>
So notice now, how the long time js standard and approach is "value" as a property?
Well, now you using .val() that is a function (method) of that search result. So just keep in mind that by adopting jQuery, then all of your code that needs to get simple values from controls has to under go a syntax change, and you as a developer will have to re-lean how to reference a simple control with new syntax. The check box is a great example - it now becomes a array, and you use that array to get at the checked property.
And same in above for a simple grab of a value from a text box.
Notice how the syntax and approach to getting the value of the text box NOW has changed!!!! So you need a cheat-sheet since simple things like value now become .val().
And the same changes occur for say a label on a web page (again syntax changes).
You will ALSO notice that the results of the check box example are an array!!! So we had to drill down into the resulting array[] to get the "checked" value.
Of course how big of a deal your code changes are by adopting jQuery? Well, it depends, on relative medium sized or even a small project? $20,000 was budgeted and we still changing things.
On larger projects you simply need more manpower and would add another zero to the above cost to adopt jQuery.
However, jQuery is now widespread used, and it will do the "dirty work" of searching the DOM for you, and if you need runtime resolution as opposed to compile time resolution to find a simple control on a web page, then jQuery is probably your best choice. And I find that jQuery is really nice for ajax calls - so while it is a big change, it still well worth the effort to adopt the jQuery library and risk introducing this framework into your existing projects.
I am using the following code on my webpage, in order to format certain numbers (with the ".pricetag" class), as i need to show them as currencies (comma separated at thousands) on my front end:
jQuery(document).ready(function($) {
$.fn.digits = function(text){
$(this).text(text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") + '€' );
};
var tempText = $.trim($(".pricetag").text());
tempText = tempText.substr(0, parseInt(tempText.length) );
$(".pricetag").digits(tempText);
});
So far so good - code works fine, and does what i need it to.
My problem is that i have more classes than just the ".pricetag" class, for which i want to use the function. So right now i have copy pasted the code, and just changed the target class (".pricetag_2" etc.).
How do i tell one version of the javascript/code, to affect several classes (both ".pricetag" and ".pricetag_2") in stead of having to copy paste the same piece of code, let's say 10 times, to target 10 different classes.
It's a bit overkill to have so much code, as the function is exactly the same every time. In CSS it's pretty easy, as you can affect several classes at once, by comma seperating them within a piece of code, but how do i do it in javascript?
Thanks!
If all your classes begin with .pricetag you might try the attribute-starts-with selector.
$("[class^='pricetag']").digits(tempText);
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'));
I sometimes need to add elements (such as a new link and image) to an existing HTML page, but I only have access to a small portion of the page far from where I need to insert elements. I want to use DOM based JavaScript techniques, and I must avoid using document.write().
Thus far, I've been using something like this:
// Create new image element
var newImg = document.createElement("img");
newImg.src = "images/button.jpg";
newImg.height = "50";
newImg.width = "150";
newImg.alt = "Click Me";
// Create new link element
var newLink = document.createElement("a");
newLink.href = "/dir/signup.html";
// Append new image into new link
newLink.appendChild(newImg);
// Append new link (with image) into its destination on the page
document.getElementById("newLinkDestination").appendChild(newLink);
Is there a more efficient way that I could use to accomplish the same thing? It all seems necessary, but I'd like to know if there's a better way I could be doing this.
There is a more efficient way, and seems to be using documentFragments if possible.
Check it out: http://ejohn.org/blog/dom-documentfragments/ . Also this way should be less error prone and more maintainable than starting to mix up huge strings literals and setting them as innerHTML of some other DOM objects.
Just beware, that innerHTML is both non-standard and notoriously buggy.
Nothing wrong with that. Using innerHTML would be marginally faster and probably fewer characters but not noticeable for something of this scale, and my personal preference is for the more standard, uniformly supported and safer DOM methods and properties.
One minor point: the height and width properties of <img> elements should be numbers rather than strings.
If you're not adding many things, the way you've been doing it is ideal vs innerHTML. If you're doing it frequently though, you might just create a generic function/object that takes the pertinent information as parameters and does the dirty work. IE
function addImage(src,width,height,alt,appendElem,href) {...}
I do this often in my own projects using prototyping to save time.
Recently I've been doing a lot of modal window pop-ups and what not, for which I used jQuery. The method that I used to create the new elements on the page has overwhelmingly been along the lines of:
$("<div></div>");
However, I'm getting the feeling that this isn't the best or the most efficient method of doing this. What is the best way to create elements in jQuery from a performance perspective?
This answer has the benchmarks to the suggestions below.
I use $(document.createElement('div')); Benchmarking shows this technique is the fastest. I speculate this is because jQuery doesn't have to identify it as an element and create the element itself.
You should really run benchmarks with different Javascript engines and weigh your audience with the results. Make a decision from there.
personally i'd suggest (for readability):
$('<div>');
some numbers on the suggestions so far (safari 3.2.1 / mac os x):
var it = 50000;
var start = new Date().getTime();
for (i = 0; i < it; ++i) {
// test creation of an element
// see below statements
}
var end = new Date().getTime();
alert( end - start );
var e = $( document.createElement('div') ); // ~300ms
var e = $('<div>'); // ~3100ms
var e = $('<div></div>'); // ~3200ms
var e = $('<div/>'); // ~3500ms
Question:
What is the most efficient way to create HTML elements using jQuery?
Answer:
Since it's about jQuery then I think it's better to use this (clean) approach (you are using)
$('<div/>', {
'id':'myDiv',
'class':'myClass',
'text':'Text Only',
}).on('click', function(){
alert(this.id); // myDiv
}).appendTo('body');
DEMO.
This way, you can even use event handlers for the specific element like
$('<div/>', {
'id':'myDiv',
'class':'myClass',
'style':'cursor:pointer;font-weight:bold;',
'html':'<span>For HTML</span>',
'click':function(){ alert(this.id) },
'mouseenter':function(){ $(this).css('color', 'red'); },
'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');
DEMO.
But when you are dealing with lots of dynamic elements, you should avoid adding event handlers in particular element, instead, you should use a delegated event handler, like
$(document).on('click', '.myClass', function(){
alert(this.innerHTML);
});
var i=1;
for(;i<=200;i++){
$('<div/>', {
'class':'myClass',
'html':'<span>Element'+i+'</span>'
}).appendTo('body');
}
DEMO.
So, if you create and append hundreds of elements with same class, i.e. (myClass) then less memory will be consumed for event handling, because only one handler will be there to do the job for all dynamically inserted elements.
Update : Since we can use following approach to create a dynamic element
$('<input/>', {
'type': 'Text',
'value':'Some Text',
'size': '30'
}).appendTo("body");
But the size attribute can't be set using this approach using jQuery-1.8.0 or later and here is an old bug report, look at this example using jQuery-1.7.2 which shows that size attribute is set to 30 using above example but using same approach we can't set size attribute using jQuery-1.8.3, here is a non-working fiddle. So, to set the size attribute, we can use following approach
$('<input/>', {
'type': 'Text',
'value':'Some Text',
attr: { size: "30" }
}).appendTo("body");
Or this one
$('<input/>', {
'type': 'Text',
'value':'Some Text',
prop: { size: "30" }
}).appendTo("body");
We can pass attr/prop as a child object but it works in jQuery-1.8.0 and later versions check this example but it won't work in jQuery-1.7.2 or earlier (not tested in all earlier versions).
BTW, taken from jQuery bug report
There are several solutions. The first is to not use it at all, since
it doesn't save you any space and this improves the clarity of the
code:
They advised to use following approach (works in earlier ones as well, tested in 1.6.4)
$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");
So, it is better to use this approach, IMO. This update is made after I read/found this answer and in this answer shows that if you use 'Size'(capital S) instead of 'size' then it will just work fine, even in version-2.0.2
$('<input>', {
'type' : 'text',
'Size' : '50', // size won't work
'autofocus' : 'true'
}).appendTo('body');
Also read about prop, because there is a difference, Attributes vs. Properties, it varies through versions.
Actually, if you're doing $('<div>'), jQuery will also use document.createElement().
(Just take a look at line 117).
There is some function-call overhead, but unless performance is critical (you're creating hundreds [thousands] of elements), there isn't much reason to revert to plain DOM.
Just creating elements for a new webpage is probably a case in which you'll best stick to the jQuery way of doing things.
If you have a lot of HTML content (more than just a single div), you might consider building the HTML into the page within a hidden container, then updating it and making it visible when needed. This way, a large portion of your markup can be pre-parsed by the browser and avoid getting bogged down by JavaScript when called. Hope this helps!
This is not the correct answer for the question but still I would like to share this...
Using just document.createElement('div') and skipping JQuery will improve the performance a lot when you want to make lot of elements on the fly and append to DOM.
I think you're using the best method, though you could optimize it to:
$("<div/>");
You don't need raw performance from an operation you will perform extremely infrequently from the point of view of the CPU.
You'll have to understand that the significance of element creation performance is irrelevant in the context of using jQuery in the first place.
Keep in mind, there's no real purpose of creating an element unless you're actually going to use it.
You may be tempted to performance test something like $(document.createElement('div')) vs. $('<div>') and get great performance gains from using $(document.createElement('div')) but that's just an element that isn't in the DOM yet.
However, in the end of the day, you'll want to use the element anyway so the real test should include f.ex. .appendTo();
Let's see, if you test the following against each other:
var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');
You will notice the results will vary. Sometimes one way is better performing than the other. And this is only because the amount of background tasks on your computer change over time.
Test yourself here
So, in the end of the day, you do want to pick the smallest and most readable way of creating an element. That way, at least, your script files will be smallest possible. Probably a more significant factor on the performance point than the way of creating an element before you use it in the DOM.
Someone has already made a benchmark:
jQuery document.createElement equivalent?
$(document.createElement('div')) is the big winner.
One point is that it may be easier to do:
$("<div class=foo id=bar style='color:white;bgcolor:blue;font-size:12pt'></div>")
Then to do all of that with jquery calls.
I am using jquery.min v2.0.3 .
It's for me better to use following:
var select = jQuery("#selecter");
jQuery("`<option/>`",{value: someValue, text: someText}).appendTo(select);
as following:
var select = jQuery("#selecter");
jQuery(document.createElement('option')).prop({value: someValue, text: someText}).appendTo(select);
Processing time of first code is much lower than second code.