I'm using jQuery hide and show function but I have a problem with the show one.
My javascript code is:
function toggle_visibility(idContent, idLien, question) {
var c = document.getElementById(idContent);
var l = document.getElementById(idLien);
var q = question;
if(c.style.display == 'block') {
$("#" + idContent).hide("blind") ;
l.innerHTML = '<h4><i class=\"icone-rouge icon-right-open-big\"></i>'+ q +'</h4>' ;
}
else {
$("#" + idContent).show("blind") ;
l.innerHTML = '<h4><i class=\"icone-rouge icon-down-open-big\"></i>'+ q +'</h4>' ;
}
}
The problem is that it doesn't work for the hide part when the div is hidden at the load of the page (with display='none'). I can display the block but then I cannot hide it.
I noticed that when I show a content, jQuery delete the display attr in my html style... Maybe there is a link.
Here a link for example : http://jsfiddle.net/29c4D/2/
Thank you.
DescampsAu, since you are using jQuery I rewrote your code to take full advantage of the powerful library. You can see the example in this fiddle.
Let jQuery do the heavy lifting of checking whether an element is hidden or not by making use of either the .toggle() or .slideToggle() methods.
Remove all of the onClick() code within your spans and use this jQuery instead:
jQuery
$(document).ready( function() {
//After the page has loaded, let jQuery know where all of the spans are.
var toggleThis = $(".toggleMe");
//Whenever you click one of the spans do this function.
toggleThis.click( function() {
//Register the span you clicked and the next div that holds the hidden stuffs.
var el = $(this),
nextDiv = el.next(".toggleMeDiv");
//Check if the span's partner div is hidden or showing by checking its css "display" value.
if(nextDiv.css("display") == "block") {
//Change the text of the span to be its title attribute plus whether its partner is showing or hidden.
el.html(el.attr("title")+" hidden");
} else {
el.text(el.attr("title")+" shown");
}
//Let jQuery toggle the partner's visibility.
nextDiv.slideToggle();
});
});
HTML
<span class="toggleMe" title="Quest 1">Quest 1</span>
<div class="toggleMeDiv">Boubou1</div>
<span class="toggleMe" title="Quest 2">Quest 2</span>
<div class="toggleMeDiv">Boubou2</div>
Making this too hard on yourself.
HTML
<span class="toggle" id="lien1" data-original-text="Quest 1">Quest 1</span>
<div id="content1">Boubou1</div>
<span class="toggle" id="lien2" data-original-text="Quest 1">Quest 2</span>
<div id="content2">Boubou2</div>
JS
$(document).ready( function () {
$('.toggle').on('click', function() {
$(this).next('div').toggle('blind', textToggle); // or slideToggle();
});
function textToggle() {
var $target = $(this).prev('span'); // "this" is the div that was toggled.
var originalText = $target.attr('data-original-text');
if ( $(this).is(':visible') ) {
$target.text( originalText + ' open' );
} else {
$target.text( originalText + ' closed' );
}
}
});
A fiddle: http://jsfiddle.net/29c4D/7/
EDIT to include label + effect.
Related
Im trying to have a href link expand/display extra text when clicked however when I click it nothing happens.
When I run the html code I can click on the link but it does not show the text for some reason.
Any idea why?
Heres the code:
<html>
click to expand
<div id="divID" style="display: none;">this is expanded</div>
</html>
I'm trying to keep the code as short as possible as the above code will have to be repeated hundreds of times for each link.
Assuming you're using jQuery, you are using the CSS selector incorrectly. Your line should be this:
click to expand
The # in #divID represents any element with an id of divID, whereas just using divID will search for divID tags (something like <divID></divID>)
See here for more documentation on the ID Selector and here's a list of all the CSS selectors you can use, including the Element Selector for you to understand why your previous code didn't work.
You can also combine CSS selectors to narrow your selection in the future, although it's not much necessary with an ID selector:
click to expand
And if you absolutely insist on not using jQuery:
click to expand
or breaking it out into its own function:
<script>
function toggleElementById(id) {
if (document.getElementById(id).style.display == 'none') {
document.getElementById(id).style.display = 'block';
} else {
document.getElementById(id).style.display = 'none';
}
}
</script>
click to expand
Add this to your page:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Then:
$('#divID').toggle();
I see you're using jQuery, right? So I wrote your answer in jQuery..
$('.toggle').click(function () {
var selected = $(this).attr('href');
$('.expandable'+selected).toggle();
});
Check out the jsfiddle
If you're not using jQuery than here is the javascript version (html changed).
var expandable = document.getElementsByClassName("expandable");
for (i = 0; i < expandable.length; ++i) {
expandable[i].setAttribute('style','display: none;');
}
var toggle = document.getElementsByClassName("toggle");
for (i = 0; i < toggle.length; ++i) {
toggle[i].setAttribute('onclick','toggler(this)');
}
function toggler(obj) {
var id = obj.dataset.toggle,
el = document.getElementById(id);
el.style.display = (el.style.display != 'none' ? 'none' : '');
}
Check out the jsfiddle
I have a lot of click handler functions which are almost (textually and functionally) identical. I've got a menu with maybe 10 items in it; when I click on an item, the click handler simply makes one div visible, and the other 9 div's hidden. Maintaining this is difficult, and I just know there's got to be a smart and/or incomprehensible way to reduce code bloat here. Any ideas how? jQuery is Ok. The code at the moment is:
// repeat this function 10 times, once for each menu item
$(function() {
$('#menuItem0').click(function(e) {
// set 9 divs hidden, 1 visble
setItem1DivVisible(false);
// ...repeat for 2 through 9, and then
setItem0DivVisible(true);
});
});
// repeat this function 10 times, once for each div
function setItem0DivVisible(on) {
var ele = document.getElementById("Item0Div");
ele.style.display = on? "block" : "none";
}
Create 10 div with a class for marking
<div id="id1" class="Testing">....</div>
<div id="id2" class="Testing">....</div>
<div id="id3" class="Testing">....</div>
and apply the code
$('.Testing').each(function() {
$(this).click(function() {
$('.Testing').css('display', 'none');
$(this).css('display', 'block');
}
}
$(document).ready(function (){
$("div").click(function(){
// I am using background-color here, because if I use display:none; I won't
// be able to show the effect; they will all disappear
$(this).css("background-color","red");
$(this).siblings().css("background-color", "none");
});
});
Use .siblings() and it makes everything easy. Use it for your menu items with appropriate IDs. This works without any for loops or extra classes/markup in your code. And will work even if you add more divs.
Demo
Fiddle - http://jsfiddle.net/9XSJW/1/
It's hard to know without an example of the html. Assuming that there is no way to traverse from the menuItem to ItemDiv - you could use .index and .eq to match up the elements based on the order they match with the selector.
var $menuItems = $("#menuItem0, #menuItem1, #menuItem2, ...");
var $divs = $("#Item0Div, #Item1Div, #Item2Div, ...");
$menuItems.click(function(){
var idx = $(this).index();
// hide all the divs
$divs.hide()
// show the one matching the index
.eq(idx).show();
})
Try
function addClick(i) {
$('#menuItem'+i).click(function(e) {
// set nine divs hidden, 1 visble
for( var j = 0; j < 10; ++j ) {
var ele = document.getElementById("Item"+j+"Div");
ele.style.display = (i == j ? "block" : "none");
}
});
}
// One click function for all menuItem/n/ elements
$('[id^="menuItem"]').on('click', function() {
var id = this.id; // Get the ID of the clicked element
$('[id^="Item"][id$="Div"]').hide(); // Hide all Item/n/Div elements
$('#Item' + id + 'Div').show(); // Show Item/n/Div related to clicked element
});
Obviously this would be much more logical if you were using classes instead:
<elem class="menuItem" data-rel="ItemDiv-1">...</elem>
...
<elem class="ItemDiv" id="ItemDiv-1">...</elem>
$('.menuItem').on('click', function() {
var rel = $(this).data('rel'); // Get related ItemDiv ID
$('.ItemDiv').hide(); // Hide all ItemDiv elements
$('#' + rel).show(); // Show ItemDiv related to clicked element
});
Save the relevant Id's in an array - ["Item0Div", "Item1Div", ...]
Create a generic setItemDivVisible method:
function setItemDivVisible(visible, id) {
var ele = document.getElementById(id);
ele.style.display = visible ? "block" : "none";
}
And set your click handler method to be:
function(e) {
var arrayLength = myStringArray.length;
for (var i = 0; i < idsArray.length; i++) {
setItemDivVisible(idsArray[i] === this.id, idsArray[i]);
}
}
I think this will do the trick
I'm new to working with JS/jQuery, I've been currently trying to figure out how to make this work, by trying many different ways that I've found here and on different sites, and am unable to get this working.
I have a website that has tabs, that changes a div's content when the click on the buttons in the menu. This all works fine, but I want to be able to link to each separate "page" using hash tags example.com/#tab-1
HTML:
<div class="tabWrapper">
<div class="tabContent">
<div class="label">TAB 1</div>
<?php include 'tab1.php'; ?>
</div>
<div class="tabContent">
<div class="label">TAB 2</div>
<?php include 'tab2.php'; ?>
</div>
tabWrapper looks like this after being generated
<div class="tabWrapper">
<ul class="tabs">
<li class="tab-1">TAB 1</li>
<li class="tab-2">TAB 2</li>
</ul>
JS :
// Generate tab navigation
if ($('div.tabWrapper').length != 0)
{
$('div.tabWrapper').each(function()
{
// Prepare tab output
var printTabs = '<ul class="tabs">';
var tabContent = $(this).find('.tabContent');
var tabCount = tabContent.length;
$(tabContent).each(function(key)
{
// Hide tab if it is not the first
if (key != 0)
{
$(this).hide();
}
// Get label for tab
var label = $(this).find('.label').text();
// Use a number if no label was given
if (!label)
{
label = 'Tab ' + (key + 1);
}
// Add id to tab content
$(this).addClass('tab-' + key);
printTabs+= '<li class="tab-' + key + '">' + label + '</li>';
});
// Add tabs
$(this).prepend(printTabs + '</ul>');
$(this).find('li:first').addClass('active');
});
}
// Handle click on tabs
$('.tabWrapper').delegate('ul.tabs li', 'click', function()
{
// Deny click on active element
if ($(this).is('.active'))
{
return false;
}
// Get tab id
var id = $(this).attr('class').split('-');
id = id[1];
// Display and animate new tab content
var parent = $(this).parent().parent();
parent.find('ul.tabs li').removeClass('active');
$(this).addClass('active');
parent.find('.tabContent').hide()
parent.find('.tab-' + id).animate({ opacity: 'show' }, animationSpeed);
});
Here is what I was trying to add, which I don't think is correct
function hash() {
if(window.location.hash){
var hash = window.location.hash.substring(1);
$("." + hash).click();
}
}
which I added in the js file just above
$('.tabWrapper').delegate('ul.tabs li', 'click', function()
I'm not sure how far I'm off with that code, as it doesn't seem to work at all. I just want it to see if there is a hash tag in the url, and if there is then run the click function to change the content.
I hope I explained what I was looking for clear enough. I'd very much appreciate any help with this.
Thank you.
UPDATE:
I updated the code with setInterval as per chiliNUT's suggestion, however it still doesn't appear to be working.
setInterval(hash,1000);
function hash() {
if(window.location.hash){
var hash = window.location.hash.substring(1);
$("." + hash).click();
}
}
UPDATE 2:
Still unable to get this working, anyone able to help?
Thanks.
My tip is using anchor tags as well.
Link
That will open example.com#tab1
The control on page load:
$( document ).ready(function() {
if(window.location.hash == "#tab1"){
$("#someId").click();
}
});
Why not just use anchor tags?
Button to open tab 1
I want to implement readmore/less feature. i.e I will be having html content and I am going to show first few characters from that content and there will be a read more link in front of it. I am currently using this code :
var txtToHide= input.substring(length);
var textToShow= input.substring(0, length);
var html = textToShow+ '<span class="readmore"> … </span>'
+ ('<span class="readmore">' + txtToHide+ '</span>');
html = html + '<a id="read-more" title="More" href="#">More</a>';
Above input is the input string and length is the length of string to be displayed initially.
There is an issue with this code, suppose if I want to strip 20 characters from this string:
"Hello <a href='#'>test</a> output", the html tags are coming between and it will mess up the page if strip it partially. What I want here is that if html tags are falling between the range it should cover the full tag i.e I need the output here to be "Hello <a href='#'>test</a>" . How can I do this
Why not just hide the hidden part of the content instead of adding it later? I usually just use a display: none for hidden content and have it set to display: block when the read more is clicked..
Edit:
I'm sorry I didn't read the question good enough.
This should work though:
<div id="test">
This links to google
<strong>and</strong> some random text to make it a little bit longer!
</div>
<script type="text/javascript">
$(document).ready(function() {
var max_length = 21;
var text_to_display = "";
var index = 0;
var full_contents = $("#test").contents();
// loop through contents, stop after maxlength is reached
$("#test").contents().each(function(i) {
if ($(this).text().length + text_to_display.length < max_length) {
text_to_display += $(this).text();
index++;
} else {
return false;
}
});
// second loop removes unwanted content
$("#test").contents().each(function(i) {
if (i > index) {
$(this).remove();
}
return true;
});
// add link to show the full text
$('read more...').click(
function(){
$("#test").html($(full_contents));
$(this).hide();
}).insertAfter($("#test"));
});
</script>
This can be accomplished quite easilly using jQuery
<div id="test">This is a link to google</div>
<script type="text/javascript">
$(document).ready(function() {
alert($("#test").text());
});
</script>
Good luck!
You stated that the html tags would become an issue, so why not remove in the string conversion and replace with plain text, then on the Show More click, Toggle plain + Html
$(document).ready(function(){
var Contents = $('#post p'); //Object
var Plain = Contents.text(); //truncate this
//Hide the texts to Contents
Contents.hide();
var PlainContainer = $("<div>").addClass("Plain_Container").val(Plain)
//Add PlainContainer div after
Contents.append(PlainContainer);
var $('.show_hide').click(function(){
$(Plain_Container).remove(); //Delete it
Contents.Show(); //Show the orginal
$(this).remove(); //Remove the link
return false; //e.PreventDefault() :)
});
});
This way using the text() function will convert html tags to there values and remove the tag itself, all you have to do is toggle them :)
Note: The code above is not guaranteed to work and is provided as example only.
I was taking a look at http://www.zenfolio.com/zf/features.aspx and I can't figure out how they are doing the accordion style expand and collapse when you click on the orange links. I have been using the Web Developer Toolbar add-on for firefox, but I have not been able to find anything in the source of the page like JavaScript that would be doing the following. If anyone knows how they are doing it, that would be very helpful.
This is actually unrelated, but if all you answers are good, who do I give the answer too?
They're setting the .display CSS property on an internal DIV from 'none' to '', which renders it.
It's a bit tricky, as the JS seems to be in here that's doing it:
http://www.zenfolio.com/zf/script/en-US/mozilla5/windows/5AN2EHZJSZSGS/sitehome.js
But that's basically how everyone does this. It's in there, somewhere.
EDIT: Here it is, it looks like:
//... (bunch of junk)
zf_Features.prototype._entry_onclick = function(e, index)
{
var cellNode = this.dom().getElementsByTagName("H3")[index].parentNode;
while (cellNode.tagName != "TD") cellNode = cellNode.parentNode;
if (this._current != null) this.dom(this._current).className = "desc";
if ("i" + index != this._current)
{
cellNode.className = "desc open";
cellNode.id = this.id + "-i" + index;
this._current = "i" + index;
}
else this._current = null;
zf_frame.recalcLayout();
return false;
};
Basically, what they're doing is a really roundabout and confusing way of making the div inside of TD's with a class "desc" change to the class "desc open", which reveals its contents. So it's a really obtuse roundabout way to do the same thing everyone does (that is, handling onclick to change the display property of a hidden div to non-hidden).
EDIT 2:
lol, while I was trying to format it, others found it too. =) You're faster than I ;)
Using jQuery, this effect can be built very easily:
$('.titleToggle').click(function() {
$(this).next().toggle();
});
If you execute this code on loading the page then it will work with any markup that looks like the following:
<span class="titleToggle">Show me</span>
<div style="display:none">This is hidden</div>
Notice that this code will work for any number of elements, so even for a whole table/list full of those items, the JavaScript code does not have to be repeated or adapted in any way. The tag names (here span and div) don't matter either. Use what best suits you.
It is being done with JavaScript.
When you click a link, the parent td's class changes from 'desc' to 'desc open'. Basically, the expanded text is always there but hidden (display: none;). When it gets the css class of 'open' the text is no longer being hidden (display: block;).
If you look in the sitehome.js and sitehome.css file you can get an idea about how they are doing that.
btw I used FireBug to get that info. Even though there is some feature duplication with Web Developer Toolbar it's worth the install.
They're using javascript. You can do it too:
<div id="feature">
Feature Name
<div id="desc" style=="display:none;">
description here...
</div>
</div>
<script type="text/javascript">
function toggle()
{
var el=document.getElementById('desc');
if (el.style.display=='none')
el.style.display='block'; //show if currently hidden
else
el.style.display='none'; //Hide if currently displayed
}
</script>
The function above can be written using Jquery for smooth fade in/fade out animations when showing/expanding the descriptions. It has also got a SlideUp and Slidedown effect.
There is a lot of obfuscated/minified JS in their master JS include. It looks like they are scraping the DOM looking for H3's and checking for table cells with class desc and then processing the A tags. ( or some other order, possibly ) and then adding the onclick handlers dynamically.
if (this._current != null) this.dom(this._current).className
= "desc"; if ("i" + index != this._current) { cellNode.className = "desc open"; cellNode.id = this.id
+ "-i" + index; this._current = "i" + index; }
http://www.zenfolio.com/zf/script/en-US/safari3/windows/5AN2EHZJSZSGS/sitehome.js
The script is here.
The relevant section seems to be (re-layed out):
// This script seems over-complicated... I wouldn't recommend it!
zf_Features.prototype._init = function()
{
// Get a list of the H3 elements
var nodeList = this.dom().getElementsByTagName("H3");
// For each one...
for (var i = 0; i < nodeList.length; i++)
{
// ... set the onclick to be the function below
var onclick = this.eventHandler(this._entry_onclick, i);
// Get the first <a> within the H3 and do the same
var node = nodeList[i].getElementsByTagName("A")[0];
node.href = "#";
node.onclick = onclick;
// And again for the first <span>
node = nodeList[i].getElementsByTagName("SPAN")[0];
node.onclick = onclick;
}
};
zf_Features.prototype._entry_onclick = function(e, index)
{
// Get the parent node of the cell that was clicked on
var cellNode = this.dom().getElementsByTagName("H3")[index].parentNode;
// Keep going up the DOM tree until we find a <td>
while (cellNode.tagName != "TD")
cellNode = cellNode.parentNode;
// Collapse the currently open section if there is one
if (this._current != null)
this.dom(this._current).className = "desc";
if ("i" + index != this._current)
{
// Open the section we clicked on by changing its class
cellNode.className = "desc open";
cellNode.id = this.id + "-i" + index;
// Record this as the current one so we can close it later
this._current = "i" + index;
}
else
this._current = null;
// ???
zf_frame.recalcLayout();
return false;
};
Edit: added some comments
Unfortunately their code is in-lined and hard to read (http://www.zenfolio.com/zf/script/en-US/mozilla5/windows/5AN2EHZJSZSGS/sitehome.js), but this looks quite simple to implement... something along these lines (using prototypejs):
<script>
var showHide = {
cachedExpandable: null
,init: function() {
var containers = $$(".container");
for(var i=0, clickable; i<containers.length; i++) {
clickable = containers[i].getElementsByClassName("clickable")[0];
Event.observe(clickable, "click", function(e) {
Event.stop(e);
showHide.doIt(containers[i]);
});
}
}
,doIt: function(container) {
if(this.cachedExpandable) this.cachedExpandable.hide();
var expandable = container.getElementsByClassName("expandable")[0];
if(expandable.style.display == "none") {
expandable.show();
} else {
expandable.hide();
}
this.cachedExpandable = expandable;
}
};
window.onload = function() {
showHide.init();
};
</script>
<div class="container">
<div class="clickable">
Storage Space
</div>
<div class="expandable" style="display: none;">
Description for storage space
</div>
</div>
<div class="container">
<div class="clickable">
Galleries
</div>
<div class="expandable" style="display: none;">
Description for galleries
</div>
</div>
Its also caching the earlier expandable element, so it hides it when you click on a new one.