I would like to dynamically create a div on a page using JS and have it behave like a dev console behaves in Chrome and Firefox. By this, I mean that when the div is visible, it does not negatively impact the display of other DOM elements. It would simply either "push up" or "push down" elements on the page.
Is this possible without having to redesign the application's DOM elements to account for the "div console?"
I've tried generating the div as the first element on the page, but that still would not account for DOM elements that are position absolute or fixed:
div = document.createElement('div');
div.id = 'wc-test-window';
div.style.width = "100%";
div.style.height = "200px";
div.style.backgroundColor = '#eee';
div.style.position = 'relative';
div.style.top = 0;
div.style.right = 0;
div.style.display = 'none';
document.body.insertBefore(div, document.body.firstChild);
I'm disappointed in this community for all of the unconstructive comments and downvotes for a perfectly legitimate question. Anyway, I solved it using framesets and frames for anyone looking for a viable answer to this problem.
function showDevConsole() {
var fs = document.createElement('frameset'),
f1 = document.createElement('frame'),
f2 = document.createElement('frame');
fs.rows = "200,*";
fs.framespacing = "0";
// top frame - show the dev console
f1.name = "topframe";
f1.src = "dev-console.html";
f1.marginwidth = "0";
f1.marginheight = "0";
f1.noresize = "noresize";
f1.scrolling = "no";
// bottom frame - show current page
f2.name = "bottomframe";
f2.src = window.location;
f2.marginwidth = "0";
f2.marginheight = "0";
f2.scrolling = "auto";
f2.frameborder = "0";
// append the frames to the frameset
fs.appendChild(f1);
fs.appendChild(f2);
// replace the entire body with the framset containing both frames
$("body").replaceWith(fs);
return false;
}
I put the current page on the bottom frame and the "console" at the top. Any DOM manipulations that the top frame can do on the bottom frame will be done via JS using the name or id of the frame.
Related
Trying to add a 'X' - close button for a google maps marker. The markers will show small on the map but will enlarge when clicked (same marker, just increasing the size). I can add a close button but cannot get it to work (reduce the size back to original). Solutions need to be dynamically added please.
Fiddle: https://jsfiddle.net/gost1zLd/
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
div.style.background = 'black';
var img = document.createElement('img');
img.style.width = '100%';
img.style.height = '100%';
img.src = '';
var exit = document.createElement('div');
function large()
{
div.classList.add("large");
if (div.className == "large")
{
div.style.width = '300px';
div.style.height = '300px';
exit.innerText = 'X';
exit.style.width = '20px';
exit.style.height = '20px';
exit.style.fontSize = 'xx-large';
exit.style.fontWeight = 'bold';
exit.style.color = 'white';
exit.style.position = 'absolute';
exit.style.top = '5px';
exit.style.left = '265px';
}
}
function close()
{
div.classList.remove("large");
}
document.body.appendChild(div);
div.appendChild(img);
div.appendChild(exit);
div.addEventListener('click', large, false);
exit.addEventListener('click', close, false);
}
The problem is that removing the class large is not enough to reset the <div> to its original state since class large in itself is meaningless because it has no CSS definition. My advice is to move the styling to CSS instead of JavaScript. See fiddle: https://jsfiddle.net/gost1zLd/1/.
If you make separate functions, you can use start() again in your close() function to reset the original style. I've refactored your code a bit, hope it's self explanatory:
function close () {
div.classList.remove("large");
start();
}
Only problem with your setup is you will rebind everything when you would call start() on close(). Instead, try to separate functionality and the issue becomes clear.
DEMO
Additionally you can optimize the dynamic styling with some helper functions.
You need a function to convert a literal object to a css string.
You need a function to extend objects, similar to jQuery's $.extend() in order to set the style at once (doc) for both states (normal and large).
this.divStyle = convertLiteralToQs(cfg.div.style);
this.divLarge = convertLiteralToQs(extend(cfg.div.style, cfg.div.large));
this.div.style.cssText = this.divStyle; // normal style
this.div.style.cssText = this.divLarge; // large style
This will speed up the browser reflow for dynamic styling in JavaScript.
DEMO
Using this approach you can now more easily "style your logic" cross referencing the HTML DOM style object.
I have a web application in which I have a bunch of iFrame from with source from other tools.
Now the user should have the possibility to open the iframe content in a new window / new tab, normaly I would simply add something like this:
function onButtonClick() { var src = $('#iframe').prop('src');
windows.open(src, "_blank"); }
But his would only open a new version of my iFrame context, e.g. if a user open a page in the iframe or clicked on something and javascript changed something within my iframe, the user would be loosing this value..
So, can I make a iframe Content to a new window content without loosing the dynamic state of the website within my iframe?
You cannot move around iframes between different windows without reloading, because the spec says the attributes must be reevaluated:
When an iframe element is inserted into a document that has a browsing context, the user agent must create a nested browsing context, and then process the iframe attributes for the "first time".
-- https://html.spec.whatwg.org/multipage/embedded-content.html#the-iframe-element
(via https://bugzilla.mozilla.org/show_bug.cgi?id=254144#c97)
Old answer:
// edit: Does not work as expected, since the iframe is reloaded on move and the original src is restored.
It is easy enough if you move the iframe out of the current page:
<button id="example-button">open in new window</button>
<div id="example-container">
<iframe id="example-iframe" src="https://example.com/">
</iframe>
</div>
document.getElementById('example-button').addEventListener('click', function (ev) {
ev.preventDefault();
var win = open('about:blank');
var iframe = document.getElementById('example-iframe');
// the popup might not be immediately available:
setTimeout(function () {
var body = win.document.body;
body.style.padding = 0;
body.style.margin = 0;
body.appendChild(iframe);
iframe.style.position = 'fixed';
iframe.style.padding = 0;
iframe.style.margin = 0;
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = 0;
}, 0);
// move the iframe back if the popup in closed
win.addEventListener('beforeunload', function () {
document.getElementById('example-container').appendChild(iframe);
iframe.style.position = '';
iframe.style.padding = '';
iframe.style.margin = '';
iframe.style.width = '';
iframe.style.height = '';
iframe.style.border = '';
});
});
Example: http://jsfiddle.net/cpy2jykv/1/
I am new to firefox extension and did not know how to develop toolbar like div in javascript/content script and want to fix it to the top of body(want to push body down). please help.
var toolbarHeight = 40;
var div = document.createElement("div");
div.id = "myToolbar";
div.textContent = " ";
var st = div.style;
st.display = "block";
st.top = "0px";
st.left = "0px";
st.width = "100%";
st.height = toolbarHeight + "px";
st.background = "#F0F0F0";
st.color = "grey";
st.fontStyle = "italic";
st.position = "fixed";
document.body.style.webkitTransform = "translateY(" + toolbarHeight + "px)";
document.documentElement.appendChild(div);
****2 UPDATE:**
I have seen update this works but div also moves with body
because document.documentElement.appendChild(div);
is not working and with document.body.insertBefore(div, document.body.firstChild);
div also moves down becuase of inserting in body
This is normal because you assign in a body the style document.body.style.webkitTransform = // Chrome, Opera, Safari
document.body.style.msTransform = // IE 9
document.body.style.transform = "translateY(" + toolbarHeight + "px)";
The problem is a style.
Now there is a one possibility where you not assign this style to <body> but only on <div> and you can create inside the body two <div>.
NOTE You cannot create two <body> in a file HTML because it 's a valid document HTML INFO
Where the first <div> is the created of script that we discuss and other the rest of the <body> in the <div>.
Final you can assign the style on a div using document.getElementById("idofdiv").style.webkitTransform =document.getElementById("idofdiv").style.msTransform =document.getElementById("idofdiv").style.transform = "translateY(" + toolbarHeight + "px)";
And I shocked on the last comment.
****UPDATE:**
With the comment I understand you problem.
I copy new you script and paste on my notebook.
I open the file HTML on Firefox and Chromium (this is a name of Chrome on Ubuntu).
You can see the output and difference on imguru.
Now the problem is only on document.body.parent.style.webkitTransform='translateY(40px)';
I find why not function and this is not supported on Firefox, IE and OPERA.
You see on the site
Now I change it with
document.body.style.webkitTransform = // Chrome, Opera, Safari
document.body.style.msTransform = // IE 9
document.body.style.transform = "translateY(" + toolbarHeight + "px)";
And the output is equal on Chrome. IMGURU
OLD:
I take you script and work in my notebook.
Inside the code there is a error on document.body.parent.style.webkitTransform='translateY(40px)'; and the error is:
TypeError: document.body.parent is undefined
This I not know that is and I delete.
Now I have other error TypeError: document.body is null on var div = document.createElement("div");
I search on google and I fix this
Now I insert window.onload{ } with inside you script and I insert the tag for push body down.
<script type="text/javascript">
window.onload = function() {
//document.body.parent.style.webkitTransform ='translateY(40px)';
var div = document.createElement("div");
var br=document.createElement("br");
div.id="divs";
div.style.display='block';
div.style.width = "600px";
div.style.height = "100px";
div.style.background = "#C2E2FF";
div.style.color = "grey";
div.innerHTML = "my div";
document.body.insertBefore(br, document.body.firstChild);
document.getElementById("divs").style.fontStyle = 'italic';
document.getElementById("divs").style.position = "fixed";
}</script>
The output not view the body because the error (I say the error but this is not error) on style="fixed" because "replace" the (The element is positioned relative to the browser window).
I remove this and the output is correct.
I think that you have a problem with position and I suggest for you of use Firebug (tool of firefox and chrome) for find error
For information on the position you go on this site
Final DEMO
I'm attempting to create a slide out panel that appends to the container div within the header and footer of my page. I'm using Bootstrap for responsive, so the solution should ideally work with the media-queries contained within that package. I'm really at a loss on how to approach this because everything I've tried doesn't seem to work in some way or another.
This picture animates best what I'm trying to accomplish (sorry not a designer):
http://d.pr/i/DzQc+
What I've tried:
Pageslide - this is was the closest solution I've found so far. this appends the slide out panel to the body. As such it doesn't allow me to keep the slide out panel within the header/footer container of the page: http://srobbin.com/jquery-plugins/pageslide/
jQuery Mobile Panel Widget - I tried to hack and repurpose the jQuery mobile panel widget plugin to function as desired without any luck.
.append Function - I tried to animate the .append function but this didn't work with the responsive functions of bootstrap.
With that all said, do any of you have a suggestion on a plugin, function or implementation that may work? I'm not necessarily looking for a working piece of code, rather I'm looking for a direction that will work as I'm hoping.
Thanks!
Here is a popup container in a prototype pattern I built that you can create to any div. CSS it up to style to your liking
Useage:
InfoPopup.Create('YourDivID');
InfoPopup.Destroy();
InfoPopup.Bounce();
$(InfoPopup.YesBtn).fadeIn();
$(InfoPopup.NoBtn).fadeIn();
$(InfoPopup.ShowBtn).fadeIn();
Ect...
InfoPopup = {
YesBtn:'',
NoBtn:'',
ShowBtn:'',
IdlBtn:'',
HintText:'',
Create:function(target, contentId){
var infoImage = "";
var infoWrapperDiv = document.createElement('div');
infoWrapperDiv.id = 'infoWrapperDiv';
//min-max button
var minMax = document.createElement('img');
minMax.src = "images/minimize.png"
minMax.id = 'infoPopupMinMax';
minMax.setAttribute('onClick','InfoPopup.Shrink();');
infoWrapperDiv.appendChild(minMax);
//content
var contentDiv = document.createElement('div');
contentDiv.id = 'infoPopupContent';
contentDiv.innerHTML = '<span>Some Stuff Here</span>'
infoWrapperDiv.appendChild(contentDiv);
//YesNoButtons - append to infoWrapperDiv if needed in specific activity
//---- set custom onClick for the specific Activity in the switch
this.YesBtn = document.createElement('input');
this.YesBtn.id = 'infoBtnYes';
this.YesBtn.setAttribute('value','Yes');
this.YesBtn.setAttribute('type','button');
this.YesBtn.className = 'inputButton';
this.NoBtn = document.createElement('input');
this.NoBtn.id = 'infoBtnNo';
this.NoBtn.setAttribute('value','No');
this.NoBtn.setAttribute('type','button');
this.NoBtn.className = 'inputButton';
this.ShowBtn = document.createElement('input');
this.ShowBtn.id = 'infoBtnShow';
this.ShowBtn.setAttribute('type','button');
this.ShowBtn.setAttribute('value','Show');
this.IdlBtn = document.createElement('input');
this.IdlBtn.setAttribute('type','button');
this.HintText = document.createElement('div');
this.HintText.className = 'infoPopupHint';
switch(contentId){//Remove switch to just set up the content
case 1://on a 1 page web app the activity will dictate what content is presented
this.YesBtn.setAttribute('onClick','currentActivityObject.SaveVerification(1);');
this.NoBtn.setAttribute('onClick','currentActivityObject.SaveVerification(0);');
this.YesBtn.style.display = 'none';
this.NoBtn.style.display = 'none';
infoWrapperDiv.appendChild(this.YesBtn);
infoWrapperDiv.appendChild(this.NoBtn);
this.ShowBtn.setAttribute('onmousedown',"currentActivityObject.ShowAnswer(1);");
this.ShowBtn.setAttribute('onmouseup',"currentActivityObject.ShowAnswer(0);");
this.ShowBtn.className = 'inputButton infoBottomLeft';
this.ShowBtn.style.display = 'none';
infoWrapperDiv.appendChild(this.ShowBtn);
break;
case 2:
break;
}
infoWrapperDiv.appendChild(this.HintText);
$id(target).appendChild(infoWrapperDiv);
$('#infoWrapperDiv').animate({top:"78%"},'fast').animate({top:"80%"},'fast');
},
Shrink:function(){
$('#infoWrapperDiv').animate({top:"90%"},'fast').animate({top:"88%"},'fast');
var minMax = document.getElementById('infoPopupMinMax');
minMax.setAttribute('onClick','InfoPopup.Grow();')
},
Grow:function(){
$('#infoWrapperDiv').animate({top:"78%"},'fast').animate({top:"80%"},'fast');
var minMax = document.getElementById('infoPopupMinMax');
minMax.setAttribute('onClick','InfoPopup.Shrink();')
},
Bounce:function(){
$('#infoWrapperDiv')
.animate({top:"90%"},'fast')
.animate({top:"80%"},'fast');
},
Destroy:function(){
var infoWrapperDiv = $id('infoWrapperDiv');
if(infoWrapperDiv){
infoWrapperDiv.parentNode.removeChild($id('infoWrapperDiv'));
}
}
};
First,I created a hidden frame like this:
var oHiddenFrame = null;
if(oHiddenFrame == null){
oHiddenFrame = document.createElement("iframe");
oHiddenFrame.name = "hiddenFrame";
oHiddenFrame.id = "hiddenFrame";
oHiddenFrame.style.height = "0px";
oHiddenFrame.style.width = "0px";
oHiddenFrame.style.position = "absolute";
oHiddenFrame.style.visbility = "hidden";
document.body.appendChild(oHiddenFrame);
}
Then,I add a event to the button like this:
var fnLocation = function(){
frames["hiddenFrame"].location.href = "http://meckmeck.cn";
}
var oButton = document.getElementById("mb_submit");
oButton.addEventListener("click", fnLocation, false);
When I click the button,I got a error:
frames.hiddenFrame is undefined
There's no such thing as document.frames. The name-indexed frame array is window.frames (aka just frames).
0-iframes are so old-school, and these days mostly associated with malware-installing exploits (especially on Chinese pages). How about using an XMLHttpRequest instead?