Jquery function implementation - javascript

I write this function for getting xpath location:
JQuery (this function get xpath):
function getXPath(node, path) {
path = path || [];
if(node.parentNode) {
path = getXPath(node.parentNode, path);
}
if(node.previousSibling) {
var count = 1;
var sibling = node.previousSibling
do {
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {count++;}
sibling = sibling.previousSibling;
} while(sibling);
if(count == 1) {count = null;}
} else if(node.nextSibling) {
var sibling = node.nextSibling;
do {
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {
var count = 1;
sibling = null;
} else {
var count = null;
sibling = sibling.previousSibling;
}
} while(sibling);
}
if(node.nodeType == 1) {
path.push(node.nodeName.toLowerCase() + (node.id ? "[#id='"+node.id+"']" : count > 0 ? "["+count+"]" : ''));
}
return path;
};
and I have an iframe:
<iframe id="frameID" width="100%" src="http://www.example.com"></iframe>
But Now I have a problem how to integrate my jquery function and where to when i click somewhere in Iframe get xpath result?

You wrote that function? -- That code was written nearly 5 years ago on DZone: http://snippets.dzone.com/posts/show/4349 -- This includes instructions for usage for the function.

You can only do that when the iframe location is in the same domain as the page embedding it.
If so, get the Document from the iframe (document.getElementById('frameId').contentDocument, see MDN) and add a click event listener to it. The event you're receiving will contain a reference to the target node.

Related

At mobile device too late to use display none, block

At Pc it works well.
but mobile it is too late.
is any other faster method or the others?
function country_change(country,countries)
{
var cls = document.getElementsByClassName("country_events");
if(document.readyState == "loading")
{
alert('not loading.');
} else
{
for (n=0; n < cls.length; n++)
{
var elem = cls[n];
var div_elem = elem.getElementsByTagName('div').length;
for (m=1; m < div_elem; m++)
{
if (elem.getAttribute('name') == country)
{
if (elem.getElementsByTagName('div')[m].style.display == "none")
{
elem.getElementsByTagName('div')[m].style.display="block";
increaseHeight()
}
}
else
{
elem.getElementsByTagName('div')[m].style.display="none";
increaseHeight()
}
}
}
}
}
at pc it works about 1~3 seconds, but mobile it takes almost 10~20 sec.
i think display is not good method, but there is no other way isn't it?
The collection returned by:
var cls = document.getElementsByClassName("country_events");
is live, so any modification to the DOM may require the browser to refresh the collection. That may happen a lot more often that you think (and much more in some browsers than others), so you may want to convert that to an array or use querySelectorAll (which returns a static collection) instead:
var cls = document.querySelectorAll(".country_events");
Then you have:
var elem = cls[n];
var div_elem = elem.getElementsByTagName('div').length;
so it is good to cache elem, but getElementsByTagName also returns a live collection so use querySelectorAll again:
var div_elem = elem.querySelectorAll('div').length;
div_elem seems an inappropriate name, perhaps divCount would be better?
Then:
if (elem.getAttribute('name') == country)
you can save a method call by accessing the property directly:
if (elem.name == country)
And then the awfully wastefull:
if (elem.getElementsByTagName('div')[m].style.display == "none")
{
elem.getElementsByTagName('div')[m].style.display="block";
increaseHeight()
You got the list of divs earlier, so cache it there
var divs = elem.querySelectorAll('div');
var divCount = divs.length;
Now reuse it:
if (divs[m].style.display == 'none') {
divs[m].style.display = '';
} else {
divs[m].style.display = 'none';
}
increaseHeight();
which can be shortened to:
divs[m].style.display == divs[m].style.display == 'none'? '' : 'none';
increaseHeight();
However the conditional operator is usually slower than the equivalent if..else.
So the function becomes:
function country_change(country,countries) {
var cls = document.querySelectorAll('.country_events');
if(document.readyState == "loading") {
alert('not loading.');
} else {
for (var n=0, nLen=cls.length; n<nLen; n++) {
var elem = cls[n];
var divs = elem.querySelectorAll('div');
var divCount = divs.length;
for (var m = 1; m < divCount; m++) {
if (elem.name == country) {
if (divs[m].style.display == 'none') {
divs[m].style.display = '';
} else {
divs[m].style.display = 'none';
}
increaseHeight()
}
}
}
}
}
Note that querySelectorAll is not supported by IE 7 and lower.
Setting element.style.display to '' (empty string) allows it to return to it's default or computed style and means you don't have to know what that is for each different type of element or what is included in CSS rules.

after picking selected range and getting the parent node of the selection is there a way to find the absolute path? [duplicate]

Say I've selected a span tag in a large html document. If I treat the entire html document as a big nested array, I can find the position of the span tag through array indexes. How can I output the index path to that span tag? eg: 1,2,0,12,7 using JavaScript.
Also, how can I select the span tag by going through the index path?
This will work. It returns the path as an array instead of a string.
Updated per your request.
You can check it out here: http://jsbin.com/isata5/edit (hit preview)
// get a node's index.
function getIndex (node) {
var parent=node.parentElement||node.parentNode, i=-1, child;
while (parent && (child=parent.childNodes[++i])) if (child==node) return i;
return -1;
}
// get a node's path.
function getPath (node) {
var parent, path=[], index=getIndex(node);
(parent=node.parentElement||node.parentNode) && (path=getPath(parent));
index > -1 && path.push(index);
return path;
}
// get a node from a path.
function getNode (path) {
var node=document.documentElement, i=0, index;
while ((index=path[++i]) > -1) node=node.childNodes[index];
return node;
}
This example should work on this page in your console.
var testNode=document.getElementById('comment-4007919');
console.log("testNode: " + testNode.innerHTML);
var testPath=getPath(testNode);
console.log("testPath: " + testPath);
var testFind=getNode(testPath);
console.log("testFind: " + testFind.innerHTML);
Using jquery:
var tag = $('#myspan_id');
var index_path = [];
while(tag) {
index_path.push(tag.index());
tag = tag.parent();
}
index_path = index_path.reverse();
Using the DOM
node = /*Your span element*/;
var currentNode = node;
var branch = [];
var cn; /*Stores a Nodelist of the current parent node's children*/
var i;
while (currentNode.parentNode !== null)
{
cn = currentNode.parentNode.childNodes;
for (i=0;i<cn.length;i++)
{
if (cn[i] === currentNode)
{
branch.push(i);
break;
}
}
currentNode = currentNode.parentNode;
}
cn = document.childNodes;
for (i=0;i<cn.length;i++)
{
if (cn[i] === currentNode)
{
branch.push(i);
break;
}
}
node.innerHTML = branch.reverse().join(",");
composedPath for native event.
(function (E, d, w) {
if (!E.composedPath) {
E.composedPath = function () {
if (this.path) {
return this.path;
}
var target = this.target;
this.path = [];
while (target.parentNode !== null) {
this.path.push(target);
target = target.parentNode;
}
this.path.push(d, w);
return this.path;
};
}
})(Event.prototype, document, window);
use:
var path = event.composedPath()

Remove image by src

I need to remove certain images with a specific src:
http://ukn.cs-mtc.com/wp-content/plugins/download-monitor/page-addon/thumbnail.gif
Is there a way to remove the whole <img> tag with JavaScript?
I had some free time (and a strange urge to write some JavaScript...), so I thought I'd offer this functional approach:
function removeNeighbour(el, elType) {
if (!el) {
return false;
}
else if (el.nextElementSibling) {
var nxt = el.nextElementSibling;
}
else {
var nxt = el.nextSibling;
while (nxt.nodeType !== 1 && nxt.nextSibling) {
nxt = nxt.nextSibling;
}
}
if (elType && nxt.tagName.toLowerCase() == elType.toLowerCase()) {
nxt.parentNode.removeChild(nxt);
}
else if (!elType) {
nxt.parentNode.removeChild(nxt);
}
}
function clearElsWithAttrEquals(el, attr, val, andNeighbour, neighbourType) {
if (!el || !attr || !val) {
return false;
}
else if (document.querySelectorAll) {
var matchingElems = document.querySelectorAll(el + '[' + attr + '="' + val + '"]'),
neighbourType = neighbourType || '';
for (var i = matchingElems.length - 1; i >= 0; i--) {
if (andNeighbour === true) {
removeNeighbour(matchingElems[i], neighbourType);
}
matchingElems[i].parentNode.removeChild(matchingElems[i]);
}
}
else {
var matchingElems = document.getElementsByTagName(el),
len = (matchingElems.length - 1);
for (var i = len; i >= 0; i--) {
if (matchingElems[i][attr] == val) {
matchingElems[i].parentNode.removeChild(matchingElems[i]);
}
}
}
}
clearElsWithAttrEquals('img', 'src', 'http://ukn.cs-mtc.com/wp-content/plugins/download-monitor/page-addon/thumbnail.gif', true, 'p');​​​
JS Fiddle demo.
Quick guide to (and the only documentation I'm ever likely to write for) clearElsWithAttrEquals() function:
clearElsWithAttrEquals(el, attr, val[, andNeighbour[, neighbourType]]);
el : (string) identifies the element type ('img','p','span'...).
attr : (string) identifies which attribute you want to search by ('id', 'src', etc...)
val : (string) this will only match if the value is exactly equal to the string
andNeighbour : (Boolean, optional) do you want to remove the neighbouring element too? Pass true (if yes) or false (if not).
neighbourType : (string, optional) remove the neighbour only if it's of this element-type ('div','hr','span', etc) ; if omitted then the next sibling element will be removed regardless of its type.
References:
document.querySelectorAll() (Compatibility).
nextElementSibling (Compatibility).
nextSibling (Compatibility).
node.nodeType (Compatibility).
parentNode (Compatibility).
removeChild() (Compatibility).
String.toLowerCase().
while (condition) {/*...*/}.
Do you use jQuery? If so,
$('img[src="http://ukn.cs-mtc.com/wp-content/plugins/download-monitor/page-addon/thumbnail.gif"]').remove(); should work.
Otherwise...
var img = document.getElementsByTagName('img');
for(var i=0,i<img.length;i++) {
if(img[i].src == 'http://ukn.cs-mtc.com/wp-content/plugins/download-monitor/page-addon/thumbnail.gif') {
img[i].parentNode.removeChild(img[i]);
}
}
This can be done easily with jQuery:
$('img[src="<path>"]').remove();

record and retrieve html element / node path using javascript

Say I've selected a span tag in a large html document. If I treat the entire html document as a big nested array, I can find the position of the span tag through array indexes. How can I output the index path to that span tag? eg: 1,2,0,12,7 using JavaScript.
Also, how can I select the span tag by going through the index path?
This will work. It returns the path as an array instead of a string.
Updated per your request.
You can check it out here: http://jsbin.com/isata5/edit (hit preview)
// get a node's index.
function getIndex (node) {
var parent=node.parentElement||node.parentNode, i=-1, child;
while (parent && (child=parent.childNodes[++i])) if (child==node) return i;
return -1;
}
// get a node's path.
function getPath (node) {
var parent, path=[], index=getIndex(node);
(parent=node.parentElement||node.parentNode) && (path=getPath(parent));
index > -1 && path.push(index);
return path;
}
// get a node from a path.
function getNode (path) {
var node=document.documentElement, i=0, index;
while ((index=path[++i]) > -1) node=node.childNodes[index];
return node;
}
This example should work on this page in your console.
var testNode=document.getElementById('comment-4007919');
console.log("testNode: " + testNode.innerHTML);
var testPath=getPath(testNode);
console.log("testPath: " + testPath);
var testFind=getNode(testPath);
console.log("testFind: " + testFind.innerHTML);
Using jquery:
var tag = $('#myspan_id');
var index_path = [];
while(tag) {
index_path.push(tag.index());
tag = tag.parent();
}
index_path = index_path.reverse();
Using the DOM
node = /*Your span element*/;
var currentNode = node;
var branch = [];
var cn; /*Stores a Nodelist of the current parent node's children*/
var i;
while (currentNode.parentNode !== null)
{
cn = currentNode.parentNode.childNodes;
for (i=0;i<cn.length;i++)
{
if (cn[i] === currentNode)
{
branch.push(i);
break;
}
}
currentNode = currentNode.parentNode;
}
cn = document.childNodes;
for (i=0;i<cn.length;i++)
{
if (cn[i] === currentNode)
{
branch.push(i);
break;
}
}
node.innerHTML = branch.reverse().join(",");
composedPath for native event.
(function (E, d, w) {
if (!E.composedPath) {
E.composedPath = function () {
if (this.path) {
return this.path;
}
var target = this.target;
this.path = [];
while (target.parentNode !== null) {
this.path.push(target);
target = target.parentNode;
}
this.path.push(d, w);
return this.path;
};
}
})(Event.prototype, document, window);
use:
var path = event.composedPath()

Remove All id Attributes from nodes in a Range of Fragment

Is there a way to remove the id attribute of every node in a range or fragment?
Update: I finally found out that the bug I'm struggling with is based on a <[script]> being included in a range, and therefore unexpectedly cloned, when a chrome user does a ctrl+a. My goal would be to remove any instance of <[script]> from the range (or doc fragment), such that it is not replicated when cloned.
You may be able to use a TreeWalker, which works in pretty much all the browers that Range works in.
function actOnElementsInRange(range, func) {
function isContainedInRange(el, range) {
var elRange = range.cloneRange();
elRange.selectNode(el);
return range.compareBoundaryPoints(Range.START_TO_START, elRange) <= 0
&& range.compareBoundaryPoints(Range.END_TO_END, elRange) >= 0;
}
var rangeStartElement = range.startContainer;
if (rangeStartElement.nodeType == 3) {
rangeStartElement = rangeStartElement.parentNode;
}
var rangeEndElement = range.endContainer;
if (rangeEndElement.nodeType == 3) {
rangeEndElement = rangeEndElement.parentNode;
}
var isInRange = function(el) {
return (el === rangeStartElement || el === rangeEndElement ||
isContainedInRange(el, range))
? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
};
var container = range.commonAncestorContainer;
if (container.nodeType != 1) {
container = container.parentNode;
}
var walker = document.createTreeWalker(document,
NodeFilter.SHOW_ELEMENT, isInRange, false);
while (walker.nextNode()) {
func(walker.currentNode);
}
}
actOnElementsInRange(range, function(el) {
el.removeAttribute("id");
});
yes: http://api.jquery.com/removeAttr/

Categories

Resources