2

Short story, I don't know why it's not working, I've tried Console.Log() to figure out what 'this' is and the event just keeps passing window. It's a click event that's suppose to activate effects on a certain figure in this carousel, which is why I can't just individually search for class (at least to my knowledge). Any fix from the smarter?

var carFigure = null;
//----------The Events
$('.figure').click(toggleCarousel(this));
//$('.figure').mouseover(stopCarousel(this));
//$('.figure').mouseleave(startCarousel(carFigure));

//------------Switcharoo function
function toggleCarousel(event) {
    var bool = false;
    console.log(event)
    if (bool) {
        stopCarousel(event);
        bool = false;
    }
    else {
        startCarousel(event);
        bool = true;
    }
}


//----------The action functions
function stopCarousel(e) {
if (carFigure != null) { document.getElementById('carousel').style.animationPlayState = "paused";
        var p = e.parentElement;
        var a = p.getElementsByTagName('DIV')[2];
        if (a.getElementsByTagName('IMG')[0].style.transform = "none") {
            a.getElementsByTagName('IMG')[0].style.transform = "scale(1.2, 1.2) translateY(-25%)";
            a.getElementsByTagName('IMG')[0].style.borderRadius = "100%";
            a.getElementsByTagName('H5')[0].style.color = "rgba(255,255,255, 0)";
            this.getElementsByClassName('links')[0].style.transform = "translateY(-250%)";
            this.getElementsByClassName('links')[0].style.opacity = "1";
            carFigure = null;
        }
    }
};
function startCarousel(e) {
    if (e != null) {
        carFigure = e;
        document.getElementById('carousel').style.animationPlayState = "running";
        var p = e.parentElement;
        var a = p.getElementsByTagName('DIV')[2];
        a.getElementsByTagName('IMG')[0].style.transform = "none";
        a.getElementsByTagName('IMG')[0].style.borderRadius = "0";
        a.getElementsByTagName('H5')[0].style.color = "rgba(255,255,255, 1)";
        this.getElementsByClassName('links')[0].style.transform = "none";
        this.getElementsByClassName('links')[0].style.opacity = "0";
    }
};
--HTML Version (Snippet)
<div class="carcontainer">
    <div id="carousel">
        <figure>
            <div class="figure">
                <div class="links">
                    <a><img src="~/Content/images/LinkedInIco.png" /></a>
                    <a href="http://www.example.com"><img src="~/Content/images/WebsiteIco.png" /></a>
                </div>
            </div>
            <div>
                <h5>Person Name</h5>
                <img src="~/Content/images/Name.jpg" alt="" />
            </div>
        </figure>
        <figure>
            <div class="figure">
                <div class="links">
                    <a><img src="~/Content/images/LinkedInIco.png" /></a>
                    <a href="http://www.example.com"><img src="~/Content/images/WebsiteIco.png" /></a>
                </div>
            </div>
            <div>
                <h5>Person Name</h5>
                <img src="~/Content/images/Name.jpg" alt="" />
            </div>
        </figure>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  • Please post the code that binds these functions to their event handlers. – Scott Marcus Jan 06 '17 at 00:23
  • If you don't post the relevant HTML (what is `.figure`), we can't help you. – Scott Marcus Jan 06 '17 at 00:33
  • I had to adjust a snippet but it is posted for you. Thank you for checking this out. – Austin Wiggins Jan 06 '17 at 00:36
  • 1
    `foo(bar())` always calls `bar()` first and passes its return value to `foo()`. Looking at `$('.figure').click(toggleCarousel(this));`, it's clear that that's wrong, since `toggleCarousel` doesn't return a function, but `.click` expects one. The same problem with the commented out lines. You are clearly passing the global object to the function here. – Felix Kling Jan 06 '17 at 00:38
  • If you don't mind me asking: What did you expect the value of `this` in `toggleCarousel(this)` to be? `toggleCarousel` expects an `event` object. Did think `this` would refer to an event? If so, why? – Felix Kling Jan 06 '17 at 00:45
  • I'm all over when it comes to programming. Languages start to intertwine and it gets confusing. I assumed this referred to the object of the event. – Austin Wiggins Jan 06 '17 at 01:10

3 Answers3

2

You aren't attaching the event handler correctly. This line:

$('.figure').click(toggleCarousel(this));

...is calling toggleCarousel with this immediately (that's what the parens will do). What you really want is to pass the function object to .click():

$('.figure').click(toggleCarousel);

Update:

As @FelixKling pointed out, you'll also want to pass the target of the event to the downstream functions; it looks like they expect an element, not the event. Also, bool will be reset to false each call, which is not what you want; you should put it in the closure:

var flag = false; // "bool" is a reserved word, changed the name
function toggleCarousel(event) {
    var element = event.target;
    if (flag) {
        stopCarousel(element);
    }
    else {
        startCarousel(element);
    }
    flag = !flag;
}
Jacob
  • 77,566
  • 24
  • 149
  • 228
  • 1
    Side note: `toggleCarousel` needs to be updated to pass the source element to `stopCarousel` and `startCarousel`. – Felix Kling Jan 06 '17 at 00:42
  • 1
    It does, but `toggleElement` calls `startCarousel(event)` but `startElement` expects the argument to be an element, not an event (as far as I can tell). – Felix Kling Jan 06 '17 at 00:44
  • Good call; can add to the answer. – Jacob Jan 06 '17 at 00:44
  • Thank you! I didn't have to pass the target actually as to carrying it through I could just set it. Furthermore I wanted to un-comment mouseover and leave so I could use both, and the setting a function in an event helped with that as well. I was stuck to the confusion that this referenced to event object and I could refer to that immediately. Fresh air is in due now! – Austin Wiggins Jan 06 '17 at 01:25
1

Your .click() event binding isn't binding a function to be called when .figure gets clicked. It's making a direct call to toggleCarousel using the this object in effect at the time (window). You need to provide a callback function to .click().

Change: $('.figure').click(toggleCarousel(this)); to:

$('.figure').click(function(){
    toggleCarousel(this);
});

So that toggleCarousel is invoked using the correct this object at the time of the click. As your code is now, it doesn't conform to the JQuery signature for .click() and attempts to invoke toggleCarousel immediately using the this object which is in control at the time the code is first encountered, which is window.


The this object binding is volatile in JavaScript...that is, it doesn't always point to the same object and its binding can change from one line of code to the very next. How you invoke the code that contains the word this determines what object it will bind to.

Here's a checklist that you can follow to know what this will bind to...

If the code that contains this is invoked:

  1. As a method or property of an object instance (through an instance variable):

    var o = new Object(); 
    
    // "this" will be bound to the "o" object instance
    // while "someProperty" and "someMethod" code executes
    o.someProperty = someValue;
    o.someMethod();
    
  2. Via a .call(), .apply(), .bind() or Array.prototype.fn invocation:

    // "this" will be bound to the object suppled as the "thisObjectBinding"
    someFunction.call(thisObjectBinding, arg, arg);
    someFunction.apply(thisObjectBinding, [arg, arg]);
    var newFunc = someFunction.bind(thisObjectBinding, arg, arg);
    

    Note: When a callback function is invoked (i.e. event handler), there is an implicit call to the handler when the event is triggered. In these cases, the object responsible for triggering the event becomes the object bound to this.

    Additionally, several Array.prototype methods allow for a thisObject to be passed which will alter the binding for the duration of the method call:

    Array.prototype.every( callbackfn [ , thisArg ] )
    Array.prototype.some( callbackfn [ , thisArg ] )
    Array.prototype.forEach( callbackfn [ , thisArg ] )
    Array.prototype.map( callbackfn [ , thisArg ] )
    Array.prototype.filter( callbackfn [ , thisArg ] )
    
  3. If none of the other scenarios apply, Default binding occurs.

    3a. With "use strict" in effect: this is undefined

    3b. Without "use strict" in effect: this binds to the Global object

NOTES:

a) this binding can also be affected by using eval(), but as a general best practice, the use of eval() should be avoided.

b) When HTML attributes are used to wire DOM elements to event handlers (i.e. onclick, onload, etc.), anonymous global wrapper functions are created around the value of the event handling property, thus making the Global object (window) the this object. This is one of several reasons to avoid inline HTML event attributes.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

This may not be the best or most direct answer but hopefully this will help you to understand what you've missed.

In javaScript the this object is set during a function call, in effect. (although do take note of the extended answer here detailing how this is defined / bound). Consider this:

function this_test () { console.log( this ); }

this_test(); // prints nothing

var x = {f:this_test}; // note, references to functions are not the same as function calls
x.f(); // prints {f:[function]} ie this==x inside the call

this_test.call( x ); // identical in effect to above.

With that in mind, consider this line you wrote:

$('.figure').click(toggleCarousel(this));

What this does is set an event handler function that is the result of calling toggleCarousel(this). Because this is (I assume) top-level code in a js file or in a script tag, in this context this === window because it's not inside a function!

What you should be doing is this:

$('.figure').click( toggleCarousel );

Finally, since you're using jQuery, you ought to use jQuery methods to lookup and modify DOM since it's far easier (and cross-browser compliant). Hence this idiom sometimes seen in jQuery event code:

function event_handler () {
    var $this = $(this);
}

Highly suggested reading - jQuery Click Event - most other event handlers work similarly.

Xeren Narcy
  • 875
  • 5
  • 15