www.webdeveloper.com
Results 1 to 3 of 3

Thread: Instantiate multiple objects same page

  1. #1
    Join Date
    Dec 2013
    Posts
    8

    Instantiate multiple objects same page

    I am currently learning OO JavaScript and I am practicing by building a homepage rotator. I am using a little jQuery to pass options but I am trying to stick to vanilla JavaScript. I am attempting to get the class, for lack of a better word, to support multiple rotators on the same page. I have it to the point where I can instantiate multiple rotators but they do not function independently. When you select the next or prev button it rotates the images in both rotators. I can totally see why it does this because that is what the code is telling it to do. My problem is I am learning all on my own and I have no idea how to adjust the other methods to support multiple rotators. Can you all give me advice on how to do this?

    var Rotator = function(options)
    {
    this.options = $.extend({
    id: 'rotator'
    }, options);

    this.counter = 0;
    this.auto = document.querySelector('.auto');
    this.rotatorId = document.getElementById(this.options.id);
    this.images = this.rotatorId.getElementsByTagName('figure');
    this.imagesCount = this.images.length;
    this.interval = 5000;
    this.init();
    if (this.auto) {
    this.autoStart();
    }
    };

    var eventUtility = {

    addEvent: function(el, type, fn)
    {
    if (typeof addEventListener !== 'undefined') {
    el.addEventListener(type, fn, false);
    } else if (typeof attachEvent !== 'undefined') {
    el.attachEvent("on" + type, fn);
    } else {
    el["on" + type] = fn;
    }
    },

    getTarget: function(e)
    {
    if (typeof e.target !== 'undefined') {
    return e.target;
    } else {
    return e.srcElement;
    }
    },

    preventDefault: function(e)
    {
    if (typeof e.preventDefault !== 'undefined') {
    e.preventDefault();
    } else {
    e.returnValue = false;
    }
    }
    };

    Rotator.prototype = {

    init: function()
    {
    eventUtility.addEvent(document, 'click', this.clickHandler.bind(this));
    },

    clickHandler: function(e)
    {
    this.target = eventUtility.getTarget(e);

    if (this.target.className == 'next') {
    console.log(this.target);
    this.next();
    }

    if (this.target.className == 'prev') {
    this.prev();
    }
    },

    autoStart: function()
    {
    var self = this;
    window.setInterval(function() {
    self.next();
    }, this.interval);
    },

    next: function()
    {
    this.counter++;
    this.showCurrent();
    },

    prev: function()
    {
    this.counter--;
    this.showCurrent();
    },

    showCurrent: function()
    {
    var itemToShow = Math.abs(this.counter % this.imagesCount);

    for (var i = 0; i < this.images.length; i++) {
    var item = this.images[i];
    item.classList.remove('show');
    }

    this.images[itemToShow].classList.add('show');
    }
    };

    var rotator1 = new Rotator({
    id: 'rotator1'
    });

    var rrotator2 = new Rotator({
    id: 'rotator2'
    });

  2. #2
    Join Date
    May 2014
    Posts
    900
    Kind of hard to say without seeing the markup you are manipulating, as some things (like FIGURE) probably dont' belong in there (unless those banners are actually mathematical or scientific FIGURES).

    But some suggestions:

    There is no harm in setting properties that don't exist, and with preventDefault null/false/undefined/0 check would be MORE than sufficient, so your 'prevent' method could be simplified to:

    Code:
    preventDefault: function(e)  {
      if (e.preventDefault) e.preventDefault();
      e.returnValue = false;
    }
    Likewise, you can use a inline evaluation to simplify your 'target' method. Honestly, I wouldn't even BOTHER making that a method since:

    var target = e.target || e.srcElement;

    Is functionally identical -- so don't waste time with the overhead of an entire function call for what's already a short one-liner.

    for what you are trying to do, I'd suggest using DOM walking instead of array indexing. You're using/learning objects, so use them properly by getting some DOM manipulation in there too.

    1) Get (and save) the parent element of all the 'slides' as a property of the rotator object.

    2) Save the firstChild that's nodetype == 1 (since firstElement is unreliable cross browser) to both a 'current' and 'first' property on your rotator object. Set it to 'current' with a class.

    3) when it's time to update the slides, pull the 'current' class off rotator.current, look for nextSibling until nodetype==1, and set rotator.current to it and add the class. If nextSibling is null, set current back to rotator.first

    This would let ANY child elements of your wrapper (typically a div) to be slides, regardless of what tag they are; which would be VERY versatile.

    Basically this is the setup:
    Code:
    var
      parent = document.getElementsById(id),
      e = parent.firstChild;
    while (e && e.nodeType != 1) e = e.nextSibling;
    this.first = this.current = e;
    if (e) classAdd(this.current, 'current');
    ... and this would be what you'd do inside the handler.

    Code:
      classRemove(this.current, 'current');
      do {
        this.current = this.current.nextSibling;
      } while (this.current && this.current.nodeType != 1);
      if (!this.current) this.current = this.first;
      classAdd(this.current, 'current');
    Naturally you'd need classAdd and classRemove functions to make that work.

    Doing it that way means that when you 'new' the class, you could run as many independant instances of them as you like.... THOUGH...

    running multiple timers at once is usually a bad idea. Every timeout/interval takes a LOT of CPU. Instead of trying to run multiple instances of the object, I'd seriously consider making a singleton that you pass an array of ID's to target to, that then makes an array of rotator objects so they can all be updated off a single timer.

    Though that doesn't help if you want them to update at different intervals...

    Ah, JavaScript, so many different ways of doing the same basic thing.
    Java is to JavaScript as Ham is to Hamburger.

  3. #3
    Join Date
    Jun 2004
    Location
    Portsmouth UK
    Posts
    2,680
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    
    <head>
      <title></title>
    <style type="text/css">
    /*<![CDATA[*/
    
    .rotator {
      position:relative;width:200px;height:150px;border:solid red 1px;
    }
    
    .hide {
      position:absolute;visibility:hidden;left:0px;top:0px;
    }
    
    .show {
      visibility:visible;
    }
    
    /*]]>*/
    </style></head>
    
    <body>
    <div id="rotator1" class="rotator" >
     <img class="hide show" src="http://www.vicsjavascripts.org/StdImages/Egypt5.jpg" alt="img" />
     <img class="hide" src="http://www.vicsjavascripts.org/StdImages/Egypt6.jpg" alt="img" />
     <img class="hide" src="http://www.vicsjavascripts.org/StdImages/Egypt7.jpg" alt="img" />
    </div>
    <input type="button" name="" value="Next" id="next" />
    <input type="button" name="" value="Back" id="back" />
    
    <div id="rotator2" class="rotator" onmouseover="r2.pause();"onmouseout="r2.autoStart(200);"  >
     <img class="hide show" src="http://www.vicsjavascripts.org/StdImages/Egypt5.jpg" alt="img" />
     <img class="hide" src="http://www.vicsjavascripts.org/StdImages/Egypt6.jpg" alt="img" />
     <img class="hide" src="http://www.vicsjavascripts.org/StdImages/Egypt7.jpg" alt="img" />
    </div>
    <input type="button" name="" value="GoTo 0" onclick="r2.showCurrent(0);" />
    <input type="button" name="" value="GoTo 1" onclick="r2.showCurrent(1);" />
    <input type="button" name="" value="GoTo 2" onclick="r2.showCurrent(2);" />
    
    <script type="text/javascript">
    /*<![CDATA[*/
    var Rotator = function(o){
     var p=document.getElementById(o.id),ms=o.interval,srt=o.autostart,b;
     if (p){
      this.counter = 0;
      this.images = p.getElementsByTagName('IMG');
      this.imagesCount = this.images.length-1;
      this.interval=typeof(ms)=='number'&&ms>100?ms:5000;
      this.lst=this.images[this.counter];
      b=document.getElementById(o.nextid);
      if (b){
       this.addevt(b,'click','next',1);
      }
      b=document.getElementById(o.backid);
      if (b){
       this.addevt(b,'click','next',-1);
      }
      if (typeof(srt)=='number'&&srt>=0) {
       this.autoStart(srt);
      }
     }
    };
    
    
    Rotator.prototype = {
    
     autoStart:function(ms){
      var self=this;
      self.to=window.setTimeout(function() { self.showCurrent(self.counter+1,true); },typeof(ms)=='number'?ms:this.interval);
     },
    
     pause:function(){
      clearTimeout(this.to);
     },
    
     next:function(ud){
      ud=typeof(ud)=='number'&&ud<0?-1:1;
      this.showCurrent(this.counter+1);
     },
    
     showCurrent:function(n,auto){
      clearTimeout(this.to);
      this.lst.className=this.lst.className.replace(' show','');
      n=n<0?this.imagesCount:n>this.imagesCount?0:n;
      this.lst=this.images[n]
      this.lst.className=this.lst.className+' show';
      this.counter=n;
      auto?this.autoStart():null;
     },
    
    
     addevt:function(o,t,f,p){
      var oop=this;
      o.addEventListener?o.addEventListener(t,function(e){ return oop[f](p,e);},false):o.attachEvent?o.attachEvent('on'+t,function(e){ return oop[f](p,e); }):null;
     }
    
    };
    
    var r1 = new Rotator({
     id: 'rotator1',
     interval:2000,
     autostart:1000,
     nextid:'next',
     backid:'back'
    });
    
    var r2 = new Rotator({
     id: 'rotator2',
     autostart:5000
    });
    /*]]>*/
    </script>
    
    </body>
    
    </html>
    Vic

    God loves you and will never love you less.

    http://www.vicsjavascripts.org/Home.htm
    If my post has been useful please donate to http://www.operationsmile.org.uk/

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles