I am trying to access the d attribute of a path created in Javascript. The result of printing the path element is:
path class=β"coastline"
d="M641.2565741281438,207.45837080935186L640.7046722156485,207.0278378856494L640.6985715873882,207.1279196729914L640.8663103175278,207.53837609537672L640.8542041922302,207.73856415298116L641.04637606029"
... with a longer path. I can access the class attribute by using the getAttribute method on class. However, when I try to access the d attribute, it gives me null. Is there something else I should be doing?
edit: here is how I am currently attempting to access the d attribute (I specifically want the coastline):
var path = d3.geo.path().projection(globe.projection).pointRadius(7);
var coastline = d3.select(".coastline");
console.log(coastline[0][0]);
console.log(coastline[0][0].getAttribute('class'));
console.log(coastline[0][0].getAttribute('d'));
The d attribute of the SVGPathElement "is a string which contains a series of path descriptions."
You can get it and set it through the getAttribute()/setAttribute() methods.
Once interpreted by the browser, the Path Object will contain an SVGPathSegListcreated from this string. This SVGPathSegList will itself contain different PathSegXTo objects.
You can access this list and modify each of the Path Segments by getting the pathSegList property of your path object, which is an ArrayLike Object, but the original string is only accessible through the getAttribute method.
var p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
p.setAttribute('class', 'coastline');
svg.appendChild(p);
// set the attribute
p.setAttribute('d', 'M50,25L60,105L65,65');
// move the third point on x axis after 1 second
setTimeout(function() {
p.pathSegList[2].x += 50;
var coastline = d3.select(".coastline");
// get the attribute with DOM method
snippet.log('from getAttribute : ' + coastline[0][0].getAttribute('d'));
// get it from d3 method
snippet.log('from d3.attr() : ' + coastline.attr('d'));
}, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<svg id="svg"></svg>
Sorry! I want to not express my opinion clearly, check the following code directly
var p = document.getElementById('test');
// general attribute | property, bi-directional
console.log(p.id);// test
console.log(p.getAttribute('id'));// test
// custom attribute, <p class='m-test' id='test' data='data'></p> and p.setAttribute('data', 'data'); one-way, only object.getAttribute() works
console.log(p.data);// undefined
console.log(p.getAttribute('data'))// data
// custom property; one-way ,only object.propery works
p.proData = 'property';
console.log(p.proData);// property
console.log(p.getAttribute('proData'));// null
<p class='m-test' id='test' data='data'>
this is a prograph
<p/>
you can set the 'd' attribute by using setAttribute method, only by getAttribute() method you get value the 'd' attribute.
Related
Using only pure JavaScript, what is the most efficient way to select all DOM elements that have a certain data- attribute (let's say data-foo).
The elements may be different, for example:
<p data-foo="0"></p><br/><h6 data-foo="1"></h6>
You can use querySelectorAll:
document.querySelectorAll('[data-foo]');
document.querySelectorAll("[data-foo]")
will get you all elements with that attribute.
document.querySelectorAll("[data-foo='1']")
will only get you ones with a value of 1.
document.querySelectorAll('[data-foo]')
to get list of all elements having attribute data-foo
If you want to get element with data attribute which is having some specific value e.g
<div data-foo="1"></div>
<div data-foo="2"></div>
and I want to get div with data-foo set to "2"
document.querySelector('[data-foo="2"]')
But here comes the twist ... what if I want to match the data attirubte value with some variable's value? For example, if I want to get the elements where data-foo attribute is set to i
var i=2;
so you can dynamically select the element having specific data element using template literals
document.querySelector(`[data-foo="${i}"]`)
Note even if you don't write value in string it gets converted to string like if I write
<div data-foo=1></div>
and then inspect the element in Chrome developer tool the element will be shown as below
<div data-foo="1"></div>
You can also cross verify by writing below code in console
console.log(typeof document.querySelector(`[data-foo="${i}"]`).dataset('dataFoo'))
why I have written 'dataFoo' though the attribute is data-foo reason dataset properties are converted to camelCase properties
I have referred below links:
MDN: data-*
MDN: Using data attributes
Try it β here
<!DOCTYPE html>
<html>
<head></head>
<body>
<p data-foo="0"></p>
<h6 data-foo="1"></h6>
<script>
var a = document.querySelectorAll('[data-foo]');
for (var i in a) if (a.hasOwnProperty(i)) {
alert(a[i].getAttribute('data-foo'));
}
</script>
</body>
</html>
Here is an interesting solution: it uses the browsers CSS engine to to add a dummy property to elements matching the selector and then evaluates the computed style to find matched elements:
It does dynamically create a style rule [...] It then scans the whole document (using the
much decried and IE-specific but very fast document.all) and gets the
computed style for each of the elements. We then look for the foo
property on the resulting object and check whether it evaluates as
βbarβ. For each element that matches, we add to an array.
Native JavaScript's querySelector and querySelectorAll methods can be used to target the element(s). Use a template string if your dataset value is a variable.
var str = "term";
var term = document.querySelectorAll(`[data-type=${str}]`);
console.log(term[0].textContent);
var details = document.querySelector('[data-type="details"]');
console.log(details.textContent);
<dl>
<dt data-type="term">Thing</dt>
<dd data-type="details">The most generic type.</dd>
</dl>
var matches = new Array();
var allDom = document.getElementsByTagName("*");
for(var i =0; i < allDom.length; i++){
var d = allDom[i];
if(d["data-foo"] !== undefined) {
matches.push(d);
}
}
Not sure who dinged me with a -1, but here's the proof.
http://jsfiddle.net/D798K/2/
While not as pretty as querySelectorAll (which has a litany of issues), here's a very flexible function that recurses the DOM and should work in most browsers (old and new). As long as the browser supports your condition (ie: data attributes), you should be able to retrieve the element.
To the curious: Don't bother testing this vs. QSA on jsPerf. Browsers like Opera 11 will cache the query and skew the results.
Code:
function recurseDOM(start, whitelist)
{
/*
* #start: Node - Specifies point of entry for recursion
* #whitelist: Object - Specifies permitted nodeTypes to collect
*/
var i = 0,
startIsNode = !!start && !!start.nodeType,
startHasChildNodes = !!start.childNodes && !!start.childNodes.length,
nodes, node, nodeHasChildNodes;
if(startIsNode && startHasChildNodes)
{
nodes = start.childNodes;
for(i;i<nodes.length;i++)
{
node = nodes[i];
nodeHasChildNodes = !!node.childNodes && !!node.childNodes.length;
if(!whitelist || whitelist[node.nodeType])
{
//condition here
if(!!node.dataset && !!node.dataset.foo)
{
//handle results here
}
if(nodeHasChildNodes)
{
recurseDOM(node, whitelist);
}
}
node = null;
nodeHasChildNodes = null;
}
}
}
You can then initiate it with the following:
recurseDOM(document.body, {"1": 1}); for speed, or just recurseDOM(document.body);
Example with your specification: http://jsbin.com/unajot/1/edit
Example with differing specification: http://jsbin.com/unajot/2/edit
I would like when I'm creating an object in Js to be able to define an attribut including the value of a previous attribut of the same object (therefore not to repeat element if I want to define an attribut with a part of an other attribut), but I don't know if it's possible.
I show you my code:
var Sel = {
timSand: document.getElementById('tim-sand'),
timSandHei: getComputedStyle(timSand).height, // not Working
}
var Sel = {
timSand: document.getElementById('tim-sand'),
timSandHei: getComputedStyle(document.getElementById('tim-sand')).height, // Working but a bit dirty
}
So when I'm doing the first exemple, I have an error, and I have to replace timSand in the second line by document.getElementById('tim-sand'), like on the second exemple.
Do you know a way to avoid this ?
You cannot because the object does not exist yet, so you cannot reference it.
But you can use a variable to avoid the heavy DOM access.
var sand = document.getElementById('tim-sand')
var Sel = {
timSand: sand,
timSandHei: getComputedStyle(sand).height, //Working
}
When i did the "inspect Element" the HTML code i got is,
<domain-picker class="pull-right"
current="{"label":"AMN/GRP","value":"assf2324234"}" in-header="true" show-in-header="true">
</domain-picker>
Could anyone please let me know in jquery
how to get the value "assf2324234" of the above "domain-picker" element.
how to set with new string for the "value" attribute of the above "domain-picker" element
Following is commented to show steps
// target element
var $picker = $('domain-picker'),
// parse current attribute value string to object
current= JSON.parse( $picker.attr('current'));
// change value
current.value ='someOtherString';
// stringify object and put back as attribute value
$picker.attr('current', JSON.stringify(current));
Modify your HTML, Use single quotes for current attribute
<domain-picker class="pull-right"
current='{"label":"AMN/GRP","value":"assf2324234"}' in-header="true" show-in-header="true">
</domain-picker>
in jQuery
var json = $("domain-picker").attr("current");
json = JSON.parse(json)
var value = json.value;
Here is working demo https://jsfiddle.net/758y0fp1/1/
As #charlietfl mentioned, if you wanna use jQuery, his answer is the 1 you need, this can be done with pure Javascript too, ie.
// getting the element
var picker = document.getElementsByTagName('domain-picker')[0];
// parsing current attribute string to object
var current= JSON.parse(picker.getAttribute('current'));
// changing the value
current.value ='newString';
// stringify the object and set the attribute again like
picker.setAttribute('current', JSON.stringify(current));
You need to first get the value of attribute .attr() in jquery or getAttribute() in javascript will help. Now since the value is an invalid JSON(as per the html provided by you), convert the invalid JSON to valid and then select the value.
var obj = document.querySelector("domain-picker").getAttribute("current");
var json = obj.replace((/'/g), "\"");
var obj = JSON.parse(json)
//console log the retrieved value.
console.log("value :", obj["value"])
// set attribute now
obj["value"] = "1234567";
document.querySelector("domain-picker").setAttribute('current', JSON.stringify(obj));
<domain-picker class="pull-right"
current="{'label':'AMN/GRP','value':'assf2324234'}" in-header="true" show-in-header="true">
Hello inpsect me to see the changed attribute value.
</domain-picker>
This appears very simple but I cannot see why it's not working. The selector is correct however the div .faqContent is simply not being updated with the data-height attribute.
$('.faqItem .faqContent').each(function(){
var h = $(this).height();
$(this).data('height',h);
});
I have checked that var h is correct, it is in colsole.log as correctly holding the height.
EDIT
It's absolutely not conflict, and console shows no errors.
The data function confuses a lot of people, it's not just you. :-)
data manages jQuery's internal data object for the element, not data-* attributes. data only uses data-* attributes to set initial values, and more, it guesses at what type you want those to be based on what they look like (so something that looks like a number is converted to a number; something that looks like JSON gets converted to an object). The data method never sets data-* attributes on elements, it only sets the data on its internal data object. That means the two (the internal data object and the attribute) get out of sync:
const t = $("#target");
let value;
// Getting the attribute always gets a string
value = t.attr("data-height");
console.log(`${value} (${typeof value})`); // 1 (string)
// Using `.data`, jQuery will guess that because the attribute looks like a number,
// you want it converted to a number
value = t.data("height");
console.log(`${value} (${typeof value})`); // 1 (number)
// `data` only sets the internal data object properties, not the attribute...
t.data("height", 2);
// ...so the attribute still has `"1"`
value = t.attr("data-height");
console.log(`${value} (${typeof value})`); // 1 (string)
// ...even though the data object has 2
value = t.data("height");
console.log(`${value} (${typeof value})`); // 2 (number)
<div id="target" data-height="1"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If you want to actually set a data-* attribute, use attr:
$(this).attr("data-height", h);
const t = $("#target");
let value;
value = t.attr("data-height");
console.log(`${value} (${typeof value})`); // 1 (string)
// `attr` converts whatever you give it to string
t.attr("data-height", 2);
value = t.attr("data-height");
console.log(`${value} (${typeof value})`); // 2 (string)
<div id="target" data-height="1"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
But if you only want this information for future use, data is fine (assuming you're okay with its automatic type conversion), just don't expect to see it in the DOM inspector, because jQuery doesn't write this information to the DOM.
You will not be able to see it in the element inspector but it is there as jquery set the data attribute internally.
try console.log($(this).data('height'));
.data() is only stores the associated new value in memory(or internally). It'll not change the attribute in the DOM hence you cannot see it updated using inspector tools.
To change the attribute, you can use .attr():
$('.faqItem .faqContent').each(function(){
var h = $(this).height();
$(this).attr('data-height',h);
});
JQuery .data() stores the value on the element itself, it won't add an attribute.
http://api.jquery.com/data/
If you want to add an attribute, use attr:
$('.faqItem .faqContent').each(function(){
var h = $(this).height();
$(this).attr('data-height', h);
});
http://api.jquery.com/attr/
Is it possible to extract properties of a HTML tag using Javascript.
For example, I want to know the values present inside with the <div> which has align = "center".
<div align="center">Hello</div>
What I know is:
var division=document.querySelectorAll("div");
but it selects the elements between <div> & </div> and not the properties inside it.
I want to use this in the Greasemonkey script where I can check for some malicious properties of a tag in a website using Javascript.
Hope I'm clear..!!
You are looking for the getAttribute function. Which is accessible though the element.
You would use it like this.
var division = document.querySelectorAll('div')
for(var i=0,length=division.length;i < length;i++)
{
var element = division[i];
var alignData = division.getAttribute('align'); //alignData = center
if(alignData === 'center')
{
console.log('Data Found!');
}
}
If you're looking to see what attributes are available on the element, these are available though
division.attributes
MDN Attributes
So for instance in your example if you wanted to see if an align property was available you could write this.
//Test to see if attribute exists on element
if(division.attributes.hasOwnProperty('align'))
{
//It does!
}
var test = document.querySelectorAll('div[align="center"]');