Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 4 of 4
  1. #1
    New Coder
    Join Date
    Feb 2005
    Posts
    97
    Thanks
    7
    Thanked 7 Times in 7 Posts

    Chaining function calls jQuery style

    Hi, I've been playing around trying to recreate the way in which jQuery chains it's functions for it's "select" then "do" behaviour.

    Note: I don't want to chain functions with jQuery, I want to chain them like jQuery.

    So based on the jQuery code what I have so far is (doesn't work in IE):

    Code:
    var x = function(string) {
        return new x.fn.init(string);
    };
    
    x.fn = x.prototype = {
    
        message: '',
    
        init: function(string) {
            x.fn.message = string;
        },
    
        log: function() {
           console.log(x.fn.message);    
        }
    };
    
    x.fn.init.prototype = x.fn;
    
    var start = function() {    
        x('hello world').log();
    };
    
    document.addEventListener('DOMContentLoaded', start, false);
    The code works but when I watch '$' in jQuery "fn" & "prototype" show up as being "jQuery()" but in my code when I watch "x": "fn" and "prototype" are both shown as objects containing "message", "init" and "log" and in both cases "init" contains "prototype" which contains my three functions again and the nesting continues seemingly infinitely...

    I'm clearly missing something here. What are they doing in differently in jQuery to prevent this endless nesting loop?

  • #2
    Regular Coder
    Join Date
    Mar 2009
    Location
    Portland Oregon
    Posts
    690
    Thanks
    44
    Thanked 63 Times in 62 Posts
    I played with your code a little. Not sure if this helped or hurt.

    Code:
    <script>
                         var x = function(id){
                                           return new  x.fn.init(id)
                                           }
    
                    x.fn = {
                           init : function(string) {
                                                   x.fn.id = string;
    	                                       x.fn.elm=document.getElementById(x.fn.id)
                            },
                       mouseover : function(fn){
    			return x.fn.elm.onmouseover=fn
                             },
                        mouseout : function(fn){
    			return x.fn.elm.onmouseout=fn
                             },
     
                         html : function(html){
                                                x.fn.elm.innerHTML = html
                              },
    		    append : function(html){
                                                x.fn.elm.innerHTML += html
                              },
                           css : function(style){
                                               x.fn.elm.style.cssText=style
                               },
                        font : function(font){
                                                x.fn.elm.style.font=font
                             },
                        color : function(color){
                                               x.fn.elm.style.color=color
                              }
    };
    
    
    x.fn.init.prototype = x.fn;
    
    
    var start = function() {  
     
    x("world").color("green")
    x("world").html("hello world")
    
    x("world2").color("red")
    x("world2").font("16px arial black")
    x("world2").html("hello2")
    x("world2").append("<br>more text")
    
    
    x("world3").css("font:16px arial black;color:orange;background-color:black")
    x("world3").html("hello3")
    x("world3").mouseover(function(){x("world3").html("mouse over")})
    x("world3").mouseout(function(){x("world3").html("hello3")})
    };
    
    window.onload= start;
    
    </script>
    <div id="world"></div><br>
    <div id="world2"></div>
    <div id="world3"></div>

  • #3
    New Coder
    Join Date
    Feb 2005
    Posts
    97
    Thanks
    7
    Thanked 7 Times in 7 Posts
    Erm you've extended it into the beginnings of your own js library rather than dealing with the question but never mind

    Actually on further investigation I've noted that the watch on "$" of jquery also allows you to go into an infinite loop of nesting via "fn" or "prototype".

    I'm guessing this isn't a bad thing and just indicates the self reference pointing.

    If it's good enough for John it's good enough for me

  • #4
    Regular Coder
    Join Date
    Mar 2009
    Location
    Portland Oregon
    Posts
    690
    Thanks
    44
    Thanked 63 Times in 62 Posts
    Well, I wasn't able to answer your question until I figured it out myself. LOL

    I used p01's method of chaining.
    http://www.p01.org/releases/20_lines...e_fractal_rug/

    It doesn't work with my move function, but you can chain the other functions.

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    <script>
    /*fauxQuery*/
    var faux = function () {}
    faux.prototype = {
      init: function (id) {
        this.id = id;
        this.elm = document.getElementById(this.id)
      },
      over: function (fn) {
        return this.elm.onmouseover = fn
      },
      out: function (fn) {
        return this.elm.onmouseout = fn
      },
      down: function (fn) {
        return this.elm.onmousedown = fn
      },
      
      move: function (prop, endVal, steps, speed, N) {
        var self = this
        self.timer = null
        self.currVal = parseInt(this.elm.style[prop])
        self.ease = function (currVal, endVal, steps, incr, N) {
          return currVal + Math.pow(incr / steps, N) * (endVal - currVal)
        }
        clearInterval(self.timer);
        var incr = 0;
        self.timer = setInterval(function () {
          self.elm.style[prop] = Math.round(self.ease(self.currVal, endVal, steps, incr, N)) + "px"
          incr++;
          if (incr > steps) {
            self.elm.style[prop] = endVal + "px";
            clearInterval(self.timer)
          }
        }, speed)
      },
      fade: function (endVal, steps, speed, N) {
        var self = this
        self.timer = null
        self.currVal = !self.elm.style.opacity ? parseFloat(self.elm.style.filter) : parseFloat(self.elm.style.opacity)
        self.ease = function (currVal, endVal, steps, incr, N) {
          return currVal + Math.pow(incr / steps, N) * (endVal - currVal)
        }
        clearInterval(self.timer);
        var incr = 0;
        self.timer = setInterval(function () {
          self.elm.style.opacity = self.ease(self.currVal, endVal, steps, incr, N);
          self.elm.style.filter = "alpha(opacity=" + (self.ease(self.currVal, endVal, steps, incr, N) * 100) + ")";
          incr++;
          if (incr > steps) {
            self.elm.style.opacity = endVal;
            self.elm.style.filter = "alpha(opacity=" + (endVal * 100) + ")";
            clearInterval(self.timer)
          }
        }, speed)
      },
      tag: function (tag, n) {
        var A = !n ? this.elm.getElementsByTagName(tag) : this.elm.getElementsByTagName(tag)[n]
        return A
      },
      clsn: function (cn, n) {
        function byClassN(Elm, cname) {
          var A = [];
    
          function classN(elm, cn) {
            return elm.attributes.getNamedItem("class").nodeValue == cn
          }
          var i = 0;
          while (Elm.children[i]) {
            var E = Elm.children[i];
            if (classN(E, cname)) {
              A.push(E)
            };
            i++
          }
          return A
        }
        if (!this.elm.getElementsByClassName) {
          return !n ? byClassN(this.elm, cn) : byClassN(this.elm, cn)[n];
        } else {
          var A = !n ? this.elm.getElementsByClassName(cn) : this.elm.getElementsByClassName(cn)[n];
          return A
        }
      },
      html: function (html) {
        this.elm.innerHTML = html
      },
      append: function (html) {
        this.elm.innerHTML += html
      },
      css: function (style) {
        this.elm.style.cssText = style
      },
      font: function (font) {
        this.elm.style.font = font
      },
      color: function (color) {
        this.elm.style.color = color
      }
    };
    function $faux(func){return function(){ return func.apply( this, arguments ) || this }}
    for( fn in faux.prototype){ faux.prototype.init.prototype[fn]  =  $faux( faux.prototype[fn] )}
    var id = function (id) {
    
           
           var $= new faux.prototype.init(id)
           
    return $
    }
    var start = function () {
    
      id("world").color("green").html("hello world").css("font:16px arial black;width:200px;height:30px;background-color:gray")
      
      id("world2").color("red").font("16px arial black").html("hello2").append("<br>more text<div class='change'></div>")
      id("world3").css("font:16px arial black;position:absolute;left:200px;top:200px;width:200px;height:70px;color:orange;background-color:black")
      id("world3").html("Example 3")
      id("world3").over(function () {
        id("world3").html("Click for instructions").color("red");
        id("world3").fade(.5, 50, 5, 2)
      })
      id("world3").out(function () {
        id("world3").html("Example 3").color("orange")
    id("world3").move("width", 200, 50, 5, 2)
    id("world3").move("height", 70, 50, 5, 2)
    id("world3").move("left", 200, 50, 5, 4)
    id("world3").move("top", 200, 50, 5, 4)
    id("world3").fade(1, 50, 5, 2)
      })
      id("world3").elm.onmousedown = function () {
    id("world3").move("width", 400, 50, 5, 4)
    id("world3").move("height", 400, 50, 5, 4)
    id("world3").move("left", 10, 50, 5, 4)
    id("world3").move("top", 10, 50, 5, 4)
    id("world3").fade(1, 50, 5, 2).color("green")
      }
      id("world3").fade(0, 1, 5, 2)
      setTimeout(' id("world3").fade(1, 50, 5, 2)', 6500)
      setTimeout('id("world4").tag("div")[0].innerHTML="tag fn works"', 1500)
      setTimeout(function () {
        id("world4").clsn("change")[0].innerHTML += "<br>class fn works"
      }, 3500)
      setTimeout(function () {
        id("world4").tag("div", "0").innerHTML += "<br>tag fn works"
      }, 4500)
      setTimeout(function () {
        id("world4").clsn("change", "0").innerHTML += "<br>class fn works"
      }, 5500)
      setTimeout(function () {
        id(id("world5").clsn("change")[0].id).css("color:green;font:18px arial black");
        id(id("world5").clsn("change")[1].id).down(function () {
          this.innerHTML = "clicked";
          this.onmouseout = function () {
            this.innerHTML = "click me "
          }
        })
      }, 200)
    };
    window.onload = start
    </script>
    <div id="world"></div><br>
    <div id="world2"></div>
    <div id="world3"></div>
    <div id="world4"></div>
    <div id="world5">div 5 <br><div id="blah" class="change">click</div><div id="blah2" class="change">click2</div></div>


  •  

    Posting Permissions

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