Source

CubeOfCoffee / coffee / app.coffee

Full commit
class CubeView
    # cube number to html cube faces correspondance
    # the order is important for the display
    faces:
        3 : 'B' 
        5 : 'D'
        0 : 'U'
        1 : 'F'
        2 : 'R'
        4 : 'L'

    # cube colors to css colors correspondance
    colors:
        1: 'yellow'
        2: 'blue'
        3: 'red'
        4: 'green'
        5: 'orange'
        6: 'white'

    # list of movements where the specified face is hidden on the showcube
    invisibles:
        'F': ['RBD','RBLD','BLD','URBD','URBLD','UBLD','URB','URBL','UBL']
        'R': ['BLD','FBLD','FLD','UBLD','UFBLD','UFLD','UBL','UFBL','UFL']
        'U': ['FRD','FRLD','FLD','FRBD','FRBLD','FBLD','RBD','RBLD','BLD']
        'L': ['FRD','FRBD','RBD','UFRD','UFRBD','URBD','UFR','UFRB','URB']
        'D': ['URB','URBL','UBL','UFRB','UFRBL','UFBL','UFRB','UFRL','UFL']
        'B': ['FLD','FRLD','FRD','UFLD','UFRLD','UFRD','UFL','UFRL','UFR']

    ismoving: false

    movcallback: undefined

    coef: 2/3

    minlength: undefined

    constructor:($container) ->
        @$container = $container
        @model = new Cube

        # set the maximum width of the future cube
        minlength = $container.clientWidth
        height = $container.clientHeight
        if height < minlength
            minlength = height
        @minlength = minlength

        # center the viewer in the container
        minlength = minlength * @coef
        perspective = minlength * 10 / @coef
        offsetX = perspective / 200 * @coef * 4
        offsetY = perspective / 200 * @coef * 2
        remaining_spaceX = (1-@coef)*(@minlength) - offsetX
        remaining_spaceY = (1-@coef)*(@minlength) - offsetY
        offsetX+=remaining_spaceX/4
        offsetY+=remaining_spaceY/4

        transforms =
            'F': ''
            'B': 'rotateY(180deg)'
            'R': 'rotateY(90deg)'
            'L': 'rotateY(-90deg)'
            'U': 'rotateX(90deg)'
            'D': 'rotateX(-90deg)'

        # create the showcube
        htmlstring = '<div class="viewer" style="left:' + offsetX + 'px;top:' + offsetY + 'px;-moz-perspective: ' + perspective + 'px"><div class="cube showcube" style="height:' + minlength + 'px;width:' + minlength + 'px;">'
        for i, face of @faces
            htmlstring+= '<div style="-moz-transform: ' + transforms[face] + ' translateZ('  + (minlength/2-1) + 'px);" class="face-' + face + '">'
            for facet, j in @model.state[i]
                hideclass = ("turn-#{mov}-hidden" for mov in @invisibles[face][j]).join(' ')
                htmlstring+= '<div class="facet-' + face + j + ' ' + hideclass + '"><div></div></div>'
            htmlstring+= '</div>'
        htmlstring+= '</div></div>'
        @$container.insertAdjacentHTML "beforeend", htmlstring
        @renderColors()

        # create a second cube and hide it
        @$showcube = @$container.querySelector '.showcube'
        @$shadowcube = @$showcube.cloneNode true
        @$shadowcube.className = 'cube shadowcube'
        $viewer = @$container.querySelector '.viewer'
        $viewer.insertBefore @$shadowcube, $viewer.firstChild

        for eventtype in ['transitionend', 'oTransitionEnd', 'webkitTransitionEnd']
            @$showcube.addEventListener eventtype, @transitionend

        # force a repaint of the cube to avoid display bugs
        $cubeofcoffee = document.querySelectorAll '.cubeofcoffee'
        for $container in $cubeofcoffee
            $container.style.visibility = 'hidden'

        window.setTimeout ->
            for $container in $cubeofcoffee
                $container.style.borderWidth = "" + 2 + 'px'
                $container.style.visibility = 'visible'
        , 0


    renderColors: =>
        for face, i in @model.state
            for facet, j in face
                $facets = @$container.getElementsByClassName "facet-#{@faces[i]}#{j}"
                for $facet in $facets
                    $facet.querySelector('div').style.backgroundColor = @colors[facet]

    turn: (mov, callback) ->
        @movcallback = callback
        @ismoving = true
        @$container.querySelector('.showcube').classList.add('transitioned')
        @model.combination(mov)
        movclass = "show-#{mov[0]}"
        if mov.length > 1
            if mov[1] is "'"
                movclass+= " #{movclass}-inv"
            else if mov[1] is "2"
                movclass+= " #{movclass}-double"
        for $cube in @$container.getElementsByClassName 'cube'
            $cube.className+= ' ' + movclass

    transitionend: =>
        @renderColors()

        @$showcube.className = "cube showcube"
        @$shadowcube.className = "cube shadowcube"

        @ismoving = false

        if @movcallback
            window.setTimeout =>
                @movcallback.apply(this)
                @movcallback = undefined
            , 0

        return true

class CubeController

    current: -1

    mode: 'stop'

    view: undefined

    turnlist: ["R2", "U", "R", "U", "R'", "U'", "R'", "U'", "R'", "U", "R'"]

    constructor:(cubeview) ->
        @view = cubeview

        # add the text movements
        @view.$container.insertAdjacentHTML "beforeend", '<div class="movtext">' + @turnlist.join(' ') + '</div><div class="movbuttons"><a class="first" href="#">|◀</a><a class="previous" href="#">◀|</a><a class="previous-play" href="#">◀</a><a class="stop" href="#">◼</a><a class="next-play" href="#">▶</a><a class="next" href="#">|▶</a><a class="last" href="#">▶|</a></div>'

        # buttons clicks
        @view.$container.querySelector('.next-play').addEventListener 'click', =>
            @next_play()
        @view.$container.querySelector('.stop').addEventListener 'click', =>
            @stop()

    end_callback: =>
        if @mode is 'play'
            if @current < @turnlist.length - 1
                @next_play()
            else
                @mode = 'stop'
                @current = -1
        else if @mode is 'play_stop'
            @mode = 'stop'


    next_play: =>
        window.setTimeout =>
            @mode = 'play'
            @current++
            @view.turn @turnlist[@current], @end_callback

    stop: =>
        window.setTimeout =>
            @mode = 'stop'
            @end_callback()

document.addEventListener 'DOMContentLoaded', ->

    for $container in document.querySelectorAll '.cubeofcoffee'
        window.$test = new CubeController(new CubeView($container))


        #       window.setInterval ->
        #           if movlist.length and window.ismoving is false
        #               domov($container)
        #       , 50
        #
        #   $(document).bind('keydown', (e) ->
        #       if e.which is 37      # RIGHT
        #           movlist.push "y"
        #       else if e.which is 39      # LEFT
        #           movlist.push "y'"
        #       else if e.which is 38      # UP
        #           movlist.push "x"
        #       else if e.which is 40      # DOWN
        #           movlist.push "x'"
        #       else if e.which is 85      # U
        #           movlist.push "R"
        #       else if e.which is 73      # I
        #           movlist.push "U"
        #       else if e.which is 82      # R
        #           movlist.push "L'"
        #       else if e.which is 69      # E
        #           movlist.push "U'"
        #       else if e.which is 74      # J
        #           movlist.push "R'"
        #       else if e.which is 70      # F
        #           movlist.push "L"
        #       else if e.which is 72      # H
        #           movlist.push "F"
        #       else if e.which is 71      # G
        #           movlist.push "F'"
        #       else if e.which is 75      # K
        #           movlist.push "D'"
        #       else if e.which is 68      # D
        #           movlist.push "D"
        #       else if e.which is 76      # L
        #           movlist.push "B'"
        #       else if e.which is 83      # S
        #           movlist.push "B"
        #
        #       return true
        #   )
        #
        #   posstart = [0, 0]
        #   $target = null
        #
        #   $(document).bind("mousedown", (ev) ->
        #       posstart = [ev.clientX, ev.clientY]
        #       $target = $(ev.target)
        #       ev.preventDefault()
        #       return false
        #   )
        #   $(document).bind("mouseup", (ev) ->
        #       posend = [ev.clientX, ev.clientY]
        #       offsetX = posend[0] - posstart[0]
        #       offsetY = posend[1] - posstart[1]
        #
        #       if $target.is('.facet-F0, .facet-F1, .facet-F2') and (Math.abs(offsetX) > Math.abs(offsetY))
        #           if (offsetX > 0)
        #               movlist.push "U'"
        #           else if (offsetX < 0)
        #               movlist.push "U"
        #       else if $target.is('.facet-F6, .facet-F7, .facet-F8') and (Math.abs(offsetX) > Math.abs(offsetY))
        #           if (offsetX > 0)
        #               movlist.push "D"
        #           else if (offsetX < 0)
        #               movlist.push "D'"
        #       else if $target.is('.facet-F2, .facet-F5, .facet-F8') and (Math.abs(offsetY) > Math.abs(offsetX))
        #           if (offsetY > 0)
        #               movlist.push "R'"
        #           else if (offsetY < 0)
        #               movlist.push "R"
        #       else if $target.is('.facet-F0, .facet-F3, .facet-F6') and (Math.abs(offsetY) > Math.abs(offsetX))
        #           if (offsetY > 0)
        #               movlist.push "L"
        #           else if (offsetY < 0)
        #               movlist.push "L'"
        #       else if $target.is('.facet-R0, .facet-R1, .facet-R2, .facet-R3, .facet-R4, .facet-R5, .facet-R6, .facet-R7, .facet-R8') and (Math.abs(offsetY) > Math.abs(offsetX))
        #           if (offsetY > 0)
        #               movlist.push "F"
        #           else if (offsetY < 0)
        #               movlist.push "F'"
        #       else
        #           if (Math.abs(offsetX) > Math.abs(offsetY))
        #               if (offsetX > 0)
        #                   movlist.push "y'"
        #               else if (offsetX < 0)
        #                   movlist.push "y"
        #           else if (Math.abs(offsetY) > Math.abs(offsetX))
        #               if (offsetY > 0)
        #                   movlist.push "x'"
        #               else if (offsetY < 0)
        #                   movlist.push "x"
        #
        #       $target = null
        #
        #       ev.preventDefault()
        #
        #       return false
        #   )
        #   $(document).bind("mouseup", (ev) ->
        #
        #       ev.preventDefault()
        #
        #       return false
        #   )