I want to create search-input with drop-down list. The list must close when i have focused or clicked anywhere except search-input.
I added listClose() to "blur"-Listener. But now I can`t catch click-event from drop-down elements. Which is the event-listener I really need? Or I need the another realization?
Please, run snippet below. I tried to write it the most clear.
document.addEventListener("DOMContentLoaded", function() {
var inputElement = document.getElementById("input_word-search");
var listElement = document.getElementById("dd-menu_search-input");
// Input will focused when document is ready.
inputElement.focus();
listOpen = function() {
listElement.classList.add('dd-open');
};
listClose = function() {
listElement.classList.remove('dd-open');
};
inputElement.addEventListener("focus", function(e) {
listOpen();
});
inputElement.addEventListener("blur", function(e) {
listClose();
});
})
.dd-menu {
padding: 8px 0;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
position: absolute;
display: none;
}
.dd-suggestion {
cursor: pointer;
text-align: left;
padding: 3px 20px;
line-height: 24px;
}
.dd-suggestion:hover {
color: #fff;
background-color: #697981;
}
.dd-open {
display: block;
}
.dd-empty {
display: none;
}
#dd-menu_search-input {
width: 74%;
}
<body>
<div id="input-group">
<input id="input_word-search" class="input_search suggest__field" type="search" autocomplete="off" name="q" placeholder="Seach">
<div id="dd-menu_search-input" class="dd-menu dd-open">
<div class="dd-dataset">
<div class="dd-suggestion" onclick="alert('Click!')">
suggestion-1
</div>
<div class="dd-suggestion" onclick="alert('Click!')">
suggestion-2
</div>
<div class="dd-suggestion" onclick="alert('Click!')">
suggestion-3
</div>
<div class="dd-suggestion" onclick="alert('Click!')">
suggestion-4
</div>
<div class="dd-suggestion" onclick="alert('Click!')">
suggestion-5
</div>
</div>
</div>
</div>
</body>
A solution (or may I say workaround) is to use onmousedown instead of onclick, so it will look like this (Note that I'm also removing the alert() and using a console.log() instead)
<body>
<div id="input-group">
<input id="input_word-search" class="input_search suggest__field" type="search" autocomplete="off" name="q" placeholder="Seach">
<div id="dd-menu_search-input" class="dd-menu dd-open">
<div class="dd-dataset">
<div class="dd-suggestion" onmousedown="console.log('Click!')">
suggestion-1
</div>
<div class="dd-suggestion" onmousedown="console.log('Click!')">
suggestion-2
</div>
<div class="dd-suggestion" onmousedown="console.log('Click!')">
suggestion-3
</div>
<div class="dd-suggestion" onmousedown="console.log('Click!')">
suggestion-4
</div>
<div class="dd-suggestion" onmousedown="console.log('Click!')">
suggestion-5
</div>
</div>
</div>
</div>
</body>
The reason is when you focusout the textbox, it call blur function and the list immediately disapear. So you can't click on the list. You can walkaround by setTimeout to listClose() like this
listClose = function() {
setTimeout(()=>{
listElement.classList.remove('dd-open');
},100)
};
I added boolean-variable that indicates mousedown-event on drop-down list
var mousedownOnNodeCalee = false;
listElement.addEventListener("mousedown", function (e) {
mousedownOnNodeCalee = true;
});
inputElement.addEventListener("blur", function (e) {
if(!mousedownOnNodeCalee) {
listClose();
return;
}
inputElement.focus();
mousedownOnNodeCalee = false;
});
Related
I'm using the clone method to duplicate a form. I'm adding and removing the active
class on the buttons but, once I clone the form, the duplicate buttons no longer
function because they share the same class as the original. I want the buttons to still
function regardless how many times I clone it. I used jQuery and JavaScript, and I'm
still new to programming. Can you please give me some ideas as to how to solve this.
Thanks in advance fellow developers.
Here is my HTML Code:
<div class="column-bottom phone">
<p class="para_txt">Phone</p>
<div id="main-wrapper">
<div id="wrapper_1" class="parentClass">
<div class="basic_infor">
<p>Select the nature of phone:</p>
<div class="parent_btns">
<button class="func_btns btn_first_4 " >Private</button>
<button class="func_btns btn_second_4" >Work</button>
</div>
</div>
<div class="basic_infor">
<p>Select the type of phone:</p>
<div class="parent_btns">
<button class="func_btns btn_5">Mobile</button>
<button class="func_btns btn_6 ">Telephone</button>
<button class="func_btns btn_7 ">Fax</button>
<button class="func_btns btn_8">Extension</button>
</div>
</div>
<div class="txt_area">
<input type="textarea" placeholder="+27 85 223 5258">
<span onclick="delete_el();">x</span>
</div>
</div>
</div>
<div class="btn_add">
<button class="repl_btns phone_repl" onclick="duplicate();">Add additional</button>
<p>Display on foreman contact list?</p>
<input type="checkbox" id="input_field" name="Phone_contact">
</div>
</div>
Here is my jQuery and JavaScript Code. I selected the class for the first button and
added a active class to it while removing the active class for the second button. I did
the same for the rest of the buttons.
//private btn
$(".btn_first_4").click(function () {
$(this).addClass("is_active");
$(".btn_second_4").removeClass("is_active");
});
//work btn
$(".btn_second_4").click(function () {
$(this).addClass("is_active");
$(".btn_first_4").removeClass("is_active");
});
//Bottom 5 btns
$(".btn_5").click(function () {
$(this).addClass("is_active");
$(".btn_6,.btn_7,.btn_8").removeClass("is_active");
})
$(".btn_6").click(function () {
$(this).addClass("is_active");
$(".btn_5,.btn_7,.btn_8").removeClass("is_active");
})
$(".btn_7").click(function () {
$(this).addClass("is_active");
$(".btn_5,.btn_6,.btn_8").removeClass("is_active");
})
$(".btn_8").click(function () {
$(this).addClass("is_active");
$(".btn_5,.btn_6,.btn_7").removeClass("is_active");
})
/*
Cloning Functions....
I tried to set the id of my new clone to "wrapper_2", but it only works when i clone it
once. I wanted to change the class attribute this way but I realize it wont work as
well. Please advise. Thanks
*/
function duplicate(){
const wrapper = document.getElementById("wrapper_1");
const clone = wrapper.cloneNode(true);
clone.id = "wrapper_2";
const main_wrapper = document.getElementById("main-wrapper");
main_wrapper.appendChild(clone)
}
function delete_el() {
const del_el = document.getElementById("wrapper_2");
del_el.remove();
}
Problems
If you use .cloneNode() any event handlers bound to the original will not carry over to the clone. Fortunately you are using jQuery which has it's own method .clone(). It has the ability to clone and keep event handlers, $(selector).clone(true) to copy with events and $(selector).clone(true, true) for a deep copy with events.
Note: Using .clone() has the side-effect of producing elements with duplicate id attributes, which are supposed to be unique. Where possible, it is recommended to avoid cloning elements with this attribute or using class attributes as identifiers instead.
.clone()|jQuery API Documentation
Do not clone anything with an id, in fact you are using jQuery so don't use id at all. Convert every id to a class, it might feel like a lot of work but in the long run you'll be thankful you did.
Do not use inline event handlers
<button onclick="lame(this)">DON'T DO THIS</button>
This is especially important if you use jQuery which makes event handling incredibly easy to write and very versatile.
let count = 0;
$('output').val(++count);
$('.remove').hide();
$('.select button').on('click', function() {
const $old = $(this).parent().find('.active');
if (!$old.is(this)) {
$old.removeClass('active');
}
$(this).toggleClass('active');
});
$('.clear').on('click', function() {
$(this).parent().find('input').val('');
});
$('.remove').on('click', function() {
$(this).closest('.fields').remove();
let out = $.makeArray($('output'));
count = out.reduce((sum, cur, idx) => {
cur.value = idx + 1;
sum = idx + 1;
return sum;
}, 0);
});
$('.add').on('click', function() {
const $first = $('.fields').first();
const $copy = $first.clone(true, true);
$copy.insertAfter($('.fields').last());
$copy.find('output').val(++count);
$copy.find('.remove').show();
$copy.find('input').val('');
});
html {
font: 300 2ch/1.2 'Segoe UI'
}
fieldset {
min-width: fit-content
}
.fields {
margin-top: 1rem;
}
output {
font-weight: 900;
}
menu {
display: flex;
align-items: center;
margin: 0.5rem 0 0.25rem;
}
button,
input {
display: inline-block;
font: inherit;
font-size: 100%;
}
button {
cursor: pointer;
border: 1.5px ridge lightgrey;
}
.numbers {
display: flex;
align-items: center;
margin: 1rem 0 0.5rem -40px;
}
.clear {
border: 0;
font-size: 1.25rem;
line-height: 1.25;
}
.right {
justify-content: flex-end;
}
.left {
padding-left: 0;
}
.number-3 {
width: 9rem;
}
.number-1 {
width: 3rem;
}
[class^="number-"] {
font-family: Consolas
}
.clear {
border: 0;
background: transparent;
}
label+label {
margin-left: 6px;
}
button:first-of-type {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
button:nth-of-type(2) {
border-radius: 0;
}
button:last-of-type {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.active {
outline: 2px lightblue solid;
outline-offset: -2px;
}
#foreman {
transform: translate(0, 1.5px)
}
.btn.remove {
display: block;
border-radius: 4px;
float: right;
}
<form id='phone'>
<fieldset class='main'>
<legend>Add Phone Numbers</legend>
<section class='fields'>
<fieldset>
<legend>Phone Number <output value='1'></output></legend>
<button class='btn remove' type='button'>Remove</button>
<label>Phone number is used for:</label>
<menu class='purpose select'>
<button class="btn priv" type='button'>Private</button>
<button class="btn work" type='button'>Work</button>
</menu>
<label>Select the type of phone:</label>
<menu class='type select'>
<button class="btn mob" type='button'>Mobile</button>
<button class="btn tel" type='button'>Telephone</button>
<button class="btn fax" type='button'>Fax</button>
</menu>
<menu class='numbers'>
<form name='numbers'>
<label>Number:  </label>
<input name='phone' class='number-3' type="tel" placeholder="+27 85 223 5258" required>
<label>  Ext.  </label>
<input name='ext' class='number-1' type='number' placeholder='327'>
<button class='btn clear' type='button'>X</button>
</form>
</menu>
</fieldset>
</section>
<fieldset>
<menu class='right'>
<button class='btn cancel' type='button'>Cancel</button>
<button class='btn done'>Done</button>
<button class='btn add' type='button'>Add</button>
</menu>
</fieldset>
<footer>
<menu>
<input id='foreman' name="contact" type="checkbox">
<label for='foreman'>Display on foreman contact list?</label>
</menu>
</footer>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
When load page , JS add event click for elements ( elements were created)
When you clone new elements ( those do not add event click) and event click of you not working on those elements
You are using Jquery then i suggest you code same as below :
$(document).on('click', ".btn_first_4", function () {
$(this).addClass("is_active");
$(".btn_second_4").removeClass("is_active");
});
//work btn
$(document).on('click', ".btn_second_4", function () {
$(this).addClass("is_active");
$(".btn_first_4").removeClass("is_active");
});
//Bottom 5 btns
$(document).on('click', ".btn_5", function () {
$(this).addClass("is_active");
$(".btn_6,.btn_7,.btn_8").removeClass("is_active");
})
$(document).on('click', ".btn_6", function () {
$(this).addClass("is_active");
$(".btn_5,.btn_7,.btn_8").removeClass("is_active");
})
$(document).on('click', ".btn_7", function () {
$(this).addClass("is_active");
$(".btn_5,.btn_6,.btn_8").removeClass("is_active");
})
$(document).on('click', ".btn_8", function () {
$(this).addClass("is_active");
$(".btn_5,.btn_6,.btn_7").removeClass("is_active");
})
function duplicate(){
const wrapper = document.getElementById("wrapper_1");
const clone = wrapper.cloneNode(true);
clone.id = "wrapper_2";
const main_wrapper = document.getElementById("main-wrapper");
main_wrapper.appendChild(clone)
}
function delete_el() {
const del_el = document.getElementById("wrapper_2");
del_el.remove();
}
.is_active {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="column-bottom phone">
<p class="para_txt">Phone</p>
<div id="main-wrapper">
<div id="wrapper_1" class="parentClass">
<div class="basic_infor">
<p>Select the nature of phone:</p>
<div class="parent_btns">
<button class="func_btns btn_first_4 " >Private</button>
<button class="func_btns btn_second_4" >Work</button>
</div>
</div>
<div class="basic_infor">
<p>Select the type of phone:</p>
<div class="parent_btns">
<button class="func_btns btn_5">Mobile</button>
<button class="func_btns btn_6 ">Telephone</button>
<button class="func_btns btn_7 ">Fax</button>
<button class="func_btns btn_8">Extension</button>
</div>
</div>
<div class="txt_area">
<input type="textarea" placeholder="+27 85 223 5258">
<span onclick="delete_el();">x</span>
</div>
</div>
</div>
<div class="btn_add">
<button class="repl_btns phone_repl" onclick="duplicate();">Add additional</button>
<p>Display on foreman contact list?</p>
<input type="checkbox" id="input_field" name="Phone_contact">
</div>
</div>
Is there a more efficient way of creating this function with Javascript.
As you can see in the demo, the first block works fine but not the second block. I plan to roll this out across hundreds of categories, so wonder if there's a neater solution here.
const btn = document.getElementById("category36SeeMore");
btn.addEventListener("click", function(e){
e.preventDefault();
const id = this.id.replace('SeeMore', '')
document.querySelectorAll('.' + id).forEach(el=>el.style.display = 'block')
});
.category36 {
margin: 5px;
padding: .5rem;
box-shadow: 2px 2px 5px rgba(0,0,0,0.03);
border-radius: 4px;
background: Skyblue;
border-bottom: 1px solid #F9F2D6;
border-right: 1px solid #F9F2D6;
}
<p>
See more
</p>
<div class="category36">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<hr>
<p>
See more
</p>
<div class="category37">
test
</div>
<div class="category37" style="display:none;">
test
</div>
<div class="category37" style="display:none;">
test
</div>
<div class="category37" style="display:none;">
test
</div>
Demo: https://jsfiddle.net/qzfesw5d/
Is jQuery a better approach here? We use that on the site already.
You have to target all the elements and loop through them to attach the event. You can either use attribute starts with selector or use a common class to target the elements:
const btnList = document.querySelectorAll("a[id^=category");
btnList.forEach(function(btn){
btn.addEventListener("click", function(e){
e.preventDefault();
const id = this.id.replace('SeeMore', '')
document.querySelectorAll('.' + id).forEach(el=>el.style.display = 'block')
});
});
.category36, .category37 {
margin: 5px;
padding: .5rem;
box-shadow: 2px 2px 5px rgba(0,0,0,0.03);
border-radius: 4px;
background: Skyblue;
border-bottom: 1px solid #F9F2D6;
border-right: 1px solid #F9F2D6;
}
<p>
See more
</p>
<div class="category36">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<hr>
<p>
See more
</p>
<div class="category37">
test
</div>
<div class="category37" style="display:none;">
test
</div>
<div class="category37" style="display:none;">
test
</div>
<div class="category37" style="display:none;">
test
</div>
If you're using plain javascript (like your example) you could apply the following logic:
Give a specific class to all your container like category-container
Instead of selection ONE using the ID, select them ALL using the classname
Loop over them to add the event
Make sure that the event will change the display of the children of the current parent
Adding new categories will not break anything. This should be entirely scalable.
Using jQuery might make things a little simpler. Here is one approach with plain JavaScript.
const categoryCount = 36
for (let i = 0; i < categoryCount; i++) {
const btn = document.getElementById(`category${i+1}SeeMore`)
if (btn) {
btn.addEventListener("click", e => {
e.preventDefault();
document.querySelectorAll(`.category${i+1}`)
.forEach(el => el.style.display = 'block')
})
}
}
You can change all ...SeeMore elements to class and then add data-* attribute to all to point to the collection that you want to show like:
See more
Then loop through each class and on click of any seemore, you can get the id easily using:
const id = this.dataset.id
and then easily show the collections divs like:
document.querySelectorAll('.category' + id).forEach(el=>el.style.display = 'block')
const btns = document.querySelectorAll(".SeeMore");
btns.forEach(function(btn) {
btn.addEventListener("click", function(e) {
e.preventDefault();
const id = this.dataset.id
document.querySelectorAll('.category' + id).forEach(el => el.style.display = 'block')
});
});
.category36, .category37 {
margin: 5px;
padding: .5rem;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.03);
border-radius: 4px;
background: Skyblue;
border-bottom: 1px solid #F9F2D6;
border-right: 1px solid #F9F2D6;
}
<p>
See more
</p>
<div class="category36">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<div class="category36" style="display:none;">
test
</div>
<hr>
<p>
See more
</p>
<div class="category37">
test
</div>
<div class="category37" style="display:none;">
test
</div>
<div class="category37" style="display:none;">
test
</div>
<div class="category37" style="display:none;">
test
</div>
I have simple div with one element:
<div id="drop-zone">
<input type="file" style="display: none;" multiple="multiple">
</div>
When I click on #drop-zone I want to trigger input manually. I'm trying like this:
jQuery('#drop-zone:not(input)').click(function() {
jQuery(this).find('input[type="file"]').trigger('click')
})
The main problem is that I'm getting an endless loop of clicks as my manual click trigger listener on parent element.
Make sure that the element clicked was the drop-zone by checking the id of the target. When jQuery emulates an event it will pass the same this reference but will not pass the event, so just check if the event is set.
$("#drop-zone").click(function(event) {
if (this.id === "drop-zone" && event.originalEvent) {
$("#drop-zone>input").trigger("click");
}
})
#drop-zone {
background-color: red;
height: 50px;
width: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drop-zone">
<input type="file" style="display: none;" multiple="multiple">
</div>
You could also just trigger the event manually.
$("#drop-zone").click(function(event) {
if (this.id === "drop-zone") {
$("#drop-zone>input")[0].click();
}
})
#drop-zone {
background-color: red;
height: 50px;
width: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drop-zone">
<input type="file" style="display: none;" multiple="multiple">
</div>
Maybe this is what you want:
var x_m = 0;
var y_m = 0;
$('#drop-zone').click(function(event) {
var mtarget = document.elementFromPoint(x_m, y_m);
if (mtarget.id === "drop-zone") {
var input = $(this).find('input[type="file"]');
var h = false;
if ($(input).is(":visible")) {
input.hide();
} else {
input.show();
h = true;
}
console.log("You clicking, the #drop-zone, input.visible =>", h);
} else {
console.log("You clicking the input.");
}
})
$('body').mousemove(function(evt){
x_m = evt.pageX;
y_m = evt.pageY;
});
#drop-zone {
height: 40px;
width: 250px;
background-color: #8b5fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drop-zone">
<input type="file" style="display: none; background: green;" multiple="multiple">
</div>
I have a few buttons across a site I am building, certain buttons have one class while others have another. What I am trying to do is find the best way to find the clicked button without having an event listener for each individual button. I have come up with the below 2 for loops to find all the buttons with class button-1 and class button-2. Being fairly new to javascript i just don't want to get into bad habits so would appreciate any advice on the best way to achieve this.
<section>
<div class="button--1"></div>
<div class="button--1"></div>
<div class="button--2"></div>
</section>
<section>
<div class="button--2"></div>
<div class="button--1"></div>
<div class="button--2"></div>
</section>
var button1 = document.querySelectorAll('.button--1');
var button2 = document.querySelectorAll('.button--2');
for (var a = 0; a < button1.length; a++) {
button1[a].addEventListener('click',function(){
//do something
});
}
for (var b = 0; b < button2.length; b++) {
button1[b].addEventListener('click',function(){
//do something
});
}
If you plan to have multiple other classes like button--3, …4 … …15,
You must want to target all div elements which class starts (^=) with "button":
(Note that you can do it in the CSS too!)
var allButtons = document.querySelectorAll('div[class^=button]');
console.log("Found", allButtons.length, "div which class starts with “button”.");
for (var i = 0; i < allButtons.length; i++) {
allButtons[i].addEventListener('click', function() {
console.clear();
console.log("You clicked:", this.innerHTML);
});
}
/* Some styling */
section {
margin: 8px 0;
border: 1px solid gray;
}
section div {
border: 1px solid lightgray;
display: inline-block;
margin-left: 8px;
padding: 4px 8px;
width: 30px;
}
section div[class^=button] {
background: lightgray;
cursor: pointer;
}
<span>You can click on the buttons:</span>
<section>
<div class="button--1">s1-1</div>
<div class="button--2">s1-2</div>
<div class="button--3">s1-3</div>
<div class="button--4">s1-4</div>
</section>
<section>
<div class="button--1">s2-1</div>
<div class="button--2">s2-2</div>
<div class="button--3">s2-3</div>
<div class="button--4">s2-4</div>
</section>
<section>
<div class="not-a-button">not1</div>
<div class="not-a-button">not2</div>
<div class="not-a-button">not3</div>
<div class="not-a-button">not4</div>
</section>
Hope it helps.
Try using event delegation
(function() {
document.body.addEventListener("click", clickButtons);
// ^ one handler for all clicks
function clickButtons(evt) {
const from = evt.target;
console.clear();
if (!from.className || !/button--\d/i.test(from.className)) { return; }
// ^check if the element clicked is one of the elements you want to handle
// if it's not one of the 'buttons', do nothing
console.log("you clicked " + from.classList);
}
}())
.button--1:before,
.button--2:before {
content: 'BTTN['attr(class)']';
}
.button--1,
.button--2 {
border: 1px solid #999;
background: #eee;
width: 220px;
padding: 3px;
text-align: center;
}
<section>
<div class="b1 button--1 section1"></div>
<div class="b2 button--1 section1"></div>
<div class="b3 button--2 section1"></div>
</section>
<section>
<div class="b4 button--2 section2"></div>
<div class="b5 button--1 section2"></div>
<div class="b6 button--2 section2"></div>
</section>
You can use multiple selectors in the string of querySelctorAll() by separating them with a ,
var button1 = document.querySelectorAll('.button--1');
var button2 = document.querySelectorAll('.button--2');
var allButtons = document.querySelectorAll('.button--1, .button--2');
console.log(button1.length);
console.log(button2.length);
console.log(allButtons.length);
<section>
<div class="button--1"></div>
<div class="button--1"></div>
<div class="button--2"></div>
</section>
<section>
<div class="button--2"></div>
<div class="button--1"></div>
<div class="button--2"></div>
</section>
My suggestion is to use jQuery so that you can do it something like this:
$(document).on('click', '.button--1', function() {
// Do something
});
$(document).on('click', '.button--1', function() {
// Do something
})
But a clean approach for pure Javascript is to create a function that binds a callback for the event.
function bindEvent(callback, eventType, targets) {
targets.forEach(function(target) {
target.addEventListener(eventType, callback);
});
};
var button1 = document.querySelectorAll('.button--1');
var button2 = document.querySelectorAll('.button--2');
bindEvent(function() {
// do something
}, 'click', button1);
bindEvent(function() {
// do something
}, 'click', button2);
The click event is fired when a pointing device button (usually a mouse's primary button) is pressed and released on a single element.
This documentation will help you to understand how it works MDN - Click event
Trying to hide one div at a time (5 seconds intervals between each) and when the third one gets hidden the first one shows right away. And like that infinitely.
I tried this but it's not working well. Hides them successfully but doesn't show them.
setTimeout(function() {
$('#span3').hide();
}, 5000);
setTimeout(function() {
$('#span2').hide();
}, 10000);
setTimeout(function() {
$('#span1').hide();
}, 15000);
setTimeout(function() {
$('#span3').show();
}, 15000);
setTimeout(function() {
$('#span2').show();
}, 20000);
setTimeout(function() {
$('#span1').show();
}, 25000);
.appear-span div span {
display: block;
background-color: black;
padding: 5px 0;
color: white;
width: 200px;
text-align: center;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="appear-span">
<div id="span3">
<span>Selling food.</span>
</div>
<div id="span2">
<span>Selling drink.</span>
</div>
<div id="span1">
<span>Selling kidneys.</span>
</div>
</div>
Where do I add the timings if I want them to hide 5 seconds one after the other?
$("#span3").hide(function(){
$("#span2").hide(function(){
$("#span1").hide(function(){
});
});
});
Check if last div is visible, hide divs one by one and if last div is hidden, show divs one by one.
setInterval(function() {
if ($(".appear-span > div:last").is(":visible"))
$(".appear-span > div:visible").first().hide();
else
$(".appear-span > div:not(:visible)").first().show();
}, 5000);
setInterval(function() {
if ($(".appear-span > div:last").is(":visible"))
$(".appear-span > div:visible").first().hide();
else
$(".appear-span > div:not(:visible)").first().show();
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="appear-span">
<div id="span3">
<span>Selling food.</span>
</div>
<div id="span2">
<span>Selling drink.</span>
</div>
<div id="span1">
<span>Selling kidneys.</span>
</div>
</div>
You can try something like this.
Logic
Hide all divs and show div that is to be shown.
You can use .eq to find element at necessary position
var counter = -1;
function updateUIState(){
$('[id^="span"]').hide().eq(++counter % 3).show()
initTimeout();
}
function initTimeout(){
setTimeout(updateUIState, 1000)
}
initTimeout();
.appear-span div span {
display: block;
background-color: black;
padding: 5px 0;
color: white;
width: 200px;
text-align: center;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="appear-span">
<div id="span3">
<span>Selling food.</span>
</div>
<div id="span2">
<span>Selling drink.</span>
</div>
<div id="span1">
<span>Selling kidneys.</span>
</div>
</div>
Just nest the calls and then recall the same function, use jquery delay.
$(function() {
var delayInterval = 5000;
function hideAndPeek() {
$('#span3').delay(delayInterval).hide(function() {
$('#span2').delay(delayInterval).hide(function() {
$('#span1').delay(delayInterval).hide(function() {
$('#span3').delay(delayInterval).show(function() {
$('#span2').delay(delayInterval).show(function() {
$('#span1').delay(delayInterval).show(function() {
hideAndPeek();
});
});
});
});
});
});
}
setTimeout(hideAndPeek(), delayInterval);
});
p {
font-size: 150%;
cursor: pointer;
}
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="appear-span">
<div id="span3">
<span>Selling food.</span>
</div>
<div id="span2">
<span>Selling drink.</span>
</div>
<div id="span1">
<span>Selling kidneys.</span>
</div>
</div>
</body>