jQuerymobile slider touch lags - jquery-mobile

I'm using a slider to change the min/max for chart I'm displaying with flot.
This is my slider HTML:
<div id=timerangeslider>
<form>
<div class="ui-grid-a" id="slider3">
<label for="slider-2">Anzeige-Zeitraum (in Stunden):</label>
<input type="range" name="slider-2" id="slider-2" data-highlight="true" min="1" max="48" value="24">
</div><!-- /ui-grid -->
</form></div>
And this is my jQuery:
function timerangeslider() {
$(document).ready(function(){
$("#slider-2").change("click",function() {
timerange = $("#slider-2").val();
energyPlot(d,timerange)
});
});
}
The function gets called on "pageinit".
It calls another function "energyPlot" which updates my chart (using flot)
Problem with this solution is, that is re-draws my chart on every change of the value of "#slider-2"
So this works, but looks like crap.
Another solution would be this:
function timerangeslider() {
$(document).ready(function(){
$(document).on("click","#timerangeslider",function(event) {
timerange = $("#slider-2").val();
energyPlot(d,timerange)
});
});
}
Problem here is, that on my device (with Phonegap) it does not recognize touches on the actual slider. You can click the number left to the slider and it get's the touch, but not if you drag the slider.
It works in browser though.
Any ideas how to react to touches on the actual slider (on device with phonegap)
Or any ideas for the first solution on how to re-draw the chart only when the slider stopped?

Just found the solution here jQueryMobile slider change event
It seems there is an event for a slider called "slidestop" and you can listen for it.
So I used this:
function timerangeslider() {
$("#slider-2").on("slidestop",function(event) {
timerange = $("#slider-2").val();
energyPlot(d,timerange);
});
}

Related

jQuery animate() on Chrome 37.0.2062.120 m / Webkit?

This is my first question here on SO, so bear with me. I am developing a small project and I recently discovered one particular problem that I did not have before.
In my project I have a small map used for selection of different regions of my country, Romania. I implemented this with Raphael.js library and jQuery/UI. It looks like this:
http://s28.postimg.org/pzg3gaiod/output_Cuap_Ye.gif
The idea is when you select a region it gets dynamically coloured and added to a vector of regions. Simple. So for every region (that is declared as a path for the Raphael library to understand and paint) I have a small function:
function clickableMinimapRegions(st, regio) {
st[0].style.cursor = "pointer";
st[0].onclick = function () {
if ($.inArray(regio, regions) != -1) {
regions.splice($.inArray(regio, regions), 1);
st.animate({
fill: "#FFFFFF"
}, 0);
} else {
regions.push(regio);
st.animate({
fill: "#e6e6e6"
}, 0);
}
};
}
Then I have this HTML:
<ul class="element-menu drop-up">
<li>
<a id="toggle" class="dropdown-toggle bg-lime text-shadow button shadow">
<img src="../img/regions.png">
</a>
<div id="content" class="dropdown-menu bg-steel" data-role="dropdown">
<div id="minimap" class="minimap"></div>
</div>
</li>
</ul>
I use Metro UI CSS library, it's a simple drop-down menu. But it's behaviour is to autoclose on click. So for that I did:
$("#minimap").click(function (event) {
event.stopPropagation();
});
http://s28.postimg.org/trltqsu19/Captura3.png
This menu is at the bottom of the screen over a leaflet map, the map is the background and this drop-down is over the map. The thing is, if the map is not loaded, than it works fine. If the map tiles are loaded, something is happening that prevents the regions to be coloured when clicked.
Thank you.
SOLUTION FOUND:
Force DOM redraw/refresh on Chrome/Mac
The second parameter in jQuery's .animate() is the duration, in milliseconds. Having set it to 0, I'd rather say the behaviour you see in other browsers is wrong, and you should expect to have the property changed immediately with no animation.
st.animate({
fill: "#FFFFFF"
}, 0);
// ^---- duration
Try changing that to a bigger value (400 ms is the default)
Here's a fiddle showing the difference: http://jsfiddle.net/exrj973b/

Highcharts does not resize charts inside tabs

I am using twitter bootstrap with tabs. I have multiple tabs and charts inside each tab. Upon browser resize, charts that are not on the current active tab do not get resized. Infact, it looks kind of funny with a thin bar. The current active tab works fine. Has anyone seen this issue and are there any workarounds ?
Here is a working example:
http://codepen.io/colinsteinmann/pen/BlGfE
Basically the .reflow() function is called on each chart when a tab is clicked. That way the chart gets redrawn based on the new dimensions which are applied to the container when it becomes visible.
This is the most important snippet of code:
// fix dimensions of chart that was in a hidden element
jQuery(document).on( 'shown.bs.tab', 'a[data-toggle="tab"]', function (e) { // on tab selection event
jQuery( ".contains-chart" ).each(function() { // target each element with the .contains-chart class
var chart = jQuery(this).highcharts(); // target the chart itself
chart.reflow() // reflow that chart
});
})
This is my fix for this (using jQuery):
$("[data-highcharts-chart]").each(function () {
var highChart = Highcharts.charts[$(this).data('highchartsChart')];
var highChartCont = $(highChart.container).parent();
highChart.setSize(highChartCont.width(), highChartCont.height());
highChart.hasUserSize = undefined;
});
Call this function whenever the chart gains focus to make sure it is resized properly.
I had a similar issue and I found that the best thing was not to load the chart until the tab was shown. So in the tab shown event I was quickly loading the chart (but only once)
I just solved this issue with the following. Using bootstrap version 3.3.5
I am leaving this here because this link showed up when I googled the issue at the beginning. I hope it helps.
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
$(e.target.hash).highcharts().reflow();
});
HTML
<!-- Nav tabs -->
<ul class="nav nav-pills nav-justified" role="tablist" id="taks-tabs">
<li role="presentation" class="active">Met Standard</li>
<li role="presentation">Commended Performance</li>
<li role="presentation">TAKS-M Met Standard</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="taks_met_std"></div>
<div role="tabpanel" class="tab-pane" id="taks_comm_perf"></div>
<div role="tabpanel" class="tab-pane" id="taks_m_met_std"></div>
</div>
add class="chart" to all highcharts containers inside tabs.
add this jQuery code:
jQuery(document).on( 'shown.bs.tab', 'a[data-toggle="tab"]', function () {
$( '.chart' ).each(function() {
$(this).highcharts().reflow();
});
})
I found the answer after looking for sometime. This was driving me crazy so I want to share it with you all since nothing here worked for me.
Add this to your CSS
.tab-content > .tab-pane,
.pill-content > .pill-pane {
display: block;
height: 0;
overflow-y: hidden;
}
.tab-content > .active,
.pill-content > .active {
height: auto;
}
For more details visit the page I found the solution at
https://jonpolygon.com/bootstrap-tabs-100-percent-width-charts/
i fix this problem with the next code.
$('#yourDivChart').highcharts({
chart: {
type: data.EjeX.Tipo,
//width: width,
//height: height,
options3d: {
enabled: true,
alpha: 15,
beta: 15,
viewDistance: 25,
depth: 40
},
width: $('#DivContainerWithYourTabs').width() - 150
},
in my case is a partial "_partialDetalleProyecto"
I hope works you.
So this is a bit old, but for anyone stumbling across this, I was having a similar issue with the highchart sizes being incorrect in a bootstrap tabbed display. The solution I came up with was to just delay creating the chart by 100ms using setTimeout().
setTimeout(function() {
drawBarChart();
}, 100);
Note: drawBarChart is a custom function I created to generate the charts I needed. The issue (at least in my case) seemed to be that the chart was being created before (or at the same time) as the container and was therefore choosing some default width instead of the width of the container.
I have 2 tabs , met same problem.
I changed only 2 rows codes of Druska, and it worked.
function anyname() {
$("[data-highcharts-chart]").each(function () {
var highChart = Highcharts.charts[$(this).data('highchartsChart')];
var highChartCont = $(highChart.container).parent();
highChart.reflow();
});
}
and add one onclick event to you HTML tab codes like below:
<input type="radio" id="tab1_1" checked onclick="anyname();" >

iframe prevents iScroll scrolling on mobile Safari

I am using iScroll on my mobile enable website (using iPhone here) to scroll inside a div.
In this this div, I have an iframe with a fixed height like this:
<body>
<div id="iscroller">
<iframe id="theIframe"></iframe>
Other stuff
</div>
</body>
Now, while scrolling within the div, everything works as expected but I cannot scroll when the scrolling gesture begins on the iframe.
The problem is described here pretty well: https://github.com/cubiq/iscroll/issues/41
So, I used the css workaround from that post by applying pointer-events:none to the iframe.
Now scrolling works perfectly but I cannot click any links which are defined within the iframe because all click/touch events on the iframe seems to be blocked due to pointer-events: none.
So, I thought:
"Ok, while the user scrolls, I need pointer-events:none. If he is
not scrolling (and instead clicking), I must set pointer-events:auto
in order to let the click/touch events pass."
So I did this:
CSS
#theIframe{pointer-events:none}
JavaScript
$("#theIframe").bind("touchstart", function(){
// Enable click before click is triggered
$(this).css("pointer-events", "auto");
});
$("#theIframe").bind("touchmove", function(){
// Disable click/touch events while scrolling
$(this).css("pointer-events", "none");
});
Even adding this doesn't work:
$("#theIframe").bind("touchend", function(){
// Re-enable click/touch events after releasing
$(this).css("pointer-events", "auto");
});
No matter what I do: Either scrolling doesn't work or clicking the link inside the iframe doesn't work.
Doesn't work. Any ideas?
I found the perfect solution. Works great on iOS and Android.
The basic idea is to put a div layer on top of that iframe. This way scrolling works smoothly.
If the user wants to tap/click on an element on that iframe I simply catch that click on the layer, save the x and y coordinates and trigger a click event on the iframe's content at these coordinates:
HTML:
<div id="wrapper">
<div id="layer"></div>
<iframe id="theIframe"></iframe>
</div>
Other stuff
CSS:
#layer{
position:absolute;
opacity:0;
width:100%;
height:100%;
top:0;
left:0;
right:0;
bottom:0;
z-index:2
}
JavaScript:
$('#layer').click(function(event){
var iframe = $('#theIframe').get(0);
var iframeDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
// Find click position (coordinates)
var x = event.offsetX;
var y = event.offsetY;
// Trigger click inside iframe
var link = iframeDoc.elementFromPoint(x, y);
var newEvent = iframeDoc.createEvent('HTMLEvents');
newEvent.initEvent('click', true, true);
link.dispatchEvent(newEvent);
});
I found a solution for this, it happens to be close to what other guys already mentioned on github but this may be useful for whoever wants to find a fast working resolution for this problem.
I'm assuming a few things, like there's only one iscroll container, here represented as ID. This is not properly tested and needs refactor. It's working in my project, but I changed it here slightly for the example but I guess you'll easily understand what you need to do:
var $iscroll = $('#iscroll');
document.addEventListener('touchstart', function(e) {
if ($iscroll.find('iframe').length > 0){
$.each($iscroll.find('iframe'), function(k,v){
var $parent = $(v).parent().first();
if ($parent.find('.preventTouch').length == 0){
$('<div class="preventTouch" style="position:absolute; z-index:2; width:100%; height:100%;"></div>')
.prependTo($parent);
};
$parent
.css('position', 'relative').css('z-index', 1);
});
$iscroll.find('.preventTouch').on('click', function(e){
e.preventDefault();
e.stopPropagation();
return false;
});
};
};
document.addEventListener('touchend', function(e) {
if ($iscroll.find('iframe').length > 0){
setTimeout(function(){
var $iscroll = $('#iscroll');
$iscroll.find('.preventTouch').remove();
$iscroll.find('iframe').css('z-index', '');
$iscroll.find('.preventTouch').off('click');
}, 400);
};
};
Thanks for looking!

changing track color between 2 Slider handles

I am using Script.aculo.us Slider.js to display dual sliders. It working perfectly.
what I want to do is to change the color to track only in between these two slider.
For example if 1st Slider is on value 5 and 2nd is on value 8. I want that the track fron 5-8 is green and the rest is gray. to simulate king of selected range.
Is it possible?
I have figured it out, it is possible by using 2 options properties
startSpan and endSpan.
Maybe it is useful for someone else I am pasting here sample HTML snippt and javascript
<div id="slider-week-track">
<div id="span1" style="float:left;background-color: #B7C0CD; height: 11px;"></div>
<div class="slider-week slider-min" id="slider-week-min-handle"></div>
<div class="slider-week slider-max" id="slider-week-max-handle"></div>
<div id="span2" style="float:right;background-color: #B7C0CD; height: 11px;"></div>
</div>
and javascript
new Control.Slider(this.options.handles, 'slider-week-track', {
range:$R(0,10, false),
sliderValue: [1,5],
values: [0,1,2,3,4,5,6,7,8,9,10],
restricted: true,
startSpan: 'span1',
endSpan: 'span2',
onChange: function(val) {
//your code here
}
});

Get scroll position of panel using SplitView (JQuery Mobile)

I have implemented a WebApp using SplitView - http://asyraf9.github.com/jquery-mobile/ - (and that seems to use the ScrollView component) together with jQuery Mobile. Everything works fine ...
Within the panel I have got a list of elements that should dynamically add elements when scrolling reaches the end of the list. On the iPhone I do not use SplitView but iScroll - http://cubiq.org/iscroll - and the following code to achieve this (and it is working).
HTML:
<div data-role="panel" data-id="menu" data-hash="crumbs" style="z-index: 10000;" id="Panel">
<div data-role="page" id="Root" class="Login" onscroll="console.log('onscroll');">
<div data-role="content" data-theme="d" onscroll="console.log('onscroll');">
<div class="sub">
<ul data-role="listview" data-theme="d" data-dividertheme="a" class="picListview" id="PortfolioList">
<!-- Content added dynamically -->
</ul>
</div>
</div>
</div>
</div>
Javascript:
var defaultIScrollOptions = {
useTransition: true,
onScrollStart: function() {
this.refresh();
},
onScrollEnd: function() {
if (this.elem && this.id) {
possiblyDisplayNextDocuments(this.y, this.elem, this.id);
}
}
};
iScrolls.push(new iScroll(document.getElementById("searchResults").parentNode, defaultIScrollOptions));
But when using SplitView I do not really know which event and which element to bind the listener on or how to get the scroll position. I already tried several combinations, but did not achieve good results. The best one was the following:
$("#PortfolioList").scrollstop(function(event) {
console.log("scrollstop: "+$("#PortfolioList").scrollTop());
});
My question is: Am I using the right event listener (since it already fires althgough the scrolling animation is still in use) and how do I get the scroll position?
dont use the scrollview plugin. its buggy. Use iscroll for both iOS phonegap apps as well as android. It works fine on both.
For detecting the scroll and loading new elements into the list, listen to the the 'onScrollMove' event of iscroll.
In the iscroll-wrapper.js add this-
options.onScrollMove = function(){
that.triggerHandler('onScrollMove', [this]);
};
then in your code attach a event handler to the onScrollMove event and handle adding new rows in that. onScrollMove will fire whenever you scroll.
In the handler you can find how many rows are there in your list and that which row is on the top of your view port using something like
iscrollScrollEventHandler:function(event){
var contentDiv= $('div:jqmData(id="main") .ui-page-active div[data-role*="content"] ul li' );
var totalItemsonList = contentDiv.length;
var cont =$('div:jqmData(id="main") .ui-page-active div:jqmData(role="content")');
var itemToScrollOn = totalItemsonList - x; // x is the item no. from the top u want to scroll on. u need to keep updating i guess
var docViewBottom = $(cont).scrollTop() + $(cont).height();
var itemOffset = $(contentDiv[itemToScrollOn]).offset();
if(itemOffset){
var elemTop = itemOffset.top;
if (elemTop <= docViewBottom){
event.data.callback();
}
}
}
and in the callback add the code to add new rows. hope that helps.

Resources