Using the jQuery UI Slider, I'm trying to figure out how to make it so that the slider stops working once certain conditions are met. Any ideas? I thought stopping event propogation in the "start" part would work, but ...it doesn't. So I'm still clueless and lost.
<script type="text/javascript">
$(document).ready(function () {
var spendable = 1000;
var spent = 0;
function spend(quantity) {
var remaining = spendable - quantity;
$('#spendable').text(remaining);
}
$("#eq .slider").each(function () {
var current = 0;
$(this).slider({
range: "min",
step: 100,
value: 0,
min: 0,
max: 500,
animate: true,
orientation: "horizontal",
start: function (event, ui) {
if (spent < spendable)
return true;
event.stopPropagation();
},
slide: function (event, ui) {
// set the current value to whatever is selected.
current = ui.value;
$(this).parent('div:eq(0)').find('.spent').text(current);
var totalled = 0;
$("#eq .slider").each(function () {
totalled += parseInt($(this).parent('div:eq(0)').find('.spent').text());
spend(totalled);
});
}
});
});
Try:
.....
slide: function (event, ui) {
// set the current value to whatever is selected.
current = ui.value;
if(current > 300){
current = 300; //otherwise, it's stuck at 301
return false;
}
....rest of your code
Related
Using JQuery UI draggable/droppable I am running into an issue where the draggable drop area is offset (normally to the left but inconsistent distance). The image can be directly over the drop area and fail and on next attempt, in exact same location, pass.
So, dragged item looks in correct spot over mouse but is incorrect when dropped... but only first attempt.
function dragAndDrop(draggedItem,dropZone,size)
{
var bool = 0;
var draggedItem = $(draggedItem);
var dragFromLeft = draggedItem.offset().left;
var dragFromTop = draggedItem.offset().top;
var dropZone = $(dropZone);
//var size = size;
draggedItem.draggable //Make item draggable
({
opacity:1,
revert:function()//'invalid'
{
$(".strobeRed").fadeTo(100, .50).fadeTo(100, 0);
$(this).offset({top: dragFromTop, left: dragFromLeft})
},
drag:function(event, ui)
{
$(this).height(size);
$(this).width(size);
},
cursorAt:
{
left:(size/2),
top:(size/2)
}
});
dropZone.droppable //Make item droppable
({
accept:draggedItem,
drop: function(event, ui)
{
$( ui.draggable ).fadeOut(),
$( this ).droppable( "option", "disabled", true ).css("background-color", "green"), //$(this) = $(event.target)
$( this ).draggable( "option", "disabled", true )
}
});
}
sample image
* EDIT 1
Adding function call from edge animate *
draggable and droppable objects are just divs with class names.
yepnope({nope:['jquery-ui.js','cookbook.js'],complete:init});
function init(){
dragAndDrop(".item1",'.dz1',50);
dragAndDrop(".item2",'.dz2',50);
dragAndDrop(".item3",'.dz3',50);
dragAndDrop(".item4",'.dz4',50);
dragAndDrop(".item5",'.dz5',50);
dragAndDrop(".item6",'.dz6',50);
dragAndDrop(".item7",'.dz7',50);
dragAndDrop(".item8",'.dz8',50);
dragAndDrop(".item9",'.dz9',50);
}
* EDIT 2
fixed issue, introduced another *
by having the scale prior to adding the draggable, it now drops correctly. The new issue is the first item I touch of each type scales and relocates to pointer but the drops. It doesn't fail it just stops being dragged.
function dragAndDrop(draggedItem,dropZone,scaleHeight,scaleWidth)
{
var bool = 0;
var draggedItem = $(draggedItem);
var dragFromLeft = draggedItem.offset().left;
var dragFromTop = draggedItem.offset().top;
var dropZone = $(dropZone);
var currentMousePos = { x: -1, y: -1 };
draggedItem.mousedown(function(event){
currentMousePos.x = event.pageX - (scaleWidth/2);
currentMousePos.y = event.pageY - (scaleHeight/2);
$(this).height(scaleHeight);
$(this).width(scaleWidth);
$(this).offset({top: currentMousePos.y, left: currentMousePos.x});
draggedItem.draggable //Make item draggable
({
opacity:1,
revert:function()//'invalid'
{
$(".strobeRed").fadeTo(100, .50).fadeTo(100, 0);
$(this).offset({top: dragFromTop, left: dragFromLeft})
}
})
});
dropZone.droppable //Make item droppable
({
accept:draggedItem,
drop: function(event, ui)
{
//$( ui.draggable ).fadeOut(),
$( this ).droppable( "option", "disabled", true ).css("background-color", "green"), //$(this) = $(event.target)
$( this ).draggable( "option", "disabled", true )
},
tolerance: "touch"
});
}
** I FOUND IT **
Ok, so my first attempt was calculating the draggable as its original size. The second attempt was not dragging the first item of each type during first attempt. I believe it was stuck in mousedown event and not running the draggable. every time after that draggable was already applied so it worked.
The fix was to assign draggable to everything in the beginning but pull the scaling into a second function. It now scales the item, centers it on mouse, drags and drops.
function dragAndDrop(draggedItem,dropZone,scaleHeight,scaleWidth)
{
var bool = 0;
var draggedItem = $(draggedItem);
var dragFromLeft = draggedItem.offset().left;
var dragFromTop = draggedItem.offset().top;
var dropZone = $(dropZone);
var currentMousePos = { x: 0, y: 0};
draggedItem.draggable //Make item draggable
({
opacity:1,
revert:function()//'invalid'
{
$(".strobeRed").fadeTo(100, .50).fadeTo(100, 0);
$(this).offset({top: dragFromTop, left: dragFromLeft})
}
})
draggedItem.mousedown(function(event){
currentMousePos.x = event.pageX - (scaleWidth/2);
currentMousePos.y = event.pageY - (scaleHeight/2);
$(this).height(scaleHeight);
$(this).width(scaleWidth);
$(this).offset({top: currentMousePos.y, left: currentMousePos.x});
});
dropZone.droppable //Make item droppable
({
accept:draggedItem,
drop: function(event, ui)
{
//$( ui.draggable ).fadeOut(),
$( this ).droppable( "option", "disabled", true ).css("background-color", "green"), //$(this) = $(event.target)
$( this ).draggable( "option", "disabled", true )
},
tolerance: "touch"
});
}
I have the following script, using howler.js and jquery-ui-1.8.21.custom.min.js:
$(function(){
var sounduser1 = new Howl({
urls: ['studio/keysintheair.mp3', 'studio/keysintheair.ogg'],
buffer:true,
volume: 1.0,
onend: function() {
$('.buttons').fadeIn();
},
});
var sounduser2 = new Howl({
urls: ['studio/keysintheair-original.mp3'],
buffer:true,
volume: 0.1,
});
var thisArray = {
user1: sounduser1,
user2: sounduser2
};
$.each( thisArray, function(key,value) {
$('.buildplayer .player').clone().attr('id',key).appendTo('#song');
$('#song .player:last .waveform').css("width", value._duration + "px");
$('#song .player:last .slider').slider({
value: value.volume() * 100,
range: "min",
animate: true,
orientation: "horizontal",
//Slider Event
slide: function(event, ui) { //When the slider is sliding
var now_id = $(this).parent().parent('.player').attr('id');
thisArray[now_id].volume(ui.value/100);
},
});
});
$('.mainplayer .trackslider').slider({
value: 0,
range: "min",
animate: true,
orientation: "horizontal",
//Slider Event
slide: function trackslider(event, ui) { //When the slider is sliding
var audiogetlength = Object.keys( thisArray ).map(function ( key ) { return thisArray[key]._duration; });
var longest = Math.max.apply( null, audiogetlength );
var dividedlength = 100/ui.value;
$.each( thisArray, function( key, value ) {
value.pos(longest/dividedlength);
if (ui.value > value._duration) {
value.stop();
}
});
},
});
setInterval(function starttrackslider() {
var dividedslider = sounduser1._duration/sounduser1.pos();
$('.trackslider').slider('value', 100/dividedslider);
},1000);
//Single Audio Track Player
$('.ex1-play').on('click', function(){
var now_id = $(this).parent().parent('.player').attr('id');
thisArray[now_id].stop().play();
});
$('.ex1-stop').on('click', function(){
var now_id = $(this).parent().parent('.player').attr('id');
thisArray[now_id].stop();
});
$('.ex1-loop').on('click', function(){
var now_id = $(this).parent().parent('.player').attr('id');
thisArray[now_id].loop(true);
});
//Main All Track Player
$('.main-play').on('click', function(){
$.each( thisArray, function( key, value ) {
value.stop().play();
$('.buttons').fadeOut();
});
});
$('.main-pause').on('click', function(){
$.each( thisArray, function( key, value ) {
value.pause();
});
});
$('.main-stop').on('click', function(){
$.each( thisArray, function( key, value ) {
value.stop();
$('.buttons').fadeIn();
});
});
$('.main-loop').on('click', function(){
$.each( thisArray, function( key, value ) {
value.loop(true);
});
});
});
At the last part of $('.mainplayer .trackslider').slider({ }); you will find if (ui.value > value._duration) {value.stop();}
value equals the Howl called sounduser2
Both audiotracks start at the same time. Using a slider will make me skip through the audio. The slider will have the length of the longest audiotrack - which is Howl called sounduser1. Using the slider will return a number which will activate the position of the audio.
If the slider returns a number bigger then the actual length of the audiotrack it should stop the shorter audiotrack.
For some reason it won't stop playing, eventhough the situation is right. Is there anybody who knows what to do?
$('.mainplayer .trackslider').slider({
value: 0,
range: "min",
animate: true,
orientation: "horizontal",
//Slider Event
slide: function (event, ui) { //When the slider is sliding
var audiogetlength = Object.keys( thisArray ).map(function ( key ) { return thisArray[key]._duration; });
var longest = Math.max.apply( null, audiogetlength );
var dividedlength = 100/ui.value;
$.each( thisArray, function( key, value ) {
var percentvalue = (value._duration/longest)*100;
if (percentvalue > ui.value) {
if (value.pos()==0) {
value.play().pos(longest/dividedlength);
} else {
value.pos(longest/dividedlength);
}
} else {
value.stop();
}
});
}
});
Did the trick
I've written a script for a simple jquery ui slider. There are two sliders (later I'll add more) and when you change their value, it displays below them, and then updates a total. What I'm having a hard time figuring out, is how to make it so as you're sliding the values are getting updated, instead of getting updated after you've finished.
Thanks for any help!
Fiddle of Demo
http://jsfiddle.net/tMmDy/
HTML
<div class="slider_1 slider"></div>
<p id="slider_1-value"></p>
<div class="slider_2 slider"></div>
<p id="slider_2-value"></p>
CSS
.slider {
width:100px;
height:5px;
background:blue;
}
JS
$(".slider").slider({
animate: "fast",
max: 25,
min: 0,
step: 1,
value: 10,
option: {}
});
$(".slider_1").on("slidechange", function (event, ui) {
total_1 = $(".slider_1").slider("value");
$("#slider_1-value").html(total_1);
total_value_update();
});
$(".slider_2").on("slidechange", function (event, ui) {
total_2 = $(".slider_2").slider("value");
$("#slider_2-value").html(total_2);
total_value_update();
});
function total_value_update() {
total_values = total_1 + total_2;
$("#total_value").html(total_values);
}
Use the slider's .slide() event and try it like this:
jsFiddle example
var total_1, total_2;
$(".slider").slider({
animate: "fast",
max: 25,
min: 0,
value: 10,
slide: function (event, ui) {
total_1 = $(".slider_1").slider("value");
total_2 = $(".slider_2").slider("value");
$("#slider_1-value").html(total_1);
$("#slider_2-value").html(total_2);
total_value_update();
},
change: function (event, ui) {
total_1 = $(".slider_1").slider("value");
total_2 = $(".slider_2").slider("value");
$("#slider_1-value").html(total_1);
$("#slider_2-value").html(total_2);
total_value_update();
}
});
function total_value_update() {
total_values = total_1 + total_2;
$("#total_value").html(total_values);
}
I'm trying to figure out if knockout js would work nicely for the following problem:
I have multiple sliders that I want to link to textboxes.
When the textbox is changed the corresponding slider must update to the new value and vice versa.
On changing the slider value or textbox a function needs to be called that uses the input from all textboxes to calculate a result.
I have my quick and dirty jQuery solution here.
Would it be easy to achieve the same result in a more elegant way using knockout js?
I guess I would need to create a custom binding handler like its done in jQuery UI datepicker change event not caught by KnockoutJS
Here is an example: http://jsfiddle.net/jearles/Dt7Ka/
I use a custom binding to integrate the jquery-ui slider and use Knockout to capture the inputs and calculate the net amount.
--
UI
<h2>Slider Demo</h2>
Savings: <input data-bind="value: savings, valueUpdate: 'afterkeydown'" />
<div style="margin: 10px" data-bind="slider: savings, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div>
Spent: <input data-bind="value: spent, valueUpdate: 'afterkeydown'" />
<div style="margin: 10px" data-bind="slider: spent, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div>
Net: <span data-bind="text: net"></span>
View Model
ko.bindingHandlers.slider = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
$(element).slider({
"slide": function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
},
"change": function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
}
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
},
update: function (element, valueAccessor) {
var value = ko.unwrap(valueAccessor());
if (isNaN(value)) {
value = 0;
}
$(element).slider("value", value);
}
};
var ViewModel = function() {
var self = this;
self.savings = ko.observable(10);
self.spent = ko.observable(5);
self.net = ko.computed(function() {
return self.savings() - self.spent();
});
}
ko.applyBindings(new ViewModel());
I know it's some days ago but I made a few adjustments to John Earles code:
ko.bindingHandlers.slider = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
ko.utils.registerEventHandler(element, "slide", function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (isNaN(value)) value = 0;
$(element).slider("option", allBindingsAccessor().sliderOptions);
$(element).slider("value", value);
}
};
The reason for this is that if you use options that change (fx another observable) then it won't affect the slider even if you wanted it to do so.
#John Earles and #Michael Kire Hansen: thanks for your wonderful solutions!
I used the advanced code from Michael Kire Hansen. I tied the "max:" option of the slider to a ko.observable and it turned out that the slider does not correctly update the value in this case. Example: Lets say the slider is at value 25 of max 25 und you change the max value to 100, the slider stays at the most right position, indicating that it is at the max value (but value is still 25, not 100). As soon as you slide one point to the left, you get the value updated to 99.
Solution:
in the "update:" part just switch the last two lines to:
$(element).slider("option", allBindingsAccessor().sliderOptions);
$(element).slider("value", value);
This changes the options first, then the value and it works like a charm.
Thanks so much for the help, I needed to use a range slider in my scenario so here is an extension to #John Earles and #Michael Kire Hansen
ko.bindingHandlers.sliderRange = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
var observable = valueAccessor();
observable.Min(ui.values[0]);
observable.Max(ui.values[1]);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
ko.utils.registerEventHandler(element, "slide", function (event, ui) {
var observable = valueAccessor();
observable.Min(ui.values[0]);
observable.Max(ui.values[1]);
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (isNaN(value.Min())) value.Min(0);
if (isNaN(value.Max())) value.Max(0);
$(element).slider("option", allBindingsAccessor().sliderOptions);
$(element).slider("values", 0, value.Min());
$(element).slider("values", 1, value.Max());
}
};
and then the HTML to accompany it
<div id="slider-range"
data-bind="sliderRange: { Min: 0, Max: 100 },
sliderOptions: {
range: true,
min: 0,
max: 100,
step: 10,
values: [0, 100]
}"></div>
i have following code for jQuery UI vertical slider, but i need auto slide (auto scroll) that slider.
(auto slide on page load)
anyone can help?
<script>$(function() {
var scrollPane = $('#content-scrolls'),
scrollableHeight = scrollPane.height() - scrollPane.parent().height() || 0;
$("#slider-vertical").slider({
orientation: "vertical",
range: "max",
min: 0,
max: scrollableHeight,
value: scrollableHeight,
animate: true,
slide: function(event, ui) {
scrollPane.css({top: ui.value - scrollableHeight});
}
}); }); </script>
$(function() {
var scrollPane = $('#content-scrolls'),
scrollableHeight = scrollPane.height() - scrollPane.parent().height() || 0;
$("#slider-vertical").slider(
{ change: handleChange,
slide: handleSlide,
orientation: "vertical",
range: "max",
min: 0,
max: scrollableHeight,
value: scrollableHeight,
animate: true,
});
setTimeout(scrollWindow, 1000);
function scrollWindow() {
var slideValue;
slideValue = $("#slider-vertical").slider("value");
if(slideValue > -100)
{
$("#slider").slider("value", slideValue - 1);
setTimeout(scrollWindow, 1000);
}
}
function handleChange(e, ui) {
var maxScroll = $("#scroller").attr("scrollHeight") -$("#scroller").height();
$("#scroller").animate({ scrollTop: -ui.value *(maxScroll / 100)}, 1000);
}
function handleSlide(e, ui) {
var maxScroll = $("#scroller").attr("scrollHeight") -$("#scroller").height();
$("#scroller").attr({ scrollTop: -ui.value* (maxScroll / 100) });
}
});
add the scroller as follow:
<div id="slider"></div>
<div id="scroller">