Multi-level menu for an FAQ - javascript

I am making a FAQ that ask you 3 question to give you the correct answer. It works in the same way as this website: Nokia Lumia FAQ.
The code works. You have 3 level of content to see depending on the button you press. When a button is pressed on level 1, level 2 and level 3 it will change color so you end with three button that have changed color, its easier to understand in that way you wanted help for Example: Phone - Andriod - Simcard help.
Notice that level 1 and level 2 content have much simliar in the JS code, but level 3 is a bit different because there your browser scroll you down when the content is displayed. And also level 3 does have hyperlink instead of button.
I have to manually dublicate part of this JS code for adding new buttons, and i think there can be an easier way. I really appreciate any help.
Here is the JS:
$(document).ready(function(){
// Level 1
function show(sel) {
var el = $(sel);
el.fadeToggle();
$('.showmore-1').not(el).fadeOut("slow");
}
$('.showmore-1').hide();
$('.click-1').click(function(){
$('.click-1').removeClass('clickcolor')
$(this).addClass('clickcolor');
});
$('#click-1a').click(function () {
show('#showmore-1a');
});
$('#click-1b').click(function () {
show('#showmore-1b');
});
$('#click-1c').click(function () {
show('#showmore-1c');
});
// Level 2
function show(sel) {
var el = $(sel);
el.fadeToggle();
$('.showmore-2').not(el).fadeOut("slow");
}
$('.showmore-2').hide();
$('.click-2').click(function(){
$('.click-2').removeClass('clickcolor')
$(this).addClass('clickcolor');
});
$('#click-2a').click(function () {
show('#showmore-2a');
});
$('#click-2b').click(function () {
show('#showmore-2b');
});
$('#click-2c').click(function () {
show('#showmore-2c');
});
// Level 3
function show(sel) {
var el = $(sel);
el.fadeToggle();
$('.showmore-3').not(el).fadeOut("slow");
}
$('.showmore-3').hide();
$('.click-3').click(function(){
$('.click-3').removeClass('clickcolortext') //Level 3 display text instead of button to be pressed and therefore another class of color.
$(this).addClass('clickcolortext');
});
$('#click-3a').click(function () {
show('#showmore-3a');
$('html, body').scrollTop($('#showmore-3a').offset().top);
return false;
});
$('#click-3b').click(function () {
show('#showmore-3b');
$('html, body').scrollTop($('#showmore-3b').offset().top);
return false;
});
$('#click-3c').click(function () {
show('#showmore-3c');
$('html, body').scrollTop($('#showmore-3c').offset().top);
return false;
});
});
enter code here
Here is a part of the HTML
<button class="click-1" id="click-1a">Mobile</button>
<button class="click-1" id="click-1b">PC</button>
<button class="click-1" id="click-1c">Tablet</button>
<div id="showmore-1a" class="showmore-1">View content for mobile help</div>
<div id="showmore-1b" class="showmore-1">View content for pc help</div>
<div id="showmore-1c" class="showmore-1">View content for tablet help</div>
enter code here
Here is the CSS
.clickcolor {
background-color: #4d4d4d !important;
}
.clickcolortext {
color: #4d4d4d !important;
}

Add a target attribute on buttons:
<button class="click-1" id="click-1a" data-target="#showmore-1a">Mobile</button>
<button class="click-1" id="click-1b" data-target="#showmore-1b">PC</button>
<button class="click-1" id="click-1c" data-target="#showmore-1c">Tablet</button>
JS
$('button.click-1').click(function(){
$('.click-1').removeClass('clickcolor')
$(this).addClass('clickcolor');
show($(this).data('target'));
});

To shorten this bit of code:
$('#click-1a').click(function () {
show('#showmore-1a');
});
$('#click-1b').click(function () {
show('#showmore-1b');
});
$('#click-1c').click(function () {
show('#showmore-1c');
});
Well, I could tell this:
$('[id^="click-"]').click(function () {
show('#showmore-' + this.id.replace("click-", ""));
});

Related

toggleClass for different functions

I guess this code does not work, because at DOM load jQuery caches its objects and bind the functions to them?
$('span.button.slide_out').on('click', function () {
$(this).toggleClass('slide_out').toggleClass('slide_in');
$('#testbox').slideDown();
});
$('span.button.slide_in').on('click', function () {
$(this).toggleClass('slide_out').toggleClass('slide_in');
$('#testbox').slideUp();
});
I know I could write this easily with slideToggle or something else, but I have to fire different actions on every first and every second click. How can I achieve this using the same selector (instead of creating two different selectors)?
JS FIDDLE
The binding is indeed done on DOM creation, but that doesn't have to be a problem in this case, it also means that the button is still clicked if it no longer has the slide_out class. Therefore you can reuse the same click event and check the current state to choose whether to slide up or down. For example:
$('.slide_out').on('click', function () {
if($(this).toggleClass('slide_out slide_in').hasClass('slide_in'))
$('#testbox').slideDown();
else
$('#testbox').slideUp();
});
Fiddle
You could use the solution from Event binding on dynamically created elements?, as suggested by https://stackoverflow.com/users/502381/juhana:
HTML:
<span class="button_container"><span class="button slide_out">Click me</span></span>
<div id="testbox">Whohoohoooo, I am slidiiing!<br><br><small>Hey… wait! Why I am not sliding up again?</small></div>
JS:
$('.button_container').on('click', '.slide_out', function () {
$(this).toggleClass('slide_out').toggleClass('slide_in');
$('#testbox').slideDown();
});
$('.button_container').on('click', '.slide_in', function () {
$(this).toggleClass('slide_out').toggleClass('slide_in');
$('#testbox').slideUp();
});
http://jsfiddle.net/ag3cpcfb/
But, in my opinion it would be better to make your code simpler by using slideToggle() and adjust your css classes:
HTML:
<span class="button">Click me</span>
<div id="testbox">Whohoohoooo, I am slidiiing!<br><br><small>Hey… wait! Why I am not sliding up again?</small></div>
JS:
$('.button').on('click', function () {
var $testbox = $('#testbox');
if ($testbox.is(':visible')) {
console.log('Click 1');
} else {
console.log('Click 2');
}
$(this).toggleClass('slide_in');
$testbox.slideToggle();
});
http://jsfiddle.net/k77ferjh/
But this fires "Click 1" all of the time if you repeatedly click on the button. If this is not an issue, fine, if it is, you can also use a number to keep track of your clicks:
JS:
var clicks = 0;
$('.button').on('click', function () {
clicks++;
if (clicks % 2 == 0) {
console.log('Slide out');
} else {
console.log('Slide in');
}
$(this).toggleClass('slide_in');
$('#testbox').slideToggle();
});
http://jsfiddle.net/k77ferjh/1/

Change TinyMCE HTML after the plugin is enabled

I can change the HTML displayed in TinyMCE by clicking "restore". I now wish to return the HTML to the orignal HTML by clicking "cancel". For the life of me, I cannot figure out why my approach doesn't work (it displays the newly modified HTML). How is this accomplished. Please see http://jsfiddle.net/3pn3x4zj/ which is duplicated below. Thank you.
JavaScript
tinymce.init({
selector: '#tinymce',
setup: function (ed) {
ed.on('init', function (e) {
e.target.hide();
});
}
});
$(function () {
$('#cancel').hide();
$('#restore').click(function () {
console.log('Save old HTML and put new HTML from GET request in DIV');
$('#cancel').show();
$('#restore').hide();
$(this).parent().data('oldHTML', $('#tinymce').html());
var newHTMLgottenFromGetRequest = '<p>Bar Bar Bar</p>'
$('#tinymce').html(newHTMLgottenFromGetRequest);
tinymce.get('tinymce').show();
});
$('#cancel').click(function () {
console.log('Put back original HTML');
$('#cancel').hide();
$('#restore').show();
$('#tinymce').html($(this).parent().data('oldHTML'));
tinymce.get('tinymce').hide();
});
});
HTML
<div id="tinymce">
<p>Foo Foo Foo</p>
</div>
<button id="restore">restore</button>
<button id="cancel">cancel</button>
Try reversing these lines in the #cancel click event:
$('#tinymce').html($(this).parent().data('oldHTML'));
tinymce.get('tinymce').hide();
becomes
tinymce.get('tinymce').hide();
$('#tinymce').html($(this).parent().data('oldHTML'));

If..Then in jQuery to check for open slideToggle()

I am using 'slideToggle' to open a couple divs on a site and want to ensure all of the divs are closed before another is opened. Is there a way to run a if..then to ensure a toggled div isn't open before opening another?
Here is my script;
<script type="text/javascript">
$(function()
{
$("a#toggle").click(function() {
$("#contact").slideToggle(500);
return false;
});
$("a#toggle_about").click(function(){
$("#about").slideToggle(500);
return false;
});
});
</script>
Calling tag;
<li>Contact Me</li>
And called div;
<div id="contact">blah, blah...</div>
And CSS;
#contact{display: none; padding: 7px; font-size: 14px;}
Thanks,
------EDIT------
This seems to work ok, I can control the transition by setting speed to 500 or 0. It just seems like a lot of code for a simple if..then.
Thanks for the suggestions and possible solutions.
<script type="text/javascript">
$(function()
{
$("a#toggle").click(function(){
if ($("#about").is(':hidden')){
$("#contact").slideToggle(500);
return false;
}else{
$("#about").slideToggle(500);
$("#contact").slideToggle(500);
return false;
}
});
$("a#toggle_about").click(function(){
if ($("#contact").is(':hidden')){
$("#about").slideToggle(500);
return false;
}else{
$("#contact").slideToggle(500);
$("#about").slideToggle(500);
return false;
}
});
});
</script>
Fiddle Example
If you add appropriate classes to your html and change the href to target the div it needs to open, you can significantly simplify your code.
<ul>
<li>Contact Me</li>
<li>About Me</li>
</ul>
<div id="contact" class="toggleable">blah, blah...</div>
<div id="about" class="toggleable">blah, blah...</div>
Now you can handle both links with a single event.
$(".toggler").click(function (e) {
e.preventDefault();
var target = $(this).attr("href");
$(".toggleable").not(target).hide();
$(target).slideToggle();
});
the end result is when you click on "Contact Me", about will hide if it is open, and contact will show if it is hidden or hide if it is shown.
http://jsfiddle.net/nYLvw/
You could implement a helper function to collapse any visible elements with a certain class, and then call that every time you're about to toggle a div.
The markup:
<div id="contact" class="toggle-content">blah, blah...</div>
The code:
function hideToggleContent() {
$('.toggle-content:visible').slideUp( 500 );
}
$(function() {
$("#toggle").click( function() {
var isVisible = $("#contact").is(':visible');
hideToggleContent();
if( isVisible ) {
return false;
}
$("#contact").slideDown( 500 );
return false;
});
$("#toggle_about").click( function() {
var isVisible = $("#about").is(':visible');
hideToggleContent();
if( isVisible ) {
return false;
}
$("#about").slideDown( 500 );
return false;
});
});
You might also check out the jQuery UI accordion, it's default behavior accomplishes the same. http://jqueryui.com/accordion/
UPDATE: Added Fiddle Link For Example
There are several ways to solution this problem.
Whenever you are tweening for effect, and you want to only tween if not already tweening, you will want to track the state of your tween.
Typically, you might have a trigger/toggler, and a target. I like to use closures to accomplish the state tracking. I might use something like this:
$(function () {
// closures
var $togglers = $('[selector][, selector]');
var $target = $('[selector]');
$target.tweening = false;
var tweenStop = function () {
$target.tweening = false;
};
var togglerClick = function () {
if (!$target.tweening) {
$target.tweening = true;
$target.slideToggle(500, tweenStop);
}
};
// handle the event
$togglers.click(togglerClick);
});
>> SAMPLE FIDDLE <<

jQuery animate div up down on click

So I have this HTML
<div id="one">One</div>
<div id="two">Two <br/> <br/>
Two
</div>
<div id="three">Three</div>
<div id="four">Four <br/> <br/>
Four <br/> <br/>
Four
</div>
jQuery:
$(document).ready(function () {
$("#two").hide();
$("#four").hide();
$("#one").click(function () {
$("#four").slideUp("slow", function () {
});
$("#three").slideToggle("slow,", function () {
});
$("#two").slideToggle("slow", function () {
});
});
$("#three").click(function () {
$("#four").slideToggle("slow,", function () {});
});
});
What I'm trying to do is show div one and three one under another.
When I click div one, I want div two to show (animate), and div three (and div four, if div three is clicked too) to move position under div two (with same animation).
When I click div one again, I want div two to hide (animate) and div three (and div four, if div three clicked) to go back to the position they had before.
Here's JSFiddle: http://jsfiddle.net/6ynnR/
It seems like you want something like this: EXAMPLE HERE
Updated jQuery:
$("#two, #four").hide();
$("#one").click(function () {
$("#two").slideToggle(function () {
$("#four").slideUp();
});
});
$("#three").click(function () {
$("#four").slideToggle(function () {
$("#two").slideUp()
});
});
Alternatively, here is another approach: EXAMPLE HERE
Just remove the following code and you're good to go :D
$("#four").slideUp("slow", function () {
});
$("#three").slideToggle("slow,", function () {
});
I hope this will work for you,
I added conditional statement:
if(($("#two").is(":visible"))&&($("#four").is(":visible"))){
$("#four").slideToggle("slow,", function () {});
$("#two").slideToggle("slow,", function () {});
}
and removed two functions :
$("#four").slideUp("slow", function () {
});
$("#three").slideToggle("slow,", function () {
});
http://jsfiddle.net/uY73z/19/

jQuery drop-down bug when used in my rails 3 app but works outside it?

I'm new to jquery but I'm trying to learn. I'm working with a drop down button that works just fine in jsfiddle. However, when I try it in my rails 3 app, it won't work. (nothing drops down when you click the link). working jsifiddle http://jsfiddle.net/rKaPN/32/
If I remove the line $(".menu").fixedMenu(); and add it into the html like this it works. I'm stumped as to why its not working unless I remove the $(".menu").fixedMenu(); line
NOT working
(function ($) {
$.fn.fixedMenu = function () {
return this.each(function () {
var menu = $(this);
$("html").click(function() {
menu.find('.drop-down').removeClass('drop-down');
});
menu.find('ul li > a').bind('click',function (event) {
event.stopPropagation();
//check whether the particular link has a dropdown
if (!$(this).parent().hasClass('single-link') && !$(this).parent().hasClass('current')) {
//hiding drop down menu when it is clicked again
if ($(this).parent().hasClass('drop-down')) {
$(this).parent().removeClass('drop-down');
}
else {
//displaying the drop down menu
$(this).parent().parent().find('.drop-down').removeClass('drop-down');
$(this).parent().addClass('drop-down');
}
}
else {
//hiding the drop down menu when some other link is clicked
$(this).parent().parent().find('.drop-down').removeClass('drop-down');
}
})
});
}
$(".menu").fixedMenu();
})(jQuery);
Working
html
<script>
$('document').ready(function(){
$('.menu').fixedMenu();
});
</script>
js
(function ($) {
$.fn.fixedMenu = function () {
return this.each(function () {
var menu = $(this);
$("html").click(function() {
menu.find('.drop-down').removeClass('drop-down');
});
menu.find('ul li > a').bind('click',function (event) {
event.stopPropagation();
//check whether the particular link has a dropdown
if (!$(this).parent().hasClass('single-link') && !$(this).parent().hasClass('current')) {
//hiding drop down menu when it is clicked again
if ($(this).parent().hasClass('drop-down')) {
$(this).parent().removeClass('drop-down');
}
else {
//displaying the drop down menu
$(this).parent().parent().find('.drop-down').removeClass('drop-down');
$(this).parent().addClass('drop-down');
}
}
else {
//hiding the drop down menu when some other link is clicked
$(this).parent().parent().find('.drop-down').removeClass('drop-down');
}
})
});
}
})(jQuery);
The line:
$(".menu").fixedMenu();
cannot be executed until the page has been loaded and the DOM is fully in place.
Thus, it works when you surround it with $(document).ready() and doesn't work when you directly executed it in your startup JS. When it's executed before the DOM is ready, the DOM object $(".menu") can't be found so it does nothing.
It works in the jsFiddle because ALL your code is wrapped in an onload handler (per the settings in the upper left of the jsFiddle).

Categories

Resources