JQuery events stop working with RxJS

So basically my problem is that at the beginning of my program jQuery .css()

works just fine, checked like this:

$("#canvas").css("border", "3px solid red");

      

Immediately after that, when I try to add a div that is actually added whenever needed, it .css()

stops working for that element. Like this:

var elem = $("<div/>", {"class": "circle"});
elem.css({'background-color': color})
    .appendTo($("#circles"));

      

It just adds <div class="circle"></div>

, no styling and can't be .remove()

'd -

Fiddle: http://jsfiddle.net/bh79fe87/

The complete 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 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>

      

+3


source to share


3 answers


Okay, so I was away. Apparently RxJS creates a new circle div for each subscriber. In this case, 4 event subscriptions were made for each round. I solved this by using Rx.Observable.prototype.publish()

.



JSFiddle working: http://jsfiddle.net/u3Lf6d26/1/

0


source


Try removing $ () in appendTo and just put "#circles" instead



0


source


class

is a reserved word in JavaScript (see ECMA-262 sec. 7.6.1.2 ), and using it probably stops your script from being executed further. There are several ways to get around this. For example, you can use a method .addClass()

to set your class.

Try to change this:

var elem = $("<div/>", {class: "circle"});
elem.css({'background-color': color})
    .appendTo($("#circles"));

      

:

var elem = $("<div/>").addClass("circle");
elem.css({'background-color': color})
    .appendTo($("#circles"));

      

and see if it helps.

0


source







All Articles