I've come across some weird behavior in IE11 when it comes to overriding functions in javascript.
On a webpage i have the following code:
(function ()
{
var tempSetItem = window.localStorage.setItem;
window.localStorage.setItem = function (key, data)
{
var newdata = JSON.stringify(data);
newdata = JSON.parse(newdata);
newdata.CachedDate = new Date();
tempSetItem.call(window.localStorage, key, JSON.stringify(newdata));
};
})();
This should simply override the localStorage.setItem() function.
However, i ran into some trouble with the code and decided to comment it out.
When i refreshed the page (cleared cache ofcourse) the same problem was still there.
I soon realised that IE had somehow cached my override.
I searched through all my files to make sure i didn't override it anywhere else and i even tried to set it to null manually through the console (In other words, it should not be null after a refresh) and after a refresh, it was now null.
It seems to be cached per domain or per URL in some way and i don't know how to clear this cache or if it's even possible.
I even tried repairing IE but localStorage.setItem is still null on my webpage.
I still don't know why the overriding gets cached but i found a way to reset it.
Calling localStorage.clear() resets the entire localStorage-object, including the setItem-function.
To avoid the rest of the problem i simply made a normal wrapper-function instead of overriding the original and called that from all the places where i would otherwise call localStorage.setItem().
Related
I have recently built a feature on our web application that uses AngularJS and I am having some issues with IE 11 not properly $apply()ing data changes to the DOM. For some reason this only occurs sometimes and never occurs when I try to debug the problem which makes it seem like a timing issue.
Here is the function that gets called when the problem occurs.
$scope.createThrottling = function (sources) {
MYAPP.modals.Throttling('New', sources, API, function () {
$scope.isLoading = true;
$scope.$apply();
API.Migrations.getThrottles({ id: jQuery.getUrlVar('id') }, function (data) {
$scope.Throttles = data.Throttles;
$scope.isLoading = false;
// THE PROBLEM IS RIGHT HERE
});
});
}
The comment above shows where the problem seems to be stemming from. At this point in the execution of the code, Angular should automatically be checking for a change in $scope.Throttling and then make a change to the DOM accordingly, however, for some reason in IE 11, on the first visit to the page the binding is not occurring.
Subsequent refreshes of the page cause the binding to work however which seems very strange. It is as if $scope.$apply() is needed after API.Migrations.getThrottles is finished, but I cannot do that because Angular throws a JS error saying that it is already digesting.
Some things to note:
This only happens in IE
This only happens on the first visit to a page per load of the browser (I can hit F5 and try the same exact thing and it will work)
Could this be occurring because my API.Migrations.getThrottles call is inside a callback function for the MYAPP.modals.Throttling module which is outside of Angular completely?
When I try to debug the JS function above, everything works just fine which makes it seem like a timing issue
Any help to finding out what is causing this bug would be much appreciated!
Thanks
for the reference, found the solution here: http://www.oodlestechnologies.com/blogs/AngularJS-caching-issue-for-Internet-Explorer
$httpProvider.defaults.cache = false;
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
$httpProvider.defaults.headers.get['If-Modified-Since'] = 'Thu, 01 Jan 1970 00:00:00 GMT';
I think I have found my problem! I finally tried printing the data that is coming back from the server in the DOM without using the debugger and I realized that the API response is NOT giving me back new data! It is sending back cached data that is no longer valid which is why the objects are not showing up in the DOM. This also explains why using the debugger works because it forces each API call to not be cached!
I was able to fix this problem in my $resource by adding { _: Date.now() } in my params object in my $resource. This appends _=1234567890 to all GET calls for this $resource which forces IE to not cache
I'm working with Solr 4.3.0 and implementing Ajax-Solr for the interface. However, Ajax-Solr does not save state automatically. There is a ParameterStore and ParameterHashStore method but they don't work with legacy browsers. I used my google-fu and found the following but it doesn't work as intended:
https://github.com/evolvingweb/ajax-solr/pull/23
...with a few more resources I came up with this:
<script>
var Manager;
(function ($) {
Manager.setStore(new AjaxSolr.ParameterHashStore());
Manager.store.exposed = [ 'fq', 'q', 'start' ];
Manager.init();
// Establish Variables
var History = window.History; // Note: We are using a capital H instead of a lower h
if ( !History.enabled ) {
// History.js is disabled for this browser.
// This is because we can optionally choose to support HTML4 browsers or not.
return false;
}
State = History.getState(),
// Bind to State Change
History.Adapter.bind(window,'statechange',function(){ // Note: We are using
statechange instead of popstate
// Log the State
var State = History.getState(); // Note: We are using History.getState() instead
of event.state
History.log('statechange:', State.data, State.title, State.url);
});
// Log Initial State
History.log('initial:', State.data, State.title, State.url);
})(jQuery);
</script>
But it doesn't work. The Forward and Back buttons are broken in all browsers and nothing gets logged to the console.
What am I missing or is v4.3.0 inherently borked right now and needs a patch?
Would greatly appreciate any help. Thank you!
I know nothing about AJAX-Solr. But I think discussing some few things with you might help.
If AJAX-Solr works the same way the normal AJAX do, then AJAX-Solr will execute some server-side function and outputs it in client-side (of course without refreshing the actual page). As consequence, you should put the function triggering the ajax call inside your History.Adapter.bind(window,'statechange',function().
About State = History.getState(); it is responsible of returning the state data of a pushed state in history stack (url, title, ajax parameters). please to read the doc about hisrory.js on github. Note also that you are using a comma instead of semicolon in your code. In addition, you are calling this function twice. Call it only one time inside your Bind function to get the state parameters and use them in your ajax call (in order to refresh the part of your page while navigating over brower back-forward buttons).
I advise you to read also Back-Forward buttons of browser are showing weird behaviour. History.js, maybe it will help you understand positionning of ajax regarding Bind.
Good luck.
my first time on here.
My problem is with AS3, Javascript and possibly the browsers Firefox and IE.
I have done so much searching for an answer so i will print my code:
i am using this line to call the flash application and in all browsers its combatible and actually traces in firebug to hold an OBJECT->FLASH_ID so thats not the problem.
var obj = document.getElementById('test');
then i use addcallback:
obj.sendStatus(loggedIn);
now whats weird is that i trace all individual elments in chrome and
-obj = flash object
-sendStatus = flash->function
-loggedIn = either false or true;
everything works great but when i am on firefox or ie
it traces differently
-obj = flash object
-sendStatus = undefined
-loggedIn = either true or false;
now what am i missing??????????
i tried embedding rather than object insertion
i made sure that the id's were all unique
i checked to make sure i had the right flash object selected with getElementById
im so confused.. and it feels like something simple.
I know about some browser - dependent timing problems, making the interface of the flash object available...
A timer could help, try this:
var obj = document.getElementById('test');
setTimeout(function(){obj.sendStatus(loggedIn);}, 500);
500 is a bit to long, but just to be sure. If it works you can try to lower it to 200 - 300.
make sure you declared allowScriptAccess = sameDomain both in embed tag and object tag
in case you don't use swfObject
Maybe the way you get a reference to the swf is wrong, try this
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html
The problem is that using ExternalInterface requires both parties (browser and flash) to be ready.
You can have the flash poll a method in the page which just returns true so that you know its ready to receive calls from flash.
On the flip side if the page is cached, it can sometimes happen that the page wants to send to flash before flash is ready, so I use a callback to the page telling it flash is ready, so its like a handshake, once both parties are ready, then we can start sending data back and forth.
This has been my approach since Firefox 3.
I'm using some jQuery that works fine in all browsers except in Internet Explorer 8 (and probably not the earlier versions although I'm not as worried about those.). I'm using jQuery's .each function to loop over every element in a JavaScript array that is auto generated on my page by the fairly inflexible CMS I'm using.
For example, my CMS writes this array of image objects in javascript to my page:
paths = [];
paths[0] = new Image();
paths[0].src = "/path/to/image1"
paths[1] = new Image();
paths[1].src = "/path/to/image2"
paths[2] = new Image();
paths[2].src = "/path/to/image3"
paths[3] = new Image();
paths[3].src = "/path/to/image4"
I then am using jQuery each function to loop over this array and return all images in a nice little unordered list.
The problem is that while using jquery's
$(document).ready(function() { ... });
is working fine in FF/Safari/Chrome, etc. and actually able to render my unordered list pretty much immediately, Internet Explorer seems run my document.ready function before it registers that the 'paths' array exists in JavaScript (even though this jQuery is included after the code for the image array). I know this because I'm thrown an 'paths is null/undefined' error in IE.
When I changed it from
$(document).ready(function() {
to
$(window).load(function() {
my code worked as it should in IE because it only executes my jquery 'each' function after the entire page is loaded (which sucks because it slows down render time and causes a 'lag' in what I'm trying to do... but hey if it works). However its appearing that IE sometimes still fires off my each function while using $(window).load before it registers that an array named 'paths' exists if the website has been cached.
Would anyone know a sure fire way to ensure that the paths variable is registered by IE immediately so my each function doesn't fail?
It's
$(document).ready(..)
not
$('document').ready(..)
Apologies for stating the obvious but are the two pieces of code in the same script /file? You are saying that IE is getting the sequence wrong unlike other browsers so I'm wondering if one or both are Asynchronous.
Another obvious thing is to have your function check that the paths array is not null, so then it doesn't throw an error. Sorry, if this comment had you throwing your mouse at your screen. Is there any way to get the function that generates the paths array to call the function or at least to set a boolean, which your function can then use to determine if its got the paths array set.
Maybe you could define the function elsewhere on the page and have your jquery do something like this:
document.ready(myfunction());
I have lots of jquery that is running on page load and it's causing one of my elements to disappear (making it style=display:none;). I'm guessing the jquery hide() function is being applied to this element by mistake, but I can't find out which statement is causing it.
Is there any javascript,firebug,etc function or tool that will essentially act as a breakpoint/listener for the html element (perhaps one I can run in my browser)? It would be great to see what function is affecting that element on page load.
Hah! I just found the answer I wanted. Firebug has a "break on mutate" function on the HTML tab that will show you what line in the javascript file is changing an html element. It is in Firebug 1.5 and the new 1.5.2 update released today moved the icon, so I noticed it and found it purely by luck!
http://www.softwareishard.com/blog/firebug/firebug-15-break-on-next/
Thanks for your attempts guys!
You can find where the element is being accessed with getters/setters. However, the setter method doesn't seem to work with chrome... it works with the latest version of minefield [firefox beta], though... so you could test it out I guess =)
myElement.style.__defineSetter__("backgroundColor", function(val)
{
var cur = arguments.callee;
var callLog = "";
while(cur != null)
{
callLog = cur.caller + "\n" + callLog;
//alert(cur.caller);
cur = cur.caller;
}
alert(callLog);
}
);
Oh, but it won't let you actually "set" the variable. to do that, you define a dummy variable and set that. Then, when you define your getter [with __defineGetter__] you return that value