Jquery scroll navigation can't detect current section - javascript

I made a page that contains several divs with class content
<div class="content" id="content-0">content 1</div>
<div class="content" id="content-1">content 2</div>
<div class="content" id="content-2">content 3</div>
<div class="content" id="content-3">content 4</div>
<div class="content" id="content-4">content 5</div>
I also made 2 links that switch between next and previous div
<div class="nav">
<a id="prev" href="#">previous</a>
<a id="next" href="#">next</a>
</div>
I used TwinMax and ScrollTo plugins to make navigate between the divs
var section = 0;
var number = $('.content').length;
$("#next").click(function(e){
e.preventDefault();
if(section < number){
section++;
}
TweenMax.to(window, 0.5, {scrollTo:{y:$("#content-" + section).offset().top}});
});
$("#prev").click(function(e){
e.preventDefault();
if(section > 0){
section--;
TweenMax.to(window, 0.5, {scrollTo:{y:$("#content-" + section).offset().top}});
}
});
Here is aJSFiddle.
The problem is this:
When I scroll with the mouse to the last section and then click the next buttom , the page scrolls back to the second section .
How do I detect the current div so the next button goes to the next div correctly?

The accepted answer on this question might help you: Check if element is visible after scrolling
After checking if the element is on the page you could set section = element number.

Related

Prevent toggleClass to be used on every element on the page

I have a function which, when clicking on a link with the class .show-more, opens up the div with the class .productinfo. Now, it also adds a class to the link itself (.active) - the problem what I have is that I have a few links on this page with the same class. I've managed to only open up the correct .productinfo when clicking on it, but the class will be added to every link nonetheless. Also tried adding the following to the code but that did not work:
$(this).find('show-more').toggleClass("active");
My structure is the following:
<div class="main-content">
<div class="col-1">Content 1</div>
<div class="col-2">Content 2</div>
<div class="col-3"><a class="show-more">Show more</a></div>
<div class="productinfo">This content is hidden and will be shown when clicked</div>
</div>
<div class="main-content">
<div class="col-1">Content 1</div>
<div class="col-2">Content 2</div>
<div class="col-3"><a class="show-more">Show more</a></div>
<div class="productinfo">This content is hidden and will be shown when clicked</div>
</div>
jQuery(document).ready(function($) {
$('body').on('click', 'a.show-more', function(e) {
e.preventDefault();
$('.show-more').toggleClass("active");
var $this = $(this).parents('.product');
$this.find('.productinfo').toggle(0, 'slide')
});
});
Why not:
$('a.show-more').on('click', function(e)
and then
$(this).toggleClass("active");

JqMOBI change 'about button' target

You have the facility for a button in the jqMOBI header bar. I would like this to have a different target depending on what page you are on. I can't seem to find a event for the end of a page transition. So The only way I can see to do this is to add a function to each tap which seems a bit OTT.
The header looks like this..
<div id="header">
About
</div>
Any suggestions or an efficient method to keep track of the active hash and change the target of the button?
i see 3 solutions:
1.Specify a custom header block for each panel, and link them by adding data-header='main-header' to each panel div. e.g.
Note: For some reason, Stackoverflow is having trouble formatting my answer so i've included the fiddle as reference http://jsfiddle.net/JeEMf/ **
<div id='page1' class='panel' data-header='page1-header'>page 1</div>
<div id='page2' class='panel' data-header='page2-header'>page 2</div>
<div id='page1-header'>
<a href='#About1' class='button' style='float:right'>About Page 1</a>
</div>
<div id='page2-header'>
<a href='#About2' class='button' style='float:right'>About Page 2</a>
</div>
2.Specify a custom function to run on all panel change/loads. Similar to #1, add data-load='MyOnPageLoadFunc' to all panel divs. (see the jqMobi kitchensink demo for the function 'loadedPanel'. That's basically the solution) e.g.
<div id='global-header'>
<a id='global-header-href' href='#About' class='button' style='float:right'>About</a>
</div>
<div id='page1' class='panel' data-load='MyOnPageLoadFunc'>page 1</div>
<div id='page2' class='panel' data-load='MyOnPageLoadFunc'>page 2</div>
then create this function
function loadedPanel(pageDiv){
var href = '';
switch (pageDiv){
case 'page1': href='#about1';
break;
case 'page2': href='#about2';
break;
case 'page2': href='#about2';
break;
default : href='#about';
}
$('#global-header-href').attr('href', href);
}
3.Same as #2, but add your own custom 'data-' attribute for the header. e.g. data-header-link='#about' to all panel divs. e.g.
<div id='global-header'>
<a id='global-header-href' href='#About' class='button' style='float:right'>About</a>
</div>
<div id='page1' class='panel' data-load='MyOnPageLoadFunc' data-header-link='#about1'>page 1</div>
<div id='page2' class='panel' data-load='MyOnPageLoadFunc' data-header-link='#about2'>page 2</div>
<div id='page3' class='panel' data-load='MyOnPageLoadFunc' data-header-link='#about3'>page 3</div>
then create this function
function loadedPanel(pageDiv){
var href = $('#'+pageDiv).data('header-link');
$('#global-header-href').attr('href', href);
}

jquery change display mode

I have the following html file containing some bunch of div elements each having id and class. I created tabs and page assigned to each tab. The problem is looping through each parent div to set the display of the children div to a different class and make the clicked tab change it's background.
I tried the following :
function MakeActiveTab(CurrentPage, CurrentTab)
{
$('#PageID').children().filter(".pageParagraph").css('display','none');
$('#PageID').children().filter("#" + CurrentPage).css('display', 'block');
$('#Mainmenu').children().filter(".TabClass").css('background', '#fff');
$('#Mainmenu').children().filter("#" + CurrentTab).css('background', '#007700;');
}
but it doesn't work! any idea is appreciated.
<div id='Mainmenu'>
<div id='menu1' class='TabClass'>
Tab1
</div>
<div id='menu2' class='TabClass'>
Tab2
</div>
</div>
<div id='PageID'>
<div id='page1' class='pageParagraph'>
some content
</div>
<div id='page2' class='pageParagraph'>
some content
</div>
</div>
I created a javascript function creating pages and menus dynamically into their parent div. That's working fine except I can't get current Tab. When I did that with javascript, it worked but not on IE8.
HTML:
<div class="page first-page-name">
page 1
<div class="tab first-tab-name">tab 1</div>
<div class="tab second-tab-name">tab 2</div>
</div>
<div class="page second-page-name">
page 2
<div class="tab first-tab-name">tab 1</div>
<div class="tab second-tab-name">tab 2</div>
</div>
JS:
function showTabOnPage(tab, page) {
$('.page').hide().siblings(page).show();
$('.tab').hide().siblings(tab).show();
}
showTabOnPage('.first-tab-name', '.second-page-name');
Check out the demo: http://jsfiddle.net/vpetrychuk/3WtyF
If the structure of your page is not the same - sorry. But I hope the general idea will be clear for you.
found a way arround it. Thanks.
refID = document.getElementById('Mainmenu').childNodes;
for (i = 0; i < refID.length; i++)
{
if (refID[i].id == 'TabClass' + objID)
{
MakeActiveTab("TabClass" + objID, "pageParag" + objID);
return 0;
}
}
That's the majic!

jQuery - how to run one event while delaying another?

I'm a bit of a jQuery newbie, so forgive me if this seems a bit simple! I am setting up a sliding header system, which works very much like an accordion menu, however the links to open and close the elements are in a different part of the HTML, so all the accordion tutorials I found didn't work.
I have got this so far: HTML:
<div class="drawer" id="drawer_about"></div>
<div class="drawer" id="drawer_contact"></div>
<div class="drawer" id="drawer_hire"></div>
<div class="drawer" id="drawer_social"></div>
...
<ul class="navigation">
<li><span>About Me</span></li>
<li><span>Get In Touch</span></li>
<li><span>Hire Me</span></li>
<li><span>Social Networks</span></li>
</ul>
And jQuery:
$(document).ready(function(){
$("#drawer_about").hide();
$("#drawer_contact").hide();
$("#drawer_hire").hide();
$("#drawer_social").hide();
lastBlock = ("#drawer_hire");
$('.show_hide_about').click(function(){
$("#drawer_about").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_about");
});
$('.show_hide_contact').click(function(){
$("#drawer_contact").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_contact");
});
$('.show_hide_hire').click(function(){
$("#drawer_hire").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_hire");
});
$('.show_hide_social').click(function(){
$("#drawer_social").slideToggle(700);
$(lastBlock).hide(700);
lastBlock = ("#drawer_social");
});
});
Am I going OTT here? is there a simpler way to do this?
The main problem I'm having is it all works, however if the ABOUT ME panel is open and the user clicks the HIRE ME link, I get a weird effect. What I'd want in this situation is for the ABOUT ME panel to fold up, then the HIRE ME panel to fold down.
Hope that makes sense, thanks folks,
Alex
I'd set up the links like this: asdf
Then you all you need is:
$('.show').click(function(ev) {
var $visibleDrawer = $('.drawer:visible').eq(0); // make sure to get only one (or 0) drawer
// set currentSection to the drawer's id or empty if no drawer was found
var currentSection = $visibleDrawer.length?$visibleDrawer.attr('id').replace('drawer_',''):'';
$('.drawer').slideUp(700);
$('a.show').removeClass('active'); // reset all link classes
(function(clickedSection, $link){ //<-- pass the active link to have access to it inside the closure
if(currentSection != clickedSection){
$link.addClass('active'); // set active class on clicked link
setTimeout(function() {
$('#drawer_'+clickedSection).slideDown(700);
}, ($visibleDrawer.length?700:0)); // set the timeout to 0 if no drawer visible
}
})($(this).data('section'),$(this)); //<--
ev.preventDefault();
});
using .animate() you can parse a callback function which will be executed at the end of the animation, or you can use .queue() to keep track of the point of execution against and element. Some pseudo code of the first way
$('#foo').animate(function() {
// do stuff with foo
}, duration, easing, function() {
$('#bar').animate(function() {
// do stuff with bar
})
});
Here is a link to how it works on jsFiddle (Note that you should choose framework to be jQuery)
I think this would work with you :
$(document).ready(
function(){
$('.header').click(function(){
//To hide all other contents
$('.content').slideUp('slow');
var num=$(this).attr('id').split('_')[1];
//And show this one ..
$('#content_'+num).slideDown('slow');
});
}
);
HTML should look like this :
<div class="header" id="title_111">Category 1</div>
<div class="content" id="content_111">
</div>
<div class="header" id="title_112">Category 2</div>
<div class="content" id="content_112">
</div>
<div class="header" id="title_113">Category 3</div>
<div class="content" id="content_113">
</div>
<div class="header" id="title_114">Category 4</div>
<div class="content" id="content_114">
</div>
<div class="header" id="title_115">Category 5</div>
<div class="content" id="content_115">
</div>
<div class="header" id="title_116">Category 6</div>
<div class="content" id="content_116">
</div>

How can I hide elements in my list and add a 'show more' feature?

I'm using javascript to build a list of results. I have a for-loop that iterates over some data and creates a mydata div, and adds that to the results div. Let's pretend it looks something like this:
<div id="results">
<div class="mydata">data 1</div>
<div class="mydata">data 2</div>
...
<div class="mydata">data 20</div>
</div>
What I want to do is only display 5 results at a time, and should the user wish to see more, they can click a show next 5 or show more button (or something similar). Any ideas?
Just to clarify, every time the user clicks "show more" I want to 'unhide' the next 5 elements, not ALL the remaining elements. So each click reveals more elements until all are displayed.
You can use the gt() and lt() selectors along with :visible pretty well here.
The following will show the next 5 results on clicking and removes the link once all items are visible.
$('.mydata:gt(4)').hide().last().after(
$('<a />').attr('href','#').text('Show more').click(function(){
var a = this;
$('.mydata:not(:visible):lt(5)').fadeIn(function(){
if ($('.mydata:not(:visible)').length == 0) $(a).remove();
}); return false;
})
);
working example: http://jsfiddle.net/niklasvh/nTv7D/
Regardless of what other people are suggesting here, I would not hide the elements using CSS, but do it in JS instead, because if a user has JS disabled and you hide the elements using CSS, he won't get them visible. However, if he has JS disabled, they will never get hidden, nor will that button appear etc, so it has a full noscript fallback in place + search engines don't like hidden content (but they won't know its hidden if you do it on DOM load).
My solution is here: jsFiddle.
You can put this link somewhere:
show more
and use the following code:
var limit = 5;
var per_page = 5;
jQuery('#results > div.mydata:gt('+(limit-1)+')').hide();
if (jQuery('#results > div.mydata').length <= limit) {
jQuery('#results-show-more').hide();
};
jQuery('#results-show-more').bind('click', function(event){
event.preventDefault();
limit += per_page;
jQuery('#results > div.mydata:lt('+(limit)+')').show();
if (jQuery('#results > div.mydata').length <= limit) {
jQuery(this).hide();
}
});
where limit is your current number of results displayed and per_page is number of results shown with each click on "show more". The link disappears if all the results are displayed. See how it works on jsFiddle.
You can create a CSS class like:
.hiddenData { display: none }
and attach it to any quantity of divs that exceeds 5.
After that make handlers for adding/deleting this class from the needed quantity of divs.
jQuery for class removing:
$(".hiddenData").removeClass("hiddenData")
Create a class with something like:
.hidden_class{
display: none;
}
Add this class to all the mydata div's that you dont want seen.
when the user click the button, remove it from the next 5 div's.
repeat everytime the user clicks the "read more" button
This should work...Let me know how it goes
<script type="text/javascript">
function ShowHide(id) { $("#" + id).toggle(); }
</script>
<div id="results">
<div class="mydata">data 1</div>
<div class="mydata">data 2</div>
<div class="mydata">data 3</div>
<div class="mydata">data 4</div>
<div class="mydata">data 5</div>
<div style="clear:both" onclick="ShowHide('grp6')">More</div>
<div id="grp6" style="display:none">
<div class="mydata">data 6</div>
<div class="mydata">data 7</div>
<div class="mydata">data 8</div>
<div class="mydata">data 9</div>
<div class="mydata">data 10</div>
</div>
<div style="clear:both" onclick="ShowHide('grp11')">More</div>
<div id="grp11" style="display:none">
<div class="mydata">data 11</div>
<div class="mydata">data 12</div>
<div class="mydata">data 13</div>
<div class="mydata">data 14</div>
<div class="mydata">data 15</div>
</div>
</div>
In your forloop, you also have to add these divs hidden container
<div style="clear:both" onclick="ShowHide('grp6')">More</div>
<div id="grp6" style="display:none">
You get the idea.
Here you have:
<style>
/*This hides all items initially*/
.mydata{
display: none;
}
</style>
Now the script
<script>
var currentPage = 1; //Global var that stores the current page
var itemsPerPage = 5;
//This function shows a specific 'page'
function showPage(page){
$("#results .mydata").each(function(i, elem){
if(i >= (page-1)*itemsPerPage && i < page*itemsPerPage) //If item is in page, show it
$(this).show();
else
$(this).hide();
});
$("#currentPage").text(currentPage);
}
$(document).ready(function(){
showPage(currentPage);
$("#next").click(function(){
showPage(++currentPage);
});
$("#prev").click(function(){
showPage(--currentPage);
});
});
</script>
And a sample html:
<div id="results">
<div class="mydata">data 1</div>
<div class="mydata">data 2</div>
<div class="mydata">data 3</div>
<div class="mydata">data 4</div>
<div class="mydata">data 5</div>
<div class="mydata">data 6</div>
<div class="mydata">data 7</div>
<div class="mydata">data 8</div>
<div class="mydata">data 9</div>
<div class="mydata">data 10</div>
<div class="mydata">data 11</div>
<div class="mydata">data 12</div>
</div>
Previous
<span id="currentPage"></span>
Next
The only thing remaining is to validate fot not going to a page lower than 1 and higher than the total. But that will be easy.
EDIT: Here you have it running: http://jsfiddle.net/U8Q4Z/
Hope this helps. Cheers.

Categories

Resources