72

I was wondering what would be the best way to execute a java-script code only on specific pages.

Let's imagine we have a template-based web-site, rewrite rule for the content ist set, jquery available and it basically looks like this:

  <!DOCTYPE html>
  <html>
   <head>
    <script src="script.js"></script>
   </head>
   <body>
    ...
    include $content;
    ..
   </body>
</html>

content 'info' contains a button, we want something to happen on click, content 'alert' should give us a message when you hover a text field.

What is the best way to trigger these actions, without running into an error, because the object is not found?

Option one: using window.location.pathname

 $(document).ready(function() {
      if (window.location.pathname == '/info.php') {
          $("#button1").click(function(){
            //do something
          })
      }else if(window.location.pathname == '/alert.php'){
           $("#mytextfield").hover(){
             alert('message');
           }
    }

Option two: checking if elements exist

$(document).ready(function() {
  if ($("#button1").length > 0) {
      $("#button1").click(function(){
        //do something
      })
  }else if ($("#mytextfield").length > 0){
       $("#mytextfield").hover(){
         alert('message');
       }
}

Option three: include the script in the loaded template

//stands for itself

Is there a better solution? Or do I have to get along with one of these solutions?

Your experience, usage, or any links related to this topic are appreciated.

//EDIT:

I might have choosen a bad example, the actual code would be somethin like:

    mCanvas = $("#jsonCanvas");
    mMyPicture = new myPicture (mCanvas);

where the myPicture constructor get's the context of the canvas element, and throws an error, if mCanvas is undefined.

Johannes Staehlin
  • 3,680
  • 7
  • 36
  • 50
  • 3
    A good idea would be to only include javascript on the pages that require it and `$(document).ready` may be called more than once on a page, so you should be safe here. – Ian Bishop Mar 06 '12 at 05:30
  • You don't need to check if the element exists before assigning event handlers if you're using jQuery: `$("someselector").click(...)` will apply the click handler to the _zero or more_ elements that matched "someselector" - it doesn't give an error if none matched. – nnnnnn Mar 06 '12 at 05:31
  • @IanBishop : That's option three :) - >load js with template @ nnnnnn : See my edit, but you're right, concerning 'only' click actions – Johannes Staehlin Mar 06 '12 at 05:38
  • @JohannesStaehlin My general approach (from my understanding the standard one) of when to use internal vs external javascript is one of convenience. If it's shared between more than one page, make it a file. If it's length is encumbering, make it a file. Otherwise, you can get away with embedding it on the page. Regardless, including scripts only on the page that you need them is the right approach to take here. It's far more robust and maintainable than any of the other options. – Ian Bishop Mar 06 '12 at 05:43
  • 2
    Consider for instance, you have 3 of these 'conditional' includes. Page A uses 1,2. Page B uses 1. Page C uses only 3. Option 1 leaves you with a mess of conditionals check which page you're on and which functions to call. Option 2 leaves you with a different mess of conditionals to check what scripts should be run. Further, if you have conflict in ids - you're in trouble. If you have say, an additional verification for submitting a form - you could have two buttons with the id 'submit'. But only one of them requires the additional verification. – Ian Bishop Mar 06 '12 at 05:47
  • Thanks, I think it's just hard to get rid of this 'way of thinking', to put all js-files into the header element. +1 – Johannes Staehlin Mar 06 '12 at 05:52
  • 4
    Another common approach is add class names to html or body tag. – charlietfl Mar 06 '12 at 05:56

5 Answers5

78

Set a class attribute to your body tag.

<body class="PageType">

And then in your script..

$(function(){
  if($('body').is('.PageType')){
    //add dynamic script tag  using createElement()
    OR
    //call specific functions
  }
});
Robin Maben
  • 22,194
  • 16
  • 64
  • 99
  • 3
    I think it's great practice to add class names to every page.. both for js and for css – Damon May 11 '12 at 14:57
  • Not a bad idea until someone renames a class – Neil Mar 19 '14 at 10:11
  • 12
    Great answer but `hasClass()` performs much better than `is()`. If you're running through multiple conditions to determine which page you are on out of the many that exist I would suggest switching the function that you're using. – JLF Jun 12 '15 at 14:32
  • 1
    such a neat answer. helped me out a lot. – z0mbieKale Jul 26 '16 at 10:03
  • 8
    Alternatively a `data` attribute can be used. I prefer using `data-*` for selectors that are going to be used in JS, this way I know that the element interacts in some way with JS. Add a `data-page` attribute to body, then just check `document.body.getAttribute('data-page') == 'pagetype'`. Run this on ready. – doup Sep 22 '17 at 10:17
20

I would use the switch statement and a variable. (I'm using jQuery!)

var windowLoc = $(location).attr('pathname'); //jquery format to get window.location.pathname

switch(windowLoc){      
  case "/info.php":
    //code here
    break;
  case "/alert.php":
    //code here
    break;
}

//use windowLoc as necessary elsewhere

This will allow you to change what "button" does based on the page that you're on. If I understood your question correctly; this is what I would do. Also, if I had were serving large amounts of javascript, I would simply add a new JS file completely.

var windowLoc = $(location).attr('pathname'); //jquery format to get window.location.pathname

switch(windowLoc){      
  case "/info.php":
    var infoJS = document.createElement('script');
    infoJS.type = 'text/javascript';
    infoJS.src = 'location/to/my/info_file.js';
    $('body').append(infoJs);
    break;
  case "/alert.php":
    var alertJS = document.createElement('script');
    alertJS.type = 'text/javascript';
    alertJS.src = 'location/to/my/alert_file.js';
    $('body').append(alertJs);
    break;
}

Hope this helps -

Cheers.

Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
13

A little different approach than checking the URL path : You can group page specific event handlers in a single function and then in each include, have a domready which will call these functions.

Eg: in script.js you have two functions (outside domready) viz. onPage1Load() and onPage2Load().

While in your page1.php you have a $(document).ready(onPage1Load) and so on for other pages. This will make sure that unintended event handlers are not registered.

Niks
  • 4,802
  • 4
  • 36
  • 55
  • i think that this is the easiest way to do the things write and it is easy to read and debug. Option one i think is like front controller not bad but can result into a mess.Also when there are aliases that is going to be hard.That may work if there is a framework to automate this somehow... The method with page class seems also good idea. – GorillaApe Apr 09 '12 at 17:17
  • 1
    What worked best for me was having an inline script that called the function only on that page. – AntonB Jan 27 '17 at 22:19
3

You can also use vanilla javascript to do the same

console.log(window.location.href);
const host = "http://127.0.0.1:5500/";
// JAVASCRIPT FOR INDEX PAGE 
if (window.location.href == host + 'index.html') {
    console.log("this is index page");
}

// JAVASCRIPT FOR ORDER PAGE 
if (window.location.href == host + 'order.html') {
    console.log("this is order page");
}
MD SHAYON
  • 7,001
  • 45
  • 38
1

You can use Require js (RequireJS is a JavaScript file and module loader) and load script if they only needed. Link is http://requirejs.org/, I know using require js not so much easy.

Sanjib Debnath
  • 3,556
  • 2
  • 22
  • 16