How to get multiple sliders to work with java script/html/jquery - javascript

I'm currently working on a site that hosts podcasts. I have it so the podcasts plays, but I can only get very first podcast volume slider to work; the second podcast's sliders moves, but doesn't change the volume at all. Each player has a "player" id that is used to identify it. I've everything else and am stuck on this one little bug. Any help would be appreciated. Here is the javascript that creates the sliders and tries to links them to each player:
<script>
audiojs.events.ready(function()
{
var as = audiojs.createAll();
$('.slider').each(function()
{
var slider = $('.slider'),
tooltip = $('.tooltip'),
audioList = document.getElementsByTagName("audio").length;
console.log(audioList)
tooltip.hide();
slider.slider(
{
range: "min",
min: 0,
max: 100,
value: 50,
change: function()
{
for (var i = 0; i <= as.length; i++)
{
//console.log(i)
var value = $(".slider").slider("value");
document.getElementById("player").volume = (value / 100);
};
},
start:function(event,ui)
{
tooltip.fadeIn('fast');
},
slide: function(event, ui)
{
var volume = $('.volume'),
value = $(".slider").slider("value");
document.getElementById("player").volume = (value / 100);
tooltip.css('left',value / 2).text(ui.value);
if(value <= 5)
{
volume.css('background-position', '0 0');
}
else if (value <= 25)
{
volume.css('background-position', '0 -25px');
}
else if (value <= 75)
{
volume.css('background-position', '0 -50px');
}
else
{
volume.css('background-position', '0 -75px');
};
},
stop:function(event,ui)
{
tooltip.fadeOut('fast');
},});});}); </script>

Related

jQuery UI Slider Missing BG

I'm using a range slider with jQuery UI but when I move the slider, the background line does not show up so it's hard to tell where it is at. How do I highlight the background line only for the selected portion?
jsfiddle is below.
https://jsfiddle.net/zbmt5qrn/
/* INTEREST RATE SLIDER */
$("#interestRange").slider({
min: 0,
max: 100,
step: 1,
values: [10],
slide: function(event, ui) {
for (var i = 0; i < ui.values.length; ++i) {
$("input.interestValue[data-index=" + i + "]").val(ui.values[i]);
}
}
});
$("input.interestValue").change(function() {
var $this = $(this);
$("#interestValue").slider("values", $this.data("index"), $this.val());
});
function handleInterestChange(input) {
if (input.value < 0) input.value = 0;
if (input.value > 24) input.value = 24;
}
var items =[ '8%','24%'];
var oneBig = 100 / (items.length - 1);
$.each(items, function(key,value){
var w = oneBig;
if(key === 0 || key === items.length-1)
w = oneBig/2;
$("#interestLabel").append("<label style='width: "+w+"%'>"+value+"</laben>");
});
I am removing the code about '8%/24%' because it does not seem to be relevant to this question.
There are a couple ways to set the background. You could insert a new element inside #interestRange and change its width based on the slider value. But if you do not need to worry about supporting outdated browsers, it would be much easier to use apply a linear-gradient to the background of #interestRange.
const sliderMin = 0
const sliderMax = 100
const sliderDefaultValue = 10
function setSliderBackground(value){
const sliderRange = sliderMax - sliderMin
const sliderPercent = Math.floor(100 * (value / sliderRange))
$("#interestRange").css({
background: `linear-gradient(90deg, #0000ff ${sliderPercent}%, #ffffff ${sliderPercent}%)`
})
}
function setSliderValue(value){
$("#interestRange").slider("value", value);
}
function setInputValue(value){
$("#interestValue").val(value)
}
$(document).ready(()=>{
$("#interestRange").slider({
min: sliderMin,
max: sliderMax,
step: 1,
// Handle when the user moves the slider
slide: (event, ui)=>{
const sliderValue = ui.value
setInputValue(sliderValue)
setSliderBackground(sliderValue)
}
})
// Handle when the user types in a value
$("#interestValue").change(()=>{
const typedValue = $("#interestValue").val()
setSliderValue(typedValue)
setSliderBackground(typedValue)
})
// Stuff to do when the page loads
setSliderValue(sliderDefaultValue)
setInputValue(sliderDefaultValue)
setSliderBackground(sliderDefaultValue)
})
<link href="https://code.jquery.com/ui/1.12.0-rc.2/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<p>Interest Rate:</p>
<div>
<div id="interestRange"></div>
<div id="interestLabel"></div>
</div>
<div>
<input type="number" id="interestValue" />
</div>

Phaser Game Development - Movement with arrows too fast in Menu

I am testing Phaser doing a simple spaceships game. I have configured some states (boot, load, menu and levelOne) for the game and his functionality.
On the menú I have 3 options in gray color (start, continue and credits), I keep a var called selected to mark which menu is selected (1, 2 or 3). When I press the Up arrow I set selected - 1, and down arrow selected + 1, in the way to navigate between options. It works perfect, but its impossible to select an option because of the change speed, see it yourself: Spaceships
JS code of the menu:
var title = ""
var starfield = null
var selected = 1;
var cursores = null;
var menuOptions = {
start: {title: "Empezar partida", variable: null},
continue: {title: "Continuar partida", variable: null},
credits: {title: "Creditos", variable: null}
}
var menuState = {
downMenu: function(){
selected += 1
console.log(selected)
if(selected>=4){
selected = 1
}
},
upMenu: function(){
selected -= 1
console.log(selected)
if(selected<=0){
selected = 4
}
},
preload: function(){
var me = this;
//console.log('preload')
space.load.bitmapFont('titleFont', 'assets/Fonts/title.png', 'assets/Fonts/title.fnt');
space.load.bitmapFont('menuFont', 'assets/Fonts/menuFont.png', 'assets/Fonts/menuFont.fnt');
space.load.image('background', 'assets/Backgrounds/menuStarfield.png')
},
create: function(){
//console.log('create')
starfield = space.add.image(0, 0, 'background')
space.stage.backgroundColor = '#000000'
title = space.add.bitmapText(50, 50, 'titleFont', 'Deviant Spaceships!', 64);
menuOptions.start.variable = createText(150, menuOptions.start.title)
menuOptions.continue.variable = createText(225, menuOptions.continue.title)
menuOptions.credits.variable = createText(300, menuOptions.credits.title)
cursores = space.input.keyboard.createCursorKeys()
//cursores.onDown.addOnce(this.changeMenu, this)
},
update: function(){
title.text = 'Oh No! Spaceships! \n';
if(cursores.down.isDown){
this.downMenu()
}
if(cursores.up.isDown){
this.upMenu()
}
if(selected == 1){
//menuOptions.start.variable.text = "-> "+menuOptions.start.variable.text
menuOptions.start.variable.fill = '#FFFFFF'
}else{
menuOptions.start.variable.fill = '#999999'
}
if(selected == 2){
//menuOptions.start.variable.text = "-> "+menuOptions.start.variable.text
menuOptions.continue.variable.fill = '#FFFFFF'
}else{
menuOptions.continue.variable.fill = '#999999'
}
if(selected == 3){
//menuOptions.start.variable.text = "-> "+menuOptions.start.variable.text
menuOptions.credits.variable.fill = '#FFFFFF'
}else{
menuOptions.credits.variable.fill = '#999999'
}
menuOptions.continue.variable.text = menuOptions.continue.title
menuOptions.credits.variable.text = menuOptions.credits.title
starfield.x -= 2
if(starfield.x <= -1026){
starfield.x = 0
}
}
}
function createText(y, texto) {
var text = space.add.text(space.world.centerX, y, texto);
text.anchor.set(0.5);
text.align = 'center';
// Font style
text.font = 'Arial Black';
text.fontSize = 50;
text.fontWeight = 'bold';
text.fill = '#999999';
return text;
}
¿How can I take the menu items selected one by one? Is there a way to stop the key being pressed in code every time I add or deduct the selected var?
I had the same problem a couple a weeks ago and I didn't find a nice solution, so I finally made a not very elegant hack... I allow to change the menu just once every a little time (200ms). I'm sure there will be a nicer solution but something like this is what I'm using(check the console):
var game = new Phaser.Game(500, 500, Phaser.CANVAS, 'game');
var selected = 1;
var menuState = {
create:function(){
cursores = game.input.keyboard.createCursorKeys();
this.cambia_menu = this.time.now + 200;
},
downMenu: function(){
selected += 1
console.log(selected)
if(selected>=4){
selected = 1
}
},
upMenu: function(){
selected -= 1
console.log(selected)
if(selected<=0){
selected = 4
}
},
update:function(){
if(cursores.down.isDown && this.cambia_menu<this.time.now){
this.cambia_menu = this.time.now + 200;
this.downMenu();
}
if(cursores.up.isDown && this.cambia_menu<this.time.now){
this.cambia_menu = this.time.now + 200;
this.upMenu();
}
},
};
game.state.add('menu', menuState);
game.state.start('menu');
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/2.4.4/phaser.min.js"></script>
<div id="game"></div>

jQuery addClass to multiple elements shows an unexpected delay

I'm making a flipping counter which is supposed to change color when reaching the target number (1000 in the example). But the thing is the different parts of the counter doesn't change color at the same time, we can clearly see a delay between the tiles that make up the counter...
I'm using a simple jQuery addClass to trigger the color change:
$("#rhcounter .count").addClass("red");
Any ideas what could be causing that ?
Here is the fiddle: http://jsfiddle.net/ka6ke28m/6/
Thanks for your help !
First issue:
There was a huge amount of wasted processing going on. jQuery selectors have an overhead so reduce them to a minimum and complex selectors more-so. I have reduced that considerably.
Second issue:
There is a nasty visual glitch on some browsers that looked like this:
Which you can eliminate by using background-color: instead of background: (which tries to completely re-render the area instead of just fill the background colour).
Third issue:
The color blue left behind was down to slow repainting of the screen. The above two fixes had a huge impact and I also tried adding specific CSS animations that worked only with the red class. This can probably be improved now you know the causes of the slow painting (e.g. have blue and red CSS animation?):
http://jsfiddle.net/TrueBlueAussie/ka6ke28m/10/
$(function () {
var total = 1000,
current = 950,
timeout = 150,
inc = 7,
prevTiles = ["0", "0", "0", "0"],
interval = setInterval(function () {
increase()
}, timeout),
increase = function () {
current += inc;
if (current >= total) {
clearInterval(interval);
current = total;
}
if (current === total) {
$("#rhcounter .count").addClass("red");
}
// instant timer to delay css
setTimeout(function () {
var tiles = [false, false, false, false],
currStr = (current + "").split("").reverse().join("");
for (var i = 0; i < currStr.length; i++) {
if (currStr[i] !== prevTiles[i]) {
tiles[i] = true;
prevTiles[i] = currStr[i];
}
}
tiles.forEach(function (tile, index) {
if (!tile) {
return;
}
// Get the current tile
var $tile = $("#rhcounter div.tile" + index);
$tile.children('span.curr').each(function () {
$(this).text($tile.text());
});
$tile.removeClass("flip");
setTimeout(function () {
$tile.addClass("flip");
}, 5);
var top = $tile.find("span.count.next.top"),
bottom = $tile.find("span.count.next.bottom"),
delay = (index === 0 ? timeout : 250);
setTimeout(function () {
top.text(prevTiles[index]);
}, delay / 2);
setTimeout(function () {
bottom.text(prevTiles[index]);
}, delay / 2);
});
}, 1);
};
});
that was happening because you were changing color before changing text. i just shifted if condition and i think that is what you wanted DEMO
$(window).load(function() {
var total = 1000, current = 950, timeout = 150, inc = 7,
prevTiles = ["0","0","0","0"],
interval = setInterval(function(){increase()}, timeout),
increase = function () {
current += inc;
if (current >= total) {
clearInterval(interval);
current = total;
}
var tiles = [false, false, false, false],
currStr = (current+"").split("").reverse().join("");
for (var i = 0; i < currStr.length; i++) {
if (currStr[i] !== prevTiles[i]) {
tiles[i] = true;
prevTiles[i] = currStr[i];
}
}
tiles.forEach(function (tile, index) {
if (!tile) { return; }
$("#rhcounter > div[class~='tile"+index+"'] > span[class~='curr']").each(function() {
$(this).text($("#rhcounter > div[class~='tile"+index+"'] > span.count.next.top").text());
});
$("#rhcounter > div[class~='tile"+index+"']").removeClass("flip");
setTimeout(function(){$("#rhcounter > div[class~='tile"+index+"']").addClass("flip");}, 5);
var top = $("#rhcounter > div[class~='tile"+index+"'] > span.count.next.top"),
bottom = $("#rhcounter > div[class~='tile"+index+"'] > span.count.next.bottom"),
delay = (index === 0 ? timeout : 250);
setTimeout(function(){ top.text(prevTiles[index]); }, delay/2);
setTimeout(function(){ bottom.text(prevTiles[index]); }, delay/2);
});
if (current === total) {
$("#rhcounter .count").addClass("red");
}};
});

Jquery ui slider move to the next value

Here's a sample image of what i'm trying to accomplish
Say I click from 150 value the handle should only move to 50 and not jump to 150. I click again it move from 50 to 100.
The other way around, say the handle is on value 150 then i click on value 5, it should not jump directly to 5 it should move from 150 to 100.
How can I do that?
Here's my code:
var valMap = [5, 10, 20, 50, 100, 150];
value = 0;
var slider = $("#slider").slider({
disabled: false,
animate: true,
min: 0,
max: valMap.length - 1,
slide: function (event, ui) {
slider.slider("option", "animate", "slow");
},
change: function () {
var Slideval = $(this).slider('value');
console.log(Slideval, value)
if(value < Slideval) {
console.log("incremented")
} else if(value > Slideval) {
console.log("decremented")
}
value = Slideval;
}
});
Here's a sample jsfiddle: http://jsfiddle.net/endl3ss/jNwww/21/
I don't know the slider too much, but here is a working solution based on your specification:
http://jsfiddle.net/5xMMz/11/
and here is the full code for reference
var valMap = [5, 10, 20, 50, 100, 150,500,1000,5000];
value= 0;
var lastSlideValue = 0;
var internalSlideCalling = false;
var slider = $("#slider").slider({
disabled : false,
animate : true,
min : 0,
max : valMap.length - 1,
slide : function(event, ui) {
slider.slider("option", "animate", "slow");
},
change: function(){
var Slideval = $(this).slider('value');
if (!internalSlideCalling)
{
if (Slideval>lastSlideValue && lastSlideValue < $(this).slider('option','max'))
{
Slideval = lastSlideValue+1;
}
else if (lastSlideValue > $(this).slider('option','min'))
{
Slideval = lastSlideValue-1;
}
lastSlideValue = Slideval;
}
console.log(Slideval, value)
if(value < Slideval) {
console.log("incremented")
} else if(value > Slideval){
console.log("decremented")
}
value = Slideval;
if (!internalSlideCalling){
internalSlideCalling = true;
$(this).slider('value',Slideval);
}
else
internalSlideCalling = false;
}
});
$("#slider").slider('values',valMap);
Then you can use event which will raise when we move slider and then set the value for slider.We can manually set the slider value.
This is event code
slide: function( event, ui ) {
// code
},
$('#id').slider("value",value); //using this we can set the slider value
Use
$("#slider").slider({
step: 50
})
Here is the link for more information - http://jqueryui.com/slider/#steps

Looking for thoughts on improvement of my javascript (jquery) code. Recursive function

I have made this code that makes some visual "tiles" that fades in and out.
But at the moment I'm having a little performance problem.
Though most browers are running the code okay (especially firefox), some like safari have problems after a while (a while = like 15 seconds).
I think its due to my recursive function (the function named changeopacity that calls itself forever on a delay)? or is it?
But anyways the problem is that this code is really heavy for most browsers. Is there, or more how can I make this code perform any better? any thoughts? (code examples would be nice) thanks :-)
The actual code:
$(document).ready(function () {
var aniduration = 2000;
var tilesize = 40;
createtable(tilesize);
$(".tile").each(function (index, domEle) {
var randomdelay = Math.floor(Math.random() * 3000);
setTimeout(function () {
changeopacity(aniduration, domEle);
}, randomdelay);
});
$("td").click(function () {
clickanimation(this, 9);
});
$("td").mouseenter(function () {
var element = $(this).find("div");
$(element).clearQueue().stop();
$(element).animate({opacity: "0.6"}, 800);
});
$("td").css("width", tilesize + "px").css("height", tilesize + "px");
});
function createtable(tilesize) {
var winwidth = $(window).width();
var winheight = $(window).height();
var horztiles = winwidth / tilesize;
var verttiles = winheight / tilesize;
for (var y = 0; y < verttiles; y++)
{
var id = "y" + y;
$("#tbl").append("<tr id='" + id + "'></tr>");
for (var x = 0; x < horztiles; x++)
{
$("#" + id).append("<td><div class='tile' style='opacity: 0; width: " + tilesize + "px; height: " + tilesize + "px;'></div></td>");
}
}
}
function changeopacity(duration, element){
var randomnum = Math.floor(Math.random() * 13);
var randomopacity = Math.floor(Math.random() * 7);
var randomdelay = Math.floor(Math.random() * 1000);
if ($(element).css("opacity") < 0.3)
{
if (randomnum != 4)
{
if ($(element).css("opacity") != 0)
animation(element, 0, duration, randomdelay);
}
else
{
animation(element, randomopacity, duration, randomdelay);
}
}
else
{
animation(element, randomopacity, duration, randomdelay);
}
setTimeout(function () {
return changeopacity(duration, element);
}, duration + randomdelay);
}
function animation(element, randomopacity, duration, randomdelay){
$(element).clearQueue().stop().delay(randomdelay).animate({opacity: "0." + randomopacity}, duration);
}
function clickanimation(column, opacitylevel) {
var element = $(column).find("div");
$(element).clearQueue().stop();
$(element).animate({"background-color": "white"}, 200);
$(element).animate({opacity: "0." + opacitylevel}, 200);
$(element).delay(200).animate({opacity: "0.0"}, 500);
//$(element).delay(600).animate({"background-color": "black"}, 500);
}
The number one issue is that you are creating one setTimeout for every single cell on your page. The only browser capable of handling that is Internet Explorer, and then it fails due to the many CSS changes causing slow redraws.
I would strongly suggest programming your own event scheduler. Something like this, which I used in a university project:
var timer = {
length: 0,
stack: {},
timer: null,
id: 0,
add: function(f,d) {
timer.id++;
timer.stack[timer.id] = {f: f, d: d, r: 0};
timer.length++;
if( timer.timer == null) timer.timer = setInterval(timer.run,50);
return timer.id;
},
addInterval: function(f,d) {
timer.id++;
timer.stack[timer.id] = {f: f, d: d, r: d};
timer.length++;
if( timer.timer == null) timer.timer = setInterval(timer.run,50);
return timer.id;
},
remove: function(id) {
if( id && timer.stack[id]) {
delete timer.stack[id];
timer.length--;
if( timer.length == 0) {
clearInterval(timer.timer);
timer.timer = null;
}
}
},
run: function() {
var x;
for( x in timer.stack) {
if( !timer.stack.hasOwnProperty(x)) continue;
timer.stack[x].d -= 50;
if( timer.stack[x].d <= 0) {
timer.stack[x].f();
if( timer.stack[x]) {
if( timer.stack[x].r == 0)
timer.remove(x);
else
timer.stack[x].d = timer.stack[x].r;
}
}
}
}
};
Then, instead of using setTimeout, call timer.add with the same arguments. Similarly, instead of setInterval you can call timer.addInterval.
This will allow you to have as many timers as you like, and they will all run off a single setInterval, causing much less issues for the browser.
Nice animation :-) However, I found some bugs and possible improvements:
Your table is not rebuilt on window resizes. Not sure if bug or feature :-)
Use delegated events. You have a lot of elements, and every event handler is costly. Sadly, this won't work for the non-bubbling mouseenter event.
It would be nice if you would not use inline styles for with and height - those don't change. For the divs, they are superflouos anyway.
I can't see a reason for all those elements to have ids. The html-string building might be more concise.
Cache the elements!!! You are using the jQuery constructor on nearly every variable, building a new instance. Just reuse them!
Your changeopacity function looks a bit odd. If the opacity is lower than 0.3, there is 1-in-13-chance to animate to zero? That might be expressed more stringent. You also might cache the opacity to a variable instead of reading it from the dom each time.
There is no reason to pass the duration and other constants as arguments, they do never change and can be used from the global scope.
Instead of using the timeout, you should use the complete callback of the animate method. Timeouts are never accurate, they may even interfere here causing (minor) problems.
var duration = 2000,
tilesize = 40,
clickopacity = 0.9;
$(document).ready(function () {
filltable($("#tbl"), tilesize)
.on("click", "td", clickanimation);
$(".tile").each(function() {
changeopacity($(this));
});
$("#tbl div").mouseenter(function () {
$(this).clearQueue()
.stop()
.animate({opacity: "0.6"}, 800);
});
});
function filltable(tbl, tilesize) {
var win = $(window).width();
var horztiles = win.width() / tilesize;
var verttiles = win.height() / tilesize;
for (var y = 0; y < verttiles; y++) {
var tr = "<tr>";
for (var x = 0; x < horztiles; x++)
tr += "<td style='width:"+tilesize+"px;height:"+tilesize+"px;'><div class='tile' style='opacity:0;'></div></td>");
tbl.append(tr+"</tr>");
}
return tbl;
}
function changeopacity(element) {
var random = Math.floor(Math.random() * 13);
var opacity = Math.floor(Math.random() * 7);
var delay = Math.floor(Math.random() * 1000);
if (element.css("opacity") < 0.3 && random != 4)
opacity = 0;
element.clearQueue().stop().delay(delay).animate({
opacity: "0." + opacity
}, duration, function() {
changeopacity(element);
});
}
function clickanimation() {
$(this.firstChild)
.clearQueue()
.stop()
.animate({"background-color": "white"}, 200)
.animate({opacity: "0." + clickopacity}, 200)
.delay(200).animate({opacity: "0.0"}, 500);
//.delay(600)
//.animate({"background-color": "black"}, 500);
}

Categories