My script:
(function($){
$.fn.megaswitcher = function(settings) {
return this.each(function() {
var $i = $(this),
current,
childs = $i.find('.selection li').length; // returns desired number
$i.find('.selection li').delegate('.active', 'dblclick', function(e){
e.preventDefault();
current = $i.find('.selection li').index(this);
alert('triggered # ' + current); // doesn't even execute
var _delay = $(this).attr('name') > 0 ? (parseInt($(this).attr('name')) * 1000) : 5000;
$(this).delay(_delay).show(0, function(){
if((current + 1) < childs){ // if not last
$(this).removeClass('active').next().addClass('active').show(0, function(){
$i.find('.image img').addClass('tempp');
$(this).find('img').clone().hide().addClass('temp').appendTo($i.find('.image')).fadeIn(400, function(){
$i.find('.image img.tempp').remove();
});
}).trigger('dblclick');
}else{
$(this).removeClass('active');
$i.find('.selection li:first').addClass('active').show(0, function(){
$i.find('.image img').addClass('tempp');
$(this).find('img').clone().hide().addClass('temp').appendTo($i.find('.image')).fadeIn(400, function(){
$i.find('.image img.tempp').remove();
});
}).trigger('dblclick');
}
});
});
$i.find('.selection li.active').trigger('dblclick');
});
};
})(jQuery);
Gotta admit, that, that's a huge mess over there, but I have no idea why that delegate is not working...
Any ideas?
P.S. I have a different plugin based on this same technique with dblclick, that works flawlessly, except, it doesn't do item selection with find();, and I have a feeling that it's the thing that's causing the problem, but I don't know with that to replace it.
Thanks in advance!
You have to call delegate on the parent of the items that you want to attach the event.
Instead of:
$i.find('.selection li').delegate('.active' ...
you should do
$i.find('.selection').delegate('li.active'
Related
I've been trying to implement a feature that removes the transparency of the dropdown menu on my website so that it is actually readable for visitors.
The code I am currently using, which removes transparency on scroll but not on drop down is:
$(document).ready(function(){
var stoptransparency = 100; // when to stop the transparent menu
var lastScrollTop = 0, delta = 5;
$(this).scrollTop(0);
$(window).on('scroll load resize', function() {
var position = $(this).scrollTop();
if(position > stoptransparency) {
$('#transmenu').removeClass('transparency');
} else {
$('#transmenu').addClass('transparency');
}
lastScrollTop = position;
});
$('#transmenu .dropdown').on('show.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
});
$('#transmenu .dropdown').on('hide.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideUp(300);
});
});
I tried changing it to this (and variations of this) but can't seem to get it to work:
$(document).ready(function(){
var stoptransparency = 100; // when to stop the transparent menu
var lastScrollTop = 0, delta = 5;
$(this).scrollTop(0);
$(window).on('scroll load resize', function() {
var position = $(this).scrollTop();
if(position > stoptransparency) {
$('#transmenu').removeClass('transparency');
} else {
$('#transmenu').addClass('transparency');
}
lastScrollTop = position;
});
$('#transmenu .dropdown').on('show.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
$('#transmenu').removeClass('transparency');
});
$('#transmenu .dropdown').on('hide.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideUp(300);
$('#transmenu').addClass('transparency');
});
});
Any help would be greatly appreciated!
Thanks!
Without the html that this is hooking into it's a bit difficult to answer your question.
But given the fact that scrolling gets the job done, the only element I can see that could be preventing the functionality you want is that your selector to add show event handler is either selecting nothing in particular or an element in the DOM that is not the bootstrap dropdown element that triggers 'show.bs.dropdown', which is my reasoning for the first statement.
You can try the following debug code to verify:
// Should log to console with 'selected' if selector works alternatively 'not selected'
console.log($('#transmenu .dropdown').length > 0 ? 'selected' : 'not selected');
// Log to console when show event triggered
$('#transmenu .dropdown').on('show.bs.dropdown', function() {
console.log('triggered');
});
Hope that helps you find a solution. Happy coding!
see the documentation at http://api.jquery.com/on/ and it should become obvious why your fancy named events are never being triggered (without defining any event namespace in the first place).
$('#transmenu .dropdown')
.on('show', function() {})
.on('hide', function() {});
the DOM selector also might be #transmenu.dropdown instead of #transmenu .dropdown (depending if id and class attributes are present on the DOM node to select - or if one selects the parent node by id and there is/are nested node/s with a class attribute present).
I got this code, which works fine, until I change '.1' too colselect. I guess its because it gets the value too late and when I want to use colselect it haven't registered. Does anyone have any ideas on how to solve this?
$(document).ready(function() {
var colSelect;
$('.test2').mousedown( function(){
colSelect = '.' + $(this).attr('id');
});
$( '#1' ).resizable(
{handles:'e'},
{alsoResize: '.1'} // <- here I would like too change '.1' to colselect
);
});
Updated:
$(document).ready(function() {
var colSelect;
$('#one').on('mouseover' ,mousedwn);
function mousedwn(){
colSelect = '.' + $(this).attr('id');
resize(colSelect);
}
$('#one').on('mouseout' ,function(){
$('#one').off('mouseover' ,mousedwn); //prevent memory leaks
});
});
function resize(para){
$( '#1' ).resizable(
{handles:'e'},
{alsoResize: para}
);
}
Working Fiddle
I've been fiddling with this:
http://jsfiddle.net/bXJhe/46/
What I need is for the time to advance to the next div id after timer has cycled. I click on "one" and it shows the current id, then it should advance to "two", "three"... and show their respective ids. I do not want to use jQuery's .remove() or .detach(). Any insight would be fantastic.
Have a big project due, and no hair left to pull out.
HTML:
<span id="bar"></span>
<span id="timer">00:05</span>
<div id="one">one</div>
<div id="two">two</div>
<div id="three">three</div>
<div id="four">four</div>
JS:
jQuery(document).ready(function() {
jQuery('div').not(':first').hide();
jQuery('a').hide();
timer(5)
});
// Timer
var GLOBAL_TIMER;
function timer(intCount) {
GLOBAL_TIMER = setInterval(function() {
var intTickLength = 5;
jQuery('#bar').css('width', intCount * intTickLength + 'px');
jQuery('#timer').html('00:0' + intCount--);
if (intCount < 0) {
jQuery('a').show('slow');
jQuery('a').click(function() {
id = jQuery(this).parent('div').attr('id');
alert('current id: ' + id);
jQuery(this).hide();
timer(5);
});
stopTimer();
}
}, 1000);
}
function stopTimer() {
clearInterval(GLOBAL_TIMER);
}
Check and see if this is what you need:
jQuery(document).ready(function() {
jQuery('div').hide();
currDiv = jQuery('#one');
timer(5);
});
// Timer
var GLOBAL_TIMER;
function timer(intCount) {
GLOBAL_TIMER = setInterval(function() {
var intTickLength = 5;
jQuery('#bar').css('width', intCount * intTickLength + 'px');
jQuery('#timer').html('00:0' + intCount--);
if (intCount < 0) {
currDiv.show('slow');
currDiv.click(function() {
id = currDiv.attr('id');
alert('current id: ' + id);
jQuery(this).hide();
currDiv = currDiv.next();
timer(5);
});
stopTimer();
}
}, 1000);
}
function stopTimer() {
clearInterval(GLOBAL_TIMER);
}
The cleanest solution, I think, is to use jQuery's data() mechanism to attach a variable to each <div>, signaling that it's the next one to be shown.
Also, you have <a> elements inside your <div> elements, and you're sometimes trying to show/hide one or the other...it seems to me it would be clearer to always operate on the same element. I chose the <div> elements.
So, first you'll want to hide all your <div> elements:
jQuery('div').hide();
Then you'll want to indicate that the "one" <div> is the next one to be shown:
jQuery('#one').data('nextToBeShown',true);
Then when you're going through each element (I go through <div>s instead of <a>s), you just have to look to see if it's the next element to be shown, and show it:
jQuery('div').each(function() {
current = jQuery(this);
if( current.data('nextToBeShown') ) {
current.show('slow');
}
});
Finally, when you click on the link, you'll want to move the "nextToBeShown" pointer:
jQuery('a').click(function() {
id = jQuery(this).parent('div').attr('id');
alert('current id: ' + id);
div = jQuery(this).parent();
div.hide();
div.data('nextToBeShown',false);
div.next().data('nextToBeShown',true);
timer(9);
});
And that gets you where you want.... See my updated jsFiddle here: http://jsfiddle.net/NjUg2/1/
jsBin demo
Referring to my old answer and my old DEMO to you....
the only thing you need to add is this:
////////////// old answer :
(function($){ // remap "$" to jQuery
$(function(){ // "Document Ready" shorthand
var divCounter = 0; ///// added
function timer(bar, intCount){
var elWidth = $(bar).width(), intTickLength=intCount, i;
function math(){
var m = Math.floor(intCount/60);
var s = intCount % 60;
if(m<10){m='0'+m;}
if(s<10){s='0'+s;}
$(bar).next('.timer').text(m+':'+s);
$(bar).width( elWidth*intCount/intTickLength );
if(intCount--<=0){
clearInterval(i);
showDiv(); /////// added
}
}
math();
i = setInterval(math, 1000);
}
timer('#bar',5);
////////////////////////////////
///////////// new answer :
$('div.box').hide(); // hide all initially
function showDiv(){
$('.box').hide().eq(divCounter%$('.box').length).show();
}
$('.box a').click(function(e){
e.preventDefault();
$('.box').hide();
divCounter++;
timer('#bar',5);
});
/////////////////////////////
});
})(jQuery);
HTML: add a class .timer to your span
<span id="bar"></span>
<span class="timer">00:05</span>
and add a common CLASS to your div elements:
<div class="box">one</div>
<div class="box">two</div>
<div class="box">three</div>
<div class="box">four</div>
If you have questions feel free to ask, and don't pull more hair out, but review some old questions for some solutions :)
How can I stop this function from happening twice when a user clicks too fast?
$(document).ready(function() {
$(".jTscroller a").click(function(event) {
event.preventDefault();
var target = $(this).attr("href");
$("#photo").fadeTo("fast", 0, function() {
$("#photo").attr("src",target);
$("#photo").load(function() {
$("#photo").fadeTo("fast", 1);
});
});
});
});
The issue I'm having is that if a user clicks too fast the element won't fade back in, it just stays hidden.
The issue wasn't what I thought it was. When I was clicking on the same thumbnail it would try to load in the same image and stick loading forever. The .stop() answer does fix double animation so I'm accepting that answer, but my solution was to check if the last clicked item was the currently displayed item. New script:
$(document).ready(function() {
$(".jTscroller a").click(function(event) {
event.preventDefault();
var last = $("#photo").attr("src");
var target = $(this).attr("href");
if (last != target) {
$("#photo").stop().fadeTo("fast", 0, function() {
$("#photo").attr("src",target);
$("#photo").load(function() {
$("#photo").fadeTo("fast", 1);
});
});
};
});
});
Well you use the correct word in your descripton. Use stop()
$("#photo").stop().fadeTo("fast", 0, function() {
You may use a setTimeout function to make a delay between click grabs. I mean, a second click will be processed only after sometime, after the first click. It sets an interval between clicks.
$(document).ready(function() {
var loaded = true;
$(".jTscroller a").click(function(event) {
if(!loaded) return;
loaded = false;
event.preventDefault();
var target = $(this).attr("href");
$("#photo").fadeTo("fast", 0, function() {
$("#photo").attr("src",target);
$("#photo").load(function() {
$("#photo").fadeTo("fast", 1);
loaded = true;
});
});
});
});
Keep track of its state
I believe what you are looking for is .stop()
http://api.jquery.com/stop/
$("#photo").stop(false, false).fadeTo()
I would prevent it like this:
var photo = $("#photo");
if (0 == photo.queue("fx").length) {
foto.fadeTo();
}
I differs from stop as it will only fire when all animations on this element are done. Also storing the element in a variable will save you some time, because the selector has to grab the element only once.
Use on() and off() :
$(document).ready(function() {
$(".jTscroller a").on('click', changeImage);
function changeImage(e) {
e.preventDefault();
$(e.target).off('click');
$("#photo").fadeOut("fast", function() {
this.src = e.target.href;
this.onload = function() {
$(this).fadeIn("fast");
$(e.target).on('click', changeImage);
});
});
}
});
I am working on a "one page" website with a fixed navigation and about 5 different pages inside the one document.
UPDATED WORKING LINK
http://www.coco-works.com/Archive/ LIVE VERSION
I'm having trouble with the active class addition. When you click Keep in Touch or Home, the class is not applied. As you can see from the live version, it's not function properly.
The page works something like this;
And here is the JavaScript;
$(document).ready(function() {
$('body').click(function(event) {
if (event.target.nodeName.toLowerCase() == 'a') {
var op = $(event.target);
var id = op.attr('href');
if (id.indexOf('#') == 0) {
$.scrollTo(id, 1000, {
offset: {
top: 75
},
axis: 'y',
onAfter: function() {
window.location.hash = id.split('#')[1];
}
});
}
return false;
}
});
$.fn.waypoint.defaults.offset = 75;
$('.section h1.page_name').waypoint(function() {
var id = this.id;
var op = $('#navigation a[href = "#' + id + '"]');
if (op.length) {
$("#navigation a").removeClass("active");
op.addClass('active');
}
});
});
I'm not a strong programmer. I've tried to edit it as best as I can and I'm just stuck. Any insight to fixing this would highly be appreciated.
Still looking for an answer, below couldn't fix the problem.
I'm not sure what the waypoints plugin was doing, but I've refactored your code and it is working for me. Note that I took out the call to .waypoints, and changed your $('body').click() handler to be a more specific handler on the navigation link elements. This handler will scroll to each element and then will perform the removal and addition of the class correctly when the scrolling is done:
$(document).ready(function()
{
function highlightNav(navElement){
$("#navigation a").removeClass('active');
navElement.addClass('active');
}
$('#navigation a').click(function(event){
var nav = $(this);
var id = nav.attr('href');
$.scrollTo(id, 1000, {
offset: { top: -75 },
axis: 'y',
onAfter: function(){
highlightNav(nav);
}
});
return false;
});
$(window).scroll(function(){
if($(this).scrollTop() == 0){
highlightNav($("#navigation a[href*='home']"));
}
});
$.fn.waypoint.defaults.offset = 75;
$('.section h1.page_name').waypoint(function() {
var id = this.id;
var op = $('#navigation a[href = "#' + id + '"]');
if (op.length) {
highlightNav(op);
}
});
// Fancybox
$("a.zoom").fancybox({
'overlayShow' : false,
'transitionIn' : 'elastic',
'transitionOut' : 'elastic'
});
$("a.outside_shade").fancybox({
'titlePosition' : 'outside',
'overlayColor' : '#000',
'overlayOpacity' : 0.9
});
$("a.inside_white").fancybox({
'titlePosition' : 'inside'
});
$("a.inside_shade").fancybox({
'titlePosition' : 'over'
});
// validation
$("form").validate();
// nivo slider
$('#slider').nivoSlider();
});
In the html I added a default active class to the first link:
<div id="navigation">
<ul>
<li>Home</li>
<li>Portfolio</li>
<li>Who Are We?</li>
<li>Our Services</li>
<li>Features</li>
<li>Keep in Touch</li>
</ul>
</div>
Also I noticed on the page you have your css defined before the reset.css is called in. That's usually bad practice you might want to make sure reset.css is always the very first css file pulled in. It doesn't appear to have affected the page much but sometimes you'll get weird results doing that.
I made a jsfiddle of the results here: http://jsfiddle.net/RNsFw/2/
the waypoints plugin isn't needed anymore I think. I didn't change the fancybox or validation stuff because i'm not sure what those are doing and it wasn't really part of your issue.
I tested it in firefox and Chrome. Let me know if you have questions :)
http://jsfiddle.net/vCgy8/9/
This removes the dependency on scrollTo, and the waypoints plugin.
$('body').click(function(event)
{
if(event.target.nodeName.toLowerCase() == 'a')
{
var op = $(event.target);
var id = op.attr('href');
if(id.indexOf('#') == 0)
{
destination = $(id).offset().top;
$("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination}, 1000, function() {
var hash = id.split('#')[1];
window.location.hash = hash;
});
}
return false;
}
});
$(window).scroll(function (event){
makeActive();
});
function makeActive(){
var y = $(this).scrollTop();
if(y!==0){
$('.page_name').each(function(){
var curPos = parseInt($(this).offset().top - y);
if(curPos <= 0){
var op = $('#navigation a[href = "#'+$(this).attr('id')+'"]');
$("#navigation a").removeClass("active");
op.addClass('active');
}
});
}else{
$("#navigation a").removeClass("active");
$("#navigation a:first").addClass('active');
}
}
makeActive();
This may be completely unrelated, but I had a similar problem yesterday - where, in the callback of an event handler, jQuery operations weren't being performed in that scope but if you threw the code into something like:
setTimeout(function() {
$(selector).addClass('foo');
}, 0);
it would work - similar to how $.animate() functions (ish) if you call $(selector).stop().animate() without the queue param being false, eg:
$(selector).stop();
$(selector).animate({ foo }, { no queue:false here });
// ^ fail
$(selector).stop();
setTimeout(function() {
$(selector).animate({ foo }, { no queue:false here either });
}, 0);
// ^ success
The problem, completely unrelated to the above example though similar in behavior/functional hack, turned out to be the method of binding - in my case I had been using $.bind() - but then I refactored this to use $.delegate() ($.live() would work also) and it functioned as expected.
Again, not sure if this related, but figured I'd pass that along just in case. Unsure if it's a bug or just me not properly understanding some of the subtler parts of jQuery.
The problem is not in your js code, but in your css/page layout.
Or maybe the problem is that you are using the waypoint plugin and you might not want to for this particular page. (As you will see you also have trouble hitting the "Home" waypoint again once you have left it, because of the offset you use.)
The thing is, the waypoint plugin won't trigger until the target element you are scrolling to is in the very top of the browser window, with respect to the offset that is. "Keep in touch" will never get to the top unless your browser window is small enough that the "keep in touch" section takes up the entire browser window (minus the offset).
You can see it visualized here: