# This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI VideojuegoWizard = -> @datos = videojuego_test @respondidas = [] @posiciones = {} @inicializar = -> respondidasObs = ko.getObservable(this, 'respondidas') respondidasObs.subscribe (newValue) => @actualizarSlider() @prepararAnimaciones() @reiniciar() @reiniciar = -> @ocultarPregunta pregunta for pregunta in @datos.preguntas $("#resultado, #slider_luz, #disfrazado2").hide() $("#inicio, #disfrazado, #inicio_globo, #andando_en_patineta").show() $("#disfrazado, #andando_en_patineta").removeAttr('style') TweenMax.set $("#disfrazado"), {clearProps: "all"} ## Oculta las preguntas preventivamente @ocultarPregunta = ( item ) -> pregunta = $("#pregunta_#{item.orden}_bloque") pregunta.hide() ## Guarda la posición actual del objeto @guardarPosicionActual = (selector) -> $obj = $(selector) if ($obj.length > 1) @guardarPosicionActual obj for obj in $obj else item = {} item.$obj = $obj item.css = item.$obj.css(["left", "top"]) @posiciones[$obj.prop('id')] = item ## Crea las funciones de la animación correspondiente a la pregunta @crearFuncionAnimacionPregunta = (item) -> $pregunta_grupo = item.$obj.children("div") $pregunta = $pregunta_grupo.children("div") $respuestas = $pregunta_grupo.find("li") $anterior = item.$obj.children("button.anterior") animarIn = (item) -> item.$obj.show() TweenMax.set item.$obj, {clearProps: "all"} TweenMax.set $pregunta_grupo, {clearProps: "all"} # TweenMax.from $pregunta_grupo, 1, {y: -100, autoAlpha: 0, scale: 0, ease:Linear.easeNone} TweenMax.set $pregunta, {clearProps: "all"} TweenMax.from $pregunta, 1, {y: -100, autoAlpha: 0, scale: 0, ease:Linear.easeNone} TweenMax.set $respuestas, {clearProps: "all"} TweenMax.staggerFrom $respuestas, 0.5, {x: 500, autoAlpha: 0, ease:Linear.easeNone, delay: 1}, 0.5 TweenMax.set $anterior, {clearProps: "all"} TweenMax.from $anterior, 0.5, {autoAlpha: 0, x: -200, ease:Linear.easeNone} animarOut = (item) -> $anterior.hide() TweenMax.to item.$obj, 1, { ease:Linear.easeNone, y: 500, rotation: 360, onComplete: -> item.$obj.hide() } item.animarIn = () -> animarIn(item) item.animarOut = () -> animarOut(item) @prepararAnimaciones = () -> # guardo la posición actual de lo que hay acá # inicio animables = [ "#inicio", "#inicio_globo", "#disfrazado", "#disfrazado2", "#andando_en_patineta", ".pregunta_grupo", "#resultado", "#slider_linea_progreso" ] @guardarPosicionActual selector for selector in animables preguntas = (@posiciones["pregunta_#{pregunta.orden}_bloque"] for pregunta in @datos.preguntas) @crearFuncionAnimacionPregunta pregunta for pregunta in preguntas ## arranca con el wizard @comenzarCuestionario = -> $("#inicio").hide() @posiciones["pregunta_1_bloque"].animarIn() @respondidas.length = 0 $("#andando_en_patineta, #inicio_globo").hide() $("#disfrazado").css({transform: "scaleX(-0.5) scaleY(0.5)"}); $("#disfrazado").animate({left: "-40px", top: "55px"}, 500) $disfrazado2 = $("#disfrazado2") TweenMax.set $disfrazado2, {clearProps: "all"} TweenMax.from $disfrazado2, 1, {autoAlpha: 0, scale: 0} # $("#disfrazado2").show() $("#slider_linea_progreso").removeAttr('style') $("#slider_luz").show() @puedeSeguir 1 # al responder la pregunta "por segunda vez" cambia la lista resultante # esto lo hacemos para que los que están observando el avance de las preguntas # se refresquen @limpiarRespuesta = ( pregunta_orden ) -> removidos = _.remove @respondidas, (r) -> r.pregunta_orden == pregunta_orden if (removidos) # le aviso a ko que se modificó el dato y esto debería ejecutar los subscriptores respondidasObs = ko.getObservable this, "respondidas" # valueHasMutated() respondidasObs.valueHasMutated() return removidos @respuesta_click = ( pregunta, respuesta ) -> if (_.has(respuesta, "check")) # también podría verificarse si hubiera conclusión respuesta.check = !(respuesta.check) else respuesta.check = true $respuesta_opcion = $("#respuesta_#{pregunta.orden}_#{respuesta.opcion}").parent() if (respuesta.check) console.log "respuesta.check : true", $respuesta_opcion TweenMax.to $respuesta_opcion, 1, {color: "#EE64A3"} TweenMax.to $respuesta_opcion, .5, {scale: 1.3} TweenMax.to $respuesta_opcion, .5, {autoAlpha: 1.5, scale: 1, delay: .5} else console.log "respuesta.check : false", $respuesta_opcion TweenMax.to $respuesta_opcion, 1, {color: "white"} @puedeSeguir pregunta.orden ########## # se pregunta si puede seguir con la pregunta siguiente ########## @puedeSeguir = ( pregunta_orden ) -> console.log "@puedeSeguir - pregunta_orden", pregunta_orden pregunta = _.find @datos.preguntas, (item) -> item.orden == pregunta_orden console.log "@puedeSeguir - pregunta", pregunta respondida = _.find @respondidas, (item) -> return (pregunta_orden == item.pregunta_orden) if (_.isUndefined(respondida)) totalPuntos = _.sum pregunta.respuestas, (item) -> if (item.check) item.puntos else 0 else totalPuntos = respondida.respuesta.puntos console.log "totalPuntos", totalPuntos $btn = $("#siguiente_#{pregunta.orden}") if (totalPuntos == 0) console.log "no puede seguir #{pregunta_orden}", $btn # TweenMax.set $btn, "visibility: hidden" $btn.css("visibility", "hidden") $btn.prop('disabled', true) else console.log "puede seguir #{pregunta_orden}", $btn # TweenMax.set $btn, "visibility: visible" $btn.css("visibility", "visible") $btn.prop('disabled', false) ## la próxima pregunta @proxima = ( pregunta, index_pregunta ) -> @limpiarRespuesta pregunta.orden console.log "pregunta", pregunta # en realidad, habría que meter la colección de respuestas respondidas # si quiero reutilizar el contador de puntos, podría meter adentro de # { respondidas[n].respuesta.puntos el total de la respuesta } totalPuntos = _.sum pregunta.respuestas, (item) -> if (item.check) item.check = false item.puntos else 0 @respondidas.push({ pregunta_orden: pregunta.orden, pregunta: pregunta respuesta: { puntos : totalPuntos } }) console.log "@respondidas #{totalPuntos}", @respondidas @posiciones["pregunta_#{pregunta.orden}_bloque"].animarOut() if (index_pregunta < (@datos.preguntas.length-1)) # me muevo a la próxima pregunta @posiciones["pregunta_#{pregunta.orden+1}_bloque"].animarIn() @limpiarRespuesta pregunta.orden+1 @puedeSeguir pregunta.orden+1 else # muestro los resultados @mostrarResultado() # vuelve para atrás la pregunta actual y resetea la respuesta @anterior = ( pregunta ) -> @limpiarRespuesta (pregunta.orden-1) @posiciones["pregunta_#{pregunta.orden}_bloque"].animarOut() _.each pregunta.respuestas, (item) -> item.check = false return @posiciones["pregunta_#{pregunta.orden-1}_bloque"].animarIn() @puedeSeguir pregunta.orden-1 # muestra los resultados al final de todas las preguntas @mostrarResultado = -> $("#slider_luz").hide() $("#resultado").show() TweenMax.to $("#disfrazado"), 0.5, {scaleY: -0.9, scaleX: 0.9, left: -30, top: 95, ease:Linear.easeNone} TweenMax.to $("#disfrazado2"), 0.5, {scale: 0, autoAlpha: 0, ease:Linear.easeNone} @actualizarSlider = -> console.log("@actualizarSlider", @respondidas) # máximo es 350px $slider_linea_progreso = @posiciones["slider_linea_progreso"] if (@respondidas && $slider_linea_progreso) startLeftPos = parseInt($slider_linea_progreso.css.left, 10) distanciaPorRecorrer = 350 - startLeftPos # ponemos una menos porque el final ya no nos importa, son los resultados totalPreguntas = @datos.preguntas.length - 1 cantRespondida = @respondidas.length distanciaPorRespuesta = (distanciaPorRecorrer / totalPreguntas) distanciaRecorrida = startLeftPos + (distanciaPorRespuesta * cantRespondida) $slider = $("#slider_linea_progreso") console.log "animate para a #{distanciaRecorrida} porque hay #{cantRespondida} respondidas" $slider.animate({left: "#{distanciaRecorrida}px"}, 500) @resultado = -> puntosAcumulados = 0 @contarResultados = (respondida) -> puntosAcumulados += respondida.respuesta.puntos @contarResultados respondida for respondida in @respondidas resultado = _.find @datos.max_respuestas, (item) -> item.puntos_desde <= puntosAcumulados && item.puntos_hasta > puntosAcumulados resultado.puntosAcumulados = puntosAcumulados console.log "puntosAcumulados #{puntosAcumulados}" resultado ko.track this # --------------------------------------------------------------------------------------------- # Activates knockout.js ko.punches.enableAll() model = new VideojuegoWizard() ko.applyBindings model model.inicializar()