So I have a Javascript function that is part of web game I'm creating. It is supposed to act as the speed selector for an object in the game. Selecting the div that says "slow" is supposed to change the object's speed to slow, and so forth. When the page is loaded, the "med" div is selected. For now, I just want to figure out why my attempt at putting a border around the currently selected speed div is not working. The code below is, hopefully, self-explanatory. (Here's a link to the game, if that helps: http://jaminweb.com/snake_TEST_PHP.php)
I'm not getting any errors in my Javascript console and I've tested (using an alert(...)) to make sure the onlick functions are being called for each of the 3 divs when I click on them.
Any help greatly appreciated.
Relevant pieces of code:
function speedController(slowButtonID, medButtonID, fastButtonID, sg)
{
/*
slowButtonID, medButtonID, fastButtonID: IDs of the buttons for slow, medium and fast, respectively
sg: Snake game object
*/
this.spdMap = {"slow" : [slowButtonID, 200], "med" : [medButtonID, 100], "fast" : [fastButtonID , 50]};
this.curSpd = "med";
this.changeSpeed = function(newSpd)
{
/*
newSpd: one of "slow", "med" or "fast"
*/
/* Do nothing if selecting same speed as current */
if (newSpd == this.curSpd)
return;
/* Else, remove border from currently selected speed button
and add border to newly selected speed button, then
change the speed of the snake's mover.
*/
$("#"+this.spdMap[this.curSpd[0]]).css("border: 0px;");
$("#"+this.spdMap[newSpd[0]]).css("border: 4px solid #3D4048;");
sg.mover = setInterval(sg.move(), this.spdMap[newSpd[1]]);
}
}
<div id="snakeSpdDiv">
<p><b>Speed:</b></p>
<div class="snakeSpdBtn" id="snakeSpdSlow">Slow</div>
<div class="snakeSpdBtn" id="snakeSpdMed" style="border: 4px solid #3D4048;">Med</div>
<div class="snakeSpdBtn" id="snakeSpdFast" onlick=>Fast</div>
<script type="text/javascript">
var sc = new speedController("snakeSpdSlow", "snakeSpdMed", "snakeSpdFast", s);
$("#snakeSpdSlow").click(function()
{
sc.changeSpeed("slow");
});
$("#snakeSpdMed").click(function()
{
sc.changeSpeed("med");
});
$("#snakeSpdFast").click(function()
{
sc.changeSpeed("fast");
});
</script>
</div>
The problem is with this part:
$("#"+this.spdMap[this.curSpd[0]]).css("border: 0px;");
$("#"+this.spdMap[newSpd[0]]).css("border: 4px solid #3D4048;");
It should be:
$("#"+this.spdMap[this.curSpd][0]).css("border", "0px");
$("#"+this.spdMap[newSpd][0]).css("border", "4px solid #3D4048");
Also, you need to change this.curSpd with newSpd afterwards.
You are not using your curSpd/newSpd variables correctly. They should be:
$("#"+this.spdMap[this.curSpd]).css("border", "0px");
$("#"+this.spdMap[newSpd]).css("border", "4px solid #3D4048");
Also, as imtheman pointed out, your css call needs to be fixed.
Related
I have a image that is created to have 4 images in one See this image
Now, what I am trying to do is get the css to load just the first square at the top. Then when a user hovers over that image it will switch between all four images.
So it will display black on load, then when a user hovers over it, the image changes to red, then blue, then green, then back to black. It then repeats over and over until the mouse is moved off the image area.
I know that I can do this by converting the png to a gif but the image is generated outside of my control so this method is needed.
If anyone can help I will be forever grateful.
Cheers.
You should use CSS sprites and to make the change happend when over use setInterval function to change position ( here the height of each block of your image mesures 300px , so we incerement by +300 ) every defined interval time ,
Below snippet I've used .hover() jquery function to set and clear annimation .
var interval;
$(function(){
$("#image").hover(
function() {
var bottom = 0;
$this = $(this);
interval = setInterval(function() {
bottom >= 900 ? bottom = 0 : bottom+=300;
$this.css({'background-position' : '0px -'+bottom+'px'});
} , 1000)
},
function(){
$this.css({'background-position' : '0 0'})
clearInterval(interval);
}
);
});
#image {
width:150px;
height:150px;
background: url('https://i.stack.imgur.com/h8h14.png') 0 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="image" ><div>
I've set up a jsFiddle here. But below is the code...
HTML
<div class="square square0"></div>
<div class="square square1"></div>
<div class="square square2"></div>
<div class="square square3"></div>
Javascript
$('.square').click(function () {
if ($(this).hasClass('square0')) {
$(this).removeClass('square0').addClass('square1');
return false;
}
if ($(this).hasClass('square1')) {
$(this).removeClass('square1').addClass('square2');
return false;
}
if ($(this).hasClass('square2')) {
$(this).removeClass('square2').addClass('square3');
return false;
}
if ($(this).hasClass('square3')) {
$(this).removeClass('square3').addClass('square0');
return false;
}
});
CSS
.square { display: block; height: 100px; width: 100px; }
.square0{ background-color: #000; }
.square1{ background-color: #F00; }
.square2{ background-color: #0F0; }
.square3{ background-color: #00F; }
The way the fiddle is set up currently is mostly what I want. The user clicks the colors and it cycles through black, red, green, blue and back to black again. However, there's a twist!
Imagine black as the default / empty value, and the colors (red, green, and blue) being the different options. If a value is already a color when the user clicks it, it will reset back to black. If it is black when the user clicks it, then it cycles through the colors.
Here's the rub...
From the moment they click black, (and it turns it to red) a timer for 2 seconds starts. If the user does not click in 2 seconds, then the next time they click it, it turns black (default / empty value). But every time they continue to click to cycle through the colors (including back to black), that timer resets to 2 seconds once again.
Lastly, if you click a black block to turn it red, and then another block, and then back to the previous one, it will turn it black (not cycle) for the very fact that you clicked away from that previous block, which gets rid of the timer.
I know it's a lot - but I feel like something with this simple of a concept shouldn't be t̲o̲o̲ h̲a̲r̲d̲ to figure out, but for some reason I just can't wrap my mind around it. It's probably stupid simple.
Help me Obi Wan Stackoverflow(i?)... you're my only hope!
You'll need to do something like this:
$('.square').click(function(e) {
var $this = $(this);
if ($this.hasClass('timer-on') || $this.hasClass('square0')) {
if ($this.hasClass('square0')) {
$this.removeClass('square0').addClass('square1');
} else if ($this.hasClass('square1')) {
$this.removeClass('square1').addClass('square2');
} else if ($this.hasClass('square2')) {
$this.removeClass('square2').addClass('square3');
} else if ($this.hasClass('square3')) {
$this.removeClass('square3').addClass('square1');
};
} else {
$this.addClass('square0').removeClass('square1 square2 square3');
};
clearTimeout($this.data('timer'));
$this.addClass('timer-on').data('timer', setTimeout(function () {
$this.removeClass('timer-on');
}, 2000));
});
http://jsfiddle.net/mblase75/bF5Re/
Your return false statements were totally unnecessary, and were interfering with the code that followed, so I removed them and changed your subsequent if statements to else if instead.
The trick I used is to add a class, timer-on, when the two-second timer starts and remove it once the timer ends. Now we just need to test for the presence of the timer-on to know if the timer has run out.
The setTimeout function returns an ID which can be cleared using clearTimeout, so we store that ID on the element clicked using .data() and reset it on every click to restart the timer.
I am implementing a jquery file upload page. While a user is adding files, I want them to be getting listed in a form of an icons in an auto-sizable grid.
Auto-sizable means it provides maximum space for containing elements. When there is two objects - it woud look like (I know i will have to handle image resizing myself):
When several are added:
Is there a "grid control" (jquery perhaps) that does at least close to what I need sizing wise?
First of all, please keep in mind that I'm a jQuery newbie and this is my first post on Stackoverflow :)
I've the same problem and I've try to fix it using jQuery and CSS. This is my body tag content:
<div id="controls">
Controls:
<button id="add">+</button>
<button id="del">-</button>
Current ratio:
<span id="value"></span>
<button id="increase">+</button>
<button id="decrease">-</button>
Referred to:
<form style="display: inline;">
width<input type="radio" name="maximize" value="width">
height<input type="radio" name="maximize" value="height">
</form>
</div>
<div id="elements" style="width: 500px; height: 300px; background: black;">
</div>
<script>
ratio = 1;
ratioWidth = true;
function autoresize() {
boxes = $('#elements').children().size();
rows = Math.ceil(Math.sqrt(boxes/ratio));
columns = Math.ceil(boxes/rows);
if (!ratioWidth) {
tmp = rows;
rows = columns;
columns = tmp;
}
$('#elements').children().css('width', 100/rows+'%');
$('#elements').children().css('height', 100/columns+'%');
}
function add() {
red = Math.floor(Math.random()*256);
green = Math.floor(Math.random()*256);
blue = Math.floor(Math.random()*256);
color = 'rgb('+red+','+green+','+blue+')';
$('#elements').append("<div style=\"background: "+color+"; float: left;\"></div>");
autoresize();
}
function update() {
$('#value').text(ratio);
autoresize();
}
function remove() {
$('#elements').children().last().remove();
update();
}
function increase() {
ratio++;
update();
}
function decrease() {
if (ratio > 1) {
ratio--;
update();
}
}
$(document).ready(function() {
$('#add').click(add);
$('#del').click(remove);
$('#increase').click(increase);
$('#decrease').click(decrease);
if (ratioWidth) value = 'width'
else value = 'height'
$('input[type=radio]').filter('[value='+value+']').attr('checked', true);
$('input[type=radio]').live('change', function() {
if ($(this).val() == 'width') ratioWidth = true
else ratioWidth = false;
autoresize();
});
update();
//$(window).bind("resize", autoresize);
});
</script>
You could remove the background color stuff and put your icons centered in those boxes.
If you find a better way of if you improve this code, please let me know :)
Edit 1 - I've added some Math.floor(...) to remove a bug when boxes side has repeating decilmals: very size is a simple integer. Now dimensions are fetched from the container div, I use black as background color for the main container and I've noticed a little issue: sometimes I see a black border near the little boxes, even if I don't set any background color. Could it be a Firefox rendering glitch?
Edit 2 - Now it's possible to set if you prefer to auto-expand horizontally, vertically, or none of them. I've tried to write a better code, and I've commented autoresize when the window is resized (use it only if your container box hasn't a fixed height/width). I think that now it needs an ratio option, in order to specify if width have to be twice longer for example. Live example: http://experimental.frafra.eu/maxarea2.html
Edit 3 - New code! Better graphical representation and a new parameter: ratio. Ratio is a coefficient between the ratio between main container width/height and the elements one. Live example: http://experimental.frafra.eu/maxarea3.html
I want the mouseover on the coverImg then show the coverInfo
the coverInfo show the title and the description of the image
then the coverInfo do show
but I want the coverInfo stay and clickable when mouserover on itself
but it disappear immediately.
So what's the point I have missed?
The HTML
<div class="workshop_img">
<div class="coverInfo"></div>
<a href="#">
<span class="coverImg" style="background-image:url('images/work/show1.jpg')" title="Chictopia "></span>
</a>
The CSS:
.coverInfo {
position:absolute;
width: 200px;
height:200px;
background:rgba(0,0,0,0.5);
top:30%;
left:30%;
display:none;
}
see the jQuery code
$(function() {
$(".coverImg").each(function() {
//make the background image move a little pixels
$(this).css({
'backgroundPosition' : "-40px 0"
}).mouseover(function() {
$(this).stop().animate({
'backgroundPosition' : " -20px -60px "
}, {
duration : 90
});
//shwo the info box
var content = $(this).attr("title");
$("<div class='coverInfo'></div>").text(content).prependTo($(this).parent()).fadeIn("fast");
}).mouseout(function() {
$(this).stop().animate({
'backgroundPosition' : "-40px 0"
}, {
duration : 200,
});
$(this).parent().find(".coverInfo").stop().fadeOut("fast");
})
})
});
</div>
EDIT:
I have searched a lot and find something similar, I took them and the answer given below together to solve my problem, here is the code:
$(function() {
$(".coverImg").css({
'backgroundPosition' : "-40px 0"
}).mouseenter(function() {
var box = $(this).parents(".workshop_img").find(".coverInfo");
var content = $(this).attr("title");
var info = box.text(content);
$(this).stop().animate({
'backgroundPosition' : " -20px -60px "
},90);
info.show();
}).mouseleave(function() {
var box = $(this).parents(".workshop_img").find(".coverInfo");
var content = $(this).attr("title");
var info = box.text(content);
$(this).stop().animate({
'backgroundPosition' : "-40px 0"
},200);
info.stop().hide();
});
});
It has just been clean, but do not work fine.
What's the problem?
The new box shows immediately because it is not initially marked as hidden. .fadeIn() only fades in something that is initially not showing.
You can make it initially not visible like this:
$("<div class='coverInfo'></div>").text(content).hide().prependTo($(this).parent()).fadeIn("fast");
You also can get rid of the .each() iterator you're using. You don't need it. You can just use:
$(".coverImg").css(...).mouseover(...).mouseout(...);
You don't need the .each() at all.
I'd also suggest you use .hover(fn1, fn2) instead of .mouseover(fn1) and .mouseout(fn2).
And, it looks like you are creating a new object and inserting it on every mouseover event such that multiple such objects will pile up in the page. You should either .remove() the object in the mouseout function or you should reuse a previously existing element if it exists in the element rather than creating more and more of them.
Sometimes when you are using the events for mouse hovering and you are also changing the page, the change to the page can cause the element to lose the mouse hover which then hides the change to the page and then it all starts over again. I can't tell for sure if that is happening in your case (I'd need a working example to play with to see), but it seems possible.
I'd like to create an animation on a website to mimic a scrolling log file or tail -f. I'd feed it a list of fake log messages and they would be written to the bottom of the div and scroll up and off the top as new messages are displayed and then loop around. It needs to look authentic, white on black using a fixed width font etc.
Does anyone know of any javascript or jQuery libraries which could help me with this? I'm a beginner with javascript, so any advice on how to approach this would be much appreciated.
I've made a simple example for you
http://jsfiddle.net/manuel/zejCD/1/
// some demo data
for(var i=0; i<100; i++) {
$("<div />").text("log line " + i).appendTo("#tail")
}
// scroll to bottom on init
tailScroll();
// add button click
$("button").click(function(e) {
e.preventDefault();
$("<div />").text("new line").appendTo("#tail");
tailScroll();
});
// tail effect
function tailScroll() {
var height = $("#tail").get(0).scrollHeight;
$("#tail").animate({
scrollTop: height
}, 500);
}
#tail {
border: 1px solid blue;
height: 500px;
width: 500px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="tail">
<div>some line of text</div>
</div>
<button>Add Line</button>
Here is a great solution
This uses an ajax request, and the HTTP Range: header to request only the last ~30KB of a log file. It then polls for data appended to that file, and only ever retrieves new data (no refreshing the whole file, or even the last 30KB). Handles file truncation too.
https://github.com/ukhas/js-logtail#readme
I've updated Manuel van Rijn's script to include a timer and a toggle switch, along with some minor changes to the log lines. hope this helps.
http://jsfiddle.net/5rLw3LoL/
html:
<div id="tail">
<div>some line of text</div>
</div>
<button>Add Line</button>
js:
var tailcounter = 100;
var tailswitch = false;
// scroll to bottom on init
tailScroll();
// add line to log
function tailappend() {
$("<div />").text("log line " + tailcounter).appendTo("#tail");
tailcounter++;
tailScroll();
}
// auto update every second
var t = setInterval(tailappend, 1000);
// toggle updates button click
$("button").click(function (e) {
e.preventDefault();
switch (tailswitch) {
case false:
clearInterval(t); // turns off auto update
tailswitch = true;
alert("auto update off");
break;
case true:
t = setInterval(tailappend, 1000); // restarts auto update
tailswitch = false;
alert("auto update on");
break;
}
});
// tail effect
function tailScroll() {
var height = $("#tail").get(0).scrollHeight;
$("#tail").animate({
scrollTop: height
}, 500);
}
css: (important for formatting)
#tail {
border: 1px solid blue;
height: 400px;
width: 500px;
overflow: hidden;
}
This can be achieved with CSS by simply flipping the outer and inner container using transform: rotateX(180deg); https://jsfiddle.net/tnrn6h59/2/
Only issue here is that the scroll is also reversed, not an issue for mobile.