Javascript google adsense rotator

Discussion in 'JavaScript' started by camjohnson95, Nov 12, 2009.

  1. #1
    Just made this adsense rotator script if anyone might find it useful.. scrolls vertically at the moment but will add horizontal option soon, just paste as many ad codes as you want within a div that has an id of adsense_rotator_X with another div nested within that (see first line of highlighted html). Make sure that the ads are all the same size for that set of ads and it will scroll through them at the interval set with time_delay (first line of javscript highlighted code)..

    
    [COLOR="Red"]<div id="adsense_rotator_1"><div>[/COLOR]
    <script type="text/javascript"><!--
    google_ad_client = "pub-0070110787519235";
    /* 468x60, created 11/26/08 */
    google_ad_slot = "0427104727";
    google_ad_width = 468;
    google_ad_height = 60;
    //-->
    </script>
    <script type="text/javascript"
    src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
    </script>
    <script type="text/javascript"><!--
    google_ad_client = "pub-0070110787519235";
    /* 468x60, created 11/26/08 */
    google_ad_slot = "0427104727";
    google_ad_width = 468;
    google_ad_height = 60;
    //-->
    </script>
    <script type="text/javascript"
    src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
    </script>
    <script type="text/javascript"><!--
    google_ad_client = "pub-0070110787519235";
    /* 468x60, created 11/26/08 */
    google_ad_slot = "0427104727";
    google_ad_width = 468;
    google_ad_height = 60;
    //-->
    </script>
    <script type="text/javascript"
    src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
    </script>
    [COLOR="Red"]</div></div>[/COLOR]
    <script type="text/javascript">
    [COLOR="red"]var time_delay = 3000;    // 3 seconds between ads[/COLOR]
    var stopscroll = false;
    window.onload = function() {
        var eDivs = document.getElementsByTagName("div");
        for(i=0; i<eDivs.length;i++) {
            if(eDivs[i].id.substr(0,15)=="adsense_rotator") {
                var script_src = eDivs[i].innerHTML;
                var ad_height = script_src.search("google_ad_height = ");
                ad_height = parseInt(script_src.substr(ad_height + 19, 3));
                var ad_width = script_src.search("google_ad_width = ");
                ad_width = parseInt(script_src.substr(ad_width + 18, 3));      
                with (eDivs[i].style) {
                    overflow = "hidden";
                    height = ad_height+"px";
                    width = ad_width+"px";
                    position = "relative";
                }     
                eDivs[i].setAttribute("ad_height", ad_height);
                var childDiv = eDivs[i].firstChild;
                childDiv.style.position = "absolute";
                childDiv.style.top = "0px" 
                setTimeout("scrollDiv('" + eDivs[i].id + "')", time_delay);          
                eDivs[i].onmouseover = function() { stopscroll = this.id };
                eDivs[i].onmouseout = function() { stopscroll = false };
            }   
        }
    }
    function scrollDiv(whatDiv) {
        var thisDiv = document.getElementById(whatDiv);
        if(stopscroll!=thisDiv.id) {
            var ad_height = thisDiv.getAttribute("ad_height");
            var childDiv = thisDiv.firstChild;
            var topVal = parseInt(childDiv.style.top);
            var number_of_ads = parseInt(thisDiv.getElementsByTagName("iframe").length);
            var d = thisDiv.getAttribute("direction");
            if(d==null) { d = "up";}
            if(d=="up") topVal -= 1;
            else topVal += 1;
            childDiv.style.top = topVal + "px";
            if((topVal % ad_height) != 0) setTimeout("scrollDiv('" + whatDiv + "')", 1);
            else setTimeout("scrollDiv('" + whatDiv + "')", time_delay);
            if(topVal == 0 - (ad_height * (number_of_ads - 1)) && d=="up") d = "down";
            if(topVal == 0 && d == "down") d = "up";
            thisDiv.setAttribute("direction",d);
        }
        else {
            setTimeout("scrollDiv('" + whatDiv + "')", 1)
        }
    }
    //Created By Cam Johnson - 2009
    </script>
    
    Code (markup):
     
    Last edited: Nov 12, 2009
    camjohnson95, Nov 12, 2009 IP
  2. dimitar christoff

    dimitar christoff Active Member

    Messages:
    882
    Likes Received:
    62
    Best Answers:
    0
    Trophy Points:
    90
    #2
    this is cool -- better exposure in less space. and good work on extracting stuff from the ad iframes, very clever :)

    couple of things you may want to look at when you do an animated scroll though.

    using setTimeout("something"); is a bad practice. when using a string, it performs an eval, which launches a new instance of the js interpreter to figure how to treat and compile and run the bit in the speech marks.

    here's an extract from the douglas crockford's book 'js: the good parts':
    don't take his word for it, you can put it to the test anyway or google "settimeout eval".

    it's particularly bad when you do this whilst animating - it will rely more on cpu use, it will not be as smooth and can actually get to be jerky at times... i should know, i have tried doing scrollers a few times :(

    try an anonymous function callback instead:
    
    setTimeout(function() {
        scrollDiv(whatDiv);
    }), nn);
    Code (javascript):
    for example, the bit where you set direction, you can write better like so:
    
    var d = thisDiv.getAttribute("direction") || "up"; // same, if null (== false), then "up"
    Code (javascript):
    parseInt without a radix can be a pain as well--it won't break in this case probably but you should know that in javascript...
    alert(parseInt("08")); // alerts 0!!! its treated as base 8 not base 10...
    alert(parseInt("08px")); // also 0!!!
    // set the radix always...
    alert(parseInt("08px"), 10); // 8!
    Code (javascript):
    that's pretty awful...

    btw, var number_of_ads = parseInt(thisDiv.getElementsByTagName("iframe").length); --> if you don't expect this to be changing midway, then you should cache that as a variable and reference it instead of running it on every frame.

    basically that's a good practice anyway - anything that you'd consider static, don't do repeatedly. setup an init method that gets the right vars and then just reference them (for each instance).

    i think by looking at your code you have tried to make it modular in the sense that it can run for any div that starts with "adsense_rotator". which is ok but you also have just one variable for "stopscroll" which is a global. what would happen if you have 2 advert blocks but one is set to have taller adverts hence would take longer to finish the animation cycle? they all start at same time and then...

    it really needs to be instantiated independently of each other, setAttribute the 'stopscroll' or better yet, write it all as a class and have a new instance for each ad block.
     
    dimitar christoff, Nov 12, 2009 IP
  3. camjohnson95

    camjohnson95 Active Member

    Messages:
    737
    Likes Received:
    17
    Best Answers:
    0
    Trophy Points:
    60
    #3
    Thanks diimitar,
    I'll post the revised code when done.
     
    camjohnson95, Nov 12, 2009 IP
  4. dimitar christoff

    dimitar christoff Active Member

    Messages:
    882
    Likes Received:
    62
    Best Answers:
    0
    Trophy Points:
    90
    #4
    here's something that can start it in the way of refactoring - i think it;s nicer because:
    1. it's namespaced.
    2. it's modular
    3. less calls and better performance during animations
    4. will support blocks of ads independely of each other, you can even have different delays if you want.
    if (!Object.bind) {
        // changes scope as per ECMA specifications for js 1.6, will auto work on new browsers
        Function.prototype.bind= function(owner) {
            var that= this;
            var args= Array.prototype.slice.call(arguments, 1);
            return function() {
                return that.apply(owner,
                    args.length===0? arguments : arguments.length===0? args :
                    args.concat(Array.prototype.slice.call(arguments, 0))
                );
            };
        };
    }
    
    if (!Array.prototype.forEach) {
        // iterates array as per js 1.6, will auto work on new browsers
        Array.prototype.forEach = function(fun /*, thisp*/) {
            var len = this.length >>> 0;
            if (typeof fun != "function")
                throw new TypeError();
    
            var thisp = arguments[1];
            for (var i = 0; i < len; i++) {
                if (i in this)
                    fun.call(thisp, this[i], i, this);
            }
        };
    }
    
    
    var adScroller = {
        timeDelay: 3,
        initialize: function(el) {
            this.ads = [];
    
            var divs = document.getElementsByTagName("div"), dl = divs.length;
            if (!dl)
                return; // no divs
            while(dl--) {
                if ((divs[dl].getAttribute("id") || "").match("adsense_rotator")) {
                    var divInner = divs[dl].innerHTML, ad_height = divInner.search("google_ad_height = "), ad_width = divInner.search("google_ad_width = ");
    
                    ad_height = parseInt(divInner.substr(ad_height + 19, 3));
                    ad_width = parseInt(divInner.substr(ad_width + 18, 3));
    
                    with (divs[dl].style) {
                        overflow = "hidden";
                        height = ad_height+"px";
                        width = ad_width+"px";
                        position = "relative";
                    }
                    var childDiv = divs[dl].firstChild;
    
                    childDiv.style.position = "absolute";
                    childDiv.style.top = 0;
    
                    var adBlock = {
                        element: divs[dl],
                        style: {
                            height: ad_height,
                            width: ad_width
                        },
                        childDiv: childDiv,
                        direction: "up",
                        paused: false // set this to true to run up the timeDelay again.
                    }
                    this.ads.push(adBlock);
                }
            }
            var al = this.ads.length;
            if (!al)
                return; // no ads
    
            this.ads.forEach(function(el) {
                setTimeout(function() {
                    this.scrollAd(el);
                }.bind(this), this.timeDelay * 1000);
            }.bind(this));
        },
        scrollAd: function(adBlock) {
            alert(adBlock.style.height); // old ad_height as attribute in element is now in object
            alert(adBlock.paused);
            alert(adBlock.childDiv.style.top);
    
            // change it... 
            adBlock.childDiv.style.top -= 1; // etc etc, do what you have to do.
       
            // animate it.
            setTimeout(function() {
                this.scrollAd(adBlock);
            }.bind(this), (adBlock.paused) ? this.timeDelay * 1000 : 1);
        }
    };
    
    adScroller.initialize();
    
    Code (javascript):
    what it will do is it will create adblocks for any number of sets based upon your initial id. within the scrollAd function, you can access the properties of the advert block. add the mouseover to adBlock.element to set adBlock.paused = true etc.
     
    Last edited: Nov 13, 2009
    dimitar christoff, Nov 13, 2009 IP
  5. ilook

    ilook Well-Known Member

    Messages:
    1,602
    Likes Received:
    15
    Best Answers:
    1
    Trophy Points:
    165
    #5
    Thanks guys.
    Was looking for this, actually in PHP but ok :)
     
    ilook, Nov 13, 2009 IP
  6. camjohnson95

    camjohnson95 Active Member

    Messages:
    737
    Likes Received:
    17
    Best Answers:
    0
    Trophy Points:
    60
    #6
    Thanks dimitar,
    That is fairly hard for me to understand that code because it is a bit above my level of coding. And it is always harder to read code then to write it. But I will look over it again tomorrow and try to understand and use it. I appreciate your help and the time that you put into your responses, but I cannot add rep because the forum will not let me.

    And to ilook,
    It isn't possible to achieve this same result with PHP. But you can rotate ads between pages ( which is probably what you mean 0.
     
    Last edited: Nov 13, 2009
    camjohnson95, Nov 13, 2009 IP
  7. dimitar christoff

    dimitar christoff Active Member

    Messages:
    882
    Likes Received:
    62
    Best Answers:
    0
    Trophy Points:
    90
    #7
    i dont care about rep tbh - this is simply something that may be of interest to me also
     
    dimitar christoff, Nov 13, 2009 IP