I am using the following code that I originally found from this question:
Prevent offline iphone webapp from opening link in Safari
bodyOnClickHandler = function(e) {
var target = e.target;
if (target.tagName == 'A') {
e.preventDefault();
var targetUrl = target.getAttribute("href");
window.location = targetUrl;
}
}
The question describes the solution but not how to actually implement it. Also, I am attempting to do the exact same thing as in the original question. Thanks!
You can do something like this.
<body>
Click me
<div id="dynamic-content"></div>
<script id="template" type="text/html">
<h1>Hello</h1>
<p>This is a template</p>
</script>
<script>
document.addEventListener('click', function (e) {
var target = e.target;
if (target.tagName == 'A') {
e.preventDefault();
document.getElementById('dynamic-content').innerHTML = document.getElementById('template').innerHTML;
}
}, false);
</script>
</body>
It catches all click events and prevents the default behavior. It then takes content from a template, which is stored inside a script tag with type "text/html", and injects it into the DOM. All browsers will ignore script tags with anything other than "text/javascript", so it's safe to hide template content this way. I'm not doing anything dynamic with the template here, but if you wanted to do that, you can use something like John Resig's MicroTemplate as he describes here: http://ejohn.org/blog/javascript-micro-templating/. When using something like MicroTemplate, you'll want to merge the template content with dynamic data before injecting it into the DOM.
Another good templating option is jQuery's official template (co-authored by Microsoft): http://api.jquery.com/category/plugins/templates/
Related
I have an iframe of a certain page from a site that I'm using, but I don't want all the parts of that page to be displayed with the iframe. Particularly, there's a navigation sidebar on the page that I don't want to be in the iframe. I'm trying to achieve this with the javascript seen below, but I can't quite figure it out.
<iframe width="800" height="800" src="scores/new?site_id=193">
<script>
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
</script>
</iframe>
For security reasons you can't run javascript through iframes. There are some exceptions if you're on the same domain but for the most part you should really avoid it.
If the iframe isn't a site you can control then there's pretty much nothing you can do. If you do control the other site and it's a different domain you might be able to work with the postMessage functions.
Edit: Check out the docs that Mozilla has up here https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
You'd need to create a listener on the inside that handles a message and hides your sidebar. Then on the parent send a message to the iframe to trigger that function.
Parent:
var iframe = document.getElementById('#iframeID');
iframe.contentWindow.postMessage('iframeTrigger');
Iframe:
window.addEventListener('iframeTrigger', hideSidebar);
function hideSidebar() {
//do stuff
}
You can insert a control in the iframed page
//inside the iframed page
var iframe = (function() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
})();
if(iframe === true) {
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
}
Hope this could suit your need.
This should work theoretically, and it works in console. But this doesn't work in the HTML, although you are trying it from the same domain, because of security reasons. I just wanted to tell my view and I tried this:
<iframe src="http://output.jsbin.com/figujeyiyo" frameborder="0" id="ifrm">
Sorry, iframes not supported.
</iframe>
<script>
console.log(document.getElementById("ifrm").contentDocument.documentElement.getElementsByTagName("div"));
e = document.getElementById("ifrm").contentDocument.documentElement.getElementsByTagName("div")[0];
console.log(e);
e.parentNode.removeChild(element);
</script>
You need to execute the code when the page loads, you can do it like this:
document.addEventListener('DOMContentLoaded', function() {
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
});
I'm looking for a way to read the source code of a page after it finished loading and inspect the code to see if it contains a specific text.
I found this reference but this only returns the text visible in the page and not the whole HTML code.
For instance, if the html source code is:
<html>
<header>
<header>
<body>
<p> This is a paragraph</a>
<body>
</html>
I want the script to print exactly the same thing.
Your help is appreciated.
I think you are over-complicating this problem. You don't need to "print" the page's HTML or "inspect the code".
In a comment, you said:
Check if page contains an iframe [and] Display a message if the iframe is found
You can just use DOM traversal functions to examine the DOM.
Try something like this:
window.addEventListener('load', function() {
if(document.getElementsByTagName('iframe').length){
console.log('Found an iframe');
}
});
Or with jQuery:
$(function() {
if($('iframe').length){
console.log('Found an iframe');
}
});
That's so simple, you can use this method to run a script after a page is fully loaded window.onload
function load(){
console.log(document.getElementsByTagName('html')[0].innerHTML);
}
window.onload = load;
For further explanations, check this post
Do like this, call this function on load
Fiddle Demo
function printBody() {
// store oiginal content
var originalContents = document.body.innerHTML;
// get the outer html of the document element
document.body.innerText = document.documentElement.outerHTML;
// call window.print if you want it on paper
window.print();
// or put it into an iframe
// var ifr = document.createElement('iframe');
// ifr.src = 'data:text/plain;charset=utf-8,' + encodeURI(document.documentElement.outerHTML);
// document.body.appendChild(iframe);
// a small delay is needed so window.print does not get the original
setTimeout(function(){
document.body.innerHTML = originalContents;
}, 2000);
}
Src: Print <div id=printarea></div> only?
Assuming that by 'print' you don't actually mean to transfer it to a paper copy, you can add some script like:
window.addEventListener('load', function() {
var content = document.documentElement.innerHTML,
pre = document.createElement('pre'),
body = document.body;
pre.innerText = content;
body.insertBefore(pre, body.firstChild);
});
What this does, step by step is:
window.addEventListener('load', function() > Wait for the page to be fully loaded and then execute the function
content = document.documentElement.innerHTML > store the actual page source in the content variable (document.documentElement refers to the 'root'-node, usually <html> in html documents
pre = document.createElement('pre') > create a new <pre>-element
body = document.body > create a reference to the <body> element
pre.innerText = content > assign the HTML-structure we've stored earlier as text to the <pre>-element
body.insertBefore(pre, body.firstChild) > put the <pre>-element (now with contents) before any other element in the body (usually on top of the page).
This leaves you with the entire source (as it was before creating the <pre>-element containing the source) on top of you page.
Edit: Added <iframe> workflow
It was not clear to me you actually wanted to target an <iframe>, so here's how to do that (using a naive approach, more on that further on):
window.addEventListener('load', function() {
var iframeList = document.getElementsByTagName('iframe'),
body = document.body,
content, pre, i;
for (i = 0; i < iframeList.length; ++i) {
content = iframeList[i].documentElement.innerHTML;
pre = document.createElement('pre');
pre.innerText = content;
body.insertBefore(pre, body.firstChild);
}
});
why is this approach naive?
There is a thing called Same-Origin-Policy in javascript, which prevents you from accessing <iframe>-content which if the contents do not originate from the same domain as the page containing the <iframe>.
There are several ways to take this into consideration, you could wrap the inside of the for-loop in try/catch-blocks, though I prefer to use a more subtle approach by not even considering <iframes> which do not match the Same-Origin-Policy.
In order to do this, you can swap the getElementsByTagName method with the querySelectorAll method (please note the compatibility table at the bottom of that page, see if it matches your requirements).
The querySelectorAll accepts a valid CSS selector and will return a NodeList containing all matching elements.
A simple selector to use would be
'iframe[src]:not([src^="//"]):not(src^="http")' which selects all iframe with a src attribute which does not start with either // or http
Disclaimer: I never use a <base>-tag (which changes all relative paths within the HTML) or refer to the current website using a path containing the domain, so the example CSS-selector does not consider these aberrations.
Can you use :not()
IE9 or better
Can you use document.querySelector(All)
IE8 or better (in order to use with :not(), IE9 or better)
hover/click the boxes above to show the spoiler
I have a test that I have been working on, trying to send a value to a function defined within an iframe (both pages from the same source). The content of the iframe when in focus responds to certain keystrokes. What I would like to achieve is triggering those keypress actions from the iframe by means of a button on the primary page.
The content of the iframe is dynamic, and needs to function without refreshing, otherwise I know I could change the iframe src to carry the variables. What I have so far...
Parent Page:
<!DOCTYPE html><html><head>
<style>
iframe{border:1px solid blue;height:100px;width:100px;margin:20px auto 0 auto;}
</style>
</head><body>
<iframe id="iframe" src="iframetest2.html"></iframe>
<button onclick="simKey(32);">CLICK</button>
<script>
var iframe=document.getElementById('iframe');
var ifContent=iframe.contentWindow
function simKey(x){
ifContent.postMessage(testScript(x),'*','[transfer]');
}
</script></body></html>
And the iFrame content:
<!DOCTYPE html><html><head>
<script>
function testScript(x){
document.body.innerHTML=x;
setTimeout(function(){document.body.innerHTML='';},700);
}
</script></head><body onkeypress="testScript(event.keyCode)"></body></html>
I am also trying to avoid the use of jQuery if possible. This is a concept web design, and really want to hand-write the Javascript so that I can modify as need be.
First, inline js (like onkeypress in your html) is a bad practice. Read some these results: https://www.google.com/search?q=Why+is+inline+js+bad%3F
I will be using the best practice addEventListener.
Fire iFrame keypress event from button on parent window:
Live demo (click).
Main Page:
var myBtn = document.getElementById('myBtn');
var iframe = document.getElementById('myIframe');
myBtn.addEventListener('click', function() {
var evt = new Event('keypress');
evt.keyCode = '115';
iframe.contentDocument.body.dispatchEvent(evt);
});
iFrame:
document.body.addEventListener('keypress', function(e) {
console.log(e.keyCode);
});
Here are some docs that might help you if you need to support older browsers or want more information: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
Old Answer: this listens to keypresses on the parent window.
In the iFrame, you just need to have this JavaScript:
window.parent.document.body.addEventListener('keypress', function(e) {
console.log(e.keyCode);
});
I'm backend developer, new to javascript. Can anyone provide a few lines of script that will allow the page to auto-scroll to the "target" element after the page loads
<html>
<bod>
<p id="target">...</p> // auto-scroll here
</bod>
</html>
Thanks
You can use scrollIntoView on the element in window.onload event..
In your case you would be doing:
window.onload = function() {
var el = document.getElementById('target');
el.scrollIntoView(true);
}
Good docs can be found here:
MDN scrollIntoView
Also change your body tag to something like
<body onload="ScrollToTarget">
Then your function can be defined in the header as
function ScrollToTarget()
{
document.getElementById("target").scrollIntoView(true);
}
First, the background:
I'm working in Tapestry 4, so the HTML for any given page is stitched together from various bits and pieces of HTML scattered throughout the application. For the component I'm working on I don't have the <body> tag so I can't give it an onload attribute.
The component has an input element that needs focus when the page loads. Does anyone know a way to set the focus to a file input (or any other text-type input) on page load without access to the body tag?
I've tried inserting script into the body like
document.body.setAttribute('onload', 'setFocus()')
(where setFocus is a function setting the focus to the file input element), but that didn't work. I can't say I was surprised by that though.
EDIT:
As has been stated, I do indeed need to do this with a page component. I ended up adding file-type inputs to the script we use for giving focus to the first editable and visible input on a page. In researching this problem I haven't found any security issues with doing this.
<script>
window.onload = function() {
document.getElementById('search_query').select();
//document.getElementById('search_query').value = '';
// where 'search_query' will be the id of the input element
};
</script>
must be useful i think !!!
This has worked well for me:
<script>
function getLastFormElem(){
var fID = document.forms.length -1;
var f = document.forms[fID];
var eID = f.elements.length -1;
return f.elements[eID];
}
</script>
<input name="whatever" id="maybesetmaybenot" type="text"/>
<!-- any other code except more form tags -->
<script>getLastFormElem().focus();</script>
you can give the window an onload handler
window.onload = setFocus;
I think you have a fundamental problem with your encapsulation. Although in most cases you could attach an event handler to the onload event - see http://ejohn.org/projects/flexible-javascript-events/ by John Resig for how to do this, setFocus needs to be managed by a page component since you can't have two components on your page requiring that they get the focus when the page loads.
Try play with tabstop attribute
First of all, the input file is no the same as the other inputs, you need to keep this in mind.... thats for security reasons. When the input file get focus it should be read only or the browser should popup a dialog to choose some file.
Now, for the other inputs you could try some onload event on some of your elements...(not only the body have the onload event) or you could use inline javascript in the middle of the html. If you put javascript code without telling that is a function it gets executes while the browser reads it. Something like:
<script type="text/javascript">
function yourFunction()
{
...;
};
alert('hello world!");
yourFunction();
</script>
The function will be executed after the alert just when the browser reads it.
If you can, you should use jQuery to do your javascript. It will make your live soooo much easy.... :)
With jQuery could be done like this:
$(function() {
$("input:file").eq(0).focus()
})
With plain javascript could be done like this:
var oldWindowOnload = window.onload; // be nice with other uses of onload
window.onload = function() {
var form = document.forms[0];
for(i=0; i < form.length; i++) {
if (form[i].type == "file") {
form[i].focus();
}
}
oldWindowOnload();
}
For more elaborate solution with plain javascript see Set Focus to First Input on Web Page on CodeProject.
Scunliffe's solution has a usability advantage.
When page scripts are loading slowly, calling focus() from "onLoad" event makes a very nasty page "jump" if user scrolls away the page. So this is a more user friendly approach:
<input id="..."></input>
... really small piece of HTML ...
<script>getTheDesiredInput().focus();</script>