JQuery Scrolling/Paging Tabs - javascript

I am trying to create a simple tab bar for a site that has the ability to scroll for tabs that do not fit on the page. This is quite simple and does not need to have any ajax or dynamically loaded content...it simply displays all the tabs, and when you click one, it takes you to another page.
I have scoured the internet and can not seem to find anything other than:
http://www.extjs.com/deploy/dev/examples/tabs/tabs-adv.html
however this is very heavy and complicated...I am looking for a lightweight example in jquery. If anyone can help I would be grateful!

I ended up writing it myself with a div who's overflow is set to hidden. Then used the jquery below to move the tabs in the div.
$(document).ready(function()
{
$('.scrollButtons .left').click(function()
{
var content = $(".tabs .scrollable .content")
var pos = content.position().left + 250;
if (pos >= 0)
{
pos = 0;
}
content.animate({ left: pos }, 1000);
});
$('.scrollButtons .right').click(function()
{
var content = $(".tabs .scrollable .content")
var width = content.children('ul').width();
var pos = content.position().left - 250;
//var width = content.width();
if (pos <= (width * -1) + 670)
{
pos = (width * -1) + 600;
}
content.animate({ left: pos }, 1000);
});
});
My Html looked like this:
<div class="tabs">
<div class="scrollable">
<div class="content">
<ul>
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
<li>Tab4</li>
<li>Tab5</li>
</ul>
</div>
</div>
<div class="scrollButtons">
<ul>
<li>
<div class="left">
</div>
</li>
<li>
<div class="right">
</div>
</li>
</ul>
</div>
</div>

I have just created a plugin myself:
Project home: http://jquery.aamirafridi.com/jst

Could you simply wrap the tabs in a DIV with overflow-x: auto set in the CSS?

I always use JQuery UI tabs as a starting point for tabs. You can customize the JQuery UI download in the download section of the website. This method should be lighter than any other implementation, if you are already using JQuery on your website.
Out of the box, the JQuery UI tabs will not give you the scrolling you desire. This I believe could be achieved by altering the CSS, but more than likely will be easier if you alter the navigation of your site (i.e. create more levels, use shorter titles).
Hope this helps

Related

Separating content within div with Jquery

I have the following HTML:
<div class="page">
<div class="somecontent_1">...</div>
<div class="somecontent_2">...</div>
<div class="somecontent_3">...</div>
<div class="somecontent_4">...</div>
</div>
Now I'd like to separate the content with a separate page so it looks something like this:
<div class="page">
<div class="somecontent">...</div>
<div class="somecontent">...</div>
</div>
<div class="newpage">
<div class="somecontent">...</div>
<div class="somecontent">...</div>
</div>
The function checks the height of each class somecontent and if it's larger than a certain amount, I need to move the content to a new page.
My guess is that I would need to create an empty div (newpage) and then fetch the elements after the height is exceeded and move them to the empty newpage and continue iterate like that.
My question would be how I would get all content that are after the last element that reached the height so I can move it to the new empty page that I would create. Other solutions are most welcome if there is a better way of doing it!
The code I came up with looks like this:
var page = $('.page');
var pageHeight = 0;
$.each(page.find('.somecontent'), function() {
if (pageHeight > 1000) {
page.next('<div class="newpage"></div>');
/* Somehow get all elements to add to the newly created page */
page.next('.newpage').append(<NEXT_ELEMENTS>);
pageHeight = 0;
}
pageHeight = pageHeight + $(this).height();
});
When you reach the page which answers the height criterion use the .nextAll function to get all the next siblings of it, then use .wrapAll to wrap them with your newpage div.
Here is the corresponding documentation of nextAll and wrapAll, it has everything you need to cover your scenario.
See comments in line below.
// Instead of the $.each() utiility function
// Just loop over each content area that needs
// examination
$('.somecontent').each(function(index, item) {
// Check if the height of the item is greater than the target (20px for this example)
if (parseInt(getComputedStyle(item).height,10) > 20) {
// Make a new div after the div that the item is currently in
// if one doesn't already exist
if($(".newpage").length === 0){
$(item.closest(".page")).after('<div class="newpage"></div>');
}
// Move the item into the new div
$(item.closest(".page")).next('.newpage').append(item);
}
});
//console.log(document.body.innerHTML); // shows resulting HTML
div.page {border:1px solid red; }
div.newpage {border:1px solid green; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="page">
<div class="somecontent">This<br>is<br>some<br>content</div>
<div class="somecontent">This is some content</div>
<div class="somecontent">
<ul>
<li>This</li>
<li>is</li>
<li>some</li>
<li>content</li>
</ul>
</div>
<div class="somecontent">Other</div>
</div>

Javascript removeClass/toggleClass works on desktop but not responsive page

I bought this theme a while back and have been chopping it up and modifying it to add/remove functionality. There is this slidein menu that appears on the page once a link is clicked from the navbar menu. The issue is that there is an X button to close the menu that is supposed to toggle/remove a class from the #btn-offcanvas-menu element when it is clicked (#btn-close-canvasmenu is clickable element); it works on the desktop but not the responsive mobile site. The only way it is toggled/removed on mobile is if the original link is clicked again. I have looked at the below questions here, and several others, including trying to use the closest/find options but nothing seems to work. What am I missing?
Desired behavior: the isLeft class should toggle/be removed when the #btn-close-canvasmenu link is clicked. It is on desktop but not mobile.
Javascript not working on mobile but works on desktop.
JavaScript - removeClass not working?
ToggleClass and RemoveClass not working
JQuery - ToggleClass/AddClass/RemoveClass
How to toggle class of closest element jquery toggle class on closest span
This is relevant portion of the index page...
<li id="recent-mobile"><!-- this is hidden by CSS on desktop -->
<a id="btn-offcanvas-menu" href="#">Recent Results</a>
</li>
<li id="recent-results"><!-- this is hidden by CSS on mobile -->
<div class="header-buttons pull-right hidden-xs hidden-sm">
<div class="navright-button">
<i class="fa fa-bars"> Recent Results</i>
</div>
</div>
</li>
<!-- Menu OffCanvas right begin -->
<div class="navright-button">
<div class="compact-menu-canvas" id="offcanvas-menu">
<h3>menu</h3><a id="btn-close-canvasmenu"><i class="fa fa-close"></i></a>
<nav>
<ul class="clearfix">
<li>Home</li>
<li>Features</li>
<li>Pages</li>
<li>Portfolios</li>
<li>Shop</li>
<li>Blog</li>
<li>Contact Us</li>
</ul>
</nav>
</div>
</div>
<!-- Menu OffCanvas right close -->
This is the relevant portion of the javascript compact.js file...
$("#btn-close-canvasmenu").on("click", function() {
$("#offcanvas-menu").stop().animate({
right: "-260px"
}, 300), $("a#btn-offcanvas-menu").removeClass("isLeft")
});
$(document).on("click", "#btn-offcanvas-menu, #btn-offcanvas-menu-mobile", {} , function(a){
var id = $(this).attr('id');
if (id === "btn-offcanvas-menu-mobile") {
$("#btn-close-canvasmenu").toggleClass("mobile");
}
return a.preventDefault(), $(this).hasClass("isLeft") ? $("#offcanvas-menu").stop().animate({
right: "-260px"
}, 300) : $("#offcanvas-menu").stop().animate({
right: "0px"
}, 300), $(this).toggleClass("isLeft"), false
});
EDIT (fixed 2/16/20): I edited the js file file to reflect this updated function: $("#btn-close-canvasmenu").on("click", function()
Essentially, what fixed it was changing the selector from #btn-offcanvas-menu to a#btn-offcanvas-menu. Not sure why that worked as opposed to using closest/find method but once I did, it toggled/removed the class on both desktop and mobile correctly. If anyone has anything thoughts on why the a made the difference with the selector, I'd appreciate the feedback as I am not an expert on js/jQuery. Otherwise, this can be considered closed.
Changing the selector in the compact.js file from #btn-offcanvas-menu to a#btn-offcanvas-menu fixed the issue and while this worked, it was the wrong way to correct the issue as connexo pointed out due to the duplicate ids.
The correct way to resolve this was to change the mobile navbar itself so I could use an id specifically for the mobile that only appeared there.
<nav id="mobile-menu" class="site-mobile-menu hidden-lg hidden-md">
<ul>
<li id="recent-mobile">
Recent Results
</li>
</ul>
</nav>
Next I changed the js function that populated the html for the mobile menu to use prepend instead of append so it populated everything above the Recent Results link...
$("#desktop-menu > ul").children().clone().prependTo($("#mobile-menu > ul")), $("#show-mobile-menu").on("click", function() {
$(this).toggleClass("clicked"), $("#mobile-menu > ul").stop(true, true).slideToggle()
});
Then I tweaked the js function to toggle the class to mobile for the #btn-close-canvasmenu if the selector was #btn-offcanvas-menu-mobile to be used later...
$(document).on("click","#btn-offcanvas-menu,#btn-offcanvas-menu-mobile", {} , function(a){
var id = $(this).attr('id');
if (id === "btn-offcanvas-menu-mobile") {
$("#btn-close-canvasmenu").toggleClass("mobile");
}
return a.preventDefault(), $(this).hasClass("isLeft") ? $("#offcanvas-menu").stop().animate({
right: "-260px"
}, 300) : $("#offcanvas-menu").stop().animate({
right: "0px"
}, 300), $(this).toggleClass("isLeft"), false
});
Finally, I tweaked the js function that closed the menu to check the class to determine which id to toggle the isLeft class for...
$(document).on("click","#btn-close-canvasmenu", {} , function(a){
var id = $(this).attr('id');
if ($(this).hasClass("mobile")) {
var container = $("#btn-offcanvas-menu-mobile");
$("#btn-close-canvasmenu").toggleClass("mobile");
} else {
var container = $("#btn-offcanvas-menu");
}
$("#offcanvas-menu").stop().animate({
right: "-260px"
}, 300), container.removeClass("isLeft")
});

Highlight active div after scroll

Is there an easy way to highlight a top with id (apply css-class with specific color f.e.) after user scrolls to it? I have a scrollspy on page, but it seems that plugin will not help me, so I can't make to ends meet.
P.S. I didn't find alike info in Google or StackOverflow, so please, don't get me wrong.
There is a rough example of page
https://jsfiddle.net/masyurik/kdnzdeb2/#&togetherjs=DeaMiBADpp
HTML
<div id="secA" class="section">
Hello it's secA
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="secB" class="section">
Hello it's secB
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="secC" class="section">
Hello it's secC
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
CSS
.section {
background-color: red;
}
.active {
background-color: yellow;
}
You need to use scrollevent and change the class accordingly... kindly check https://jsfiddle.net/77v3329y/1/
jQuery
$(document).ready(function() {
var a = +$('#secA').height();
var b = $('#secB').height();
var c = $('#secC').height();
console.log(a);
console.log(b);
console.log(c);
$(window).on('scroll', function() {
$('#secA, #secB, #secC').removeClass('active');
var st = $(document).scrollTop();
if (st < a) {
$('#secA').addClass('active');
}
if (st > a) {
$('#secB').addClass('active');
}
if (st > a + b) {
$('#secC').addClass('active');
}
})
});
You can use jquery-waypoints to know which element has reached at top of the viewport. The plugin will give you the callback which will help you to change the css of the active element.
Here is the solutions to detect the scroll to top event.
Fire event when div is visible to visitor with jQuery?
Simply use jQuery to change the css of the element when scroll to top: $("#secA").css("background-color", "yellow");

how use sticky sidebar move up when window scroll top

Sticky Sidebar that only sticks when sidebar bottom is at window bottom
i get this site ( got to bootstrap sticky example)
javascript
$(function() {
var win = $(window);
var doc = $(document);
var wh = win.height();
var dh = doc.height();
var sidebar = $('.rightside .stickybar');
var sot = sidebar.offset().top;
var sh = sidebar.height();
var elementToBottom = dh - sot - sh;
// reset the sidebar width
var wt = sidebar.width();
sidebar.width(wt);
win.scroll(function(){
var dst = doc.scrollTop();
var scrollBottom = dh - dst - wh;
if(scrollBottom <= elementToBottom) {
sidebar.addClass('fixToBottom');
} else {
sidebar.removeClass('fixToBottom');
}
});
});
css
.fixToTop {
position: fixed;
top: 50px;
}
.fixToBottom {
bottom: 60px;
position: fixed;
}
html
<header> </header>
<div class="contents">
<div class = "leftside"> left</div>
< div class="righside">
<div class="stickybar">
// when move scrolling up and down
</div>
</div>
</div>
<footer> footer </div>
I have a 2 column layout. The left column is way longer than the sidebar. I want the sidebar only to stick when its bottom reaches the bottom of the browser window. So the user can continue to scroll down the left column content while the right sidebar sticks. I've seen a lot of sticky questions here, however this particular situation still stumps me. I also have a sticking headline bar on the left column that i've successfully gotten to stick.
Check out this example, I whipped up.
http://www.bootply.com/hVx29SmQ4g
If you or anyone has any questions, just send me a message and I'll try to explain. I commented the code however, so it should be quite straightforward. I hope its what you needed though!
:::CODE:::
/*
=== JS ===
============
Author: Kevin Leegsma
Updated: Feb 10, 2015
Notes: Coded for Stack Overflow - re: Sticky Sidebar
*/
/* Base function that waits till rest of site loads and then executes */
$(document).ready(function () {
"use strict";
/* activate sidebar, this can also be done as in-line HTML using the following line, instead of the Javascript below */
/* <div class = "col-xs-4" id = "rightColumn" data-spy = "affix" data-offset-bottom = "200"> */
$('#sidebar').affix({
offset: {
top: 400 /* both TOP and BOTTOM can be used here, tweek to your own needs */
}
});
/*This function gets the WIDTH of the wrapper and maintains it for the SIDEBAR*/
/*It does this by setting the WRAPPER as the PARENT, it then calls a function to resize the child (SIDEBAR)
in this case equal to the parent size.*/
/*NOTE: Without this function, the AFFIX still works, just doesn't function as nicely as it doesn't follow
standard Bootstrap grid CSS rules. */
$('#sidebar').each(function () {
var elem = $(this);
var parentWrapper = $('#sidebarWrapper');
var childToParentResize = function () {
var sidebarWidth = $(parentWrapper).width();
elem.width(sidebarWidth);
};
childToParentResize();
$(window).resize(childToParentResize);
});
/* Alert to inform you the SIDEBAR has become fixed, can be removed/commented, just for testing, but helpful for those new to AFFIX */
$('#sidebar').on('affixed.bs.affix', function(){
alert("The left navigation menu has been affixed. Now it doesn't scroll with the page.");
});
});
/* CSS used here will be applied after bootstrap.css
=== CSS ===
=============
Author: Kevin Leegsma
Updated: Feb 10, 2015
Notes: Coded for Stack Overflow - re: Sticky Sidebar
--------------------------------------
Layout
-------------------------------------- */
/* Targets the SIDEBAR once the affix has become active */
/* Adjust these to cater to your layout settings */
#sidebar.affix{
top: 10px;
right: 8.5%;
}
/*
==============
=== HTML ===
==============
Author: Kevin Leegsma
Updated: February 10, 2015
Notes: Coded for Stack Overflow - re: how-use-sticky-sidebar-move-up-when-window-scroll-top
*/
<!-- Main Code -->
<div class="container" id="main">
<!-- Left column with dummy text -->
<div class="col-xs-8" id="leftColumn">
<h1> LEFT COLUMN</h1>
<h3>With Even More Filler Text!</h3>
<p>...a bunch of text...</p>
</div><!--end leftColumn-->
<!-- Right column/sidebar that affixes itself as the window is scrolled -->
<!-- Stuck within a col-xs-4 parent element, this is because the AFFIX
has wonky width controls, they ignore Bootstrap grids and aren't responsive
with this wrapper and the JS however, it resizes well. -->
<div class="col-xs-4" id="sidebarWrapper">
<div id="sidebar" data-spy="affix">
<h1> SIDEBAR</h1>
<h3>With Filler!</h3>
<small>
<p>...sidebar text/links...</p>
</small>
</div><!--end sidebar-->
</div><!--end sidebarWrapper-->
</div><!--end container-->
I'm not at my computer at home right now, if it still isn't answered by tonight I'll whip up an example.
However if I'm reading what you need correctly, all you need to do is give the one element, that's to be fixed, the AFFIX property either through HTML/CSS
<div id="sidebar" data-spy="affix" data-affix-bottom="50">
NOTE -> the data-affix-bottom is an offset number, so tweak it to suit your needs
Or through JavaScript
$("#sidebar").affix({
offset: {
bottom: someValue
}
}
});
Some useful links that explain it more in depth:
http://getbootstrap.com/javascript/#affix
And
http://goo.gl/8knwd4 (With a scrolling sidebar example)

Define number of visible elements

Some introduction:
Hello, i wanted to ask, if there is an easy way, to know how many of "tabs" are visible for user when he clicks on some button?
Description of what i have so far:
http://jsfiddle.net/L7bPc/7/
Here, on jsfiddle, you can see example of tabs i am thinking of, when you widen or narrow the width, more or less tabs are visible (rest disappears thanks to "overflow:hidden;").
Question:
My question is, is there any easy way to get to know, how many tabs are visible once clicking on red square in top right corner?
Explanation of what i want to achieve:
Why? Because i will try to generate a list of "not visible" tabs, once clicked on red square later (i will style it properly ofcourse). I want it to look similar to many programs with tabs, when there are too many of them, you can find a little arrow on the end of it, to expand the rest of tabs, in drop down menu.
I am asking how to know how many tabs are visible, and how many not (so i know which to generate after clicking on it in dropdown), i am NOT asking how to create the dropdown.
This part is generated by php, getting data from MySQL database, and style them in css to look like tabs (i didn't use php in jsfiddle, just plain html):
<div class="tabs">
<ul>
<li id=090NCI class='active'><a href='#' class='active'><span class='active'>090NCI</span></a></li>
<li id=061PPP><a href='#'><span>061PPP</span></a></li>
<li id=072KWM><a href='#'><span>072KWM</span></a></li>
<li id=057ALS><a href='#'><span>057ALS</span></a></li>
<li id=099AKG><a href='#'><span>099AKG</span></a></li>
<li id=090WPW><a href='#'><span>090WPW</span></a></li>
<li id=020MSM><a href='#'><span>020MSM</span></a></li>
<li id=014LSP><a href='#'><span>014LSP</span></a></li>
<li id=010AAV><a href='#'><span>010AAV</span></a></li>
<li id=080MKS><a href='#'><span>080MKS</span></a></li>
<li id=006ALS><a href='#'><span>006ALS</span></a></li>
<li id=007KSG><a href='#'><span>007KSG</span></a></li>
<li id=091AOW><a href='#'><span>091AOW</span></a></li>
<li id=004ALO><a href='#'><span>004ALO</span></a></li>
<li id=003WWW><a href='#'><span>003WWW</span></a></li>
<li id=002KSO><a href='#'><span>002KSO</span></a></li>
<li id=001NWD><a href='#'><span>001NWD</span></a></li>
</ul>
<div style="position: absolute; right:5px; top:26px; background: red; color:red; width:20px; height: 20px;" onclick="dosomething()"></div>
</div>
Any tips? Solutions might be both, in jQuery and javascript, no big difference for me.
Try this:
$("#redbox").click(function() {
var visibleLis = $("li").filter(function() {
var offset = $(this).offset();
return $(document.elementFromPoint(offset.left, offset.top)).closest(this).length > 0;
});
alert(visibleLis.length);
});
http://jsfiddle.net/L7bPc/11/
If you defined the .tabs to fully vertically contain the tabs, you can use far more optimized version:
$("#redbox").click(function() {
var boundingBox = $(".tabs")[0].getBoundingClientRect(),
bbRight = boundingBox.left + boundingBox.width,
bbBottom = boundingBox.top + boundingBox.height,
bbLeft = boundingBox.left,
bbTop = boundingBox.top;
var visibleLis = $("li").filter(function() {
var box = this.getBoundingClientRect(),
left = box.left,
top = box.top,
right = box.left + box.width,
bottom = box.top + box.height;
return left >= bbLeft && right <= bbRight && top >= bbTop && bottom <= bbBottom;
});
alert(visibleLis.length);
});
http://jsfiddle.net/L7bPc/13/

Categories

Resources