I am creating a mobile web app, I have a login/ signup page where users can choose the method they want.
In order to reduce the refresh rate of pages I am hiding and showing objects depending on what the user clicks with jquery.
I have virtual back buttons on each of the 'pages' which hide/show the objects including the back buttons themselves, each time I need to add an extra 'page' I have to add and call the different buttons.
Is there a way I can have one button and use that depending on what elements are hidden/shown?
e.g
html
<div id="go_button"</div>
<div id="next_button"</div
<div id="backbutton1"</div>
<div id="backbutton2"</div>
<div id="page1"
<p> some information here </p>
</div>
<div id="page2"
<p> some more information here </p>
</div>
jQuery
$("#gobutton").click(function(){
$('#backbutton1').fadeIn(250);
$('#page1').fadeIn(250);
$('#next_button').fadeIn(250);
});
$('#next_button').click(function(){
$('#backbutton1').hide();
$('#backbutton2').show();
$('#page1').fadeOut(250);
$('#page2').fadeIn(250);
$('#next_button').fadeOut(250);
$("#backbutton1").click(function(){
$('#backbutton1').fadeOut(250);
$('#page1').fadeOut(250);
$('#next_button').fadeOut(250);
});
etc etc
Would something like this work for you?
I checked the currently visible page, and based on that and what button is clicked, it would go forward or back.
var
$go = $('#go_button'),
$next = $('#next_button'),
$back = $('#backbutton'),
$pages = $('div[id^=page]');
$go.click(function() {
$next.fadeIn(250);
$back.fadeIn(250);
$pages.first().fadeIn(250);
});
$next.click(function() {
var $current = $pages.filter(':visible'); // Get currently visible page
if (!$current.is($pages.last())) { // If this is not the last page, do something
$current
.hide() // hide current page
.next() // get next page
.fadeIn(250); // fade in next page
}
});
// Opposite of the $next.click
$back.click(function() {
var $current = $pages.filter(':visible');
if (!$current.is($pages.first())) {
$current
.hide()
.prev()
.fadeIn(250);
}
});
div[id^=page] {
padding: 5px 10px;
border: 1px solid #ddd;
display: none;
}
#next_button,
#backbutton {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="go_button">go</button>
<button id="next_button">next</button>
<button id="backbutton">back</button>
<div id="page1">
<p> 1 some information here </p>
</div>
<div id="page2">
<p> 2 some more information here </p>
</div>
<div id="page3">
<p> 3 more information here </p>
</div>
<div id="page4">
<p> 4 more! more! more! more!</p>
</div>
Make a function ..
function operation(name){
if(name == "go_button"){
//operation
}else if(name == "next_button"){
//do this.
}
}
now in html
<div id="go_button" onclick="operation('go_button')" > </div>
<div id="next_button" onclick="operation('next_button')" ></div
Related
I have an XML DB with movies. Each movies comes with a picture. On click on the picture modal opens and in the modal you can see the information about the movie. With the following code I am able to iterate over all my pictures, which are buttons.
btn.forEach(element => {
element.addEventListener("click", () => {
modal.style.display = "block";
} );
} );
Problem is, this opens the same modal all the time, meaning, the content is not dynamically changing, depending on the movie I click. I tried the following
btn.forEach(element => {
element.addEventListener("click", () => {
modal.forEach(item => {
item.style.display = "block";
});
});
});
But this changes the content to the last on the data base, showing again same modal all the time and also breaking the close span for all modals. How do I show a correct modal for each movie?
I would recommend not to use arrow functions here because of context or so to say binding 'this' the best way is to use a plain old function and some DOM traversing
The thing is you havent supplied code for btn so I don't know how are you selcting all buttons but I would do it like so:
Array.from(document.getElementsByClassName('btn')).map(btn => btn.addEventListener('click', function(){
const theContainer = this.closest('.container')
theContainer.getElementsByClassName('modal')[0].classList.add('show')
theContainer.getElementsByClassName('close')[0].onclick = function(){
this.closest('.modal').classList.toggle('show')
}
}))
.modal {
display: none;
}
.show {
display: block;
border: 1px solid red;
}
<div class='container'>
<div class='modal'>
<p> modal </p>
<button class='close'>X</button>
</div>
<button class='btn'>0</button>
</div>
<div class='container'>
<div class='modal'>
<p> modal 1</p>
<button class='close'>X</button>
</div>
<button class='btn'>1</button>
</div>
<div class='container'>
<div class='modal'>
<p> modal 2</p>
<button class='close'>X</button>
</div>
<button class='btn'>2</button>
</div>
<div class='container'>
<div class='modal'>
<p> modal 3</p>
<button class='close'>X</button>
</div>
<button class='btn'>3</button>
</div>
This is the HTML I got to do a button click event to control selected items in more than one list.
$('#button').click(function(){
var $next = $('.section.selected').removeClass('selected').next('.section')
if ($next.length) {
$next.addClass('selected');
}
else {
$(".section:first").addClass('selected');
}
});
//On click I select next div with same class and remove selected from previous.
//How to loop? After 3 is selected, I want it to go to one again.
.selected { background:red }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="all">
<div class="section selected">ONE</div>
<div class="section">TWO</div>
<div class="section">THREE</div>
</div>
<div id="all">
<div class="section selected">ONE</div>
<div class="section">TWO</div>
<div class="section">THREE</div>
</div>
<br />
CLICK
However, because the items are using the same class name, at the end, the script can't decide which one is first / last item.
Can anyone give me an idea?
To get the items, use Queries like first-child, last-child and so on.
For more detals, Check jQuery API Documentation
Use this instead $(".section:first-child").addClass('selected') in your else condition
I want to add a CSS class name to the next sibling of an element as soon as I click on it to get a simple show/hide effect
I have the following html output and I don't have element-ID's.
<div class="news-message">
<div class="message-head"> Headline of Message 1 </div>
<div class="message-content"> Here comes the content of message 1 </div>
</div>
<div class="news-message">
<div class="message-head"> Headline of Message 2 </div>
<div class="message-content"> Here comes the content of message 2 </div>
</div>
<div class="news-message">
<div class="message-head"> Headline of Message 3 </div>
<div class="message-content"> Here comes the content of message 3 </div>
</div>
Now I want to hide the message-content and just display the headline (easy to realize with display: none).
As soon as I click on the headline, I want the content of that specific message to be displayed.
So my idea was to add a CSS class "visible" to the DIV "message-content" by click on message-head and remove it by another click.
So I added a "onClick="changeClass()" to the "pm-head" Element and the following javascript
function changeClass() {
var hidecontent = document.querySelectorAll('.message-content');
var i;
for (i = 0; i < hidecontent.length; i++) {
hidecontent[i].classList.toggle('visible'); } }
but this adds the class visible to all "message-content" divs on that page while I just need it to be added to the next sibling of the "pm-head" element on which I have clicked.
And I can´t use jquery or other frameworks/libraries on this one.
Sorry, I am new to javascript, probably an easy to answer question.
Thanks
John
nextSibling is the answer you seek.
Without testing it myself, but this should work for you:
function changeClass(e) {
e.target.nextSibling.classList.toggle("visible");
}
You could use this code, which requires an extra class hidden to be defined, and to be added to your HTML for each of the message-content tags:
Array.from(document.querySelectorAll('.news-message'), function (elem) {
elem.addEventListener('click', function hideContent(e) {
e.currentTarget.querySelector('.message-content').classList.toggle('hidden');
});
});
Array.from(document.querySelectorAll('.news-message'), function (elem) {
elem.addEventListener('click', function hideContent(e) {
e.currentTarget.querySelector('.message-content').classList.toggle('hidden');
});
});
.hidden { display:none; }
<div class="news-message">
<div class="message-head">
Headline of Message 1
</div>
<div class="message-content hidden">
Here comes the content of message 1
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 2
</div>
<div class="message-content hidden">
Here comes the content of message 2
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 3
</div>
<div class="message-content hidden">
Here comes the content of message 3
</div>
</div>
Note that although you could use nextSibling, this uses another approach: it captures the click on the news-message element, which is the parent, then locates the message-content element, and finally toggles the hidden class on it.
By capturing the click event on the parent level, you can also toggle the content's display by clicking on the content itself. This can be useful. If you don't want this behaviour then change the code to this:
Array.from(document.querySelectorAll('.message-head'), function (elem) {
elem.addEventListener('click', function hideContent(e) {
e.currentTarget.parentNode.querySelector('.message-content')
.classList.toggle('hidden');
});
});
Array.from(document.querySelectorAll('.message-head'), function (elem) {
elem.addEventListener('click', function hideContent(e) {
e.currentTarget.parentNode.querySelector('.message-content')
.classList.toggle('hidden');
});
});
.hidden { display:none; }
<div class="news-message">
<div class="message-head">
Headline of Message 1
</div>
<div class="message-content hidden">
Here comes the content of message 1
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 2
</div>
<div class="message-content hidden">
Here comes the content of message 2
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 3
</div>
<div class="message-content hidden">
Here comes the content of message 3
</div>
</div>
This variation will only process clicks on the header, go to its parent node, and proceed from there as before.
I'd suggest, if you're able to use ES6:
// a named function to handle the toggling of visibility:
function toggleNextSibling(event) {
// event.target is the element/node that triggered
// the event:
event.target
// the nextElementSibling finds the next element
// sibling of the clicked node:
.nextElementSibling
// we use Element.classList.toggle to add the
// supplied class-name if it's not present, or
// remove the supplied class-name if it is
// present:
.classList.toggle('shown');
}
// here we document.querySelectorAll() to retrieve a (non-live)
// NodeList of the elements of the document that match the
// supplied CSS selector, this NodeList is then passed to
// Array.from() to convert the Array-like NodeList into an
// Array:
Array.from(document.querySelectorAll('.message-head'))
// as we have an Array we can then use Array.prototype.forEach()
// to iterate over each element of the Array to perform actions
// upon them:
.forEach(
// 'head' is a reference to the Array element of the Array
// over which we're iterating, and upon each of those
// Array elements we're then using addEventListener() to
// bind a function (toggleNextSibling()) as the event-
// handler for the 'click' event (but note the deliberate
// absence of parentheses following the function name):
head => head.addEventListener('click', toggleNextSibling)
);
function toggleNextSibling(event) {
event.target.nextElementSibling.classList.toggle('shown');
}
Array.from(document.querySelectorAll('.message-head'))
.forEach(head => head.addEventListener('click', toggleNextSibling));
.message-head {
cursor: pointer;
margin: 0.5em 0 0 0;
}
.news-message:first-child.message-head {
margin-top: 0;
}
.message-content {
display: none;
text-indent: 1em;
color: rebeccapurple;
}
.message-content.shown {
display: block;
}
<div class="news-message">
<div class="message-head">
Headline of Message 1
</div>
<div class="message-content">
Here comes the content of message 1
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 2
</div>
<div class="message-content">
Here comes the content of message 2
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 3
</div>
<div class="message-content">
Here comes the content of message 3
</div>
</div>
Without ES6 the above can be translated to the following (albeit the function itself requires no changes):
// here we use Function.prototype.call(), to enable us to
// pass the NodeList to Array.prototype.slice(), which converts
// the NodeList to an Array:
Array.prototype.slice.call(document.querySelectorAll('.message-head'))
// again, having an Array allows us to use Array methods, but
// here we cannot use Arrow function expressions (as they were
// not available until ES6), so instead we use a function expression:
.forEach(function(head) {
// 'head' refers to the current Array element of the Array
// over which we're iterating, and we again use addEventListener
// to bind the named function to the 'click' event:
head.addEventListener('click', toggleNextSibling)
});
function toggleNextSibling(event) {
event.target.nextElementSibling.classList.toggle('shown');
}
Array.prototype.slice.call(document.querySelectorAll('.message-head'))
.forEach(function(head) {
head.addEventListener('click', toggleNextSibling)
});
.message-head {
cursor: pointer;
margin: 0.5em 0 0 0;
}
.news-message:first-child.message-head {
margin-top: 0;
}
.message-content {
display: none;
text-indent: 1em;
color: rebeccapurple;
}
.message-content.shown {
display: block;
}
<div class="news-message">
<div class="message-head">
Headline of Message 1
</div>
<div class="message-content">
Here comes the content of message 1
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 2
</div>
<div class="message-content">
Here comes the content of message 2
</div>
</div>
<div class="news-message">
<div class="message-head">
Headline of Message 3
</div>
<div class="message-content">
Here comes the content of message 3
</div>
</div>
This is my first question in here, so any direction for making a better ask is appreciated, and of course any help even more so. :-)
I am working with Drupal behaviors and jquery to setup navigation for a long form. (Form is created using entityform)
I have three dropdowns (One on the top, one in a side bar and one below the form) that the user can use to navigate from one "page" to another. The dropdown at the bottom also includes prev and next buttons.
My issue is that all the bottom dropdown and prev and next buttons are not working properly. The issues are as follows:
When selecting an element from the bottom dropdown list it doesn't change
the content (Adding and removing class hidden). The top and side
dropbar works
When clicking next I am taken to the next page. However, when I click prev I am taken to the first page and the next button also no longer works.
I have tried to create a JSfiddle It has the correct HTML markup, but I cannot get the JS to work, maybe because it was made for drupal behaviors. A live version can be found here.
I have experimented with prevAll() and nextAll(), instead of prev() and next() but not getting any improvements. And I am pretty lost on why the bottom dropdown doesn't work when the others are.
Html Markup
<div class="preform">
<select id="topnav" class="navdrop">
<option>title1</option>
<option>title2</option>
<option>title3</option>
</select>
</div>
<div id="form">
<div class="row">
<div class="col1">
<div class="page">
<h3>title1</h3>
[some content]
</div>
<div class="page">
<h3>title2</h3>
[some content]
</div>
<div class="page">
<h3>title3</h3>
[some content]
</div>
</div>
<div class="col2">
<div class="static">
<select id="bottomnav" class="navdrop">
<option>title1</option>
<option>title2</option>
<option>title3</option>
</select>
</div>
</div>
</div>
</div>
<div id="form-nav">
<input value="Previous" type="button" class="btn btn-default" id="buttonPrev">
<select id="bottomnav" class="navdrop">
<option>title1</option>
<option>title2</option>
<option>title3</option>
</select>
<input value="Next" type="button" class="btn btn-default" id="buttonNext">
</div>
jquery that runs once on page load to setup start conditions
$('#edit-actions',context).once('gotButtons', function() {
/* hides pages and shows welcome page on first load */
$(".page").addClass("hidden");
$("h3:contains('title1')").parent().removeClass("hidden");
$("#buttonPrev",context).prop('disabled', true);
$(".nav-drop > option:selected").attr("selected","selected");
});
jquery on change of dropdown event
$(".nav-drop",context).change(function() {
/* hides everything */
$(".page").addClass("hidden");
/* unhides the selected item */
var item = this.value;
$('.page h3').filter(function(){
return($(this).text() == item);
}).parent().removeClass("hidden");
/* update all dropdowns to the chosen value */
$(".nav-drop",context).val(item);
/* Disable first and last button */
var isFirstElementSelected = $('#topnav > option:selected').index() === 0;
var isLastElementSelected = $('#topnav > option:selected').index() == $('#topnav > option').length -1;
if (isFirstElementSelected) {
$("#buttonPrev",context).prop('disabled', true);
$("#buttonNext",context).prop('disabled', false);
} else if (isLastElementSelected) {
$("#buttonPrev",context).prop('disabled', false);
$("#buttonNext",context).prop('disabled', true);
} else {
$("#buttonPrev",context).prop('disabled', false);
$("#buttonNext",context).prop('disabled', false);
}
});
jquery for button clicked
/* Adds next/prev functionality */
$("#buttonNext").click(function() {
$('.nav-drop > option:selected').removeAttr('selected').next('option').attr('selected', 'selected');
$(".nav-drop",context).trigger("change");
});
$("#buttonPrev").click(function() {
$('.nav-drop > option:selected').removeAttr('selected').prevAll('option').attr('selected', 'selected');
$(".nav-drop",context).trigger("change");
});
Thank you for your help in advance!
<html>
<head>
<style type='text/css'>
span {
text-decoration:underline;
color:blue;
cursor:pointer;
}
</style>
<script>
// show the given page, hide the rest
function show(elementID) {
// try to find the requested page and alert if it's not found
var ele = document.getElementById(elementID);
if (!ele) {
alert("no such element");
return;
}
// get all pages, loop through them and hide them
var pages = document.getElementsByClassName('page');
for(var i = 0; i < pages.length; i++) {
pages[i].style.display = 'none';
}
// then show the requested page
ele.style.display = 'block';
}
</script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function() {
$( "#accordion" ).accordion();
});
</script>
</head>
<body>
<div style="float: left; width: 20%;">
<div id="accordion">
<h3>Section 1</h3>
<div>
<p>
<button>Link 1</button>
</p>
</div>
<h3>Section 2</h3>
<div>
<p>
<button>Link 2</button>
</p>
</div>
</div>
</div>
<div style="float: right; width: 75%;">
<div>
<p>
Show page
<span onclick="show('Page1');">1</span>,
<span onclick="show('Page2');">2</span>,
<span onclick="show('Page3');">3</span>.
</p>
<div id="Page1" class="page" style="">
Content of page 1
</div>
<div id="Page2" class="page" style="display:none">
Content of page 2
</div>
<div id="Page3" class="page" style="display:none">
Content of page 3
</div>
</div>
</div>
</body>
</html>
Above is the code that I have so far.
Right now, when clicking on page 1, page 2, or page 3, the desire page will appear below. This code is set up on the right side of the page. <div style="float: right; width: 75%;">
On the left side of the page <div style="float: left; width: 20%;">, i have an accordion with a couple button links. My question is when clicking on button link 1 or button link 2 in the accordion, how can I switch the right page from a selection of different pages keeping the same function it has right now.
Thus, first i would click on button link 1 in the accordion to show desired page on the right side and if i would like to switch pages, then i would click on button link 2 in the accordion and show that desired page.
For visual, please see this fiddle
If you saw the fiddle, then the links inside of the black box switch pages within the div, but I would like to add another function and switch the black boxes depending if the user presses button link 1 or button link 2
Any suggestions? thanks!
I am not certain that I understand the question correctly.
What I believe could be very useful for you, is to look into jQuery UI Tabs:
http://jqueryui.com/tabs/
and link the tab click events to the accordion menu.
Edit:
JSFiddle, including the jQuery UI tabs.
Provided the code on how you can activate the tabs on a click event from the accordion menu.
http://jsfiddle.net/kimgysen/BcCnL/2/
$(document).ready(function() {
//Tabs
$('#body_div').tabs();
$('#newsfeed').click(function(){
$("#body_div").tabs("option", "active", 0);
});
$('#myprofile_edit').click(function(){
$("#body_div").tabs("option", "active", 1);
});
$('#myprofile_view').click(function(){
$("#body_div").tabs("option", "active", 2);
});
});