create fn function with callback - javascript

I did the following little plugIn (to add to query.transit by Rico St Cruz):
$.fn.translateLeft = function( left, duration, easing, callback ) {
var $this = $(this);
var currentLeftPx = parseInt( $this.css('left') );
var parentWidth = $this.parent().width();
// final left layout destination in px
var finalLeftPx = parentWidth/100 * left;
// actual distances to final left layout destination in px
var distanceLeftPx = currentLeftPx - finalLeftPx;
$this.transition( { x: -distanceLeftPx }, duration, easing, function() {
$this.stop(true).css( { left: left +'%', x: 0 } );
callback();
} );
}
I used it (without the callback I tried to implement it worked well so far) so:
$("#someElement").translateLeft( 10.5, 300, 'easeOutSine', function() {
// do something else
} );
This helps to make smooth x translate instead of left, yet keeps the possibility to set % values that refer to the parent (which is not possible with x alone which refers alway to the element). This only for explanation.
And as I said it works very good, yet my inserted callback does not.
Did I do something wrong here semantically?
Thanks for advice!
Garavani
EDIT:
Thanks so far for your comments that made me think. Actually even in my (beginner) fn code the callback actually works if I put for example alert( "Callback" ) in there instead of the other code. So it seems it is not possible to mix up my plugIn with any kind of code. To complete my question here is the whole code involved even if I am quite aware that it is quite complicated and will make you run out of nerves.:
This is the function IN which I liked to use my plugIn:
function switchMenuItem( id ) {
var $menuItem = $("#"+ id );
var $menu = $menuItem.parent();
var $menuImg = $menu.children(); //all siblings including selected element by id
var $prev = $menuItem.prev();
// calculate animation values
var index = $menuImg.index( $menuItem );
var ww = $(window).width();
var cssLeftPx = parseInt( $menuItem.css('left') );
var cssLeftPercent = 100 * cssLeftPx/ww;
if ( index == 1 ) { var dur = ww/2.4; };
if ( index == 2 ) { var dur = ww/1.5; };
$menuItem .stop(true)
.animate( { left: '10.5%' }, dur, 'easeOutSine', function() {
$(this) .prependTo($menu );
} );
$menuImg .first()
.stop(true)
.animate( { left: cssLeftPercent+'%' }, dur, 'easeOutSine', function() {
$(this) .insertAfter( $prev );
$menuItem.siblings()
.animate( { opacity: 1 }, 150, 'linear' )
.css( { cursor: 'pointer' } );
switchComplete = true;
subReady = true;
} );
…
}
and I would love to get rid of the query animate and substitute it with a smooth x translate with the help of Rico St Cruz transit plugIn (in the way I did successfully before with my kind of plugIn:
$.fn.translateLeft = function( left, duration, easing, callback ) {
var $this = $(this);
var currentLeftPx = parseInt( $this.css('left') );
var parentWidth = $this.parent().width();
// final left layout destination in px
var finalLeftPx = parentWidth/100 * left;
// actual distances to final left layout destination in px
var distanceLeftPx = currentLeftPx - finalLeftPx;
$this.transition( { x: -distanceLeftPx }, duration, easing, function() {
$this.stop(true).css( { left: left +'%', x: 0 } );
callback();
} );
}
So instead of „animate“ I want to use „translate Left“ which uses a smooth x translate and then return at the end a „cleaned up“ css position so that it is ready for other window resizing etc.
Did I explain myself? Any advice is appreciated a lot. Thank you in advance!

Related

How to use Mina in Snap svg?

This is an animation code using Snap svg:
var s = Snap(3000,3000);
var circle7 = s.circle(130,90,5);
var circle8 = s.circle(155,90,5);
var circle9 = s.circle(180,90,5);
var circle10 = s.circle(205,90,5);
var circle11 = s.circle(230,90,5);
var circle12 = s.circle(255,90,5);
circle.attr({fill:"#ffffff",opacity:0});
circle1.attr({fill:"#ffffff",opacity:0});
circle2.attr({fill:"#ffffff",opacity:0});
circle3.attr({fill:"#ffffff",opacity:0});
circle4.attr({fill:"#ffffff",opacity:0});
circle5.attr({fill:"#ffffff",opacity:0});
circle6.attr({fill:"#ffffff",opacity:0});
circle7.attr({fill:"#ffffff",opacity:0});
circle8.attr({fill:"#ffffff",opacity:0});
circle9.attr({fill:"#ffffff",opacity:0});
circle10.attr({fill:"#ffffff",opacity:0});
circle11.attr({fill:"#ffffff",opacity:0});
circle12.attr({fill:"#ffffff",opacity:0});
circle.animate({fill:"#0000FF",opacity:1},4500);
circle1.animate({fill:"#0000FF",opacity:1},4000);
circle2.animate({fill:"#0000FF",opacity:1},3500);
circle3.animate({fill:"#0000FF",opacity:1},3000);
circle4.animate({fill:"#0000FF",opacity:1},2500);
circle5.animate({fill:"#0000FF",opacity:1},2000);
circle6.animate({fill:"#0000FF",opacity:1},1500);
circle7.animate({fill:"#0000FF",opacity:1},4500);
circle8.animate({fill:"#0000FF",opacity:1},5000);
circle9.animate({fill:"#0000FF",opacity:1},5500);
circle10.animate({fill:"#0000FF",opacity:1},6000);
circle11.animate({fill:"#0000FF",opacity:1},6500);
circle12.animate({fill:"#0000FF",opacity:1},7000);
var cloud = s.image("D:/DigiMKey/login page_files/cloud.png", 0 , 260, 180,
125);
cloud.attr({opacity:0,width:100,height:65});
cloud.animate({opacity:1,width:200,height:125},1000)
var school =s.image("D:/DigiMKey/images/School-Icon.png", 265, 50, 100,100);
school.attr({opacity:0,width:80,height:80});
school.animate({opacity:1,width:100,height:100},2000)
I want to animate these objects using Mina so that they can be executed one after another.
Objects should fade in one by one.
how to do that?
This code gives no errors, however they all come at once instead of one after another.
There is a callback in animate function, use it to call the next animation.
var
s = Snap(300,300),
circle7 = s.circle(130,90,5).attr({fill:"#fff",opacity:0}),
circle8 = s.circle(155,90,5).attr({fill:"#fff",opacity:0}),
circle9 = s.circle(180,90,5).attr({fill:"#fff",opacity:0}),
circle10 = s.circle(205,90,5).attr({fill:"#fff",opacity:0}),
circle11 = s.circle(230,90,5).attr({fill:"#fff",opacity:0}),
circle12 = s.circle(255,90,5).attr({fill:"#fff",opacity:0}),
duration = 500,
props = {fill:"#00f",opacity:1};
/*
var anim = function() { circle.animate({fill:"#00f",opacity:1}, duration,mina.linear,anim1);}
var anim1 = function() { circle1.animate({fill:"#00f",opacity:1},duration,mina.linear,anim2);}
var anim2 = function() { circle2.animate({fill:"#00f",opacity:1},duration,mina.linear,anim3);}
var anim3 = function() { circle3.animate({fill:"#00f",opacity:1},duration,mina.linear,anim4);}
var anim4 = function() { circle4.animate({fill:"#00f",opacity:1},duration,mina.linear,anim5);}
var anim5 = function() { circle5.animate({fill:"#00f",opacity:1},duration,mina.linear,anim6);}
var anim6 = function() { circle6.animate({fill:"#00f",opacity:1},duration,mina.linear,anim7);}
*/
var anim7 = function() { circle7.animate(props,duration,mina.linear,anim8);}
var anim8 = function() { circle8.animate(props,duration,mina.linear,anim9);}
var anim9 = function() { circle9.animate(props,duration,mina.linear,anim10);}
var anim10= function() { circle10.animate(props,duration,mina.linear,anim11);}
var anim11= function() { circle11.animate(props,duration,mina.linear,anim12);}
var anim12= function() { circle12.animate(props,duration,mina.linear);};
anim7();
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>
There is nothing there that makes them animate in a sequence.
The way to animate in a sequence is to use a callback, which is part of the animate() method. So you can do...
circle1.animate({ fill:"#0000FF" }, 1000, mina.linear, callbackFunc2 );
function callbackFunc2() {
circle2.animate({ fill:"#0000FF" }, 1000, mina.linear, callbackFunc3 );
}
function callbackFunc3()...
And so on. Naturally that can feel a bit clunky when you have a lot, so I find it useful to add a sequence plugin to help. For example here
function nextFrame ( el, frameArray, whichFrame ) {
if( whichFrame >= frameArray.length ) { return }
el.animate( frameArray[ whichFrame ].animation, frameArray[ whichFrame ].dur, nextFrame.bind( null, el, frameArray, whichFrame + 1 ) );
}
I also extended it a bit and suggested it here (see the jsfiddle) which may be of use, if you're doing a lot of them.

Jquery splitter plugin getting error too much recursion

I am using this jquery splitter plugin located here: http://methvin.com/splitter/
It is working fine with the version of jquery I am using until I enable the resizeToWidth property then it is giving me the error: too much recursion.
Here is a link to a demo I created on jsfiddle: http://jsfiddle.net/S97rv/4/
Iv looked at the plugin code but im not a javascript expert and don't want to mess with it to much.
Can anybody see a solution to this error?
Here is the plugin code but probably better just looking at the jsfiddle link:
;(function($){
$.fn.splitter = function(args){
args = args || {};
return this.each(function() {
var zombie; // left-behind splitbar for outline resizes
function startSplitMouse(evt) {
if ( opts.outline )
zombie = zombie || bar.clone(false).insertAfter(A);
panes.css("-webkit-user-select", "none"); // Safari selects A/B text on a move
bar.addClass(opts.activeClass);
A._posSplit = A[0][opts.pxSplit] - evt[opts.eventPos];
$(document)
.bind("mousemove", doSplitMouse)
.bind("mouseup", endSplitMouse);
}
function doSplitMouse(evt) {
var newPos = A._posSplit+evt[opts.eventPos];
if ( opts.outline ) {
newPos = Math.max(0, Math.min(newPos, splitter._DA - bar._DA));
bar.css(opts.origin, newPos);
} else
resplit(newPos);
}
function endSplitMouse(evt) {
bar.removeClass(opts.activeClass);
var newPos = A._posSplit+evt[opts.eventPos];
if ( opts.outline ) {
zombie.remove(); zombie = null;
resplit(newPos);
}
panes.css("-webkit-user-select", "text"); // let Safari select text again
$(document)
.unbind("mousemove", doSplitMouse)
.unbind("mouseup", endSplitMouse);
}
function resplit(newPos) {
// Constrain new splitbar position to fit pane size limits
newPos = Math.max(A._min, splitter._DA - B._max,
Math.min(newPos, A._max, splitter._DA - bar._DA - B._min));
// Resize/position the two panes
bar._DA = bar[0][opts.pxSplit]; // bar size may change during dock
bar.css(opts.origin, newPos).css(opts.fixed, splitter._DF);
A.css(opts.origin, 0).css(opts.split, newPos).css(opts.fixed, splitter._DF);
B.css(opts.origin, newPos+bar._DA)
.css(opts.split, splitter._DA-bar._DA-newPos).css(opts.fixed, splitter._DF);
// IE fires resize for us; all others pay cash
if ( !$.browser.msie )
panes.trigger("resize");
}
function dimSum(jq, dims) {
// Opera returns -1 for missing min/max width, turn into 0
var sum = 0;
for ( var i=1; i < arguments.length; i++ )
sum += Math.max(parseInt(jq.css(arguments[i])) || 0, 0);
return sum;
}
// Determine settings based on incoming opts, element classes, and defaults
var vh = (args.splitHorizontal? 'h' : args.splitVertical? 'v' : args.type) || 'v';
var opts = $.extend({
activeClass: 'active', // class name for active splitter
pxPerKey: 8, // splitter px moved per keypress
tabIndex: 0, // tab order indicator
accessKey: '' // accessKey for splitbar
},{
v: { // Vertical splitters:
keyLeft: 39, keyRight: 37, cursor: "e-resize",
splitbarClass: "vsplitbar", outlineClass: "voutline",
type: 'v', eventPos: "pageX", origin: "left",
split: "width", pxSplit: "offsetWidth", side1: "Left", side2: "Right",
fixed: "height", pxFixed: "offsetHeight", side3: "Top", side4: "Bottom"
},
h: { // Horizontal splitters:
keyTop: 40, keyBottom: 38, cursor: "n-resize",
splitbarClass: "hsplitbar", outlineClass: "houtline",
type: 'h', eventPos: "pageY", origin: "top",
split: "height", pxSplit: "offsetHeight", side1: "Top", side2: "Bottom",
fixed: "width", pxFixed: "offsetWidth", side3: "Left", side4: "Right"
}
}[vh], args);
// Create jQuery object closures for splitter and both panes
var splitter = $(this).css({position: "relative"});
var panes = $(">*", splitter[0]).css({
position: "absolute", // positioned inside splitter container
"z-index": "1", // splitbar is positioned above
"-moz-outline-style": "none" // don't show dotted outline
});
var A = $(panes[0]); // left or top
var B = $(panes[1]); // right or bottom
// Focuser element, provides keyboard support; title is shown by Opera accessKeys
var focuser = $('')
.attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex, title: opts.splitbarClass})
.bind($.browser.opera?"click":"focus", function(){ this.focus(); bar.addClass(opts.activeClass) })
.bind("keydown", function(e){
var key = e.which || e.keyCode;
var dir = key==opts["key"+opts.side1]? 1 : key==opts["key"+opts.side2]? -1 : 0;
if ( dir )
resplit(A[0][opts.pxSplit]+dir*opts.pxPerKey, false);
})
.bind("blur", function(){ bar.removeClass(opts.activeClass) });
// Splitbar element, can be already in the doc or we create one
var bar = $(panes[2] || '<div></div>')
.insertAfter(A).css("z-index", "100").append(focuser)
.attr({"class": opts.splitbarClass, unselectable: "on"})
.css({position: "absolute", "user-select": "none", "-webkit-user-select": "none",
"-khtml-user-select": "none", "-moz-user-select": "none"})
.bind("mousedown", startSplitMouse);
// Use our cursor unless the style specifies a non-default cursor
if ( /^(auto|default|)$/.test(bar.css("cursor")) )
bar.css("cursor", opts.cursor);
// Cache several dimensions for speed, rather than re-querying constantly
bar._DA = bar[0][opts.pxSplit];
splitter._PBF = $.boxModel? dimSum(splitter, "border"+opts.side3+"Width", "border"+opts.side4+"Width") : 0;
splitter._PBA = $.boxModel? dimSum(splitter, "border"+opts.side1+"Width", "border"+opts.side2+"Width") : 0;
A._pane = opts.side1;
B._pane = opts.side2;
$.each([A,B], function(){
this._min = opts["min"+this._pane] || dimSum(this, "min-"+opts.split);
this._max = opts["max"+this._pane] || dimSum(this, "max-"+opts.split) || 9999;
this._init = opts["size"+this._pane]===true ?
parseInt($.curCSS(this[0],opts.split)) : opts["size"+this._pane];
});
// Determine initial position, get from cookie if specified
var initPos = A._init;
if ( !isNaN(B._init) ) // recalc initial B size as an offset from the top or left side
initPos = splitter[0][opts.pxSplit] - splitter._PBA - B._init - bar._DA;
if ( opts.cookie ) {
if ( !$.cookie )
alert('jQuery.splitter(): jQuery cookie plugin required');
var ckpos = parseInt($.cookie(opts.cookie));
if ( !isNaN(ckpos) )
initPos = ckpos;
$(window).bind("unload", function(){
var state = String(bar.css(opts.origin)); // current location of splitbar
$.cookie(opts.cookie, state, {expires: opts.cookieExpires || 365,
path: opts.cookiePath || document.location.pathname});
});
}
if ( isNaN(initPos) ) // King Solomon's algorithm
initPos = Math.round((splitter[0][opts.pxSplit] - splitter._PBA - bar._DA)/2);
// Resize event propagation and splitter sizing
if ( opts.anchorToWindow ) {
// Account for margin or border on the splitter container and enforce min height
splitter._hadjust = dimSum(splitter, "borderTopWidth", "borderBottomWidth", "marginBottom");
splitter._hmin = Math.max(dimSum(splitter, "minHeight"), 20);
$(window).bind("resize", function(){
var top = splitter.offset().top;
var wh = $(window).height();
splitter.css("height", Math.max(wh-top-splitter._hadjust, splitter._hmin)+"px");
if ( !$.browser.msie ) splitter.trigger("resize");
}).trigger("resize");
}
else if ( opts.resizeToWidth && !$.browser.msie )
$(window).bind("resize", function(){
splitter.trigger("resize");
});
// Resize event handler; triggered immediately to set initial position
splitter.bind("resize", function(e, size){
// Custom events bubble in jQuery 1.3; don't get into a Yo Dawg
if ( e.target != this ) return;
// Determine new width/height of splitter container
splitter._DF = splitter[0][opts.pxFixed] - splitter._PBF;
splitter._DA = splitter[0][opts.pxSplit] - splitter._PBA;
// Bail if splitter isn't visible or content isn't there yet
if ( splitter._DF <= 0 || splitter._DA <= 0 ) return;
// Re-divvy the adjustable dimension; maintain size of the preferred pane
resplit(!isNaN(size)? size : (!(opts.sizeRight||opts.sizeBottom)? A[0][opts.pxSplit] :
splitter._DA-B[0][opts.pxSplit]-bar._DA));
}).trigger("resize" , [initPos]);
});
};
})(jQuery);
The plugin you are using is based on a old jQuery version. For some reason, an infinite recursion was introduced by jQuery 1.6, probably due to event bubbling. It seems like a resize event triggered on a specific DOM element follow the event propagation path, all the way to document.
In the resize event handler, you can add a test to prevent recursion:
$(window).bind("resize", function (e) {
if (e.target === window) { splitter.trigger('resize'); }
});
That works, at least in Chrome and Firefox.
Using jQuery Migrate plugin will allow you to use jQuery 1.9 and even 2.0; but relying on browser specific behavior is generally a bad practice. You may have a look at this splitter.js fork, which already fixes your infinite recursion issue, using the same test as above.

JQuery: how to make a superposition of many moving animations which start asynchronously?

I want to make one animation superimposed on another. The second (the third, the fourth) animation can start asynchronously. To do that I need to specify difference between new and old positions (not absolute 'left').
E.g.
// One moment
$( '#my_div' ).animate( { 'leftShift': "+20px", 2000, 'easeOutQuad' } );
// Another moment, may be a second later
$( '#my_div' ).animate( { 'leftShift': "+50px" }, 2000, 'easeOutQuad' );
Is it possible to add results of several animations?
The graph to clarify what I want (X-axis: time, Y-axis: speed of distance change).
I'd like to see that speeds of animations are added, not the one-by-one animations.
What did Roko C. Buljan offer?
But I don't want deferred animations, I want a real-time animation.
Note. The current syntax ("+20px", "+50px") is not supported now. It's just for the example.
I solved the problem for my case.
I need very smooth animation. So, when a user initiates a new push, it should be like a new impulse. So, an object mustn't be stopped before.
I choose an 'easing' function for smooth movement - 'easeInOutQuad'. I implemented my own version (I removed not necessary parameters which was for standart 'easing' options of jQuery):
// Some browsers works bad if there is float px
function asyncAnimate( obj, props, duration, easing )
{
function _getTime()
{
var d = new Date();
return d.getTime();
}
var startTime = _getTime();
var duration = duration;
var animNum = asyncAnimate._animNum;
var propInts = {}; // to increment only ints
var propFloats = {};
for( var iProp in props )
{
var sProp = obj.css( iProp );
propFloats[ iProp ] = 0.0; // in the beginning all floats is 0
}
var animInterval = setInterval(
function()
{
var curTime = _getTime();
if( curTime <= startTime + duration )
{
var timeDiff = curTime - startTime;
var step = easing( timeDiff / duration, timeDiff, 0, 1, duration );
var dStep;
var prevStep = asyncAnimate._prevSteps[ animNum ];
if( prevStep == null )
{
dStep = step;
}
else
{
dStep = step - prevStep;
}
asyncAnimate._prevSteps[ animNum ] = step;
for( var iProp in props )
{
var prop = props[ iProp ];
// we can increment int px only (for crossbrowser solution),
// so, we need to save a float part
var propStep = prop * dStep;
// calculate total int part
var savedFloatPart = propFloats[ iProp ];
var totalPropStep = propStep + savedFloatPart;
var totalPropStepInt = parseInt( totalPropStep );
var totalPropStepFloat = totalPropStep - totalPropStepInt;
if( Math.abs( totalPropStepInt ) > 0 )
{
obj.css( iProp, "+=" + String( totalPropStepInt ) + "px" );
}
// reset saved int/float parts
propFloats[ iProp ] = totalPropStepFloat;
}
}
else
{
clearInterval( animInterval );
}
},
10
);
asyncAnimate._animNum++;
}
asyncAnimate._prevSteps = {};
asyncAnimate._animNum = 0;
Examples of usage (do not forgent to include a js with easing functions) or create your own:
asyncAnimate( $( '#div1' ), { 'margin-left': 50 }, 1000, $.easing.easeInOutElastic );
// ...
asyncAnimate( $( '.green' ), { 'width': -50, 'height': -50 }, 250, $.easing.easeInOutQuad );
You can see how it works (try to press buttons in very short intervals).
I hope it's easy to adapt it for some other types of animations.
It seems that animate() of jQuery does not support the behavior currently.
LIVE DEMO
The .stop() method will clear your current animation. You can use += and -= to update the current element position
Just for example:
<input type="button" value="50" />
<input type="button" value="-50" />
<input type="button" value="150" />
<input type="button" value="-150" />
<div id="my_div"></div>
$(':button').click(function(){
$('#my_div').stop().animate( { left: "+="+ this.value }, 2000 );
});
Logically if you don't need to clear the previous animation just remove .stop()

Javascript module pattern - what am I doing wrong?

A working version of this is here: http://est.pagodabox.com/client/svedka
I have the following function which I'm trying to convert into a module pattern, but when I try to use one of the function that I return at the bottom, for example:
est_project.closeContent($html);
I get an error that it's not a function. Is there something i'm doing wrong here?
Thanks!
var est_project = (function(){
// Setup functions
var flexDestroy,
cloneCurrent,
clonePosition,
switchSlide,
projectLayout,
contentHeight,
slidePos,
slideClick,
infoToggle,
closeContent;
// Destroy flexslider
flexDestroy = function($slider,$cleanSlider, $projBg) {
// Insert the clone of the un-initialized slide element, and remove the current flexslider
// Effectively "destroys" the current slider
var $curSlide = $slider.find('.flex-active-slide'),
// Get the zero based index of current slide
curSlideIndex = $curSlide.index() - 1,
curBg = $curSlide.find('img').attr('src'),
slideCount = $cleanSlider.data('count'),
i = 0,
$rearrange = $('');
// When you switch projects, the current slide should stay put
if(curSlideIndex !== 0 && slideCount > 1) {
// Cut from the current slide to the end, paste at the beginning
for(i = 0 ; i < slideCount; i += 1) {
if(curSlideIndex > i) {continue;}
$rearrange = $rearrange.add( $cleanSlider.find('li:eq(' + i + ')') );
}
$rearrange.remove();
$cleanSlider.find('li:first-child').before($rearrange)
$cleanSlider.css({'background-image' : 'url(' + curBg + ')'});
}
$slider.after($cleanSlider).remove();
clonePosition(slideheight);
};
return {
// Clone current
cloneCurrent: function($el) {
var $clean,
slideCount = $el.find('li').length;
$clean = $el.clone();
$clean.removeClass('project-current').find('div').removeClass('img-loading');
$clean.data('count',slideCount);
return $clean;
},
// Set the clone position, for when we add it to the DOM or resize the window
clonePosition: function(slideheight) {
var n = $cleanSlider.index(),
$myBg = $cleanSlider.find('div'),
myPosition = n * slideheight;
// Set the position of the inserted clone
$cleanSlider
.css({height: slideheight, top: myPosition, position : 'absolute'});
$myBg
.css({height: slideheight});
},
switchSlide: function($me, $slider) {
$('.project-current').removeClass('project-current');
$me.addClass('project-current');
// Get rid of current flexslider
flexDestroy($slider,$cleanSlider);
// Clone the unitialized slider so we can add it back in later when it gets destroyed
$cleanSlider = cloneCurrent($me);
$me.addClass('flexslider').flexslider({
animation: "slide",
animationSpeed: 500,
slideshow: false,
manualControls: '.dot-nav li a'
});
// After the flexslider initializes, slide the content
setTimeout(function(){
slidePos($me, $slidewrap, slideheight, $win);
},100);
},
// Custom "masonry" function, absolutely positions each project div according to the slide height
projectLayout: function(slideheight,$proj,$projBg) {
var n = 0;
$proj.each(function(){
var $me = $(this),
myPosition = n * slideheight;
// Set all the heights
$me
.css({top: myPosition, position : 'absolute'})
.add($projBg)
.css({height: slideheight});
n++;
});
},
// Set slide wrapper height to window height
contentHeight: function($win, $slidewrap) {
var winHeight = $win.height();
$slidewrap.css({height: winHeight});
},
// Set slide wrapper position to slide to the clicked slide, and set content position
slidePos: function($me, $slidewrap, slideheight, $win) {
var $contentText = $('.project-content .text'),
projNavHeight = Math.round( $win.height() * .1 ),
curIndex = $me.index(),
curTop = 0 - (curIndex * slideheight) + projNavHeight;
$slidewrap.css({transform: 'translate(0,' + curTop.toString() + 'px)'});
$('.corner-btn').add($contentText).css({'padding-top' : projNavHeight});
setTimeout(function(){
$slidewrap.removeClass('tr-none movin').addClass('tr-all');
$('.project').css({opacity: .4})
}, 100);
},
// Click a project, slide to it
slideClick: function($proj) {
$('.project').live('click',function(){
var $me = $(this),
myHref = $me.data('href'),
myTitle = $me.data('title'),
$slider = $('.flexslider'),
indexMy = $me.index(),
indexCur = $('.project-current').index(),
projDir;
$me.css({opacity: 1});
// Stop here if we click on the current project
if($me.hasClass('project-current')) {
return false;
}
History.pushState(null,myTitle,myHref);
});
},
// Hide and show content
infoToggle: function() {
// Open content
$('#corner-btn-info').on('click',function(){
$html.addClass('show-content');
if($('.project-content .text').height() <= $win.height()) {
$html.addClass('no-overflow');
}
$('.project-content-wrap').css({'z-index': 10});
});
// Close content
$('#corner-btn-close').live('click',function(){
closeContent($html);
});
},
closeContent: function($html) {
$html.removeClass('show-content');
setTimeout(function(){
$('.project-content-wrap').css({'z-index': -1});
$html.removeClass('no-overflow');
$('#classy').animate({scrollTop: 0})
},300);
}
};
});
The problem is that you're not executing the anonymous function, your code is the equivalent of:
var est_project = function() {};
You need to execute the function if you want it to return the functions defined in it.
Just replace the last line:
});
By:
}());
Or you can keep your code and call the closeContent function like this:
est_project().closeContent();
But I guess that's not what you want :-) You'd instantiate a new object everytime you call the est_project function.
At the start and end of your file just attach the object to window with the executed function and wrap whole function inside a self executing function. like this
(function(global) {
//your code goes here
global.est_project = est_project();
})(this)

How can a restart a loop in an animation?

I am trying to build a game like space invader (since I only started coding 5 days ago) where if a shoe hits the zombie, the zombie will disappear and reappear at the top of the screen (coming down again). I just can't seem to make the zombie go back to the top (they remain at the lowest point of the animation)
Below is the test for the collision:
function zombietestCollision(position1, size1, position2, size2) {
if (((position1.left + size1.width) > position2.left) &&
((position1.top + size1.height) > position2.top) &&
((position2.left + size2.width) > position1.left) &&
((position2.top + size2.height) > position1.top)) {
function loop () {
movedown($zombie);
moveup($zombie);
};
$(function zombieloop() {
setInterval( loop, 1 );
});
}
}
I have encompassed this test in my downward movement of the zombie
// down movement of the zombies
function movedown($zombie) {
$zombie.animate({
'left': 300,
}, {
duration:5000,
step:function(){
$.each($("#zombie"), function(index,zombie) {
var $zombie = $(zombie);
var $shoe = $("#shoe");
var shoeSize = {
height: $shoe.height(),
width : $shoe.width()
};
var zombieSize = {
height: $zombie.height(),
width : $zombie.width()
};
zombietestCollision($shoe.position(), shoeSize, $zombie.position(), zombieSize);
});
}
When I run this, the screen is just blank. What have I done in correctly?
If needed here is the full code: http://jsfiddle.net/JKd9K/7/
Sorry but I am completely new to programming, so it's hard for me to understand which part I did wrong. Cheers!
You need to be careful with how you're closing functions. Take a look at this http://jsfiddle.net/JKd9K/2/
Your movedown function should be like this
function movedown($zombie) {
$zombie.animate({
'left': 300
}, {
duration: 5000,
step: function() {
$.each($("#zombie"), function(index, zombie) {
var $zombie = $(zombie);
var $shoe = $("#shoe");
var shoeSize = {
height: $shoe.height(),
width: $shoe.width()
};
var zombieSize = {
height: $zombie.height(),
width: $zombie.width()
};
zombietestCollision(
$shoe.position(),
shoeSize,
$zombie.position(),
zombieSize);
});
}
});
}
Note that there's a bunch of extra braces at the end.

Categories

Resources