Javascript getting xlink:href from XPath using document.evaluate - javascript

Hey all I am having the worst time trying to figure out why my XPath code below is not able to find the Image tag and the HREF link that goes with it within my document.
The XPath (full) looks like this:
//html/body/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/a/div/svg/g/descendant::image[starts-with(#href,'https://')]
The javascript code I am using is:
function checking(Path) {
const nodes = document.evaluate(Path, document, null, XPathResult.ANY_TYPE, null);
const result = {
Data: []
};
let attr = nodes.iterateNext();
result.Data.push({ href: attr});
return JSON.stringify(result);
}
console.log(checking("//html/body/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div/a/div/svg/g/descendant::image[starts-with(#href,'https://')]"));
And the HTML that I am looking through to get said image Xlink:HREF:
<body class="">
<div id="" style="">
<div>
<div class="">
<div class="">
<div class="">
<div class="">
<div class="">
<div class="">
<div class="">
<div class="">
<div class="" role="5ma">
<div class="">
<div class="">
<div class="">
<div>
<div class="">
<div class="">
<div class="">
<a aria-label="" class="" href="https://www.this.com/link/is/not/needed" tabindex="0">
<div class="">
<svg aria-label="" class="" data-visualcompletion="ignore-dynamic" role="img" style="height: 168px; width: 168px;">
<g mask="url(#)">
<image x="0" y="0" height="100%" width="100%" xlink:href="https://www.google.com/logos/doodles/2021/seasonal-holidays-2021-6753651837109324-6752733080595603-cst.gif" style="height: 168px; width: 168px;"></image>
<circle class="" cx="8" cy="4" r="4"></circle>
</g>
</svg>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
I keep getting NULL for the output for some reason? And here is a jsfiddle to visually test it.
{
"Data": [
{
"href": null
}
]
}
Anyone have a clue as to why I am?
UPDATE 1
Checking the "offical" xPath to my project comes out to be this:
// html/body/div1/div/div1/div/div3/div/div/div1/div1/div/div/div1/div2/div/div/div/div1/div/div/svg/g/image
Which I change the latest fiddle to reflect what #bigless suggested in his fiddle but still get null.
Newest fiddle

Alternative to #Jack Fleeting answer (skipping all those divs just for example) with xlink:href selector:
string(//*[name() = 'svg']/*[name()='g']//*[name()='image' and starts-with(#*[name()='xlink:href'],'https://')]/#*[name()='xlink:href'])
This will extract just attribute value as a string (first occurence)

A few things:
First, you have a problem with namespaces and Deprecated XLink URL reference attributes.
Second, in
result.Data.push({
href: attr
});
you should push the node value of the attribute:
result.Data.push({
href: attr.nodeValue
});
Finally, because of the namespace issue, and to simplify the xpath expression, change your comeback to
var comeback = checking("//*[local-name()='image'][starts-with(./#href,'https://')]/#href");
And it should work as in this fiddle.

Related

jquery: how to append DOM element to selector within variable containing other DOM elements

When storing DOM elements in a javascript variable prior to appending them to the actual DOM is there a way with jQuery to select elements inside the variable?
For example,
I have a list of tweets on my page. Every time I click a refresh button I append a new tweet to the list below.
I add the new tweet like follows:
new tweet
<li class="tweet normal-tweet" data-user-name="Dorothy">
<div class="image">
<img height="48" width="48" src="http://twitter.com/api/users/profile_image?screen_name=Dorothy" alt="" />
</div>
<div class="content">
<div class="user">
<a class="user-name" href="http://twitter.com/Dorothy" title="Dorothy">Dorothy</a>
<div class="full-name"></div>
</div>
<div class="text">Once in a lullaby</div>
<div class="time-stamp" data-time="1322631934000">1322631934000</div>
</div>
</li>
Inside each tweet on the page, not the new tweet yet, I use jQuery to append some elements.
I have:
var actionsMarkup =
"<div class='actions'>
<span class='favorite'>Favorite</span>
<span class='retweet'>Retweet</span>
<span class='reply'>Reply</span>
</div>";
and I append it to the element with the .content class
$(actionsMarkup).appendTo('#tweets .tweet .content');
Now, when I make a new tweet I do the following:
$(document).on('click', '.refresh', function() {
newTweet = $(<new tweet code from above>);
actionsMark = $(actionsMarkup);
$(newTweet.appendTo('#tweets');
I need to be able to append the actionsMark contents to the div with class .content. However, I can't just reapply my prior statement of
$(actionsMarkup).appendTo('#tweets .tweet .content');
because that puts the markup on all .content divs again, even if it is already there.
Is there a way for me to use selectors to access the DOM nodes in my newTweet variable before I append it to the document object?
I am thinking something like
$(actionsMarkup).appendTo( newTweet, '.content');
If there is no way with selectors to do this then what are some other quick ways?
List of Tweets and Tweet container
<ul id="tweets" class="normal-tweet show-promoted-tweets">
<li class="tweet promoted-tweet" data-user-name="Dorothy">
<div class="image">
<img height="48" width="48" src="http://twitter.com/api/users/profile_image?screen_name=Dorothy" alt="" />
</div>
<div class="content">
<div class="user">
<a class="user-name" href="http://twitter.com/Dorothy" title="Dorothy">Dorothy</a>
<div class="full-name">Dorothy</div>
</div>
<div class="text">Somewhere over the rainbow</div>
<div class="time-stamp" data-time="1322631934000">3 minutes ago</div>
</div>
</li>
<li class="tweet promoted-tweet" data-user-name="lion">
<div class="image">
<img height="48" width="48" src="http://twitter.com/api/users/profile_image?screen_name=lion" alt="" />
</div>
<div class="content">
<div class="user">
<a class="user-name" href="http://twitter.com/lion" title="lion">lion</a>
<div class="full-name">Lion</div>
</div>
<div class="text">Way up high,</div>
<div class="time-stamp" data-time="1322631934000">17 minutes ago</div>
</div>
</li>
<li class="tweet normal-tweet" data-user-name="scarecrow">
<div class="image">
<img height="48" width="48" src="http://twitter.com/api/users/profile_image?screen_name=scarecrow" alt="" />
</div>
<div class="content">
<div class="user">
<a class="user-name" href="http://twitter.com/scarecrow" title="scarecrow">scarecrow</a>
<div class="full-name">Scarecrow</div>
</div>
<div class="text">And the dreams that you dreamed of,</div>
<div class="time-stamp" data-time="1322631934000">32 minutes ago</div>
</div>
</li>
</ul>
You can use .last(), to select the last element after you append your new tweet, like below:
$(document).on('click', '.refresh', function() {
newTweet = $(<new tweet code from above>);
$(newTweet).appendTo('#tweets');
var actionsMarkup =
"<div class='actions'>
<span class='favorite'>Favorite</span>
<span class='retweet'>Retweet</span>
<span class='reply'>Reply</span>
</div>";
$("#tweets .tweet").last().find(".content").append(actionsMarkup);
});
if you insist to use appendTo(), you can try using :last-child:
$(actionsMarkup).appendTo('#tweets .tweet:last-child .content');
I was looking to see if you can do the same thing, found this question but the existing answer is not useful in my case as i would like to alter the element before adding.
You can create a new dom element in a variable with jQuery and do operations on it as if it is already in the dom before appending it.
Example:
var newTweet = $('<div></div>');
newTweet.addClass('tweet');
newTweet.append('<span class="username"></span>');
newTweet.find('span.username').html('John Doe');
$('body').append(newTweet);
the following will be appended to the body:
<div class="tweet"><span class="username">John Doe</span></div>
Very handy if you are building a reusable interface element (like a dialogue box) with multiple options.

JQuery Parent-Child Selection

I am new to jQuery and am trying to write a script that will run through a menu list and display the correct background image based on the menu item. The menu list is going to be randomly populated so a script is necessary to load the correct image.
The problem is that the attribute where I am able to see which item the menu belongs to is not on the list item itself but on a div contained inside the list item. My question is is it possible to select a child element of the already selected element ?
E.g (the menuli a segment)
$(document).ready( function() {
$(menuli).each( function(index) {
$itemnumber = $(menuli a).attr("href");
switch($itemnumber) {
case 1:
$(this).css("background-image", "image01.jpg");
break;
}
});
});
This is more or less the script I am trying to get, where each list item is iterated through and depending on the href of the link inside the list item a background image is set to that list item.
EDIT
Here is my html:
<div id="divMenuSportGSXSports">
<div class="VociMenuSportG">
<div class="ImgSport" style="background-image:url(../ImgSport.ashx?IDBook=53&IDSport=468&Antepost=0&)">
<img src="buttons_void.png">
</div>
<div class="NomeSport">
<a id="h_w_PC_cSport_repSport_ctl00_lnkSport" href="/Sport/Groups.aspx?IDSport=468&Antepost=0">
<span title="SOCCER">SOCCER</span>
</a>
</div>
</div>
<div class="VociMenuSportG">
<div class="ImgSport" style="background-image:url(../ImgSport.ashx?IDBook=53&IDSport=520&Antepost=0&)">
<img src="buttons_void.png">
</div>
<div class="NomeSport">
<a id="h_w_PC_cSport_repSport_ctl01_lnkSport" href="/Sport/Groups.aspx?IDSport=520&Antepost=0">
<span title="BASEBALL">BASEBALL</span>
</a>
</div>
</div>
<div class="VociMenuSportG">
<div class="ImgSport" style="background-image:url(../ImgSport.ashx?IDBook=53&IDSport=544&Antepost=0&)">
<img src="buttons_void.png">
</div>
<div class="NomeSport">
<a id="h_w_PC_cSport_repSport_ctl02_lnkSport" href="/Sport/Groups.aspx?IDSport=544&Antepost=0">
<span title="CRICKET">CRICKET</span>
</a>
</div>
</div>
<div class="VociMenuSportG">
<div class="ImgSport" style="background-image:url(../ImgSport.ashx?IDBook=53&IDSport=525&Antepost=0&Tema=Supabets)">
<img src="buttons_void.png">
</div>
<div class="NomeSport">
<a id="h_w_PC_cSport_repSport_ctl03_lnkSport" href="/Sport/Groups.aspx?IDSport=525&Antepost=0">
<span title="BASKETBALL">BASKETBALL</span>
</a>
</div>
</div>
<div class="VociMenuSportG">
<div class="ImgSport" style="background-image:url(../ImgSport.ashx?IDBook=53&IDSport=534&Antepost=0&)">
<img src="buttons_void.png">
</div>
<div class="NomeSport">
<a id="h_w_PC_cSport_repSport_ctl04_lnkSport" href="/Sport/Groups.aspx?IDSport=534&Antepost=0">
<span title="ICE HOCKEY">ICE HOCKEY</span>
</a>
</div>
</div>
<div class="VociMenuSportG">
<div class="ImgSport" style="background-image:url(../ImgSport.ashx?IDBook=53&IDSport=523&Antepost=0&)">
<img src="buttons_void.png">
</div>
<div class="NomeSport">
<a id="h_w_PC_cSport_repSport_ctl05_lnkSport" href="/Sport/Groups.aspx?IDSport=523&Antepost=0">
<span title="TENNIS">TENNIS</span>
</a>
</div>
</div>
</div>
Yes you can, use find
var parentElement = $('#someElement');
var childElement = parentElement.find('.child'); //where .child should be your child selector
Where as example code is not clear, I just gave answer to your question.
try to change this:
$(this).css("background-image", "image01.jpg");
to this:
$(this).children("div").css("background-image", "image01.jpg");
If you want to target the direct child of the element, better to use children() than find()
Please refer to this: What is fastest children() or find() in jQuery?

getting undefined values in java-script alert

can anyone please tell me why i'm getting undefined in javascript when i run the below code.
its a simple code for getting the parent div id. All div's are closed properly but still getting undefined.
html
<div id="ricolaId_2" class="ricMo ricIndex ricBlocking ricInline" style="width: 730px; left: 309px; top: 144px; z-index: 13000; display: block;">
<div class="ricTitle">
<a class="ricClose">
<span class="ui-icon ui-icon-close" title="Close">
</span>
</a>
<span class="ricTitle">Manage</span>
</div>
<div class="ricModal ng-scope" style="height: auto;">
<div>
<div>
<div ng-controller="Manage" class="ng-scope">
<div class="ricCenter">
<div class="ricport">
<div class="ricWr">
</div>
</div>
</div>
</div>
<br style=""></br><br style=""></br>
<div align="center" class="row btn-group">
<button onclick="cancel(this)" class="ricSmall" type="button" id="sss" ric:loaded="true">Close</button>
</div>
</div>
</div>
</div>
</div>
script
function cancel(btn)
{
try{
ricId_1 = $(btn).parent().parent();
alert(ricId_1.attr("id"));
}catch(a){alert(a);}
}
To target that id you need:
$(btn).parent().parent().parent().parent().parent();
or:
$(btn).closest('.ricModal').parent();
Demo
Use parents instead of .parent()
function cancel(btn)
{
try{
ricId_1 = $(btn).parents('#ricolaId_2');
alert(ricId_1.attr("id"));
}catch(a){alert(a);}
}
parent method only travels a single level up the DOM tree and parents method travels through multiple level up the DOM tree.
I changed a few things, and look: It's working! You should add an id to ng-scope So, http://jsfiddle.net/8F8Mr/7/
Update
http://jsfiddle.net/8F8Mr/9/

Flowplayer start at specified index of playlist

I have the following code to insert a flowplayer with playlist via javascript on my page. Now I need the player to start at video[playing], this means at a predefined position in the playlist. The console tells me that the object (v.flowplayer) has no method play... what am I doing wrong?
Thanks to the source of the video element, the player starts at the right video, but using the .prev() and .next() functions, messes up the playlist order by playing the second video after using .next(), even if the initial video was the 5th video in the playlist.
var v = videos.eq(2);
var p = $('<div class="fp-playlist"></div>');
var vt = $('<video>');
var s = $("<source>");
var a;
vt.attr({poster: playlist[playing].poster});
s.attr({src: playlist[playing].url, type: "video/" + playlist[playing].videotype});
v.append(vt.append(s));
for(var i = 0; i < playlist.length; i++){
a = $(''.compose(playlist[i].url));
p.append(a);
}
v.append(p);
v.flowplayer().play(playing);
The HTML looks like this, after the javascript has run:
<div class="video flowplayer no-volume fixed-controls no-toggle no-time is-mouseover video0 is-muted is-ready is-paused is-poster" data-embed="false" data-keyboard="false" data-fullscreen="false" style="background-image: url(somepic.jpg);">
<video poster="poster.jpg" class="fp-engine" src="somevid.webm"></video>
<div class="fp-playlist">
</div>
<div class="fp-ratio" style="padding-top: 56.25%;"></div>
<div class="fp-ui">
<div class="fp-waiting">
<em></em>
<em></em>
<em></em>
</div>
<a class="fp-unload"></a>
<p class="fp-speed"></p>
<div class="fp-controls">
<a class="fp-play"></a>
<div class="fp-timeline">
<div class="fp-buffer" style="width: 100%;"></div>
<div class="fp-progress"></div>
</div>
<div class="fp-volume">
<a class="fp-mute"></a>
<div class="fp-volumeslider" style="">
<div class="fp-volumelevel" style="width: 0%;"></div>
</div>
</div>
</div>
<div class="fp-time">
<em class="fp-elapsed">00:00</em>
<em class="fp-remaining">00:12</em>
<em class="fp-duration">00:12</em>
</div>
<div class="fp-message">
<h2></h2>
<p></p>
</div>
</div>
<div class="fp-context-menu" style="left: 489.21875px; top: 179px; display: block;">
<ul>
<li class="copyright">© 2013</li>
<li>About Flowplayer
</li>
<li>GPL based license
</li>
</ul>
</div>
The last javascript line with v.flowplayer().play(playing) should be like:
v.data('flowplayer').play(playing);

Can't seem to get element ID

I have a list of images and I really need to get ID of each image inside my JS, but I don't know how to do that. I've tried this method, but it is returning empty string instead of ID. I tried getting it from DOM elements http://galleria.aino.se/docs/1.2/references/dom/ like $(".galleria-thumbnails img").click(function(){alert((this).id)}); but this method is not working, alert is simply not showing up. Also I did some research here http://galleria.aino.se/docs/1.2/api/methods/ and got this code, but this is showing alert of empty string.
$("#gallery").galleria({
});
myGalleria = Galleria.get(0);
myGalleria.$('thumbnails').click(function(){
alert((this).id);
});
gallery div
<div id="gallery">
<img id="someid" src="http://photoapproaches.files.wordpress.com/2010/03/helen-model-2272.jpg" />
<img id="otherid" src="http://leandrovieira.com/projects/jquery/lightbox/photos/image1.jpg" />
</div>
Console is empty of errors, nothing is showing in console. Also this markup is working fine the gallery plugin is making DOM elements on their own, and that is very frustrating with this situation. DOM structure can be viewed here, but I will link it in here as well http://galleria.aino.se/docs/1.2/references/dom/
<div class="galleria-container">
<div class="galleria-stage">
<div class="galleria-images">
<div class="galleria-image">
<img>
</div>
<div class="galleria-image">
<img>
</div>
</div>
<div class="galleria-loader"></div>
<div class="galleria-counter">
<span class="current"></span>
<span class="total"></span>
</div>
<div class="galleria-image-nav">
<div class="galleria-image-right-nav"></div>
<div class="galleria-image-left-nav"></div>
</div>
</div>
<div class="galleria-thumbnails-container [ carousel ]">
<div class="galleria-thumb-nav-left [ disabled ]"></div>
<div class="galleria-thumbnails-list">
<div class="galleria-thumbnails">
<div class="galleria-image">
<img>
</div>
[...]
</div>
</div>
<div class="galleria-thumb-nav-right [ disabled ]"></div>
</div>
<div class="galleria-info">
<div class="galleria-info-text">
<div class="galleria-info-title"></div>
<div class="galleria-info-description"></div>
<div class="galleria-info-author"></div>
</div>
</div>
<div class="galleria-tooltip"></div>
</div>
Here is a one way to access id of an element:
var currentId = $(this).attr('id');
For your case, you can try this:
myGalleria.$('thumbnails').click(function(){
alert($(this).attr('id'));
});
should it not be alert($(this).id);? (Note the $).

Categories

Resources