问题
I am using jQDateRangeSlider to trigger a jQuery.ajax call.There are two ways in which the slider can be moved.
- By moving the ends of the slider individually
- By moving the entire highlighted block from one place to other
In case of 1, my code works fine, but in case 2, the 'userValuesChanged' gets invoked two or four times.Is this some bug with the widget or am I doing something wrong here? This is how my code looks?
function init() {
var tp = $('tp').value;
if (tp == 'Daily') {
dataFile1 = "http://localhost:8080/composite2/Composite/datejson";
d3.json(dataFile1, function (error, data) {
if (data) dataset1 = data;
var min = dataset1[0].a;
var jugad = dataset1[0].c;
jugad2 = new Date(jugad);
var min2 = new Date(min);
var max = dataset1[dataset1.length - 1].b;
var max2 = new Date(max);
function addZero(val) {
if (val < 10) {
return "0" + val;
}
return val;
}
var s = $j("#slider").dateRangeSlider({
bounds: {
"min": min2,
"max": max2
},
range: {
min: {
hours: 25
},
max: {
days: 7
},
},
formatter: function (val) {
var m = moment(val);
return m.format("DD/MM/YYYY HH:00:00 ");
},
defaultValues: {
min: min2,
max: max2
}
});
x = jugad2;
x.setMinutes(0);
x.setSeconds(0);
z = x.getFullYear() + '-' + (x.getMonth() + 1) + '-' + x.getDate() + ' ' + x.getHours() + ':' + '00' + ':' + '00';
var y = (s.dateRangeSlider("values").max);
y.setMinutes(0);
y.setSeconds(0);
b = y.getFullYear() + '-' + (y.getMonth() + 1) + '-' + y.getDate() + ' ' + y.getHours() + ':' + '00' + ':' + '00'
jQuery.ajax({
type: 'POST',
data: 'metric=' + $('metric').value + '&tp=' + $('tp').value + '&date_hour=' + z + '&date_hour=' + b,
url: '/composite2/Composite/ajaxGetMv',
success: function (data, textStatus) {
loadData(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {}
});
$j('#slider').on("userValuesChanged", function (e, data) {
var x = data.values.min;
x.setMinutes(0);
x.setSeconds(0);
z = x.getFullYear() + '-' + (x.getMonth() + 1) + '-' + x.getDate() + ' ' + x.getHours() + ':' + '00' + ':' + '00';
var last = data.values.max;
last.setMinutes(0);
last.setSeconds(0);
b = last.getFullYear() + '-' + (last.getMonth() + 1) + '-' + last.getDate() + ' ' + last.getHours() + ':' + '00' + ':' + '00';
jQuery.ajax({
type: 'POST',
data: 'metric=' + $('metric').value + '&tp=' + $('tp').value + '&date_hour=' + z + '&date_hour=' + b,
url: '/composite2/Composite/ajaxGetMv',
success: function (data, textStatus) {
loadData(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {}
});
})
});
} //end of Daily Slider
} //end of init()
UPDATE
init() is being called from function decide.
function decide()
{
var tp = $('tp').value;
if (tp == 'Daily')
{
init();
}
else
{
init1();
}
}
This function decide() is being called on the onchange of a dropdown 'tp'
回答1:
I'm having to guess a bit here as you don't say what versions of the libraries you're using. However I tested the plugin in jsFiddle and it works fine, so I assume that you're doing repeated calls to init
which are binding extra handlers to the event. You say:
This function
decide()
is being called on the onchange of a dropdowntp
This means that whenever that dropdown changes init
is called again and the handler is added again to that event. You can see this happening here in my jsFiddle, counts are normal until you click the button to call init()
again. There are a few ways round this, see the comments in the fiddle as well.
Option 1 -- Simple but not really elegant.
Just destroy the slider at the start of the init() routine:
function init() {
$j("#slider").dateRangeSlider("destroy");
This doesn't throw an error if the slider hasn't been initialized (looks like the plugin has some sanity checking) but it may cause a visual glitch on some browsers.
Option 2 -- A bit better
Use a global variable to keep a note of if you've created the event
var is_init = false;
function init() {
// ... other code ...
if (!is_init)
{
$j('#slider').on("userValuesChanged", function (e, data) {
// ... handler code ...
});
is_init = true;
}
}
There are a few other ways to use the 'global variable' idea, including faking static function variables but this is the simple way and it may work since you have two init routines.
Option 3 -- Probably my choice
Your init()
function is really a (re)init since it can be called more than once. You only want to bind the handler once so you can just do it outside the init function (or inside a different function that's only called once). You can do this before calling init, just after page load. This works it just registers an event handler, it doesn't care that at that point that element can't generate the event, it'll handle it just fine later. Here's a fiddle for that.
It really sounds like you want an init
function somewhere that's called once (not tied to an element) and a reinit
function tied to the dropdown that just changes the values but doesn't rebind the event. I don't see anything in your event handler that changes depending on the different settings but if there is you'll probably have to go with Option 1.
There are some other options (unbind the event handler, detect if there's already a handler bound) but they may run into more trouble if other handlers are also bound to that event.
And this may not be the root cause of your problem, but I hope the fiddles help you in any case.
来源:https://stackoverflow.com/questions/25759135/jquery-ajax-called-twice-from-uservalueschanged-in-daterangeslider