I'm making a javascript metro app and have some code like this:
<script>
document.writeln(foo());//this line is trouble
</script>
and when I tried to run, it gave me a rather long error:
Unhandled exception at line 20, column 9 in ms-appx://a375ffac-3b69-475a-bd53-ee3c1ccf4c4e/default.html
0x800c001c - JavaScript runtime error: Unable to add dynamic content.
A script attempted to inject dynamic content, or elements previously
modified dynamically, that might be unsafe. For example, using the
innerHTML property to add script or malformed HTML will generate this
exception. Use the toStaticHTML method to filter dynamic content, or
explicitly create elements and attributes with a method such as
createElement. For more information, see
http://go.microsoft.com/fwlink/?LinkID=247104.
How can I get around this?
Windows 8 restricts the content you can set through innerHTML and Writeln, because it's considered unsafe...
The correct way to add content is:
// The untrusted data contains unsafe dynamic content
var unTrustedData = "<img src='http://www.contoso.com/logo.jpg' on-click='calltoUnsafeCode();'/>";
// Safe dynamic content can be added to the DOM without introducing errors
var safeData = window.toStaticHTML(unTrustedData);
// The content of the data is now
// "<img src='http://www.contoso.com/logo.jpg'/>"
// and is safe to add because it was filtered
document.write(safeData);
If your code has some javascript, you can use this function (But microsoft dont recomend it):
MSApp.execUnsafeLocalFunction(function() {
var body = document.getElementsByTagName('body')[0];
body.innerHTML = '<div style="color:' + textColor + '">example</div>';
});
See at:
http://msdn.microsoft.com/en-us/library/windows/apps/Hh767331.aspx
For your case:
MSApp.execUnsafeLocalFunction(function() {
document.writeln(foo());
});
Note that you should only do this if you understand your content is safe; if you don't, I would recommend using the toStaticHTML method.
regarding to the docs I would try :
document.writeln(window.toStaticHTML(foo()));
Windows 8 store apps have a restriction on placing dynamic content inside innerHTML attribute. To fix this you need to include winstore-jscompat.js file from following location in your page as first reference. Please see this link to know more about winstore-jscompat.
This file is not required on Windows 10.
Related
I want to insert a script in Firefox Add-on SDK content script added via page-mod. So, when user goes to page XXX, he gets a page with the inserted script. But, when trying to insert this at the top of HEAD, I got an error that the 1st Node child is not an object.
My content script code with which I insert the <script> is:
script='<script>var d=new Date(2012,2,24); window.Date=function () {return d;}</script>';
var head = document.getElementsByTagName("head")[0];
head.insertBefore(script, head.firstChild);
What's with it?
You have not provided a Minimal, Complete, and Verifiable Example. Thus, this answer is based just on the code you have provided.
Issue with how you are using insertBefore():
The first issue I noticed is that you are providing a string as the first argument to insertBefore() when that argument needs to be a node object.
However, you state the error you are getting is "1st Node child is not an object". This does not match what I would expect from an error based on the code provided. When I put your code in a page-mod content script, the error I got was:
console.error: testpagemodinsertBefore:
Object
- _errorType = TypeError
- message = Argument 1 of Node.insertBefore is not an object.
- fileName = resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://testpagemodinsertbefore/data/contentScript.js
- lineNumber = 26
- stack = #resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://testpagemodinsertbefore/data/contentScript.js:26:1|
- name = TypeError
This is the error which I would expect from the code in the question. Thus, you have either not posted the code which is producing the error you have stated, or you have inaccurately reported the error which you saw in the console. In the future, please be exact in what you are reporting. Being more verbose is better than leaving things out.
Inserting HTML text:
Your code:
script='<script>var d=new Date(2012,2,24); window.Date=function () {return d;}</script>';
defines some HTML text which you are trying to insert into the DOM.
If you want to insert HTML text instead of inserting nodes, one way for you to do so is to use insertAdjacentHTML(). One way you could do this in your code is:
head.insertAdjacentHTML('afterbegin',script);
This works well for most HTML. But, does not result in the contents of the <script> tag being executed/evaluated. This is for security reasons. It is much easier for an attacker to get arbitrary text inserted into the DOM than it is for them to insert actual nodes/elements. The HTML specification specifies that a tag inserted inserted as text will not be executed.
Inserting a <script> tag that is evaluated and executed:
We can do this by creating a <script> element containing the script text desired, then inserting that element into the DOM.
For your code that would look something like:
//Get the first <head> element
let head = document.getElementsByTagName("head")[0];
//The script text desired
let scriptText='var d=new Date(2012,2,24); window.Date=function () {return d;};';
//Add an alert for testing (\n is not needed. But, is more readable when inspecting DOM.)
scriptText = 'window.alert("In inserted script");\n' + scriptText;
//Create a <script> element
let scriptEl = document.createElement( 'script' );
//That is JavaScript
scriptEl.type = 'text/javascript';
//Add the script text
scriptEl.textContent = scriptText;
//Insert it as the firstChild of <head>
head.insertBefore( scriptEl, head.firstChild );
Further reading:
You appear to be desire to interact with page scripts using your content script. I suggest that you read the MDN page "Interacting with page scripts".
I want to read a webpage programmatically (with javascript-angular) and search some elements inside. What i have until now is:
$http.get('http://.....').success(function(data) {
var doc = new DOMParser().parseFromString(data, 'text/html');
var result = doc.evaluate('//div[#class = \'xx\']/a', doc, null, XPathResult.STRING_TYPE, null);
$scope.all = result.stringValue;
});
so in the example i can read the value of any html element.
Very unluckily, the page i want to read uses some Javascript and the source code (html) is just a part of its entire html source (including DOM changes), which the browser at the end shows. So the html which is returned from the http get, does not necessarily contain the elements i need.
Is there a way of getting the entire html after the javascript run?
Edit: Yes the page is from another domain + The provided API does not give me the info i need.
I´m trying to get the elements from a web page in Google spreadsheet using:
function pegarAsCoisas() {
var html = UrlFetchApp.fetch("http://www.saosilvestre.com.br").getContentText();
var elements = XmlService.parse(html);
}
However I keep geting the error:
Error on line 2: Attribute name "itemscope" associated with an element type "html" must be followed by the ' = ' character. (line 4, file "")
How do I solve this? I want to get the H1 text from this site, but for other sites I´ll have to select other elements.
I know the method XmlService.parse(html) works for other sites, like Wikipedia. As you can see here.
The html isn't xml. And you don't need to try to parse it. You need to use string methods:
function pegarAsCoisas() {
var urlFetchReturn = UrlFetchApp.fetch("http://www.saosilvestre.com.br");
var html = urlFetchReturn.getContentText();
Logger.log('html.length: ' + html.length);
var index_OfH1 = html.indexOf('<h1');
var endingH1 = html.indexOf('</h1>');
Logger.log('index_OfH1: ' + index_OfH1);
Logger.log('endingH1: ' + endingH1);
var h1Content = html.slice(index_OfH1, endingH1);
var h1Content = h1Content.slice(h1Content.indexOf(">")+1);
Logger.log('h1Content: ' + h1Content);
};
The XMLService service works only with 100% correct XML content. It's not error tolerant. Google apps script used to have a tolerant service called XML service but it was deprecated. However, it still works and you can use that instead as explained here: GAS-XML
Technically HTML and XHTML are not the same. See What are the main differences between XHTML and HTML?
Regarding the OP code, the following works just fine
function pegarAsCoisas() {
var html = UrlFetchApp
.fetch('http://www.saosilvestre.com.br')
.getContentText();
Logger.log(html);
}
As was said on previous answers, other methods should be used instead of using the XmlService directly on the object returned by UrlFetchApp. You could try first to convert the web page source code from HTML to XHTML in order to be able to use the Xml Service Service (XmlService), use the Xml Service as it could work directly with HTML pages, or to handle the web page source code directly as a text file.
Related questions:
How to parse an HTML string in Google Apps Script without using XmlService?
What is the best way to parse html in google apps script
Try replace itemscope by itemscope = '':
function pegarAsCoisas() {
var html = UrlFetchApp.fetch("http://www.saosilvestre.com.br").getContentText();
html = replace("itemscope", "itemscope = ''");
var elements = XmlService.parse(html);
}
For more information, look here.
I'm working on Chrome extension and I have following problem:
var myDiv = document.createElement('div');
myDiv.innerHTML = '<img src="a.png">';
What happens now is that Chrome tries to load the "a.png" resource, even If I don't attach the "div" element to document. Is there a way to prevent it?
_In the extension I need to get data from a site that doesn't provide any API, so I have to parse the whole HTML to get the necessary data. Writing my own simple HTML parser could be tricky so I would rather use the native HTML parser. However, in Chrome when I put the whole source code to some temporary non-attached element (so it would get parsed and I could filter the necessary data), ale the images (and possibly other resources) start to load as well, causing higher traffic or (in case of relative paths) lots of errors in console. _
To prevent the resources from being loaded, you'll need to create your Node in an entirely new #document. You can use document.implementation.createHTMLDocument for this.
var dom = document.implementation.createHTMLDocument(); // make new #document
// now use this to..
var myDiv = dom.createElement('div'); // ..create a <div>
myDiv.innerHTML = '<img src="a.png">'; // ..parse HTML
You can delay parsing/loading html by storing it in non-standard attribute, then assigning it to innerHtml, "when the time comes":
myDiv.setAttribute('deferredHtml', '<img src="http://upload.wikimedia.org/wikipedia/commons/4/4e/Single_apple.png">');
global.loadDeferredImage = function() {
if(myDiv.hasAttribute('deferredHtml')) {
myDiv.innerHTML = myDiv.getAttribute('deferredHtml');
myDiv.removeAttribute('deferredHtml');
}
};
... onclick="loadDeferredImage()"
I created jsfiddle illustrating this idea:
http://jsfiddle.net/akhikhl/CbCst/3/
I'm trying to customize a Tipue search script.
Currently the script is searching the entire HTML file (including metadata) and triggering false positives on the search results. I'd like to eliminate the metadata from the critera or only allow the script to search a specific DIV (i.e. #pagewrap).
Here is a link to the current script:
http://www.worldonecommunications.com/ndrill/tipuesearch/tipuesearch.js
(Lines 37-77)
The pages are being indexed in a separate file, but I think the problem lies in the file listed above.
I think you need to change these lines:
var t_1 = html.toLowerCase().indexOf('<title>');
var t_2 = html.toLowerCase().indexOf('</title>', t_1 + 7);
...
var t_1 = html.toLowerCase().indexOf('<meta name="description"');
var t_2 = html.toLowerCase().indexOf('"', t_1 + 34);
I'am also searching a way how to modify this engine to out results from page body.
For others who are interested:
The developer finally updated the search script to target only a specific DIV. The updated code can be downloaded from their site:
http://www.tipue.com/search/