Javascript within Javascript

Hi all,

I’m trying to embed this code:

<script type="text/javascript" src="http://sdscdn.userreport.com/popup.min.js"></script>
<script type="text/javascript">try { _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa'); } catch(err) {}</script>

Inside this code:


<script type="text/javascript">
    $(function(){
        var value = $.cookie('the_cookie'),
            date = null;
        if (/^\\d+$/.test(value || "")) {
             date = new Date();
             date.setTime(value);
        } else if ((value || "") == "") {
             $.cookie('the_cookie', new Date().getTime());
        }

        if (null != date /* && date meets your requirements */){
			
CODE TO BE INSERTED HERE!!!

        }
    });
</script>

I’m trying to put it after the “If” statement, where I have written “Code to be inserted here”

The idea is, the first piece of code is NOT shown if it is the first time the user has visited the site… only if it is the 2nd.

Can somebody please show me the correct syntax to use?

Regards,

I use a requireOnce function to conditionally append scripts to the HEAD of the document. Note that the scripts will be executed as soon as they’re created, as if there were actual SCRIPT tags in the HEAD.

Usage:


<script type="text/javascript" src="requireOnce.js"></script>
<script type="text/javascript">
  if (userHasVisited) {
    requireOnce('returningVisitor.js');
  }
  else {
    requireOnce('newVisitor.js');
  }
</script>

requireOnce.js:


window.requires = [];

requireOnce = function()
{
  var uri, ext;
  for (var i = 0; i < arguments.length; i++) {
    uri = arguments[i];
    if (window.requires.indexOf(uri) == -1) {
      window.requires.push(uri);
      ext = uri.substr(uri.lastIndexOf('.') + 1).toLowerCase();
      switch (ext) {
        case "js":
          _requireScript();
          break;
        case "css":
          _requireStylesheet();
          break;
        default:
          break;
      }
	}
  }

  function _requireScript()
  {
    var script = document.createElement('SCRIPT');
    with (script) {
      setAttribute('type', 'text/javascript');
      setAttribute('src',  uri);
    }
    document.getElementsByTagName('head').item(0).appendChild(script);
  } // _requireScript

  function _requireStylesheet()
  {
    var link = document.createElement('LINK');
    with (link) {
      setAttribute('rel',  'stylesheet');
      setAttribute('type', 'text/css');
      setAttribute('href', uri);
    }
    document.getElementsByTagName('head').item(0).appendChild(link);
  } // _requireStylesheet

}; // requireOnce

Sorry to sound thick but JS is not my area of expertise… is the if statement you have in your example standard or is it a function you have written?

Would I be able to use if(userHasVisited) for my example? Or is there some additional setup required?

I appreciate your help - I just can’t get my head around how my example and your example can merge to create what I am looking for.

You would use your own if statement to check the cookie as in your original post. Sorry about the shorthand. :smiley:

So something like this:

<script type="text/javascript">
    $(function(){
        var value = $.cookie('the_cookie'),
            date = null;
        if (/^\\d+$/.test(value || "")) {
             date = new Date();
             date.setTime(value);
        } else if ((value || "") == "") {
             $.cookie('the_cookie', new Date().getTime());
        }

        if (null != date /* && date meets your requirements */){
			
requireOnce('returningVisitor.js');

        }
    });
</script>

Then my returningVisitor.js file would be:


<script type="text/javascript" src="http://sdscdn.userreport.com/popup.min.js"></script>
<script type="text/javascript">try { _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa'); } catch(err) {}</script>

Am I understanding you correctly?

Don’t put the SCRIPT tags in the JavaScript files, just the actual code. You can require more than one file with one function call:


requireOnce('file_1.js', 'file_2.js', 'file_3.js');

So I could do this:

<script type="text/javascript">
    $(function(){
        var value = $.cookie('the_cookie'),
            date = null;
        if (/^\\d+$/.test(value || "")) {
             date = new Date();
             date.setTime(value);
        } else if ((value || "") == "") {
             $.cookie('the_cookie', new Date().getTime());
        }

        if (null != date /* && date meets your requirements */){
			
requireOnce('returningVisitor.js', 'http://sdscdn.userreport.com/popup.min.js');

        }
    });
</script>

Then I could put this in my retuningVisitor.js :

try { _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa'); } catch(err) {}

Is that right?

I’ve tried doing the above but it doesn’t work.

The script is supposed to execute upon the visitor’s 2nd visit to my site. However, it is not executing.

If I just put this on the page:

<script type="text/javascript" src="http://sdscdn.userreport.com/popup.min.js"></script>
<script type="text/javascript">try { _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa'); } catch(err) {}</script>

The script executes and I get a usability survery which the user is asked to complete. But putting that on it’s own, without the “offset” script means the usability survey comes up even if it is the user’s first visit to the site, which is a bit pointless since asking someone how they like your site when they haven’t even had a chance to look at it is a bit silly… So I want to wrap that script in an “offset” script so that it only comes up if the user has visited the site before.

Any ideas if there is an easier way to do this - since this way just doesn’t seem to work - unless there’s something wrong with the script I am using.

Anyone?

It looks like you’re trying to (a) check for the existence of a cookie; if there is no cookie, then the visitor has never come here before, and you want to do nothing (other than set that cookie); but if there is a cookie, which means this is at least the second time they’ve visited, then (b) load a script, and (when that script is loaded) execute your try-catch.

Is that right? (If so, then how do you want to handle the third, fourth, etc. time they’ve visited? Just keep showing the survey?)

The first part, checking for a cookie, is much easier than you’re making it out to be. I think all you need to is this:


function doesCookieExist(cookieName) {
    // convert the cookie value to a boolean
    // if it does exist, this'll be true; otherwise, false
    return !!$.cookie(cookieName);
}

Then you can have a different function that handles loading the script and running the try-catch. The problem with using the requireOnce function is that it didn’t guarantee the order of the scripts you passed to it. Your try-catch could have tried to execute before the external script loaded.

For simplicity sake, I suggest using Dustin Diaz’s $script.js. It’s really small, and it allows you pass a function that will only execute once the script has loaded:


function scriptLoaded() {
    try {
        _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa');
    } catch (err) {}
}
$script('http://sdscdn.userreport.com/popup.min.js', scriptLoaded);

So when you put it all together, here’s what it would look like:


<!-- load the script loader -->
<script src="path/to/script.js"></script>

<script>
function doesCookieExist(cookieName) {
    return !!$.cookie(cookieName);
}

function scriptLoaded() {
    try {
        _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa');
    } catch (err) {}
}

if (doesCookieExist('the_cookie')) {
    $script('http://sdscdn.userreport.com/popup.min.js', scriptLoaded);
} else {
    // set the cookie, so that when they return, they can fill out the survey...
    $.cookie('the_cookie', 'yepper', { expires: 365 });
}
</script>

Hi,

Thanks for the reply.

Yes - that is exactly what I want to do. The survey has it’s own way of handling repeat visitors which is already built into their javascript file so on the 3rd, 4th 5th and subsequent visits it only displays a “Feedback” symbol on the left of the page instead of the actual survey popup.

Just one question - The first line of your example “Load the script loader” points to a javascript file - which file should I be pointing this to? What is the script loader?

Regards,
Chris

The script loader is called $script.js. What you would do is download it ([url=https://github.com/ded/script.js/blob/master/dist/script.min.js]here’s the minified version of $script.js), save it somewhere on your own server, and then load it as you would any script:


<!--
It's a little confusing because the filename doesn't
have the $, but that's what you're loading here: -->

<script src="local/path/to/script.js"></script>

Hmmm

It still doesn’t seem to be working. I have done exactly as you have said.

This is what is on the page:


<!-- load the script loader -->
<script src="http://ivegotkids.com/wp-content/themes/thepink/usability.js"></script>

<script>
function doesCookieExist(cookieName) {
    return !!$.cookie(cookieName);
}

function scriptLoaded() {
    try {
        _bvt.initSite('cd46ee4c-d008-40e9-bea4-b09fe7f792fa');
    } catch (err) {}
}

if (doesCookieExist('the_cookie')) {
    $script('http://sdscdn.userreport.com/popup.min.js', scriptLoaded);
} else {
    // set the cookie, so that when they return, they can fill out the survey...
    $.cookie('the_cookie', 'yepper', { expires: 365 });
}
</script>

And this is what is in the referenced js file (usability.js)


/*!
  * $script.js Async loader & dependency manager
  * https://github.com/ded/script.js
  * (c) Dustin Diaz, Jacob Thornton 2011
  * License: MIT
  */
!function(a,b){typeof define=="function"?define(b):typeof module!="undefined"?module.exports=b():this[a]=b()}("$script",function(){function s(a,b,c){for(c=0,j=a.length;c<j;++c)if(!b(a[c]))return m;return 1}function t(a,b){s(a,function(a){return!b(a)})}function u(a,b,c){function o(a){return a.call?a():f[a]}function p(){if(!--m){f[l]=1,j&&j();for(var a in h)s(a.split("|"),o)&&!t(h[a],o)&&(h[a]=[])}}a=a[n]?a:[a];var e=b&&b.call,j=e?b:c,l=e?a.join(""):b,m=a.length;return setTimeout(function(){t(a,function(a){if(k[a])return l&&(g[l]=1),k[a]==2&&p();k[a]=1,l&&(g[l]=1),v(!d.test(a)&&i?i+a+".js":a,p)})},0),u}function v(a,d){var e=b.createElement("script"),f=m;e.onload=e.onerror=e[r]=function(){if(e[p]&&!/^c|loade/.test(e[p])||f)return;e.onload=e[r]=null,f=1,k[a]=2,d()},e.async=1,e.src=a,c.insertBefore(e,c.firstChild)}var a=this,b=document,c=b.getElementsByTagName("head")[0],d=/^https?:\\/\\//,e=a.$script,f={},g={},h={},i,k={},l="string",m=!1,n="push",o="DOMContentLoaded",p="readyState",q="addEventListener",r="onreadystatechange";return!b[p]&&b[q]&&(b[q](o,function w(){b.removeEventListener(o,w,m),b[p]="complete"},m),b[p]="loading"),u.get=v,u.order=function(a,b,c){(function d(e){e=a.shift(),a.length?u(e,d):u(e,b,c)})()},u.path=function(a){i=a},u.ready=function(a,b,c){a=a[n]?a:[a];var d=[];return!t(a,function(a){f[a]||d[n](a)})&&s(a,function(a){return f[a]})?b():!function(a){h[a]=h[a]||[],h[a][n](b),c&&c(d)}(a.join("|")),u},u.noConflict=function(){return a.$script=e,this},u})

This is the page I have tested it on:

http://ivegotkids.com/submitarticles

You can see there when you load that page, no survey comes up (which you’d think was okay if you were a first time visitor) but when you reload the page, you should get the survey but you don’t.

I’ve done something wrong :-s

Ach, forgot to mention that $.cookie is a freaking plugin. So that’s another script that you’ll need to save to your server and load yourself:


<script src="path/to/jquery.cookie.js"></script>
<script src="http://ivegotkids.com/wp-content/themes/thepink/usability.js"></script>
<script>
// THEN do all the checking...

Also, as I was looking through your source, I noticed that your j4m slider seems to get loaded twice: You have two links to jquery-1.4.2.min.js, two links to jquery-ui-1.7.3.custom.min.js, and two <script> blocks that seem to initialize the slider (lines 92 and 432 in the HTML source). FYI

Yeah there’s quite a bit of javascript tweaking to do to optimize the entire site - the J4M slider isn’t even on that page so it shouldn’t even need to be loaded there… I’ve got a whole list of these little tweaks that need to be made - I’m just working my way through them…

  • Anyway. I’ve made the other changes and it is all working perfectly now - thank you very much :slight_smile:

And now on to the rest of my JS tweaking.