Dynamically created table supposed to break if too long - javascript

I have a simple Jquery code to call a bunch of AJAX ping methods to find out if the system modules are up. This is generating a table row-by-row on every AJAX call result. The table looks pretty simple.
Now my problem is that the number of callable methods is growing and it might end up in a lot of scrolling, so I thought i set:
body {
max-height: 500px;
}
but the table won't break, and I still end up in scrolling a lot. Any Idea to solve this?
I replaced the method calls with a random OK/ERROR so you can run it in JSFiddle here.
// instead of AJAX call result just append random result
for (i = 0; i < 50; i++) {
$( "#resultTable" ).append( '<tr><td> TestWS </td>' +
(Math.random()<.5 ?
'<td class="ok"> OK </td></tr>' :
'<td class="error"> ERROR </td></tr>'
)
);
}
This dummy JQuery code is not important, only an example to show the problem, what I am looking for is to make this table break if it's too long.
Any suggestions are welcome. Thanks!

For the easiest way would be is to use a scrollable vertical table. So, you'll have a scroll bar and you can scroll through the table data.
To create a scrollable vertical table. You'll need set the display and overflow property.
table {
display: block;
height: 200px;
overflow-y: scroll;
}
For your convenience, I modified your Fiddle so that you can have a look.

So far one of the best options to use seems to be this:
Putting the table in a container and setting:
#container {
column-count:3;
-moz-column-count:3;
-webkit-column-count:3;
}
So it shows the table in multiple columns without much (or no) scrolling needed.
Fiddle
Any backdraws or major browser compatibility issues?

Here is another approach. Possibly flexbox is a better solution, but fwiw:
// instead of AJAX call result just append random result
var pageHeight = 200, cnt=1, oldcnt=0;
var endStr = '';
for (i = 0; i < 50; i++) {
$( "#div"+cnt ).find('table.resultTable').append( '\
<tr><td> TestWS </td>' +
(Math.random()<.5 ?
'<td class="ok"> OK </td></tr>' :
'<td class="error"> ERROR </td></tr>'
)
);
if ( $( "#div"+cnt ).find('table.resultTable').height() > pageHeight){
oldcnt = cnt;
cnt++;
$( "#container").append('<div id="div'+cnt+'"><table class="resultTable"><tr><th>Service</th><th>Result</th></tr></table>');
}
}
body {width:100%;max-height: 200px;}
th, td{padding:2px;border:1px solid;xwidth:50px;}
.resultTable th{background-color:#CCCCCC;font-weight:bold;}
.resultTable td.ok{background-color:#E1FFD8;font-weight:bold;}
.resultTable td.error{background-color:#FFB5B5;font-weight:bold;}
#container{width:100%;overflow:auto;border:1px solid orange;}
[id^=div]{max-width:120px;width:120px;float:left;margin-right:7px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div id="container">
<div id="div1">
<table class='resultTable'>
<tr><th>Service</th><th>Result</th></tr>
</table>
</div>
</div>
jsFiddle Demo to play with

Here's an alternative. You can use the tools from jQuery mobile to create a nice feature: collapsible headers. That way your users can isolate specific test results in logically arranged groupings.
Click / press the header to toggle visibility of the content beneath.
You can organize things just the way you need them.
<script src="http://demos.jquerymobile.com/1.4.5/js/jquery.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js"></script>
<link rel="stylesheet" href="http://demos.jquerymobile.com/1.4.0/css/themes/default/jquery.mobile-1.4.0.min.css" />
<style type="text/css">
li div { padding: 2px; border: 1px solid; float: left; width: 150px }
.ui-collapsible-content .ui-filterable{ display: none; }
li { background-color: #CCCCCC; font-weight: bold; }
li div.ok { background-color: #E1FFD8; font-weight: bold; }
li div.error { background-color: #FFB5B5; font-weight: bold; }
.ui-li-static.ui-collapsible > .ui-collapsible-heading { margin: 0; }
.ui-li-static.ui-collapsible { padding: 0; }
.ui-li-static.ui-collapsible > .ui-collapsible-heading > .ui-btn { border-top-width: 0; }
.ui-li-static.ui-collapsible > .ui-collapsible-heading.ui-collapsible-heading-collapsed > .ui-btn, .ui-li-static.ui-collapsible > .ui-collapsible-content { border-bottom-width: 0; }
</style>
<div data-role="collapsible" data-theme="b" data-content-theme- "b">
<h2>First Category</h2>
<ul data-role="listview" data-filter="true">
<li><div class="title">TestWS1</div>
<div class="ok"> OK </div>
</li>
<li><div class="title">TestWS2</div>
<div class="error"> ERROR </div>
</li>
<li><div class="title">TestWS3</div>
<div class="ok"> OK </div>
</li>
<li><div class="title">TestWS4</div>
<div class="error"> ERROR </div>
</li>
</ul>
</div>
<div data-role="collapsible" data-theme="b" data-content-theme- "b">
<h2>Second Category</h2>
<ul data-role="listview" data-filter="true">
<li><div class="title">TestWS10</div>
<div class="ok"> OK </div>
</li>
<li><div class="title">TestWS11</div>
<div class="error"> ERROR </div>
</li>
<li><div class="title">TestWS12</div>
<div class="ok"> OK </div>
</li>
<li><div class="title">TestWS13</div>
<div class="error"> ERROR </div>
</li>
</ul>
</div>

Related

Trying to get jQuery to change a different img src when clicked

I've got 2 seperate divs that change background img src when clicked which works fine, but I would like it to change the other image its present with. E.g. div 1 is pressed and becomes "open", if div2 is "open" it then becomes closed. My jQuery is rather limited and have it functioning where it can change the image, but need to figure out how to apply the "closed" class to images that haven't just been clicked. Ideally it would use the attr() so I can add more later.
jQuery
$(".box").on("click", function() {
// need to make this function select the other div.
if ($(this).hasClass("closed")) {
$(this).addClass("open").removeClass("closed");
} else {
$(this).addClass("closed").removeClass("open");
}
var id = $(this).attr("data-id");
$(this).toggleClass("open");
$(".hideDivs").hide();
$("#" + id).show();
});
.container {
width: 640px;
height: 450px;
background-color: #eee;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
}
.text-primary {
font-size: 14px;
text-align: center;
margin-bottom: 5px;
}
.box {
cursor: pointer;
width: 90px;
height: 180px;
display:block;
margin:auto;
background-image: url("http://res.cloudinary.com/dez1tdup3/image/upload/v1499052120/closed_vo1pn2.png");
}
.open {
background-image: url("http://res.cloudinary.com/dez1tdup3/image/upload/v1499052120/open_ihcmuz.png");
}
.closed {
background-image: url("http://res.cloudinary.com/dez1tdup3/image/upload/v1499052120/closed_vo1pn2.png");
}
.hideDivs {
display: none;
}
.panel-body {
padding: 10px;
margin-top: 5px;
}
.title {
font-weight: bold;
font-size: 14px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-xs-6">
<div class="box" data-id="divId1">
</div>
</div>
<div class="col-xs-6">
<div class="box" data-id="divId2">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="panel panel-default hideDivs" id="divId1">
<div class="panel-body">
<span class="title">Practices for safe packaging of cooked foods</span>
<ul>
<li>Label and date all food.</li>
<li>Package high-risk food in small batches for refrigeration and return to refrigerated storage as soon as possible (within 20 minutes).</li>
<li>Store packaging products in a clean environment and protect from contamination.</li>
</ul>
</div>
</div>
<div class="panel panel-default hideDivs" id="divId2">
<div class="panel-body">
<span class="title">Practices for safe freezing of cooked foods</span>
<ul>
<li>When packaging food for freezing, cover or wrap, label and date (production and freezing date) all foods.</li>
<li>Freeze food in small quantities to ensure food is frozen quickly.</li>
<li>Do not overload freezer units and ensure air can circulate.</li>
<li>Do not freeze foods that have been cooked then refrigerated and reheated.</li>
</ul>
</div>
</div>
</div>
</div>
</div>
Please check the jsfiddle and let me know if you are looking something like this.
https://jsfiddle.net/314sybno/2/
$(".box").on("click", function() {
var id = $(this).attr("data-id");
if( id === 'divId1') {
$('div[data-id="divId2"]').addClass('closed').removeClass('open');
} else {
$('div[data-id="divId1"]').addClass('closed').removeClass('open');
}
// need to make this function select the other div.
if ($(this).hasClass("closed")) {
$(this).addClass("open").removeClass("closed");
} else {
$(this).addClass("closed").removeClass("open");
}
$(".hideDivs").hide();
$("#" + id).show();
});
This might be a better approach:
$(".box").on("click", function() {
// Hide all detail divs
$(".hideDivs").hide();
if ($(this).is(".closed")) {
// Close other open boxes
$(".box.open").removeClass("open").addClass("closed");
// Open this box and show the corresponding details div
$(this).removeClass("closed").addClass("open");
var id = $(this).attr("data-id");
$("#" + id).show();
} else {
// Close this box
$(this).removeClass("open").addClass("closed");
}
});
Also, I would recommend changing your HTML to have your 'box' elements also have a 'closed' class, so you do not repeat/need the CSS background attribute on the 'box' class.
See it working on this fiddle

On Scroll change color of menu HTML

First of all I'm as newbie in this area. I tried to search about this but nothing fits on what I want.
So I have this html:
<aside>
<div align="center">
<img src="images/teste.jpg" style="width:200px;height:200px;">
</div>
...
<div id="disciplinas">
<h3>Disciplinas:</h3>
<li>x</span></li>
<li>y</span></li>
<li>z</span></li>
<li>w</span></li>
<br/>
</div>
</aside>
<div id="main">
<section id="x">
<div>
<img src="images/teste.jpg">
</div>
</section>
<section id="y">
<div>
<img src="images/teste.jpg">
</div>
</section>
...
I tried this code but didn't work:
<script type="text/javascript">
$(document).ready(function(){
var scroll_pos = 0;
$(document).scroll(function() {
scroll_pos = $(this).scrollTop();
if(scroll_pos > 210) {
$("li").css('background-color', 'blue');
} else {
$("li").css('background-color', 'red');
}
});
});
</script>
I would like to know how can i change the color of the <li> on scroll, when they get to the correct section (or maybe i need to use a div instead).
Thanks
If it helps, the css of div disciplinas and li:
#disciplinas {
border: 1px solid;
margin-top: 5%;
margin-bottom: 5%;
text-align: center;
box-shadow: 10px 10px 5px #DCDCDC;
background-color: white;
}
li {
text-align: center;
list-style-type: none;
}
Try using this code,
$(window).scroll(function () {
var scroll_pos= $(window).scrollTop();
if(scroll_pos > 210) {
$("li").css('background-color', 'blue');
} else {
$("li").css('background-color', 'red');
}
});
hope it helps.
Add jquery library js file
Remove unnecessary html tag
<aside>
<div align="center">
<img src="images/teste.jpg" style="width:200px;height:200px;">
</div>
...
<div id="disciplinas">
<h3>Disciplinas:</h3>
<li>x</li>
<li>y</li>
<li>z</li>
<li>w</li>
<br/>
</div>
</aside>
<div id="main">
<section id="x">
<div>
<img src="images/teste.jpg">
</div>
</section>
<section id="y">
<div>
<img src="images/teste.jpg">
</div>
</section>
https://jsfiddle.net/rq6rgrcj/
Check this codepen:
http://codepen.io/yuki-san/pen/eJqLNO
You can see the idea and how the sections are tied to the scrolling event.
Now use that and just change the li background color instead of underline
Create a css class lets say - scrollColor and add it using jQuery
.addClass(".scrollColor")
when the window scrolled to the right place and remove it when scrolled away

How to Stick elements on page scroll

I have a one page, scrolling site with 5 main sections that have title bars that span across the top of each respective section. I want each title bar to stick at the top (well, relative top-underneath the top sticky header) as you scroll down the section. I can get one to stick, but I am having trouble making it so that one sticks and then it goes away once the next section's title bar gets to the sticky point.
I can't figure out another way to bind the HTML or CSS with the jQuery if else statement to make this work. I was thinking I could try to make it work within each sections' id but I don't think there's like a "withinId" jQuery selector.
I'm posting the latest jQuery I attempted (with just 2 out of the 5 variables I will need to make work here). I know it's wrong but I'm seriously stuck. Any ideas here? Thanks a million.
(abbreviated) HTML:
<div id="welcome">
<div class="title-bar">
<p>WELCOME</p>
</div>
</div>
<div id="global">
<div class="title-bar">
<p>GLOBAL ENGAGEMENT</p>
</div>
</div>
<div id="community">
<div class="title-bar">
<p>COMMUNITY</p>
</div>
</div>
<div id="resources">
<div class="title-bar">
<p>RESOURCES</p>
</div>
</div>
<div id="horizon">
<div class="title-bar">
<p>ON THE HORIZON</p>
</div>
</div>
CSS:
.title-bar {
padding: 5px;
position: relative;
}
.title-bar.sticky {
position: fixed;
top: 111px;
width: 100%;
z-index: 1040;
}
jQuery:
$(document).ready(function() {
var welcomeTitle = $('#welcome .title-bar');
var globalTitle = $('#global .title-bar');
var communityTitle = $('#community .title-bar');
var resourcesTitle = $('#resources .title-bar');
var horizonTitle = $('#horizon .title-bar');
var stickyOffset = $('#header').offset().top;
if ($w.scrollTop() > stickyOffset + 225) {
welcomeTitle.addClass('sticky');
globalTitle.addClass('sticky');
} else {
welcomeTitle.removeClass('sticky');
globalTitle.addClass('sticky');
}
if (welcomeTitle.hasClass('sticky') && globalTitle.hasClass('sticky')) {
welcomeTitle.removeClass('sticky');
} else {
//
}
});
jsBin demo
Give your "pages" a class="page" and listen for their positions using JS's Element.getBoundingClientRect on: DOM Ready, window Load, window Scroll
$(function() { // DOM ready
var $win = $(window),
$page = $(".page").each(function(){
// Memorize their titles elements (performance boost)
this._bar = $(this).find(".title-bar");
});
function fixpos() {
$page.each(function(){
var br = this.getBoundingClientRect();
$(this._bar).toggleClass("sticky", br.top<0 && br.bottom>0);
});
}
fixpos(); // on DOM ready
$win.on("load scroll", fixpos); // and load + scroll
});
*{box-sizing: border-box;}
html, body{height:100%;}
body{margin:0;font:16px/1 sans-serif; color:#777;}
.page{
position:relative;
min-height:100vh;
}
.title-bar {
position: absolute;
top:0;
width: 100%;
background:#fff;
box-shadow: 0 3px 4px rgba(0,0,0,0.3);
}
.title-bar.sticky {
position: fixed;
}
#welcome {background:#5fc;}
#global {background:#f5c;}
#community{background:#cf5;}
#resources{background:#fc5;}
#horizon {background:#5cf;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="welcome" class="page">
<div class="title-bar">
<h2>WELCOME</h2>
</div>
</div>
<div id="global" class="page">
<div class="title-bar">
<h2>GLOBAL ENGAGEMENT</h2>
</div>
</div>
<div id="community" class="page">
<div class="title-bar">
<h2>COMMUNITY</h2>
</div>
</div>
<div id="resources" class="page">
<div class="title-bar">
<h2>RESOURCES</h2>
</div>
</div>
<div id="horizon" class="page">
<div class="title-bar">
<h2>ON THE HORIZON</h2>
</div>
</div>
Design-wise > add a padding-top to the first container element (inside your .page) to prevent content going underneath the title element (since it toggles from absolute/fixed positions).
Have a look at the Waypoints plugin.
You can probably make it a little easier on yourself by assigning each section a class and then add and remove the class from each section with jquery each function.
Try something like the following:
$(window).on( "scroll", function() {
$( ".section" ).each(function() {
if ( $(window).scrollTop() >= $(this).offset().top - 50 ) {
$( this ).addClass("sticky");
}else{
$( this ).removeClass("sticky");
}
});
});
Then your css
.section{
height: 200px;
background: #333;
border:1px solid #222;
position:relative;
}
.section .title-bar{
position:absolute;
top:0;
left:0;
width:100%;
height:50px;
}
.section.sticky .title-bar {
position:fixed;
}
And html
<div class="section">
<div class="title-bar"></div>
</div>
<div class="section">
<div class="title-bar"></div>
</div>
<div class="section">
<div class="title-bar"></div>
</div>

Simplify this javascript for Show one, Hide Rest

I am using a script for a gallery in which clicking on an element in the navigation shows only one div, but hides the others.
Currently my script is very specific, as I need to add a new function for every possible instance. See below... You can imagine this grows out of control easily the more images are added.
Can someone help me make this code more generic and elegant? I'm not very experienced with Javascript/JQuery but this is getting a bit embarrassing lol
So in case it's not clear from the code: the #li1, #li2, #li3 etc are the navigational thumbnails which are always visible. The #img1, #img2, #img3 etc. are the variable displayed divs. When one is visible, the rest should be hidden.
Additional questions:
for every #img1 displayed, I'd like to also show a title in a separate div, let's say #title1, #title2, etc. How do I do this? So eg clicking #li1 would show #img1 and #title1 but hide all other #img.. and #title..
all #'s contain images. I've noticed that when one of the images is broken, the whole script stops working properly (all #img.. divs show at once). Why is that?
this script doesn't actually hide all the images until everything is loaded, which you don't notice when running the HTML locally, but you do when you're waiting for the images to download. I'm suspecting because the $("#li1").load(function() refers to a div that is further down in the document. How can I counter this?
I hope I'm not asking too much, I've tried to understand this myself but I can't figure it out.
$("#li1").load(function() {
$("#img2, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0, #intro").hide();
$("#img1").show();
});
$("#li1").on('click', function() {
$("#img2, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
$("#img1").show();
});
$("#li2").on('click', function() {
$("#img1, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
$("#img2").show();
});
$("#li3").on('click', function() {
$("#img2, #img1, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
$("#img3").show();
});
etc.
I would probably try something like this:
Thumbnails like:
<li class="thumbnail" data-imageId="0">
...thumbnail...
</li>
<li class="thumbnail" data-imageId="1">
...thumbnail...
</li>
<li class="thumbnail" data-imageId="2">
...thumbnail...
</li>
Images like:
<div class="image" data-imageId="0">
...image...
</div>
<div class="image" data-imageId="1" style="display: none;">
...image...
</div>
<div class="image" data-imageId="2" style="display: none;">
...image...
</div>
<!-- The style attribute in these element hides the element by default,
while still allowing jQuery to show them using show(). -->
And then the JS:
$(".thumbnail").click(function() {
// Hides all images.
$(".image").hide();
// Shows appropriate one.
var imageId = $(this).data("imageId"); // Fetches the value of the data-imageId attribute.
$(".image[data-imageId="+imageId+"]").show();
});
I see that your li's have ids of 'li1', 'li2', etc. Assign them all a specific class, like 'liLinks'.
Then, add an event handler for that class like this:
$(".liLinks").click(function(){
var ImageToShow = $(this).prop("id").replace("li", ""); // This gets the number of the li
for (i=0; i<= 10; i++){ //or however many images you have
if (i != ImageToShow)
$("#img" + i).hide();
else
$("#img" + i).show();
}
});
Oh, and you can show and hide any other elements with the same method used above. Just make sure their naming convention is the same, and you should be all set!
So, I have two solutions for you:
First option: Edit the HTML code to fix this logic:
<li class="nav" data-image="0">0</li>
<li class="nav" data-image="1">2</li>
<li class="nav" data-image="2">3</li>
...
...and so on.
Now the JavaScript code will be pretty short and easy, here it is:
function showOne(e) {
var max = 5, // assuming that there are 5 images, from #img0 to #img4
toShow = e.target.dataset.image;
for (var i=0; i < max; i++) {
if (i == toShow) $('#img'+i).hide();
else $('#img'+i).show();
}
}
$('.nav').bind('click', showOne);
If your logic isn't this one then i suggest you to edit the HTML to fix this logic, which is the easiest way to do what you want.
Second option: I am assuming that you use a logic like this:
#li0 shows #img0
#li1 shows #img1
#li2 shows #img2
...
#liN shows the Nth img of the array
Here's the code then:
function showOne() {
var max = 4, // assuming that there are 5 images, from #img0 to #img4
toShow = this.id.substr(2);
$('#img'+toShow).show();
for (var i=0; i < max; i++) {
if (i != toShow) $('#img'+i).hide();
}
}
$('#li0, #li1, #li2, #li3, #li4').bind('click', showOne);
In this snippet I only used 5 images, but you can add more images changing the max value and adding the relative li elements in the $('#li0, #li1, ...) selector.
Just hide all of them with CSS, then override the one you care about to show.
<!doctype html>
<html>
<head>
<style type="text/css">
#showbox img { display: none; width: 300px; }
#showbox.show1 img#img1,
#showbox.show2 img#img2,
#showbox.show3 img#img3,
#showbox.show4 img#img4 { display: block; }
</style>
</head>
<body>
<div id="showbox" class="3">
<img id="img1" src="http://upload.wikimedia.org/wikipedia/commons/6/6f/ChessSet.jpg">
<img id="img2" src="http://upload.wikimedia.org/wikipedia/commons/c/c3/Chess_board_opening_staunton.jpg">
<img id="img3" src="http://www.umbc.edu/studentlife/orgs/chess/images/News%20and%20Events/chess_sets.jpg">
<img id="img4" src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Russisches_festungsschach.PNG/350px-Russisches_festungsschach.PNG">
</div>
<input onchange="document.getElementById('showbox').className = 'show' + this.value;">
</body>
</html>
Your images is not hidden while the images is loading because you didn't use
$(function () {
$("imgs").hide ();
});
This function is excuted when the DOM (HTML) is loaded not the images.
The code will be "HTML":
link1
link2
link3
...
jQuery:
$(function () {
$(".img").hide ();
$(".nav").click (function (e) {
$(".img").show ();
});
});
As you might expect you need to change this code to be more progressive but you now get the idea of making them hidden when the page finish liading not when the images finish downloading. And good luck ;) .
var $img = $('#images img'); /* Cache your selector */
$('#nav li').click(function(){
$img.fadeOut().eq( $(this).index() ).stop().fadeIn();
});
#images{ position:relative; }
#images img{ position:absolute; left:0; }
#images img + img {display:none; } /* hide all but first */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id=nav>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div id=images>
<img src="//placehold.it/50x50/cf5" alt="">
<img src="//placehold.it/50x50/f0f" alt="">
<img src="//placehold.it/50x50/444" alt="">
</div>
Following is an approach:
Add special classes to identify images.
Use classes to show/hide image like: .showing{display:block;}
Use data attribute to store title like: data-title="title"
Add class to identify li and mark selected li with another class like active
$(function() {
$("li.switch").click(function() {
var liActive = $("li.active");
var imgActive = liActive.data("image");
$(imgActive).removeClass("showing").addClass("hidden");
$(liActive).removeClass("active");
//currently clicked li
var $this = $(this);
$this.addClass("active");
var d = $this.data("image");
$(d).removeClass("hidden").addClass("showing");
$("#imgTitle").text($(d).data("title"));
});
});
.gallery {
width: 250px;
height: 250px;
padding: 10px;
}
img {
height: 200px;
width: 200px;
margin: auto auto;
}
.hidden {
display: none;
}
.showing {
display: inline-block;
}
ul {
list-style: none none outside;
display: inline;
}
li {
list-style: none none outside;
display: inline-block;
padding: 3px 6px;
border: 1px solid grey;
color: #0f0;
cursor: pointer;
}
li.active {
border: 2px solid red;
background-color: #c0c0c0;
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="gallery">
<img src='https://c2.staticflickr.com/4/3862/15320672416_65b28179b4_c.jpg' class='gimage showing' id='img1' data-title="This is image 1" />
<img src='https://c2.staticflickr.com/4/3893/15156335390_16e16aa1c9_c.jpg' class='gimage hidden' id='img2' data-title="This is image 2" />
<img src='https://c1.staticflickr.com/3/2942/15341799225_09d0f05098_c.jpg' class='gimage hidden' id='img3' data-title="This is image 3" />
<img src='https://c2.staticflickr.com/4/3907/15339877992_695dd1daae_c.jpg' class='gimage hidden' id='img4' data-title="This is image 4" />
<img src='https://farm3.staticflickr.com/2942/15333547162_325fefd6d1.jpg' class='gimage hidden' id='img5' data-title="This is image 5" />
</div>
<div id="imgTitle"></div>
<ul>
<li class="switch active" id="li1" data-image="#img1">1</li>
<li class="switch" id="li1" data-image="#img2">2</li>
<li class="switch" id="li1" data-image="#img3">3</li>
<li class="switch" id="li1" data-image="#img4">4</li>
<li class="switch" id="li1" data-image="#img5">5</li>
</ul>
Try it in this fiddle
Fix from Ricardo van den Broek's code, because
var imageId = $(this).data("imageId");
is seem doesn't work. It's returns "Undefined". So we need to change it to
var imageId = $(this).attr("data-imageId");
Here is all the code,
HTML (Thumbnail section)
<ul>
<li class="thumbnail" data-imageId="0">
Thumbnail 0
</li>
<li class="thumbnail" data-imageId="1">
Thumbnail 1
</li>
<li class="thumbnail" data-imageId="2">
Thumbnail 2
</li>
</ul>
HTML (Image section)
<div class="image" data-imageId="0">
Image 0
</div>
<div class="image" data-imageId="1" style="display: none;">
Image 1
</div>
<div class="image" data-imageId="2" style="display: none;">
Image 2
</div>
JavaScript (jQuery)
$(".thumbnail").click(function() {
$(".image").hide();
// Shows the appropriate one.
var imageId = $(this).attr("data-imageId");
$(".image[data-imageId="+imageId+"]").show();
});

How can I expand and collapse a <div> using javascript?

I have created a list on my site. This list is created by a foreach loop that builds with information from my database. Each item is a container with different sections, so this is not a list like 1, 2, 3... etc. I am listing repeating sections with information. In each section, there is a subsection. The general build is as follows:
<div>
<fieldset class="majorpoints" onclick="majorpointsexpand($(this).find('legend').innerHTML)">
<legend class="majorpointslegend">Expand</legend>
<div style="display:none" >
<ul>
<li></li>
<li></li>
</ul>
</div>
</div>
So, I am trying to call a function with onclick="majorpointsexpand($(this).find('legend').innerHTML)"
The div I am trying to manipulate is style="display:none" by default, and I want to use javascript to make it visible on click.
The "$(this).find('legend').innerHTML" is attempting to pass, in this case, "Expand" as an argument in the function.
Here is the javascript:
function majorpointsexpand(expand)
{
if (expand == "Expand")
{
document.write.$(this).find('div').style = "display:inherit";
document.write.$(this).find('legend').innerHTML = "Collapse";
}
else
{
document.write.$(this).find('div').style = "display:none";
document.write.$(this).find('legend').innerHTML = "Expand";
}
}
I am almost 100% sure my problem is syntax, and I don't have much of a grasp on how javascript works.
I do have jQuery linked to the document with:
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
In the <head></head> section.
Okay, so you've got two options here :
Use jQuery UI's accordion - its nice, easy and fast. See more info here
Or, if you still wanna do this by yourself, you could remove the fieldset (its not semantically right to use it for this anyway) and create a structure by yourself.
Here's how you do that. Create a HTML structure like this :
<div class="container">
<div class="header"><span>Expand</span>
</div>
<div class="content">
<ul>
<li>This is just some random content.</li>
<li>This is just some random content.</li>
<li>This is just some random content.</li>
<li>This is just some random content.</li>
</ul>
</div>
</div>
With this CSS: (This is to hide the .content stuff when the page loads.
.container .content {
display: none;
padding : 5px;
}
Then, using jQuery, write a click event for the header.
$(".header").click(function () {
$header = $(this);
//getting the next element
$content = $header.next();
//open up the content needed - toggle the slide- if visible, slide up, if not slidedown.
$content.slideToggle(500, function () {
//execute this after slideToggle is done
//change text of header based on visibility of content div
$header.text(function () {
//change text based on condition
return $content.is(":visible") ? "Collapse" : "Expand";
});
});
});
Here's a demo : http://jsfiddle.net/hungerpain/eK8X5/7/
how about:
jQuery:
$('.majorpoints').click(function(){
$(this).find('.hider').toggle();
});
HTML
<div>
<fieldset class="majorpoints">
<legend class="majorpointslegend">Expand</legend>
<div class="hider" style="display:none" >
<ul>
<li>cccc</li>
<li></li>
</ul>
</div>
</div>
Fiddle
This way you are binding the click event to the .majorpoints class an you don't have to write it in the HTML each time.
You might want to give a look at this simple Javascript method to be invoked when clicking on a link to make a panel/div expande or collapse.
<script language="javascript">
function toggle(elementId) {
var ele = document.getElementById(elementId);
if(ele.style.display == "block") {
ele.style.display = "none";
}
else {
ele.style.display = "block";
}
}
</script>
You can pass the div ID and it will toggle between display 'none' or 'block'.
Original source on snip2code - How to collapse a div in html
So, first of all, your Javascript isn't even using jQuery. There are a couple ways to do this. For example:
First way, using the jQuery toggle method:
<div class="expandContent">
Click Here to Display More Content
</div>
<div class="showMe" style="display:none">
This content was hidden, but now shows up
</div>
<script>
$('.expandContent').click(function(){
$('.showMe').toggle();
});
</script>
jsFiddle: http://jsfiddle.net/pM3DF/
Another way is simply to use the jQuery show method:
<div class="expandContent">
Click Here to Display More Content
</div>
<div class="showMe" style="display:none">
This content was hidden, but now shows up
</div>
<script>
$('.expandContent').click(function(){
$('.showMe').show();
});
</script>
jsFiddle: http://jsfiddle.net/Q2wfM/
Yet a third way is to use the slideToggle method of jQuery which allows for some effects. Such as $('#showMe').slideToggle('slow'); which will slowly display the hidden div.
Many problems here
I've set up a fiddle that works for you: http://jsfiddle.net/w9kSU/
$('.majorpointslegend').click(function(){
if($(this).text()=='Expand'){
$('#mylist').show();
$(this).text('Colapse');
}else{
$('#mylist').hide();
$(this).text('Expand');
}
});
try jquery,
<div>
<a href="#" class="majorpoints" onclick="majorpointsexpand(" + $('.majorpointslegend').html() + ")"/>
<legend class="majorpointslegend">Expand</legend>
<div id="data" style="display:none" >
<ul>
<li></li>
<li></li>
</ul>
</div>
</div>
function majorpointsexpand(expand)
{
if (expand == "Expand")
{
$('#data').css("display","inherit");
$(".majorpointslegend").html("Collapse");
}
else
{
$('#data').css("display","none");
$(".majorpointslegend").html("Expand");
}
}
Here there is my example of animation a staff list with expand a description.
<html>
<head>
<style>
.staff { margin:10px 0;}
.staff-block{ float: left; width:48%; padding-left: 10px; padding-bottom: 10px;}
.staff-title{ font-family: Verdana, Tahoma, Arial, Serif; background-color: #1162c5; color: white; padding:4px; border: solid 1px #2e3d7a; border-top-left-radius:3px; border-top-right-radius: 6px; font-weight: bold;}
.staff-name { font-family: Myriad Web Pro; font-size: 11pt; line-height:30px; padding: 0 10px;}
.staff-name:hover { background-color: silver !important; cursor: pointer;}
.staff-section { display:inline-block; padding-left: 10px;}
.staff-desc { font-family: Myriad Web Pro; height: 0px; padding: 3px; overflow:hidden; background-color:#def; display: block; border: solid 1px silver;}
.staff-desc p { text-align: justify; margin-top: 5px;}
.staff-desc img { margin: 5px 10px 5px 5px; float:left; height: 185px; }
</style>
</head>
<body>
<!-- START STAFF SECTION -->
<div class="staff">
<div class="staff-block">
<div class="staff-title">Staff</div>
<div class="staff-section">
<div class="staff-name">Maria Beavis</div>
<div class="staff-desc">
<p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Maria earned a Bachelor of Commerce degree from McGill University in 2006 with concentrations in Finance and International Business. She has completed her wealth Management Essentials course with the Canadian Securities Institute and has worked in the industry since 2007.</p>
</div>
<div class="staff-name">Diana Smitt</div>
<div class="staff-desc">
<p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Diana joined the Diana Smitt Group to help contribute to its ongoing commitment to provide superior investement advice and exceptional service. She has a Bachelor of Commerce degree from the John Molson School of Business with a major in Finance and has been continuing her education by completing courses.</p>
</div>
<div class="staff-name">Mike Ford</div>
<div class="staff-desc">
<p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Mike: A graduate of École des hautes études commerciales (HEC Montreal), Guillaume holds the Chartered Investment Management designation (CIM). After having been active in the financial services industry for 4 years at a leading competitor he joined the Mike Ford Group.</p>
</div>
</div>
</div>
<div class="staff-block">
<div class="staff-title">Technical Advisors</div>
<div class="staff-section">
<div class="staff-name">TA Elvira Bett</div>
<div class="staff-desc">
<p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Elvira has completed her wealth Management Essentials course with the Canadian Securities Institute and has worked in the industry since 2007. Laura works directly with Caroline Hild, aiding in revising client portfolios, maintaining investment objectives, and executing client trades.</p>
</div>
<div class="staff-name">TA Sonya Rosman</div>
<div class="staff-desc">
<p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Sonya has a Bachelor of Commerce degree from the John Molson School of Business with a major in Finance and has been continuing her education by completing courses through the Canadian Securities Institute. She recently completed her Wealth Management Essentials course and became an Investment Associate.</p>
</div>
<div class="staff-name">TA Tim Herson</div>
<div class="staff-desc">
<p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Tim joined his father’s group in order to continue advising affluent families in Quebec. He is currently President of the Mike Ford Professionals Association and a member of various other organisations.</p>
</div>
</div>
</div>
</div>
<!-- STOP STAFF SECTION -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script language="javascript"><!--
//<![CDATA[
$('.staff-name').hover(function() {
$(this).toggleClass('hover');
});
var lastItem;
$('.staff-name').click(function(currentItem) {
var currentItem = $(this);
if ($(this).next().height() == 0) {
$(lastItem).css({'font-weight':'normal'});
$(lastItem).next().animate({height: '0px'},400,'swing');
$(this).css({'font-weight':'bold'});
$(this).next().animate({height: '300px',opacity: 1},400,'swing');
} else {
$(this).css({'font-weight':'normal'});
$(this).next().animate({height: '0px',opacity: 1},400,'swing');
}
lastItem = $(this);
});
//]]>
--></script>
</body></html>
Fiddle
Take a look at toggle() jQuery function :
http://api.jquery.com/toggle/
Also, innerHTML jQuery Function is .html().
Since you have jQuery on the page, you can remove that onclick attribute and the majorpointsexpand function. Add the following script to the bottom of you page or, preferably, to an external .js file:
$(function(){
$('.majorpointslegend').click(function(){
$(this).next().toggle().text( $(this).is(':visible')?'Collapse':'Expand' );
});
});
This solutionshould work with your HTML as is but it isn't really a very robust answer. If you change your fieldset layout, it could break it. I'd suggest that you put a class attribute in that hidden div, like class="majorpointsdetail" and use this code instead:
$(function(){
$('.majorpoints').on('click', '.majorpointslegend', function(event){
$(event.currentTarget).find('.majorpointsdetail').toggle();
$(this).text( $(this).is(':visible')?'Collapse':'Expand' );
});
});
Obs: there's no closing </fieldset> tag in your question so I'm assuming the hidden div is inside the fieldset.
If you used the data-role collapsible e.g.
<div id="selector" data-role="collapsible" data-collapsed="true">
html......
</div>
then it will close the the expanded div
$("#selector").collapsible().collapsible("collapse");
Pure javascript allowing only one expanded div at a time. It allows multi-level sub-expanders. The html only need the expanders contents. The javascript will create the expanders headers with the titles form the content data attribute and a svg arrow.
<style>
/* expanders headers divs */
.expanderHead {
color: white;
background-color: #1E9D8B;
border: 2px solid #1E9D8B;
margin-top: 9px;
border-radius: 6px;
padding: 3px;
padding-left: 9px;
cursor: default;
font-family: Verdana;
font-size: 14px;
}
.expanderHead:first-child {
margin-top: 0 !important;
}
.expanderBody:last-child {
margin-bottom: 0 !important;
}
/* expanders svg arrows */
.expanderHead svg > g > path {
fill: none;
stroke: white;
stroke-width: 2;
stroke-miterlimit: 5;
pointer-events: stroke;
}
/* expanders contents divs */
.expanderBody {
border: 2px solid #1E9D8B;
border-top: 0;
background-color: white;
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
padding: 6px;
font-family: Verdana;
font-size: 12px;
}
/* widget window */
.widget {
width: 400px;
background-color: white;
padding: 9px;
border: 2px solid #1E9D8B;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
</style>
<div class="widget">
<div data-title="expander 1" class="expanderBody">
expander 1 content
</div>
<div data-title="expander 2" class="expanderBody">
expander 2 content
</div>
<div data-title="expander 3" class="expanderBody">
<div>
expander 3 content
</div>
<div data-title="expander 3.1" class="expanderBody">
expander 3.1 content
</div>
<div data-title="expander 3.2" class="expanderBody">
expander 3.2 content
</div>
<div data-title="expander 3.3" class="expanderBody">
expander 3.3 content
</div>
</div>
</div>
<script>
document.querySelectorAll(".expanderBody").forEach(item => {
if (item.dataset.title) {
// create expander header
let divHeader = document.createElement("div");
divHeader.className = "expanderHead";
divHeader.innerHTML = "<svg width='14px' height='8px' viewBox='0 0 12 6'><g><path d='M 5 5 L 10 1'/><path d='M 1 1 L 5 5'/></g></svg> <span>" + item.dataset.title + "</span>";
// expander click event
divHeader.addEventListener("click", function () {
// open / close expander
for (let i = 0; i < this.parentNode.children.length; i++) {
let expander = this.parentNode.children[i];
// check if it's expander header
if (expander.className == "expanderHead") {
if (expander == this && expander.nextElementSibling.style.display == "none") {
// open expander body
expander.nextElementSibling.style.display = "";
expander.innerHTML = "<svg width='14px' height='8px' viewBox='0 0 12 6'><g><path d='M 1 5 L 5 1'/><path d='M 5 1 L 10 5'/></g></svg> <span>" + expander.nextElementSibling.dataset.title + "</span>";
expander.style.borderBottomLeftRadius = "0";
expander.style.borderBottomRightRadius = "0";
}
else {
// close expander body
expander.nextElementSibling.style.display = "none";
expander.innerHTML = "<svg width='14px' height='8px' viewBox='0 0 12 6'><g><path d='M 5 5 L 10 1'/><path d='M 1 1 L 5 5'/></g></svg> <span>" + expander.nextElementSibling.dataset.title + "</span>";
expander.style.borderBottomLeftRadius = "6px";
expander.style.borderBottomRightRadius = "6px";
}
}
}
}, true);
item.parentNode.insertBefore(divHeader, item);
item.style.display = "none";
}
});
</script>
Check out Jed Foster's Readmore.js library.
It's usage is as simple as:
$(document).ready(function() {
$('article').readmore({collapsedHeight: 100});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script src="https://fastcdn.org/Readmore.js/2.1.0/readmore.min.js" type="text/javascript"></script>
<article>
<p>From this distant vantage point, the Earth might not seem of any particular interest. But for us, it's different. Consider again that dot. That's here. That's home. That's us. On it everyone you love, everyone you know, everyone you ever heard of, every human being who ever was, lived out their lives. The aggregate of our joy and suffering, thousands of confident religions, ideologies, and economic doctrines, every hunter and forager, every hero and coward, every creator and destroyer of civilization, every king and peasant, every young couple in love, every mother and father, hopeful child, inventor and explorer, every teacher of morals, every corrupt politician, every "superstar," every "supreme leader," every saint and sinner in the history of our species lived there – on a mote of dust suspended in a sunbeam.</p>
<p>Space, the final frontier. These are the voyages of the starship Enterprise. Its five year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before!</p>
<p>Here's how it is: Earth got used up, so we terraformed a whole new galaxy of Earths, some rich and flush with the new technologies, some not so much. Central Planets, them was formed the Alliance, waged war to bring everyone under their rule; a few idiots tried to fight it, among them myself. I'm Malcolm Reynolds, captain of Serenity. Got a good crew: fighters, pilot, mechanic. We even picked up a preacher, and a bona fide companion. There's a doctor, too, took his genius sister out of some Alliance camp, so they're keeping a low profile. You got a job, we can do it, don't much care what it is.</p>
<p>Space, the final frontier. These are the voyages of the starship Enterprise. Its five year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before!</p>
</article>
Here are the available options to configure your widget:
{
speed: 100,
collapsedHeight: 200,
heightMargin: 16,
moreLink: 'Read More',
lessLink: 'Close',
embedCSS: true,
blockCSS: 'display: block; width: 100%;',
startOpen: false,
// callbacks
blockProcessed: function() {},
beforeToggle: function() {},
afterToggle: function() {}
},
Use can use it like:
$('article').readmore({
collapsedHeight: 100,
moreLink: 'Continue reading...',
});
I hope it helps.
Using Pure Javascript
const collapsableBtn = document.querySelectorAll('.collapsable-toggle');
for (let index = 0; index < collapsableBtn.length; index++) {
collapsableBtn[index].addEventListener('click', function(e) {
// e.preventDefault();
e.stopImmediatePropagation();
iterateElement = this;
getCollapsableParent = iterateElement.parentElement;
if(getCollapsableParent.classList.contains('show')) {
getCollapsableParent.classList.remove('show')
iterateElement.innerText = iterateElement.getAttribute('data-onCloseText');
} else {
getCollapsableParent.classList.add('show');
iterateElement.innerText = iterateElement.getAttribute('data-onOpenText');
}
})
}
.collapsable-container #expand {
display:none;
}
.collapsable-container.show #expand {
display:block;
}
<div class="collapsable-container">
Show First Content
<div id="expand">
This is some Content
</div>
</div>
<div class="collapsable-container">
Show Second Content
<div id="expand">
This is some Content
</div>
</div>

Categories

Resources