0

There are a few answers on here and some things I found through google that almost get me to where I want to be, but something tells me I'm going about this wrong and was hoping for some help.

I am trying to simplify adding multiple event listeners to the same element. I think my issue is just that I'm not using the correct scope for this when calling the controller.listenz() function. Any help would be greatly appreciated.

The error I am currently getting is being thrown in the listenz() method and is telling me "fn is not a function". Which makes sense I guess, it is an object, but how do I fix that?

JSFIDDLE

Javascript

 var controller = {

     realtime: true,
     listenz: function(ele, e, fn, c, o) {

         //validate
         if (!(e instanceof Array)) {
             throw 'Javascript Listener:  Error 642';
         }


         var h = function() {
            fn.apply(this, o && o instanceof Array ? o : []);
         };


         //bind events
         for (var i = 0; i < e.length; i += 1) {
             ele.addEventListener(e[i], h, c);
         }
     },
     initz: function() {
         this.listenz(document.getElementById("real"), ["change"], this, false);
         this.listenz(document.getElementById("foi"), ["change"], this, false);
         this.listenz(document.getElementById("sim"), ["change"], this, false);
         this.listenz(document.getElementById("rev"), ["change"], this, false);
     },

     handleEvent: function(e) {
         switch (e.target.id) {
             case 'real':
                 console.log('real');
                 //this.realtime = e.target.checked ? true : false;
                 //this.realz();
                 //if (this.realtime) this.submitz();
                 break;
             default:
                 console.log('default');
                 //if (this.realtime) this.submitz();
                 break;
         }
     }
 };

HTML

<body>
    <div class="wrapper">
        <ul>
            <li>
                Real
                <input type="checkbox" name="real" id="real">
            </li>
            <li>
                Strip
                <input type="checkbox" name="sim" id="sim">
            </li>
            <li>
                Reverse
                <input type="checkbox" name="rev" id="rev">
            </li>
            <li>
                Foil
                <input type="checkbox" name="foi" id="foi">
            </li>
        </ul>
    </div>
    <script>
        controller.initz();
    </script>
</body>
7
  • c should be a callback function, here you pass this. Obviously, this is not a function. In your initz function, I think you want this.listenz(yourElement, ["change"], handleEvent, false); Commented Oct 22, 2015 at 1:43
  • @Kaiido If I use this.handleEvent, it tells me that the event is undefined, specifically "cannot read property 'target' of undefined". Any ideas? Commented Oct 22, 2015 at 1:47
  • Any idea why my fiddle isn't working ? jsfiddle.net/incept0/rn7rx6fr/2 Commented Oct 22, 2015 at 1:53
  • Your controller never was initiated and h should be h: function(){fn.apply(this, o && o instanceof Array ? o : arguments); };. updated fiddle Commented Oct 22, 2015 at 2:00
  • @Kaiido Can you modify the fiddle to reflect what you mean. The h function currently inside the listenz function. Are you saying to take it out and make it a method of the controller object instead? How would I call that ? Commented Oct 22, 2015 at 2:07

1 Answer 1

1

A few problems :

  • The fn parameter of your listenz function actually stands for function and waits for a callback one. Here, in your listenz function you are passing this, which is the controller object. Change it to this.handleEvent.

  • The h variable will override the default event arguments to the ones specified in the o parameter in the listenz function, if any. As it is written now, if no o parameter is specified, it will apply an empty array to the callback function. What you want instead is to apply default arguments so you should change it to

     var h = function() {
        fn.apply(this, o && o instanceof Array ? o : arguments);
     }  
    

Finally, you never initiate the controller object.

Here is a working snippet :

     var controller = {

         realtime: true,
         listenz: function(ele, e, fn, c, o) {

             //validate
             if (!(e instanceof Array)) {
                 throw 'Javascript Listener:  Error 642';
             }


             var h = function() {
             	fn.apply(this, o && o instanceof Array ? o : arguments);
             };


             //bind events
             for (var i = 0; i < e.length; i ++) {
                 ele.addEventListener(e[i], h, c);
             }
         },
         initz: function() {
             this.listenz(document.getElementById("real"), ["change"], this.handleEvent, false);
             this.listenz(document.getElementById("foi"), ["change"], this.handleEvent, false);
             this.listenz(document.getElementById("sim"), ["change"], this.handleEvent, false);
             this.listenz(document.getElementById("rev"), ["change"], this.handleEvent, false);
         },

         handleEvent: function(e) {
             switch (e.target.id) {
                 case 'real':
                     alert('real');
                 	 
                     //this.realtime = e.target.checked ? true : false;
                     //this.realz();
                     if (this.realtime) this.submitz();
                     break;
                 default:
                     console.log('default');
                     if (this.realtime) this.submitz();
                     break;
             }
         }
     };
controller.initz()
	<body>
	    <div class="wrapper">
	        <ul>
	            <li>
	                Real
	                <input type="checkbox" name="real" id="real">
	            </li>
	            <li>
	                Strip
	                <input type="checkbox" name="sim" id="sim">
	            </li>
	            <li>
	                Reverse
	                <input type="checkbox" name="rev" id="rev">
	            </li>
	            <li>
	                Foil
	                <input type="checkbox" name="foi" id="foi">
	            </li>
	        </ul>
	    </div>
	   
	</body>

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the help. One note: the controller object is actually being initialized iin the html just before the closing tag for body.
@NotoriousPet0 you're welcome, about the controller.initz it wasn't in your fiddle and I missed it in your code sample. I'll leave it here if you don't see any objections
of course, no objection and you are right, I did not put it in the fiddle because I didn't realize that it should go in the javascript part. So you helped me figure that out as well. Thanks again for all your help.
Oh, be carefull though, you have to call the 'controler.initz()' after the elements has been parsed. So either you do as you did in your question's snippet, either you wrap the whole thing in an onload event handler (which is the recommended way and jsfiddle's default)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.