How to enable and disable a DIV - javascript

I am using the Prototype JavaScript library and have this div:
new Element('div', {id: 'summaryGraph', style: 'width: 100%; height:90px;'});
Inside that div, I am showing a graph:
summaryGraph: function (data, bounds) {
var p = Flotr.draw(
$('summaryGraph'),
[data],
{
}
);
return p;
}
Now my question is, is it possible to disable and enable the div depending on the conditions?

If you want to "disable" the Graph you have 2 possibilities:
hide the Graph and show a placeholder (image, text) stating that the Graph is not accessible at the moment
overlay the Graph with a semi-transparent DIV, which will prevent any interaction with it

I'm not sure what you mean by 'disabling' the graph. But you may want to take a look at hide() (relevant docs) or show() (relevant docs).
If your graph should not respond to mouse events, add a disable flag and in the mouse event listener, return false if the flag is set.

Related

Javascript Scroll by one pixel on load of a div

I am using a mixture of jQueryTools overlay (lightbox type thing) and a scroll-bar called Perfect Scrollbar. The problem I have is that when the overlay is loaded the scroll-bar doesn't show until you scroll within that box. I need to be able to make it clearer so that everyone knows it is a scroll-able content box. One way this could be possible is to make the content box scroll up one pixel when the overlay is opened. I have found the following code
$(".scroll-content").load(function() {
window.scrollBy(0,-1);
}
which I have been told should work but no matter what I can't get it to scroll at all.. Is there something i'm doing wrong?
Since you have the scroll bar method bind to an element that is initially in a 'hide' status, in fact .BigSuperBlock .block_overlay is hidden by display:none; in Css, the plugin can not properly calculate the height of the overlay container.
So, when you call the function that show-up the 'overlay' container, you have to call the method on the scroll-content class:
$('.scroll-content').perfectScrollbar('update');
You can find the documentation of this in the author's page.
To make it works, you have to call the plugin 'update' method, again, in the jQueryTools modal function, as a callback.
$(".block_overlay").overlay({
onLoad: function(event) {
$('.scroll-content').perfectScrollbar('update');
// here you update the perfectScrollbar plugin
},
onClose: function(event) {
// other custom code
}
});
Try with this:
jQuery("container").animate({ scrollTop: 50 }, 800);
Give that you want to make clear that there is a scrollbar, you can have it on all the time if you change the perfect-scrollbar.css
.ps-container .ps-scrollbar-x-rail {
...
opacity: 0.6;
}
.ps-container .ps-scrollbar-y-rail {
...
opacity: 0.6;
}

Google Chart loads extremely small when included in jQuery-based tabs

I am using Google's line chart almost exactly as the demo - only the data has changed - inside of this jQuery tab plugin with no modification. Maybe 50% of the time, the chart will load at 400x200 even though it has been specified to load at 700x250. The containing div will have the proper width and height, but the chart as rendered by the API will load inside of that at 400x200.
I suspect this is because the tabs aren't being displayed when the API tries to render. Because of that, it tries to render in something it considers null and therefore forces itself into the smallest default resolution.
My thought is that if the display of the chart can be delayed until the appropriate tab is clicked, it would resolve the problem. Sadly, I have no idea how to do that, and my research hasn't been fruitful. The closest I could find is this thread, but I didn't find any real answers there.
I'd appreciate any advice if you have any, and I'd be glad to follow up with more information if necessary.
Rendering charts in a hidden div (which is what the non-selected tabs of a tab UI most likely are) messes with the Visualization API's ability to detect dimensions, so you want to do one of two things: either render all charts before instantiating tabs, or (as you've caught on to) bind event listeners to draw the charts when a tab is first opened. Setting the height and width in the chart's options is insufficient to solve the problem in all browsers.
I scanned over the easytabs documentation, and it looks like you should be able to do something like this:
// draw chart(s) in your default open tab
// track which tabs you've drawn charts in
var chartsDrawn = {
tab1: true,
tab2: false,
tab3: false
// etc
};
$('#tab-container').bind('easytabs:after', function (e) {
if (e.tab == 'tab-2' && !chartsDrawn.tab2) {
// draw chart(s) in tab 2
chartsDrawn.tab2 = true;
}
else if (e.tab == 'tab-3' && !chartsDrawn.tab3) {
// draw chart(s) in tab 3
chartsDrawn.tab3 = true;
}
// etc
});
change chart options to set the width and height as you need
var options = {
title: 'Company Performance'
,width:900
,height:500
};
This is how I solved using angular-bootstrap https://angular-ui.github.io/bootstrap/
<div class="google-chart" google-chart chart="chartObject1" on-ready="displayGoogleCharts()"></div>
<tab heading="Past Week" select="googleChartSizeFix()">
googleChartSizeFix = function() {
$('svg').parent().css({ opacity:"0" });
$(window).resize();
};
displayGoogleCharts = function() {
$('svg').parent().css({ opacity:"1" });
};
Each time a Tab is selected (the function googleChartSizeFix is triggered) the Google Chart is set to transparent (opacity = 0, so it does not disappear by the use of hide(), but keeps its size since its content is transparent) followed by the window resize is triggered, this forces Google Chart to fit the div that contains it, by the use of width 100% and height 100%:
"options": {
"chartArea": {
"width":'100%',
"height":'100%'
}
}
and finally once the Google Chart is ready (after resize) the displayGoogleCharts function is triggered and the opacity of the google chart is reset to 1, so the content is visible once again.
I stumbled across this "feature" of Bootstrap tabs. When cut-and-pasting multiple tabs in my HTML, I accidentally left the <div class=" tab-pane active"> in the "active" state for all the tabs. The result was that the content for all the tabs displayed sequentially in the first tab, but went away as you switched tabs.
My solution to the hidden tabs is to define them as active and then remove the "active" class from the div after I call chart.draw.
<div class="tab-pane active" id="myid" role="tabpanel">
<script type="text/javascript">
// all the chart stuff
chart.draw(data, options);
$('#myid').removeClass('active');
</script>
</div>
I see that jQuery tabs also use the "active" class. Perhaps this trick will work there too.
I solved this by, leaving off the bootstrap class in the element holding the chart, and then after chart had been loaded, then apply the bootstrap class.
For example lets say we want to setup a collapsible with the chart in it:
<a href="#div-id" data-toggle="collapse">
Expand
</a>
<div id="div-id" class="future-collapse">
<div id="some-chart"></div>
</div>
And then in your script:
/**
* Callback function E.G. google.charts.setOnLoadCallback(drawChart);
*/
function drawChart(){
// Drawing the charts
draw_some_chart();
// Applying the collapse class to our elements with the future-collapse class
$('.future-collapse').attr('class', 'collapse');
}
function draw_some_chart(){
// Draw your charts
}

How do I change the default cursor in leaflet maps?

I am trying to modify the default cursor icon when a certain control button is pressed.
Although I was partially successful by using css on the container div, doing this overrides the move cursor state, which is something I do not want. What I mean with this is that the move icon no longer appears while moving through the map (but not when on markers!).
I'd like to know if there is a non-hacky way through the api to achieve special cursor behaviour without redifining everything.
This is what I tried to do, #map is the container div for the leaflet map.
#map[control=pressed] {
cursor: url('..custom.png');
}
Edit 5.18.2017: Raw CSS and Javascript via Leaflet Framework (recommended)
I was looking through the source code for the BoxZoom plugin and noticed their approach using Leaflet's built-in DOM mutators and wanted to promote it here...this is certainly the best practice.
Example jsfiddle
Somewhere in your CSS include a class like this..
.leaflet-container.crosshair-cursor-enabled {
cursor:crosshair;
}
When you want to enable crosshairs, do this in your JS..
// Assumes your Leaflet map variable is 'map'..
L.DomUtil.addClass(map._container,'crosshair-cursor-enabled');
Then, when you want to disable crosshairs, do this in your JS..
L.DomUtil.removeClass(map._container,'crosshair-cursor-enabled');
Original Answer: Map-level Crosshairs
#scud42 got me on the right path. You can use JQuery to change the Leaflet map cursor like this:
$('.leaflet-container').css('cursor','crosshair');
Then later, when you want to reset the map cursor, you can do this:
$('.leaflet-container').css('cursor','');
Edit 1.21.2016: Per-feature Crosshairs
You can also enable crosshairs for individual features supporting the className option, such as a polygon, or feature vertices, etc.
Here's an example of a draggable vertice that will toggle pointer crosshairs (jsfiddle):
var svg_html_default = '<div style="margin:0px;padding:0px;height:8px;width:8px;border-style:solid;border-color:#FFFFFF;border-width:1px;background-color:#424242"</div>';
var default_icon = L.divIcon({
html: svg_html_default,
className: 'leaflet-mouse-marker',
iconAnchor: [5,5],
iconSize: [8,8]
});
var m = new L.marker([33.9731003, -80.9968865], {
icon: default_icon,
draggable: true,
opacity: 0.7
}).addTo( map );
m.on("mouseover",function(){$('.leaflet-mouse-marker').css('cursor','crosshair');});
m.on("mouseout",function(){$('.leaflet-mouse-marker').css('cursor','');});
Leaflet's styles allow you to change some cursor behavior. Put these in your local CSS to make the change.
/* Change cursor when mousing over clickable layer */
.leaflet-clickable {
cursor: crosshair !important;
}
/* Change cursor when over entire map */
.leaflet-container {
cursor: help !important;
}
Set to crosshair:
document.getElementById('map').style.cursor = 'crosshair'
Reset it back:
document.getElementById('map').style.cursor = ''
Use the active pseudo class.
#map:active {
cursor: url('..custom.png');
}
JSFiddle
For overriding a cursor you will probably want to use the css3 attribute user-select: none so that it doesn't toggle between the text and default cursor when dragging on the element. That implementation is also shown in the JSFiddle.
This is what worked for me:
// CSS first. Add this to leaflet stylesheet.
.leaflet-interactive.wait-cursor-enabled {
cursor: wait !important;
}
// JS select from map container and add class to each element
let map = L.map('map');
let els = map.getContainer().querySelectorAll('.leaflet-interactive');
for(let el of els){
el.classList += ' wait-cursor-enabled';
}
//JS remove class once no longer needed
let els = map.getContainer().querySelectorAll('.leaflet-interactive.wait-cursor-enabled');
for(let el of els){
el.classList.remove("wait-cursor-enabled");
}
$('.leaflet-container').css('cursor','crosshair');
I use react-leaflet and needed to change the cursor over the map and the polygons on it, based on a bit of state higher up in the app. Changing the cursor for the map itself was simple:
map.getContainer().style.cursor = 'crosshair';
For the polygons on the map it was not as straightforward. Leaflet polygons take a className option, which could be used to override the default leaflet-interactive class that sets the cursor to pointer. However, I found that className was not a dynamic option: re-rendering the polygon did not change the className (see this github issue).
I use styled-components, so I tried to wrap the Polygon component to override the cursor style rule, but this, also, only worked when the Polygon was first created. Eventually, I settled on capturing a reference to the Polygon object:
<Polygon ref={(el:any) => this.wrapperRef = el} /* ... */ />
and used this to set the cursor style rule on update:
componentDidUpdate = () => {
this.wrapperRef._path.style.cursor = this.props.cursor;
}
As discussed in the aforementioned github issue, the property _path of the object created by Leaflet can be used to access and override the style.

Flot graph does not render when parent container is hidden

I was having an issue where a flot graph would not render in a tabbed interface because the placeholder divs were children of divs with 'display: none'. The axes would be displayed, but no graph content.
I wrote the javascript function below as a wrapper for the plot function in order to solve this issue. It might be useful for others doing something similar.
function safePlot(placeholderDiv, data, options){
// Move the graph place holder to the hidden loader
// div to render
var parentContainer = placeholderDiv.parent();
$('#graphLoaderDiv').append(placeholderDiv);
// Render the graph
$.plot(placeholderDiv, data, options);
// Move the graph back to it's original parent
// container
parentContainer.append(placeholderDiv);
}
Here is the CSS for the graph loader div which can be placed
anywhere on the page.
#graphLoaderDiv{
visibility: hidden;
position: absolute;
top: 0px;
left: 0px;
width: 500px;
height: 150px;
}
Perhaps this is better solution. It can be used as a drop in replacement for $.plot():
var fplot = function(e,data,options){
var jqParent, jqHidden;
if (e.offsetWidth <=0 || e.offetHeight <=0){
// lets attempt to compensate for an ancestor with display:none
jqParent = $(e).parent();
jqHidden = $("<div style='visibility:hidden'></div>");
$('body').append(jqHidden);
jqHidden.append(e);
}
var plot=$.plot(e,data,options);
// if we moved it above, lets put it back
if (jqParent){
jqParent.append(e);
jqHidden.remove();
}
return plot;
};
Then just take your call to $.plot() and change it to fplot()
The only thing that works without any CSS trick is to load the plot 1 second after like this:
$('#myTab a[href="#tabname"]').on("click", function() {
setTimeout(function() {
$.plot($(divChartArea), data, options);
}, 1000);
});
or for older jquery
$('#myTab a[href="#tabname"]').click (function() {
setTimeout(function() {
$.plot($(divChartArea), data, options);
}, 1000);
});
The above example is applied to Bootstrap tags for Click funtion. But should work for any hidden div or object.
Working example: http://topg.org/server-desteria-factions-levels-classes-tokens-id388539
Just click the "Players" tab and you'll see the above example in action.
This one is a FAQ:
Your #graphLoaderDiv must have a width and height, and unfortunately, invisible divs do not have them. Instead, make it visible, but set its left to -10000px. Then once you are ready to show it, just set it's left to 0px (or whatever).
OK, I understand better now what you're actually saying... I still think your answer is too complicated though. I just tried this out using a tabbed interface where the graph is in a hidden tab when it's loaded. It seems to work fine for me.
http://jsfiddle.net/ryleyb/dB8UZ/
I didn't have the visibility:hidden bit in there, but it didn't seem necessary...
You could also have visibility:hidden set and then change the tabs code to something like this:
$('#tabs').tabs({
show: function(e,ui){
if (ui.index != 2) { return; }
$('#graphLoaderDiv').css('visibility','visible');
}
});
But given the information provided, none of that seems particularly necessary.
I know this is a bit old but you can also try using the Resize plugin for Flot.
http://benalman.com/projects/jquery-resize-plugin/
It is not perfect because you'll sometimes get a flash of the non-sized graph which may be shrunk. Also some formatting and positioning may be off depending on the type of graph that you are using.

Image swap in firefox

I'm trying to change the background image of a button when the mouse is hovered.
with the statement
function testIn ()
{
elem.style.backgroundImage = 'url("image_name_in.png")';
}
function testOut ()
{
elem.style.backgroundImage = 'url("image_name_out.png")';
}
i'm doing this with onMouseOver=testIn() and onMouseOut=testOut().
Here the problem is that, when i hover the mouse. I'm seeing the progress bar (bottom right side) is shown in firefox as if some page is getting loaded
Use :hover pseudo-class and CSS Sprites instead.
You need a few changes in order to pass your object reference:
onMouseOver="testIn(this)"
function testIn (elem)
{
elem.style.backgroundImage = 'url("image_name_in.png")';
}
BTW - convention now uses "onmouseover" (no caps)
You're getting activity in the progress bar because your onmouseover image does NOT load until you call the function.
You could use a sprite combined with :hover CSS for the effect - like #Tomasz mentions.
If you don't want to combine your default and hover image states into a sprite, you may try adding an additional container for the hover image (setting it's default CSS to display:none;) then use JS, or jQuery to swap the display states of the default and hover images on mouseover or hover.
$('myDefaultImage').hover(function() {
$(this).hide();
$('myHoverImage').show();
}, function () {
...the inverse, etc.
});
This will eliminate the progress bar issue because all of your images will be loaded together.
At the same time, this is going to bloat your page size unnecessarily.
I'd really try to go with the :hover CSS and sprite, or reevaluate the importance of what you're trying to accomplish with the image swap (is it really the best solution for your overall project?).

Categories

Resources