mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-17 19:12:33 -05:00
LoadingScreen -> level intro behavior
This commit is contained in:
parent
4497334e6d
commit
2259076800
12 changed files with 240 additions and 107 deletions
|
@ -248,3 +248,39 @@ module.exports.getPrepaidCodeAmount = getPrepaidCodeAmount = (price=999, users=0
|
||||||
return 0 unless users > 0 and months > 0
|
return 0 unless users > 0 and months > 0
|
||||||
total = price * users * months
|
total = price * users * months
|
||||||
total
|
total
|
||||||
|
|
||||||
|
module.exports.filterMarkdownCodeLanguages = (text) ->
|
||||||
|
currentLanguage = me.get('aceConfig')?.language or 'python'
|
||||||
|
excludedLanguages = _.without ['javascript', 'python', 'coffeescript', 'clojure', 'lua', 'io'], currentLanguage
|
||||||
|
exclusionRegex = new RegExp "```(#{excludedLanguages.join('|')})\n[^`]+```\n?", 'gm'
|
||||||
|
text.replace exclusionRegex, ''
|
||||||
|
|
||||||
|
module.exports.aceEditModes = aceEditModes =
|
||||||
|
'javascript': 'ace/mode/javascript'
|
||||||
|
'coffeescript': 'ace/mode/coffee'
|
||||||
|
'python': 'ace/mode/python'
|
||||||
|
'clojure': 'ace/mode/clojure'
|
||||||
|
'lua': 'ace/mode/lua'
|
||||||
|
'io': 'ace/mode/text'
|
||||||
|
|
||||||
|
module.exports.initializeACE = (el, codeLanguage) ->
|
||||||
|
contents = $(el).text().trim()
|
||||||
|
editor = ace.edit el
|
||||||
|
editor.setOptions maxLines: Infinity
|
||||||
|
editor.setReadOnly true
|
||||||
|
editor.setTheme 'ace/theme/textmate'
|
||||||
|
editor.setShowPrintMargin false
|
||||||
|
editor.setShowFoldWidgets false
|
||||||
|
editor.setHighlightActiveLine false
|
||||||
|
editor.setHighlightActiveLine false
|
||||||
|
editor.setBehavioursEnabled false
|
||||||
|
editor.renderer.setShowGutter false
|
||||||
|
editor.setValue contents
|
||||||
|
editor.clearSelection()
|
||||||
|
session = editor.getSession()
|
||||||
|
session.setUseWorker false
|
||||||
|
session.setMode aceEditModes[codeLanguage]
|
||||||
|
session.setWrapLimitRange null
|
||||||
|
session.setUseWrapMode true
|
||||||
|
session.setNewLineMode 'unix'
|
||||||
|
return editor
|
||||||
|
|
|
@ -79,15 +79,15 @@ _.extend LevelSessionSchema.properties,
|
||||||
currentScriptOffset:
|
currentScriptOffset:
|
||||||
type: 'number'
|
type: 'number'
|
||||||
|
|
||||||
selected:
|
selected: # Not tracked any more, delete with old level types
|
||||||
type: [
|
type: [
|
||||||
'null'
|
'null'
|
||||||
'string'
|
'string'
|
||||||
]
|
]
|
||||||
playing:
|
playing:
|
||||||
type: 'boolean' # Not tracked any more
|
type: 'boolean' # Not tracked any more, delete with old level types
|
||||||
frame:
|
frame:
|
||||||
type: 'number' # Not tracked any more
|
type: 'number' # Not tracked any more, delete with old level types
|
||||||
thangs: # ... what is this? Is this used?
|
thangs: # ... what is this? Is this used?
|
||||||
type: 'object'
|
type: 'object'
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
|
|
@ -72,7 +72,13 @@ $level-resize-transition-time: 0.5s
|
||||||
width: 55%
|
width: 55%
|
||||||
position: relative
|
position: relative
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
@include transition($level-resize-transition-time ease-out)
|
@include transition(all $level-resize-transition-time ease-out, z-index 1.2s linear)
|
||||||
|
z-index: 0
|
||||||
|
|
||||||
|
&.preview-overlay
|
||||||
|
z-index: 20
|
||||||
|
#goals-view
|
||||||
|
visibility: hidden
|
||||||
|
|
||||||
canvas#webgl-surface
|
canvas#webgl-surface
|
||||||
background-color: #333
|
background-color: #333
|
||||||
|
|
|
@ -8,24 +8,48 @@
|
||||||
background-position: top $backgroundPosition
|
background-position: top $backgroundPosition
|
||||||
background-size: contain
|
background-size: contain
|
||||||
|
|
||||||
|
$UNVEIL_TIME: 1.2s
|
||||||
|
|
||||||
#level-loading-view
|
#level-loading-view
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
position: absolute
|
position: absolute
|
||||||
z-index: 20
|
z-index: 20
|
||||||
$UNVEIL_TIME: 1.2s
|
|
||||||
|
|
||||||
&.unveiled
|
&.unveiled
|
||||||
pointer-events: none
|
pointer-events: none
|
||||||
|
|
||||||
.loading-details
|
&.preview-screen
|
||||||
|
background-color: rgba(0, 0, 0, 0.5)
|
||||||
|
|
||||||
|
.left-wing, .right-wing
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
position: absolute
|
||||||
|
pointer-events: none
|
||||||
|
|
||||||
|
.left-wing
|
||||||
|
@include wing-background('/images/level/loading_left_wing_1920.jpg', right)
|
||||||
|
@media screen and ( max-width: 1366px )
|
||||||
|
@include wing-background('/images/level/loading_left_wing_1366.jpg', right)
|
||||||
|
left: -50%
|
||||||
|
@include transition(all $UNVEIL_TIME ease)
|
||||||
|
|
||||||
|
.right-wing
|
||||||
|
@include wing-background('/images/level/loading_right_wing_1920.jpg', left)
|
||||||
|
@media screen and ( max-width: 1366px )
|
||||||
|
@include wing-background('/images/level/loading_right_wing_1366.jpg', left)
|
||||||
|
right: -50%
|
||||||
|
@include transition(all $UNVEIL_TIME ease)
|
||||||
|
|
||||||
|
#loading-details
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 86px
|
top: 86px
|
||||||
left: 50%
|
right: 50%
|
||||||
$WIDTH: 450px
|
$WIDTH: 450px
|
||||||
width: $WIDTH
|
width: $WIDTH
|
||||||
height: 450px
|
height: 450px
|
||||||
margin-left: (-$WIDTH / 2)
|
margin-right: (-$WIDTH / 2)
|
||||||
z-index: 100
|
z-index: 100
|
||||||
background: transparent url(/images/level/code_editor_background.png) no-repeat
|
background: transparent url(/images/level/code_editor_background.png) no-repeat
|
||||||
background-size: 100% 100%
|
background-size: 100% 100%
|
||||||
|
@ -34,9 +58,22 @@
|
||||||
padding: 80px 80px 40px 80px
|
padding: 80px 80px 40px 80px
|
||||||
text-align: center
|
text-align: center
|
||||||
// http://matthewlein.com/ceaser/ Bounce down a bit, then snap up.
|
// http://matthewlein.com/ceaser/ Bounce down a bit, then snap up.
|
||||||
@include transition(top $UNVEIL_TIME cubic-bezier(0.285, -0.595, 0.670, -0.600))
|
@include transition($UNVEIL_TIME cubic-bezier(0.285, -0.595, 0.670, -0.600))
|
||||||
font-family: 'Open Sans Condensed'
|
font-family: 'Open Sans Condensed'
|
||||||
|
|
||||||
|
&.preview
|
||||||
|
top: 0
|
||||||
|
right: 0
|
||||||
|
margin-right: 0
|
||||||
|
width: 45%
|
||||||
|
height: auto
|
||||||
|
pointer-events: all
|
||||||
|
@include transition($UNVEIL_TIME ease-in-out)
|
||||||
|
|
||||||
|
padding: 80px 70px 40px 50px
|
||||||
|
.progress-or-start-container.intro-footer
|
||||||
|
bottom: 30px
|
||||||
|
|
||||||
.level-loading-goals
|
.level-loading-goals
|
||||||
text-align: left
|
text-align: left
|
||||||
|
|
||||||
|
@ -49,12 +86,21 @@
|
||||||
font-size: 20px
|
font-size: 20px
|
||||||
color: black
|
color: black
|
||||||
|
|
||||||
|
.intro-doc
|
||||||
|
text-align: left
|
||||||
|
font-size: 16px
|
||||||
|
overflow: scroll
|
||||||
|
|
||||||
|
img
|
||||||
|
max-width: 100%
|
||||||
|
|
||||||
.progress-or-start-container
|
.progress-or-start-container
|
||||||
position: absolute
|
position: absolute
|
||||||
bottom: 95px
|
bottom: 95px
|
||||||
width: 325px
|
|
||||||
height: 80px
|
height: 80px
|
||||||
left: 48px
|
left: 48px
|
||||||
|
right: 77px
|
||||||
|
@include transition(bottom $UNVEIL_TIME ease-out)
|
||||||
|
|
||||||
.load-progress
|
.load-progress
|
||||||
width: 100%
|
width: 100%
|
||||||
|
@ -131,21 +177,7 @@
|
||||||
width: 401px
|
width: 401px
|
||||||
color: #666
|
color: #666
|
||||||
|
|
||||||
.left-wing, .right-wing
|
&.preview #tip-wrapper
|
||||||
width: 100%
|
left: 48px
|
||||||
height: 100%
|
right: 77px
|
||||||
position: absolute
|
width: auto
|
||||||
|
|
||||||
.left-wing
|
|
||||||
@include wing-background('/images/level/loading_left_wing_1920.jpg', right)
|
|
||||||
@media screen and ( max-width: 1366px )
|
|
||||||
@include wing-background('/images/level/loading_left_wing_1366.jpg', right)
|
|
||||||
left: -50%
|
|
||||||
@include transition(all $UNVEIL_TIME ease)
|
|
||||||
|
|
||||||
.right-wing
|
|
||||||
@include wing-background('/images/level/loading_right_wing_1920.jpg', left)
|
|
||||||
@media screen and ( max-width: 1366px )
|
|
||||||
@include wing-background('/images/level/loading_right_wing_1366.jpg', left)
|
|
||||||
right: -50%
|
|
||||||
@include transition(all $UNVEIL_TIME ease)
|
|
||||||
|
|
|
@ -52,3 +52,14 @@
|
||||||
border-image: url(/images/level/code_toolbar_submit_button_zazz_pressed.png) 14 20 20 20 fill round
|
border-image: url(/images/level/code_toolbar_submit_button_zazz_pressed.png) 14 20 20 20 fill round
|
||||||
padding: 2px 0 0 2px
|
padding: 2px 0 0 2px
|
||||||
color: white
|
color: white
|
||||||
|
|
||||||
|
#guide-view
|
||||||
|
pre.ace_editor
|
||||||
|
padding: 2px 4px
|
||||||
|
border-radius: 4px
|
||||||
|
background-color: #f9f2f4
|
||||||
|
font-size: 12px
|
||||||
|
font-family: Monaco, Menlo, Ubuntu Mono, Consolas, "source-code-pro", monospace !important
|
||||||
|
|
||||||
|
.ace_cursor, .ace_bracket
|
||||||
|
display: none
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
.right-wing
|
.right-wing
|
||||||
|
|
||||||
.loading-details.loading-container
|
#loading-details.loading-container
|
||||||
|
|
||||||
.level-loading-goals.secret
|
.level-loading-goals.secret
|
||||||
.goals-title(data-i18n="play_level.goals") Goals
|
.goals-title(data-i18n="play_level.goals") Goals
|
||||||
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
.errors
|
.errors
|
||||||
|
|
||||||
|
.intro-doc
|
||||||
|
|
||||||
.progress-or-start-container
|
.progress-or-start-container
|
||||||
button.start-level-button.btn.btn-lg.btn-success.btn-illustrated.header-font.needsclick(data-i18n="play_level.loading_start") Start Level
|
button.start-level-button.btn.btn-lg.btn-success.btn-illustrated.header-font.needsclick(data-i18n="play_level.loading_start") Start Level
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ module.exports = class ArchmageView extends ContributeClassView
|
||||||
contributorClassName: 'archmage'
|
contributorClassName: 'archmage'
|
||||||
|
|
||||||
contributors: [
|
contributors: [
|
||||||
|
{id: '547acbb2af18b03c0563fdb3', name: 'David Liu', github: 'trotod'}
|
||||||
{id: '52ccfc9bd3eb6b5a4100b60d', name: 'Glen De Cauwsemaecker', github: 'GlenDC'}
|
{id: '52ccfc9bd3eb6b5a4100b60d', name: 'Glen De Cauwsemaecker', github: 'GlenDC'}
|
||||||
{id: '52bfc3ecb7ec628868001297', name: 'Tom Steinbrecher', github: 'TomSteinbrecher'}
|
{id: '52bfc3ecb7ec628868001297', name: 'Tom Steinbrecher', github: 'TomSteinbrecher'}
|
||||||
{id: '5272806093680c5817033f73', name: 'Sébastien Moratinos', github: 'smoratinos'}
|
{id: '5272806093680c5817033f73', name: 'Sébastien Moratinos', github: 'smoratinos'}
|
||||||
|
@ -27,8 +28,8 @@ module.exports = class ArchmageView extends ContributeClassView
|
||||||
{id: '531258b5e0789d4609614110', name: 'Ruben Vereecken', github: 'rubenvereecken'}
|
{id: '531258b5e0789d4609614110', name: 'Ruben Vereecken', github: 'rubenvereecken'}
|
||||||
{id: '5276ad5dcf83207a2801d3b4', name: 'Zach Martin', github: 'zachster01'}
|
{id: '5276ad5dcf83207a2801d3b4', name: 'Zach Martin', github: 'zachster01'}
|
||||||
{id: '530df0cbc06854403ba67c15', name: 'Alexandru Caciulescu', github: 'Darredevil'}
|
{id: '530df0cbc06854403ba67c15', name: 'Alexandru Caciulescu', github: 'Darredevil'}
|
||||||
{id: '5268d9baa39d7db617000b18', name: 'Thanish Muhammed', github: 'mnmtanish'}
|
{id: '5268d9baa39d7db617000b18', name: 'Thanish Muhammed', github: 'mnmtanish'}
|
||||||
{id: '53232f458e54704b074b271d', name: 'Bang Honam', github: 'walkingtospace'}
|
{id: '53232f458e54704b074b271d', name: 'Bang Honam', github: 'walkingtospace'}
|
||||||
{id: '52d16c1dc931e2544d001daa', name: 'David Pendray', github: 'dpen2000'}
|
{id: '52d16c1dc931e2544d001daa', name: 'David Pendray', github: 'dpen2000'}
|
||||||
{id: '53132ea1828a1706108ebb38', name: 'Dominik Kundel'}
|
{id: '53132ea1828a1706108ebb38', name: 'Dominik Kundel'}
|
||||||
{id: '530eb29347a891b3518b3990', name: 'Ian Li'}
|
{id: '530eb29347a891b3518b3990', name: 'Ian Li'}
|
||||||
|
|
|
@ -14,6 +14,7 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
|
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'level:loaded': 'onLevelLoaded' # If Level loads after level loading view.
|
'level:loaded': 'onLevelLoaded' # If Level loads after level loading view.
|
||||||
|
'level:session-loaded': 'onSessionLoaded'
|
||||||
'level:subscription-required': 'onSubscriptionRequired' # If they'd need a subscription to start playing.
|
'level:subscription-required': 'onSubscriptionRequired' # If they'd need a subscription to start playing.
|
||||||
'level:course-membership-required': 'onCourseMembershipRequired' # If they'd need a subscription to start playing.
|
'level:course-membership-required': 'onCourseMembershipRequired' # If they'd need a subscription to start playing.
|
||||||
'subscribe-modal:subscribed': 'onSubscribed'
|
'subscribe-modal:subscribed': 'onSubscribed'
|
||||||
|
@ -44,6 +45,14 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
|
|
||||||
onLevelLoaded: (e) ->
|
onLevelLoaded: (e) ->
|
||||||
@level = e.level
|
@level = e.level
|
||||||
|
@prepareGoals()
|
||||||
|
@prepareTip()
|
||||||
|
@prepareIntro()
|
||||||
|
|
||||||
|
onSessionLoaded: (e) ->
|
||||||
|
@session = e.session if e.session.get('creator') is me.id
|
||||||
|
|
||||||
|
prepareGoals: ->
|
||||||
goalContainer = @$el.find('.level-loading-goals')
|
goalContainer = @$el.find('.level-loading-goals')
|
||||||
goalList = goalContainer.find('ul')
|
goalList = goalContainer.find('ul')
|
||||||
goalCount = 0
|
goalCount = 0
|
||||||
|
@ -55,57 +64,120 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
goalContainer.removeClass('secret')
|
goalContainer.removeClass('secret')
|
||||||
if goalCount is 1
|
if goalCount is 1
|
||||||
goalContainer.find('.panel-heading').text $.i18n.t 'play_level.goal' # Not plural
|
goalContainer.find('.panel-heading').text $.i18n.t 'play_level.goal' # Not plural
|
||||||
|
|
||||||
|
prepareTip: ->
|
||||||
tip = @$el.find('.tip')
|
tip = @$el.find('.tip')
|
||||||
if @level.get('loadingTip')
|
if @level.get('loadingTip')
|
||||||
loadingTip = utils.i18n @level.attributes, 'loadingTip'
|
loadingTip = utils.i18n @level.attributes, 'loadingTip'
|
||||||
tip.text(loadingTip)
|
tip.text(loadingTip)
|
||||||
tip.removeClass('secret')
|
tip.removeClass('secret')
|
||||||
|
|
||||||
|
prepareIntro: ->
|
||||||
|
@docs = @level.get('documentation') ? {}
|
||||||
|
specific = @docs.specificArticles or []
|
||||||
|
return unless @intro = _.find specific, name: 'Intro'
|
||||||
|
@intro.html = marked utils.filterMarkdownCodeLanguages(utils.i18n(@intro, 'body'))
|
||||||
|
@intro.name = utils.i18n @intro, 'name'
|
||||||
|
|
||||||
showReady: ->
|
showReady: ->
|
||||||
return if @shownReady
|
return if @shownReady
|
||||||
@shownReady = true
|
@shownReady = true
|
||||||
_.delay @finishShowingReady, 1500 # Let any blocking JS hog the main thread before we show that we're done.
|
_.delay @finishShowingReady, 100 # Let any blocking JS hog the main thread before we show that we're done.
|
||||||
|
|
||||||
finishShowingReady: =>
|
finishShowingReady: =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
if @options.autoUnveil
|
if @options.autoUnveil or (@session?.get('state').complete and not @getQueryVariable('intro'))
|
||||||
@startUnveiling()
|
@startUnveiling()
|
||||||
@unveil()
|
@unveil true
|
||||||
else
|
else
|
||||||
@playSound 'level_loaded', 0.75 # old: loading_ready
|
@playSound 'level_loaded', 0.75 # old: loading_ready
|
||||||
@$el.find('.progress').hide()
|
@$el.find('.progress').hide()
|
||||||
@$el.find('.start-level-button').show()
|
@$el.find('.start-level-button').show()
|
||||||
|
@unveil false
|
||||||
|
|
||||||
startUnveiling: (e) ->
|
startUnveiling: (e) ->
|
||||||
@playSound 'menu-button-click'
|
@playSound 'menu-button-click'
|
||||||
|
@unveiling = true
|
||||||
Backbone.Mediator.publish 'level:loading-view-unveiling', {}
|
Backbone.Mediator.publish 'level:loading-view-unveiling', {}
|
||||||
_.delay @onClickStartLevel, 1000 # If they never mouse-up for the click (or a modal shows up and interrupts the click), do it anyway.
|
_.delay @onClickStartLevel, 1000 # If they never mouse-up for the click (or a modal shows up and interrupts the click), do it anyway.
|
||||||
|
|
||||||
onClickStartLevel: (e) =>
|
onClickStartLevel: (e) =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
@unveil()
|
@unveil true
|
||||||
|
|
||||||
onEnterPressed: (e) ->
|
onEnterPressed: (e) ->
|
||||||
return unless @shownReady and not @$el.hasClass 'unveiled'
|
return unless @shownReady and not @unveiled
|
||||||
@startUnveiling()
|
@startUnveiling()
|
||||||
@onClickStartLevel()
|
@onClickStartLevel()
|
||||||
|
|
||||||
unveil: ->
|
unveil: (full) ->
|
||||||
return if @$el.hasClass 'unveiled'
|
return if @destroyed or @unveiled
|
||||||
@$el.addClass 'unveiled'
|
@unveiled = full
|
||||||
loadingDetails = @$el.find('.loading-details')
|
@$loadingDetails = @$el.find('#loading-details')
|
||||||
duration = parseFloat loadingDetails.css 'transition-duration'
|
duration = parseFloat(@$loadingDetails.css 'transition-duration') * 1000
|
||||||
loadingDetails.css 'top', -loadingDetails.outerHeight(true)
|
unless @$el.hasClass 'unveiled'
|
||||||
|
@$el.addClass 'unveiled'
|
||||||
|
@unveilWings duration
|
||||||
|
if full
|
||||||
|
@unveilLoadingFull()
|
||||||
|
_.delay @onUnveilEnded, duration
|
||||||
|
else
|
||||||
|
@unveilLoadingPreview duration
|
||||||
|
|
||||||
|
unveilLoadingFull: ->
|
||||||
|
# Get rid of the loading details screen entirely--the level is totally ready.
|
||||||
|
unless @unveiling
|
||||||
|
Backbone.Mediator.publish 'level:loading-view-unveiling', {}
|
||||||
|
@unveiling = true
|
||||||
|
if @$el.hasClass 'preview-screen'
|
||||||
|
@$loadingDetails.css 'right', -@$loadingDetails.outerWidth(true)
|
||||||
|
else
|
||||||
|
@$loadingDetails.css 'top', -@$loadingDetails.outerHeight(true)
|
||||||
|
@$el.removeClass 'preview-screen'
|
||||||
|
$('#canvas-wrapper').removeClass 'preview-overlay'
|
||||||
|
|
||||||
|
unveilLoadingPreview: (duration) ->
|
||||||
|
# Move the loading details screen over the code editor to preview the level.
|
||||||
|
return if @$el.hasClass 'preview-screen'
|
||||||
|
$('#canvas-wrapper').addClass 'preview-overlay'
|
||||||
|
@$el.addClass('preview-screen')
|
||||||
|
@$loadingDetails.addClass('preview')
|
||||||
|
@resize()
|
||||||
|
@onWindowResize = _.debounce @onWindowResize, 700 # Wait a bit for other views to resize before we resize
|
||||||
|
$(window).on 'resize', @onWindowResize
|
||||||
|
if @intro
|
||||||
|
@$el.find('.progress-or-start-container').addClass('intro-footer')
|
||||||
|
@$el.find('#tip-wrapper').remove()
|
||||||
|
_.delay @unveilIntro, duration
|
||||||
|
|
||||||
|
resize: ->
|
||||||
|
maxHeight = $('#page-container').outerHeight(true)
|
||||||
|
minHeight = $('#code-area').outerHeight(true)
|
||||||
|
@$el.css height: maxHeight
|
||||||
|
@$loadingDetails.css minHeight: minHeight, maxHeight: maxHeight
|
||||||
|
$intro = @$el.find('.intro-doc')
|
||||||
|
$intro.css maxHeight: minHeight - $intro.offset().top - @$el.find('.progress-or-start-container').outerHeight() - 30 - 20
|
||||||
|
|
||||||
|
unveilWings: (duration) ->
|
||||||
|
@playSound 'loading-view-unveil', 0.5
|
||||||
@$el.find('.left-wing').css left: '-100%', backgroundPosition: 'right -400px top 0'
|
@$el.find('.left-wing').css left: '-100%', backgroundPosition: 'right -400px top 0'
|
||||||
@$el.find('.right-wing').css right: '-100%', backgroundPosition: 'left -400px top 0'
|
@$el.find('.right-wing').css right: '-100%', backgroundPosition: 'left -400px top 0'
|
||||||
@playSound 'loading-view-unveil', 0.5
|
$('#level-footer-background').detach().appendTo('#page-container').slideDown(duration)
|
||||||
_.delay @onUnveilEnded, duration * 1000
|
|
||||||
$('#level-footer-background').detach().appendTo('#page-container').slideDown(duration * 1000)
|
unveilIntro: =>
|
||||||
|
return if @destroyed or not @intro or @unveiled
|
||||||
|
@$el.find('.intro-doc').html @intro.html
|
||||||
|
@resize()
|
||||||
|
|
||||||
onUnveilEnded: =>
|
onUnveilEnded: =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
Backbone.Mediator.publish 'level:loading-view-unveiled', view: @
|
Backbone.Mediator.publish 'level:loading-view-unveiled', view: @
|
||||||
|
|
||||||
|
onWindowResize: (e) =>
|
||||||
|
return if @destroyed
|
||||||
|
@$loadingDetails.css transition: 'none'
|
||||||
|
@resize()
|
||||||
|
|
||||||
onSubscriptionRequired: (e) ->
|
onSubscriptionRequired: (e) ->
|
||||||
@$el.find('.level-loading-goals, .tip, .load-progress').hide()
|
@$el.find('.level-loading-goals, .tip, .load-progress').hide()
|
||||||
@$el.find('.subscription-required').show()
|
@$el.find('.subscription-required').show()
|
||||||
|
@ -120,3 +192,7 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
|
|
||||||
onSubscribed: ->
|
onSubscribed: ->
|
||||||
document.location.reload()
|
document.location.reload()
|
||||||
|
|
||||||
|
destroy: ->
|
||||||
|
$(window).off 'resize', @onWindowResize
|
||||||
|
super()
|
||||||
|
|
|
@ -155,7 +155,7 @@ module.exports = class PlayLevelView extends RootView
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
super()
|
super()
|
||||||
window.onPlayLevelViewLoaded? @ # still a hack
|
window.onPlayLevelViewLoaded? @ # still a hack
|
||||||
@insertSubView @loadingView = new LevelLoadingView autoUnveil: @options.autoUnveil or @observing, level: @levelLoader?.level ? @level # May not have @level loaded yet
|
@insertSubView @loadingView = new LevelLoadingView autoUnveil: @options.autoUnveil or @observing, level: @levelLoader?.level ? @level, session: @levelLoader?.session ? @session # May not have @level loaded yet
|
||||||
@$el.find('#level-done-button').hide()
|
@$el.find('#level-done-button').hide()
|
||||||
$('body').addClass('is-playing')
|
$('body').addClass('is-playing')
|
||||||
$('body').bind('touchmove', false) if @isIPadApp()
|
$('body').bind('touchmove', false) if @isIPadApp()
|
||||||
|
@ -177,7 +177,6 @@ module.exports = class PlayLevelView extends RootView
|
||||||
@initVolume()
|
@initVolume()
|
||||||
@listenTo(@session, 'change:multiplayer', @onMultiplayerChanged)
|
@listenTo(@session, 'change:multiplayer', @onMultiplayerChanged)
|
||||||
|
|
||||||
@originalSessionState = $.extend(true, {}, @session.get('state'))
|
|
||||||
@register()
|
@register()
|
||||||
@controlBar.setBus(@bus)
|
@controlBar.setBus(@bus)
|
||||||
@initScriptManager()
|
@initScriptManager()
|
||||||
|
@ -341,14 +340,16 @@ module.exports = class PlayLevelView extends RootView
|
||||||
if window.currentModal and not window.currentModal.destroyed and window.currentModal.constructor isnt VictoryModal
|
if window.currentModal and not window.currentModal.destroyed and window.currentModal.constructor isnt VictoryModal
|
||||||
return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @
|
return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @
|
||||||
@surface.showLevel()
|
@surface.showLevel()
|
||||||
|
Backbone.Mediator.publish 'level:set-time', time: 0
|
||||||
if @isEditorPreview or @observing
|
if @isEditorPreview or @observing
|
||||||
@loadingView.startUnveiling()
|
@loadingView.startUnveiling()
|
||||||
@loadingView.unveil()
|
@loadingView.unveil true
|
||||||
|
|
||||||
onLoadingViewUnveiling: (e) ->
|
onLoadingViewUnveiling: (e) ->
|
||||||
@restoreSessionState()
|
@selectHero()
|
||||||
|
|
||||||
onLoadingViewUnveiled: (e) ->
|
onLoadingViewUnveiled: (e) ->
|
||||||
|
Backbone.Mediator.publish 'level:set-playing', playing: true
|
||||||
@loadingView.$el.remove()
|
@loadingView.$el.remove()
|
||||||
@removeSubView @loadingView
|
@removeSubView @loadingView
|
||||||
@loadingView = null
|
@loadingView = null
|
||||||
|
@ -372,21 +373,11 @@ module.exports = class PlayLevelView extends RootView
|
||||||
@ambientSound = createjs.Sound.play src, loop: -1, volume: 0.1
|
@ambientSound = createjs.Sound.play src, loop: -1, volume: 0.1
|
||||||
createjs.Tween.get(@ambientSound).to({volume: 1.0}, 10000)
|
createjs.Tween.get(@ambientSound).to({volume: 1.0}, 10000)
|
||||||
|
|
||||||
restoreSessionState: ->
|
selectHero: ->
|
||||||
return if @alreadyLoadedState
|
Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: true
|
||||||
@alreadyLoadedState = true
|
Backbone.Mediator.publish 'tome:select-primary-sprite', {}
|
||||||
state = @originalSessionState
|
Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: false
|
||||||
if not @level or @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder']
|
@surface.focusOnHero()
|
||||||
Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: true
|
|
||||||
Backbone.Mediator.publish 'tome:select-primary-sprite', {}
|
|
||||||
Backbone.Mediator.publish 'level:suppress-selection-sounds', suppress: false
|
|
||||||
@surface.focusOnHero()
|
|
||||||
Backbone.Mediator.publish 'level:set-time', time: 0
|
|
||||||
Backbone.Mediator.publish 'level:set-playing', playing: true
|
|
||||||
else
|
|
||||||
if state.selected
|
|
||||||
# TODO: Should also restore selected spell here by saving spellName
|
|
||||||
Backbone.Mediator.publish 'level:select-sprite', thangID: state.selected, spellName: null
|
|
||||||
|
|
||||||
# callbacks
|
# callbacks
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ template = require 'templates/play/level/tome/spell_palette_entry'
|
||||||
{me} = require 'core/auth'
|
{me} = require 'core/auth'
|
||||||
filters = require 'lib/image_filter'
|
filters = require 'lib/image_filter'
|
||||||
DocFormatter = require './DocFormatter'
|
DocFormatter = require './DocFormatter'
|
||||||
SpellView = require 'views/play/level/tome/SpellView'
|
utils = require 'core/utils'
|
||||||
|
|
||||||
module.exports = class SpellPaletteEntryView extends CocoView
|
module.exports = class SpellPaletteEntryView extends CocoView
|
||||||
tagName: 'div' # Could also try <code> instead of <div>, but would need to adjust colors
|
tagName: 'div' # Could also try <code> instead of <div>, but would need to adjust colors
|
||||||
|
@ -59,26 +59,8 @@ module.exports = class SpellPaletteEntryView extends CocoView
|
||||||
@aceEditors = []
|
@aceEditors = []
|
||||||
aceEditors = @aceEditors
|
aceEditors = @aceEditors
|
||||||
popover?.$tip?.find('.docs-ace').each ->
|
popover?.$tip?.find('.docs-ace').each ->
|
||||||
contents = $(@).text()
|
aceEditor = utils.initializeACE @, codeLanguage
|
||||||
editor = ace.edit @
|
aceEditors.push aceEditor
|
||||||
editor.setOptions maxLines: Infinity
|
|
||||||
editor.setReadOnly true
|
|
||||||
editor.setTheme 'ace/theme/textmate'
|
|
||||||
editor.setShowPrintMargin false
|
|
||||||
editor.setShowFoldWidgets false
|
|
||||||
editor.setHighlightActiveLine false
|
|
||||||
editor.setHighlightActiveLine false
|
|
||||||
editor.setBehavioursEnabled false
|
|
||||||
editor.renderer.setShowGutter false
|
|
||||||
editor.setValue contents
|
|
||||||
editor.clearSelection()
|
|
||||||
session = editor.getSession()
|
|
||||||
session.setUseWorker false
|
|
||||||
session.setMode SpellView.editModes[codeLanguage]
|
|
||||||
session.setWrapLimitRange null
|
|
||||||
session.setUseWrapMode true
|
|
||||||
session.setNewLineMode 'unix'
|
|
||||||
aceEditors.push editor
|
|
||||||
|
|
||||||
onMouseEnter: (e) ->
|
onMouseEnter: (e) ->
|
||||||
# Make sure the doc has the updated Thang so it can regenerate its prop value
|
# Make sure the doc has the updated Thang so it can regenerate its prop value
|
||||||
|
|
|
@ -9,6 +9,7 @@ SpellDebugView = require './SpellDebugView'
|
||||||
SpellToolbarView = require './SpellToolbarView'
|
SpellToolbarView = require './SpellToolbarView'
|
||||||
LevelComponent = require 'models/LevelComponent'
|
LevelComponent = require 'models/LevelComponent'
|
||||||
UserCodeProblem = require 'models/UserCodeProblem'
|
UserCodeProblem = require 'models/UserCodeProblem'
|
||||||
|
utils = require 'core/utils'
|
||||||
|
|
||||||
module.exports = class SpellView extends CocoView
|
module.exports = class SpellView extends CocoView
|
||||||
id: 'spell-view'
|
id: 'spell-view'
|
||||||
|
@ -18,14 +19,6 @@ module.exports = class SpellView extends CocoView
|
||||||
eventsSuppressed: true
|
eventsSuppressed: true
|
||||||
writable: true
|
writable: true
|
||||||
|
|
||||||
@editModes:
|
|
||||||
'javascript': 'ace/mode/javascript'
|
|
||||||
'coffeescript': 'ace/mode/coffee'
|
|
||||||
'python': 'ace/mode/python'
|
|
||||||
'clojure': 'ace/mode/clojure'
|
|
||||||
'lua': 'ace/mode/lua'
|
|
||||||
'io': 'ace/mode/text'
|
|
||||||
|
|
||||||
keyBindings:
|
keyBindings:
|
||||||
'default': null
|
'default': null
|
||||||
'vim': 'ace/keyboard/vim'
|
'vim': 'ace/keyboard/vim'
|
||||||
|
@ -93,7 +86,7 @@ module.exports = class SpellView extends CocoView
|
||||||
@aceSession = @ace.getSession()
|
@aceSession = @ace.getSession()
|
||||||
@aceDoc = @aceSession.getDocument()
|
@aceDoc = @aceSession.getDocument()
|
||||||
@aceSession.setUseWorker false
|
@aceSession.setUseWorker false
|
||||||
@aceSession.setMode SpellView.editModes[@spell.language]
|
@aceSession.setMode utils.aceEditModes[@spell.language]
|
||||||
@aceSession.setWrapLimitRange null
|
@aceSession.setWrapLimitRange null
|
||||||
@aceSession.setUseWrapMode true
|
@aceSession.setUseWrapMode true
|
||||||
@aceSession.setNewLineMode 'unix'
|
@aceSession.setNewLineMode 'unix'
|
||||||
|
@ -479,7 +472,7 @@ module.exports = class SpellView extends CocoView
|
||||||
|
|
||||||
# window.zatannaInstance = @zatanna # For debugging. Make sure to not leave active when committing.
|
# window.zatannaInstance = @zatanna # For debugging. Make sure to not leave active when committing.
|
||||||
# window.snippetEntries = snippetEntries
|
# window.snippetEntries = snippetEntries
|
||||||
lang = SpellView.editModes[e.language].substr 'ace/mode/'.length
|
lang = utils.aceEditModes[e.language].substr 'ace/mode/'.length
|
||||||
@zatanna.addSnippets snippetEntries, lang
|
@zatanna.addSnippets snippetEntries, lang
|
||||||
@editorLang = lang
|
@editorLang = lang
|
||||||
|
|
||||||
|
@ -1138,8 +1131,8 @@ module.exports = class SpellView extends CocoView
|
||||||
|
|
||||||
onChangeLanguage: (e) ->
|
onChangeLanguage: (e) ->
|
||||||
return unless @spell.canWrite()
|
return unless @spell.canWrite()
|
||||||
@aceSession.setMode SpellView.editModes[e.language]
|
@aceSession.setMode utils.aceEditModes[e.language]
|
||||||
@zatanna?.set 'language', SpellView.editModes[e.language].substr('ace/mode/')
|
@zatanna?.set 'language', utils.aceEditModes[e.language].substr('ace/mode/')
|
||||||
wasDefault = @getSource() is @spell.originalSource
|
wasDefault = @getSource() is @spell.originalSource
|
||||||
@spell.setLanguage e.language
|
@spell.setLanguage e.language
|
||||||
@reloadCode true if wasDefault
|
@reloadCode true if wasDefault
|
||||||
|
|
|
@ -4,8 +4,6 @@ Article = require 'models/Article'
|
||||||
SubscribeModal = require 'views/core/SubscribeModal'
|
SubscribeModal = require 'views/core/SubscribeModal'
|
||||||
utils = require 'core/utils'
|
utils = require 'core/utils'
|
||||||
|
|
||||||
# let's implement this once we have the docs database schema set up
|
|
||||||
|
|
||||||
module.exports = class LevelGuideView extends CocoView
|
module.exports = class LevelGuideView extends CocoView
|
||||||
template: template
|
template: template
|
||||||
id: 'guide-view'
|
id: 'guide-view'
|
||||||
|
@ -41,10 +39,10 @@ module.exports = class LevelGuideView extends CocoView
|
||||||
@docs = specific.concat(general)
|
@docs = specific.concat(general)
|
||||||
@docs = $.extend(true, [], @docs)
|
@docs = $.extend(true, [], @docs)
|
||||||
@docs = [@docs[0]] if @firstOnly and @docs[0]
|
@docs = [@docs[0]] if @firstOnly and @docs[0]
|
||||||
doc.html = marked(@filterCodeLanguages(utils.i18n(doc, 'body'))) for doc in @docs
|
doc.html = marked(utils.filterMarkdownCodeLanguages(utils.i18n(doc, 'body'))) for doc in @docs
|
||||||
doc.name = (utils.i18n doc, 'name') for doc in @docs
|
doc.name = (utils.i18n doc, 'name') for doc in @docs
|
||||||
doc.slug = _.string.slugify(doc.name) for doc in @docs
|
doc.slug = _.string.slugify(doc.name) for doc in @docs
|
||||||
super()
|
super options
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
if @vimeoListenerAttached
|
if @vimeoListenerAttached
|
||||||
|
@ -52,6 +50,7 @@ module.exports = class LevelGuideView extends CocoView
|
||||||
window.removeEventListener('message', @onMessageReceived, false)
|
window.removeEventListener('message', @onMessageReceived, false)
|
||||||
else
|
else
|
||||||
window.detachEvent('onmessage', @onMessageReceived, false)
|
window.detachEvent('onmessage', @onMessageReceived, false)
|
||||||
|
oldEditor.destroy() for oldEditor in @aceEditors ? []
|
||||||
super()
|
super()
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
|
@ -70,13 +69,17 @@ module.exports = class LevelGuideView extends CocoView
|
||||||
@$el.find('.nav-tabs li:first').addClass('active')
|
@$el.find('.nav-tabs li:first').addClass('active')
|
||||||
@$el.find('.tab-content .tab-pane:first').addClass('active')
|
@$el.find('.tab-content .tab-pane:first').addClass('active')
|
||||||
@$el.find('.nav-tabs a').click(@clickTab)
|
@$el.find('.nav-tabs a').click(@clickTab)
|
||||||
|
@configureACEEditors()
|
||||||
@playSound 'guide-open'
|
@playSound 'guide-open'
|
||||||
|
|
||||||
filterCodeLanguages: (text) ->
|
configureACEEditors: ->
|
||||||
currentLanguage = me.get('aceConfig')?.language or 'python'
|
oldEditor.destroy() for oldEditor in @aceEditors ? []
|
||||||
excludedLanguages = _.without ['javascript', 'python', 'coffeescript', 'clojure', 'lua', 'io'], currentLanguage
|
@aceEditors = []
|
||||||
exclusionRegex = new RegExp "```(#{excludedLanguages.join('|')})\n[^`]+```\n?", 'gm'
|
aceEditors = @aceEditors
|
||||||
text.replace exclusionRegex, ''
|
codeLanguage = me.get('aceConfig')?.language or 'python'
|
||||||
|
@$el.find('pre').each ->
|
||||||
|
aceEditor = utils.initializeACE @, codeLanguage
|
||||||
|
aceEditors.push aceEditor
|
||||||
|
|
||||||
clickSubscribe: (e) ->
|
clickSubscribe: (e) ->
|
||||||
level = @levelSlug # Save ref to level slug
|
level = @levelSlug # Save ref to level slug
|
||||||
|
|
Loading…
Reference in a new issue