Hej sry when I ask but is there a way to use the webview tag in an nw.js application without that everything under the webview is covered in an shadow-root?
<webview id="foo" src="file:///C:/Users/midjo/Desktop/TEST.html" style="display:flex; height:100%; width:100%;" partition="trusted" tabindex="-1">
shadow-root(open)
No, but shadow-root is Ok, it's easy to do whatever you want with DOM inside.
For example:
<webview id="foo" src="test.html" partition="trusted" style="display: flex;"></webview>
<script>
foo.addEventListener('loadstop', e => {
foo.executeScript({
code: `document.querySelector('body').innerText;`
}, result => {
console.log(result);
});
});
</script>
You can get any content, click things and even inject any js-file.
Related
I have a really weird behaviour right now in production which is that, on a Single Sign-On login page (we are the SSO provider), some JS selectors instructions are not working when the page is loaded through an iFrame on another website.
The selectors are executed on the login page template, on my side (the SSO side), they are not executed on the page hosting the iFrame. Still, they return null.
HTML code:
<document>
<body>
<script>
if (window.parent != window) {
window.document.getElementById('content').style.padding = '0';
}
</script>
<div class="container">
<main id="content" class="flex-column">
<div class="sib-login-title">
You need to login to access this page
</div>
</main>
</div>
</body>
</document>
The code here is really basic because I extracted the base elements, what's weird is that, when accessing my login page in the browser and executing the getElementById in the console, it works:
window.document.getElementById("content");
<main id="content" class="flex-column">
Same code from the script tag when the page is loaded through an iframe returns:
?next=/authorize/%3Fclient_id%xxxxxxxxxxxxxxxx%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520email%2520preferred_username%2520roles%26redirect_uri%3Dhttps%3A//xxxxxxxx/auth:42 Uncaught TypeError: Cannot read properties of null (reading 'style')
I want to emphasize that this script tag is really on the document loaded through the iframe, not on the parent document loading the iframe, so I really do not get why.
I checked a lot of questions on SO but they are all asking how to access elements inside the iframe from the parent document, that's not my scenario here.
Any ideas ? Something I forgot about ?
Thanks in advance.
The JavaScript is trying to reference the element before it exists (it exists a couple of lines later, so you're just a bit keen).
You just need to put things in the correct order, like this:
#content {
padding: 100px;
}
<div class="container">
<main id="content" class="flex-column">
<div class="sib-login-title">
You need to login to access this page
</div>
</main>
</div>
<script>
if (window.parent != window) {
document.getElementById('content').style.padding = '0';
}
</script>
I am really not great at web stuff, so I am apologizing in advance for a potentially poor explanation of my problem.
Basically, I have a webpage which utilizes the handlebars js templating. Unfortunately, this means that many of my div elements are contained within javascript tags like the following:
<script type="text/x-handlebars" data-template-name="index">
<div class="row intro">
......
</div>
<div class="descript">
.....
</div>
</script>
My intent is to grab one of these div elements using jquery.find(), but from what I understand, the html within the script tags is not treated as part of the dom...so jquery does not see it as a dom element. I was wondering if there is any other way I could go about this. Some more code is included.
Here is another more explicit explanation in case the one I gave above was a little muddled: I am working on a personal website and would like to embed a project I have been working on in unity3d, but I need to add/remove elements based on whether or not the client has the unity3d web player installed. Normally I would get a particular element with
var $missingScreen = jQuery("#unityPlayer").find(".missing");
where 'missing' is simply an element inside unityPlayer which displays a link if the client does not have unity3d. I am also using some javascript templating to make my site look pretty and as a result, I have this problem:
<script type="text/x-handlebars" data-template-name="index">
<div class="row intro">
<div class="intro-text">Hi, I'm *****</div>
</div>
<div class="descript">
<p>
Here's a Project I have been working on in case I am of interest to you:
</p>
</div>
<div class="content">
<div id="unityPlayer">
<div class="missing">
<a href="http://unity3d.com/webplayer/" title="Unity Web Player. Install now!">
<img alt="Unity Web Player. Install now!" src="http://webplayer.unity3d.com/installation/getunity.png" width="193" height="63" />
</a>
</div>
</div>
</div>
<p class="footer">« created with Unity »</p>
</script>
Jquery cannot access the missing element. Is there any way to do this? Thanks for any help you can give me and sorry again for my inexperience.
EDIT* some people might want to know: here is how I determine whether or not to show the missing div. Another note; everything works fine if I remove the script tags...it is only when I put html within the script tags that it becomes inaccessible to jquery.
jQuery(function() {
var $missingScreen = jQuery("#unityPlayer").find(".missing");
$missingScreen.hide();
u.observeProgress(function (progress) {
switch(progress.pluginStatus) {
case "missing":
$missingScreen.find("a").click(function (e) {
e.stopPropagation();
e.preventDefault();
u.installPlugin();
return false;
});
$missingScreen.show();
break;
case "installed":
$missingScreen.remove();
break;
case "first":
break;
}
});
u.initPlugin(jQuery("#unityPlayer")[0], "temmp.unity3d");
});
Instead of
var $missingScreen = jQuery("#unityPlayer").find(".missing");
I would try out
var $missingScreen = jQuery("#unityPlayer").children(".missing");
or
var $missingScreen = jQuery("#unityPlayer .missing");
Don't forget the space between Player and .missing!
I hope it works.
I've been trying to figure out how to toggle a Div in Android Webview, like this http://jsfiddle.net/Z9f2b/
this is my Android code but doesn't toggle at all, can someone explain what I'm doing wrong? thanks:
wv = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = wv.getSettings();
wv.setWebViewClient(new WebViewClient());
wv.getSettings().setLoadWithOverviewMode(true);
wv.getSettings().setUseWideViewPort(true);
wv.getSettings().setDisplayZoomControls(false);
wv.getSettings().setBuiltInZoomControls(false);
wv.getSettings().setSupportZoom (false);
wv.getSettings().setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
String script = "$('#liked').on('click', function() {$('#liked').hide();$('#notliked').show();});$('#notliked').on('click', function() {$('#liked').show();$('#notliked').hide();});";
html = "<div id='liked' style='float:left;display:none; height:100px; width:100px; background-color:blue'>1</div><div id='notliked' style="float:left;height:100px; width:100px; background-color:red">2</div>";
String summary = "<html>"+script+"<body>"+html+"</body></html>";
wv.loadUrl("about:blank");
wv.loadData(summary, "text/html", null);
Try wrapping your javascript in <script> tags.
Also, you need to wrap the javascript that you have in a call to $(window).load so the handlers get registered when the DOM is ready.
Additionally, you need to link to a version of the JQuery library.
Are you sure you need JQuery for this? You could write it in standard javascript very simply with an onclick handler on the div... something like:
<div id='liked' style='float:left;display:none; height:100px; width:100px; background-color:blue' onclick="document.getElementById('notliked').style.display='block'; document.getElementById('liked').style.display='none';">1</div>
<div id='notliked' style="float:left;height:100px; width:100px; background-color:red; disply:block" onclick=" document.getElementById('liked').style.display='block'; document.getElementById('notliked').style.display='none';">2</div>
Try loading HTML data before insertion of script. Javascript can be inserted after HTML is loaded into web view. This is the better idea. So your code should probably go like this:
String summary = "<html><body>"+html+"</body></html>";
wv.loadUrl("about:blank");
wv.loadData(summary, "text/html", null);
and followed by:
wv.loadUrl("javascript:"+script);
This will insert javascript onto current web page and you dont even need to take care that where it has to be inserted and how. Webview will take care of it.
I have a home page with multiple <div> tags. One of the <div id="top_bar"> contains a link. If I click on the link, a new web page should load on one of the other <div id="content"> in home page. How do I do that?
More over, if the newly loaded page on one of the other <div id="content"> contains a link, and clicking on the link helps the 2nd new web page load in the <div id ="content"> tag replacing the first content of the div , the question is how do I do that?
This is an assignment given to me and the rules are:
I have to use Javascript, CSS and HTML only.
I can't use <iframe> tag.
I can't use <table> tag either to load page in a row/column.
I need help and advice about how to do it.
home.html
<body>
<div id="topBar">
HOME
<a href="#" onclick="load_about()" > ABOUT </a>
SONG LIST
</div>
<div id ="content"> </div>
</body>
I want the music.html to open in side the < div id="content" > which all ready does. but in music.html there is a button. I want to open Songlist.html in < div id="content" > by clicking on that button. code for
music.html :
<body >
<form name="flyrics" method="get" >
Lyrics: <input type ="text" name ="lyrics"/>
Artist Name:<input type ="text" name ="artist" />
<input type="submit" id="x" value="Search" />
</form>
</body>
javascript:
function load_home(){ document.getElementById("content").innerHTML='<object type="type/html" data="home.html" id="link_pages" ></object>'; }
function load_about(){ document.getElementById("content").innerHTML='<object type="type/html" data="about.html" id="link_pages" ></object>'; }
function load_search(){ document.getElementById("content").innerHTML='<object type="type/html" data="music.html" id="link_pages" ></object>'; }
function validation(){
var x=document.forms["flyrics"]["lyrics"].value;
if (x==null || x=="")
{
alert("Search without Lyrics?");
return false;
}
var y=document.forms["flyrics"]["artist"] value;
if (y==null || y=="")
{
alert("Search without Artist Name?");
return false;
}
window.open("songList.html", "currentWindow");
}
AJAX is what your assignment is looking for.
Simple Example
HTML:
<button id="nav">load</button>
<div id="page"></div>
JS:
document.getElementById('nav').onclick = function(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function()
{
if (xhr.readyState==4)
{
document.getElementById("page").innerHTML = xhr.response;
}
}
xhr.open("GET", "http://www.codecademy.com/", false);
xhr.send();
}
fiddle: http://jsfiddle.net/DZmBG/3/
In one of your comments, you mentioned using <object> tags to embed external HTML files.
Here is an example using that method:
HTML:
<div id="links">
stuff
fun
bing
</div>
<div id="container"></div>
CSS:
div#container {
width:500px;
height:500px;
overflow:hidden;
}
JS:
function go(obj) {
var page=obj.href;
document.getElementById('container').innerHTML='<object data="'+page+
'" type="text/html"><embed src="'+page+'" type="text/html" /></object>';
return false;
}
http://jsfiddle.net/sAcCV/
EDIT:
This being said, I recommend using AJAX to load external content, instead:
http://www.javascriptkit.com/dhtmltutors/ajaxincludes.shtml
See Relfor's answer.
Iframe is the obvious answer. That's what it was made for. But since your requirements state you can't use it....
Any site that's not within your domain is going to violate the same origin policy, and Javascript in the remote page is not going to run as you probably would think it would inside a div on your site. You'd probably have to examine a CURL get approach or something similar to do it with a straight div and javascript.
AJAX is definitely the way to go if you are not able to use iframes. I would suggest using jQuery for this example to save some time. Their AJAX handling is pretty straightforward and you are gonna want to use their .live() or .on() event handlers to track the click events inside the containers.
Additionally, you may run into issues if you are loading sites on different domains. AJAX calls are typically meant for same-domain responses. You can get around this using JSONP. However, your web service must support method injection for this to work. In not, you may want to see if you can work around the iframe barrier with your host/webmaster.
You can not. You are asking for something that can not be done. For such situation you must use iframe.
First just let me say I'm open to ideas on a different approach altogether.
I have and iframe as such:
<div id="testloadlogin">
<iframe src="../security/login.aspx" width="400" height="500"
scrolling="auto" frameborder="1">
[Your user agent does not support frames or is currently configured
not to display frames. However, you may visit
the related document.]
</iframe>
</div>
The page being loaded with the iframe has a div called loginInnerBox. I only want to display the loginInnerBox and everything inside of it.
Any ideas on how to do this? I was thinking of using Jquery or javascript of some kind to remove everything else on the page loaded by the iframe, not sure how to access that though...
Just to be clear I want everything on my page outside of the iframe to remain intact. I want the equivalent of saying $.('testloadlogin').load('../security/login.aspx' #loginInnerBox) which would just get loginInnerBox's html and place it in the testloadlogin div. However I need the back-end processing from the other page which is supported by iframe, but not by the Jquery load.
The markup of the page loaded by the iframe is
<body>
<div>
</div>.......
<div class="AspNet-Login" id="ctl00_CLPMainContent_Login1">
<div id="loginInnerBox">
<div id="loginCreds">
<table>
</table>
</div>
</div>
</div>
<div>
</div>....
</body>
Do you need more information than that?
I tried this, it had no effect:
<div class="ui-corner-all" id="RefRes">
<div id="testloadlogin">
<iframe onload="javascript:loadlogin()" id="loginiframe" src="../security/login.aspx"
scrolling="auto" frameborder="1">
[Your user agent does not support frames or is currently configured
not to display frames. However, you may visit
the related document.]
</iframe>
</div>
</div>
<script type="text/javascript">
function loadlogin() {
$('<body>*', this.contentWindow.document).not('#ctl00_CLPMainContent_Login1').hide();
}
</script>
With jQuery, you can load not just the contents of a URL, but a specific CSS selector from within that URL. This would be a much cleaner approach. It's like this.
$("#area").load("something.html #content");
Via CSS Tricks
$("iframe").contents().find("*:not(#loginInnerBox)").remove();
Be aware this would only work on iframes loaded from the same domain (same origin policy)
EDIT: Probably this removes children of loginInnerBox as well. In that case you could try to clone it before:
var iframe = $("iframe").contents(),
loginBox = iframe.find("#loginInnerBox").clone();
iframe.find("*").remove();
iframe.append(loginBox);
Something like that..
Add this to the <iframe>-elememt:
onload="$('body>*',this.contentWindow.document).not('#ctl00_CLPMainContent_Login1').hide();"
it will hide every child of the body except #ctl00_CLPMainContent_Login1
If #ctl00_CLPMainContent_Login1 contains more than the loginbox, you have to use the suggestion using clone() posted by pex.