HtmlUnit click() on div does not trigger JavaScript - javascript

I am trying to get all images particularly from this website: http://web.archive.org/web/20160110012916/http://habibemaia.com/ . I can get almost all by gathering all "src" tags and downloading from there, but there are problems with the main picture which is changed by javascript either with timing or on a click event. I set up my webclient like this:
webClient.getOptions().setCssEnabled(true);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.waitForBackgroundJavaScript(15000);
webClient.waitForBackgroundJavaScriptStartingBefore(5000);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setUseInsecureSSL(true);
After I got the div I try to use click like this:
HtmlPage newPage = div.click();
DomNodeList<DomElement> newImages = newPage.getElementsByTagName("img");
for (DomElement img : newImages) {
if (img.hasAttribute("src")) {
newImagesStrings.add(img.getAttribute("src"));
System.out.println("Image added: "+img.getAttribute("src"));
}
}
If I click on this div int the browser, a new image appears. Unfortunately this code does not trigger the javascript that changes the image. I have tried using
webClient.waitForBackgroundJavaScript(3000);
after click(), as suggested elsewhere, but no luck. The page does not change. Now I am out of ideas completely. Thanks for help.

webClient.waitForBackgroundJavaScript(15000);
webClient.waitForBackgroundJavaScriptStartingBefore(5000);
are both no option settings. The make only sense if you call them after some action - remove this from the setup part of your code.
Regarding the images: I did a quick analysis of the page with firebug. For me it looks like all the images are part of the code and the javascript only toggles the visibility (with some fancy effects).
Maybe something like:
find the div with class 'cameraCont'
iterate over all children with the style 'cameraSlide'
every of this div has an img child that points to a different image

Related

Problems when combining css :target selector with url hash parameters for showing a modal

My javascript and css knowledge is rather limited. I think I am missing some subtleties of when and how css is applied as well as how page loading, combined with asynchronous javascript, calls works.
This is working:
I have a css only modal which displays when the id of my modal (view) matches the hash in the url (#view). I use it to display images (it is the same modal div for all images and the actual image src is updated via event listeners added to links to the modals' anchor). This is working fine.
This is working:
I wanted to extend this so I could directly link to an already open popup by providing the url as a hash parameter. I.e. example.com/#view=imageUrl. Just opening this will not make the css selector :target match, since it now contains the view, but if I split this off by checking var hash = window.location.hash.substr(1); I can separate the url from the anchor and if I then use:
window.history.pushState("", "", window.location.href.split('=')[0]);
updateModal(imageUrl)
where updateModal sets the source of the image to the split off url. All is fine, too, i.e. the site opens with the modal open and the image from the url in there.
This is not working:
Now I thought, it is possible that the image provided as hash parameter does not exist anymore, so I only want to show the modal if there is a valid image provided, otherwise go to the main page. I created a dummy image element, try loading the image from imageUrl and move the splitting and updating bits to the onload method of the dummy image, like so:
dummyImage.onload = function () {
window.history.pushState("", "", window.location.href.split('=')[0])
updateModal(imageUrl)
}
If I do this, the modal does not show. The css does not get applied, why is this?
I also tried changing the visibility of the modal myself:
dummyImage.onload = function () {
window.history.pushState("", "", window.location.href.split('=')[0])
updateModal(imageUrl)
var myModal = document.getElementById('view')
myModal.style.display = 'flex'
myModal.style.visibility = 'visible'
}
Which makes the modal appear, but seems to add a style that cannot be overridden by the css anymore. Specifically, when I click the close link of the modal which just goes to a different anchor #noname the url changes, the css :target selector should not match anymore, but the modal does not close anymore. Why would the css not apply anymore?
Reading the below links, I believe this is a bug and that, on changing the url with pushState, the :target selector is not re-evaluated after page load. I will work around this by always showing the modal, as in the second working example in the question and use a fall-back image and message to alert the users that the image is no longer available (I can trigger this update with dummyImage.onerror).
https://bugs.webkit.org/show_bug.cgi?id=83490
https://css-tricks.com/on-target/
https://github.com/ReactTraining/history/issues/503
https://github.com/whatwg/html/issues/639
If anybody knows a better solution or workaround, I am still interested to learn!

jQuery .hover() not changing image

I've looked around and tried a few things I've seen on here to try to fix this issue but I can't seem to find out why. I have five images in the toppic class. I want to be able to hover over an image in the toppic class and change the big image (id = Biggin) in my screen with the image that is being hovered over, and then change back to the default when the mouse leaves the image. Is there anything blatantly wrong? I copied and pasted from a previous working function and I'm not sure as to what I did wrong this time.
$(".toppic").hover(function() {
var imgsrc = this.src;
$("#Biggin").attr("src", imgsrc);
})
$(".toppic").mouseout(function() {
$("#Biggin").attr("src", ".//Images/IMG_3604.JPG");
})
I had similar issues when starting out using jQuery, and there could be a few reasons why your code isn't working as intended. The most common reason mine wasn't working is that the jQuery script element was getting activated before the DOM existed.
Make sure that the jQuery script element in your html file loads after your DOM loads. You can place the jQuery script element at the end of the HTML file so your jQuery would be loaded after the HTML loads.
I hope that helps.

jQuery .attr Not Working Properly, Miss-Retrieving Links

This is a page I'm currently working on as a project
$(function() {
$(".modal-launcher, #modal-background").click(function() {
$(".modal-content, #modal-background").toggleClass("active");
$(".vid-1i").attr("src", "link1");
$(".vid-2i").attr("src", "link2");
$(".vid-3i").attr("src", "link3");
$(".vid-4i").attr("src", "link4");
$(".vid-5i").attr("src", "link5");
$(".vid-6i").attr("src", "link6");
$(".vid-7i").attr("src", "link7");
$(".vid-8i").attr("src", "link8");
//$('html').toggleClass('active').css('top', -(document.documentElement.scrollTop) + 'px');//
});
});
above the actual links are replaced just to display a quick idea of the bad jQuery.
In it, I am attempting to create my own popup launcher for videos; however, I am having trouble using jQuery to replace the "" src of an iframe element to a YouTube link. I am unable to figure out why the jQuery is not working. I understand that the jQuery is, of course, working properly, and that it is me who has written the code incorrectly, but here I am asking if anyone is able to figure out what it is I've done wrong, or what can be changed to make it work.
For some reason, the last video in the jQuery list is always the one retrieved.
Understand that the images are missing from the page due to them being local files and not network locations. Clicking above the captions that read like "Match One" will have the "intended" result, regardless if the image is showing or not.
Coming back to this and understanding more of JavaScript and jQuery, my problem was simply misunderstanding the code. In order to do something like this, one function per link would be more suitable.
function video1()
{
$("#popup, #modal-background").toggleClass("active");
$("#popup").prop("src", "https://www.youtube.com/embed/7h1s15n74r3all1nk");
document.getElementById('scroll').style.cssText ='overflow:hidden';
}
complementary html would look like this:
<div onclick="video1()"></div>
The previous code would run each line, effectively setting the last link as the source of the element. The new code is button independent, ensuring only one link belongs to each button.

IE is not showing updated IMG SRC change done in Javascript

ISSUE: IE version 7 and 8 is not showing updated IMG SRC change done in JavaScript
You can see what I mean if you go to the URL below, and on the left under (3) I want a different liner, you choose one of the swatches; lets say you choose "Asahi Chartreuse". Notice nothing happens to the preview on the left. BUT then if you go ahead and choose another swatch, you will see the preview on the left shift to show Asahi Chartreuse. So it is one behind. This is why I believe it is a "refresh" issue. It works in Chrome just fine.
In IE: Notice if you click on some other control, the refresh happens.
You can see the code here: https://www.casemodo.com/test.asp
WHAT I'VE TRIED SO FAR:
I've tried adding headers to say "no-cache".
I've tried adding "?" and random number after the png file name.
I've tried setting focus() to the image after changing the src.
I've tried, after changing src, telling the style.display to be hidden and then visible.
I've tried creating a hidden (and not hidden) text input box on the page and then setting focus() to it after changing img src.
I've tried setting window.focus().
I've tried (as you see now) setting an alert after changing the src.
GUESS: What it looks like now is the JavaScript engine just pauses after I set that src UNTIL you manually click (focus) somewhere else on the screen. So it never even gets to all of those scripts I've tried above.
Set the src attribute to null, then set it to your new url:
in jquery:
var myImg = $('#myImg');
myImg.attr('src', null);
myImg.attr('src', newUrl);
in straight js:
var myImg = document.getElementById('myImg');
myImg.src = null;
myImg.src = newUrl
This worked for me - it was driving me mad!
Try to use onclick instead of onchange. The latter doesnt work well with some form elements in some browsers.
I've seen similar IE issues solved with a seemingly bizarre reassignment of innerHTML. Suppose "container" is a variable referencing the parentNode of the img. Try "container.innerHTML = container.innerHTML". This triggers a re-rendering and may bring the errant img to life.
Comments on the question:
Please include a code snippet in the question.
Was the javascript in an onchange event, or where?
If the client browser is Google Chrome, does it work?
(Sounds like yet-another-IE-image-src-bug.)
The demonstration page you linked to has been changed since this question was posted;
as I write this, clicking on a swatch causes submit which causes load of a different page.
A suggestion:
Use setTimeout, so that the actual change occurs when the timeout event fires, instead of in the original GUI event thread.
For example, if the original javascript was
SomeFunction();
change this to
setTimeout(SomeFunction, 10);
(where image.src = newURL; is done inside SomeFunction)
This question is probably no longer relevant but we ran into the same issue today when we checked backward compatibility for one of our libraries.
The only thing that worked for us was to replace the image element by itself before changing the value for the src attribute:
var myImg = document.getElementById('myImg');
myImg.parentNode.replaceChild(myImg, myImg);
myImg.src = newUrl;
I was working with a Lazy Loading implementation, and got to a similar problem. For some reason, after changing the data-srcset attributes to srcset in code, even with the other approaches described on this page, the elements still didn't seem to get the new attributes values. After some research, I got to this page on github, about a bug fix on a lazy loading plugin. It gave me the idea to, instead of using the replace option described here, or the your_element.src=null approach, to use something like this:
your_element.setAttribute("src", your_element.getAttribute("data-srcset"));
And it ended up working for me.

If ID has class, set attribute of another element

I'm trying to detect if a class is present and, if so, set the background attribute of another element. This is what I have but it's not working.
if(jQuery("#slider-banner").hasClass('living-nutrients'))
{
jQuery("#home-middle-first").css("background-image","[path to new background image]");
}
BTW - My next step is for this to detect it whenever the ID "slider-banner" changes, but so far I can't even get it to work once on page load. Any help would be greatly appreciated... Thanks!
EDIT: I changed from .attr to .css as instructed. Makes sense... but still not working. I've tried adding console.log message within the IF statement and got nothing also. Does that give anyone any more ideas?
Example HTML where class changes:
<img id="slider-banner" class="living-nutrients" src="[image path]">
Example HTML where I want to change background image:
<div class="home-middle-one-third" id="home-middle-first">
</div>
UPDATE:
For everyone who said it "should work"... you are right! Turns out that, as written, it doesn't like being in the footer of the page, but when I moved it to the head, presto!
The final piece of this puzzle is to have it detect and evaluate based on the #slider-banner changing, (or more accurately, which class is present for the ID'd area), not just the page loading, as is currently.
The ID is for one element of a slide within a slider. There are three possible classes I could assign to the ID depending on which slide is visible. So I need the script to evaluate every time a slide changes.
Any ideas? Thank you all!
background-image is a element's style property, not its own one.
So .css("background-image","[path to new background image]");
Almost!
if(jQuery("#slider-banner").hasClass('living-nutrients'))
{
jQuery("#home-middle-first").css("background-image","[path to new background image]");
}
css is the correct function to set a CSS attribute.
The attr will set an HTML attribute. <div attr='attr value'>
Edit
I'm kind of guessing about the functionality of your script here in the following example.
When you set the background-image of a HTML node, that's all it does is set the background image. You must also set the width and height accordingly, to all the node to be large enough to even see the background of the node. Background images will not automatically resize the node.
var slider = jQuery("#slider-banner"); // jQuery("#slider-banner") is slow, so we save it to a var if we use it more than once
console.log(slider); // should be this in Chrome: [<img id="slider-banner" class="living-nutrients" src="[image path]">]
if(slider.hasClass('living-nutrients'))
{
jQuery("#home-middle-first").css({
"background-image":"url("+slider.attr('src')+")", // url() for good meassures
//"background-image":slider.css('background-image'), //try this if that doesn't work
"height":slider.height(),
"width":slider.width()
});
}
Here is a working example.
Try this
jQuery("#home-middle-first").css("background-image","url([path])");

Categories

Resources