Adding Multiple Vanilla JavaScript Tabs to the Same Page - javascript

Using a variation of the following code, I was able to successfully add one set of Vanilla JavaScript tabs.
Yet how to do I add multiple sets of JavaScript tabs to one page using the same classes in the HTML.
I'm having difficultly creating unique dynamic IDs for the tab selectors and tab content areas using JavaScript. As you can see in https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html, these unique IDs are needed for accessible tags.
var accessibleTabsContainers = document.querySelectorAll('.accessible-tabs-container');
var tabSelector = document.querySelectorAll('.tab-selectors > li');
var tabContent = document.querySelectorAll('.tab-contents > div');
var largeRandNumber = Math.floor((Math.random() * 1000) + 1000);
accessibleTabsContainers.forEach(function(elem, indexAccessibleTabContainer) {
elem.setAttribute('data-id', indexAccessibleTabContainer);
tabSelector.forEach(function(singleTabSelector, i) {
var ariaControlTabContent = 'tab-content-' + largeRandNumber + '-' + i + '_' + indexAccessibleTabContainer;
var tabSelectorId = 'tab-selector-' + largeRandNumber + '-' + i + '_' + indexAccessibleTabContainer;
singleTabSelector.setAttribute('data-id', i);
singleTabSelector.setAttribute('id', tabSelectorId);
singleTabSelector.setAttribute('aria-controls', ariaControlTabContent);
tabContent[i].setAttribute('data-id', i);
tabContent[i].setAttribute('tabindex', 0);
tabContent[i].setAttribute('role', 'tabpanel');
tabContent[i].setAttribute('id', ariaControlTabContent);
tabContent[i].setAttribute('aria-labeledby', tabSelectorId);
if(i === 0) {
tabSelector[i].setAttribute('aria-pressed', 'true');
} else {
tabSelector[i].setAttribute('aria-pressed', 'false');
tabSelector[i].setAttribute('tabindex', -1);
}
});
});
function onTabSelectorClick(e) {
accessibleTabsContainers.forEach(function(accessibleTabsContainer, indexAccessibleTabContainer) {
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.parentElement.parentElement;
if(!tabSelectorSelected.classList.contains('active-tab-selector')) {
var tabSelectorSelectedFromContainer = accessibleTabsContainerSelected.querySelectorAll('.tab-contents > div');
console.log(tabSelectorSelectedFromContainer);
tabSelector.forEach(function(singleTabSelected, i) {
if(tabSelectorSelected.getAttribute('data-id') === tabContent[i].getAttribute('data-id')) {
tabContent[i].classList.add('tab-content-active');
} else {
tabSelector[i].classList.remove('active-tab-selector');
tabSelector[i].setAttribute('aria-pressed', 'false');
tabSelector[i].setAttribute('aria-selected', 'false');
tabSelector[i].setAttribute('tabindex', -1);
tabContent[i].classList.remove('tab-content-active');
}
});
tabSelectorSelected.classList.add('active-tab-selector');
tabSelectorSelected.setAttribute('aria-pressed', 'true');
tabSelectorSelected.setAttribute('aria-selected', 'true');
tabSelectorSelected.removeAttribute('tabindex');
}
});
}
tabSelector.forEach(function(tabSelector) {
tabSelector.addEventListener('click', onTabSelectorClick);
});
.wrapper {
max-width: 960px;
margin: 0 auto;
}
.tab-selectors {
display: inline-block;
}
.tab-selectors > li {
padding: 10px;
}
.tab-selectors > .active-tab-selector {
border: 1px solid #f00;
}
.tab-content {
display: inline-block;
}
.tab-contents > div {
padding: 10px;
border: 2px solid #000;
height: 150px;
width: 150px;
display: none;
}
.tab-contents > .tab-content-active {
display: block;
}
<div class="wrapper">
<h1>Accessible Tabs using Vanilla JavaScript</h1>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
</div>
I'm trying to generate these unique IDs in line 6 of the Vanilla JavaScript (accessibleTabsContainers.forEach) but it's not working.
Any assistance would be appreciated.

I solved my own issue. In the forEach loop that iterates inside the onTabSelectorClick function, I refactored the code to add the lines below:
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');
var tabSelectorsSelectedFromTabs = accessibleTabsContainerSelected.querySelectorAll('ul > li');
Then in a forEach loop instead of iterating through tabSelector (which references var tabSelector = document.querySelectorAll('.tab-selectors > li');) and loops through all tabs li tags, not just the ones referenced by the element clicked, I used tabSelectorsSelectedFromTabs, which references the tab elements inside their parent div tag (var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');), from the tab element (li tag) clicked (var tabSelectorSelected = e.target;).
See https://codepen.io/hollyw00d/pen/JjYJWjG. Also, I added the correct code in this answer. Below is a more useful before and after description of the code:
Incorrect forEach Loop Snippet inside onTabSelectorClick function that is passed in Click Event Handler
var tabSelector = document.querySelectorAll('.tab-selectors > li');
function onTabSelectorClick(e) {
tabSelector.forEach(function() {
// Code here
});
}
Correct forEach Loop Snippet inside onTabSelectorClick function that is passed in Click Event Handler
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');
var tabSelectorsSelectedFromTabs = accessibleTabsContainerSelected.querySelectorAll('ul > li');
function onTabSelectorClick(e) {
tabSelectorsSelectedFromTabs.forEach(function() {
// Code here
});
}
var accessibleTabsContainers = document.querySelectorAll('.accessible-tabs-container');
var tabSelector = document.querySelectorAll('.tab-selectors > li');
var tabContent = document.querySelectorAll('.tab-contents > div');
var largeRandNumber = Math.floor((Math.random() * 1000) + 1000);
accessibleTabsContainers.forEach(function(elem, indexAccessibleTabContainer) {
elem.setAttribute('data-id', indexAccessibleTabContainer);
tabSelector.forEach(function(singleTabSelector, i) {
var tabSelectorId = 'tab-selector-' + largeRandNumber + '_' + i + '_' + indexAccessibleTabContainer;
var ariaControlTabContent = 'tab-content-' + largeRandNumber + '_' + i + '_' + indexAccessibleTabContainer;
singleTabSelector.setAttribute('data-id', i);
singleTabSelector.setAttribute('id', tabSelectorId);
singleTabSelector.setAttribute('aria-controls', ariaControlTabContent);
tabContent[i].setAttribute('data-id', i);
tabContent[i].setAttribute('tabindex', 0);
tabContent[i].setAttribute('role', 'tabpanel');
tabContent[i].setAttribute('id', ariaControlTabContent);
tabContent[i].setAttribute('aria-labeledby', tabSelectorId);
if(i === 0) {
singleTabSelector.setAttribute('aria-pressed', 'true');
} else {
singleTabSelector.setAttribute('aria-pressed', 'false');
singleTabSelector.setAttribute('tabindex', -1);
}
});
});
function onTabSelectorClick(e) {
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');
var tabSelectorsSelectedFromTabs = accessibleTabsContainerSelected.querySelectorAll('ul > li');
var tabContentsSelectedFromContainer = accessibleTabsContainerSelected.querySelectorAll('.tab-contents > div');
if(!tabSelectorSelected.classList.contains('active-tab-selector')) {
tabSelectorsSelectedFromTabs.forEach(function(singleTabSelected, i) {
if(tabSelectorSelected.getAttribute('data-id') === tabContentsSelectedFromContainer[i].getAttribute('data-id')) {
singleTabSelected.classList.add('active-tab-selector');
singleTabSelected.setAttribute('tabindex', 0);
singleTabSelected.setAttribute('aria-pressed', 'true');
tabContentsSelectedFromContainer[i].classList.add('tab-content-active');
} else {
singleTabSelected.classList.remove('active-tab-selector');
singleTabSelected.setAttribute('tabindex', -1);
singleTabSelected.setAttribute('aria-pressed', 'false');
tabContentsSelectedFromContainer[i].classList.remove('tab-content-active');
}
});
}
}
tabSelector.forEach(function(tabSelector) {
tabSelector.addEventListener('click', onTabSelectorClick);
});
.wrapper {
max-width: 960px;
margin: 0 auto;
}
.tab-selectors {
display: inline-block;
}
.tab-selectors > li {
padding: 10px;
}
.tab-selectors > .active-tab-selector {
border: 1px solid #f00;
}
.tab-content {
display: inline-block;
}
.tab-contents > div {
padding: 10px;
border: 2px solid #000;
height: 150px;
width: 150px;
display: none;
}
.tab-contents > .tab-content-active {
display: block;
}
<div class="wrapper">
<h1>Accessible Tabs using Vanilla JavaScript</h1>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
</div>

Related

Word count for sections displayed (using the :target selector)

I have this:
var editor = document.getElementById('editor');
var words = document.querySelector('.words');
function wordsCount() {
var arr = editor.innerText.trim().replace(/\s+/g, ' ').split(' ');
words.textContent = !arr[0] ? 0 : arr.length;
}
wordsCount();
section {
display: none;
}
:target {
display: block;
}
.words:before {
content: "words: "
}
.words {
margin-top: 10px;
background-color: silver;
}
<aside>
<ol>
<li>Show 1</li>
<li>Show 2</li>
<li>Show 3</li>
</ol>
</aside>
<div id="editor">
<section id="1">Section 1 text</section>
<section id="2">Section 2 text</section>
<section id="3">Section 3 text</section>
</div>
<div class="words"></div>
Note: Right now, for the word count to work I need to delete:
section {
display: none;
}
My question is: How do I make the word count script target (count) only sections that are displayed, and only those. Any ideas?
You can attach click event to a element, pass this.hash from index 1 to wordsCount(), use RegExp /[^\s]+/g and String.prototype.match()
var editor = document.getElementById('editor');
var words = document.querySelector('.words');
function wordsCount(el) {
var arr = el.textContent.trim().match(/[^\s]+/g);
words.textContent = !arr[0] ? 0 : arr.length;
}
document.querySelectorAll("a")
.forEach(function(el) {
el.onclick = function() {
wordsCount(document.getElementById(this.hash.slice(1)))
}
})
section {
display: none;
}
:target {
display: block;
}
.words:before {
content: "words: "
}
.words {
margin-top: 10px;
background-color: silver;
}
<aside>
<ol>
<li>Show 1</li>
<li>Show 2</li>
<li>Show 3</li>
</ol>
</aside>
<div id="editor">
<section id="1">Section 1 text a</section>
<section id="2">Section 2 text b c</section>
<section id="3">Section 3 text d e f</section>
</div>
<div class="words"></div>
You have to find the length of words on click event of the anchor tag.
Stack Snippet
var words = document.querySelector('.words');
var anchor = document.querySelectorAll("a");
var section = document.querySelectorAll("section");
for (let i = 0; i < anchor.length; i++) {
anchor[i].addEventListener("click", function() {
var arr = document.getElementById(i + 1).innerText.trim().replace(/\s+/g, ' ').split(' ');
words.textContent = !arr[0] ? 0 : arr.length;
})
}
section {
display: none;
}
:target {
display: block;
}
.words:before {
content: "words: "
}
.words {
margin-top: 10px;
background-color: silver;
}
<aside>
<ol>
<li>Show 1</li>
<li>Show 2</li>
<li>Show 3</li>
</ol>
</aside>
<div id="editor">
<section id="1">Section 1 text 2</section>
<section id="2">Section 2 text</section>
<section id="3">Section 3 text 3 4</section>
</div>
<div class="words"></div>

Adding directional controls (prev/next) to switch between tabs

I've just finished a creating a bare bones JavaScript tabs functionality for website. Right now I'm having a bit of problem trying to add directional functions in order to switch between tabs. Here is what I've created so far. I'm not sue on how I can increment or decrement the index in order to use the directional arrows to switch tabs and also the content
$(document).ready(function() {
$('.tabs-list li:first-child').addClass('active'),
$('.tab-content .show-content:first-child').addClass('active');
$('.tabs-list li').click(function(e) {
event.preventDefault();
if (!$(this).hasClass('active')) {
var tabIndex = $(this).index();
var nthChild = tabIndex + 1;
// select the right elements
var $tabsList = $(this).parent();
var $tabContent = $tabsList.next('.tab-content');
$tabsList.find('li.active').removeClass('active');
$(this).addClass('active');
$tabContent.find('.show-content').removeClass('active');
$tabContent.find('.show-content:nth-child(' + nthChild + ')').addClass('active');
}
})
$('.prev').on('click', function() {});
$('next').on('click', function() {});
})
.tabs-list li {
display: inline-block;
}
.tab-content .show-content {
display: none
}
.tab-content .show-content.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul class="tabs-list">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
<div class="tab-content">
<div class="show-content">
Content 1
</div>
<div class="show-content">
Content 2
</div>
<di>
Content 3
</di>
</div>
</div>
<ul>
<li class="prev">Prev</li>
<li class="next">Next</li>
</ul>
You can do it using jQuery .prev() and .next() methods. You just need to get the current .active tab and change it accordingly.
Here's the code you need:
$('.prev').on('click', function() {
var current = $('.tab-content .show-content.active');
if (current.prev('.tab-content .show-content')[0]) {
current.removeClass('active');
current.prev('.tab-content .show-content').addClass('active');
}
});
$('.next').on('click', function() {
var current = $('.tab-content .show-content.active');
if (current.next('.tab-content .show-content')[0]) {
current.removeClass('active');
current.next('.tab-content .show-content').addClass('active');
}
});
Demo:
This is a working Fiddle and a working Demo snippet:
$(document).ready(function() {
$('.tabs-list li:first-child').addClass('active'),
$('.tab-content .show-content:first-child').addClass('active');
$('.tabs-list li').click(function(e) {
event.preventDefault();
if (!$(this).hasClass('active')) {
var tabIndex = $(this).index();
var nthChild = tabIndex + 1;
// select the right elements
var $tabsList = $(this).parent();
var $tabContent = $tabsList.next('.tab-content');
$tabsList.find('li.active').removeClass('active');
$(this).addClass('active');
$tabContent.find('.show-content').removeClass('active');
$tabContent.find('.show-content:nth-child(' + nthChild + ')').addClass('active');
}
})
$('.prev').on('click', function() {
var current = $('.tab-content .show-content.active');
if (current.prev('.tab-content .show-content')[0]) {
current.removeClass('active');
current.prev('.tab-content .show-content').addClass('active');
}
});
$('.next').on('click', function() {
var current = $('.tab-content .show-content.active');
if (current.next('.tab-content .show-content')[0]) {
current.removeClass('active');
current.next('.tab-content .show-content').addClass('active');
}
});
})
.tabs-list li {
display: inline-block;
cursor: pointer;
}
.tab-content .show-content {
display: none
}
.tab-content .show-content.active {
display: block;
}
.as-console-row-code {
display: none;
}
.prev,
.next {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul class="tabs-list">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
<div class="tab-content">
<div class="show-content">
Content 1
</div>
<div class="show-content">
Content 2
</div>
<div class="show-content">
Content 3
</div>
</div>
</div>
<ul>
<li class="prev">Prev</li>
<li class="next">Next</li>
</ul>
Edit:
To make it loop in a cyclic way and doesn't stop in first or last elements, we should just implement that in the else block of our if statement, so it won't stop.
Here's how will be your code:
$('.prev').on('click', function() {
var current = $('.tab-content .show-content.active');
if (current.prev('.tab-content .show-content')[0]) {
current.removeClass('active');
current.prev('.tab-content .show-content').addClass('active');
} else {
current.removeClass('active');
$(".tab-content .show-content:last").addClass('active');
}
});
$('.next').on('click', function() {
var current = $('.tab-content .show-content.active');
if (current.next('.tab-content .show-content')[0]) {
current.removeClass('active');
current.next('.tab-content .show-content').addClass('active');
} else {
current.removeClass('active');
$(".tab-content .show-content:first").addClass('active');
}
});
And this is an updated Fiddle taking in consideration these changes.

jQuery tabs - Enable and disable

I'm having a problem on how to disable tab 3 when the first button is clicked. When I click Activate 2nd tab, the 2nd tab will be enabled, but the 3rd tab will be enabled, too; it should be enabled when I click Activate 3rd tab.
What should I do?
<div class="tab-wrapper" id="tab-wrapper">
<div class="tab-header">
<ul class="tabs">
<li>Step 1</li>
<li>Step 2</li>
<li>Step 3</li>
</ul>
</div>
<div class="tab_container">
<div id="tab1" class="tab_content">
this is tab 1
<button id="button2">Activate 2nd tab</button>
</div>
<div id="tab2" class="tab_content">
this is tab 2
<button id="button3">Activate 3rd tab</button>
</div>
<div id="tab3" class="tab_content">
This is tab3
</div>
</div>
</div>
</body>
<script type="text/javascript">
$(function() {
var activate = false,
tabLinks = $('.tabs a'),
tabContent = $('.tab_container').children();
tabLinks.eq(0).addClass('active'); // Add active class, could possibly go in markup
$('#tab2').hide();
$('#tab3').hide(); // Hide second tab
tabLinks.bind('click', function(e) {
e.preventDefault();
if(activate === true) { // Only do something if button has been clicked
var target = this.hash,
el = $(this);
tabLinks.filter('.active').removeClass('active');
el.addClass('active');
tabContent.hide(); // Hide all
$(target).show(); // Show selected
}
});
$('#button2').bind('click', function() {
activate = true; // Activate tab functionality
tabLinks.eq(1).trigger('click'); // Trigger a click on the second tab link
});
$('#button3').bind('click', function() {
activate = true; // Activate tab functionality
tabLinks.eq(2).trigger('click'); // Trigger a click on the third tab link
});
});
</script>
</html>
You can do something like this (using an array to know if the tab is already activated instead of only one boolean):
$(function() {
var activate = [true, false, false],
tabLinks = $('.tabs a'),
tabContent = $('.tab_container').children();
tabLinks.eq(0).addClass('active'); // Add active class, could possibly go in markup
$('#tab2').hide(); // Hide second tab
$('#tab3').hide(); // Hide second tab
tabLinks.on('click', function(e) {
e.preventDefault();
var idx = $(this).data('index');
if (activate[idx] === true) { // Only do something if button has been clicked
var target = this.hash,
el = $(this);
tabLinks.filter('.active').removeClass('active');
el.addClass('active');
tabContent.hide(); // Hide all
$(target).show(); // Show selected
}
});
$('button').on('click', function() {
var index = $(this).data('index');
activate[index] = true; // Activate tab functionality
tabLinks.eq(index).trigger('click'); // Trigger a click on the second tab link
});
});
* {
padding: 0;
margin: 0;
}
body {
margin: 30px;
}
.tab-wrapper {
width: 500px;
}
.tabs {
overflow: hidden;
list-style: none;
}
.tabs li {
float: left;
margin-right: 10px;
border: 1px solid #ccc;
border-bottom: 0;
}
.tabs a {
display: block;
padding: 5px;
width: 100px;
}
.tabs a.active {
background: #efefef;
}
.tab_container > div {
padding: 10px;
border: 1px solid #ccc;
}
button {
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="tab-wrapper" id="tab-wrapper">
<div class="tab-header">
<ul class="tabs">
<li>step1</li>
<li>step2</li>
<li>step3</li>
</ul>
</div>
<div class="tab_container">
<div id="tab1" class="tab_content">
here is the list of the overview
<button data-index="1">Activate 2nd tab</button>
</div>
<div id="tab2" class="tab_content">
here is the list of the overview
<button data-index="2">Activate 3nd tab</button>
</div>
<div id="tab3" class="tab_content">
End
</div>
</div>
</div>
</body>
You can find the code on jsfiddle too :
https://jsfiddle.net/psLshz3u/

How can show specific number of li using jquery?

I want to show 3 li and after 1 second these 3 li will be slide up and next 3 li will be automatically show up in the div.#content
<div id="content">
<ul>
<li>122</li>
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>fifth</li>
<li>sixth</li>
</ul>
</div>
I tried toggle with setTimeout function, but it does fulfill on my requirements. I know this question may be stupid for someone but believe I really need your guideline please guide me how can i done this task. I will appreciate if someone guide me. I don't want to use any plugin.
A better way (not a semantic way, but) to achieve this is to wrap every 3 <li> and then walk through them. One way is:
$(function () {
var lis = $("ul > li");
for(var i = 0; i < lis.length; i+=3) {
lis.slice(i, i+3).wrapAll("<div class='slide'></div>");
}
$(".slide").hide();
$(".slide:first").slideDown();
setInterval(function () {
if ($(".slide:visible").next(".slide").length == 0) {
$(".slide:visible").slideUp(function () {
$(".slide:first").slideDown();
});
}
else
$(".slide:visible").slideUp(function () {
$(this).next(".slide").slideDown();
});
}, 2500);
});
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<div id="content">
<ul>
<li>122</li>
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>fifth</li>
<li>sixth</li>
</ul>
</div>
You can use :lt() and :gt() pseudo selectors
var i = 2,
$ul = $('#content ul'),
int = setInterval(function() {
$('li', $ul).slideUp();
$('li:gt(' + i + '):lt(3)', $ul).slideDown();
i += 3;
if (i + 1 >= $('li', $ul).length) clearInterval(int);
},
2000)
#content ul li:nth-child(n+4) {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content">
<ul>
<li>122</li>
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>fifth</li>
<li>sixth</li>
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>fifth</li>
<li>sixth</li>
</ul>
</div>
UPDATE:
If you want to slide continuously then following code can be used
var i = 2,
$ul = $('#content ul'),
int = setInterval(function() {
$('li', $ul).slideUp();
$('li' + (i == -1 ? '' : ':gt(' + i + ')') + ':lt(3)', $ul).slideDown();
i += 3;
if (i + 1 >= $('li', $ul).length) i = -1;
},
2000)
#content ul li:nth-child(n+4) {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content">
<ul>
<li>122</li>
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>fifth</li>
<li>sixth</li>
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>fifth</li>
<li>sixth</li>
</ul>
</div>
You can try this:
$("li").hide(); // this will hide all li first
$('ul li:lt(3)').show(); // this will display first 3 li from all li
You can do like this,
$("#content ul li").hide();
i = 0;
setInterval(function() {
i = (i + 3) % $("#content ul li").length;
$("#content > ul >li").slideUp();
$("#content > ul >li:gt(" + i + ")").slideDown();
$("#content > ul >li:gt(" + (i + 3) % $("#content ul li").length + ")").hide();
}, 1000);
Fiddle
Here is another possibility:
var steps = 3;
$(function tick() {
setTimeout(function () {
var top = '-=' + (steps * 31) + 'px';
var lis = $('li:lt(' + steps + ')');
var clones = lis.clone().appendTo('ul');
$.when(
$('li').animate({ top: top }, 'slow')
).done(function () {
clones.remove();
lis.appendTo('ul');
$('li').css('top', 'auto');
tick();
});
}, 1000);
});
* {
padding: 0;
margin: 0;
}
ul {
overflow: hidden;
height: 92px;
}
li {
display: block;
position: relative;
line-height: 30px;
padding: 0 10px;
background: #DDD;
margin-bottom: 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul><li>A</li><li>B</li><li>C</li><li>D</li><li>E</li><li>F</li><li>G</li><li>H</li></ul>

YUI 3 drag and drop with Constraints

I am new to YUI. I am wanting to achieve a drag and drop operation with contstraints. I am following the simple YUI 3 guide and was able to achieve the drag and drop according to the code they given which is.
http://yuilibrary.com/yui/docs/dd/scroll-list.html
HTML
<body>
<div id="demo">
<ul id="list1">
<li class="list1">Item #1</li>
<li class="list1">Item #2</li>
<li class="list1">Item #3</li>
<li class="list1">Item #4</li>
<li class="list1">Item #5</li>
<li class="list1">Item #6</li>
<li class="list1">Item #7</li>
<li class="list1">Item #8</li>
<li class="list1">Item #9</li>
<li class="list1">Item #10</li>
<li class="list1">Item #11</li>
<li class="list1">Item #12</li>
</ul>
<ul id="list2">
<li class="list2">Item #1</li>
<li class="list2">Item #2</li>
<li class="list2">Item #3</li>
<li class="list2">Item #4</li>
<li class="list2">Item #5</li>
<li class="list2">Item #6</li>
<li class="list2">Item #7</li>
<li class="list2">Item #8</li>
<li class="list2">Item #9</li>
<li class="list2">Item #10</li>
<li class="list2">Item #11</li>
<li class="list2">Item #12</li>
</ul>
</div>
CSS
yui3-dd-proxy {
text-align: left;
}
#demo {
width: 600px;
}
#demo {
border: 1px solid black;
padding: 10px;
margin: 10px;
zoom: 1;
}
#demo ul li {
border: 1px solid black;
background-color: #8DD5E7;
cursor: move;
margin: 3px;
list-style-type: none;
}
#demo:after { display: block; clear: both; visibility: hidden; content: '.'; height: 0;}
#demo ul {
border: 1px solid black;
margin: 10px;
width: 200px;
height: 400px;
float: left;
padding: 0;
zoom: 1;
position: relative;
overflow: auto;
}
#demo ul li.list1 {
background-color: #8DD5E7;
border:1px solid #004C6D;
}
#demo ul li.list2 {
background-color: #EDFF9F;
border:1px solid #CDCDCD;
}
Javascript
YUI().use('dd-constrain', 'dd-proxy', 'dd-drop', 'dd-scroll', function(Y) {
//Listen for all drop:over events
//Y.DD.DDM._debugShim = true;
Y.DD.DDM.on('drop:over', function(e) {
//Get a reference to our drag and drop nodes
var drag = e.drag.get('node'),
drop = e.drop.get('node');
//Are we dropping on a li node?
if (drop.get('tagName').toLowerCase() === 'li') {
//Are we not going up?
if (!goingUp) {
drop = drop.get('nextSibling');
}
//Add the node to this list
e.drop.get('node').get('parentNode').insertBefore(drag, drop);
//Set the new parentScroll on the nodescroll plugin
e.drag.nodescroll.set('parentScroll', e.drop.get('node').get('parentNode'));
//Resize this nodes shim, so we can drop on it later.
e.drop.sizeShim();
}
});
//Listen for all drag:drag events
Y.DD.DDM.on('drag:drag', function(e) {
//Get the last y point
var y = e.target.lastXY[1];
//is it greater than the lastY var?
if (y < lastY) {
//We are going up
goingUp = true;
} else {
//We are going down.
goingUp = false;
}
//Cache for next check
lastY = y;
Y.DD.DDM.syncActiveShims(true);
});
//Listen for all drag:start events
Y.DD.DDM.on('drag:start', function(e) {
//Get our drag object
var drag = e.target;
//Set some styles here
drag.get('node').setStyle('opacity', '.25');
drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
drag.get('dragNode').setStyles({
opacity: '.5',
borderColor: drag.get('node').getStyle('borderColor'),
backgroundColor: drag.get('node').getStyle('backgroundColor')
});
});
//Listen for a drag:end events
Y.DD.DDM.on('drag:end', function(e) {
var drag = e.target;
//Put our styles back
drag.get('node').setStyles({
visibility: '',
opacity: '1'
});
});
//Listen for all drag:drophit events
Y.DD.DDM.on('drag:drophit', function(e) {
var drop = e.drop.get('node'),
drag = e.drag.get('node');
//if we are not on an li, we must have been dropped on a ul
if (drop.get('tagName').toLowerCase() !== 'li') {
if (!drop.contains(drag)) {
drop.appendChild(drag);
//Set the new parentScroll on the nodescroll plugin
e.drag.nodescroll.set('parentScroll', e.drop.get('node'));
}
}
});
//Static Vars
var goingUp = false, lastY = 0;
//Get the list of li's in the lists and make them draggable
var lis = Y.all('#demo ul li');
lis.each(function(v, k) {
var dd = new Y.DD.Drag({
node: v,
target: {
padding: '0 0 0 20'
}
}).plug(Y.Plugin.DDProxy, {
moveOnEnd: false
}).plug(Y.Plugin.DDConstrained, {
constrain2node: '#demo'
}).plug(Y.Plugin.DDNodeScroll, {
node: v.get('parentNode')
});
});
Y.one('#make').on('click', function(e) {
YUI().use('dd-drag', 'dd-proxy', function(Y) {
//Selector of the node to make draggable
var dd = new Y.DD.Drag({
container: '#demo',
node: 'li'
}).plug(Y.Plugin.DDProxy); //This config option makes the node a Proxy Drag
var demo =Y.one('#demo ul');
for (var i = 1; i < 11; i++) {
//demo.append('<li class="list3">New item #' + i + '</i><br>');
demo.append('<li class="list3">Item #' + i + '</li>' )
}
})
});
//Create simple targets for the 2 lists.
var uls = Y.all('#demo ul');
uls.each(function(v, k) {
var tar = new Y.DD.Drop({
node: v
});
});
});
YUI().use('dd-delegate', 'dd-drop-plugin', 'dd-constrain', 'dd-proxy', function(Y) {
var del = new Y.DD.Delegate({
container: '#demo',
nodes: 'li'
});
del.on('drag:start', function(e) {
e.target.get('node').setStyle('opacity', '.5');
});
del.on('drag:end', function(e) {
e.target.get('node').setStyle('opacity', '1');
});
del.dd.plug(Y.Plugin.DDConstrained, {
constrain2node: '#play'
});
del.dd.plug(Y.Plugin.DDProxy, {
moveOnEnd: false,
cloneNode: true
});
var drop = Y.one('#drop').plug(Y.Plugin.Drop);
drop.drop.on('drop:hit', function(e) {
drop.set('innerHTML', 'You dropped: <strong>' + e.drag.get('node').get('innerHTML') + '</strong>');
});
});
I would like to Contrain the left drag meaning when i drag the blue over to the yellow. I would like to repopulate the blue item once it is dropped in the yellow area. The YUI guide has something similar to what I want to achieve here:
http://yuilibrary.com/yui/docs/dd/delegate-plugins.html
I am not quite clear on how to implement these two operations together to achieve the effect I need.
Any help would be good.
thanks
Javascript
YUI().use('dd-delegate', 'dd-drop-plugin', 'dd-constrain', 'dd-proxy', function(Y) {
var del = new Y.DD.Delegate({
container: '#demo',
nodes: 'li'
});
del.on('drag:start', function(e) {
e.target.get('node').setStyle('opacity', '.5');
});
del.on('drag:end', function(e) {
e.target.get('node').setStyle('opacity', '1');
});
del.dd.plug(Y.Plugin.DDConstrained, {
constrain2node: '#play'
});
del.dd.plug(Y.Plugin.DDProxy, {
moveOnEnd: false,
cloneNode: true
});
var drop = Y.one('#drop').plug(Y.Plugin.Drop);
drop.drop.on('drop:hit', function(e) {
drop.set('innerHTML', 'You dropped: <strong>' + e.drag.get('node').get('innerHTML') + '</strong>');
});
});

Categories

Resources