I'm using the beta version of the jQuery UI spinner, as of jQuery UI 1.9 milestone 7. What I'm trying to do is the following: I have a series of spinner inputs, all with the same class that I can use as a jQuery selector (.spinner). These spinners are setting values for a set of objects, which all draw from the same "pool" of resources. Each time a spinner's value is updated, I want to go through and update all spinners' max value based on how much of that resource pool remains. Here is the basic code so far:
var unusedPool = 500;
jQuery(document).ready(function($) {
$('.spinner').spinner({
min: 0,
max: (unusedPool + this.value),
change: function(event, ui) {
// An AJAX call which pushes the change to the DB,
// and returns a JSON object containing the change in what remains
// in the resource pool.
jQuery.ajax({
// URL, type, etc. etc.
data: { newValue: this.value },
success: function (data) {
unusedPool -= data.change;
// Here is where I need to go through and update *all* spinners,
// so their new "max" is their current value plus the new
// unusedPoolSize.
}
}
}
});
Is there a way to do what I'm trying to do? Do I need to bind an event to all spinners and then trigger that event, or is there a more direct way (within the change callback) to access all of the spinners and alter the "max" value?
I suppose you could add something like this in the success function:
$('.spinner').each(function() {
$(this).spinner().change(function() {
$(this).spinner('option', 'max', $(this).spinner('value') + unusedPool);
});
});
Kvam's answer turns out to be very close, but the update inside the success function does not go inside of the spinner.change callback (since the .ajax call itself is inside the .change callback). I eventually discovered that this does the job:
var unusedPool = 500;
jQuery(document).ready(function($) {
var spinners = $('.spinner').each(function() {
$(this).spinner({
min: 0,
max: (parseInt(this.value) + unusedPool),
change: function(event, ui) {
jQuery.ajax({
data: { newValue = this.value },
success: function(data) {
unusedPool -= data.change;
spinners.each(function() {
var newMax = parseInt(this.value) + unusedPool;
$(this).spinner({ max: newMax });
}
}
});
}
});
});
Related
I'm using a jQuery script from here.
So far it works great, but the only thing that I'm wondering about is how to go about getting a comma into one of the values.
Since the number animate up when you scroll, it's tricky to get the browser to check what the integer is after the fact. I've read a bunch of posts that will add a comma (in this case I'm trying to get 100,000) but it won't work since the browser can't see that integer initially (starts at 0).
Here's the script that I'm using to invoke the animaition when you scroll down the page:
$(function () {
var fx = function fx() {
$(".stat-number").each(function (i, el) {
var data = parseInt(this.dataset.n, 10);
var props = {
"from": {
"count": 0
},
"to": {
"count": data
}
};
$(props.from).animate(props.to, {
duration: 500 * 1,
step: function (now, fx) {
$(el).text(Math.ceil(now));
},
complete:function() {
if (el.dataset.sym !== undefined) {
el.textContent = el.textContent.concat(el.dataset.sym)
}
}
});
});
};
var reset = function reset() {
console.log($(this).scrollTop())
if ($(this).scrollTop() > 950) {
$(this).off("scroll");
fx()
}
};
$(window).on("scroll", reset);
});
It takes the value from the data attribute data-n in the HTML and then works it's magic from there. If I have 100,000 in the data-n attribute then it cuts it short at 100 when the numbers animate.
So yeah, I'm not sure if I need to amend this script so it can accommodate for the comma in the data attribute or if there is something else I might need to do after the fact?
Ok, so after digging through it a bit more, I was able to come up with a solution.
I found this:
$.fn.digits = function(){
return this.each(function(){
$(this).text( $(this).text().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") );
})
}
and then added an addtional class in my HTML.
I then hooked into the complete:function and added:
$(".class-i-added").digits();
to the end of the animation.
Overall, that appears to provide the result that I am looking for.
Since I only need to attribute it to one number (so far) it works as it should.
I have several files I'm pulling minor text from (a single word most), and then stylizing that with another script.
Currently they load and display as they should. However, the text files update at random times, so I'd like them to be reloaded, and the subsequent script applied to them again.
I've tried different setTimeout as well as setInterval commands, but I think the issue is my placement or use. After several hours of research I'm certain it's just the syntax that's out of place.
This runs locally but is pulled through a program that excecutes the script as if remote. (no cross domain issues)
Here's one example segment that pulls a file and loads to the html the subsequent script reads to display:
$(function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
$("#follow").append(data).serialize();
},
setTimeout(fuction(){
follow_pull()
}, 10000);
});
});
Here's the segment that loads those files into the script to display:
$(window).ready(function ledload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount:650,
verticalPixelsCount:5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor : '#020202',
enabledPixelColor: '#ff522b'
};
$('.canvasld, .crl').leddisplay($.extend(options, {pixelSize: 3}));
},
setTimeout(fuction(){
ledload()
}, 10000););
Any direction is appreciated. I can post the entire file if need by, but I figured someone would get what I'm doing and know how to direct me best.
For context I'm using a script that takes the text, and makes it look like an LED and scrolls as if it's a ticker. This is being used for a broadcaster on Twitch.
So reviewing what you provided in your comment, I found a way to get it working.
First, is the html below. Here are the differences:
I created a new element <div class="led"></div>. I also gave the .crl css to that element, and instead made .crl have display: none. This is because the .leddisplay function takes the element and replaces it with it's own HTML to render the LEDs. So you need to keep the div you are using to store your info separate from the div you are using to render it. (I would recommend just using JS variables to store that info, but I'm not trying to rewrite your code, just trying to get it working.)
But then how do you get the text into the LED display? With .leddisplay you can input the text you want as the second parameter of the function. You can see how I did that in postload().
To update your info, you were using append(). This adds to the divs, but you want to update them, so I replaced every .append() with .text() to replace the text rather than add on to it.
Finally, the heart of the solution. The leddisplay plugin doesn't have a way to update the led. So you have to 'destroy' it, and then rerun it, as I have done in the setTimeout() of postload(). But by itself, starts the scrolling all over again every 10 seconds. So what I do is track the current position, then after rerunning it, I resume the scrolling from there. However to make that work, I needed to update the plugin code. Below the HTML is the explanation for that.
HTML:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<style>
.led {
padding-top: 2px;
padding-bottom: 2px;
background-color: #444;
}
.crl {
display: none;
}
</style>
<div class="top-bar"></div>
<div class="crl">Newest Subscriber - <span id="sub"></span>
LAST DONATION - <span id="donation"></span>
LATEST BITS - <span id="bits"></span>
rECENT FOLLOWEr - <span id="follow"></span>
Sub Goal - <span id="subgoal"></span> / 80</div>
<div class="led"></div>
<div class="bottom-bar"></div>
<script type="text/javascript">
$.ajaxSetup({
async: false,
cache: false
});
$(function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#follow").text(data);
setTimeout(function(){
follow_pull()
}, 10000);
},
});
});
$(function donator_pull() {
$.ajax({
url : "most_recent_donator.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#donation").text(data);
setTimeout(function(){
donator_pull()
}, 10000);
},
});
});
$(function cheerer_pull() {
$.ajax({
url : "most_recent_cheerer.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#bits").text(data);
setTimeout(function(){
cheerer_pull()
}, 10000);
},
});
});
$(function subscriber_pull() {
$.ajax({
url : "most_recent_subscriber.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#sub").text(data);
setTimeout(function(){
subscriber_pull()
}, 10000);
},
});
});
$(function count_pull() {
$.ajax({
url : "total_subscriber_count.txt",
dataType: "text",
success : function (data) {
console.log(data);
$("#subgoal").text(data);
setTimeout(function(){
count_pull()
}, 10000);
},
});
});
$(function ledload() {
$.getScript( "ticker/jquery.leddisplay.js", function( data, textStatus, jqxhr ) {
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
});
});
$(function postload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount:650,
verticalPixelsCount:5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor : '#020202',
enabledPixelColor: '#ff522b'
};
$(".led").leddisplay($.extend(options, {
pixelSize: 3
}), $('.crl').text());
setTimeout(function () {
//get the current position
var x = $(".led").leddisplay('getCurrentPosition')
//destroy the led setup
$('.led').leddisplay('destroy');
//create it again
postload();
//set the position to where it left off at
$(".led").leddisplay('setCurrentPosition', x)
}, 10000);
});
</script>
Inside the plugin, look for customMethods towards the bottom. I added 2 more methods to it: getCurrentPosition and setCurrentPosition, so it should look like this:
jquery.leddisplay.js, customMethods:
var customMethods = {
init: function(){
var _arg = arguments;
return this.each(function() {
var $this = $(this);
if ($this.data('leddisplay'))
return;
$this.data('leddisplay', true);
var methods = resolveMethods(this);
methods.init.apply($this, _arg);
});
},
destroy: function(){
var _arg = arguments;
return this.each(function() {
var $this = $(this);
if (!$this.data('leddisplay'))
return;
$this.data('leddisplay', null);
var methods = resolveMethods(this);
methods.destroy.apply($this, _arg);
});
},
start: function(){
},
stop: function(){
},
getCurrentPosition: function(){
return $(this).data('currentPosition');
},
setCurrentPosition: function(x){
$(this).data('currentPosition', x);
}
}
After you make these changes, it should work as expected.
First I'd pull ledload() out of the $window.ready(). This way, it can be referenced by it's name. Also, I'm pretty sure you don't need the $(...) wrapper for the follow_pull() function...
function ledload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount:650,
verticalPixelsCount:5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor : '#020202',
enabledPixelColor: '#ff522b'
};
$('.canvasld, .crl').leddisplay($.extend(options, {pixelSize: 3}));
}
function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
$("#follow").append(data).serialize();
ledload();
setTimeout(function(){
follow_pull();
}, 10000);
}
});
};
follow_pull() calls ledload() when it successfully gets the data. Then it sets up a 10 second delay before it does it all over again.
If you still wanted ledload to run on $(window).ready(), you can add this line as well:
$(window).ready(ledload);
P.S. I don't see what .serialize() is doing...Is that supposed to get passed into ledload()?
You're on the right track, but you need to move the setTimeouts slightly, like so:
$(function follow_pull() {
$.ajax({
url : "most_recent_follower.txt",
dataType: "text",
success : function (data) {
$("#follow").append(data).serialize();
setTimeout(fuction(){
follow_pull()
}, 10000);
},
});
});
This way, once the data has successfully loaded, it will call follow_pull again after 10 seconds.
For the other bit, you need to move it like so:
$(window).ready(function ledload() {
var options = {
pixelSize: 5,
stepDelay: 62,
horizontalPixelsCount: 650,
verticalPixelsCount: 5,
pixelRatio: 0.8,
pathToPixelImage: 'ticker/pixel.png',
backgroundColor: '#000',
disabledPixelColor: '#020202',
enabledPixelColor: '#ff522b'
};
$('.canvasld, .crl').leddisplay($.extend(options, {
pixelSize: 3
}));
setTimeout(fuction() {
ledload()
}, 10000);
});
The AJAX ready function only takes one argument, but you were passing the setTimeout as a second argument, so it was being ignored.
This is a jquery code that performs a database update when the user modifies a cell:
$( document ).ready(function() {
$('tr').on('blur', 'td[contenteditable]', function() {
$.post("ajax/modQtyModels", {
modelId: $(this).closest('tr').children('td.idmodel').text(),
qty: $(this).closest('tr').children('td.editQty').text(),
ajax: true,
success: function(data) {
$(this).closest('tr').children('td.editQty').addClass("success");
}
});
});
});
In the "success" part I want it to just change the class (to change its color as it uses bootstrap) of that cell to show the user that their data changed successfully but it doesn't seem to notice that it has to change the color. I've tried everything on that line but I guess the line is not the problem. Other actions like an alert work well so I suspect of the $(this).
In the success callback you are dealing with another function, so the scope is no longer the one of your blur event callback, so this keyword will point out to another object and not your jQuery element.
So you need to save the this value in another variable and refer to your element with this neww variable, inside the success callback.
(document).ready(function() {
$('tr').on('blur', 'td[contenteditable]', function() {
var tr = $(this);
$.post("ajax/modQtyModels", {
modelId: $(this).closest('tr').children('td.idmodel').text(),
qty: $(this).closest('tr').children('td.editQty').text(),
ajax: true,
success: function(data) {
tr.closest('tr').children('td.editQty').addClass("success");
}
});
});
});
this inside of success: function(data) { does not refer to this inside of $('tr').on('blur'
You can save the value of this (typically in a variable called that), so that when you are in that new function, you can do:
$( document ).ready(function() {
$('tr').on('blur', 'td[contenteditable]', function() {
var that = this;
$.post("ajax/modQtyModels", {
modelId: $(this).closest('tr').children('td.idmodel').text(),
qty: $(this).closest('tr').children('td.editQty').text(),
ajax: true,
success: function(data) {
$(that).closest('tr').children('td.editQty').addClass("success");
}
});
});
});
I need to have a vertical slider input. Since this is not possible with the built-in sliderInput function, I opted to implement it myself.
According to this thread it is either possible to (I) rotate the sliderInput widget using CSS or (II) use a common slider and implement the capability to interact with Shiny.
I decided to go for option (II) because (I) did not work out the way I wanted.
I followed this article in order to implement a custom verticalSlider function
verticalSlider <- function(inputId, min, max, value) {
tagList(
singleton(tags$head(tags$link(rel = "stylesheet", type = "text/css", href = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.8.1/css/bootstrap-slider.min.css"))),
singleton(tags$head(tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.8.1/bootstrap-slider.min.js"))),
singleton(tags$head(tags$link(rel = "stylesheet", type = "text/css", href = "css/verticalSlider.css"))),
singleton(tags$head(tags$script(src = "js/verticalSlider.js"))),
tags$input(id = inputId,
class = "verticalSlider",
type = "text",
value = "",
`data-slider-min` = as.character(min),
`data-slider-max` = as.character(max),
`data-slider-step` = as.character(1),
`data-slider-value` = as.character(min),
`data-slider-orientation` = "vertical"
)
)
}
I implemented the input binding and initialized the slider in "js/verticalSlider.js".
$(function() {
$('.verticalSlider').each(function() {
$(this).slider({
reversed : true,
handle : 'square',
change: function(event, ui){}
});
});
});
var verticalSliderBinding = new Shiny.InputBinding();
$.extend(verticalSliderBinding, {
find: function(scope) {
return $(scope).find(".verticalSlider");
},
getValue: function(el) {
return $(el).value;
},
setValue: function(el, val) {
$(el).value = val;
},
subscribe: function(el, callback) {
$(el).on("change.verticalSliderBinding", function(e) {
callback();
});
},
unsubscribe: function(el) {
$(el).off(".verticalSliderBinding");
},
getRatePolicy: function() {
return {
policy: 'debounce',
delay: 150
};
}
});
Shiny.inputBindings.register(verticalSliderBinding, "shiny.verticalSlider");
So far so good. The subscribe function is called everytime I move the slider's knob.
Moving the handle has no effect when the slider's value is bound to a textOutput however.
Shiny's "reactiveness" does not seem to work for my custom component. Could someone point me in the right direction?
Hi according to bootstrap-slider readme, you should rewrite getValue and setValue methods in your bindings :
getValue: function(el) {
return $(el).slider('getValue');
},
setValue: function(el, val) {
$(el).slider('setValue', val);
}
I think setValue is only used if you define an update method.
I have a large HTML form that contains many fields that need an autocomplete for accounts. I tag these fields with the class AccountLookup and jQuery does the dirty work for the autocomplete:
$(".AccountLookup").autocomplete({
source: function (request, response) {
$.ajax({
url: "Lookup.asmx/GetAccounts",
data: "{ 'Search': '" + request.term + "' }",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data.d, function (item) {
return {
value: item.Value
}
}))
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
},
minLength: 3
});
Now, when a user selects something from the autocomplete I need it to populate a hidden field just BEFORE the tagged input field; probably using something like:
$(this).prev().val(item.Key);
How do I incorporate this functionality? Also, how do I force a user to select from the auto complete? (All the values are pre-defined, the user cannot add new ones.)
EDIT:
As far as I understand from inspecting the DOM, the select option is currently filling in the hidden form field.
select: function (event, ui) {
$(this).prev().val(ui.item.key);
}
I know this is an old post--- but I ran into it in trying to solve a similar problem (forcing the user to select an item from the list)...
$("#ac").autocomplete({
source: function (req, resp) {
//add code here...
},
select: function (e, ui) {
$(this).next().val(ui.item.id);
},
change: function (ev, ui) {
if (!ui.item)
$(this).val("");
}
});
$(".AccountLookup").autocomplete({
/*...*/
}).result(function(event, item) {
$(this).prev().val(item.Key);
});
You could also use a jQuery validate to ensure that the field is populated.
for force selection, you can use "change" event of Autocomplete
var availableTags = [
"ActionScript",
"AppleScript"
];
$("#tags").autocomplete({
source: availableTags,
change: function (event, ui) {
if(!ui.item){
//http://api.jqueryui.com/autocomplete/#event-change -
// The item selected from the menu, if any. Otherwise the property is null
//so clear the item for force selection
$("#tags").val("");
}
}
});
For the selection action, try using the formatItem option. You can format each result to have an onclick event that will populate the other textbox.
For the forcing to select from autocomplete, you need to use the mustMatch option.
http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
I ran into this same problem quite awhile ago and some post helped me along with it. I have since modified the code as I found that there were cases I wanted one or more fields to fill in from the information returned. In the select option of the autocomplete I added a function.
select: function (e, ui) {ReSetField({'txtID':'id','txtPrice':'price' [,etc...]}, ui) }
The function "ResetFields" then takes in a JSON list of element names paired with fieldnames and uses the fieldnames to match the elements in the ui object. The value can then be pulled from the ui item and put into the html element.
function ReSetField(_flds, _vals) {
//Set up the flds to be reset with values passed in.
try {
if (_flds != undefined) {
if ($.type(_flds) == 'string') {
_flds = JSON.parse(_flds);
};
var _fld = null;
var _val = '';
$.each(_flds, function (index) {
if (index.length > 0) {
_fld = '#' + index; //Set the forms field name to set
_val = _flds[index]; //Pick up the field name to set the fields value
$fld = $(_fld);
$fld.val(_vals.item[_val]); //Set the fields value to the returned value
}
}
})
};
}
catch (e) {
alert('Cannot set field ' + _fld + '.');
}
}
By sticking the "fieldlist" into the HTML element as an attribute like "fieldlist" and using a class like "comboBox" I can then use a single function to find all ComboBox elements and set up the autocomplete on a form reducing the amount of code required to handle 2 or more lookups on a form.