I have created a nice little javascript menu, which purposely doesn't use data tags as I was having issued with html purifier conflicts (another, long story).
Anyway, after alot of tinkering, the functionality and styling works exactly as I wanted, but with one exception - when I click on each menu item, it opens the content at different points on the screen, seemingly depending on the amount of content. I want it to always open at the top, so that the menu is always visible, along with the top of the content, and you can then scroll down as you wish.
I've been trying to resolve this for a while, so would appreciate any assistance, or amending of the attached fiddle.
Thanks in advance
Paul
https://jsfiddle.net/awcguxs5/
$(document).ready(function () {
var lastItem = null;
$('#listingmenu').on('click', 'a', function () {
newItem = this.getAttribute('href').substring(1);
if (newItem != lastItem) {
$('.current').not($(this).closest('li').addClass('current')).removeClass('current');
// fade out all open subcontents
$('.pbox:visible').hide(600);
// fade in new selected subcontent
$('#' + newItem).show(600);
lastItem = newItem;
}
}).find('a:first').click();
});
The problem is the references are still going to the corresponding ID locations. I've added one line of jquery that will scroll the page back to the top after the click. here is the line added:
$("html, body").animate({ scrollTop: 0 }, 1);
Here is your jsfiddle with this line:
https://jsfiddle.net/awcguxs5/2/
Let me know if this is what you were looking for! :)
$(document).ready(function () {
var lastItem = null;
$('#listingmenu').on('click', 'a', function () {
newItem = this.getAttribute('href').substring(1);
if (newItem != lastItem) {
$('.current').not($(this).closest('li').addClass('current')).removeClass('current');
// fade out all open subcontents
$('.pbox').hide( 600);
// fade in new selected subcontent
setTimeout( function(){$('#' + newItem).show(600)} , 600 );
lastItem = newItem;
}
}).find('a:first').click();
});
The settimeout fixes the issue and gives -i think- a nicer effect than firing the hide and the show simultaneously.
This happens precisely because you did not want to use "data tags".
Add this to onclick block:
$('#listingmenu').on('click', 'a', function (e) {
e.preventDefault();
.... //rest of your code.
e.preventDefault() will stop the default action of a-href, which in your case uses #div1 anchors to jump to that div.
Your updated fiddle here: https://jsfiddle.net/awcguxs5/3/
Related
I have having a little trouble with the slideToggle when I have a link inside of the slideup panel. What I am trying to do is have the ability to press a button and a div will slide up and display related posts and once you press another or the related project button on the page it will close the toggle and reveal another effect that I am using (100% width and heigh popup). The script I am using works perfect but I am running into one problem. When I click a related post inside of the slideToggle it causes the div to slide down instead of going to the page that represents the link.
Here is my code below and an example http://jsfiddle.net/K8vBg/15/.
$(document).ready(function(){
// build a variable to target the #menu div
var menu = $('#menu')
// bind a click function to the menu-trigger
$('#menu-trigger').click(function(event){
event.preventDefault();
event.stopPropagation();
// if the menu is visible slide it up
if (menu.is(":visible"))
{
menu.slideUp(1000);
}
// otherwise, slide the menu down
else
{
menu.slideDown(400);
}
});
$(document).not('.projectHolder-small,#projectSpecs').click(function(event) {
event.preventDefault();
if (menu.is(":visible"))
{
menu.slideUp(400);
}
});
})
If I change .projectHolder-small,#projectSpecs in the .not function to just read #menu then I am able to click the link inside of the panel but the panel will not slideDown when I click another button on the page. The popup from #project specs will just go over the panel instead of closing it.
Is there something I am missing in my script?
Thank you
Try changing the $(document).not().click() to:
$(document).click(function(event){
if(!$(event.target).closest('.projectHolder-small,#projectSpecs').length){
if (menu.is(":visible")){
menu.slideUp(400);
}
}
});
I am using closest() instead of the usual is(), so that even clicking on the children elements of '.projectHolder-small,#projectSpecs' the panel won't close.
I rewrote the script to the following and it works perfect
$(document).ready(function () {
var $frm = $('#menu').hide();
var $bts = $("#menu-trigger").on('click', function () {
var $this = $(this)
$bts.filter(".selected").not(this).removeClass('selected');
$this.toggleClass('selected');
if ($this.hasClass('selected') && $frm.is(':visible')) {
$frm.stop(true, true).slideUp(function () {
$(this).slideDown()
});
} else {
$frm.stop(true, true).slideToggle();
}
});
$bts.filter('.selected').click();
$("#projectSpecs, #menuButton").click(function () {
$bts.filter(".selected").removeClass('selected');
$frm.slideUp();
});
});
I have a button on a page which I have programmed to scroll to the next div in a large container. However, I also want the same button to scroll the browser window over a certain amount of pixels whenever I scroll to the left or the right of the page.
Here is what I have tried:
This scrolls the container over a div. Then I tried adding a function that said scroll window from "getOffset"
var colwidth = $('#container').width(),
contwidth = $('#contents').width(),
getOffset = function() {
return parseInt($('#container').css('margin-left'));
};
$(".left").click(function(){
if (getOffset() === 0) return false;
function scrollWindow(scrollValue) {
window.scrollBy(getOffset, 0);
}
$("#contents").animate({left: '+=' + colwidth},500);
$("#container").animate({'margin-left': '-=' + colwidth},500);
});
$(".right").click(function(){
if (getOffset() === contwidth - colwidth) return false;
$("#contents").animate({left: '-=' + colwidth},500);
$("#container").animate({'margin-left': '+=' + colwidth},500);
function scrollWindow(scrollValue) {
window.scrollBy(getOffset, 0);
}
});
</script>
Logically to me it seems like it should work, but my page ignores the function to scroll the window over. I would appreciate any help. Where is my logic wrong?
Thanks
To attach event handlers to dynamic elements, use the jQuery .on() method if you're using jQuery 1.7+. If you are using older versions, choose among .bind(), .delegate(), and .live() jQuery methods.
I've got the following problem (test version available http://jsfiddle.net/qmP8R/2/):
I have two <div> containing two versions of text and a third <div> used as a "container".
On load the container is populated with the shorten text. On the click of a button I want to change the short version for the long version with some animation (sliding up/down animation) and vice versa (swap short for long and long for short - basically toggle).
In the test version it works quite as expected, but I am not able to solve the following problems:
animation on 1st click does not work (but the text is changed to the long version)
on second click the whole container is slided up - not reverting to initial state
Basically what I waht to achieve is a kind of toggle behaviour, but connected with .text replacement rather than display: show/hide.
P.S.: AJAX content replacement is not available as a solution in my case.
How about sliding the text up, then changing it, and sliding it back down:
$(document).ready(function(){
$("#popis").text($("#popis_short").text());
var toggle_sw = true;
$("#popis_switch").click(function(){
var full = $("#popis_full").text(),
short = $("#popis_short").text();
if ( toggle_sw == true )
{
$("#popis").slideUp('slow', function () {
$(this).text(full).slideDown('slow');
});
toggle_sw = false;
}
else
{
$("#popis").slideUp('slow', function () {
$(this).text(short).slideDown('slow');
});
toggle_sw = true;
}
});
});
Here is a demo: http://jsfiddle.net/qmP8R/11/
Update
Since the text does not change, you can optimize your code a bit by selecting the text of the elements when the document is ready rather than doing so every-time the click event handler is called:
$(function(){
var $popis = $('#popis'),
toggle_sw = true,
full = $("#popis_full").text(),
short = $("#popis_short").text();
$popis.text(short);
$("#popis_switch").click(function(){
if ( toggle_sw ) {
$popis.slideUp('slow', function () {
$(this).text(full).slideDown('slow');
});
toggle_sw = false;
} else {
$popis.slideUp('slow', function () {
$(this).text(short).slideDown('slow');
});
toggle_sw = true;
}
});
});
Here is a demo of the optimized version: http://jsfiddle.net/qmP8R/13/
This example caches everything it can so no calculations have to happen that don't need to in the click event handler.
Check out JSFiddle. I've basically removed all the logic you had with changing the text.
There is a short div and a long div. The short div contains the first part and the long div contains the REST. Then all you need to do is slide up and down on the long div without changing any of the text.
This best way to do it in my opinion is to hide only the part of the text that should only be shown when you want the full text. This will save on the size of data required as well.
See my example here: http://jsfiddle.net/qmP8R/19/
The javascript is much simpler, and there is less html too:
$(document).ready(function(){
$("#popis_switch").on( 'click', function(){
if ( $("#popis_full").is(':visible') )
{
$("#popis_full").slideUp('slow');
}
else
{
$("#popis_full").slideDown('slow');
}
});
});
The sliding animation is hiding the toggle. I've edited the script to remove the animation and it shows the toggle working as intended. How you had it, the initial state is there but is hidden by the slide up.
$(document).ready(function(){
$("#popis").text($("#popis_short").text());
var toggle_sw = true;
$("#popis_switch").click(function(){
var full = $("#popis_full").text();
var short = $("#popis_short").text();
if ( toggle_sw == true )
$("#popis").text(full).slideDown('slow');
else
$("#popis").text(short).slideUp('slow').slideDown('slow');
toggle_sw = !toggle_sw;
});
});
EDIT:
Changing the order in the jquery chain, I was able to get a smooth animation:
$(document).ready(function(){
$("#popis").text($("#popis_short").text());
var toggle_sw = true;
$("#popis_switch").click(function(){
var full = $("#popis_full").text();
var short = $("#popis_short").text();
if ( toggle_sw == true )
$("#popis").slideUp('slow').text(full).slideDown('slow');
else
$("#popis").slideUp('slow').text(short).slideDown('slow');
toggle_sw = !toggle_sw;
});
});
Or : http://jsfiddle.net/qmP8R/24/
Here's the URL: http://174.120.239.48/~peakperf/
Here's the jQuery:
http://pastebin.com/fB16ahcZ
Site is still under heavy development.
If you mouse over "Services retention" on the carousel you will see what the function should work like. on hover a span element is faded in, on mouse out it hides. Some are stuck, some work fine. Also notice that when you click the right arrow and scroll through the carousel the spans get stuck "on".
Any help would be appreciated, thank you!
Your mark up is invalid as it is missing a closing "a" tag (see below)
</a>
Here is the error in your code.
<a href="#" id="homeslide6-show">
<img src="http://174.120.239.48/~peakperf/wp-content/themes/strausberg/images/home_service_retention.jpg" width="200" height="92" />
</li>
</ul>
Additionally your jquery code could be reduced by about 90% by using the each() function.
For example add a id to your ul and do it like so
<ul id="mycarousel">
jQuery('#mycarousel').find('span').each(function(){
jQuery(this).hover(function() {
jQuery(this).next().fadeIn('slow');
return false;
}, function(){
jQuery(this).next().fadeOut('slow');
return false;
});
});
Ps, this code is fixed to the current html structure, you should use classes for making it more flexible
You seem to have several tags with the same ID, which is not allowed. The ID is "homeslide6-show". You should also try stopping the animation, before starting and simplify your JavaScript to:
jQuery(document).ready(function() {
// hides the slickbox as soon as the DOM is ready
jQuery('#homeslide1, #homeslide2, #homeslide3, #homeslide4, #homeslide5, #homeslide6').hide();
// shows the slickbox on clicking the noted link Â
for (var i = 1; i <= 6; i++) {
jQuery('#homeslide' + i + '-show').parent().hover(
function(e, i) {
jQuery('#homeslide' + i).stop(true, true).fadeIn('slow');
e.preventDefault();
return false;
},
function(e, i){
jQuery('#homeslide' + i).stop(true, true).fadeOut('slow');
e.preventDefault();
return false;
}
);
}
});
and let me know if this works.
EDITED
My javascript above is incorrect. The following works:
jQuery(document).ready(function() {
// hides the slickbox as soon as the DOM is ready
jQuery('#homeslide1, #homeslide2, #homeslide3, #homeslide4, #homeslide5, #homeslide6').hide();
// shows the slickbox on clicking the noted link Â
for (var i = 1; i <= 6; i++) {
jQuery('#homeslide' + i + '-show').parent().data({element: '#homeslide' + i}).hover(
function() {
var element = jQuery('element');
jQuery(element).stop(true, true).fadeIn('slow');
return false;
},
function(){
var element = jQuery('element');
jQuery(element).stop(true, true).fadeOut('slow');
return false;
}
);
}
});
I have a small jQuery script:
$('.field').blur(function() {
$(this).next().children().hide();
});
The children that is hidden contains some links. This makes it impossible to click the links (because they get hidden). What is an appropriate solution to this?
This is as close as I have got:
$('.field').blur(function() {
$('*').not('.adress').click(function(e) {
foo = $(this).data('events').click;
if(foo.length <= 1) {
// $(this).next('.spacer').children().removeClass("visible");
}
$(this).unbind(e);
});
});
The uncommented line is suppose to refer to the field that is blurred, but it doesn't seem to work. Any suggestions?
You can give it a slight delay, like this:
$('.field').blur(function() {
var kids = $(this).next().children();
setTimeout(function() { kids.hide(); }, 10);
});
This gives you time to click before those child links go away.
This is how I ended up doing it:
var curFocus;
$(document).delegate('*','mousedown', function(){
if ((this != curFocus) && // don't bother if this was the previous active element
($(curFocus).is('.field')) && // if it was a .field that was blurred
!($(this).is('.adress'))
) {
$('.' + $(curFocus).attr("id")).removeClass("visible"); // take action based on the blurred element
}
curFocus = this; // log the newly focussed element for the next event
});
I believe you can use .not('a') in this situation:
$('.field').not('a').blur(function() {
$(this).next().children().hide();
});
This isn't tested, so I am not sure if this will work or not.