5

I´m developing a Phonegap app with Ratchet 2.0.2 using push.js for transition between pages. Everything is working smoothly but a couple of hours ago I stumble upon this:

Script tags containing JavaScript will not be executed on pages that are loaded with push.js. If you would like to attach event handlers to elements on other pages, document-level event delegation is a common solution.

After doing more research I found out this: Execute custom script after page loaded with Ratchet\Push.js

Which is almost the same problem I have, however I need to go further because I need to load not only one script, but two (and perhaps more in the future), how can I take advantage of checkPage() to load more than one script?

var checkPage = function(){
    //Only run if twitter-widget exists on page
    if(document.getElementById('twitter-widget')) {
        loadTwitterFeed(document,"script","twitter-wjs");
    }
};

window.addEventListener('push', checkPage);
Community
  • 1
  • 1
Danito
  • 51
  • 1
  • 5
  • Can you add more detail as to what scripts you are trying to load\execute? – Schmalzy Apr 21 '14 at 23:36
  • Sure @Schmalzy: One is JQuery 2.0.1, Handlebars.js and the default index.js that Phonegap uses to load custom scripts. All loaded using tags. Same case as you, if I load an internal page it works perfect, if I load from index.html, push.js interferes. – Danito Apr 22 '14 at 03:41
  • If they are just external libraries, you can still load then on your index page. and they will still be present with another page loads. – Schmalzy Apr 22 '14 at 13:54
  • @Danito, its not that push.js interferes exactly. You shouldn't expect scripts on pages other than index.html to be loaded. Push.js is for loading content, not executing scripts. – kindasimple Nov 19 '14 at 19:26

4 Answers4

6

UPDATE: Also see this question.

Here is a solution that I have tried and it seems to work correctly, but I'm looking for some feedback on if this is the best method or not... please feel free to comment, and I will make updates as needed. I know that eval() is dangerous, but I' not sure how dangerous it is in this case.

On your index\first page place the following script at the bottom of your page, OUTSIDE of the .content div, so that it does not get overwritten by push.js.

<script>
    window.addEventListener('push', function(){
        var scriptsList = document.querySelectorAll('script.js-custom');
        for(var i = 0; i < scriptsList.length; ++i) {
            eval(scriptsList[i].innerHTML);
        }
    });
</script>

Then, on any other page that gets loaded via push.js, just give the script a class of .js-custom. This script must be placed INSIDE the .content div.

<div class="content">
    ...
    <script class="js-custom">
         alert('I was executed!');
    </script>
</div>

The fist script will find and loop through any <script> tags with the .js-custom class and execute it's contents using eval().

Community
  • 1
  • 1
Schmalzy
  • 17,044
  • 7
  • 46
  • 47
  • Thanks Schmalzy! I´ll give it a try and post the results. – Danito May 06 '14 at 13:15
  • Uncaught SyntaxError: Unexpected token < on this line: eval(scriptsList[i].innerHTML); – Danito May 06 '14 at 15:36
  • What does your ` – Schmalzy May 06 '14 at 17:12
  • Just a note: this does not work if your javascript file is loaded separately. The innerHTML is exactly what it says - the content between the script tags – Mark Brittingham May 25 '14 at 17:52
  • Just a reminder. Eval is evil! Be careful while using it. Your script content (loaded via ajax) may have malicious code that works in your current context with eval & result would be a perfect XSS attack. – risyasin Dec 24 '14 at 15:25
2

Here is my version of loading scripts for push.js, adapted from Danito's answer.

I have a 1:1 relationship for html and js files. There will be a thinga.html and thinga.js file. What I decided to do was to add an id of thinga to the content div in the html, like so:

<div class="content" id="thinga">
    ...
</div>

Then, in the initial app setup I attached a function called 'checkPage' to the push global event:

window.addEventListener('push', checkPage);

The checkPage function grabs the id from the content div and checks to see if there a javascript file of the same name, and if so, load it using jQuery's $.getScript() from the scripts/ directory

var checkPage = function(){

    var elm = document.getElementsByClassName("content")[0];
    var script = elm.id;

    if(script) {
        $.getScript("scripts/"+elm.id+".js")
        .done(function( script, textStatus ) {
           console.log( textStatus );
        })
        .fail(function( jqxhr, statusText, errorThrown ) {
            console.log(errorThrown);
            console.log(statusText);
            console.log(jqxhr);
        });
    }
};

This seems to do the trick, at least for my use-case. Just wanted to throw it out there on the off chance that it may help someone else someday.

TheBrockEllis
  • 979
  • 9
  • 19
1

I have found a solution for this problem when i'm working with push.js. What I ended up doing in the end is give each html page i want to load an #description. This means that when i link to the pages i link to contactlist.html#contact.

On my main html page, i add the event listener:

 window.addEventListener('push', pageHandler);

Then in a separate file i run this script.

var pageHandler= function(){
  var page= window.location.hash;

  if (page == '#contact'){
     //Put every script you want to use on this page here. 
  }
  if(page == '#info'){
    //Same here, every script you need for this page. 
  }
};

Don't know if this is the best way, but i feel like I then have good control over my script, and it works.

ComplX
  • 11
  • 1
1

Just put my thoughts here. I made a change for Ratchet.js to make individual js works for each page. Each html has a js file linked. (https://github.com/mazong1123/ratchet-pro)

By using the new ratchetPro.js, we can do followings:

(function () {
    var rachetPageManager = new window.RATCHET.Class.PageManager();
    rachetPageManager.ready(function () {
        window.RATCHET.getScript('js/jquery.js', function () {
             // Put your logic here.
        });
    });
})();

Call window.RATCHET.getScript to load your external js. Once the external js has been loaded, it'll be cached and never load again. However, the callback will always be executed when the page switched in.

Jim Ma
  • 709
  • 5
  • 15