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 10 of 10
  1. #1
    Regular Coder Krupski's Avatar
    Join Date
    Dec 2010
    Location
    United States of America
    Posts
    505
    Thanks
    39
    Thanked 47 Times in 46 Posts

    "Wrap up" functions in one block for closure?

    Hi all,

    I've got some simple code that I use to drag the corners of a DIV to resize it on the fly. One thing that bothers me is that there is a "global" variable just hanging outside and I would rather "encapsulate" it all into a block of code so that the variable persists, but is not visible outside of the code that uses it.

    So, here's the code:

    Code:
    /***
     * support for mouse drag resize of mChat window
     * "global" save of mouse start position
     **/
    var start = 0;
    
    /***
     * do-nothing function to attach unused events to
     **/
    function nullFunc () {
        return false;
    };
    
    /***
     * begin drag
     **/
    function drag () {
        start = 0;
        document.onmouseup = up;
        document.onmousedown = nullFunc;
        document.onmousemove = move;
        return false;
    };
    
    /***
     * end drag
     **/
    function up () {
        start = 0;
        document.onmouseup = nullFunc;
        document.onmousedown = nullFunc;
        document.onmousemove = nullFunc;
        return false;
    };
    
    /***
     * mouse move capture
     **/
    function move (e) {
        var o = mouseXY(e); /* mouseXY not shown here */
        if (start) {
            mChatSize(o.y - start); /* mChatSize not shown here */
        }
        start = o.y;
        return false;
    };
    You see the code captures the mouse Y coordinate and then subtracts "start" from it to generate a DELTA (which is what the mChatSize function needs). So, moving the mouse up generates "-1, -1, -1" maybe -2 if dragged fast and +1 +1 +1... if moved down.... you see?

    Now what I want to do is put all this code in a "box" so that "start" is global to the box, but invisible outside. I tried to do it and made no headway... I'm sure it's simple and I'm just missing it.

    Any help will be appreciated. Thanks!

    -- Roger
    "Anything that is complex is not useful and anything that is useful is simple. This has been my whole life's motto." -- Mikhail T. Kalashnikov

  • #2
    Regular Coder Amphiluke's Avatar
    Join Date
    Jul 2009
    Posts
    312
    Thanks
    3
    Thanked 89 Times in 89 Posts
    The simplest way to avoid global variables is use a lambda function which is called immediately after the declaration.
    Code:
    (function() {
      // place here any variables and function declarations...
    })();
    So, try to wrap your code with such an anonymous function.
    I am still learning English

  • Users who have thanked Amphiluke for this post:

    Krupski (12-10-2011)

  • #3
    Regular Coder Krupski's Avatar
    Join Date
    Dec 2010
    Location
    United States of America
    Posts
    505
    Thanks
    39
    Thanked 47 Times in 46 Posts
    Quote Originally Posted by Amphiluke View Post
    The simplest way to avoid global variables is use a lambda function which is called immediately after the declaration.
    Code:
    (function() {
      // place here any variables and function declarations...
    })();
    So, try to wrap your code with such an anonymous function.
    OK but then how do I call a function inside? Just by it's name as usual?
    "Anything that is complex is not useful and anything that is useful is simple. This has been my whole life's motto." -- Mikhail T. Kalashnikov

  • #4
    Regular Coder Amphiluke's Avatar
    Join Date
    Jul 2009
    Posts
    312
    Thanks
    3
    Thanked 89 Times in 89 Posts
    Inside the anonymous function you may call all the nested functions by names as usual.
    I am still learning English

  • #5
    Regular Coder Krupski's Avatar
    Join Date
    Dec 2010
    Location
    United States of America
    Posts
    505
    Thanks
    39
    Thanked 47 Times in 46 Posts
    Quote Originally Posted by Amphiluke View Post
    Inside the anonymous function you may call all the nested functions by names as usual.
    Yes but how do I call it from the outside?

    To use the code I posted above, I call it like this:

    Code:
    <img src="./img/handle.gif" id="handle" title="Drag to resize" onmousedown="drag();" />
    "Anything that is complex is not useful and anything that is useful is simple. This has been my whole life's motto." -- Mikhail T. Kalashnikov

  • #6
    Regular Coder Amphiluke's Avatar
    Join Date
    Jul 2009
    Posts
    312
    Thanks
    3
    Thanked 89 Times in 89 Posts
    You should not call the function drag() from outside. If the function is called from an event handler, it must be registered as an event handler from within the anonymous function.

    Code:
    (function() {
        window.onload = function() {
            document.getElementById("handle").onmousedown = drag;
        }
        // other routines
    })();
    Note that function names also should not take global namespace, if it is possible.
    I am still learning English

  • #7
    Regular Coder Krupski's Avatar
    Join Date
    Dec 2010
    Location
    United States of America
    Posts
    505
    Thanks
    39
    Thanked 47 Times in 46 Posts
    Quote Originally Posted by Amphiluke View Post
    You should not call the function drag() from outside. If the function is called from an event handler, it must be registered as an event handler from within the anonymous function.

    Code:
    (function() {
        window.onload = function() {
            document.getElementById("handle").onmousedown = drag;
        }
        // other routines
    })();
    Note that function names also should not take global namespace, if it is possible.
    Very strange. I can't get it to work... I understand what you're showing me but it's not working. I'll have to work at it until I figure it out.

    Thanks!

    -- Roger
    "Anything that is complex is not useful and anything that is useful is simple. This has been my whole life's motto." -- Mikhail T. Kalashnikov

  • #8
    WA
    WA is offline
    Administrator
    Join Date
    Mar 2002
    Posts
    2,596
    Thanks
    2
    Thanked 19 Times in 18 Posts
    You can wrap everything in an immediate function to prevent the code from polluting the global space, but return an object inside it at the end exposing what you wish to access globally:

    Code:
    var utils=(function(){
    	var t=5 //private var
    
    	function doit(){ //private func
    		alert(t)
    	}
    
    	function doit2(num){ //private func
    		alert(num + t)
    	}
    
    	return {
    		doit: doit,
    		doit2: doit2
    	}
    
    })()
    
    utils.doit() //alerts 5
    utils.doit2(3) //alerts 8
    In the above, only "utils" is a global variable that in turn contains all the public functions you need to access within the immediate function.
    - George
    - JavaScript Kit- JavaScript tutorials and 400+ scripts!
    - JavaScript Reference- JavaScript reference you can relate to.

  • Users who have thanked WA for this post:

    Krupski (12-12-2011)

  • #9
    Regular Coder Krupski's Avatar
    Join Date
    Dec 2010
    Location
    United States of America
    Posts
    505
    Thanks
    39
    Thanked 47 Times in 46 Posts
    Quote Originally Posted by WA View Post
    You can wrap everything in an immediate function to prevent the code from polluting the global space, but return an object inside it at the end exposing what you wish to access globally:

    Code:
    var utils=(function(){
        var t=5 //private var
    
        function doit(){ //private func
            alert(t)
        }
    
        function doit2(num){ //private func
            alert(num + t)
        }
    
        return {
            doit: doit,
            doit2: doit2
        }
    
    })()
    
    utils.doit() //alerts 5
    utils.doit2(3) //alerts 8
    In the above, only "utils" is a global variable that in turn contains all the public functions you need to access within the immediate function.
    OH!!!! I see! Thanks! So simple.

    Edit:
    You are the best! Works like a charm. Thanks again!

    Code:
    /***
     * mchat drag resize
     **/
    var chat = (function() {
    
        var lastPos = 0;
    
        function nullFunc () {
            return false;
        };
    
        function drag () {
            lastPos = 0;
            document.onmouseup = up;
            document.onmousedown = nullFunc;
            document.onmousemove = move;
            return false;
        };
    
        function up () {
            lastPos = 0;
            document.onmouseup = nullFunc;
            document.onmousedown = nullFunc;
            document.onmousemove = nullFunc;
            return false;
        };
    
        function move (event) {
            var o = mouseXY(event);
            if (lastPos) {
                mChatSize(o.y - lastPos);
            }
            lastPos = o.y;
            return false;
        };
    
        return {
            drag : drag
        };
    
    })();
    Last edited by Krupski; 12-12-2011 at 03:45 PM.
    "Anything that is complex is not useful and anything that is useful is simple. This has been my whole life's motto." -- Mikhail T. Kalashnikov

  • #10
    Regular Coder Krupski's Avatar
    Join Date
    Dec 2010
    Location
    United States of America
    Posts
    505
    Thanks
    39
    Thanked 47 Times in 46 Posts
    Quote Originally Posted by WA View Post
    You can wrap everything in an immediate function to prevent the code from polluting the global space, but return an object inside it at the end exposing what you wish to access globally:

    Code:
    var utils=(function(){
        var t=5 //private var
    
        function doit(){ //private func
            alert(t)
        }
    
        function doit2(num){ //private func
            alert(num + t)
        }
    
        return {
            doit: doit,
            doit2: doit2
        }
    
    })()
    In the above, only "utils" is a global variable that in turn contains all the public functions you need to access within the immediate function.
    Just wanted to thank you again... because now I UNDERSTAND what's going on. I also looked at a block of code and realized that even this way above can be shortened:

    Code:
    var utils=(function(){
        var t=5 //private var
        return {
            doit : function() { //private func
                alert(t)
            },
            doit2 : function(num){ //private func
                alert(num + t)
            }
        };
    })();
    The "light bulb" lit up in my head when I saw "doit : doit".....

    Thanks again for adding another block of understanding to my head!

    -- Roger
    "Anything that is complex is not useful and anything that is useful is simple. This has been my whole life's motto." -- Mikhail T. Kalashnikov


  •  

    Posting Permissions

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