Loading a form into an iframe - javascript

I want to load a form into an iframe. The iframe will be loaded into a random page when the user clicks the bookmarklet.
Here is the code so far:
loginForm = document.createElement("form");
loginForm.setAttribute("method","Post");
loginForm.setAttribute("action","http://devserver:8000/action/");
parameters = {};
parameters['url'] = parent.window.location;
for(var key in parameters)
{
var hiddenField = document.createElement("input");
hiddenField.setAttribute('type',"hidden");
hiddenField.setAttribute('name',key);
hiddenField.setAttribute('value',parameters[key]);
loginForm.appendChild(hiddenField);
}
loginIFrame = document.createElement('iframe');
loginIFrame.src = "about:blank";
loginIFrame.appendChild(loginForm);
loginIFrame.style.top = "0px";
loginIFrame.style.position='fixed';
loginIFrame.style.display = 'block';
loginIFrame.style.zIndex = 100;
loginIFrame.style.border = "solid #48D236 10px";
loginIFrame.height = "25px";
loginIFrame.width = "100%";
loginIFrame.style.border = 0;
loginIFrame.id = "loginFrame";
loginIFrame.name = "loginFrame";
usernameField = document.createElement("input");
usernameField.type = "text";
usernameField.size = 8;
usernameField.name = "usernameField";
usernameField.id = "usernameField";
passwordField = document.createElement("input");
passwordField.type = "password";
passwordField.size = 8;
passwordField.name = "passwordField";
passwordField.id = "passwordField";
submitButton.style.position='fixed';
submitButton.style.top = "60px";
submitButton.type = "button";
submitButton.value = "Submit";
submitButton.onclick = function(){loginUser();};*/
b.style.position="relative";
addToBody(loginIFrame);
loginForm.submit();
What ends up happening is the entire page gets reloaded on the submit (last line of code) rather than the iframe. Any ideas?
Thanks in advance

You might want to try adding the form using loginIFrame.contentWindow.document instead of loginIFrame.appendChild.
You might also need to add your form after the iframe has been added to the page since the contentWindow property won't be available.
I could be wrong, but I'm pretty sure that form isn't being added to the iframe, because you are using appendChild. I really don't think you can manipulate it that wa since it will be loading the URL you tell it to load (i.e. about:blank).
Edit: You might also want to add loginForm.setAttribute("target", "loginFrame");
Here is what I've been testing with and it works fine:
loginIFrame = document.createElement('iframe');
loginIFrame.src = "about:blank";
loginIFrame.style.top = "0px";
loginIFrame.style.position='fixed';
loginIFrame.style.display = 'block';
loginIFrame.style.zIndex = 100;
loginIFrame.style.border = "solid #48D236 10px";
loginIFrame.height = "100px";
loginIFrame.width = "100%";
loginIFrame.style.border = 0;
loginIFrame.id = "loginFrame";
loginIFrame.name = "loginFrame";
document.body.appendChild(loginIFrame);
var idocument = loginIFrame.contentWindow.document;
loginForm = idocument.createElement("form");
loginForm.setAttribute("target", "loginFrame");
loginForm.setAttribute("method","Post");
loginForm.setAttribute("action","http://devserver:8000/action/");
parameters = {};
parameters['url'] = parent.window.location;
for(var key in parameters)
{
var hiddenField = idocument.createElement("input");
hiddenField.setAttribute('type',"hidden");
hiddenField.setAttribute('name',key);
hiddenField.setAttribute('value',parameters[key]);
loginForm.appendChild(hiddenField);
}
loginIFrame.appendChild(loginForm);
loginForm.submit();
Christian

Possibly set the form target to the iFrame. I'm imagining, since you're creating elements within the "parent" page context, it's using the main page as a target (even though it's embeded).
EDIT
You could also try calling createElement from the iFrame after you've created it to keep context too.

Related

Popup won't close

Popup won't close when i click close button, i tried debugging with console.log and it looks like closeButton.onclick function doesn't run at all for some reason.
When running close() function manually from the console everything works fine.
class Popup {
constructor(content){
this.div = document.createElement("div");
this.div.className = "block";
//tried positioning popup into the center of the screen, doesn't work yet
this.div.style.position = "fixed";
this.div.style.margin = "auto auto";
//caption
this.caption = document.createElement("div");
this.caption.style.textAlign = "right";
//closeButton
this.closeButton = document.createElement("button");
this.closeButton.textContent = "X";
this.closeButton.onclick = this.close;
document.body.appendChild(this.div);
this.div.appendChild(this.caption);
this.caption.appendChild(this.closeButton);
this.div.innerHTML += content;
}
close(){
this.div.parentNode.removeChild(this.div);
delete this;
}
}
new Popup("close me");
That's how it looks like:
var popup = new Popup("hm hello");
SOLUTION:
The issue was happening because:
I was appending content of the popup right into main div using +=. That made DOM refresh and onclick trigger reset.
this.closeButton.onclick = this.close; here onclick trigger will execute close function and also will overwrite this keyword, so it contains a button that called trigger, not the Popup object. I decided to put Popup into a variable that is visible to onclick function. Now everything works fine.
class Popup {
constructor(content){
this.div = document.createElement("div");
this.div.className = "block";
this.div.style.position = "fixed";
this.div.style.margin = "auto auto";
//делоем капшон
this.caption = document.createElement("div");
this.caption.style.textAlign = "right";
//кнопка закрытия
this.closeButton = document.createElement("button");
this.closeButton.textContent = "X";
let popup = this;
this.closeButton.onclick = function(){popup.close()};
this.content = document.createElement("div");
this.content.innerHTML = content;
this.caption.appendChild(this.closeButton);
this.div.appendChild(this.caption);
this.div.appendChild(this.content);
document.body.appendChild(this.div);
}
close(){
this.div.parentNode.removeChild(this.div);
delete this;
}
}
new Popup("hello guys");
The issue is that right here:
this.div.innerHTML += content;
When you assign a value to .innerHTML, the entire previous value is overwritten with the new value. Even if the new value contains the same HTML string as the previous value, any DOM event bindings on elements in the original HTML will have been lost. The solution is to not use .innerHTML and instead use .appendChild. To accomplish this in your case (so that you don't lose the existing content), you can create a "dummy" element that you could use .innerHTML on, but because of performance issues with .innerHTML, it's better to set non-HTML content up with the .textContent property of a DOM object.
You were also going to have troubles inside close() locating the correct parentNode and node to remove, so I've updated that.
class Popup {
constructor(content){
this.div = document.createElement("div");
this.div.className = "block";
this.div.style.position = "fixed";
this.div.style.margin = "auto auto";
//caption
this.caption = document.createElement("div");
this.caption.style.textAlign = "right";
//closeButton
this.closeButton = document.createElement("button");
this.closeButton.textContent = "X";
this.closeButton.addEventListener("click", this.close);
this.caption.appendChild(this.closeButton);
this.div.appendChild(this.caption);
// Create a "dummy" wrapper that we can place content into
var dummy = document.createElement("div");
dummy.textContent = content;
// Then append the wrapper to the existing element (which won't kill
// any event bindings on DOM elements already present).
this.div.appendChild(dummy);
document.body.appendChild(this.div);
}
close() {
var currentPopup = document.querySelector(".block");
currentPopup.parentNode.removeChild(currentPopup);
delete this;
}
}
var popup = new Popup("hm hello");
I've finally found a final solution.
As Scott Marcus mentioned in his answer, i will have troubles inside close function, so i decided to put Popup object into a variable that is visible to close function. Everything works fine without applying classes. Though it may look like a bad code.
class Popup {
constructor(content){
this.div = document.createElement("div");
this.div.className = "block";
this.div.style.position = "fixed";
this.div.style.margin = "auto auto";
//делоем капшон
this.caption = document.createElement("div");
this.caption.style.textAlign = "right";
//кнопка закрытия
this.closeButton = document.createElement("button");
this.closeButton.textContent = "X";
let popup = this;
this.closeButton.onclick = function(){popup.close()};
this.content = document.createElement("div");
this.content.innerHTML = content;
this.caption.appendChild(this.closeButton);
this.div.appendChild(this.caption);
this.div.appendChild(this.content);
document.body.appendChild(this.div);
}
close(){
this.div.parentNode.removeChild(this.div);
delete this;
}
}
new Popup("hello guys")
P.S.
What's the point of this restriction?

tag onclick being processed twice

I want clicking on an "expando" to toggle between its states: expanded and collapsed.
I'm still pretty new to DOM/JS, so my style here is probably awful; If you have any style guidelines let me know, but for right now I want to get the code working. I've tried a few different ways, like setting the expand or collapse behavior in dom's onclick (and changing it in the expand and collapse functions), but if I do that, then for some reason clicking doesn't trigger a collapse, but it will trigger an expand.
The problem with the code below is that I can expand an expando, but when I click on it, it also triggers the collapse, so it expands and then immediately collapses back.
var expandos = document.getElementsByTagName("expando");
var uid = 0;
for(var i=0; i<expandos.length; ++i) {
var dom = expandos[i];
dom.id = "expando_"+uid++;
var iframe = document.createElement("iframe");
iframe.src = dom.innerHTML;
iframe.name = dom.id +".big";
iframe.id = iframe.name;
iframe.scrolling = "no";
iframe.style.display = "inline";
iframe.onclick = collapse(dom);
var p = document.createElement("p");
var text = document.createTextNode(dom.innerHTML);
p.id = dom.id+".small";
p.style.display = "inline";
p.appendChild(text);
p.onclick = expand(dom);
dom.innerHTML = "";
/* We have to clear the innerHTML to prevent the original text from
showing up in addition to the text added by p.
*/
dom.appendChild(iframe);
dom.appendChild(p);
/* We have to append iframe and p **after** we clear innerHTML
because otherwise clearing innerHTML will clear the appended
children.
*/
function expand(dom) {
return function() {
alert("Expanding "+dom.id);
var iframe = document.getElementById(dom.id+".big");
var p = document.getElementById(dom.id+".small");
p.style.display = "none";
iframe.style.display = "initial";
dom.onclick = collapse(dom);
}
}
function collapse(dom) {
return function() {
alert("Collapsing "+dom.id);
var iframe = document.getElementById(dom.id+".big");
var p = document.getElementById(dom.id+".small");
p.style.display = "initial";
iframe.style.display = "none";
dom.onclick = expand(dom);
}
}
collapse(dom)();
}
The sample HTML I'm testing on:
<body>
<expando>The quick brown</expando> fox jumps over <expando>the lazy dog</expando>.
<script src="loadExpandos.js"></script>
</body>
In the same directory, I have files named "The quick brown" and "the lazy dog", and they expand properly.
A quick fix for to get the basic functionality you want is to combine your expand and collapse into a single function and have an if/else block that checks the state. Not 100% on what caused your original issue, but I'd guess it has something to do with your onClick events not being cleared.
function clickHandler(dom) {
return function() {
var iframe = document.getElementById(dom.id+".big");
var p = document.getElementById(dom.id+".small");
if(p.style.display === "initial"){
p.style.display = "none";
iframe.style.display = "initial";
} else {
p.style.display = "initial";
iframe.style.display = "none";
}

JavaScript: ImageClick through transparent iframe

I have a transperent iframe, which created by next JS function:
Frames.prototype.CreateIframe = function (frameName, frWidth, frHeight, zindex) {
var frameObj = document.createElement('iframe');
frameObj.width = PX(frWidth);
frameObj.src = 'Content.htm';
frameObj.height = PX(frHeight);
frameObj.id = frameName;
frameObj.name = frameName;
frameObj.frameBorder = 0;
frameObj.allowTransparency = 'allowtransparency';
frameObj.style.zIndex = zindex;
frameObj.style.position = 'absolute';
frameObj.style.scrolling = 'no';
frameObj.style.scroll = 'no';
frameObj.style.overflow = 'hidden';
frameObj.style.left = PX(0);
frameObj.style.top = PX(0);
GlobalClass.AppendChild(window, frameObj);
}
Below that is another iframe where the images are placed. I created event handlers for these images. For example document.GetElementById("MyImage").onclick(alert("Click!"));
If I run it by IE, everything works fine. But I run it by Chrome, Firefox, Opera nothing works. How I can correct this?
The upper transparent iframe has event handlers and it works in IE also.
document.GetElementById("MyImage").onclick= function(){
alert("Click!");
}

Dynamic img creation through a link without attaching multiple instances

I have a link that is attached with an "onclick" function. When pressed it attaches an img element into a separate div called "mediaBox". The problem I'm having is that if it's pressed multiple times then it attaches more instances of the img. How can I control this. I'm still new to JavaScript and I prefer to receive this answer in pure Javascript not jQuery, as I will cross that bridge after I have a full understanding of Javascript.
var rkf = document.getElementById("submenulinks").getElementsByTagName("li")[0];
rkf.onclick = function(){
var client = document.getElementById('client');
var description2 = document.getElementById('description2');
var role = document.getElementById('role');
var mediaBox = document.getElementById('mediaBox');
var thumb = document.getElementById("thumb");
var client2 = document.getElementById("client2");
var newImage = document.createElement("img");
client2.innerHTML = "Role - Applications";
client.innerHTML = "RKF Real Estate";
client2.innerHTML = "Role - Applications";
description2.innerHTML = "Quarterly Catalog of Exclusive Listings managed by RKF";
role.innerHTML = "Custom designed Cover and listings content. Tables were also utilized within Indesign. <br><br><b><i> Photoshop and Indesign</i></b>";
newImage.setAttribute("src", "../images/rkf_cover.jpg");
newImage.setAttribute("height", "500px");
newImage.setAttribute("width", "387px");
newImage.setAttribute("alt", "rkf");
newImage.setAttribute("href", "#");
mediaBox.style.backgroundImage = "none";
document.getElementById("mediaBox").appendChild(newImage);
newImage.style.display = "block";
newImage.style.marginLeft = "auto";
newImage.style.marginRight = "auto";
newImage.style.marginTop = "25px";
}
rkf.onclick = function(){
var client = document.getElementById('client');
...
...
...
// Remove the handler after it ran once.
this.onclick = null; // <<<<<========================
}
Since you do want to use jQuery in the future, it's equal to:
$('#submenulinks li:first').one('click', handler);

Confirm replacement in JavaScript

Yes, I've searched high and low on Stack Overflow and seen some great solutions to this problem that's been solved time and time again with things like SimpleModal, jQuery.confirm and the like.
Problem is, I am developing for this low level device that doesn't allow for a JS framework to be utilized AND I am having to shoehorn this modal confirm into existing JS.
There is an existing script that I am at liberty to edit (but not rewrite) that does a few things like validate, concatenate a few inputs into a single variable, and more.
The script was written to:
Take some session variables and assign new variable names to them and format accordingly
Present a confirm to the user to see whether they want to use those variables to pre-populate the form on the page
Get some functions ready to validate inputs.
other stuff, like offer an abandonment scenario, among other things
Now, all was good when the "confirm" was in place as the script would pause until an OK or Cancel was provided. I am now presenting a modal on the page that I want to mock this behavior and the only way I can think of doing it is to remove that reliance on the line that goes through the confirm thing and NOT run the script until the user interacts with the modal.
Does anyone have an idea how to take what's in place and "wrap" it in a "listening" if/else scenario for each of the YES or NO possibilities?
Sorry if this is jumbled... my brain is all blended up at the moment, too.
As far as I know there is - so far - no way to halt scripts like the Browser specific alert() or confirm() Dialog does.
Frameworks like dojo for example try to mock this behaviour by putting a transparent DIV over the whole window to prevent clicks or other input while the Dialog is showing.
This is quite tricky as I have experienced, since Keyboard-Input may be able to activate Input Fields or Buttons behind this curtain. Keyboard Shortcuts or Field-Tabbing for example.
One sollution is to disable active Elements manually, which works quite well with me in most cases.
One or more function is passed to this "mock" Dialog to execute when an option was chosen.
Escpecially with ajax background activity the responsibilty to stop conflicting function calls while the Dialog is open lies with the developer.
Here is an example I came up with:
<html>
<head>
<title>Modal Dialog example</title>
<script type="text/javascript">
<!--
var ModalDialog = function(text,choices){
this._text = text;
this._choices = choices;
this._panel = null;
this._modalDialog = null;
this._disableElements = function(tag){
var elements = document.getElementsByTagName(tag);
for(i=0; i < elements.length; i++){
elements[i].disabled = true;
}
};
this._enableElements = function(tag){
var elements = document.getElementsByTagName(tag);
for(i=0; i < elements.length; i++){
elements[i].disabled = false;
}
};
this._disableBackground = function(){
if(this._panel){
this._panel.style.display = 'block';
}
else{
// lower the curtain
this._panel = document.createElement('div');
this._panel.style.position = 'fixed';
this._panel.style.top = 0;
this._panel.style.left = 0;
this._panel.style.backgroundColor = 'gray';
this._panel.style.opacity = '0.2';
this._panel.style.zIndex = 99; // make sure the curtain is in front existing Elements
this._panel.style.width = '100%';
this._panel.style.height = '100%';
document.body.appendChild(this._panel);
// Disable active Elements behind the curtain
this._disableElements('INPUT');
this._disableElements('BUTTON');
this._disableElements('SELECT');
this._disableElements('TEXTAREA');
}
};
this.close = function(){
// Hide Curtain
this._panel.style.display = 'none';
// Hide Dialog for later reuse - could also be removed completely
this._modalDialog.style.display = 'none';
// reactivate disabled Elements
this._enableElements('INPUT');
this._enableElements('BUTTON');
this._enableElements('SELECT');
this._enableElements('TEXTAREA');
};
this.open = function(){
var _this = this;
this._disableBackground();
if(this._modalDialog){
this._modalDialog.style.display = 'block';
}
else{
// create the Dialog
this._modalDialog = document.createElement('div');
this._modalDialog.style.position = 'absolute';
this._modalDialog.style.backgroundColor = 'white';
this._modalDialog.style.border = '1px solid black';
this._modalDialog.style.padding = '10px';
this._modalDialog.style.top = '40%';
this._modalDialog.style.left = '30%';
this._modalDialog.style.zIndex = 100; // make sure the Dialog is in front of the curtain
var dialogText = document.createElement('div');
dialogText.appendChild(document.createTextNode(this._text));
// add Choice Buttons to the Dialog
var dialogChoices = document.createElement('div');
for(i = 0; i < this._choices.length; i++){
var choiceButton = document.createElement('button');
choiceButton.innerHTML = this._choices[i].label;
var choiceAction = _this._choices[i].action
var clickAction = function(){
_this.close();
if(choiceAction)choiceAction();
};
choiceButton.onclick = clickAction;
dialogChoices.appendChild(choiceButton);
}
this._modalDialog.appendChild(dialogText);
this._modalDialog.appendChild(dialogChoices);
document.body.appendChild(this._modalDialog);
}
};
};
var myConfirm = function(text,okAction){
var dialog = new ModalDialog(text,[
{
label:'ok',
action : function(){
console.log('ok')
okAction();
}
},
{
label:'cancel'
}
]);
dialog.open();
};
-->
</script>
</head>
<body>
<form name="identity" action="saveIdentity.do">
<label>Firstname</label><input name="name" type="text"><br>
<label>Lastname</label><input name="name" type="text"><br>
<input type="button"
value="submit"
onclick="if(myConfirm('Do you really want to Commit?',function(){ document.forms['identity'].submit();}));">
</form>
</body>
</html>
In this code there is still an error concerning the availability of the stored choice-function (undefined) at execution time. The function variable is no longer available in the closure. If anyone has a sollution for this you are welcome to add to it.
Hope that comes near to what you need to know.
Updated version: fixed choiceAction undefined, added IE compatibility. Internet Explorer is one main reason to use this, since confirm() is now blocked by default.
<!doctype html>
<html><head>
<title>Modal Dialog example</title>
<script type="text/javascript"><!-- //http://stackoverflow.com/questions/4739740/yet-another-confirm-replacement-quesiton
var ModalDialog = function(text,choices) {
this._text = text;
this._choices = choices;
this._panel = null;
this._modalDialog = null;
this._disableElements = function(tag) {
var elements = document.getElementsByTagName(tag);
for(i=0; i < elements.length; i++) {
elements[i].disabled = true;
}
};
this._enableElements = function(tag) {
var elements = document.getElementsByTagName(tag);
for(i=0; i < elements.length; i++) {
elements[i].disabled = false;
}
};
this._disableBackground = function() {
if(this._panel) {
this._panel.style.display = 'block';
}
else {
// lower the curtain
this._panel = document.createElement('div');
this._panel.style.position = 'fixed';
this._panel.style.top = 0;
this._panel.style.left = 0;
this._panel.style.backgroundColor = '#000';
this._panel.style.opacity = '0.3';
this._panel.style.filter = 'alpha(opacity=30)'; //ie7+
this._panel.style.zIndex = 99; // make sure the curtain is in front existing Elements
this._panel.style.width = '100%';
this._panel.style.height = '100%';
document.body.appendChild(this._panel);
// Disable active Elements behind the curtain
this._disableElements('INPUT');
this._disableElements('BUTTON');
this._disableElements('SELECT');
this._disableElements('TEXTAREA');
}
};
this.close = function() {
// Hide Curtain
this._panel.style.display = 'none';
// Hide Dialog for later reuse - could also be removed completely
this._modalDialog.style.display = 'none';
// reactivate disabled Elements
this._enableElements('INPUT');
this._enableElements('BUTTON');
this._enableElements('SELECT');
this._enableElements('TEXTAREA');
};
this.open = function() {
var _this = this;
this._disableBackground();
if(this._modalDialog) {
this._modalDialog.style.display = 'block';
}
else {
// create the Dialog
this._modalDialog = document.createElement('div');
this._modalDialog.style.position = 'absolute';
this._modalDialog.style.backgroundColor = 'white';
this._modalDialog.style.border = '1px solid black';
this._modalDialog.style.padding = '16px';
this._modalDialog.style.top = '35%';
this._modalDialog.style.left = '30%';
this._modalDialog.style.zIndex = 100; // make sure the Dialog is in front of the curtain
var dialogText = document.createElement('div');
dialogText.style.padding = '0 10px 10px 0';
dialogText.style.fontFamily = 'Arial,sans-serif';
dialogText.appendChild(document.createTextNode(this._text));
// add Choice Buttons to the Dialog
var dialogChoices = document.createElement('div');
for(i = 0; i < this._choices.length; i++) {
var choiceButton = document.createElement('button');
choiceButton.style.marginRight = '8px';
choiceButton.name = i;
choiceButton.innerHTML = this._choices[i].label;
var clickAction = function() {
_this.close();
if(_this._choices[this.name].action) _this._choices[this.name].action();
};
choiceButton.onclick = clickAction;
dialogChoices.appendChild(choiceButton);
}
this._modalDialog.appendChild(dialogText);
this._modalDialog.appendChild(dialogChoices);
document.body.appendChild(this._modalDialog);
}
};
};
var myConfirm = function(text,okAction){
var dialog = new ModalDialog(text,[
{
label : 'OK',
action : function() {
console.log('ok');
okAction();
}
},
{
label : 'Cancel'
}
]);
dialog.open();
};
-->
</script>
</head>
<body>
<form name="identity" action="saveIdentity.do">
<label>Firstname</label><input name="name" type="text"><br>
<label>Lastname</label><input name="name" type="text"><br>
<input type="button" value="submit"
onclick="if(myConfirm('Do you really want to Commit?',function(){ alert('submitted') }));">
<!-- document.forms['identity'].submit(); -->
</form>
</body>
</html>

Categories

Resources