I've come across an interesting problem with IE9 and object tags.
In the simplest form for a client I am hosting a website (ASP .NET Web Forms site) within an object tag from a page in a separate website, for reasons that are ridiculous and mind blowing, the html looks like the following:
<object id="so" data="https://so.com/so" scrolling="auto" frameborder="0">
</object>
In Chrome and Firefox when I click a link in the html inside the object tag, the browser tab has a loading icon (as per a normal page event) giving the user feedback that an event has occurred. In IE 9 this does not occur so the user doesn't know that clicking the link has fired any events.
I've looked at the onbeforeunload event of the object tag with no success, for instance:
<object id="so" data="https://so.com/so" scrolling="auto" frameborder="0" onBeforeOnLoad="javascript: onDocumentUnLoad();">
</object>
Using the above method the onbeforeunload function is not called.
I also tried using a ajax load via jQuery into a div but handling out of context css and js references and post-backs become unmanageable and also adding click events to every button or href affected performance and functionality.
I was was wondering if there's another approach to give the user feedback or a simple workaround.
I've found a solution that works.
In the parent page create an handler for a custom event. In this case "unloadingChild":
//using jQuery 1.4.2
$("body").bind("unloadingChild", function(){
console.log("child unloaded");
});
In the child hosted page trigger the custom event via the body unload event:
//body element unload
$(window).unload(bodyUnload());
function bodyUnload(){
//trigger the parent unloadingChild event
parent.$("body").trigger("unloadingChild");
}
I don't know if it's the best way but it seems like a good way. That certainly works for this scenario.
It doesn't solve the object unload but it gets around the problem.
This will only work for two websites with the same origin. Otherwise you will get an error similar to "Permission denied to access property '$'"
Related
In my scenario an HTML5 page (parent) contains an iframe (child) from a different domain. Ideally I would like to be able to drag an element from the parent into the child.
This works in FireFox but fails in Chrome due to security restrictions (afaik https://bugs.chromium.org/p/chromium/issues/detail?id=251718).
However if I open the same HTML5 page in a different browser instance, drag from there into the iframe of the other instance, then this is allowed.
The reasoning for the security restriction is that the user does not see the URL of the target iframe, but this is true in both scenarios. Why would one work and but not the other?
Sample on
http://carsten-leue.de/iframe/cross-domain/
Try to drag drag me into drop here. This is not possible in Chrome. Open the same URL in another browser window and drag drag me from the new window into drop here of the old window. This works.
I would like you to use this API since it allows dragging! (not like an image type how your source shows!)
<!-- HTML -->
<body>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>
</body>
// JavaScript
document.getElementById('elementId').draggable();
// Or if you have a class name
document.getElementsByClassName('elementClass').draggable();
Using HTML5 Drag and Drop API to create Cross Frame and Cross Browser Implementation. http://blog.stackhive.com/post/137799349684/building-a-seamless-drag-and-drop-interface
EDIT - The previous link wasn't valid (dockPHP got rebranded as StackHive) so have written out a more complete post that can help in creating an epic drag and drop interface.
Source: Drag-Drop elements between parent frame and child iframe
Before I start describing my problem I just want to give a heads-up that all the pages, iFrames etc. are hosted locally on my PC. And that I have used page.setBypassCSP(true) to temporarily disable any origin based restrictions.
Here we go, I have a webpage which embeds an iFrame and that iFrame may embed another one (and the list can go on...). Some of the deeper iFrames may be appended to the body of it's parent via Javascript e.g. document.body.appendChild inside a setTimeout(..., 3000) which kind of simulates a dynamic iframe load. I want to know what is the best way to evaluate a script source on all of these iFrames. I tried using page.on('framenavigated', ...) but this only works for the page's immediate child frame(s).
I tried recursively iterating through all the frames in the page using page.frames() but that only works for iFrames that are available at the time when the DOMContentLoaded event is fired.
I'm looking for a way to listen to all the framenavigated events fired by all the nested iFrames even for the ones that loaded dynamically at any point of time, after the page is loaded. Any pointers would be greatly appreciated.
UPDATE:
I have tried listening to events using page.on('frameattached', ...) and page.on('framedetached', ...) but that also doesn't let me list all iFrames.
I am using Sitecore and I have a header sublayout that I use in all pages. This layout contains a Logout button that fires OnClick event when clicked and executes the onclick event function. But in few pages it wont fire OnClick event at all instead it reloads the page.
Below is the code for the logout button
<asp:button id="btnLogout" runat="server" borderstyle="None" onclick="btnLogout_Click" text="Log out" ToolTip="Log out" backcolor="Transparent" style="cursor:pointer" class="logout_new"></asp:button>
Below is the code for the event function
protected void btnLogout_Click(object sender, EventArgs e)
{
Sitecore.Security.Authentication.AuthenticationManager.Logout();
Response.Redirect("/Login.aspx");
}
I found out that the difference between the pages where the logout fires the onclick event and pages where it does'nt is that they use the same header sublayout containing the logout button but they use different content sublayout though.
Note: I have not applied Cache to any sublayout.
Can anyone help me with this?
From the given context I don’t know what is the issue but here is what I will do if I have issue like this.
As you said only on few pages it is not working, it could be the other controls on that particular page is causing the issue.
I will pick two pages which has less controls on the presentation layer. Say PageA is a working page and PageB is a non-working page. Then I compare PageA and PageB and remove all common controls, this should narrow down the number of the controls on the presentation layer. Now check again to see if Page B is working or not. If not, I will try to remove one control at a time on PageB untill it starts working. If you find by removing certain control and the page started working then you can look into the particular control and identify the issue.
I hope this helps.
try disabling the cache as it would return the html without triggering the back end code.
To do so, one option is going to the presentation detail of those pages, find the control and click on it to edit. Under the "Caching section" uncheck "Cacheable" and publish the item. If this fixes your problem, I'd review the standard values of the template, to apply the change to all the items with the same template
This behavior happens to me at annoying times too, but it's almost always the same thing: the Sitecore sublayout the code is in is being cached.
The onclick javascript fires, but the page is not re-rendered with new content because the "unclicked" version is stored in the cache.
You'll need to disable caching on the sublayout to make the button work.
This can, however, be somewhat annoying if you're trying to cache as much presentation stuff as you can. In those cases, it often means you need to, counter-intuitively, create a number of "sub-sublayouts" and place them statically. Set the containing sublayout to be uncached, and then you can set each smaller one's caching appropriately (caching static parts, not caching dynamic stuff).
The problem was in the content sublayout in which it was not working, the Page_Load function was calling a Response.Redirect function to itself and it was not checking if it was a post back request or not before that. So Whenever a user clicked logout button it used to post it back to the server and the page used to reload instead of executing the onclick event.
I noticed that in the other content sublayout where it was working, it was checking if it was a post back or not.
I added a if(!IsPostBack) before that and it started working.
So I am playing around with the HTML service of GAS.
It has been working fine (more or less). But I hit a wall now.
I want the script (inside the html file) to create some html on when called.
In particular a few tags.
However, I want those tags to have onClick handlers (which will edit the div element).
Now the problem is that the onClick should depend on certain properties and I can not
pre-create those objects, they have to be made pragmatically and for some reason when I add a
onClick="someFunction(elementID)" after the new code has been added to the old one the click handler disappears.
(it works tho if the handler function has no parameters)
eg.
var div="<div id=\"box"+count+"\" class=\"square\" insert></div>";
if(something)
div=div.replace("insert", "onclick=\"myFunction(box"+count+"\"");
This is intentional and documented: see the section called "Dynamically adding scripts or external CSS" in the HtmlService user guide.
I have two iframes from the same domain, which are hosted in document from another domain. The problem is these iframes cannot communicate with each other through postMessage. I cant even access the DOM of iframe1 from iframe2 even though they belong to same domain. Is there any solution ????
I used following options to refer the required iframe.
parent.frame[x]
I tried following lines to access DOM of iframes
parent.frame[x].contentWindow returns null,
parent.frame[x].document.getElementsByTagName("body") returns null
Update:
I guess my question is not clear enough. There is no problem with postMessage api, the actual problem is browser creates a custom frameset around the iframe document, in my case!
So parent.frame[x] won't point to the iframe window, instead it points to the custom frameset inside the iframe window.
Following question explains the problem well.
Prevent browser from loading a custom frameset in an iframe's document
If you want cross-window same-domain communication, you can set it up via localStorage. When you add an item to localStorage, you get window "storage" event in all other windows / iframes / tabs of the same domain.
So, you basically localStorage.setItem('name', 'value') in one iframe while you listen to window.addEventListener('storage', (event) => {/* handle message */}) and you get the message.
Take a look at the following description of the postMessage function and how it could be used. So in frame1 you call the postMessage method and in frame2 you subscribe for notifications. Obviously the browser you are using must support this API.
There's also a very nice jQuery plugin which wraps this API and simplifies its usage. It also works in browsers that do not support the postMessage method by using the hash portion of the url.