Lets say I have this:
<div data-uid="aaa" data-name="bbb", data-value="ccc" onclick="fun(this.data.uid, this.data-name, this.data-value)">
And this:
function fun(one, two, three) {
//some code
}
Well this is not working but I have absolutely no idea why. could someone post a working example please?
The easiest way to get data-* attributes is with element.getAttribute():
onclick="fun(this.getAttribute('data-uid'), this.getAttribute('data-name'), this.getAttribute('data-value'));"
DEMO: http://jsfiddle.net/pm6cH/
Although I would suggest just passing this to fun(), and getting the 3 attributes inside the fun function:
onclick="fun(this);"
And then:
function fun(obj) {
var one = obj.getAttribute('data-uid'),
two = obj.getAttribute('data-name'),
three = obj.getAttribute('data-value');
}
DEMO: http://jsfiddle.net/pm6cH/1/
The new way to access them by property is with dataset, but that isn't supported by all browsers. You'd get them like the following:
this.dataset.uid
// and
this.dataset.name
// and
this.dataset.value
DEMO: http://jsfiddle.net/pm6cH/2/
Also note that in your HTML, there shouldn't be a comma here:
data-name="bbb",
References:
element.getAttribute(): https://developer.mozilla.org/en-US/docs/DOM/element.getAttribute
.dataset: https://developer.mozilla.org/en-US/docs/DOM/element.dataset
.dataset browser compatibility: http://caniuse.com/dataset
If you are using jQuery you can easily fetch the data attributes by
$(this).data("id") or $(event.target).data("id")
The short answer is that the syntax is this.dataset.whatever.
Your code should look like this:
<div data-uid="aaa" data-name="bbb" data-value="ccc"
onclick="fun(this.dataset.uid, this.dataset.name, this.dataset.value)">
Another important note: Javascript will always strip out hyphens and make the data attributes camelCase, regardless of whatever capitalization you use. data-camelCase will become this.dataset.camelcase and data-Camel-case will become this.dataset.camelCase.
jQuery (after v1.5 and later) always uses lowercase, regardless of your capitalization.
So when referencing your data attributes using this method, remember the camelCase:
<div data-this-is-wild="yes, it's true"
onclick="fun(this.dataset.thisIsWild)">
Also, you don't need to use commas to separate attributes.
HTML:
<div data-uid="aaa" data-name="bbb", data-value="ccc" onclick="fun(this)">
JavaScript:
function fun(obj) {
var uid= $(obj).attr('data-uid');
var name= $(obj).attr('data-name');
var value= $(obj).attr('data-value');
}
but I'm using jQuery.
JS:
function fun(obj) {
var uid= $(obj).data('uid');
var name= $(obj).data('name');
var value= $(obj).data('value');
}
you might use default parameters in your function
and then just pass the entire dataset itself, since the
dataset is already a DOMStringMap Object
<div data-uid="aaa" data-name="bbb" data-value="ccc"
onclick="fun(this.dataset)">
<script>
const fun = ({uid:'ddd', name:'eee', value:'fff', other:'default'} = {}) {
//
}
</script>
that way, you can deal with any data-values that got set in the html tag,
or use defaults if they weren't set - that kind of thing
maybe not in this situation, but in others, it might be advantageous to put all
your preferences in a single data-attribute
<div data-all='{"uid":"aaa","name":"bbb","value":"ccc"}'
onclick="fun(JSON.parse(this.dataset.all))">
there are probably more terse ways of doing that, if you already know
certain things about the order of the data
<div data-all="aaa,bbb,ccc" onclick="fun(this.dataset.all.split(','))">
Related
So far I know that we can store data in html element by using:
<div data-test="hello">
$.("div").data("test")
However , I just can store raw text for data attribute
what I need is:
var t= hello
<div data-test=t>
but when I tried this , it shows the letter t instead of hello.
Actually you are changing not the attribute but an property of the DOM object. For data JavaScript has it's own mechanism to hold data for the elements. For more take a look on Documentation.
You can change the data using jQuery (as you have already used it). Use data function and pass your variable as the second argument to the function like $("#d").data("test", t);
console.log($("#d").data("test"));
const t = 'hello';
$("#d").data("test", t); // <- second parameter
console.log($("#d").data("test"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="d" data-test="test">
You can use the attr() function of JQuery instead of data()
var t= 'hello';
$("div").attr("data-test",t);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-test=t>asd
Without jQuery
jQuery is definitely unnecessary in this case. You can achieve the same thing with this code
HTML
<div data-test="hello">
JS
const textToChange = 'other text';
const divWithDataAttribute = document.querySelector('[data-test]');
diveWithDataAttribute.dataSet.test = textToChange;
Conclusion
This will apply the new result to the data attribute and we didn't need jQuery.
A thing to note is the part dataSet.test this part comes from the data-test attribute. We drop the data- part and camel case the rest of the words.
For example data-test-new-test="whatever" becomes testNewTest when accessing the dataSet.
yes you can try this:
$("div").attr("data-test", "test");
var t="hello";
$("div").attr("data-test",t);
I'd like to set css of a div element dynamically using jQuery css() function instead of using string literals/ string constants for the css() function. Is it possible?
Instead of using the following codes with string literals:
$('#myDiv').css('color', '#00ff00');
I would like to use variables to set css for #myDiv element like
Version 1:
var propertyName = get_propery_name(myVariable1); // function get_propery_name() returns a string like 'background-color'
var value = get_value(myVariable2) ; // function get_value() returns a string like '#00ff00'
$('#myDiv').css(propertyName, value);
Version 2: (just hard coded to see if they work without calling custom functions like version 1 above):
var propertyName = 'background-color';
var value = '#00ff00';
$('#divLeftReportView').css(propertyName, value);
Both variable versions of codes do not work. Please help. Thanks.
Both of your examples will work just fine. I would suggest just a bit cleaner approach (personal syntax preference):
$(document).ready(function () {
$('#myDiv').css(get_propery_name(myVariable1), get_value(myVariable2));
}
Here's a working fiddle.
If you want to take it a step further, you can return a CSS map instead of strings:
$('#divLeftReportView').css(GetCssMap("foo"));
function GetCssMap(mapIdentifier) {
return { "background-color" : "#00ff00" }
}
Here's a working fiddle.
The code you posted here should work. I have done both versions of what you are trying to do several times. If it is not working, there is a good chance that something is wrong somewhere else in your javascript OR that you do not have the correct selector/id for the element(s) which you want to change.
Try adding alert("test"); immediately after $('#divLeftReportView').css(propertyName, value);. If you get the popup saying "test" then the problem is with your selector. If not, then the problem is a bug in your javascript.
Also try adding $('#divLeftReportView').css("background-color", "#00ff00"); in the same place. That will confirm whether or not the selector is working.
Seems to work fine at http://jsfiddle.net/gaby/6wHtW/
Make sure you run your code after the DOM ready event..
$(function(){
var propertyName = 'background-color';
var value = '#00ff00';
$('#divLeftReportView').css(propertyName, value);
});
otherwise your elements might not be present in the DOM..
You can also pass multiple CSS parameters within one variable as an array:
$(function(){
var divStyle = {'background-color': '#00ff00', 'color': '#000000'}
$('#divID').css(divStyle);
});
yes, using jQuery attr method you can change css dynamically
var height=$(".sampleClass1").innerHeight();
$('.sammpleClass2').attr('style', 'min-height:'+height+' !important');
I have elements in my DOM with class="LiveVal:variablepart" and i would like to write a JQuery selector that works even if the elements have other classes on tom of the above. Eg. class="header LiveVal:varablepart" or class="LiveVal:varablepart header".
It works fro me if LiveVal is the first class with:
$('[class^=LiveVal:]').each(function ( intIndex ) { somefunction });
but obviously not if another class is before LiveVal.
In the function I need to extract the variable part. I planned to do like this:
theclass = $( this ).attr('class');
varpart = theclass.replace('\bLiveVal:(.+?)[\s]', '$1');
..but alas, it doesn't match. I've tested the regex on http://gskinner.com/RegExr/ where it seems to work, but it doesn't in javascript !?
Any help would be greatly appreciated.
This will check if a class name contains 'LiveVal:'
$('[class*=LiveVal:]').each(function ( intIndex ) { somefunction });
EDIT
did not realise you had that requirement (although a good one). You can do this instead: $('[class^="LiveVal:"], [class*=" LiveVal:"]')
Here is a fiddle: http://jsfiddle.net/wY8Mh/
It might be somewhat faster to do this with an explicit filter:
$("*").filter(function() { return /\bLiveVal:/.test(this.className); }).something();
It depends on whether the native "querySelectorAll" does the work, and does it quickly. This also would avoid the "FooLiveVal" problem.
It's worth noting that in an HTML5 world, it might be better to use a "data-LiveVal" attribute to store that "variable part" information on your elements. Then you could just say:
$('[data-LiveVal]').something();
In the HTML, it'd look like this:
<div class='whatever' data-LiveVal='variable part'>
Since version 1.5, jQuery will fetch stuff in a "data-foo" attribute when you pass the tail of the attribute (the part after "data-") to the ".data()" method:
var variablePart = $(this).data('LiveVal');
The ".data()" method will not, however, update the "data-foo" property when you store a new "variable part".
edit — if you want the value that's stuffed into the class after your property name prefix ("LivaVal:"), you can extract it like this:
var rLiveVal = /\bLiveVal:(\S*)\b/;
$('*').filter(function() { return rLiveVal.test(this.className); }).each(function() {
var variablePart = rLiveVal.exec(this.className)[1];
//
// ... do something ...
//
});
(or some variation on that theme).
Let's say I'm generating markup through server-side code. I'm generating a bunch of HTML tags but I want to add custom client-side behavior.
With JavaScript (if I had a reference to the DOM node) I could have written:
var myDOMNode = ...
myDOMNode.myCustomAttribute = "Hi!";
Now the issue here is that I don't want to qualify every element with an unique id just to initialize data. And it's really strange to me, that there's not an easier and unobtrusive way to attach client-side behavior.
If I'm remembing this correctly, this is valid IE stuff.
<div onload="this.myCustomAttribute='Hi!'"></div>
If I was able to do this, I should be able to access it's "data context" though the identifier 'myCustomAttribute', which is really what I want.
The following will work but not validate:
<div myattribute="myvalue"></div>
But if you are injecting it into the HTML with Javascript, then perhaps that's not concern for you. Otherwise, you can use something like jQuery to process the elements before adding them to the DOM:
$(elements).each(function(){
$(this).attr('myattribute','myvalue');
});
First off you should access custom attributes using the getAttribute and setAttribute methods if you want your code to work on other browsers than IE.
As to your event handler question that really depends on how you add the event handler.
Assigning a function directly to the elements onXXXX property would allow you access the the element via this.
If you use IE's attachEvent you can't use this, you can access the element that generated the event using event.srcElementbut that may be child element of the div. Hence you will need to test for the existance of myCustomAttribute and search up the ancestors until you find it.
I do appricate the input but I've finally figured this out and it's the way I go about initialization that has been the thorn in my side.
What you never wan't do is to pollute your global namespace with a bunch of short lived identifiers. Any time you put id="" on an element you're doing exactly that (same thing for any top level function). By relying on jQuery, HTML5 data and CSS there's a solution to my problem which I think is quite elegant.
What I do is that I reserve a CSS class for a specific behavior and then use HTML5 data to parameterize the behavior. When the document is ready, I query the document (using Query) for the CSS class that represents the behavior and initialize the client-side behavior.
I've been doing a lot of ASP.NET and within this context both the id="" and name="" belongs to ASP.NET and is pretty useless for anything else than internal ASP.NET stuff. What you typically find yourself doing is to get at a server-side property called ClientID you can refer to this from client-side JavaScript, it's a lot of hassle. They made it easier in 4.0 but fundamentally I think it's pretty much broken.
Using this hybrid of CSS, HTML5 data and jQuery solves this problem altogether. Here's an example of an attached behavior that uses regular expressions to validate the input of a textbox.
<input type="text" class="-input-regex" data-regex="^[a-z]+$" />
And here's the script:
$(function () {
function checkRegex(inp) {
if (inp.data("regex").test(inp.val()))
inp.data("good-value", inp.val());
else
inp.val(inp.data("good-value"));
}
$(".-input-regex")
.each(function () {
// starting with jQuery 1.5
// you can get at HTML5 data like this
var inp = $(this);
var pattern = inp.data("regex");
inp.data("regex", new RegExp(pattern));
checkRegex(inp);
})
.keyup(function (e) {
checkRegex($(this));
})
.change(function (e) {
checkRegex($(this));
})
.bind("paste", undefined, function (e) {
checkRegex($(this));
})
;
});
Totally clean, no funky id="" or obtrusive dependency.
In HTML5 there are HTML5 data attributes introduced exactly for the case.
<!DOCTYPE html>
<div data-my-custom-attribute='Hi!'></div>
is now corect, validating html. You can use any name starting with data- in any quantity.
There is jQuery .data method for interaction with them. Use .data( key ) to get, .data(key, value) to set data-key attribute. For example,
$('div').each(function () {
$(this).html($(this).data('myCustomAttribute')).data('processed', 'OK');
});
How about this?
<script>
function LoadElement(myDiv)
{
alert(this.myCustomAttribute);
}
</script>
<div onload="LoadElement(this)"></div>
not tested btw
Since you're trying to do this for multiple elements, you may try name attributes and getElementsByName.
<div name="handleonload">...</div>
window.onload = function () {
var divs = document.getElementsByName('handleonload');
for (var i = 0; i < divs.length; i += 1) {
divs[i].foo = 'bar';
}
};
Alternatively, you can use selectors, using libraries (such as jQuery and Prototype) and their respective iterators. This will also allow for you to search by other attributes (such as class).
Though, be cautious with your terminology:
obj.property = value;
<tag attribute="value">
<div style="width:100px;height:100px;border:solid black 1px" myCustomAttribute='Hi!' onclick="alert(myCustomAttribute);"></div>
The onload event is used for server side events. Its not part of the standard html element events.
Take a look at the following functions (especially the walk_the_dom one):
// walk_the_DOM visits every node of the tree in HTML source order, starting
// from some given node. It invokes a function,
// passing it each node in turn. walk_the_DOM calls
// itself to process each of the child nodes.
var walk_the_DOM = function walk(node, func) {
func(node);
node = node.firstChild;
while (node) {
walk(node, func);
node = node.nextSibling;
}
};
// getElementsByAttribute takes an attribute name string and an optional
// matching value. It calls walk_the_DOM, passing it a
// function that looks for an attribute name in the
// node. The matching nodes are accumulated in a
// results array.
var getElementsByAttribute = function (att, value) {
var results = [];
walk_the_DOM(document.body, function (node) {
var actual = node.nodeType === 1 && node.getAttribute(att);
if (typeof actual === 'string' &&
(actual === value || typeof value !== 'string')) {
results.push(node);
}
});
return results;
};
With the above two functions at hand, now we can do something like this:
some link
<script>
var els = getElementsByAttribute('dreas');
if (els.length > 0) {
els[0].innerHTML = 'changed text';
}
</script>
Notice how now I am making finding that particular element (which has an attribute called dreas) without using an id or a class name...or even a tag name
Looks like jQuery is the best bet for this one based on my searching. You can bind an object to a DOM node by:
var domNode = ...
var myObject = { ... }
$(domNode).data('mydata', mymyObj);
then you can call the data back up the same way, using your key.
var myObect = $(domNode).data('mydata');
I assume you could also store a reference to this within this object, but that may be more info then you really want. Hope I could help.
HI All,
I have a piece of javaScript that removes commas from a provided string (in my case currency values)
It is:
function replaceCommaInCurrency(myField, val)
{
var re = /,/g;
document.net1003Form.myField.value=val.replace(re, '');
}
'MyField' was my attempt to dynamically have this work on any field that I pass in, but it doesn't work, I get errors saying 'MyField' is not valid. I sort of get my, but I thought this was valid.
I am calling by using: onBlur="replaceCommaInCurrency(this.name, this.value);return false;"
this.name and this.value are passing in the right values...field name and its value.
How do I do this dynamically?
-Jason
You can use eval to make your code snippet work:
eval("document.net1003Form." + myField + ".value=val.replace(re, '');");
As mentioned below, the square brackets work (and don't suck like eval), stupid me for forgetting about those:
document.net1003Form[myField].value=val.replace(re, '');
Alternatively, try something like this:
function replaceCommaInCurrency(field){
var re = /,/g;
field.value = field.value.replace(re, '');
}
Which gets called like so:
onBlur="replaceCommaInCurrency(this); return false";
You should consider using a javascript toolkit for things like this. You could set a class like "currency" on each input, then use this snippet of jQuery based Javascript to handle everything:
$(function(){
$("input.currency").bind('blur', function(){
this.value = $(this).val().replace(',', '');
})
});
This code would fire on document ready, attach an event handler to each input with currency as its class, and then do the replacements. Note that you don't need a regex for replacement as well.
If you code it right into the markup like that, e.g. onblur="replaceCommaInCurrency(this)", the control originating the event gets passed as the parameter. Then you should be able to do something like:
myField.value = myField.value.replace(re, '');
with jQuery:
var jqField = $(myField);
jqField.val(jqField.val().replace(re, ''));
In general, you should be using a framework that will handle low level functionality like this, but the specific answer to your question is to use bracket notation for the field name:
function replaceCommaInCurrency( myField, val)
{
var re = /,/g;
document.net1003Form[myField].value=val.replace(re, '');
}
function removeCommaInCurrency(myField)
{
var re = /,/g;
myField.value=myField.value.replace(re, '');
}
-- and then call it like this:
<input type="text" name="..." onchange="removeCommaInCurrency(this);">
flatline and roenving's solution with ‘this’ is the cleaner approach, it also avoids the problems of ‘document.formname.fieldname’.
(Use ‘document.forms.formname’ to access a form without possible clashing on forms having the same name as members of the document object, and ‘forms.elements.fieldname’ to do the same with fields. Like all JavaScript object, object[namevariable] can also be used. Or, better, add IDs and use the unambiguous document.getElementById method.)
By moving binding into the script you can also remove the inline JavaScript of the onclick attribute, making the markup cleaner still:
<input type="text" class="number" name="something" />
...
<script type="text/javascript"> // external script is best, linked after all forms
function numberfield_bind() {
var inputs= document.getElementsByTagName('input');
for (var inputi= inputs.length; inputi-->0;)
if (inputs[inputi].className=='number')
inputs[inputi].onchange= numberfield_change;
}
function numberfield_change() {
this.value= this.value.split(',').join('');
}
numberfield_bind();
</script>