0

I'm trying to do some OO JavaScript to just simply swap pictures with a fade transition, but nothing happens when the page loads.

All my images are named Joe_#.jpg, where # is a number.

Here is my imagesJS.js file:

//GLOBALS
var delay = 5000;
var opacityDelay = 100;
var pathBeginning = "images\joe\Joe_";
var pathEnding = ".jpg";

//IMAGE CLASS
function imageObj(id, start, end, initDelay) {

    this.obj = document.getElementById(id);

    this.cur = start;
    this.start = start;
    this.end = end;

    this.initDelay = initDelay;
    this.opacity = 1;


    this.fadeIn = function() {
        if(this.opacity < 1) {
            this.opacity = this.opacity + 0.1;
            obj.style.opacity = this.opacity;
            setTimeout(this.fadeIn(), opacityDelay);
        }
    }

    this.nextImage = function() {

        if(this.cur == this.end) {
            this.cur = this.start;
        }
        else {
            this.cur++;
        }

        obj.src = pathBeginning + this.cur.toString() + pathEnding;

        this.fadeIn();
    }

    this.fadeOut = function() {
        if(this.opacity > 0.5) {
            this.opacity = this.opacity - 0.1;
            obj.style.opacity = this.opacity;
            setTimeout(this.fadeOut(), opacityDelay);
        }
        else {
            this.nextImage();
        }
    }

    this.process = function() {
        setInterval(this.fadeOut(), delay + Math.floor(Math.random()*delay));
    }
}

imageObj.prototype.startProcess = function() {
    setTimeout(this.process(), this.initDelay);
}


//IMAGE OBJECTS
var img1 = imageObj('img1', 1, 5, 5000);
img1.startProcess();

Here is how I include everything on the HTML page:

<head>
    <!-- Links/Scripts -->
    <link rel="stylesheet" type="text/css" href="style.css"/>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="myJavascript.js" type="text/javascript"></script>
    <script src="imagesJS.js" type="text/javascript"></script>

And this is the myJavascript.js file (maybe it has something to do with it):

// GLOBAL VARIABLES
var body = $('.body');

//***********//
//  On Load  //
//***********//
$(document).ready(function(){
    //MenuItem Color Change
    $('.menuItem').mouseover(function(){
        $(this).css({"color":"#6699ff"})
    }).mouseout(function(){
        $(this).css({"color":"black"})
    });
});

Should I be putting the objects in the onLoad function? I can't seem to find me problem. Thanks in Advance!

//############################################################################ UPDATE 1

Here's the code after correcting the advice from net.uk.sweet below and some scope issues from this link Using setTimeout() within a JavaScript class function

UPDATED CODE -

//GLOBALS
var delay = 5000;
var opacityDelay = 100;
var pathBeginning = "images\joe\Joe_";
var pathEnding = ".jpg";

//IMAGE CLASS
function imageObj(id, start, end, initDelay) {

    this.obj = document.getElementById(id);

    this.cur = start;
    this.start = start;
    this.end = end;

    this.initDelay = initDelay;
    this.opacity = 1;


    this.fadeIn = function() {
        if(this.opacity < 1) {
            this.opacity = this.opacity + 0.1;
            this.obj.style.opacity = this.opacity;
            setTimeout(fadeIn, opacityDelay);
        }
    }

    this.nextImage = function() {

        if(this.cur == this.end) {
            this.cur = this.start;
        }
        else {
            this.cur++;
        }

        this.obj.src = pathBeginning + this.cur.toString() + pathEnding;

        this.fadeIn();
    }

    this.fadeOut = function() {
        if(this.opacity > 0.5) {
            this.opacity = this.opacity - 0.1;
            this.obj.style.opacity = this.opacity;
            setTimeout(fadeOut, opacityDelay);
        }
        else {
            this.nextImage();
        }
    }

    this.process = function() {
        var self = this;
        self.fadeOut();
        setInterval(function() {self.fadeOut();}, delay+Math.floor(Math.random()*delay));
    }
}

imageObj.prototype.startProcess = function() {
    var self = this;
    setTimeout(function() {self.process();}, this.initDelay);
}

//IMAGE OBJECTS
var img1 = new imageObj('img1', 1, 5, 5000);
img1.startProcess();

Unfortunately, it still doesn't work.... Any ideas?

//################################################################################ SOLUTION UPDATE

I had to add the creation and calling of the startProcess function in the onLoad function on my other javascript file.

Here is the solution Code:

//GLOBALS
var delay = 5000;
var opacityDelay = 100;
var pathBeginning = "images\\joe\\Joe_";
var pathEnding = ".jpg";

//IMAGE CLASS
function imageObj(id, start, end, initDelay) {

    this.obj = document.getElementById(id);
    this.cur = start;
    this.start = start;
    this.end = end;
    this.initDelay = initDelay;
    this.opacity = 1;

    this.fadeIn = function() {
        var self = this;
        if(this.opacity < 1) {
            this.opacity = this.opacity + 0.1;
            this.obj.style.opacity = this.opacity;
            setTimeout(function() {self.fadeIn();}, opacityDelay);
        }
    }

    this.nextImage = function() {

        if(this.cur == this.end) {
            this.cur = this.start;
        }
        else {
            this.cur++;
        }

        this.obj.src = pathBeginning + this.cur.toString() + pathEnding;
        this.fadeIn();
    }

    this.fadeOut = function() {
        var self = this;
        if(this.opacity > 0.2) {
            this.opacity = this.opacity - 0.1;
            this.obj.style.opacity = this.opacity;
            setTimeout(function() {self.fadeOut();}, opacityDelay);
        }
        else {
            self.nextImage();
        }
    }

    this.process = function() {
        var self = this;
        self.fadeOut();
        setInterval(function() {self.fadeOut();}, delay + Math.floor(Math.random()*delay));
    }
}

imageObj.prototype.startProcess = function() {
    var self = this;
    setTimeout(function() {self.process();}, this.initDelay);
}

Thanks for all the help net.uk.sweet!!! Learned a lot about scope and chrome dev tools! Hope I can help someone else one day!

1 Answer 1

2

You'll be doing yourself a massive favour if you get familiar with the debugging tools within your favourite browser (here's how). The console will output details of any errors in your code and any log statements you enter to help you follow the flow of the program, and you can use advanced debugging features such as break points to step through the code and see where it's breaking down.

That said, I can see a few obvious problem with your code.

When instantiating a new object in JavaScript using a function definition, you need to use the new keyword:

var img1 = new imageObj('img1', 1, 5, 5000);

Every time you use setTimeout you're invoking the function directly instead of passing it by reference. This means that the function is executed immediately and not when the timeout has completed. For example, you should update the code in your startProcess method as follows:

// Note the missing parenthesis. You should pass the function to 
// setTimeout by reference instead of invoking the function directly.
setTimeout(this.process, this.initDelay);

But... you're also running into issues related to scope when using setTimeout (see the answer on this stackoverflow thread for a good explanation). Try using a closure to ensure that your methods are called with the instance as the scope rather than the global window object:

imageObj.prototype.startProcess = function() {
    var self = this;
    setTimeout(function() {
        self.process();
    }, this.initDelay);
}

I think the obj variable is out of scope the way you reference it. Try accessing it using this:

this.fadeIn = function() {

    // Sending information to the console is a very simple way of debugging
    // your program. You can even use it to trace the value of variables! 
    console.log('In here! Current image opacity is:', this.opacity);

    if(this.opacity < 1) {
        this.opacity = this.opacity + 0.1;
        this.obj.style.opacity = this.opacity;
        setTimeout(this.fadeIn(), opacityDelay);
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks! That definitely makes sense that with the parenthesis I am calling a function. While without i'm passing a reference to the function. However, there seems to be another bug. But thanks!
Like I said, use the debugging tools to track down the issue and then come back with a question if you don't understand it then. I've had another look and identified a further couple of errors, but generally people aren't going to be prepared to debug your code for you if you haven't tried to help yourself first.
I've been debugging it using Chrome Dev Tools, and it tells me that once the 'process' function gets called after the initDelay that the this.fadeOut() function is not recognized in the scope. Specifically this error: code Uncaught TypeError: Object [object global] has no method 'fadeOut' code
You've got issues with scope as well. Have a look at the following which explains how to call setTimeout with the correct scope: stackoverflow.com/questions/6997921/…
I think I followed that link well. I pasted an updated code above. THANKS AGAIN FOR ALL THE HELP SO FAR!
|

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.