3
  • I am developing a javascript module, which adds a lot of functionality to a complex page.
  • Data binding is done with php.
  • I am putting my js files to the end of my page, as recommended by html5boilerplate

How do I pass data from the server into my js module? The only thing I can think of is: storing the data in some DOM variable and then reading it from the JS file. Like so:

PHP:

 <script type="text/javascript">
     var saveMethodUrl = '<?php echo $this->getUrl("page/save") ?>';
 </script>

JS:

module = (function ($) {
   var url = saveMethodUrl;
   ...

But this seems kinda dirty. Is there a best practice on how to do it?

Sven
  • 6,288
  • 24
  • 74
  • 116
  • Ajax is not an option here. – Sven Jul 09 '13 at 12:45
  • ok. well do you mean you don't like echoing the data into a script tag? – iConnor Jul 09 '13 at 12:47
  • Ajax is the inferior choice to the suggested method as it creates additional network overhead. I'm inclined to say that there is no cleaner way. – Maxim Kumpan Jul 09 '13 at 12:47
  • what about creating a javascript file and creating a json object in that file then echo the link on the page? it's cleaner anyway. don't know if it would be bad for perfomance – iConnor Jul 09 '13 at 12:48
  • JSON is also useful when you want to work with a PHP-array! Take a look at this: http://stackoverflow.com/questions/1808108/how-to-access-php-variables-in-javascript-or-jquery-rather-than-php-echo-vari – Pieter Jul 09 '13 at 12:57

2 Answers2

1

I would, instead, expose a method on your module to set the save method URL and in turn call that method, instead of setting a global variable.

<script type="text/javascript">
window.onModuleLoaded = function(module)
{
    module.setSaveMethodURL('<?php echo $this->getUrl("page/save") ?>');
}
</script>

Then, in your module code you'd make a modification similar to the following: (depending on the design pattern you're using to expose your module)

module = (function ($) {
var url = saveMethodUrl;

var setSaveMethodURL = function(save_url)
{
    url = save_url;

    return url;
}

var returnObject = {
    setSaveMethodURL: setSaveMethodURL
};

//this is executed when the module is loaded via the <script> tag)
//check to see if the moduleLoaded callback is defined
if (typeof window.onModuleLoaded != undefined)
{
    //if the moduleLoaded callback is defined and is a function, call it
    if (typeof window.onModuleLoaded == 'function')
    {
        window.onModuleLoaded(returnObject);
    }

    //if it's defined and is an object, iterate through the object and call
    //each function in the object. (this allows you to add multiple callbacks
    //to be executed when this module is loaded
    else if (typeof window.onModuleLoaded == 'object')
    {
        for (key in window.onModuleLoaded)
        {
            if (typeof window.onModuleLoaded[ key ] == 'function')
            {
                window.onModuleLoaded[ key ](returnObject);
            }
        }
    }
}

//return a reference to your setSaveMethodURL api method
return returnObject;

})();

As far as loading your module asynchronously, you can check out this other stack overflow question about loading javascript asynchronously

Community
  • 1
  • 1
Jim Rubenstein
  • 6,836
  • 4
  • 36
  • 54
  • For that I would have to put my js module from the bottom of the page into the head area, right? – Sven Jul 09 '13 at 12:52
  • You wouldn't have to, you could just put it before the script that calles the module, at the bottom of the page. Or, you could write yourself an event that your module looks for when it loads, utilize that event to call the setSaveMethodURL API and then you can add your php code to set the variable (via the api call in the event) at the top of your page, while still loading the module at the bottom (and even asynchronously if you want) – Jim Rubenstein Jul 09 '13 at 13:06
  • The asynchronous event thingy sounds awesome. Could you please hint me into the right direction with some example code? – Sven Jul 09 '13 at 13:13
  • Edited with code examples with comments and references. In my specific example, I implemented a callback for when the module loads, not so much an event. For most purposes, that's probably fine. Triggering it through an event adds some (minor) complication, which would probably not add you a whole lot of benefit right now. – Jim Rubenstein Jul 09 '13 at 13:32
  • I also had to update the code sample (in case you looked at it between when i posted it originally and right now) to account for the fact that the module hasn't made it to the global namespace just yet (the check for the global loaded callback happens before the module initialization method returns) – Jim Rubenstein Jul 09 '13 at 13:37
1

How about calling a PHP script that returns a Javascript file:

<script src="my_js_variables.php"></script>

And in your my_js_variables.php you have:

<?php

header('Content-type: text/javascript');

$variables = array('saveMethodUrl' => $this->getUrl("page/save"));

echo "var php = " . json_encode($variables);

?>

And you access the variables in your JS file like php.saveMethodUrl.

This actually does not work any differently than your proposed solution, but I think it is cleaner.

Amberlamps
  • 39,180
  • 5
  • 43
  • 53