jQuery UI Dialog IE8 problem - javascript

I have a jQuery UI dialog which contains a form, allowing the user to post an ad. Since the form contains a file upload, the form's target is an iFrame.
From this iFrame, I destroy the dialog in the parent window and create a new one (or I change the options of the original dialog, it doesn't make any difference). The point is that from the iFrame, I define new buttons for the new dialog which themselves are attached to events that work on the main window elements.
In Firefox, Safari, Chrome this works perfectly well:
var p = parent;
p.$('#dialog_new_ad').html('<form id="post_ad_form" style="display: none" data-remote="true"></form><div class="header"><h1 class="header_title"></h1><div class="header_company"></div><div class="header_location"></div></div><div class="content"></div>');
p.$('#dialog_new_ad').dialog({
minHeight: 600,
width: 800,
position: ['center',25],
modal: true,
autoOpen: false,
title: '<%= 'Preview: ' if params[:action] == 'preview' %><%= #ad.title %>',
buttons: {
"« Back": function() {
p.$('#post_ad_form').attr('method','get');
p.$('#post_ad_form').attr('action','/ads/<%= #ad.id %>/revise');
p.$('#post_ad_form').submit();
},
"Submit »": function() {
p.$('#post_ad_form').attr('method','post');
p.$('#post_ad_form').html('<input type="hidden" name="_method" value="put">');
p.$('#post_ad_form').attr('action',"/ads/<%= #ad.id %>/confirm");
p.$('#post_ad_form').submit();
}
}
});
This code is in the iFrame which the form POSTs to.
If you look at the button functions, you'll see that what they are doing is also defined in the context of the child window (iFrame), even though the buttons are in the parent window. It's because the function is created in the iFrame, and thus the objects must be referenced from that context.
Now the problem is that in Internet Explorer it works sometimes, but not others. When it doesn't, the error I get is "Can't execute code in a freed script" and it points to the part of jquery-ui.js where the button functions are defined. Whether or not the error occurs is simply random. As if it depends on whether or not something has finished before that code is called. As mentioned, in any other browser it always works.
The entire thing (in the iFrame) is enclosed in a $(function() { [...] } , so the DOM is loaded that's not the issue. It might have something to do with the fact that the form which is created by the .html call is not "finished being put into the DOM" when the button functions are defined, but that would seem strange to me. Any ideas?
Note: The jQuery .html function uses innerHTML to create the new elements. Is it possible that this leads to any problems in IE, if the elements are referenced directly thereafter?
Update: I gave up and simply put the dummy form in the parent element, so it can always be used by children iFrames of different kinds, whether or not they are actually loaded. When the form is a static part of the parent HTML and not dynamically inserted, everything works just fine. I still don't understand why the dynamic insertion doesn't work in IE though.

Related

Is it possible to keep a popup hidden until some code is executed?

So, I have this extension, and it should show a custom popup on the page when the icon is clicked, and by "custom popup", I mean, something rendered inside an <iframe> and injected in the page dom itself, not an "traditional extension popup", but the problem is that in some pages i'm not able to inject a content-script, in those cases, I would want to display the content in the "traditional extension popup".
I got it to work, but it's not the most elegant of a solution, here's how I'm doing it
The popup.html has no content in it's <body>, and it imports a script.
This script tries to send a message to the content script running in the page, if the message is successfully, the popup will close itself, and the content script will handle the render on the page
If the message could not be sent then it tries to inject the script on the page, if the injection works, then the message is sent again, if it doesn't, then we are on a page that does not allow injection, in that case, we simply render the content to the popup's body (i'm using Svelte here)
browser.tabs.query({active: true, currentWindow: true}).then(tabs => {
const tab = tabs[0];
browser.tabs.sendMessage(tab.id, {action: "toggle"}).then(() => {
window.close();
}).catch(() => {
injectScript(tab).then(() => {
browser.tabs.sendMessage(tab.id, {action: "toggle"}).then(() => {
window.close();
});
}).catch(() => {
document.body.style.width="400px";
document.documentElement.style.height="580px";
new App({
target: document.body,
});
});
});
});
The thing is, most of the time, this process is basically instantaneous, you just click the icon, and the custom popup shows up, but sometimes, it takes a little longer (maybe 1 sec?), and in that time, you can see the "traditional popup" on it's minimum size (maybe something around 32x32? It's a really small square)
What I would like is to keep the popup hidden until my code "decided" wheter it's possible or not to inject the content in the page.
What I've tried and does not work:
Setting width and/or height of the and/or tags to 0px
Setting display:none and/or visibility: hidden on and/or tags
Is there any way to do what I'm looking for?
EDIT:
Here's an image so you can better understand what I'm talking about, this is the "square":
Sometimes you can't even see it, sometimes it just blinks, and sometimes it takes a bit longer to go away, it depends on the pc I think
I would use a layer in this case. A layer can be done using CSS, can contain all of the proper formatting and text, and can be shown or hidden whenever you want not affecting any of the other text around it due to it being on another layer. I'm unsure if this will solve your problem because I don't really know the context of the program you are creating and what you are trying to accomplish.

Is it possible to return content from a custom window in TinyMCE 4?

Like many others, due to the limitations of TinyMCE's Image Plugin, I've decided to take the route of creating one that ties into my site's own uploading system.
I've gotten this partially working and pulling up a individual page, designed just for the purpose. However, now I want to return content from selecting images on this page. Is that possible or am I hitting a dead end?
tinymce.PluginManager.add('imageLoader', function(editor, url) {
// Adds a menu item to the tools menu
editor.addButton('imageLoader', {
icon: 'mce-ico mce-i-link',
image: 'Photos.png',
onclick: function() {
// Open window
editor.windowManager.open({
title: 'Image Loader',
url: 'load_images',
width: 500,
height: 400,
onsubmit: function(e) {
// Insert content when the window form is submitted
editor.insertContent('Image To Insert');
}
});
}
});
return {
getMetadata: function () {
return {
name: "Image Loader"
};
}
};
});
We made this a lot easier in TinyMCE 5 with a new URL dialog api:
https://www.tiny.cloud/docs/ui-components/urldialog/
In version 4, I believe the usual technique was to (inside the iframe) access the TinyMCE instance that opened the dialog via window.parent.tinymce.activeEditor, and then replicate the onsubmit function there. With the editor instance you can insert whatever content you need to and then editor.windowManager.close() will close the topmost window (i.e. the url dialog).
For more advanced use cases, editor.windowManager.getParams() can be used to pass information between the plugin and dialog, although perhaps not from the dialog to the plugin. editor.plugins is another possible technique, it's a name/value object of active plugin instances (it's a live reference to the return value from the PluginManager.add init function which can be mutated at runtime).
These are all fairly complicated, but likely more reliable than searching for the dialog iframe from your plugin.
I found an answer, although this is likely not the most elegant solution.
The image that I'm selecting is passed into a hidden text input in my custom page. From there, on Submit or Closing the TinyMCE 4 Frame, I use this snippet:
let getVal = $('[role="application"]').find('iframe')[1].contentWindow.document.getElementById("imgHolder").value;
In order:
It first finds the iFrame. Since both external pages and the editor itself use iFrames, this will generally be the 'second' iFrame - unfortunately, it isn't given an ID.
"contentWindow.document.getElementByID" fetches the hidden input, in my case named "imgHolder"
From here, you can get your content as normal with .value, and insert it into the TinyMCE Editor.
I hope this helps point others in the right direction, especially knowing that it gets asked a lot for TinyMCE 4. Further I hope this can be made a bit more elegent as well.

Completely delete all instances of a div with a specific class using javascript/jquery?

I am using Popup.js by Toddish.
http://docs.toddish.co.uk/popup/demos/
Long story short, the popup plugin creates divs by default given the classes ".popup_back" and ".popup_cont".
I have another button I wish to press which should completely delete the added divs with those classes after they have been generated and added to the html. As if they never even existed. Surely this is possible?
I have tried running a function which simply runs:
$(".popup_back").remove();
$(".popup_cont").remove();
As shown in this example:
http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_dom_remove
Unfortunately despite the code running, the actual divs are never deleted as required.
Any ideas? I am new to this kind of thing and have googled around and read a lot about DOM etc but am yet to crack it.
Thanks
EDIT:
In reply to the comments:
The Javascript:
function removePopups() { // This function is called to remove the popups.
console.log("removing...");
$(".popup_back").remove();
$(".popup_cont").remove();
}
function func(url) { // url is the url of the image to be displayed within the popup.
removePopups(); // As soon as the function casillas is called, removePopups is used to remove any existing instances of the divs.
$('a.theimage').popup({ // This is where the Popup plugin is utilised.
content : $(url),
type : 'html'
});
}
The HTML:
<a class="theimage" onclick="func('image/image1.jpg')" href="#" >
Long story short, an image is displayed in the popup.
I think the issue is that the popup plugin runs due to the class but the function func is never actually run when the click occurs. However simultaneously "removing..." still prints out in the console which tells me that the function IS being executed. The problem is I want the popup plugin to run together with the javascript function. Is there a solution for this conflict?
Your implementation should really be as simple as this:
<a class="theimage" href="#" >Open</a>
Bind the popup creation to your popup link:
$('a.theimage').popup({
content : 'image/image1.jpg',
type : 'html'
});
I'm speculating here, but what might be happening is that you're invoking the popup twice by binding the popup() call to a click handler in your markup. The popup plugin already binds the popup creation to a click event.
View working demo. Note the 3 external resource: the popup CSS, the popup JS, and the jQuery JS.

Dojo tabcontainer not displaying

Having some trouble getting dojo to display a borderContainer containing a tabContainer and a series of tabs, all contained within a dialog. This has all been done programmatically and the startup() event has been called.
The tabs are rendered and displayed, but rather unusually. Once the dialog itself is refreshed (discovered while opening and closing the console) everything rights itself. I've tried to force a resize() by calling it as part of start up - this hasn't worked. I've been trying to get this working properly for ages now. Its the only niggling thing about this! Having the manually refresh a dialog because a widget isn't displaying properly isn't exactly good UI design. The borderContainer does have height and width properties.
Could anyone suggest a few methods to try and why?
http://i.stack.imgur.com/YXtkq.png
Screen shot above (sorry I don't have 10 rep yet)!
I've tried to use 'doLayout: false' and that hasn't worked. I've got the 'style' set to height: 360px and width: 575px which are both well within the boundaries of the containing widget.
Well I discovered that simply doing startup() on the parent widget was not enough. Because it was instantiated in a hidden dialog widget, it needed to be instantiated from there.
the onclick event for the button was:
//custom widget - contrary to its name, this is the content!
var invoiceDialogWidget = new InvoiceDialogWidget(dialogValues);
var dia = new DijitDialog({
id: "invoiceDialogWidget",
content: invoiceDialogWidget,
title: "Invoice Detail"
onHide: function(){
this.destroyRecursive();
}
});
dia.show();
//magic line
invoiceDialogWidget.invoiceDialogContentNode.startup();
What I found was that by calling startup() as I had in the snippet above - the custom widget was instantiated correctly and matched the style of the dialog (which was made visible). Before I was calling it from within the custom widget, which hadn't been fully instantiated yet!
The result was calling startup() on a widget which defaulted to its parents style - which was invisible at the time.

jQuery UI .dialog() method failing silently in IE6

I'm having some trouble with IE6 and jQuery UI. I have a popup dialog (modal, if it matters), that displays a "yes/no" dialog to the user with some information. In order to facilitate this, I build the dialog with autoOpen = false, and then I call $('#popup').show() later on as needed, in response to various different events. Now, in IE6 (and only IE6, as far as I can tell), the .dialog method will occasionally fail but STILL return the jQuery object. So, rather than show a popup, the .show() method just display a div container in the html page.
What could be causing this, and how I can fix this behavior?
Thanks.
$('#myDialog').dialog({
autoOpen: false,
buttons: {
"No": function()
{
$(this).dialog('close');
//do stuff
},
"Yes": function()
{
$(this).dialog('close');
//do stuff
}
},
draggable: false,
modal: true,
resizable: false,
title: "Confirmation",
width: "500px",
zIndex: 2000
});
and later
$('#myDialog').dialog('open').show();
Pretty standard.
New information
I'm loading the page that makes the dialog with ajax inside of another dialog, which can be repeatedly created and destroyed. Now, each time my page gets loaded with ajax, .dialog(opts) should re-instantiate the dialog div, correct? I've found that this is the scenario.
1.) An outer dialog uses ajax to replace its content with my content.
2.) My content launches a dialog that was previously created and set to not autoopen.
3.) The outer dialog is destroyed as the inner dialog is closed.
4.) The outer dialog is reopened. The inner dialog no longer is able to appear as a dialog in ie6. This ONLY happens in ie6.
You should open your dialog using
$('#myDialog').dialog('open');
instead of
$('#myDialog').show();
The first method displays actual dialog box, while the one you are using just causes the #myDialog item to be displayed (with no UI Dialog magic). show() method is the part of the core jQuery library and shoudn't be used to invoke a dialog.
I had a similar situation and was never able to reuse the dialog. I had to destroy and recreate both dialogs each time.
I use the bgiframe: true and I never got any problem with them with I6, FFox, etc.
More info: http://docs.jquery.com/UI/Dialog#option-bgiframe
Regards.
By the way, when you are hiding your modal before you open it, are you using style="display:none" as your hiding attribute, or a CSS class, or jquery?
The reason I ask, is that if you use simply style="display:none" I never have problems with the modal showing the modal perfectly all the time using dialog("open") but if I use either css or jquery, I always have problems.
You may want to test it.
Marcus

Categories