Dygraphs in collapsed panel not rendering correctly - javascript

I would like to render a dygraphs graph in a collapsed bootstrap panel. Once the user shows the panel the graph should be visible.
My problem is that, when the initially collapsed panel appears, the dygraphs graph inside it is not shown correctly. See this jsfiddle.
My html body looks like this (using bootstrap 3):
<div class="container">
<div class="row">
<div class="col-sm-3">
<label><input type="checkbox" onclick="checkboxChanged(this)"/> Show panel 2</label>
</div>
<div class="col-sm-9">
<div class="panel panel-default">
<div id="panel1" class="panel-body">
<div id="graphdiv1"></div>
</div>
<div id="panel2" class="panel-body collapse">
<div id="graphdiv2"></div>
</div>
</div>
</div>
</div>
</div>
My javascript looks like this:
function checkboxChanged(checkbox){
if(checkbox.checked){
document.getElementById('panel1').classList.add("collapse");
document.getElementById('panel2').classList.remove("collapse");
} else {
document.getElementById('panel1').classList.remove("collapse");
document.getElementById('panel2').classList.add("collapse");
}
}
g1 = new Dygraph(
document.getElementById("graphdiv1"),
"Date,Temperature\n" +
"2008-05-07,75\n" +
"2008-05-08,70\n" +
"2008-05-09,80\n",
{ title: 'Graph on panel 1' }
);
g2 = new Dygraph(
document.getElementById("graphdiv2"),
"Date,Temperature\n" +
"2008-05-07,20\n" +
"2008-05-08,37\n" +
"2008-05-09,17\n",
{ title: 'Graph on panel 2' }
);
What I get:
What I expect:
Note: A curious thing is that, when I resize the output area of the jsfiddle, the graph gets rendered correctly. When I then uncheck the 'show panel 2' checkbox, the first panel graph is rendered incorrectly.
I have tried updating the dygraphs in the end of the checkbox method like this:
g1.updateOptions({});
g2.updateOptions({});
but this doesn't seem to have any effect.
Any help would be greatly appreciated. Thanks!

I found a hack that seems to work. Any suggestions for a cleaner solution would be much appreciated!
My solution is to place a hidden div, containing graphdiv2, at the very end of the document using visibility:hidden; (rather than display:none;) and then, when the checkbox is checked, to have the two graph divs switch places.
So the html body now looks like this:
<div class="container">
<div class="row">
<div class="col-sm-3">
<label><input type="checkbox" onclick="checkboxChanged(this)"/> Show panel 2</label>
</div>
<div class="col-sm-9">
<div class="panel panel-default">
<div id="my_panel" class="panel-body">
<div id="graphdiv1"></div>
</div>
</div>
</div>
</div>
</div>
<div id="hidden_zone" style="visibility:hidden;">
<div id="graphdiv2"></div>
</div>
And the checkbox onclick function now looks like this:
function checkboxChanged(checkbox){
graph1_div = document.getElementById("graphdiv1");
graph2_div = document.getElementById("graphdiv2");
show_parent = document.getElementById('my_panel');
hidden_zone = document.getElementById('hidden_zone');
if(checkbox.checked){
hidden_zone.appendChild(graph1_div);
show_parent.appendChild(graph2_div);
} else {
hidden_zone.appendChild(graph2_div);
show_parent.appendChild(graph1_div);
}
}
Here's the jsfiddel to this solution.
Any suggestions for a cleaner solution?

Related

Multiple Divs horizontally - Slide Open / Close Div

My goal is to have a functionality that when a user clicks on "Label - Filter 1" then the content within div - "Filter_1_Content" appears and the other two divs slide down simultanously. However, when a user clicks on "Label - Filter 2", the content of "Filter 1" should disappear and "Filter 2" should appear while "Filter 3" slides down simoultanously. The same applys to Filter 3 and so on. Please note that at the first load of the page, only the labels should appear.
This is the jQuery code I currently have and it works for Filter 1. However, the Filter 2 and Filter 3 do not move. Any ideas?
<div id="Filter_1">
<label id="Filter1_Label">Filter 1</label>
<div id="Filter_1_Content" class"Filters">
...content
</div>
</div>
<div id="Filter_2">
<label id="Filter2_Label">Filter 2</label>
<div id="Filter_2_Content" class"Filters">
...content
</div>
</div>
<div id="Filter_3">
<label id="Filter2_Label">Filter 3</label>
<div id="Filter_3_Content" class"Filters">
...content
</div>
</div>
function SlideDiv() {
var scopeFilters = $("#Filter1_Label").next(".Filters");
if (scopeFilters.is(":hidden")) {
scopeFilters.slideDown('fast');
} else {
scopeFilters.slideUp('fast');
}
};
To achieve what you need most effectively, you can use common classes and DOM traversal to apply the common logic to a repeated HTML structure. Try this:
var $content = $('.filter-container > div');
$('.filter-container label').click(function() {
var $target = $(this).next('div');
$content.not($target).slideUp('fast');
$target.slideToggle('fast');
});
.filter-container > div {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
<label>Filter 1</label>
<div class="filters">
Content...
</div>
</div>
<div class="filter-container">
<label>Filter 2</label>
<div class="filters">
Content...
</div>
</div>
<div class="filter-container">
<label>Filter 3</label>
<div class="filters">
Content...
</div>
</div>
As you can see from the above, using incremental id attributes is making much more (unnecessary) work for yourself, and would result in much more complex JS code for absolutely no benefit.
you can try below logic where you can find parent div and then it's siblings to find other filter divs.
Slide up other filter divs and slideup clicked filter div.
$(function(){
$("div[id^='Filter_'] label").on("click", function(){
var $parent = $(this).closest("div");
$parent.siblings().find("div.Filters").slideUp("fast");
$(this).next("div.Filters").slideToggle("fast");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div id="Filter_1">
<label>Filter 1</label>
<div id="Filter_1_Content" class="Filters">
...content
</div>
</div>
<div id="Filter_2">
<label>Filter 2</label>
<div id="Filter_2_Content" class="Filters">
...content
</div>
</div>
<div id="Filter_3">
<label>Filter 3</label>
<div id="Filter_3_Content" class="Filters">
...content
</div>
</div>

JQuery - Show multiple divs

I'm having some trouble making a working show div and I just can't get it.
So I have the following:
function GetCaptcha() {
$(".panel-captcha").fadeIn(500);
}
Get
<div class="panel-captcha">
TEXT
</div>
The div has the display:none tag.
It works very well, but I have one problem. I need to have many divs inside the same page ( not the same, it may change from database ). If I have 3 or 4 panels, when I click the button it will show them all instead only the div where I have the link to show.
Anyone can help me? Thanks.
Complete HTML file...
<div class="col-md-4">
<div class="panel panel-blue" data-widget='{"draggable": "false"}'>
<div class="panel-heading">
<h2>TEXT</h2>
<div class="panel-ctrls">
<i class="ti ti-eye"></i>
<!-- BUTTON TO SHOW CAPTCHA -->
</div>
</div>
<div class="panel-body">
<small>Other Text...</small>
</div>
<div class="panel-footer">
<div class="tabular">
<div class="tabular-row tabular-row">
<div class="tabular-cell">
<span class="status-total"><strong>More Text...</strong></span>
</div>
<div class="tabular-cell">
<span class="status-pending">Other Text...</span>
</div>
</div>
</div>
</div>
<div class="panel-captcha">
<!-- HIDDEN DIV -->
<div class="tabular-cell">
HIDDEN TEXT
</div>
</div>
<!-- END HIDDEN DIV -->
</div>
</div>
You can pass the reference of element to click handler, then use .next()
Script
function GetCaptcha(elem) {
$(elem).next(".panel-captcha").fadeIn(500);
}
.panel-captcha {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Get
<div class="panel-captcha">
TEXT
</div>
As you are using jQuery bind event using it.
HTML
Get
<div class="panel-captcha">
TEXT
</div>
Script
$(function() {
$('.captcha').on('click', function () {
$(this).next(".panel-captcha").fadeIn(500);
});
});
EDIT
As per updated HTML use
function GetCaptcha(elem) {
$(elem).closest('.panel').find(".panel-captcha").fadeIn(500);
}

Foundation: using a checkbox to hide/show div

I'm trying to use checkboxes with categories at the top of my page as filters to display the lower content of the page (which gives specific options as buttons under each category). The lowers divs should only be displayed if the checkbox is checked; I set the display as none for the div in the CSS. However, my code doesn't work..
I've tried using different syntax for the JS that I found online, and declaring the js in different places in my HTML, but nothing so far has worked.
HTML
<input type="checkbox" id="supportcheck"> Support
<div class="row" id= "support">
<h5>Support</h5>
<div class="large-6 medium-6 columns">
<div class="callout panel" >
<div role="button" tabindex="0" class="small radius support button">Managed</div>
</div>
</div>
<div class="large-6 medium-6 columns">
<div class="callout panel">
<div role="button" tabindex="0" class="small radius support button">Self-Managed</div>
</div>
</div>
</div>
JavaScript
$('.supportcheck').change(function () {
if ($(this).attr("checked"))
{
$('.support').fadeIn();
return;
}
$('.support').fadeOut();
});
supportcheck is an id not a class. Use
$('#supportcheck').change(function () {
to add the event handler to the input.
try this instead:
$('#supportcheck').change(function () {
if ($(this).is(':checked'))
{
$('#support').fadeIn();
return;
}
$('#support').fadeOut();
});

Unable to use $.after() to close a div tag

This problem is best illustrated by example:
http://jsbin.com/lavonexuse
The desired effect is for clicking "Insert Row" to insert a full-width row after the indicated column (indicated by the class .insertion-point). The problem I'm running into is that instead of closing the current row first, and starting a new one, it just embeds a new row within the main row.
How do I close out the current row after any given column, make a new row, close that one, then resume showing the "data" columns?
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item insertion-point">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
</div>
</div>
<button class="btn btn-primary insert-row">Insert Row</button>
</body>
</html>
CSS:
.item {
border: 1px solid #f00;
}
.pane {
background: #999;
height: 100px;
}
JavaScript:
$('.insert-row').on('click', function() {
code = '</div><!--end row--><div class="row"><div class="col-sm-12 pane"></div></div>';
$('.insertion-point').after(code);
});
EDIT:
The code string above probably should end with <div class="row"> to re-open the row. But I tried that and it still doesn't work.
The problem here is that visually it looks like my solution works. Though in reality, it's creating bad HTML.
Further explanation (I think this is hard to explain). Here is what's happening, and this is NOT what I want:
I need that inserted row to be at the same level as the row it was erroneously inserted into.
Desired HTML after jQuery manipulation
<div class="container">
<div class="row">
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item insertion-point">
Data
</div>
</div>
<div class="row">
<div class="col-sm-12 pane"></div>
</div>
<div class="row">
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
</div>
</div>
Further Ramblings
Maybe, since this is Bootstrap, there's some way I can use the grid system to have the same effect.
The code below should resolve your issue. Check out the code snippet and demo:
$('.insert-row').on('click', function() {
var row = $('<div/>',{class:"row"}),
code = '<!--end row--><div class="row"><div class="col-sm-12 pane">New</div></div>',
rest = $('.insertion-point').nextAll(),
dest = $('.insertion-point').closest('.row');
dest.after( row.append( rest ) ).after( code );
});
<script src="//code.jquery.com/jquery.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<div class="container">
<div class="row">
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item insertion-point">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
<div class="col-sm-4 item">
Data
</div>
</div>
</div>
<button class="btn btn-primary insert-row">Insert Row</button>
i worked out this four you: JsFiddle
$(document).ready(function() {
var firstRow = $('.row');
$('.insert-row').on('click', function() {
var code = $('<div/>', {clas: 'row'}).append($('<div/>', {class: "col-sm-12 pane"})),
row = $('<div/>', {class: 'row'}),
items = $('.insertion-point').nextAll();
row.append(items);
firstRow.after(row);
firstRow.after(code);
});
});
Update:
after seen the nextAll function by jQuery .. this will be much faster:
updated fiddle
I think what you need is appendTo which will append html onto the specified tag. In this case you want to append a div onto your row.
http://api.jquery.com/appendto/
Just get rid of the closing tag in the code variable and your code will work and be well formed
code = '</div><!--end row--><div class="row"><div class="col-sm-12 pane"></div></div>';
should be
code = '<div class="row"><div class="col-sm-12 pane"></div></div>';
Also you need to insert rows after / before other rows like so
$('.insert-row').on('click', function() {
code = '<div class="row"><div class="col-sm-12 pane"></div></div>';
$('.insertion-point').closest(".row").after(code);
});
The above code finds where you want to insert (which I changed to be an id selector since you want to insert after one unique element). However you want to find the closest parent element (or this one) that is a row so that you insert a row after that row. This way you can choose a row or a column to insert after and it will always insert a row after the closest row properly.
Lucky for you browsers are very forgiving when it comes to syntax errors in HTML. They will remove the initial closing tag (which is unnecessary) and use the rest of your HTML. But some browser may behave differently and that is what you have to be careful of.
You need to add a new row after the first by removing the elements after the insertion point and including them in the new row.
You can't treat the DOM like a text editor when inserting html.
$('.insert-row').on('click', function() {
var $insertEL=$('.insertion-point');
var code = '<div class="row"><div class="col-sm-12 pane"></div></div>';
/* create new row and append all siblings after insertion point element*/
var $newRow=$(code).append($insertEL.nextAll());
/* add new row to DOM*/
$insertEL.closest('.row').after($newRow);
});
DEMO
Got it!
Layout solved by using Bootstrap grid, very little jQuery DOM manipulation. I don't know why I didn't think of this earlier. Sheesh. I've been coding for hours non-stop, my brain is fried.
Solution: http://jsbin.com/zopiquzore
This is correct, yes?

Hide parent div if child div is missing

Is it possible at all to hide a parent div if there is a child div missing?
In the example below I would like to hide the parent div of "#live-sessions" if some of the divs are missing such as .views-content and .views-row.
This is what it looks like when the divs are there:
<div id="live-sessions">
<div class="container">
<div class="row">
<div class="col-sm-3">
<h3 class="session-title">Sessions Live Now</h3>
<div class="col-sm-9">
<div class-"view-display-id-live_sessions">
<div class="views-content">
<div class="views-row">
</div>
<div class="views-row">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
This is what it looks like when the divs are missing:
<div id="live-sessions">
<div class="container">
<div class="row">
<div class="col-sm-3">
<h3 class="session-title">Sessions Live Now</h3>
<div class="col-sm-9">
<div class-"view-display-id-live_sessions">
</div>
</div>
</div>
</div>
</div>
I tried using the :empty selector with the parent method, but my child div contains some blank lines so it doesn't think it's empty. Also I would like to hide the parent of the parent of the empty div.
$(".view-display-id-live_sessions:empty").parent().hide();
You have a typo in your html:
class-"view-display-id-live_sessions"
should be
class="view-display-id-live_sessions"
you can try the following jQuery code:
if ($(".view-display-id-live_sessions").html().trim() == '') {
$(".view-display-id-live_sessions").parent().parent().hide();
}
jqVersion demo
Use jQuery has() in a negative if test - http://api.jquery.com/has/
if(!$('#parent').has('.child')){
$('#parent').hide();
}
There isn't a one-line-query for this. Following code would do the trick:
$('#live-sessions .row').each(function(idx, row) {
if ($(row).find('.views-content').length == 0) {
$(row).hide();
}
});
If you want to keep using jQuery, you could instead do:
if ( ! $(".view-display-id-live_sessions").children().length ) { /* your logic */ }
Note that there's a syntax error in your code:
<div class-"view-display-id-live_sessions">
Should be
<div class="view-display-id-live_sessions">
If you understand your question:
First you need to check the number of .views-row divs. If the length is zero hide the parent div.
Ex:
if ($('.views-row').length < 1)
$('#live-sessions').hide();
Good Luck.
You need to trim the blank spaces, correct a typo and test for the text within the div -
class="view-display-id-live_sessions" // note the equals sign after class
The code to do the hiding (EDIT re-read problem again):
var liveSessionsText = $.trim( $('.view-display-id-live_sessions').text() );
if(0 == liveSessionsText.length) {
$('.view-display-id-live_sessions').closest('.row').hide();
}
The div with class="row" is the parent of the parent of view-display-id-live_sessions.

Categories

Resources