I'm currently converting my Javascript App from jQuery to AngularJS. I used a lot of Object which modified the DOM and animate my elements. I wanted to create a factory, but I can't access to the scope, and that's not why they're made for.
A directive seems to be a good solution, but I don't want to declare a new element, or an attribute in my DOM, and I want to be able to use it as an object in my controller, and I want that object to access to the current controller scope.
For exemple:
myModule.controller("myController", ['$scope', 'Animation',
function($scope, Animation) {
Animation.doSomeStuff();
}
]);
Is there any solution, or good way to do this ?
EDIT: The ultra complet version of my jQuery object that I want to convert into the Angular way:
function Loader() {
var that = this;
this.STATES = new Array("sleep", "animate", "complete");
this.state;
this.animationDuration;
this.animation;
this.currentDiv;
this._completeTimer;
this._contenderResized = new Array();
//Events
this.onComplete = function(){};
this.onStop = function(){};
this.onStart = function(){};
this.init = function(animationName) {
this.state = "sleep";
this.animationDuration = 300;
this.animation = animationName;
switch(this.animation) {
case "circle":
this._initCircle();
break;
case "free":
this._initSquare();
break;
case "square":
this._initSquare();
break;
}
};
this.reset = function() {
this.state = "sleep";
this.currentDiv.find(".vote").removeClass("activated");
that.currentDiv.find(".loader").hide();
switch(this.animation) {
case "circle":
this._resetCircle();
break;
case "free":
this._resetSquare();
break;
case "square":
this._resetSquare();
break;
}
this.onComplete = function() {};
this.currentDiv = "";
};
this._removeAnimationClass = function() {
this.currentDiv.find(".vote").removeClass("activated");
var loaderCursor = this.currentDiv.find(".loader-cursor");
if(loaderCursor.hasClass("loader-cursor-right"))
loaderCursor.removeClass("loader-animate-right");
if(loaderCursor.hasClass("loader-cursor-left"))
loaderCursor.removeClass("loader-animate-left");
loaderCursor.removeClass("loader-animate");
loaderCursor.removeClass("loader-complete");
};
this.start = function(contenderDiv) {
this.currentDiv = contenderDiv;
this._animate(contenderDiv);
this._completeTimer = setTimeout(this._complete, this.animationDuration);
};
this.stop = function() {
if(this.state !== "animate" || !this.currentDiv) return;
clearTimeout(this._completeTimer);
switch(this.animation) {
case "circle" :
this._stopCircle();
break;
case "free":
this._stopSquare();
break;
case "square":
this._stopSquare();
break;
}
setTimeout(function() {
//that.currentDiv.find(".loader").hide();
}, 20);
};
this._animate = function(contenderDiv) {
this.state = "animate";
switch (this.animation) {
case "circle" :
this._animateCircle(contenderDiv);
break;
case "free":
this._animateSquare(contenderDiv);
break;
case "square":
this._animateSquare(contenderDiv);
break;
}
};
this._complete = function() {
that.state = "complete";
switch (that.animation) {
case "circle" :
that._completeCircle();
break;
case "free":
var loaderCursor = that.currentDiv.find(".loader-cursor");
loaderCursor.addClass("loader-complete");
break;
case "square":
var loaderCursor = that.currentDiv.find(".loader-cursor");
loaderCursor.addClass("loader-complete");
break;
}
setTimeout(function() {
that.onComplete();
that.reset();
}, 300);
};
this._resizeLoaderToContainImage = function(contenderDiv){
if(jQuery.inArray(contenderDiv.find(".vote").attr("rel"),this._contenderResized) !== -1)
return;
var img = contenderDiv.find(".contenderImg");
var imageSrc = jQuery(img).css('backgroundImage')
.replace(/url\((['"])?(.*?)\1\)/gi, '$2')
.split(',')[0];
var image = new Image();
image.src = imageSrc;
var bgwidth = image.width,
bgheight = image.height,
bgContainWidth = jQuery(img).width();
var bgContainHeight = (bgheight*bgContainWidth)/bgwidth;
var decimal = bgContainHeight.toString().split('.');
if(decimal[0]>=5)
{
bgContainHeight = Math.ceil(bgContainHeight);
}
else
{
bgContainHeight = Math.floor(bgContainHeight);
}
var hRatio = bgheight / parseInt(contenderDiv.css("height"));
var testWidth = bgwidth / hRatio;
var decimal = bgContainHeight.toString().split('.');
if(decimal[0]>=5)
{
testWidth = Math.ceil(testWidth);
}
else
{
testWidth = Math.floor(testWidth);
}
console.log("test "+testWidth);
var loader = contenderDiv.find(".loader");
loader.css("height", bgContainHeight);
loader.css("width", testWidth);
//Center Horizontal
var marginTop = bgContainHeight / 2;
loader.css("margin-top", -marginTop);
//Center Vertical
var marginLeft = testWidth / 2;
loader.css("margin-left", -marginLeft);
this._contenderResized.push(contenderDiv.find(".vote").attr("rel"));
};
/**********************
* SQUARE
**********************/
this._initSquare = function() {
/*jQuery('.contender').hover(function(){
//IN
jQuery(this).find(".loader").show();
that._resizeLoaderToContainImage(jQuery(this));
},
function(){
//OUT
jQuery(this).find(".loader").hide();
});*/
};
this._animateSquare = function(contenderDiv) {
contenderDiv.find(".contenderImg").addClass("loader-animate");
contenderDiv.find(".vkrz").stop(true, true).hide().fadeIn(300);
if(contenderDiv.find("#contenderA").length === 1) {
jQuery("#contenderB").find(".contenderImg").addClass("loader-animate-grayscale");
}
else {
jQuery("#contenderA").find(".contenderImg").addClass("loader-animate-grayscale");
}
};
this._stopSquare = function() {
if(this.currentDiv.find("#contenderA").length === 1) {
jQuery("#contenderB").find(".contenderImg").removeClass("loader-animate-grayscale");
}
else {
jQuery("#contenderA").find(".contenderImg").removeClass("loader-animate-grayscale");
}
this.currentDiv.find(".vkrz").hide();
this.currentDiv.find(".contenderImg").removeClass("loader-animate");
this._removeAnimationClass();
};
this._resetSquare = function() {
jQuery(".vkrz").hide();
jQuery(".contenderImg").removeClass("loader-animate loader-animate-grayscale");
this._removeAnimationClass();
};
/**********************
* CIRCLE
**********************/
this._initCircle = function() {
jQuery('.contender').hover(function(){
//IN
jQuery(this).find(".loader").stop(true, true).addClass("loader-hover");
},
function(){
//OUT
jQuery(this).find(".loader").stop(true, true).removeClass("loader-hover");
});
};
this._animateCircle = function(contenderDiv) {
contenderDiv.find(".loader").stop(true, true).addClass("loader-animate");
};
this._stopCircle = function() {
this.currentDiv.find(".vote").removeClass("activated");
this.currentDiv.find('.loader').removeClass("loader-animate");
};
this._resetCircle = function() {
this.currentDiv.find(".vote").removeClass("activated");
jQuery(".loader").removeClass("loader-animate loader-complete").show();
};
this._completeCircle = function() {
this.currentDiv.find(".loader").addClass('loader-complete');
};
}