Reputation: 456
So, basically, my problem is that at the start of my program, the jQuery .css()
works just fine, tested by this:
$("#canvas").css("border", "3px solid red");
Just after that, when I try to add a div - which does indeed get added whenever it is required - .css()
stops working for that element. Like this:
var elem = $("<div/>", {"class": "circle"});
elem.css({'background-color': color})
.appendTo($("#circles"));
This just appends a <div class="circle"></div>
, with no style and which can't later be .remove()
'd-
Fiddle: http://jsfiddle.net/bh79fe87/
The full code looks like this (LiveScript):
O = Rx.Observable
## Extensions
Rx.Observable.repeatFunc = -> Rx.Observable.return null .map it .repeat!
Rx.Observable.prototype.scanCount = -> this.map 1 .scan 0 (+) .startWith 0
## Utils
write = (t, s) --> t.html t.html! + s + '<br />'
pairs-to-obj = -> {[p[0], p[1]] for p in it}
assoc = (m, t) -->
for k, v of m
if k of t then [k, t[k]]
else [k, v]
|> (++ [[k, v] for k, v of t if k not of m])
|> pairs-to-obj
toLocal = (e, x, y) ->
o = $(e).offset!
{x: x - o.left, y: y - o.top}
## Game
createCircle = ->
x = Math.random! * ($(canvas).width() - 20)
y = -40 + Math.random! * 10
color = ['#FF0000', '#00FF00', '#0000FF'][Math.floor Math.random! * 3]
do
x: x
y: y
color: color
createCircleStream = ($canvas, $circles) ->
elem = $ '<div/>', class: 'circle'
elemclicks = O.fromEvent elem, 'click'
.map -> true
.first! # Kill the event after a click.
stream = O.interval 16
.scan createCircle!, (obj, click) -> assoc obj, y: obj.y + 1
.takeWhile -> it.y < $canvas.height! + 1
killstream = stream
.filter -> it.y > $canvas.height!
.merge elemclicks
.map -> true
.first!
do
clicks: elemclicks
stream: stream
kill: killstream
elem: elem
$ ->
$canvas = $ '#canvas'
$hits = $ '#hits'
$missclicks = $ '#missclicks'
$misses = $ '#misses'
$circles = $ '#circles'
$canvas.css 'border', '3px solid red'
# Events
canvasclicks = O.fromEvent $canvas, 'click'
.map -> toLocal canvas, it.pageX, it.pageY
# Data streams
circlestream = O.return 1 # O.repeatFunc -> createCircleStream $canvas, $circles
.repeat!
.controlled!
circles = circlestream.map -> createCircleStream $canvas, $circles
circleclicks = circles
.flatMap (circle) ->
circle.clicks
.map -> circle
circleupdates = circles
.flatMap (circle) ->
circle.stream
.map -> assoc it, elem: circle.elem
.takeUntil circle.kill
circlekills = circles
.flatMap (circle) ->
circle.kill
.map -> circle.elem
hits = circleclicks.scanCount!
missclicks = canvasclicks.scanCount!.combineLatest hits, (-)
misses = circlekills.scanCount!.combineLatest hits, (-)
# Side effects
circles.subscribe ->
it.elem.css 'background-color': it.color
.appendTo $circles
$('#canvas').css 'background-color': it.color
circleupdates.subscribe ->
it.elem.css do
'left': it.x
'top': it.y
'background-color': it.color
circlekills.subscribe ->
it.remove!
circlestream.request 1
hits.subscribe -> $hits.html "Hits: #it"
missclicks.subscribe -> $missclicks.html "Missed clicks: #it"
misses.subscribe -> $misses.html "Missed circles: #it"
# Kick off the game.
circlestream.request 5
Also the HTML:
<html>
<head>
<title>RxTest</title>
<script type="text/javascript" src="libs/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="libs/rx.all.js"></script>
<script type="text/javascript" src="js/rxtest.js"></script>
<style>
#canvas {
position: relative;
width: 640px; height: 360px; background: #000000;
color: #FFFFFF;
overflow: hidden;
}
.game-container {
position: absolute;
background: transparent;
color: #FFFFFF;
}
.circle {
position: absolute;
border-radius: 50%;
width: 30px;
height: 30px;
}
</style>
</head>
<body>
<div id="canvas">
<div id="circles" class="game-container"></div>
<div id="stats" class="game-container">
<div id="hits"></div>
<div id="missclicks"></div>
<div id="misses"></div>
</div>
</div>
</body>
</html>
Upvotes: 3
Views: 218
Reputation: 456
Ookay, so, I was way off. Apparently, RxJS creates a new circle div for every subscriber. In this case, 4 event subscriptions were made for each circle. I solved this by using Rx.Observable.prototype.publish()
.
Working JSFiddle: http://jsfiddle.net/u3Lf6d26/1/
Upvotes: 0
Reputation: 111506
class
is a reserved word in JavaScript (see: ECMA-262 sec. 7.6.1.2) and using it probably stops your script from further execution. The are few ways to get around this. For example you can use .addClass()
method to set your class.
Try changing this:
var elem = $("<div/>", {class: "circle"});
elem.css({'background-color': color})
.appendTo($("#circles"));
to this:
var elem = $("<div/>").addClass("circle");
elem.css({'background-color': color})
.appendTo($("#circles"));
and see if it helps.
Upvotes: 0
Reputation: 312
Try removing the $() in appendTo and just putting "#circles" there instead
Upvotes: 0