diff --git a/app/core/utils.coffee b/app/core/utils.coffee index 94cbb152b..782d487d7 100644 --- a/app/core/utils.coffee +++ b/app/core/utils.coffee @@ -248,3 +248,39 @@ module.exports.getPrepaidCodeAmount = getPrepaidCodeAmount = (price=999, users=0 return 0 unless users > 0 and months > 0 total = price * users * months 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 diff --git a/app/schemas/models/level_session.coffee b/app/schemas/models/level_session.coffee index 66a3bddb8..e2caf8b87 100644 --- a/app/schemas/models/level_session.coffee +++ b/app/schemas/models/level_session.coffee @@ -79,15 +79,15 @@ _.extend LevelSessionSchema.properties, currentScriptOffset: type: 'number' - selected: + selected: # Not tracked any more, delete with old level types type: [ 'null' 'string' ] playing: - type: 'boolean' # Not tracked any more + type: 'boolean' # Not tracked any more, delete with old level types 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? type: 'object' additionalProperties: diff --git a/app/styles/play/level.sass b/app/styles/play/level.sass index 82ad555d4..ad2a515c5 100644 --- a/app/styles/play/level.sass +++ b/app/styles/play/level.sass @@ -72,7 +72,13 @@ $level-resize-transition-time: 0.5s width: 55% position: relative 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 background-color: #333 diff --git a/app/styles/play/level/loading.sass b/app/styles/play/level/loading.sass index 10c62bee3..5c8d6942b 100644 --- a/app/styles/play/level/loading.sass +++ b/app/styles/play/level/loading.sass @@ -8,24 +8,48 @@ background-position: top $backgroundPosition background-size: contain +$UNVEIL_TIME: 1.2s + #level-loading-view width: 100% height: 100% position: absolute z-index: 20 - $UNVEIL_TIME: 1.2s &.unveiled 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 top: 86px - left: 50% + right: 50% $WIDTH: 450px width: $WIDTH height: 450px - margin-left: (-$WIDTH / 2) + margin-right: (-$WIDTH / 2) z-index: 100 background: transparent url(/images/level/code_editor_background.png) no-repeat background-size: 100% 100% @@ -34,9 +58,22 @@ padding: 80px 80px 40px 80px text-align: center // 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' + &.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 text-align: left @@ -49,12 +86,21 @@ font-size: 20px color: black + .intro-doc + text-align: left + font-size: 16px + overflow: scroll + + img + max-width: 100% + .progress-or-start-container position: absolute bottom: 95px - width: 325px height: 80px left: 48px + right: 77px + @include transition(bottom $UNVEIL_TIME ease-out) .load-progress width: 100% @@ -131,21 +177,7 @@ width: 401px color: #666 - .left-wing, .right-wing - width: 100% - height: 100% - position: absolute - - .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) + &.preview #tip-wrapper + left: 48px + right: 77px + width: auto diff --git a/app/styles/play/menu/guide-view.sass b/app/styles/play/menu/guide-view.sass index 503097adf..25ce5b57b 100644 --- a/app/styles/play/menu/guide-view.sass +++ b/app/styles/play/menu/guide-view.sass @@ -52,3 +52,14 @@ border-image: url(/images/level/code_toolbar_submit_button_zazz_pressed.png) 14 20 20 20 fill round padding: 2px 0 0 2px 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 diff --git a/app/templates/play/level/level_loading.jade b/app/templates/play/level/level_loading.jade index 693cfc297..71ef46fd3 100644 --- a/app/templates/play/level/level_loading.jade +++ b/app/templates/play/level/level_loading.jade @@ -2,7 +2,7 @@ .right-wing -.loading-details.loading-container +#loading-details.loading-container .level-loading-goals.secret .goals-title(data-i18n="play_level.goals") Goals @@ -10,6 +10,8 @@ .errors + .intro-doc + .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 diff --git a/app/views/contribute/ArchmageView.coffee b/app/views/contribute/ArchmageView.coffee index 7a428f5f5..93cdc9401 100644 --- a/app/views/contribute/ArchmageView.coffee +++ b/app/views/contribute/ArchmageView.coffee @@ -7,6 +7,7 @@ module.exports = class ArchmageView extends ContributeClassView contributorClassName: 'archmage' contributors: [ + {id: '547acbb2af18b03c0563fdb3', name: 'David Liu', github: 'trotod'} {id: '52ccfc9bd3eb6b5a4100b60d', name: 'Glen De Cauwsemaecker', github: 'GlenDC'} {id: '52bfc3ecb7ec628868001297', name: 'Tom Steinbrecher', github: 'TomSteinbrecher'} {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: '5276ad5dcf83207a2801d3b4', name: 'Zach Martin', github: 'zachster01'} {id: '530df0cbc06854403ba67c15', name: 'Alexandru Caciulescu', github: 'Darredevil'} - {id: '5268d9baa39d7db617000b18', name: 'Thanish Muhammed', github: 'mnmtanish'} - {id: '53232f458e54704b074b271d', name: 'Bang Honam', github: 'walkingtospace'} + {id: '5268d9baa39d7db617000b18', name: 'Thanish Muhammed', github: 'mnmtanish'} + {id: '53232f458e54704b074b271d', name: 'Bang Honam', github: 'walkingtospace'} {id: '52d16c1dc931e2544d001daa', name: 'David Pendray', github: 'dpen2000'} {id: '53132ea1828a1706108ebb38', name: 'Dominik Kundel'} {id: '530eb29347a891b3518b3990', name: 'Ian Li'} diff --git a/app/views/play/level/LevelLoadingView.coffee b/app/views/play/level/LevelLoadingView.coffee index 3a7211d9a..68a6ca701 100644 --- a/app/views/play/level/LevelLoadingView.coffee +++ b/app/views/play/level/LevelLoadingView.coffee @@ -14,6 +14,7 @@ module.exports = class LevelLoadingView extends CocoView subscriptions: '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:course-membership-required': 'onCourseMembershipRequired' # If they'd need a subscription to start playing. 'subscribe-modal:subscribed': 'onSubscribed' @@ -44,6 +45,14 @@ module.exports = class LevelLoadingView extends CocoView onLevelLoaded: (e) -> @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') goalList = goalContainer.find('ul') goalCount = 0 @@ -55,57 +64,120 @@ module.exports = class LevelLoadingView extends CocoView goalContainer.removeClass('secret') if goalCount is 1 goalContainer.find('.panel-heading').text $.i18n.t 'play_level.goal' # Not plural + + prepareTip: -> tip = @$el.find('.tip') if @level.get('loadingTip') loadingTip = utils.i18n @level.attributes, 'loadingTip' tip.text(loadingTip) 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: -> return if @shownReady @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: => return if @destroyed - if @options.autoUnveil + if @options.autoUnveil or (@session?.get('state').complete and not @getQueryVariable('intro')) @startUnveiling() - @unveil() + @unveil true else @playSound 'level_loaded', 0.75 # old: loading_ready @$el.find('.progress').hide() @$el.find('.start-level-button').show() + @unveil false startUnveiling: (e) -> @playSound 'menu-button-click' + @unveiling = true 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. onClickStartLevel: (e) => return if @destroyed - @unveil() + @unveil true onEnterPressed: (e) -> - return unless @shownReady and not @$el.hasClass 'unveiled' + return unless @shownReady and not @unveiled @startUnveiling() @onClickStartLevel() - unveil: -> - return if @$el.hasClass 'unveiled' - @$el.addClass 'unveiled' - loadingDetails = @$el.find('.loading-details') - duration = parseFloat loadingDetails.css 'transition-duration' - loadingDetails.css 'top', -loadingDetails.outerHeight(true) + unveil: (full) -> + return if @destroyed or @unveiled + @unveiled = full + @$loadingDetails = @$el.find('#loading-details') + duration = parseFloat(@$loadingDetails.css 'transition-duration') * 1000 + 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('.right-wing').css right: '-100%', backgroundPosition: 'left -400px top 0' - @playSound 'loading-view-unveil', 0.5 - _.delay @onUnveilEnded, duration * 1000 - $('#level-footer-background').detach().appendTo('#page-container').slideDown(duration * 1000) + $('#level-footer-background').detach().appendTo('#page-container').slideDown(duration) + + unveilIntro: => + return if @destroyed or not @intro or @unveiled + @$el.find('.intro-doc').html @intro.html + @resize() onUnveilEnded: => return if @destroyed Backbone.Mediator.publish 'level:loading-view-unveiled', view: @ + onWindowResize: (e) => + return if @destroyed + @$loadingDetails.css transition: 'none' + @resize() + onSubscriptionRequired: (e) -> @$el.find('.level-loading-goals, .tip, .load-progress').hide() @$el.find('.subscription-required').show() @@ -120,3 +192,7 @@ module.exports = class LevelLoadingView extends CocoView onSubscribed: -> document.location.reload() + + destroy: -> + $(window).off 'resize', @onWindowResize + super() diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee index 627245cb3..f4f43f450 100644 --- a/app/views/play/level/PlayLevelView.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -155,7 +155,7 @@ module.exports = class PlayLevelView extends RootView afterRender: -> super() 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() $('body').addClass('is-playing') $('body').bind('touchmove', false) if @isIPadApp() @@ -177,7 +177,6 @@ module.exports = class PlayLevelView extends RootView @initVolume() @listenTo(@session, 'change:multiplayer', @onMultiplayerChanged) - @originalSessionState = $.extend(true, {}, @session.get('state')) @register() @controlBar.setBus(@bus) @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 return Backbone.Mediator.subscribeOnce 'modal:closed', @onLevelStarted, @ @surface.showLevel() + Backbone.Mediator.publish 'level:set-time', time: 0 if @isEditorPreview or @observing @loadingView.startUnveiling() - @loadingView.unveil() + @loadingView.unveil true onLoadingViewUnveiling: (e) -> - @restoreSessionState() + @selectHero() onLoadingViewUnveiled: (e) -> + Backbone.Mediator.publish 'level:set-playing', playing: true @loadingView.$el.remove() @removeSubView @loadingView @loadingView = null @@ -372,21 +373,11 @@ module.exports = class PlayLevelView extends RootView @ambientSound = createjs.Sound.play src, loop: -1, volume: 0.1 createjs.Tween.get(@ambientSound).to({volume: 1.0}, 10000) - restoreSessionState: -> - return if @alreadyLoadedState - @alreadyLoadedState = true - state = @originalSessionState - if not @level or @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder'] - 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 + selectHero: -> + 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() # callbacks diff --git a/app/views/play/level/tome/SpellPaletteEntryView.coffee b/app/views/play/level/tome/SpellPaletteEntryView.coffee index 27c505502..9cdc15491 100644 --- a/app/views/play/level/tome/SpellPaletteEntryView.coffee +++ b/app/views/play/level/tome/SpellPaletteEntryView.coffee @@ -3,7 +3,7 @@ template = require 'templates/play/level/tome/spell_palette_entry' {me} = require 'core/auth' filters = require 'lib/image_filter' DocFormatter = require './DocFormatter' -SpellView = require 'views/play/level/tome/SpellView' +utils = require 'core/utils' module.exports = class SpellPaletteEntryView extends CocoView tagName: 'div' # Could also try instead of
, but would need to adjust colors @@ -59,26 +59,8 @@ module.exports = class SpellPaletteEntryView extends CocoView @aceEditors = [] aceEditors = @aceEditors popover?.$tip?.find('.docs-ace').each -> - contents = $(@).text() - editor = ace.edit @ - 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 + aceEditor = utils.initializeACE @, codeLanguage + aceEditors.push aceEditor onMouseEnter: (e) -> # Make sure the doc has the updated Thang so it can regenerate its prop value diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index 1e7214182..95be903e7 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -9,6 +9,7 @@ SpellDebugView = require './SpellDebugView' SpellToolbarView = require './SpellToolbarView' LevelComponent = require 'models/LevelComponent' UserCodeProblem = require 'models/UserCodeProblem' +utils = require 'core/utils' module.exports = class SpellView extends CocoView id: 'spell-view' @@ -18,14 +19,6 @@ module.exports = class SpellView extends CocoView eventsSuppressed: 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: 'default': null 'vim': 'ace/keyboard/vim' @@ -93,7 +86,7 @@ module.exports = class SpellView extends CocoView @aceSession = @ace.getSession() @aceDoc = @aceSession.getDocument() @aceSession.setUseWorker false - @aceSession.setMode SpellView.editModes[@spell.language] + @aceSession.setMode utils.aceEditModes[@spell.language] @aceSession.setWrapLimitRange null @aceSession.setUseWrapMode true @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.snippetEntries = snippetEntries - lang = SpellView.editModes[e.language].substr 'ace/mode/'.length + lang = utils.aceEditModes[e.language].substr 'ace/mode/'.length @zatanna.addSnippets snippetEntries, lang @editorLang = lang @@ -1138,8 +1131,8 @@ module.exports = class SpellView extends CocoView onChangeLanguage: (e) -> return unless @spell.canWrite() - @aceSession.setMode SpellView.editModes[e.language] - @zatanna?.set 'language', SpellView.editModes[e.language].substr('ace/mode/') + @aceSession.setMode utils.aceEditModes[e.language] + @zatanna?.set 'language', utils.aceEditModes[e.language].substr('ace/mode/') wasDefault = @getSource() is @spell.originalSource @spell.setLanguage e.language @reloadCode true if wasDefault diff --git a/app/views/play/menu/GuideView.coffee b/app/views/play/menu/GuideView.coffee index 606c586b4..b1d727081 100644 --- a/app/views/play/menu/GuideView.coffee +++ b/app/views/play/menu/GuideView.coffee @@ -4,8 +4,6 @@ Article = require 'models/Article' SubscribeModal = require 'views/core/SubscribeModal' utils = require 'core/utils' -# let's implement this once we have the docs database schema set up - module.exports = class LevelGuideView extends CocoView template: template id: 'guide-view' @@ -41,10 +39,10 @@ module.exports = class LevelGuideView extends CocoView @docs = specific.concat(general) @docs = $.extend(true, [], @docs) @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.slug = _.string.slugify(doc.name) for doc in @docs - super() + super options destroy: -> if @vimeoListenerAttached @@ -52,6 +50,7 @@ module.exports = class LevelGuideView extends CocoView window.removeEventListener('message', @onMessageReceived, false) else window.detachEvent('onmessage', @onMessageReceived, false) + oldEditor.destroy() for oldEditor in @aceEditors ? [] super() getRenderData: -> @@ -70,13 +69,17 @@ module.exports = class LevelGuideView extends CocoView @$el.find('.nav-tabs li:first').addClass('active') @$el.find('.tab-content .tab-pane:first').addClass('active') @$el.find('.nav-tabs a').click(@clickTab) + @configureACEEditors() @playSound 'guide-open' - filterCodeLanguages: (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, '' + configureACEEditors: -> + oldEditor.destroy() for oldEditor in @aceEditors ? [] + @aceEditors = [] + aceEditors = @aceEditors + codeLanguage = me.get('aceConfig')?.language or 'python' + @$el.find('pre').each -> + aceEditor = utils.initializeACE @, codeLanguage + aceEditors.push aceEditor clickSubscribe: (e) -> level = @levelSlug # Save ref to level slug