JS Script execution order on displaying from cache - javascript

I am writing a rail app making trees, with bootstrap and jsPlumb.
I have this problem, when displaying a page for the first time, everything works perfectly. When I go again on a page, some code is not properly executed.
This happens with both jsPlumb and bootstrap-tagsinput: a simple tagsinput on a page is not displaying properly.
If I hit refresh, then the page loads properly again.
I tend to think this is related to the fact that when I display a page with some cached elements, some of the script are not executed, or are executed in the wrong order, but I have no clue about it, since I can't see any error.
Hence the questions,:
How can I check that everything is properly executed (i used the console.log, the function are called)?
Is there anything to know about the way the cache may have an effect on script?
How can I debug this type of problem?
Thank you!

I found the answer, this was due to turbolinks, which handles some of the caching on the server-side. It was a holdover gem that I suppressed, and the problem is gone.

Related

javascript scratchblocks squarespace

I would like to use Scratchblocks (a tool for rendering visual Scratch code blocks from a text listing, on GitHub) on my Squarespace website. The problem I am getting is that the scratchblocks are never rendered on the first load - but only after a refresh.
This is in the header (set in the header for that particular blog):
<script src="https://scratchblocks.github.io/js/scratchblocks-v3.1-min.js""></script>
Then I think I need to call this function at the end of the page - I've put it in the footer:
scratchblocks.renderMatching('pre.blocks');
NOTE: When I view the source I sort of see this JavaScript twice at the end of the page. Not sure what is happening there.
Here's an example of it on my website, where it renders the scratchblocks only after a refresh. [UPDATE - following the fix provided below, this now renders first time, every time as far as I can tell.]
[http://www.glennbroadway.com/coding-zone/2017/4/6/simple-collisions-in-scratch]2
Here's an example of someone else using it and it working properly. I've inspected the source and I can't work out how they are doing it.
https://codeclubprojects.org/en-GB/scratch/memory/
I've also tried all the different methods listed elsewhere on stackoverflow for getting javascript to load only after the HTML has finished. I can't get any of them to work - but I think the problem is something to do with Squarespace, I just don't have the knowledge to work out what.
Any help would be greatly appreciated.
In Squarespace, when your custom Javascript only works after a page refresh, it most likely has to do with Squarespace's AJAX loading:
Occasionally, Ajax may conflict with embedded custom code or anchor
links. Ajax can also interfere with site analytics, logging hits on
the first page only.
You may be able to disable AJAX for your template. Or, see the other approaches outlined here: https://stackoverflow.com/a/42604055/5338581 including:
window.addEventListener("mercury:load", function(){
// do stuff
});
In addition, I would generally recommend placing custom code in the "Footer" code injection area unless you have a specific reason to do otherwise.

JavaScript getElementsByTagName not working correctly

console.log(document.getElementsByTagName("input").length);
is printing out 0. I have found many suggestions online saying that the page is not loaded, but this is not the case. I am running the code via the console on a loaded page (and I have already tried onload). But here is the catch:
The first time I load the page and run it on a computer, the code works correctly and finds all the input elements on the page. However, once I run the code, if I refresh the page, it will always return 0 from there on out. If I switch computers and run the same code, it works fine ONCE and then stops working on refresh.
Furthermore, it's not just limited to "input". It happens to everything (i.e. "a"). Basically I can no longer find ANY elements on the webpage, but they're definitely there. I can inspect the page and look at all of them.
What could be causing this? Is the website blocking JavaScript for me once it sees me using it? If so, what can I do to prevent this from happening?
It's just a simple survey website for my school.
It seems that the title of the tag is always capitalized, as in all these examples:
https://www.w3schools.com/JSREF/met_document_getelementsbytagname.asp
So your code should look something like this:
console.log(document.getElementsByTagName("INPUT").length);

Loading image is shown too late for users with slow connection

The issues is with existing ASP.NET MVC 4 project. The View itself is not that big but there are also several service calls and what happens is that people with slow internet connection reports that for some period of time when they request the page it stay unresponsive, so they don't know if the content is loading or something went wrong.
So in general, what I need is a way to show a loading image as the very first thing from this page (or at least fast enough) so even if it takes some time for the browser to download the full content, at least the user will know that something is going on.
However it seems that this is not as trivial as it sounds. I came up with two ideas, one was already proven to not work in all cases and the second is also something that many people doesn't recommend.
What I've tried was to use pure JavaScript in the <head> tag like so:
<html>
<head>
<script>
document.write("<div style='margin-left: 50px; margin-top : 50px;'>LOADING...</div>");
</script>
</head>
Of course the styling is just to get the idea. This seemed like it was working until recently when on a minor build of IE 11 the page broke which after some investigation was proven to be due to the usage of document.write() inside the <head> tag. Even though this seems to work on most browsers and versions the fact that it's a potential danger requires a change in the approach.
The second idea is pretty similar to this, again - writing directly in the <head> tag but this time instead of using document.write() just putting the html markup directly there. From what I've read this is also a recipe for disaster so I don't even want to try it, but those are the two ideas that I could came up with. Everything else just doesn't work for slow internet connections since the mainstream solutions relays on the fact that some part of the DOM is already loaded so you can use it to apply behaviour/style.
I hope I'm not the first one that got this problem so I would appreciate any suggestion on how to solve this issue. Since I am using ASP.NET MVC 4 there was an idea to use a dedicated controller with view which to get called first just for the sake of showing the loading image and then moving to the requested view. Even though this idea seems interesting I didn't have the time to think it over, it also sounds a pretty complicated, but anyways, all help will be appreciated.
When faced with the same issue, we did as you mentioned: Load a super-light-weight page first with a tiny loading icon & "Loading..." text, then called back to the server to pull down the heavy content in chunks using ajax.
If you content is really heavy, it's also worth mentioning that you need make sure you have gzip compression turned on at your web server layer also.
Don't block the rendering of the DOM. Load the page and call your scripts right before the closing body tag and attach to an event like DOMContentLoaded or window.load (if you're using jQuery, that would be $(document).ready). In other words, you should allow the page to load completely, even if it's empty, before running any of your JavaScript.
Then, don't worry about writing the "Loading" div dynamically. Just include it in the rendered HTML and hide it initially. The first thing your JavaScript will do, before issuing any AJAX calls, is to show this "Loading" div.

AngularJS initial route controller not loaded. Subsequent ones are fine

I have a HTML5 pushState app. For some reason or another, the controller responsible for the route that I hit initiall is not loaded when I first load the up. If I click around, everything is fine.
I'm not exactly sure why this is happening, a demo can be viewed here: http://osumo.paas.allizom.org
This used to be okay. I did some work today on some components that had nothing to do with the $routeProvider and it just broke.
Does anyone have any ideas?
Thanks.
So to answer this question, it gets quite.. interesting. The problem actually came from this line: https://github.com/shuhaowu/osumo/commit/c539d8048696152ad75f13a6d965160381b89a21#L2L22
The reason of this is actually quite logical, though it is a big pain to figure out. Basically I'm doing things that I should not be doing (as often that happens).
So first thing first, the code is setting a locale when a service is being initialized. That itself is no big deal, as we want to set the locale to navigator.language. This code is here: https://github.com/shuhaowu/osumo/blob/c539d8048696152ad75f13a6d965160381b89a21/static/js/develop/services/appservice.js#L165
When this gets called, an event gets triggered and this event will cause a bunch of directive to change its texts. Again, this is no big deal. https://github.com/shuhaowu/osumo/blob/c539d8048696152ad75f13a6d965160381b89a21/static/js/vendors/l10n.js#L23
Here comes the trouble. The version of the code that's problematic included $rootScope.$$phase || $rootScope.$apply() as when the library is designed it is assumed that setLocale could be called outside of the angular world and it wants to be a little magical so that things just works when the event fires. While I cannot be certain exactly what is going on in Angular, my guess would be that $scope.$$phase is not set at this point as we're still initializing the different components. Calling $apply here caused angular to start applying to the page, which causes the page to never load.
Lesson learned: don't do stupid stuff.

Execute JavaScript function after SharePoint is initialized

I have a custom JS script which I load into SharePoint and have problems to get my init method executed after SP is finished with its own initializing.
_spBodyOnLoadFunctionNames
I tried the "official" way first and added my function name to the list of executed functions after body load with _spBodyOnLoadFunctionNames.push("myInitMethod"); but that does not fire on every page load, I can't rely on that.
ExecuteOrDelayUntilScriptLoaded
Then I tried to use ExecuteOrDelayUntilScriptLoaded(myInitMethod, "sp.js"); function but it does not fire on every page load either.
Both ways work - but not every time. I assume that my script is loaded sometimes before the SP is initialized. This happens mostly on Chrome but on IE as well.
How can I make sure that my script is executed when SP is ready?
Note: There is an interesting behaviour when the page is loaded and the SP object is not fully initialized (the registered functions in ExecuteOrDelayUntilScriptLoaded has not been called): As soon as I click on the "Navigate Up" anchor in the page (where you can see the hiarchy of the subsites) the following files gets loaded and my init function (registered in ExecuteOrDelayUntilScriptLoaded) gets called!
core.debug.js
sp.core.debug.js
ScriptResx.ashx
sp.ui.dialog.debug.js
sp.runtime.debug.js
sp.debug.js
So everything is fine after that click - but why not on pageload as it should be?
It seems that this behaviour is related to some issues between SP 2010 and Google Chrome - I don't have this issues on other browsers.
This is a timing issue that somehow occurs only on non-IE browsers.
See http://withinsharepoint.com/archives/256 for an explanation and very easy fix.
Hey I came across your question when I was looking for a way to delay my JavaScript from loading until sp.js has.
The reason your code you provided works some of the time is because (some of the time) SharePoint doesn't initialize all of it's codebase. This is a big problem in Google Chrome, but can happen in other browsers (non-IE) as well. To work around that particular issue you can do something like this:
if (typeof(_spBodyOnLoadWrapper)!='undefined'){_spBodyOnLoadWrapper();}
I put mine inside of $(document).ready().
And thanks for answering my question :)

Categories