JS knockout plays fine with Ratchet and push.js until I add a data transition

I use the Ratchet.js / push.js library to create a user interface for a mobile web application. In this library, links are processed by "clicking" the downloaded file into the ".content" DOM ​​element, rather than loading the entire page. However, push.js does not load the scripts that it finds when the page loads, which disables my Knockout.js code.

I found a solution here on StackOverflow that works very well - just add an event listener for the push event. I changed it so that it can load any script on several pages and therefore it works with external script files:

window.addEventListener('push', function () { var scriptsList = document.querySelectorAll('script.js-custom'); // Add a "js-custom" class to your script tag for (var i = 0; i < scriptsList.length; ++i) { // Handle scripts in separate files by assigning the script file name to its id. // We save it in a variable because the ".done" callback is asynchronous. scriptName = scriptsList[i].id; // IMPORTANT: Only one loadable script per page! $.getScript("/path info here/" + scriptName) .done(function (script, textStatus) { eval(script); }) ... error handling ... } }); 

On the target HTML page of the script, class and identifier tags are set, so they work with the above:

  <script src="Challenge.js" class="js-custom" id="challenge.js"></script> 

Note also that Knockout bindings must occur with a specific DOM element name so that knockout is not confused:

 ko.cleanNode($("#ChallengePage")[0]); ko.applyBindings(challengeFn, $("#ChallengePage")[0]); 

We use cleanNode to avoid "already related" errors.

OK! So all of this works great, and I hope that anyone struggling with this will find this useful.

HOWEVER, when a link gets a transition:

 <a href="challenge.html" data-transition="slide-in">.... 

It then breaks down into “Unable to read the“ nodeType ”property from undefined. I thought that maybe it was just a problem of waiting for the transition to complete, but even if I replaced the script evaluation with:

 scriptContents = script; setTimeout(function () { eval(scriptContents); }, 1000); 

It does not help.

Any advice or help would be greatly appreciated! I don’t need to “click” the pages if I don’t use the transitions, so I hope that someone will have the last key to make it all work!

UPDATE: an error occurred because the call to "document.querySelectorAll" when using a transition uses the current document, not the one that was clicked. Also, using "webkitTransitionEnd" as my event also works, but it does not fix the document problem. That way, I can do this work, but for just one transition - now I have no way to load a document. Ideally, a solution that works if the links use the transition or not is what I'm looking for.

+3
javascript jquery html ratchet-2
source share
1 answer

The combination of Ratchet and Knockout is likely to be popular in the coming months, so I hope others find this solution.

To combine the Ratchet.js and Knockout.js libraries, it only requires that Ratchet.js (via Push.js) will try to control the transition to the page. During the transition, JavaScript on your landing page, including Knockout, will not be launched unless you specifically do so. This is what this solution makes: it allows you to load and run your JavaScript code for knockout, although Ratchet controls the transition of the page.

In my solution, we always place JavaScript in a separate file and implement a content security policy that prevents the execution of any JS code on the page. This is just good safety hygiene and helps reduce the attack surface for XSS attacks. Thus, the solution below 1) assumes that JS is in a separate file and 2) assumes that the HTML and JS files have the same name and path, with the exception of the extensions (like what the .js file is processing, for example ASP.NET for HTML file).

On your “root” page - the one that launches all your interactions with other pages of your mobile web application, put the following function. It will download the corresponding .js file whenever the corresponding .html file is downloaded using Ratchet:

 window.addEventListener('push', function (params) { var targetPage = params.target.document.baseURI.replace(".html", ".js"); $.getScript(targetPage) .done(function (script, textStatus) { eval(script); }) .fail(function (jqxhr, settings, exception) { alert("Error loading script: " + exception); }); }); 

Note that you will need to apply Knockout bindings to the named and unique div on your HTML page (usually a div that lives directly under DivX Ratchet.content). This is due to the fact that every page load should apply Knockout bindings only to downloadable HTML.

 ko.cleanNode($("#DivPageName")[0]); ko.applyBindings(KnockoutFn, $("#DivPageName")[0]); 

UPDATE: I found that this solution is sometimes "confused" when pages are popped and popped from the history stack. I decided not to use it, although it seems that there are about 97%. If someone has improvements that will make it completely reliable, I’m all ears!

+3
source share

All Articles