Automatically jump to a certain part of a WebView - javascript

I'm making a Chrome App, and i'm using the web view tag, which is similar to an iframe.
Is there a way to load halfway down the webpage that's inside the web view?
I have tried:
<webview onLoad="window.scroll(0, 150)" class="test" src="http://example.co.uk/test.aspx"></webview>
But it seems that would be far to easy. I'm not convinced its even possible.
Thanks

Assuming for a moment that code would execute (it won't because of the CSP), window would refer to the app's page, not the embedded page.
You need to execute the code in the context of the embedded page.
If you worked with Chrome extensions before, you would know that the part interacting with web content is called a Content Script.
Apps have a similar concept for <webview> elements. You can either declare in advance which pages should get which content script while they load, or you can explicitly load a content script.
So, suppose you have a file content.js with the following contents (excuse the pun):
window.scroll(0, 150);
Also, assume you have a script app.js running inside your app page, and a variable webview is a reference to the <webview> in there.
Then, you can make the webview execute it:
Declaratively, by calling webview.addContentScripts before loading the page (e.g. before setting src from app.js code):
// Assuming <webview id="wv"></webview>
var webview = document.getElementById("wv");
webview.addContentScripts([{
name: "ExampleRule",
matches: ["http://example.co.uk/*"], // can be as narrow as you wish
js: ["content.js"]
}]);
webview.src = "http://example.co.uk/test.aspx";
Explicitly, when the page is already loaded:
// Assuming <webview id="wv" src="http://example.co.uk/test.aspx"></webview>
var webview = document.getElementById("wv");
webview.executeScript({file: "content.js"});
It is, of course, possible to make content.js much more sophisticated (for example, receive commands from the app) and/or more precisely control the timing of your operation - but those are at this point generic content script questions for which you can find solutions elsewhere or ask a new question.

Related

basic javascript alert not working in Intel XDK code editor

I'm starting fresh with a new blank Intel project and I haven't even started coding yet. I'm just setting up my file tree and making sure the html and javascript pages are connected via the right anchors and script paths. My first .js file won't work though.
I've included a screen shot of test code and the errors. I know the syntax is correct because it works when I put it in <script> tags in the index.html file.
I'm getting "document not defined" and "alert not defined" errors or the js page though. I don't know what that means.
I've considered that my script tag src path in the index file is incorrect, but all the paths are relative in the commented out template script tags intel provides on the index page right out of the box, so why would I have to use an absolute path?
My path is: js/Test.js and it's the last script tag before the body.
Index.html file
*****UPDATE****
So I've tried a few things and it's still not working but I HAVE managed to get my errors down to just one inexplicable "missing semicolon", which will turn into an "unnecessary semicolon" error if I place it.
Any way as per the first screen shot you'll see that I wasn't placing the document object inside of an explicitly declared variable. Once I did that and accessed it through dot syntax instead of an equal sign then I stopped getting the error. I included this screenshot to show my work before I made the changes.
so the problem I went on to have is that unless every function or dom object was declared with "Var", I'd get an error. This includes the alert() function which I don't think I've ever seen needing to be declared that way, but I gave the code editor what it wanted and this last screenshot is the results. It's not working, BUT I'm not getting the errors I was before, except for the missing/unnecessary semicolon paradox. Removing it or including it throws an error.
JavaScript can be loaded before or after the HTML, however the way it is done is slightly different depending on how you do it.
For example if you wish to include your JavaScript files within the head of the HTML file then you must wrap your JavaScript code with either DOMContentLoaded or jQuery's $(document).ready().
The common misconception of using window.onload will not fix the issue where the elements have not loaded in correctly.
The Mozilla Developer Network states on this page:
The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. A very different event - load - should be used only to detect a fully-loaded page. It is an incredibly popular mistake to use load where DOMContentLoaded would be much more appropriate, so be cautious.
That quote in itself should prove that onload should not be relied on if you want the full DOM to be loaded properly before you start manipulating it. Instead you should do the following:
Vanilla
document.addEventListener("DOMContentLoaded", function (e) {
/** DOM has been fully loaded here, so manipulation can begin. **/
/** Your code here. **/
});
jQuery
$(document).ready(function () {
/** DOM has been fully loaded here, so manipulation can begin. **/
/** Your code here. **/
});
Click this link to see the difference between vanilla and jQuery.
The second way you can load JavaScript is by having all the script tags within the body but after all the HTML, that way it is guaranteed to load after the HTML.
Example
Try this working example I quickly coded up.
HTML
Replace the content within the body tag of your HTML to the following:
<button id="myJsTest">Click Me!</button>
<div id="clickCounter">Click Count: 0</div>
Replace the contents of your JavaScript with the following:
JavaScript
document.addEventListener("DOMContentLoaded", function() {
var clickCount = 0;
document.getElementById("myJsTest").addEventListener("click", function() {
clickCount++;
document.getElementById("clickCounter").innerText = "Click Count: " + clickCount;
});
});
Then use the Emulate tab in Intel XDK to test it.
Additional Information
When I use Intel XDK and I have an error, I quickly load the file in to the browser and check the console. It can be a really helpful and effective way of squashing those pesky little bugs.
Try using window.alert as alert is defined in the window object.
The reason you're seeing all those "error" messages in the editor window is because you've got the various JSLint/Hint tools loaded in the editor. They're trying to keep you honest and save you lots of time in the debugger chasing potential syntax errors.
The editor inside the XDK is Brackets, it is using standard Brackets extensions to provide those JSLint/Hint tools. You can download it and run it standalone on your system and edit directly within it, you don't have to use the editor inside the XDK (or you can use any other editor you like).
Because the Lint/Hint tools only look at one file at a time, and because your app is normally spread over multiple files, they don't know much about about what's defined in your other files. Likewise, those hint/lint tools need to be told that you're using some of the standard global methods and properties that are expected to be found in a browser (but which may not be found in other JavaScript environments, because JavaScript is no longer limited to just a browser environment -- in fact, your XDK app, aka Cordova app, runs inside a "webview" not in a browser, but that's another story...)
So, you should follow some standard practice of setting up your JSHint/Lint directives at the top of your JS files. For example, this is a good starting point:
/*jslint browser:true, devel:true, white:true, vars:true */
/*global $:false, intel:false */
See the JSHint documentation for details... and see the "Blank Cordova Starter App" in the "Start a New Project" section of the Projects tab for a better blank template to start (there is no real difference between a blank template and a demo app, they are structured identically).
For a more complete and even more instructive app, see the "Hello, Cordova" sample app. Both of those apps can also be found on the Intel XDK GitHub repo.
You are adding the js file that is <script src="js/Test.js"></script> inside header tag.
So js will be first loaded and and it will attach all events to it. But when js is loaded button id="jsTest" is not present because DOM is not loaded.
Solutions :-You can follow either of the approach
Add your js files after DOM is ready
<body>
<button id ="js/Test.js">Test JS</button>
// other HTML tags
<script src = "js/Test.js></script>
</body>
Use window.onload
The load event fires at the end of the document loading process.
window.onload = testJsFile(){
//Your code goes here
}
I will prefer to use the first approach since that also address other issues like page loading time
Try to put the line outside your JS function
document.getElementById(......
inside your html page between
<script>HERE</script>
If this is still no working. Try to add onClick attribute to the button like this:
<button id="" onClick="testJsFile()">
Its also good to use google chrome element inspection while devlopping cuse it will give you error msg for all these things.

'document.getElementById' only works on index.html

Ultimate goal is to cycle through photos on a blog page. Seems like 'document.getElementById().src' would be a good approach.
Problem: To make sure the javascript code is successfully linking to the blog page, I tried testing with this in my script.js file:
document.getElementById('testID').innerHTML = "Running test";
and this in my .html file:
<div id="testID"></div>
But, the text "Running Test" does not show up on the blog page. However, when running this same exact test in my index.html page, it does work. Both .html files load the same script file along with jQuery. I don't understand why it works in one html file and not the other.
NEW FINDING:
This line of code now works on the blog page when I remove it from inside
$(document).ready(function(){ ... });
Why would that be?
The Javascript in the current page can only access HTML elements that are in pages that are currently loaded into the browser.
More specifically, document.getElementById() ONLY searches the current web page's document for matching elements. It does not search any other pages and certainly does not search other files on your server that are not loaded into the browser. "current web page" means the HTML loaded from the current URL in the browser bar.
When a web page is no longer visible in the browser window (e.g it's been replaced by some other page), it is gone and no longer reachable by any Javascript. In some specific cases, you can access document loaded into other tabs or other frames (subject to same-origin security rules and requires a different method of access).
In addition, no changes to a web page are persistent in the browser. As soon as a web page is no longer loaded into an active browser window, it is gone and reloading it again will load the original, unmodified version of that document.
If you want the same code from one page to run in another page, then you must include that same code in the other page. You can want, you can share a reference to the code by putting the code into its own page and then using a <script src="xxx.js"> tag in each page to cause the same code to get loaded into each page.
If interpret Question correctly, try using .load()
$("#container").load("/blog/blog_1.html #testID")

jQuery selector not working on iframe contents

This part of a script works fine on a normal page:
<script>
$(function() {
$(".counter").countimator();
});
</script>
But when that same page is loaded in an iframe on a page on another domain, it doesn't work.
Is there a way to get this selector/code work when the page is loaded within an iframe? I want to give people a iframe code that they can use on their personal websites to get the content of my page on their website.
Edit
I published the basic code on http://joomlaground.com/iframe_test/
The http://joomlaground.com/iframe_test/clock.php runs standalone like it should.
Then I created a very basic iframe page iframe.php which iframe the clock.php. However then the clock.php is not counting any more.
How can I fix this?
If '.counter' element is outside of the iframe you're running the internal iframe script has no access to this element as the current document and iframe are separate documents. If you'll have any questions don't hesitate to ask below.
When you move this script in an iframe then it means you are running your script in a new window.
Now in new window you are trying to access some library function:
$(".counter").countimator();
That can only be done if you have that library included in the source of that iframe.

Injecting chrome extension UI using shadow DOM

I am very new to HTML and the complete web world wrt development. I am trying to create a chrome extension and have decided upon showing the extension UI to the user by injecting a content script when the browser action is clicked. I have created an HTML page for the UI to be shown and now I need to load this HTML page as a small widget somewhere on the right top of the current page (to appear like a popup). From the different things looked up on the internet, I have decided to use shadow DOM but have no clue how to do all this. Can someone help me with a sample code to help me go ahead with this? I am not able to write a javascript that would be used as the content script to do the above mentioned job.
Edit 1: After some more reading, I found out out that we need to create the element hierarchy using javascript and cannot directly make use of any created HTML page. Is that correct? And if we have to make use of javascript, should make use of calls to document.createElement and add element? or document.write?
Just compiling reference from the responses I've got in this thread:
My Background.js:
function hello() {
chrome.tabs.executeScript(null, { file: "injectedScripts/jquery-2.1.3.min.js" }, function () {
chrome.tabs.executeScript(null, { file: "injectedScripts/a.js" });
});
}
// Supposed to Called when the user clicks on the browser action icon.
chrome.browserAction.onClicked.addListener(hello);
Injected Script a.js:
$.get(chrome.extension.getURL("popup.html"), function (data) {
//$(data).appendTo('body');
// Or if you're using jQuery 1.8+:
$($.parseHTML(data)).appendTo('body');
});
Also added popup.html and a.js paths to web_accessible_resources in manifest.json
For Chrome extension content scripts you'll only be able to inject JavaScript/CSS. You won't be able to have you're own HTML popup page like when using browserAction.
With JavaScript you'll need to dynamically create elements and insert them into the DOM. You're on the right track. You can use document.createElement or a library like jQuery to help with DOM manipulation as you get more familiar with web dev.

Gmail Chrome Extension "chrome.extension" undefined

I have a content script running inside the Gmail UI and I am injecting some new HTML at different points. This is all working, but to keep the code clean I wanted to insert pre-defined HTML markup into certain parts of the page in a single function call.
This all seems feasible using chrome.extension.getURL(), but when I was testing this, it looks like chrome.extension is undefined! I was unable to find anywhere in the documentation that says this shouldn't be defined and several places where it says it should.
I am using chrome Version 39.0.2171.95 (64-bit)
Here is what the chrome object looks like in the javascript console:
First off, anyone know why chrome.extension might be undefined? Secondly, is there another (perhaps better) way to do this? I'd rather not just programmatically inject a large amount HTML into the page in code using jQuery, etc. in the content script, but can resort to this if there is no other way.
If you're testing this in the console, you must be aware of the concept of the Isolated World. When you add a content script, it has a separate JavaScript context for itself that is isolated from the page.
At the top of the Console tab of Dev Tools, you'll see <top frame> in a dropdown. This is a dropdown that selects JS context it is executing in. It will list frames inside the document and all extensions that have content scripts injected.
The chrome object you show in the screenshot corresponds to what the webpage normally sees. If you switch context, you'll see a different picture:
In any case, if you are really executing chrome.extension.getURL() in the content script - it will be well defined.
Now, if you injected a <script> tag in the page and tried it in that code - it would fail again, since the code will be in the page context. See this question for this situation.
Finally, most of the Chrome API will not be exposed to content scripts for security reasons. If an API is undefined when it shouldn't be, you may need a background page to do the job for you.

Categories

Resources