I'd like to make a tool which allows to process data picked from an iframed page.
Something similar to this:
http://jsfiddle.net/jr6uG/4/
I stopped on events (hover, click, etc.).
Is it possible to do it my way? Is there a better way?
I need somthing like this:
$('iframe body *').bind('click', function(event){
console.log('clicked', this);
});
The iframe runs a separate DOM, meaning there's no interoperability between DOM objects in the original document and the iframe document.
You'd have to do this over the network. A little like JSFiddle captures console logs from within the iframe generated to the console in the document you're viewing.
To process data picked from an iframed page, as you're intending to do, you'd be looking to direct any page that you're trying to process through a bespoke proxy, where you could inject your own scripts, for example, to create an alert when an element is clicked.
Related
According to the official docs window.onbeforeprint allow[s] pages to change their content before printing starts (perhaps to remove a banner, for example).
However, this doesn’t work in my cases, since window.onbeforeprint is fired asynchronously — like any event in JS. I do change the DOM content in my event handler, but the changes are not in the print preview. Only, when I cancel the first print attempt and hit Cmd+P again, the changes (of the first event) inside the DOM are part of the print preview.
I’m not talking about long-running processes here like fetching something from the net. Just simple copy/paste inside the DOM.
So I wonder if I’m doing anything wrong here, or if window.onbeforeprint is pretty much pointless for changing content prior to printing.
After some additional troubleshooting, I can confirm, that window.onbeforeprint actually allows DOM manipulations to happen before the print view is generated. The problem in my case was the framework: Vue.js. The Vue component didn’t update in time. If I manipulate the DOM directly inside the event handler, it works.
this is the situation.
I have a complex UI inside an iframe in which a user can perform several actions before submitting. During the process, the user can switch to another page (in the iframe) and come back. That means 2 postbacks inside the iframe.
Obviously, I don't want the user to lose everything but since all the actions have been done on the client-side, I can't reload the previous state from the server.
So now, I'm trying to move the first page content to the iframe parent and put it back in place when we come back. I'm half way there since the elements show back in the page but they lose their data attributes and event handlers.
I'm using this to move the content on the parent :
$("#resp").clone(true).attr("id", "refillResp").appendTo(window.top.$("#global"));
And this to put it back :
window.top.$("#global").find("#refillResp").clone(true).attr("id", "resp").appendTo($("#tdResp"));
Is there anyone who knows a way to do this ?
PS: I've tested how the content react when simply moved on the parent and data and events are already gone.
It is more a comment, but it does not fit in there.
Moving DOM element around different documents around is alway a little bit risky. Because it could lead to unexpected behavior (memory leaks, elements that behave strange). In current browsers it most of the time works, but i would not recommend it.
If you use jQuery you have another problem. jQuery has a cache for storing informations about data and event that are assigned to an Object, this cache is stored with the documents window. For further details please read this answer, to another question:
How to set jQuery data() on an iFrame body tag and retrieve it from inside the iFrame?
So if you move element with jQuery between different document, you will currently on the one hand loose these informations, on the other hand it could result in memory leaks.
With events it is even more complicate. e.g. if you have delegated events it could be become completely messy.
If you need to exchange data between iframe and parent you should think of some other logic.
I also mention this in a comment to the other answer of me, where i referred to this post:
How to set jQuery data() on an iFrame body tag and retrieve it from inside the iFrame?
This is the question:
I have an iframe that displays any web page (not necessarily developed by me).
On this page may be attached events (which presumably I do not know).
How can I dynamically intercepting these events and store them for later replicate?
For example:
suppose that when the mouse moves over a certain div it changes color.
I would like to make sure that when you trigger the event that would change color to the div it is "registered" with all a series of information that will allow me (without user interaction) to replicate it at a later time.
Ideas for both the recording and subsequent replication?
The short answer is: you cannot.
You cannot access the document object of "any web page" with JavaScript on your page if it is on a different domain, which I assume if you say "any web page", because of the Same Origin Policy. You would need the website in the IFRAME to cooperate with your script to achieve this, which will not happen with "any web page".
IFRAME on same domain
If your web page is on the same domain then you can access the events of the IFRAMEs body element by adding a listener for every event you want to catch like described here. This is possible for all events that bubble up to the body. So if you have Events that are prevented from bubbling upwards to the body, they will not be catched with this solution.
jQuery('#website body').on('click mouseover mouseout', function(event) {
console.log(event.type);
});
Assuming you have an IFRAME with the id website you can catch the events you wish by listing them separated with spaces as above. The example catches click, mousover and mouseout.
Maybe this is closer to what you want?
Add event handlers to your divs. For your example you could use
$('#div').mouseover(function(e) { ... })
or
('#div').on('mouseover', function(e) { ... })
For 'replication', you'd have to store information about past events in some object. You could even store the event object itself.
I am creating a jQuery Mobile web app, which loads some pages.
For example, a.html is my main page. It may call b1.html,b2.html,...,b100.html (User may click on one of buttons). (The pages are loading with ajax navigation feature of jQuery Mobile)
And there is some events in each b[i].html page, and ids and many things are same in every b[i].html page. But the point is, at any time, just one of them may be in DOM. So there will be no id conflicts or such.
The problem
The problem is the conflict of the events. When user come back to a.html from b[i].html, the HTML will be removed, but events will remain. This will cause many problems if I first go to b[i].html, and then come back to a.html and then go to b[j].html. I mean, b[j].html will not work correctly... :(
What I have tried
I have putted this in a.html, to remove all events:
$("#mainpage").off("pagebeforeshow").on("pagebeforeshow",function() {
$("*").not("#mainpage").off();
//Other initialization codes...
});
But, problem not solved...
(mainpage is the id of data-role="page" of a.html)
Example
For example, I have this in each b[i].html:
$(window).resize(function () {
alert("Resized");
});
At the beginning (in a.html), If I resize the window, there will be no alerts, but after visiting b[i].html and then coming back to a.html, I'll see alerts if I resize the window, even with that line of code (What I have tried part.)...
So, How to remove those event handlers when users come back to a.html from b[i].html?
If you are using jQuery Mobile, more than one of said pages may exist in the dom at the same time, resulting in non-unique id conflicts.
I would ditch putting js on the individual pages and have it done from the primary page, or through a script loading system such as require.js. Then do all of the events through delegation from the document. Obviously that won't work with window.resize(), but it doesn't need to be delegated anyway.
"Can you please explain more?"
Basically, if you are including scripts on the child pages, you will need to have both setup and teardown for every page. setup adds the events, and teardown removes them. If you instead used a single global script that adds ALL of the events using event delegation from the document, all of the pages should work. Obviously that global script could get pretty big on a complex site, so you could instead use require.js to load in js that does the same thing as needed, preventing it from loading the same dependency more than once.
As far as removing all events, I've never tried this, but can you use $("*").off()? According to the docs it should work. I'm not sure how it will affect jQuery mobile. To remove events on the document and/or window, you will have to do it manually because $("*") will not select them.
$(document).on("vmousemove","#link",func) is how you delegate an event from the document.
I am trying to intercept links clicked on a page including those inside an iframe. This is the code that I have but it is not working. Any ideas what I need to do?
$("#container").delegate('a', 'click', function(e){
//do stuff
}
Container is the id of the div just inside the iframe.
Thanks in advance for any advice
You need to reach inside the <iframe> and set the delegate there, you can do it like this:
$('#myiframe').contents().find("#container").delegate('a', 'click', function(e){
//do stuff
}
Edit - Mailslut makes a good points below, if the iframe isn't on the same domain (and port), you can't do anything like this. If that's the case and you want to know more about why, read about the same-origin policy there for security reasons.
Why not add the event listener inside the iframe and then call the parent / opener to notify the event.
If you the contents of the iframe is on a different domain, you won't be able to perform this as it is classed as "click-jacking", which was a big security threat.