Im developing Windows 10 store apps Javascript/Html and since there is Microsoft EDGE in apps as the browser, inline scripting no longer works. If i put the code in an external file, the page loads, but none of the click events work. Is there any solution for this. Small example where onclick attribute does not work.
Code
default.html 7 default.js
// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
function gored() {
document.body.style.backgroundColor = red;
}
(function () {
"use strict";
WinJS.Binding.optimizeBindingReferences = true;
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var isFromBackground = false;
app.onactivated = function (args) {
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll());
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your application is suspended, call
// args.setPromise().
isFromBackground = true;
};
app.start();
})();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>App1</title>
<!-- WinJS references -->
<!-- To get the latest version of WinJS, go to: http://go.microsoft.com/fwlink/?LinkId=533245 -->
<link href="WinJS/css/ui-dark.css" rel="stylesheet" />
<script src="WinJS/js/WinJS.js"></script>
<!-- App1 references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
</head>
<body>
<p>Content goes here</p>
<button onclick="gored()"> Click Me</button>
</body>
</html>
I went into detail about this in a blog post.
Windows HTML5 apps have a strict security setting, especially when it comes to injecting code at runtime via JavaScript. I ran into this issue before as well.
You can wrap the function that you are using to inject the Javascript with another function, MSApp.execUnsafeLocalFunction().
When attempting to dynamically insert a div, Windows 8 throws an error. Specifically, it’s when trying to use something like:
div.innerHTML = "A string of some stuff"
HTML1701: Unable to add dynamic content ' a' 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=
Reason:
The reasoning behind all of these problems is the same, so I’ll just state it here once for the sake of brevity. `Microsoft fears that the string can be intercepted somewhere along the line, and malicious content can be added to the values of your string.
Work Around:
The big issue with this method is that you’re trying to use innerHtml. Instead, use .append.
That still won’t work if you just try to pass in a string, however. What you need to do is set your string to a variable, then pass in that variable. If you do not create an object (that is, setting the string to a variable) then this will not work. If you just try to use a string, then you’ll see nothing but text where the div should be.
Here’s a single line example:
$panel.append('<'img src="' + item.thumbImageUrl +'" >');
If you try to pass that in, Windows 8 will throw the error seen above. Even if I wrap that in MSApp.execUnsafeLocalFunction() I will still see an error.
The workaround is as follow:
var appendString = '<'img src="' + item.thumbImageUrl '" >';
$panel.append(appendString);
Because I’m now taking that string and setting it to a variable (thereby turning it into an object), Windows 8 will allow me to pass in that object and create dynamic content.
Even then, it will occasionally throw the error above. HOWEVER, if you were to wrap that object in MSApp.execUnsafeLocalFunction(), you would then be in the clear. WinJS offers a function to wrap your own functions in, which allows you to basically say “I take responsibility for this function, and I assure you it’s safe.” That function is called: MSApp.execUnsafeLocalFunction().
So the final solution looks like this:
var appendString = '<'img src="' + item.thumbImageUrl '" >';
MSApp.execUnsafeLocalFunction(function() {
$panel.append(appendString);
});
You can read more about this issue here.
Further Reading:
execUnsafeLocalFunction from MSDN
TutsPlus tutorial on jQuery and Win8
I had a similar problem and found that a script read in the header did not work but when I moved it to the body, it did:
WORKS ON MOST BUT NOT ALL PAGES WITH 'EDGE'. WORKS WITH ALL PAGES ON ALL OTHER BROWSERS:
LT script type="text/javascript" src="../ie5.js" GT LT /script GT
LT script type="text/javascript" src="../common_functions.js" GT LT /script GT
LT /head GT
LT body GT
WORKS ON ALL PAGES WITH 'EDGE' AND OTHER BROWSERS:
LT /head GT
LT body GT
LT script type="text/javascript" src="../ie5.js" GT LT /script GT
LT script type="text/javascript" src="../common_functions.js" GT LT /script GT
Why? Only Microsoft will know.
Related
I'm trying to get PouchDB's Getting Started Guide working using IE11 from a local file (file://). Is it possible?
It works great using a local http server by adding the following scripts to the header in the index.html file:
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill#8/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch#3.0.0/dist/fetch.umd.min.js"></script>
I think my issue is both indexedDB and localStorage seem to be restricted by IE when served using the file:// protocol, however I was able to get localStorage working on it's own using the code below from this post:
!localStorage && (l = location, p = l.pathname.replace(/(^..)(:)/, "$1$$"), (l.href = l.protocol + "//127.0.0.1" + p));
So I thought that would get it working, but even then when i add the pouchdb localstorage adapter I get this error: "AssertionError: .status required, old abstract-leveldown".
Even if that did work, the solution isn't ideal because I need to add file://127.0.0.1 to the trusted sites list.
That's about as far as I've gotten, any help would be appreciated!
Thanks to Zhi Lv - MSFT comment I was able to get the demo working in IE11, however it requires the user to add 'file://127.0.0.1' to the trusted sites list in IE.
After completing the 'Getting Started' guide you'll need to make the following changes.
Update the head element in index.html file:
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>VanillaJS • TodoMVC</title>
<link rel="stylesheet" href="style/base.css">
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill#8/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch#3.0.0/dist/fetch.umd.min.js"></script>
<script src="pouchdb/object-assign.js"></script>
<script src="pouchdb/pouchdb-7.2.1.js"></script>
<script src="pouchdb/pouchdb.localstorage.js"></script>
<script src="pouchdb/pouchdb.memory.js"></script>
<!--[if IE]>
<script src="style/ie.js"></script>
<![endif]-->
</head>
You will need to download any missing 7.2.1 pouch-db files and put into a pouchdb directory. object-assign.js can be found here.
Modify the app.js, replace the db variable with these two lines:
!localStorage && (l = location, p = l.pathname.replace(/(^..)(:)/, "$1$$"), (l.href = l.protocol + "//127.0.0.1" + p));
var db = new PouchDB('todos', {adapter: 'localstorage'});
Goto line 8796 of pouchdb.localstorage.js, edit it to set the db.status like this:
function LevelUP (db, options, callback) {
db.status = 'unknown';
if (!(this instanceof LevelUP)) {
return new LevelUP(db, options, callback)
}
Bit of a muck around, but worked for me. Any improvement please let me know.
this is my page Test1.asp
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>New Page 1</title>
<script type="text/javascript">
function Alex()
{
var xmlHttp;
try
{
xmlHttp=new XMLHttpRequest(); }
catch (e)
{
try
{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
alert("Your browser does not support AJAX!");
return false;
}
}
}
xmlHttp.onreadystatechange=function()
{
if(xmlHttp.readyState==4)
{
document.getElementById("Alex").innerHTML =xmlHttp.responseText;//Get Google Destination Map
}
}
xmlHttp.open("GET","Test2.asp" ,true);
xmlHttp.send(null);
}
</script>
</head>
<body>
<div id ="Alex"></div>
<label onclick="Alex()" >ssss</label>
</body>
</html>
This is requested page Test2.asp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>New Page 1</title>
</head>
<body>
<div id="Mathew"></div>
</body>
<script type="text/javascript" >
{
document.getElementById("Mathew").innerHTML='ajax is working';
}
</script>
</html>
In the page (Test2.asp) javascript is not working
How do i call test2.asp to my test1.asp using ajax
In HTML inserted by Javascript does not execute automatically (at least in IE for sure). The only solution to this is to gather each of the script blocks in the loaded HTML and evaluate them each.
EDIT
I am using YUI here... the Dom class can collect all script tags from within the given block.
var domElement = document.getElementById("Alex");
var scriptBlocks = YAHOO.util.Dom.getElementsBy(function() {return true;},'script',domElement);
for (var i = 0 ; i < scriptBlocks.length ; ++i){
eval(scriptBlocks[i].innerHTML);
}
Simple as that. Also becareful about Internet Explorer... if you load in HTML using ajax, and it comes back with the script block as one of the first elements, it will, for some odd reason, ignore the script block and not include it in the response. To fix it, put a div above the script block with text in it with a style attribute of display:none;
If this is the HTML returned to IE, it will not include the script block in the response
<div>
<script type="text/javascript">
/* Some javascript */
</script>
</div>
This will fix the issue
<div style="display:none;">some text</div>
<div>
<script type="text/javascript">
/* Some javascript */
</script>
</div>
Very weird, but thats how IE rolls.
By default JavaScript contained with AJAX responses is not executed.
There is no point in building an Ajax handler from scratch when this problem has already be solved in various libraries just as jQuery and Prototype.
Use an absolute URI instead of a relative URL.
Adding a <script> element into a document via innerHTML doesn't(*) execute its contents as a script.
You're also trying to insert the entire HTML document, including <html>, <head> and <body> inside a <div>, which is quite invalid.
If you need to return both HTML and some script to execute, better to return a JSON object, eg.:
{
"html": "<div id="Mathew"></div>",
"js": "document.getElementById(\"Mathew\").innerHTML='ajax is working';"
}
then parse the JSON object, set the innerHTML to obj.html and eval the js. (Though it's generally questionable to be returning and executing arbitrary, scripts, there can sometimes be a use for it.)
(*: Well, doesn't generally. Exactly when a <script> element's contents get executed is browser-dependent. For example Firefox executes script when you append/insert a DOM HTMLScriptElement or ancestor into an element that is part of the document, whereas IE executes it when you insert the element into any parent for the first time, whether inside the document or not. In general, avoid inserting JavaScript-in-HTML content into HTML.)
Your methodology is slightly amiss. Typically, AJAX is used to send and receive data in non-HTML formats, such as XML, JSON, or sometimes even CSV (however, HTML is sometimes returned to the client, but usually as pieces of a page, not entire pages as in your example).
Logic is rarely transmitted and is usually maintained on the respective sides of the transmission. In other words, the client/request side has all of its own logic and already knows what to do with the data returned from the server/response side (which also doesn't accept or require any logic generated from the client side). Further, the use of eval, which is usually necessary to consistently execute the logic found in the response, is generally frowned upon and considered a bad practice, thus the saying, "eval is evil."
In some cases, it may be necessary, advantageous or just plain easier to receive logic as part of the response from the server. In these situations however, it is still considered a best practice to separate your data from your logic.
All that to nicely say that you're doing it wrong. I encourage you to read up on how AJAX works and how best to use it: w3schools walk-through, Mozilla MDC intro, AJAX and XML processing, updating a page (similar to what I think you're trying to do), and finally, AJAX API docs for jQuery, Prototype and Dojo.
Prototype has a nice way of handling this. See their stripScripts, extractStrips, and evalScripts methods on the String object. If you just strip the scripts, put your text into a div and then evalScripts, that'll work across all brwosers so scripts get executed exactly once.
I have a WordPress website and I have installed one plugin and the plugin has some problems in IE6 browser.
So, I want to disable that jQuery plugin when the page is viewed with the IE6 browser.
So now I need a jQuery statement to disable ALL other statements that are loading from other JS files.
use Downlevel-revealed conditional comments :
<!--[if lte IE 6]><![if gte IE 7]><![endif]-->
<!-- keep your script in between these two comments,
it will work in all browser except ie -->
<!--[if lte IE 6]><![endif]><![endif]-->
Explained here : Hiding some HTML from IE6?
I'm not entirely sure why IE6 is even on your agenda, but to each their own.
If it were me I would write something like this.
<!doctype html>
<!--[if lt IE 7 ]> <html class="ie6"> <![endif]-->....
.....
(function ($) {
"use strict";
// Detect IE 6
var greatGreatGranddadsBrowser;
if ($('html').is('.ie6')) {
greatGreatGranddadsBrowser = true;
}
if (greatGreatGranddadsBrowser) {
// Remove the elements that you don't want loaded
// Tell the users to seriously consider coming into the real world
} else {
// Do whatever else you need to do
}
}(jQuery));
For FireFox el.dom.innerHTML
<title>Test</title>
<link rel="stylesheet" type="text/css" href="common.css">
Test
For IE el.dom.innerHTML
Test
In FF the returned el.dom.innerhtml includes the and tag but in IE it does not. Are these filtered out by Ext in anyway and if so why?
Below this forum link give solution to override the Ext.element.Update method.
Ext.override(Ext.Element, {
update : function(html, loadScripts, callback){
}
http://www.sencha.com/forum/showthread.php?30110-internet-explorer-autoLoad-css-not-applied
But I have question where I add this function which ExtJs files. because ext-all-2.2.js and ext-base-2.2 is core files of ExtJs Libarary. I put this code in ExtExtension-2.2.js file but Override Update method doesn't fire when assign
this.el.dom.innerHtml=Markup (markup is string which contain html string.)
Please help me which ExtJs file I put function . Ext.Override(Ext.Element) Update Method?
That override simply needs to run sometime after the Ext scripts are loaded. So include a javascript file after including the Ext files, and the method will be overridden.
<script type="text/javascript" src="/path/to/ext-all-2.2.js"></script>
<script type="text/javascript" src="/path/to/myscript.js"></script>
The in myscript.js:
Ext.override(Ext.Element, {
update : function(html, loadScripts, callback){
...
}
}
Remember though, that Ext isn't magic. It can't automatically fire the update function when simply assigning innerHTML, as that is handled entirely by the browser. Rather, use the update function directly, and that will update the innerHTML:
Instead of:
this.el.dom.innerHtml=Markup;
use:
this.el.update(Markup);
Greetings all,
I am attempting to explicitly load the effects.js and builder.js Scriptaculous libraries on a page, using this code:
<script type="text/javascript" src="/javascripts/scriptaculous.js?load=builder,effects"></script>
This works like a charm in FF 3.0.x, IE7 and Opera 9.6.x. It does not work in Firefox 2.0.x, however. The libraries never become loaded. In order to get them to load in FF 2.0.x, I must explicitly reference them with two extra <script /> tags, i.e.:
<script type="text/javascript" src="/javascripts/scriptaculous.js?load=builder,effects"></script>
<script type="text/javascript" src="/javascripts/builder.js"></script>
<script type="text/javascript" src="/javascripts/effects.js"></script>
Does anyone happen to know what the discrepency between FF 2.0 and 3.0 is that causes this behavior? Is there a better solution to my problem?
Thanks for your help!
I've had too much coffee today, so I figure I will give this a go.
One possibility is the load function in scriptaculous.js does not correctly do the processing to include the libraries passed to it as parameters (scriptaculous.js?load=builder,effects).
Try putting in an alert to see if the load function in scriptaculous.js is being entered into, if it is, then the process probably doesn't do what it's supposed to on FF2:
load: function() {
alert('In the load function!');
...rest of code here...
If it isn't, then (maybe) firefox 2 does not want to execute load.
The last part of load seems to do the work for including other libs:
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
From the above code, I can see that the includes variable should parse out the library names, see if that's being assigned anything, replace it with something like:
var includes = s.src.match(/\?.*load=([a-z,]*)/);
alert(includes[0] + ' ' + includes[1]);
That should give you a better idea of what's going on. While this is an interesting little problem, I would definitely go with the solution you proposed:
<script type="text/javascript" src="/javascripts/scriptaculous.js"></script>
<script type="text/javascript" src="/javascripts/builder.js"></script>
<script type="text/javascript" src="/javascripts/effects.js"></script>