SmoothState keeping js files for all pages, some functions being repalced - javascript

Lots of pages on my site have their own javascript files that are included in their respective pages.
SmoothState provides the onAfter handler to re-initialize plugins, and some of these pages' javascript files have their own "init function" that initializes whatever plugins they are using. So obviously, the goal would be to invoke these initialization functions in the onAfter handler.
It appears however that SmoothState is keeping each pages javascript file loaded. What this results in, is that some of these scripts have functions of the same name (but obviously different function) and this is causing some of them to be "replaced."
For example, the init function is never invoked correctly because the last loaded page overrides it.

I toyed around with this a bit.
You need to place the <script> tags that are unique per page inside the container you provide to smoothstate during its initialization. I.e, inside the "main" div. Maybe this is in the documentation somewhere, but I did not see it.
Everything outside of the main div will not be reloaded.

Related

Where to put script references for widgets (partial page)

Working on MVC5 asp.net website.
I have a "dashboard" page that allows the user to place pre-defined "widgets" on the page. These widgets are simply MVC 5 partial pages (Razor). I really wanted each widget to be "self-contained" so all references, scripts, etc... are within the widget's cshtml file. BUT, the main "dashboard" page also needs certain references to jQuery, bootstrap, etc...
Of course, doing this, I could encounter conflicts, duplicate references (one from main page, one from widget), etc....
Question: What is the preferred method for this scenario? Should references like jQuery and bootstrap be JUST on the main "dashboard" page? What about javascript or jQuery code that is in the widget itself? Should this remain in the widget? If so, will I encounter the issue where it doesn't have jQuery defined (because it's in the parent page), etc...?
Any thoughts on this would be appreciated?
Thanks!
**** UPDATE ****
TO further clarify: If I put the scripts, references, etc (specific to the widget) at the bottom of the widget, then when the partial page is rendered on the main page, the scripts, etc.. are not rendered at the bottom of the main page. This causes my code to act funny because of the order that things are rendered. This is one reason I ask this question. Hope this makes sense. Thanks.
Put the script code and references that are global to the application , that are used everywhere and that are not specific to a widget in the most outer page.
What i would do, is i would bundle all my script references in one place and add that bundle link to the dashboard page, this makes your code cleaner and your page will have less external references thus a better client side performance.

Maddening scope issue

Little things like this drive me crazy!
Working with a typical Joomla website and all it's complexity.
Start with a functioning website. Edit a particular javascript file of a template to add a simple function:
function socialShare(title, url) {
alert("goop!");
}
I reference it in a link:
<a class="icon-facebook"
onclick="socialShare('blog-entries', '11-blog-article/15-oppressive-tyranny&title=Triumph Over Tyranny')"> </a>
The function is included along with 37 other external scripts in a file at the end of the page, included within the body element like this:
<script src="/bts/templates/vg_progressive/js/articleRev.js"></script>
I inserted the sociaShare function definition as the first thing in the include articleRev.js file. The list of external scripts include core functionality like bootstrap, jquery etc etc.
I can see the function in the included script file with firebug's debugger & the include line in the page source near the bottom. BUT IT DOESN'T GET EXECUTED!! If I include the exact same function within a element anywhere on the page it works just fine. For some reason the instance in the external script file is not within the scope of that page / article, tho I can see it clearly in the page source.
I can also put the function within script tags as the last thing inside the body and it is within scope and works fine. I discovered I can define the function in a different included javascript file that is found in the very same folder and it also works fine.
Like I said, things like this make me pull my hair out! What can cause this behavior? How can I narrow it down?
As per Ed Cotrel, here are 2 files which [may] be helpful, tho I don't think so. Rename articleRev.txt to .js and pageSrc.txt to pageSrc.html. As for your comments Ed, I believe I've stated the issue as clearly as I can.
The desired behavior is to see an alert box when the anchor tag is clicked. Simple. The anchor tag displays a social media icon based on one of the class definitions. The onclick attribute should call the javascript function socialShare and display an alert box containing a text message with the 2 parameters. The alert never shows up. If the socialSharing function is moved to the main.js script file located in the same folder and included the same way in the same place in the page flow it works. Is that clearer?
1) http://thecomingbitsharesrevolution.website/media/articleRev.txt
2) http://thecomingbitsharesrevolution.website/media/pageSrc.txt

When is requireJS done loading all modules

I'm wanting to wait for all of my requireJS modules to finish loading before firing an event.
Is there an event, or a way to listen for all of my requireJS modules to finish loading?
The details:
I'm trying to add custom dimensions to my Google Analytics, and then send a pageview. This is easy to do on all pages if I set the same dimensions but in some of my requireJS modules I want to change the dimensions BEFORE the page view.
I've got my template javascript which is run on every single page, I want it to do:
LISTEN_FOR_MODULES_TO_LOAD(function() {
$(document).trigger('set-your-analytics-dimensions-yall');
ga('send', 'pageview');
});
Then on some of my subpages I've got modules doing:
$(document).on('set-your-analytics-dimensions-yall', function() {
ga('set', 'dimension');
});
I want the flow to be:
Listen for all my modules to finish loading
Ask other modules to set their dimensions and other values
Set pageview
The problem is that I have no way to listen for all my requirejs modules to load.
Things I've considered:
DOM Ready
This doesn't work because DOM Ready can fire before or after all JavaScript modules are loaded.
window.onload
This isn't reliable and can fire multiple times. If an image is added to the page 10 minutes later it can fire again. If an external resource never loads this event will never fire.
Is there an options I have missed? Or something I have missed entirely from requireJS?
This question is over two years old, but it was the only relevant question I found on SO when I had the same problem. I eventually found an answer that works for me. Here's some background: I have a dynamically generated page, with multiple and varied numbers of page sections that may include modules loaded by require.js. Picture a page with a variable number tiles for example, and each tile may load scripts using require. Now when all tiles are loaded, I want to run some other javascript. But how do you tell when require.js is done loading everything, including modules that may be loaded as sub modules?
Looking at the require.js code, I see that it contains a registry, which appears to be a list of pending loads and their callbacks. So when the registry is empty, require.js is done loading and done running callbacks. At least it appears that way, and this works for me. Basically at the bottom of the page (below any other calls to require()), I add this javascript:
function run_final_action($) {
if ($.isEmptyObject(require.s.contexts._.registry)) {
do_final_action();
}
else {
setTimeout(run_final_action, 100);
}
}
require( ['jquery'], function ($) { run_final_action($) } );
Here I am using jquery because I already have it loaded in the page, but it isn't really necessary. The basic idea is just to check the registry for the default context in requirejs (named "_") and when it is empty, that means requirejs has no pending scripts to load or callbacks to run. This works for my use case anyway.

hiding container until fully loaded not working with cached images

I have a website with a background and a main container. I wanted to hide the container until the whole page has been loaded. so i added
#cover{opacity:0}
at the start of the page and
$(window).load(function() {
$('#cover').css('opacity','1');
});
at the end, just before </body> tag. It works perfectly when page is loaded for the first time.
PROBLEM : If I load the same page once more, it shows all the images and text scattered throughout the page. It works fine once completely loaded. certainly this type of behavior is caused by cached images. but all the images are inside the main container which has opacity:0, This has completely confused me.
UPDATE 1:
I am using turn.js to convert the whole container into a book, i want the book become visible when the book is ready i.e. both loading of images and javascript initialization has completed.
UPDATE 2:
This is how i am checking for "images loaded" and "javascript initialized". it worked as i wanted it to. is this a good way to handle the situation?
$(window).load(function(){
$(window).ready(function() {
$('#cover').css('opacity','1');
});
});
$(window).ready(function(){
$(window).load(function() {
$('#cover').css('opacity','1');
});
});
The problem may be related to your $('window').onload();
Take some time and read this SO post.
what-is-the-difference-between-window-load-and-document-ready
load is called when all assets are done loading, including images.
ready is fired when the DOM is ready for interaction.
From the MDC, window.onload:
The load event fires at the end of the document loading process. At
this point, all of the objects in the document are in the DOM, and all
the images and sub-frames have finished loading.
From the jQuery API
documentation, .ready( handler ):
While JavaScript provides the load event for executing code when a
page is rendered, this event does not get triggered until all assets
such as images have been completely received. In most cases, the
script can be run as soon as the DOM hierarchy has been fully
constructed. The handler passed to .ready() is guaranteed to be
executed after the DOM is ready, so this is usually the best place to
attach all other event handlers and run other jQuery code. When using
scripts that rely on the value of CSS style properties, it's important
to reference external stylesheets or embed style elements before
referencing the scripts.
Let me know if this change works.
You do not call the same block in your CSS (#container) and in your JS (#cover).

Execute page-specific javascript code after PJAX success

Here's my conundrum:
My website uses PJAX to load HTML into the '#main' container for each page.
Each page has its own specific javascript file. E.g: 'dashboard.index.js', 'inbox.index.js' and so on.
Note: All libraries are preloaded on the first load of the page through PreloadJS to avoid javascript compilation overhead.
The first load of the page is perfect, no worries, since it is a normal HTML load.
However if i come back to this page again, PJAX won't reload the javascript file, given it's already in the DOM.
What i tried so far & didn't work perfectly:
Place javascript file at the bottom of 'main' container. PJAX transfers it to the 'HEAD' of the DOM and won't load it the second time around.
Place in-line scripts in the 'main' container to execute functions of each page. Fails since the code is executed before JS libraries are loaded.
Bind 'PJAX success' event and execute function. Unable to determine which function to execute based on current loaded page.
Hence, my question:
Is there any strategy to load specific javascript files associated to each page?
When loading HTML from pjax, i added a 'data-js' attribute to the div, which contained the name of the function to call upon successfully loading HTML.
Then it was just a matter of using the 'pjax:success' event to call the function.

Categories

Resources