Hey i can't figure out why my code is not working. I've pulled out my hair please take a look and tell me what's wrong with this code
Note : it's working fine in chrome and mozilla only not working in IE10 and all below versions of IE
please note that am trying by two different ways so please don't confuse in that
here is fiddle link http://jsfiddle.net/rEmn6/
here is my html code
<div id="wrapper">
<div id="editable" contenteditable="true" onkeyup="SaveValue(this)"></div>
<button onclick="clearData()" id="reset">Reset</button>
<br>
<textarea id="message" onKeyUp="setVal(this)"></textarea>
</div>
here is javascript code
var editable = document.getElementById('editable');
var store = window["localStorage"], storage = window.localStorage;
if (navigator.appVersion.indexOf("MSIE 7.") != 1){
console.log(navigator);
var msg = document.getElementById('message');
function setVal(ths) {
console.log(ths.value);
storage.setItem('sms', ths.value);
};
if(storage.getItem('sms')){
msg.value = storage.getItem('sms');
}
}
function SaveValue(ths){
var val = ths.innerHTML;
if (val != ''){
store.setItem('contenteditable', val)
console.log(val);
}
}
function clearData(){
console.log('clear hoga');
store.clear();
}
if (store.getItem('contenteditable')) {
editable.innerHTML = store.getItem('contenteditable');
}
If you are trying localStorage on a local machine and without use of a web server like WAMP, XAMPP or similar programs. IE browser will definitely throws an error. So make sure that you are trying it in a web server for development purposes.
When you run your page from local filesystem, the browser will not act like he does for web server.
I suspect this is what you wanted to achieve :
<div id="wrapper">
<div id="editable" contenteditable="true"></div>
<button onclick="localStorage.clear()">Reset</button>
<br>
<textarea id="message"></textarea>
</div>
<script>
function init()
{
function setup (name, prop)
{
function save (prop)
{
localStorage.setItem (this.id, this[prop]);
}
var elem = document.getElementById(name);
// retrieve value
elem[prop] = localStorage.getItem (name) || '';
// setup save handler
//elem.onkeyup = save.bind (elem, prop);
elem.onkeyup = function (e,p) { // IE8+ compat.
return function () {
save.call (e, p);
};
}(elem, prop);
}
setup ('editable', 'innerHTML');
setup ('message' , 'value');
}
window.onload = init;
</script>
Your code was flawed in so many ways I reckoned it was easier to rewrite it from scratch:
complete duplication of code for the saving/restoring of your 2 elements, with the code located in two different places while the problem is basically the same
confusing names ('ths' is an eyesore. The first time I checked your code I automatically identified it as a typo for 'this')
wrong way of defining event handlers and passing them parameters (defining event handlers inside HTML code is causing all sorts of problems, since you can't access anything but this and global variables)
mumble-jumble of global and local variables (due to the definition of the event handlers inside HTML)
your code did not work in the fiddle since all your global functions were moved into the init procedure
It was much less work (at least for me) to rewrite it than to try to rebuild a functional version and then try to understand what went wrong with it.
I dumped the attempt at detecting whatever IE7 version. It was getting in the way, since your problem was targeting IE10 anyway. As a side note, a site using this kind of features should simply drop IE7- compatibility altogether, IMHO.
I tested this code on IE8/XP, FF, Opera, Chrome, IE11 and safari/XP.
All tests were run from a web server except IE11. It is well possible IE10- have problems with local storage when run localy.
In Internet Explorer 11 I get the error message SaveValue is undefined appearing here:
<div id="editable" contenteditable="true" onkeyup="SaveValue(this)"></div>
You should be using unobtrusive Javascript techniques and place the onKeyUp event handling in your script instead of in the div.
var editable = document.getElementById('editable');
editable.onkeyup = SaveValue;
In your SaveValue function you can now use this.innerHTML to get the text
This should save you some tears
Related
I am developing a Windows Phone Application in JavaScript. I am using the AngularJS library. The problem is that I cannot add a dynamic content because of security reasons.
The error I get: HTML1701: Unable to add dynamic content '<div id="view_login" class="view"> <div id="view_login_container"> <img class="logo" src="http://oi60.tinypic.com/okwifa.jpg"> <input type="text" placeholder="Username" ng-model="loginUsername"> <input type="password" placeholder="******" ng-model="loginPassword"> <button ng-click="doLogin()">Login</button> <button ng-click="changeView('/signup')" class="link">... or sign up now</button> </div> </div>'. 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.
I changed one line in AngularJS library which should fix the problem:
append:function(a,c){
**MSApp.execUnsafeLocalFunction(function () {**
r(new N(c),function(c){
1!==a.nodeType&&11!==a.nodeType||a.appendChild(c)
})
});
}
Unfortunately it did not work.
I spent several hours trying to find a solution, but I did not manage it. I would appreciate any suggestions how to make working the Windows Phone App written in JavaScript with AngularJS.
Microsoft Open Technologies recently released a shim which will prevent this exact problem for Windows Store apps using AngularJS, as well as many other popular JavaScript libraries.
Simply download the JavaScript Dynamic Content shim off of GitHub, then reference the file towards the beginning of your app before any other scripts are run. You should no longer see a dynamic content error.
Let me know if this solves your problem!
I encountered this issue when using Angular in a Windows Store App. The solution I came up with was to monkey patch the DOM manipulation functions that were unsafe, rather than having to hack up Angular or jQuery because I still wanted to be able to update using bower.
var patch = {
methods: [
'appendNode',
'cloneNode',
'insertBefore',
'removeChild',
'replaceChild'
],
properties: [
'innerHTML',
'outerHTML'
]
};
patch.methods.forEach(function (name) {
proxyUnsafeMethod(HTMLElement.prototype, name);
});
patch.properties.forEach(function (name) {
proxyUnsafeProperty(HTMLElement.prototype, name);
});
function proxyUnsafeMethod(object, name) {
var _unsafe = object[name];
object[name] = function () {
var context = this;
var args = arguments;
return MSApp.execUnsafeLocalFunction(function () {
return _unsafe.apply(context, args);
});
};
}
function proxyUnsafeProperty(object, prop) {
var descriptor = Object.getOwnPropertyDescriptor(object, prop);
proxyUnsafeMethod(descriptor, 'set');
Object.defineProperty(object, prop, descriptor);
}
Angular dynamically puts HTML comment tags <!-- --> for ng-repeat and other directives. Unfortunately, Microsoft considers these to be unsafe when put in from javascript using element.innerHTML, and thus is not allowed.
The workaround is to modify the actual angular.js file and wrap all element.innerHTML calls in MSApp.execUnsafeLocalFunction();
In the version of Angular that I'm using, this is line 2539 and line 2162
Line 2539:
MSApp.execUnsafeLocalFunction(function() { element.innerHTML = value; });
Line 2162:
MSApp.execUnsafeLocalFunction(function() { div.innerHTML = '<div> </div>' + element });
The best method would be to search the angular.js file for all instances of innerHTML and wrap it.
In a lot of cases where you run into issues with dynamic content Winstore-jsContrib might help. Simply add the .js file at the beginning of your app and you're good to go.
I'm writing a decent sized JavaScript animation library, that I would like to include debugging code in. I could easily do a check :
if(myLib.debugger){
console.warn('warning message');
}
However if this runs a couple thousand times a second, it would eventually cause performance issues. Add in a few more checks throughout the code and the effect will be even more noticeable.
What I'm wondering is if it would be possible to check onload if the debugger should be enabled, and if so... turn something like this:
//debugger if(!this.name) console.warn('No name provided');
into:
if(!this.name) console.warn('No name provided');
Leaving the code commented if its not enabled, and uncommenting it if it is, thus removing any possible performance issues. Could this be done somehow with a regular expression on the entire script if loaded in through ajax? I'm trying to avoid the need for 2 versions of the same code, lib.dbug.js and a lib.js.
Cross browser compatibility is not of great importance for this (I'm really only worried about new browsers), I see it as nice to have item. If its possible however, it would be a great thing to have.
Any insight would be greatly appreciated.
The simplest way to do this would be to check if the debugger should be disabled and if so, replace it with a mock object that does nothing at the very start of your script:
if (!myLib.debugger) {
window.console = (function () {
var newConsole = {};
var key;
for (key in window.console) {
if (typeof window.console[key] === 'function') {
newConsole[key] = function () {};
}
}
return newConsole;
}());
}
The overhead of this approach should be negligible.
If this is a JavaScript library... then I'd expect as a 3rd party developer that I could download/use 2 versions. The production version (no debug, AND minimized). If I wanted to debug, I would point to the debug version of the library instead.
e.g.
<script src="foo-lib-min.js"></script>
<!-- swap to this for debugging <script src="foo-lib-full.js"></script>-->
Is there a way through javascript to see what version (or rollup) the crm organization/server is on? What I really want to know is if I am on UR11 or before.
I've tried:
Xrm.Page.context - but nothing about versions (did I miss something?)
Checking if (crmForm == null) (Since that was disabled as of UR12) The problem is that if the org enables HTC support then crmForm will not be null, and I need to know what version with or without HTC support enabled.
What I've done for now is put the onus on the solution installer to modify a javascript file that has the "isRollup12" variable to true or false, which is quite clunky.
There is a global JS variable you could check:
alert(APPLICATION_FULL_VERSION);
//on UR12 '5.0.9690.3236'
//on UR11 '5.0.9690.2839'
//and so on...
But this method isn't supported, so use at your own risk.
you can check if the getClientUrl function is defined, it's a new function included inside UR12.
var isRollup12 = false;
if (Xrm.Page.context.getClientUrl !== undefined) {
isRollup12 = true;
}
This is an interesting problem that I am facing with JavaScript and IE8 on Windows XP and Windows 2003. I create an object on the page and then retrive information about that object (for example, its version). When trying to get the version, I am running this code:
var myObject = document.getElementById(objectId);
console.log(myObject.version);
What is interesting is that this code works on every single browser except IE8 on Windows XP and 2003. I've done some debugging and this is where things get interesting.
myObject is not null but myObject.version is undefined. So what I did is I added an alert in between so the code is now as follows:
var myObject = document.getElementById(objectId);
alert(myObject.version);
console.log(myObject.version);
The alert results in "undefined", however, the console.log is now resulting in the actual version. If I add an alert before this alert of anything (let's say alert("something")) then the second alert has the actual version now. I am assuming this is a timing issue (for some reason the object needs sometime to be able to provide the data stored in it?) but I am not sure what kind of timing issue this is or how to approach it.
Sorry for the long description but any help is appreciated.
document.getElementById doesn't return an object. It returns a DOM element. So, you expect to see a .version property in a DOM element, which by the official W3C specification is missing (or at least I don't know about this).
I'm not sure what you are expecting to see in .version, but if it is something custom then you should create a custom object like that:
var o = { version: "..." }
console.log(o);
You said that this may be a time issue. If that's true then I'll suggest to try to access the .version property after the DOM is fully loaded. You can use jQuery for the purpose:
$(document).ready(function() {
var myObject = document.getElementById(objectId);
alert(myObject.version);
console.log(myObject.version);
});
You can add a setTimeout in your function till the .version property is there.
var f = function(callback) {
var check = function() {
var myObject = document.getElementById(objectId);
alert(myObject.version);
console.log(myObject.version);
if(typeof myObject.version !== "undefined") {
callback(myObject.version);
} else {
setTimeout(check, 1000);
}
}
setTimeout(check, 1000);
}
What happens if you put the <script>...</script> tag with the js code at the end of the html file? In my opinion, the code is executed when the DOM is not ready. If you put it in the end, then it will be executed after it's loaded.
I have a Greasemonkey script that works just fine in Firefox and Opera. I struggle with getting it to work in Chrome, however. The problem is injecting a function into the page that can be invoked by code from the page. Here's what I'm doing so far:
First, I get a helper reference to the unsafeWindow for Firefox. This allows me to have the same code for FF and Opera (and Chrome, I thought).
var uw = (this.unsafeWindow) ? this.unsafeWindow : window;
Next, I inject a function into the page. It's really just a very thin wrapper that does nothing but invoking the corresponding function in the context of my GM script:
uw.setConfigOption = function(newValue) {
setTimeout(setConfigOption, 0, newValue);
}
Then, there's the corresponding function right in my script:
setConfigOption = function(newValue) {
// do something with it, e.g. store in localStorage
}
Last, I inject some HTML into the page with a link to invoke the function.
var p = document.createElement('p');
p.innerHTML = 'set config option to 1';
document.getElementById('injection-point').appendChild(p);
To summarize:
In Firefox, when the user clicks that injected link, it will execute the function call on the unsafeWindow, which then triggers a timeout that invokes the corresponding function in the context of my GM script, which then does the actual processing. (Correct me if I'm wrong here.)
In Chrome, I just get a "Uncaught ReferenceError: setConfigOption is not defined" error. And indeed, entering "window.setConfigOption" into the console yields an "undefined". In Firebug and the Opera developer console, the function is there.
Maybe there's another way to do this, but a few of my functions are invoked by a Flash object on the page, which I believe makes it necessary that I have functions in the page context.
I took a quick look at the alternatives to unsafeWindow on the Greasemonkey wiki, but they all look pretty ugly. Am I completely on the wrong track here or should I look more closely into these?
RESOLUTION: I followed Max S.' advice and it works in both Firefox and Chrome now. Because the functions I needed to be available to the page had to call back into the regular ones, I moved my whole script to the page, i.e. it is completely wrapped into the function he called 'main()'.
To make the extra uglyness of that hack a little bit more bearable, I could at least drop the usage of unsafeWindow and wrappedJSObject now.
I still haven't managed to get the content scope runner from the Greasemonkey wiki working. It should do the same and it seems to execute just fine, but my functions are never accessible to <a> elements from the page, for example. I haven't yet figured out why that is.
The only way to communicate with the code running on the page in Chrome is through the DOM, so you'll have to use a hack like inserting a <script> tag with your code. Note that this may prove buggy if your script needs to run before everything else on the page.
EDIT: Here's how the Nice Alert extension does this:
function main () {
// ...
window.alert = function() {/* ... */};
// ...
}
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);
I have this :
contentscript.js :
function injectJs(link) {
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;
document.getElementsByTagName('head')[0].appendChild(scr)
//document.body.appendChild(scr);
}
injectJs(chrome.extension.getURL('injected.js'));
injected.js :
function main() {
alert('Hello World!');
}
main();
The other answers either force you to use function expressions, import an external additional file or use a long patched hack.
This answer will add the javascript into the page directly from your source code. It will use ECMAScript 6 (ES6) template literals to get the multi-line javascript string effortlessly onto the page.
var script = document.createElement('script');
script.type = "text/javascript";
script.innerHTML = `
function test() {
alert(1);
}
`;
document.getElementsByTagName('head')[0].appendChild(script);
Please note the backticks `` that define the beginning and the end of a multi-line string.
I took a quick look at the alternatives to unsafeWindow on the Greasemonkey wiki, but they all look pretty ugly. Am I completely on the wrong track here or should I look more closely into these?
You should look, because it's only available option. I'd prefer to use location hack.
myscript.user.js:
function myFunc(){
alert('Hello World!');
}
location.href="javascript:(function(){" + myFunc + "})()"
example.com/mypage.html
<script>
myFunc() // Hello World!
</script>
Sure, it's ugly. But it's working well.
Content Scope Runner method, mentioned by Max S. is better than location hack, because its easier to debug.