I have a mootools code:
(function() {
var index = 0;
Element.implement({
toggle: function() {
var args = Array.slice(arguments, 0);
count = args.length - 1;
return this.addEvent("click", function() {
args[index].apply(this, arguments);
index = (count > index) ? index + 1 : 0;
});
},
resetToggle: function() {
index = 0;
}
});
})();
document.getElement(".toggle").toggle(
function() {
document.id("menu").setStyle("display", "block");
}, function() {
document.id("menu").setStyle("display", "none");
}
);
});
How to hide/show div.menu container with animation?
Thanks!
haha this looks like my old toggle code :) do:
document.id('menu').setStyles({
display: 'block',
opacity: 0
}).fade(1);
and the opposite.
update to:
(function(){
var Element = this.Element,
Elements = this.Elements;
[Element, Elements].invoke('implement', {
toggle: function(){
var args = Array.prototype.slice.call(arguments),
count = args.length-1,
// start at 0
index = 0;
return this.addEvent('click', function(){
var fn = args[index];
typeof fn === 'function' && fn.apply(this, arguments);
// loop args.
index = count > index ? index+1 : 0;
});
}
});
}());
If you want to make a animation you could use reveal() / dissolve() available in MooTools-More
document.getElement(".toggle").toggle(function () {
document.id("menu").reveal();
}, function () {
document.id("menu").dissolve();
});
Note you had a pair }); too much in your code (last line)
Example
But if you would use more, there is already a .toggle() method you can use, that would give you just show/hide like this.
Related
I am trying to create a text rotator with a pause on 3 seconds in the end and then repeat. I have found a relevant script but have some problems with adding the pause in the end.
Codepen:
http://codepen.io/AmruthPillai/pen/axvqB/
Script:
(function($) {
$.fn.extend({
rotaterator: function(options) {
var defaults = {
fadeSpeed: 500,
pauseSpeed: 100,
child: null
};
var options = $.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = $(this);
var items = $(obj.children(), obj);
items.each(function() {
$(this).hide();
})
if (!o.child) {
var next = $(obj).children(':first');
} else {
var next = o.child;
}
$(next).fadeIn(o.fadeSpeed, function() {
$(next).delay(o.pauseSpeed).fadeOut(o.fadeSpeed, function() {
var next = $(this).next();
if (next.length == 0) {
next = $(obj).children(':first');
}
$(obj).rotaterator({
child: next,
fadeSpeed: o.fadeSpeed,
pauseSpeed: o.pauseSpeed
});
})
});
});
}
});
})(jQuery);
$(document).ready(function() {
$('#rotate').rotaterator({
fadeSpeed: 0,
pauseSpeed: 100
});
});
the function already uses pauseSpeed to delay the fadeOut so I added the following:
var nextDelay = $(next).is(':last-child') ? o.pauseSpeed + 3000 : o.pauseSpeed
I check if the next element .is(':last-child') and add 3000 to the value o.pauseSpeed
and used nextDelay instead of o.pauseSpeed to delay the fadeOut
Working CodePen
(function($) {
$.fn.extend({
rotaterator: function(options) {
var defaults = {
fadeSpeed: 500,
pauseSpeed: 100,
child: null
};
var options = $.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = $(this);
var items = $(obj.children(), obj);
items.each(function() {
$(this).hide();
})
if (!o.child) {
var next = $(obj).children(':first');
} else {
var next = o.child;
}
$(next).fadeIn(o.fadeSpeed, function() {
var nextDelay = $(next).is(':last-child') ? o.pauseSpeed + 3000 : o.pauseSpeed
$(next).delay(nextDelay).fadeOut(o.fadeSpeed, function() {
var next = $(this).next();
if (next.length == 0) {
next = $(obj).children(':first');
}
$(obj).rotaterator({child: next,fadeSpeed: o.fadeSpeed,pauseSpeed: o.pauseSpeed});
})
});
});
}
});
})(jQuery);
$(document).ready(function() {
$('#rotate').rotaterator({
fadeSpeed: 500,
pauseSpeed: 100
});
});
related code is this:
$(next).delay(o.pauseSpeed).fadeOut(o.fadeSpeed, function() {
I changed it to this:
var nextDelay = $(next).is(':last-child') ? o.pauseSpeed + 3000 : o.pauseSpeed
$(next).delay(nextDelay).fadeOut(o.fadeSpeed, function() {
$(next): is the next element selector.
.is(':last-child'): checks if $(next) element is the last-child of their parent
.delay(number of milliseconds): .delay() Set a timer to delay execution of subsequent items in the queue (fadeOut in this case).
.fadeOut(): Hide the matched elements by fading them to transparent.
var nextDelay: is defined using Conditional (ternary) Operator
You can wait for 3 seconds or whatever interval you like using setTimeout call. I've updated your code. Check http://codepen.io/anon/pen/XMJQYy
if (next.length == 0){
next = $(obj).children(':first');
setTimeout(function() {
$(obj).rotaterator({child : next, fadeSpeed : o.fadeSpeed, pauseSpeed : o.pauseSpeed});
}, 2000);
} else {
$(obj).rotaterator({child : next, fadeSpeed : o.fadeSpeed, pauseSpeed : o.pauseSpeed});
}
Lets see this script, that it's a simple carrousel
$script = {
init: function(){
this.heros(3000);
},
heros: function (time) {
var t;
var $hero = $('.hero');
var $images = $('.hero > div');
$hero.data('current', 0);
var $bullets = $('<div>').addClass('bullets');
for ( var i = 0; i<$images.length; i++ ) {
var $item = $('<span>');
$item.on('click', function () {
clearTimeout(t);
play( $(this).index() );
});
if(i==0) { $item.addClass('active') }
$bullets.append( $item );
}
var play = function (current) {
if(current==undefined) {
current = $hero.data('current');
}
var nextMargin;
if ( (current+1) == $images.length ) {
nextMargin = 0 ;
$hero.data('current',0);
} else {
nextMargin = (current + 1 )*100;
$hero.data('current', (current + 1));
}
$images.eq(0).css('marginLeft', -nextMargin + '%');
$bullets.find('span').eq($hero.data('current')).addClass('active').siblings().removeClass('active');
clearTimeout(t);
t = setTimeout(play, time);
}
$hero.append($bullets);
t = setTimeout(play, time);
},
}
The thing is that it works great, but only if there's just one .hero element.. if there are multiple the bullets mix up and it doesn't respect the .length
I know that option one should be rewrite it again, but Does anyone of you sees a quick fix that would make it reusable?
A single fiddle: https://jsfiddle.net/6z8n5pnq/
A multiple fiddle: https://jsfiddle.net/6z8n5pnq/1/
-EDIT-
I tried:
Defining a previous function, that is called on init
preheros: function(time) {
var self = this;
$('.heros').each(function(){
self.heros($(this), time);
});
},
And editing The begining of heros:
heros: function ($hero, time) {
var t;
/*var $hero = $('.hero');*/
var $images = $hero.find('>div');
but no success...
any idea?
-EDIT-
GOD, it's $('.hero').each not $('.heros').each it was working!
The easiest way to do this is to isolate context for each .hero component by using $(selector).each function. Slightly corrected your fiddle https://jsfiddle.net/6z8n5pnq/2/
function apply($hero, time){
var t;
var $images = $hero.children('div');
//all your logic here...
}
$script = {
init: function () {
this.heros(3000);
},
heros: function (time) {
$('.hero').each(function(){
apply($(this), time);
});
},
}
I'm struggling to understand why the transitions don't behave as expected. It's supposed to apply the "from", then add the "transition" to the "el", then it's supposed to run "to" and finally onTransitionEnd it's supposed to run "callback" (prepended to which is a bit of code which clears the transition properties).
In Webkit browsers, it transitions slideDown correctly, but slideUp is instant. Reverse is true in Firefox.
Erg?
JSFiddle: http://jsfiddle.net/enhTd/
var $ = function(query) {
var a = [],
n = document.querySelectorAll(query),
l = n.length;
for( var i = 0; i<l; i++){
a.push(n[i]);
}
if(l>1) {return a;} else {return a[0];}
},
$id = function(query) { return document.getElementById(query);},
getSupportedPropertyName = function(properties) {
for (var i = 0; i < properties.length; i++) {
if (typeof document.body.style[properties[i]] != "undefined") {
return properties[i];
}
}
return null;
},
vendorTransitions = ["transition", "msTransition", "webkitTransition", "MozTransition", "OTransition"],
prefixedTransitionProperty = getSupportedPropertyName(vendorTransitions),
transition = function(opts){
opts.from && opts.from();
if(prefixedTransitionProperty){
var c = opts.callback || function() {},
el = opts.el,
cb = function(event){
var ev = event, callback = c;
ev.target.removeEventListener(prefixedTransitionProperty+"End", cb);
ev.target.style[prefixedTransitionProperty] = "none";
if(callback) {
callback(ev);
}
};
el.style[prefixedTransitionProperty] = opts.transition || "";
el.addEventListener(prefixedTransitionProperty+"End", cb);
}
opts.to && opts.to();
},
slideDown = function(el, t){
var style = el.style,
h, oh = el.offsetHeight,
t = t || 1000;
//Grab real height
style.height = "";
h = el.offsetHeight;
transition({
"el": el,
transition: "height "+t+"ms ease",
from: function() {
style.height = oh+"px";
},
to: function(){
style.overflow = "hidden";
style.height = h+"px";
},
callback: function(event){
event.target.style.height = "";
}
});
},
slideUp = function(el, t){
var style = el.style,
h = el.offsetHeight,
t = t || 1000;
transition({
"el": el,
transition: "height "+t+"ms ease",
from: function() {
style.height = h+"px";
},
to: function(){
style.overflow = "hidden";
style.height = "0";
}
});
},
slideToggle = function(el, t){
var t = t || 1000;
if(el.style.height=="0px"){
slideDown(el, t);
} else {
slideUp(el, t);
}
};
slideUp($id("intro"));
$("a[href='#intro']").forEach(function(el){
el.addEventListener("click", function(ev) {
ev.preventDefault();
if(ev.target.classList.contains("hide")){
slideUp($(ev.target.hash));
} else {
slideDown($(ev.target.hash));
}
});
});
$("li h3").forEach(function(el){
el.addEventListener("click", function(ev) {
ev.preventDefault();
slideToggle(ev.target.parentNode);
});
});
In some browsers, you cannot just set the initial state, set the final state and expect a CSS transition to work.
Instead, the initial state must be set and then it must be rendered before you can set the final state and expect the transition to run. The simplest way to cause it to be rendered is to return back to the event loop and then do any further processing (like setting the final state) after a setTimeout() call.
try this: http://jsfiddle.net/enhTd/1/ (tested in chrome and ff)
first: do what jfriend00 talked about:
in your transition function:
transition = function (opts) {
..
setTimeout(function() {
opts.to && opts.to();
}, 1)
}
second: the callback wasn't necessary in your slideDown() method:
slideDown = function (el, t) {
..
take this out:
/*callback: function (event) {
event.target.style.height = "";
}*/
});
from a design point of view.. the callback function wasn't adding any value.. you should just continue from where you left off when it comes to transitions.
third: disable slide down when the slide is already down.. but I'll leave that to you.
I have the code below but I cannot call nextPromo because it is not a function. How can I make this work? I am trying to setup a rotator using object oriented style. I am new to it so i am very confused. I have tried many things but I jsut don't know and I am very frustrated with it, please help
function promoSlides(s){
this.index = 0;
this.prevIndex = 0;
this.currentVeh = "";
this.t;
this.slides = s;
this.len = this.slides.length;
this.sortWeight = function(){
($('body').hasClass('en')) ? this.slides.sort(SortByWeight) : this.slides.sort(SortByWeightFr);
};
function SortByWeight(a,b) { return b.weight - a.weight; }
function SortByWeightFr(a,b) { return a.frWeight - b.frWeight; }
this.startTimer = function(){ this.t = setTimeout("this.nextPromo()", 3000); }
this.nextPromo = function(){
if(this.index > 0 || this.prevIndex > 0) $(this.slides[this.prevIndex].el).css("display","none");
$(this.slides[this.index].el).css("display","block");
this.prevIndex = this.index;
this.index = (this.index < this.len-1) ? this.index+1 : 0;
this.startTimer();
}
return true;
} ;
Actually, nextPromo is a function. You can call it like:
this.nextPromo();
Or, if that doesn't work, you can just call it like a normal function:
nextPromo();
See this jsFiddle for an example of this kind of function.
Hope this helps.
EDIT: Here is a simplified example which I have tested. This uses setInterval to periodically advance the slide index. The "next" functionality is contained within an anonymous function.
function promoSlides(s) {
this.startTimer = function () {
setInterval(
function () {
alert("called");
// if (this.index > 0 || this.prevIndex > 0) {
// $(this.slides[this.prevIndex].el).css("display", "none");
// }
// $(this.slides[this.index].el).css("display", "block");
// this.prevIndex = this.index;
// this.index = (this.index < this.len - 1) ? this.index + 1 : 0;
}, 3000
);
}
return true;
};
var p = new promoSlides(null);
p.startTimer();
You're assigning a function to this.nextPromo, so calling this.nextPromo(); should work.
I'm trying to add an image rotator to my site but for some reason firebug tells me the function I need to call to start the rotator isn't defined. My jQuery file is loading just fine and the image rotator script is loading so I'm not sure what is wrong. The site is heritage.newcoastmedia.com but I'll go ahead and post the script:
;(function($) {
$.fn.featureList = function(options) {
var tabs = $(this);
var output = $(options.output);
new jQuery.featureList(tabs, output, options);
return this;
};
$.featureList = function(tabs, output, options) {
function slide(nr) {
if (typeof nr == "undefined") {
nr = visible_item + 1;
nr = nr >= total_items ? 0 : nr;
}
tabs.removeClass('current').filter(":eq(" + nr + ")").addClass('current');
output.stop(true, true).filter(":visible").fadeOut();
output.filter(":eq(" + nr + ")").fadeIn(function() {
visible_item = nr;
});
}
var options = options || {};
var total_items = tabs.length;
var visible_item = options.start_item || 0;
options.pause_on_hover = options.pause_on_hover || true;
options.transition_interval = options.transition_interval || 5000;
output.hide().eq( visible_item ).show();
tabs.eq( visible_item ).addClass('current');
tabs.click(function() {
if ($(this).hasClass('current')) {
return false;
}
slide( tabs.index( this) );
});
if (options.transition_interval > 0) {
var timer = setInterval(function () {
slide();
}, options.transition_interval);
if (options.pause_on_hover) {
tabs.mouseenter(function() {
clearInterval( timer );
}).mouseleave(function() {
clearInterval( timer );
timer = setInterval(function () {
slide();
}, options.transition_interval);
});
}
}
};
});
And here is the script to start the image rotator:
<script language="javascript">
$(document).ready(function() {
$.featureList(
$("#tabs li a"),
$("#output li"), {
start_item : 1
}
);
});
</script>
Your code creates an anonymous function, but doesn't call it.
You need to call the function by adding (jQuery) at the end.
You cannot do $.featureList(
See Chrome error:
The plugin needs to applied to an object
You've just slightly missed out on the right syntax for creating a plugin. What you really want is:
(function($) {
$.fn.featureList = function() { // etc; }
$.featureList = function() { // yet more etc; }
})(jQuery);