Merge pull request #1235 from codecombat/master

Master into production
This commit is contained in:
Michael Schmatz 2014-06-26 10:42:00 -07:00
commit 475bb74001
75 changed files with 624 additions and 241 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "български език", englishDescri
# required: "You need to log in before you can go that way."
home:
slogan: "Научи се да програмираш на JavaScript, докато играеш игра "
slogan: "Научи се да програмираш, докато играеш игра "
no_ie: "CodeCombat не работи под Internet Explorer 9 или по-стар. Съжалявам!"
no_mobile: "CodeCombat не е направен за мобилни устройства и може да не работи!"
play: "Играй"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# required: "You need to log in before you can go that way."
home:
slogan: "Aprén a programar JavaScript tot Jugant"
slogan: "Aprén a programar tot Jugant"
no_ie: "CodeCombat no funciona en Internet Explorer 9 o versions anteriors. Perdó!"
no_mobile: "CodeCombat no ha estat dissenyat per dispositius mòbils i per tant no funcionarà!"
play: "Jugar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
# required: "You need to log in before you can go that way."
home:
slogan: "Naučte se programování JavaScriptu při hraní více-hráčové programovací hry."
slogan: "Naučte se programování tu při hraní více-hráčové programovací hry."
no_ie: "Omlouváme se, ale CodeCombat boužel nefunguje v Internet Exploreru 9 nebo starším."
no_mobile: "CodeCombat není navržen pro mobilní zařízení a nemusí fungovat správně!"
play: "Hrát"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# required: "You need to log in before you can go that way."
home:
slogan: "Lær at Kode Javascript ved at Spille et Spil"
slogan: "Lær at Kode ved at Spille et Spil"
no_ie: "CodeCombat kan desværre ikke køre i Internet Explorer 9 eller ældre. Beklager!"
no_mobile: "CodeCombat er ikke designet til mobile enheder og vil måske ikke virke!"
play: "Spil"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
# required: "You need to log in before you can go that way."
home:
slogan: "Lerne spielend JavaScript"
slogan: "Lerne spielend Programmieren"
no_ie: "CodeCombat läuft nicht im IE8 oder älteren Browsern. Tut uns Leid!"
no_mobile: "CodeCombat ist nicht für Mobilgeräte optimiert und funktioniert möglicherweise nicht."
play: "Spielen"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
# required: "You need to log in before you can go that way."
home:
slogan: "Lerne spielend JavaScript"
slogan: "Lerne spielend Programmieren"
no_ie: "CodeCombat läuft nicht im IE8 oder älteren Browsern. Tut uns Leid!"
no_mobile: "CodeCombat ist nicht für Mobilgeräte optimiert und funktioniert möglicherweise nicht."
play: "Spielen"

View file

@ -90,7 +90,7 @@
required: "You need to log in before you can go that way."
home:
slogan: "Learn to Code JavaScript by Playing a Game"
slogan: "Learn to Code by Playing a Game"
no_ie: "CodeCombat does not run in Internet Explorer 9 or older. Sorry!"
no_mobile: "CodeCombat wasn't designed for mobile devices and may not work!"
play: "Play"
@ -426,6 +426,7 @@
tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem."
time_current: "Now:"
time_total: "Max:"
time_goto: "Go to:"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
# required: "You need to log in before you can go that way."
home:
slogan: "Aprende a programar en JavaScript jugando"
slogan: "Aprende a programar jugando"
no_ie: "¡Lo sentimos! CodeCombat no funciona en Internet Explorer 9 o versiones anteriores."
no_mobile: "¡CodeCombat no fue diseñado para dispositivos móviles y quizás no funcione!"
play: "Jugar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
required: "Tienes que estar reginstrado antes de poder seguir por aquí."
home:
slogan: "Aprende a programar JavaScript jugando"
slogan: "Aprende a programar jugando"
no_ie: "CodeCombat no funciona en Internet Explorer 9 o anteriores. ¡Lo sentimos!"
no_mobile: "¡CodeCombat no fue diseñado para dispositivos móviles y puede que no funcione!"
play: "Jugar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
# required: "You need to log in before you can go that way."
home:
slogan: "Aprende a programar en JavaScript jugando"
slogan: "Aprende a programar jugando"
no_ie: "CodeCombat no funciona en Internet Explorer 9 o versiones anteriores. ¡Lo sentimos!"
no_mobile: "¡CodeCombat no fue diseñado para dispositivos móviles y quizás no funcione!"
play: "Jugar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# required: "You need to log in before you can go that way."
home:
slogan: "کد نویسی به زبان جاوااسکریپت را با بازی بیاموزید"
slogan: "کد نویسیا با بازی بیاموزید"
no_ie: "متاسفیم اما بازی بر روی مرورگر های اینترنت اکسپلورر نسخه ۹ به قبل اجرا نمی شود"
no_mobile: "این بازی برای دستگاه های موبایل طراحی نشده است و بر روی آن ها اجرا نمی شود"
play: "شروع بازی"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
required: "Vous devez être connecté pour voir cela"
home:
slogan: "Apprenez à coder en JavaScript tout en jouant"
slogan: "Apprenez à coder tout en jouant"
no_ie: "CodeCombat ne fonctionnera pas sous Internet Explorer 9 ou moins. Désolé !"
no_mobile: "CodeCombat n'a pas été créé pour les plateformes mobiles donc il est possible qu'il ne fonctionne pas correctement ! "
play: "Jouer"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
required: "Csak akkor mehetsz arra, ha már bejelentkeztél."
home:
slogan: "Tanulj meg JavaScript nyelven programozni, miközben játszol!"
slogan: "Tanulj meg nyelven programozni, miközben játszol!"
no_ie: "A CodeCombat nem támogatja az Internet Explorer 9, vagy korábbi verzióit. Bocsi!"
no_mobile: "A CodeCombat nem mobil eszközökre lett tervezve. Valószínűleg nem működik helyesen."
play: "Játssz!"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
# required: "You need to log in before you can go that way."
home:
slogan: "Impara a programmare in JavaScript giocando"
slogan: "Impara a programmare giocando"
no_ie: "CodeCombat non supporta Internet Explorer 9 o browser precedenti. Ci dispiace!"
no_mobile: "CodeCombat non è stato progettato per dispositivi mobile e potrebbe non funzionare!"
play: "Gioca"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# required: "You need to log in before you can go that way."
home:
slogan: "ゲームをプレイしてJavaScriptを学びましょう"
slogan: "ゲームをプレイして学びましょう"
no_ie: "大変申し訳ありませんが、ご利用のブラウザIE8以下はサポートされていません。(ChromeやFirefoxをご利用ください)"
no_mobile: "CodeCombat は携帯端末向けに制作されていないため、動作しない可能性があります。"
play: "ゲームスタート"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# required: "You need to log in before you can go that way."
home:
slogan: "쉽고 간단한 게임으로 자바스크립트 배우기"
slogan: "쉽고 간단한 게임배우기"
no_ie: "죄송하지만 코드컴뱃은 인터넷 익스플로러 9에서는 동작하지 않습니다."
no_mobile: "코드 컴뱃은 모바일 기기용으로 제작되지 않았습니다. 아마 동작하지 않을 가능성이 높습니다."
play: "시작"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
# required: "You need to log in before you can go that way."
home:
slogan: "Belajar Kod JavaScript Dengan Permainan"
slogan: "Belajar Kod bDengan Permainan"
no_ie: "CodeCombat tidak berfungsi dalam Internet Explorer 9 dan terdahulu. Maaf!"
no_mobile: "CodeCombat tidak dibangunkan untuk telefon mudah-alih dan tablet dan tidak akan berfungsi!"
play: "Mula"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
# required: "You need to log in before you can go that way."
home:
slogan: "Lær å Kode JavaScript ved å Spille et Spill"
slogan: "Lær å Kode ved å Spille et Spill"
no_ie: "CodeCombat kjører ikke på IE8 eller eldre. Beklager!"
no_mobile: "CodeCombat ble ikke designet for mobile enheter, og vil muligens ikke virke!"
play: "Spill"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
# required: "You need to log in before you can go that way."
home:
slogan: "Leer programmeren in JavaScript door het spelen van een spel"
slogan: "Leer programmeren door het spelen van een spel"
no_ie: "CodeCombat werkt niet in IE8 of ouder. Sorry!"
no_mobile: "CodeCombat is niet gemaakt voor mobiele apparaten en werkt misschien niet!"
play: "Speel"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
# required: "You need to log in before you can go that way."
home:
slogan: "Leer programmeren in JavaScript door het spelen van een spel"
slogan: "Leer programmeren door het spelen van een spel"
no_ie: "CodeCombat werkt niet in IE8 of ouder. Sorry!"
no_mobile: "CodeCombat is niet gemaakt voor mobiele apparaten en werkt misschien niet!"
play: "Speel"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
# required: "You need to log in before you can go that way."
home:
slogan: "Leer programmeren in JavaScript door het spelen van een spel"
slogan: "Leer programmeren door het spelen van een spel"
no_ie: "CodeCombat werkt niet in IE8 of ouder. Sorry!"
no_mobile: "CodeCombat is niet gemaakt voor mobiele apparaten en werkt misschien niet!"
play: "Speel"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
# required: "You need to log in before you can go that way."
home:
slogan: "Lær å Kode JavaScript ved å Spille et Spill"
slogan: "Lær å Kode ved å Spille et Spill"
no_ie: "CodeCombat kjører ikke på IE8 eller eldre. Beklager!"
no_mobile: "CodeCombat ble ikke designet for mobile enheter, og vil muligens ikke virke!"
play: "Spill"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
# required: "You need to log in before you can go that way."
home:
slogan: "Naucz się JavaScript grając"
slogan: "Naucz się programowania grając"
no_ie: "CodeCombat nie działa na Internet Explorer 9 lub starszym. Przepraszamy!"
no_mobile: "CodeCombat nie został zaprojektowany dla użądzeń przenośnych więc może nie działać!"
play: "Graj"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
# required: "You need to log in before you can go that way."
home:
slogan: "Aprenda a programar em JavaScript enquanto se diverte com um jogo."
slogan: "Aprenda a programar enquanto se diverte com um jogo."
no_ie: "CodeCombat não roda em versões mais antigas que o Internet Explorer 10. Desculpe!"
no_mobile: "CodeCombat não foi projetado para dispositivos móveis e pode não funcionar!"
play: "Jogar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
# required: "You need to log in before you can go that way."
home:
slogan: "Aprende a Programar JavaScript ao Jogar um Jogo"
slogan: "Aprende a Programar ao Jogar um Jogo"
no_ie: "O CodeCombat não corre em Internet Explorer 9 ou anterior. Desculpa!"
no_mobile: "O CodeCombat não foi desenhado para dispositivos móveis e pode não funcionar!"
play: "Jogar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
# required: "You need to log in before you can go that way."
home:
slogan: "Aprenda a programar em JavaScript enquanto se diverte com um jogo."
slogan: "Aprenda a programar enquanto se diverte com um jogo."
no_ie: "CodeCombat não roda em versões mais antigas que o Internet Explorer 10. Desculpe!"
no_mobile: "CodeCombat não foi projetado para dispositivos móveis e pode não funcionar!"
play: "Jogar"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
# required: "You need to log in before you can go that way."
home:
slogan: "Învață sa scrii JavaScript jucându-te"
slogan: "Învață sa scrii cod jucându-te"
no_ie: "CodeCombat nu merge pe Internet Explorer 9 sau mai vechi. Scuze!"
no_mobile: "CodeCombat nu a fost proiectat pentru dispozitive mobile si s-ar putea sa nu meargă!"
play: "Joacă"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
required: "Войдите для того чтобы продолжить."
home:
slogan: "Научитесь программировать на JavaScript, играя в игру"
slogan: "Научитесь программировать, играя в игру"
no_ie: "CodeCombat не работает в IE8 или более старых версиях. Нам очень жаль!"
no_mobile: "CodeCombat не приспособлен для работы на мобильных устройствах и может не работать!"
play: "Играть"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
# required: "You need to log in before you can go that way."
home:
slogan: "Nauč sa programovať v Javascripte pomocou hry"
slogan: "Nauč sa programovať pomocou hry"
no_ie: "CodeCombat nefunguje v prehliadači Internet Explorer 9 a jeho starších verziách. Ospravedlňujeme sa."
no_mobile: "CodeCombat nebol navrhnutý pre mobilné zariadenia a nemusí na nich fungovať správne!"
play: "Hraj"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
# required: "You need to log in before you can go that way."
home:
slogan: "Научи да пишеш JavaScript играјући игру"
slogan: "Научи да пишеш код играјући игру"
no_ie: "CodeCombat не ради у IE8 и старијим верзијама. Жао нам је!"
no_mobile: "CodeCombat није дизајниран за мобилне уређаје и може да се деси да не ради!"
play: "Играј"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
# required: "You need to log in before you can go that way."
home:
slogan: "Lär dig att koda Javascript genom att spela ett spel."
slogan: "Lär dig att koda genom att spela ett spel."
no_ie: "CodeCombat fungerar tyvärr inte i IE8 eller äldre."
no_mobile: "CodeCombat är inte designat för mobila enhter och fungerar kanske inte!"
play: "Spela"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
# required: "You need to log in before you can go that way."
home:
slogan: "Oyun oynayarak JavaScript kodlamayı öğrenin"
slogan: "Oyun oynayarak kodlamayı öğrenin"
no_ie: "CodeCombat maalesef Internet Explorer 9 veya daha eski sürümlerde çalışmaz."
no_mobile: "CodeCombat mobil cihazlar için tasarlanmamıştır bu sebeple mobil cihazlarda çalışmayabilir."
play: "Oyna"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
# required: "You need to log in before you can go that way."
home:
slogan: "Навчіться програмувати на JavaScript, граючи у гру"
slogan: "Навчіться програмувати, граючи у гру"
no_ie: "На жаль, CodeCombat не працює в IE8 чи більш старих версіях!"
no_mobile: "CodeCombat не призначений для мобільних приладів і може не працювати!"
play: "Грати"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
# required: "You need to log in before you can go that way."
home:
slogan: "Học mã Javascript bằng chơi Games"
slogan: "Học mã bằng chơi Games"
no_ie: "Codecombat không chạy trong Internet Explorer 9 hoặc cũ hơn. Xin lỗi!"
no_mobile: "Codecombat không được thiết kế cho các thiết bị di động và có thể không hoạt động được!"
play: "Chơi"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
# required: "You need to log in before you can go that way."
home:
slogan: "通过游戏学习 Javascript"
slogan: "通过游戏学习编程"
no_ie: "抱歉! Internet Explorer 9 等旧式预览器无法使用本网站。"
no_mobile: "CodeCombat 不是针对手机设备设计的,所以可能无法达到最好的体验!"
play: "开始游戏"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
# required: "You need to log in before you can go that way."
home:
slogan: "通過玩遊戲學習Javascript 腳本語言"
slogan: "通過玩遊戲學習編程"
no_ie: "抱歉Internet Explorer 9 等舊的瀏覽器打不開此網站"
no_mobile: "CodeCombat 不是針對手機設備設計的,所以可能會出問題!"
play: "開始遊戲"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
# required: "You need to log in before you can go that way."
home:
slogan: "打遊戲來學 Javascript"
slogan: "打遊戲來學編程"
no_ie: "對弗住!箇網站叻 Internet Explorer 9 箇粒老個瀏覽器嘸處用。"
no_mobile: "CodeCombat 勿是照手機設備設計個,怪得嘸數达弗到頂讚個享受!"
play: "遊戲開打"

View file

@ -90,7 +90,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
# required: "You need to log in before you can go that way."
home:
slogan: "通过游戏学习Javascript脚本语言"
slogan: "通过游戏学习编程"
no_ie: "抱歉Internet Explorer 9等更旧的预览器打不开此网站"
no_mobile: "CodeCombat暂时没有手机版本可能无法运行!"
play: ""

View file

@ -26,14 +26,32 @@ PropertyDocumentationSchema = c.object {
name: {type: 'string', title: "Name", description: "Name of the property."}
# not actual JS types, just whatever they describe...
type: c.shortString(title: "Type", description: "Intended type of the property.")
description: {title: "Description", type: 'string', description: "Description of the property.", format: 'markdown', maxLength: 1000}
description:
oneOf: [
{title: "Description", type: 'string', description: "Description of the property.", maxLength: 1000, format: 'markdown'}
{
type: 'object',
title: "Language Descriptions",
description: "Property descriptions by code language.",
additionalProperties: {type: 'string', description: "Description of the property.", maxLength: 1000, format: 'markdown'}
}
]
args: c.array {title: "Arguments", description: "If this property has type 'function', then provide documentation for any function arguments."}, c.FunctionArgumentSchema
owner: {title: "Owner", type: 'string', description: 'Owner of the property, like "this" or "Math".'}
example: {title: "Example", type: 'string', description: 'An optional example code block.', format: 'javascript'}
example:
oneOf: [
{title: "Example", type: 'string', description: 'An optional example code block.', format: 'javascript'}
{
type: 'object',
title: "Language Examples",
description: "Examples by code language.",
additionalProperties: {type: 'string', description: 'An example code block.', format: 'javascript'} # TODO: not JS
}
]
snippets: c.object {
title: "Snippets",
title: "Snippets",
description: "List of snippets for the respective programming languages"
},
},
javascript: c.object {title: 'JavaScript'}, c.codeSnippet 'javascript'
coffeescript: c.object {title: 'CoffeeScript'}, c.codeSnippet 'coffee'
python: c.object {title: 'Python'}, c.codeSnippet 'python'
@ -47,8 +65,26 @@ PropertyDocumentationSchema = c.object {
default: {type: 'null'}
},
type: c.shortString(title: "Type", description: "Type of the return value")
example: c.shortString(title: "Example", description: "Example return value")
description: {title: "Description", type: 'string', description: "Description of the return value.", maxLength: 1000}
example:
oneOf: [
c.shortString(title: "Example", description: "Example return value")
{
type: 'object',
title: "Language Examples",
description: "Example return values by code language.",
additionalProperties: c.shortString(description: 'Example return value.', format: 'javascript') # TODO: not JS
}
]
description:
oneOf: [
{title: "Description", type: 'string', description: "Description of the return value.", maxLength: 1000}
{
type: 'object',
title: "Language Descriptions",
description: "Example return values by code language.",
additionalProperties: {type: 'string', description: "Description of the return value.", maxLength: 1000}
}
]
DependencySchema = c.object {
title: "Component Dependency"

View file

@ -164,8 +164,26 @@ me.FunctionArgumentSchema = me.object {
name: {type: 'string', pattern: me.identifierPattern, title: "Name", description: "Name of the function argument."}
# not actual JS types, just whatever they describe...
type: me.shortString(title: "Type", description: "Intended type of the argument.")
example: me.shortString(title: "Example", description: "Example value for the argument.")
description: {title: "Description", type: 'string', description: "Description of the argument.", maxLength: 1000}
example:
oneOf: [
me.shortString(title: "Example", description: "Example value for the argument.")
{
type: 'object',
title: "Language Examples",
description: "Examples by code language.",
additionalProperties: me.shortString(description: 'Example value for the argument.')
}
]
description:
oneOf: [
{title: "Description", type: 'string', description: "Description of the argument.", maxLength: 1000}
{
type: 'object',
title: "Language Descriptions",
description: "Example argument descriptions by code language.",
additionalProperties: {type: 'string', description: "Description of the argument.", maxLength: 1000}
}
]
"default":
title: "Default"
description: "Default value of the argument. (Your code should set this.)"

View file

@ -63,9 +63,6 @@ module.exports =
"next-game-pressed":
{} # TODO schema
"focus-editor":
{} # TODO schema
"end-current-script":
{} # TODO schema
@ -87,14 +84,14 @@ module.exports =
scriptRunning: { type: 'string' }
noteGroupRunning: { type: 'string' }
timeSinceLastScriptEnded: { type: 'number' }
scriptStates:
scriptStates:
type: 'object'
additionalProperties:
title: 'Script State'
type: 'object'
additionalProperties: false
properties:
timeSinceLastEnded:
timeSinceLastEnded:
type: 'number'
description: 'seconds since this script ended last'
timeSinceLastTriggered:
@ -143,7 +140,7 @@ module.exports =
additionalProperties: false
properties:
showModal: { type: 'boolean' }
"level-highlight-dom":
type: 'object'
additionalProperties: false

View file

@ -67,7 +67,29 @@ module.exports =
"tome:spell-shown":
{} # TODO schema
# TODO proposition: add tome to name
"focus-editor":
"tome:focus-editor":
{} # TODO schema
"tome:change-language":
title: "Tome Change Language"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when the Tome should update its programming language."
type: "object"
additionalProperties: false
properties:
language:
type: "string"
required: ["language"]
"tome:spell-changed-language":
title: "Spell Changed Language"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when an individual spell has updated its code language."
type: "object"
additionalProperties: false
properties:
spell:
type: "object"
language:
type: "string"
required: ["spell"]

View file

@ -32,6 +32,7 @@
img
display: block
margin: 0 auto
@include transition(box-shadow .50s ease-in-out)
text-shadow: 2px 2px 5px black
@ -58,14 +59,160 @@
color: $yellow
font-size: 90px
font-family: Bangers
@include transition(color .10s linear)
@include transition(color .25s ease-in-out)
&:hover div
&:hover div, &.hovered div
color: lighten($yellow, 20%)
&:hover img
&:hover img, &.hovered img
filter: brightness(1.2)
-webkit-filter: brightness(1.2)
box-shadow: 0 0 5px black
box-shadow: 0 0 15px black
.code-language-logo
background-color: transparent
background-repeat: no-repeat
position: absolute
right: 35px
top: 15px
width: 50px
height: 50px
&.inverted
filter: invert(100%)
-webkit-filter: invert(100%)
.code-languages
margin: 10px 0 30px 0
&:hover
.code-language
opacity: 0.6
.code-language.selected-language:not(:hover)
opacity: 0.8
h2, h3
text-shadow: none
.code-wizard
opacity: 0.5
.code-language
cursor: pointer
text-align: center
position: relative
opacity: 0.6
&:hover
opacity: 1
h2, h3
text-shadow: 0px 0px 5px white
.code-wizard
display: block
opacity: 1
&.selected-language
opacity: 1
h2, h3
text-shadow: 0px 0px 5px white
.code-wizard
display: block
.code-wizard
position: absolute
background: transparent url(/images/pages/home/wizard.png) no-repeat
background-size: contain
width: 111px
height: 97px
display: none
.code-language-beta
background: transparent url(/images/pages/home/language_beta_sticker.png) no-repeat
background-size: contain
width: 100px
height: 32px
position: absolute
right: 20px
top: -7px
.primary-code-languages
#javascript
background: transparent url(/images/pages/home/language_js.png) no-repeat
padding-right: 150px
.code-wizard
left: 120px
#python
background: transparent url(/images/pages/home/language_python.png) no-repeat
padding-left: 150px
.code-wizard
right: 120px
.code-language
width: 498px
height: 153px
padding: 30px
margin: 0px 0 0 -6px
.code-wizard
top: -65px
h2
margin: 15px 0 5px
.secondary-code-languages
margin-left: -10px
.col-md-3
padding: 0px
.code-language
background: transparent url(/images/pages/home/language_background_small.png) no-repeat
width: 250px
height: 80px
margin: 20px 0 20px 0
padding: 20px 20px 20px 70px
.code-wizard
top: -51px
left: 89px
height: 63px
.code-language-logo
position: absolute
left: 15px
top: 17px
width: 50px
height: 50px
.code-language-beta
right: -15px
top: -16px
height: 24px
h3
margin: 0
padding: 0
#coffeescript .code-language-logo
background: transparent url(/images/pages/home/language_logo_coffeescript.png) no-repeat center
#clojure .code-language-logo
background: transparent url(/images/pages/home/language_logo_clojure.png) no-repeat center
#lua .code-language-logo
background: transparent url(/images/pages/home/language_logo_lua.png) no-repeat center
#io .code-language-logo
background: transparent url(/images/pages/home/language_logo_io.png) no-repeat center
#multiplayer-launch-modal
.modal-dialog

View file

@ -60,3 +60,29 @@
display: inline-block
margin-right: 3px
vertical-align: top
.code-language-logo
position: absolute
width: 20px
height: 20px
left: 12px
top: 34px
z-index: 10
background-color: transparent
background-repeat: no-repeat
background-size: contain
cursor: pointer
&.javascript
background-image: url(/images/pages/home/language_logo_javascript.png)
&.python
background-image: url(/images/pages/home/language_logo_python.png)
&.coffeescript
background-image: url(/images/pages/home/language_logo_coffeescript.png)
&.clojure
background-image: url(/images/pages/home/language_logo_clojure.png)
&.lua
background-image: url(/images/pages/home/language_logo_lua.png)
&.io
background-image: url(/images/pages/home/language_logo_io.png)

View file

@ -2,32 +2,62 @@ extends /templates/base
block content
h1#site-slogan(data-i18n="home.slogan") Learn to Code JavaScript by Playing a Game
h1#site-slogan(data-i18n="home.slogan") Learn to Code by Playing a Game
if frontPageContent == 'video'
//- if language is Chinese, we use youku, because China can't visit youtube.
//- otherwise, we use youtube.
if languageName == "zh-HANS"
#trailer-wrapper
<embed src="http://player.youku.com/player.php/sid/XNjk2Mzg5NjYw/v.swf" style="margin-left:15px; margin-top:8px;"allowFullScreen="true" quality="high" width="920" height="518" wmode="opaque"></embed>
img(src="/images/pages/home/video_border.png")
#mobile-trailer-wrapper
<embed src="http://player.youku.com/player.php/sid/XNjk2Mzg5NjYw/v.swf" style="margin-left:15px; margin-top:8px;"allowFullScreen="true" quality="high" width="280" height="158" wmode="opaque"></embed>
else
#trailer-wrapper
<iframe width="920" height="518" src="//www.youtube.com/embed/1zjaA13k-dA?rel=0&controls=0&modestbranding=1&showinfo=0&iv_load_policy=3&vq=hd720&wmode=transparent" frameborder="0" wmode="opaque" allowfullscreen></iframe>
img(src="/images/pages/home/video_border.png")
#mobile-trailer-wrapper
<iframe src="//www.youtube.com/embed/1zjaA13k-dA" frameborder="0" width="280" height="158"></iframe>
hr
else if frontPageContent == 'screenshot'
if me.isAdmin()
// Admin gate until fully tested
.code-languages
.primary-code-languages.row
.col-md-6
.code-language#javascript(data-code-language='javascript')
.code-wizard
h2 JavaScript
p The language of the web. Great for writing websites, web apps, HTML5 games, and servers.
.col-md-6
.code-language.beta#python(data-code-language='python')
.code-wizard
.code-language-beta
h2 Python
p Simple yet powerful, Python is a great general purpose programming language.
.secondary-code-languages.row
.col-md-3
.code-language.beta#coffeescript(data-code-language='coffeescript')
.code-language-logo
.code-wizard
.code-language-beta
h3 CoffeeScript
p Nicer JavaScript syntax
.col-md-3
.code-language.beta#clojure(data-code-language='clojure')
.code-language-logo
.code-wizard
.code-language-beta
h3 Clojure
p A modern Lisp
.col-md-3
.code-language.beta#lua(data-code-language='lua')
.code-language-logo
.code-wizard
.code-language-beta
h3 Lua
p Game scripting language
.col-md-3
.code-language.beta#io(data-code-language='io')
.code-language-logo
.code-wizard
.code-language-beta
h3 Io
p Simple but obscure
else
// Old
#front-screenshot
img(src="/images/pages/home/front_screenshot_01.png", alt="")
else if frontPageContent == 'nothing'
p &nbsp;
.alert.alert-danger.lt-ie10
strong(data-i18n="home.no_ie") CodeCombat does not run in Internet Explorer 9 or older. Sorry!
@ -49,6 +79,7 @@ block content
h3(data-i18n="home.campaign") Campaign
h4(data-i18n="home.for_beginners") For Beginners
.play-text(data-i18n="home.play") Play
.code-language-logo
a#multiplayer(href="/play/ladder")
div.game-mode-wrapper
@ -59,5 +90,6 @@ block content
h3(data-i18n="home.multiplayer") Multiplayer
h4(data-i18n="home.for_developers") For Developers
.play-text(data-i18n="home.play") Play
.code-language-logo
.clearfix

View file

@ -25,6 +25,7 @@
strong.tip(data-i18n='play_level.tip_impossible') It always seems impossible until it's done. - Nelson Mandela
strong.tip.rare(data-i18n='play_level.tip_baby_coders') In the future, even babies will be Archmages.
strong.tip.rare(data-i18n='play_level.tip_hardware_problem') Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem.
strong.tip.rare(data-i18n='play_level.tip_morale_improves') Loading will continue until morale improves.
strong.tip.rare(data-i18n='play_level.tip_all_species') We believe in equal opportunities to learn programming for all species.
strong.tip.rare(data-i18n='play_level.tip_reticulating') Reticulating spines.
@ -42,4 +43,4 @@
span= me.get('name') || 'Anoner'
.errors

View file

@ -2,7 +2,7 @@
i.icon-chevron-down
.thang-avatar-placeholder
code #{spell.name}(#{parameters})
code #{methodSignature}
.btn.btn-small.reload-code(title="Reload original code for " + spell.name)
i.icon-repeat

View file

@ -1,9 +1,10 @@
img(src="/images/level/code_palette_background.png").code-palette-background
.code-language-logo
ul(class="nav nav-pills" + (tabbed ? ' multiple-tabs' : ''))
each slug, group in entryGroupSlugs
li(class=group == "this" || slug == "available-spells" ? "active" : "")
a(data-toggle="pill", data-target='#palette-tab-' + slug)
h4= group
h4= entryGroupNames[group]
.tab-content
each slug, group in entryGroupSlugs
div(id="palette-tab-" + slug, class="tab-pane nano" + (group == "this" || slug == defaultGroupSlug ? " active" : ""))

View file

@ -11,11 +11,22 @@ if doc.example
p.example
strong Example:
div!= marked("```\n" + doc.example + "```")
else if doc.type == 'function'
else if doc.type == 'function' && argumentExamples.length
p.example
strong Example:
div
code= doc.owner + '.' + doc.name + '(' + argumentExamples.join(', ') + ');'
if language == 'javascript'
code= doc.owner + '.' + doc.name + '(' + argumentExamples.join(', ') + ');'
else if language == 'coffeescript'
code= doc.ownerName + (doc.ownerName == '@' ? '' : '.') + doc.name + ' ' + argumentExamples.join(', ')
else if language == 'python'
code= doc.ownerName + '.' + doc.name + '(' + argumentExamples.join(', ') + ')'
else if language == 'clojure'
code= '(.' + doc.name + ' ' + doc.ownerName + ' ' + argumentExamples.join(', ') + ')'
else if language == 'lua'
code= doc.ownerName + ':' + doc.name + '(' + argumentExamples.join(', ') + ')'
else if language == 'io'
code= (doc.ownerName == 'this' ? '' : doc.ownerName + ' ') + doc.name + '(' + argumentExamples.join(', ') + ')'
if (doc.type != 'function' && doc.type != 'snippet') || doc.name == 'now'
p.value

View file

@ -10,6 +10,9 @@ module.exports = class HomeView extends View
id: 'home-view'
template: template
events:
'click .code-language': 'onCodeLanguageSelected'
constructor: ->
super(arguments...)
ThangType.loadUniversalWizard()
@ -25,10 +28,7 @@ module.exports = class HomeView extends View
console.warn 'no more jquery browser version...'
c.isEnglish = (me.get('preferredLanguage') or 'en').startsWith 'en'
c.languageName = me.get('preferredLanguage')
# A/B test: https://github.com/codecombat/codecombat/issues/769
c.frontPageContent = {0: "video", 1: "screenshot", 2: "nothing"}[me.get('testGroupNumber') % 3]
application.tracker.identify frontPageContent: c.frontPageContent
application.tracker.trackEvent 'Front Page Content', frontPageContent: c.frontPageContent
c.codeLanguage = (me.get('aceConfig') ? {}).language or 'javascript'
c
afterRender: ->
@ -46,3 +46,26 @@ module.exports = class HomeView extends View
href[href.length-1] = lastLevel if href.length isnt 0
href = href.join("/")
playLink.attr("href", href)
codeLanguage = (me.get('aceConfig') ? {}).language or 'javascript'
@$el.find(".code-language[data-code-language=#{codeLanguage}]").addClass 'selected-language'
@updateLanguageLogos codeLanguage
updateLanguageLogos: (codeLanguage) ->
@$el.find('.game-mode-wrapper .code-language-logo').css('background-image', "url(/images/pages/home/language_logo_#{codeLanguage}.png)").toggleClass 'inverted', (codeLanguage in ['io', 'coffeescript'])
onCodeLanguageSelected: (e) ->
target = $(e.target).closest('.code-language')
codeLanguage = target.data('code-language')
@$el.find('.code-language').removeClass 'selected-language'
target.addClass 'selected-language'
aceConfig = me.get('aceConfig') ? {}
return if (aceConfig.language or 'javascript') is codeLanguage
aceConfig.language = codeLanguage
me.set 'aceConfig', aceConfig
me.save() # me.patch() doesn't work if aceConfig previously existed and we switched just once
firstButton = @$el.find('#beginner-campaign .game-mode-wrapper').delay(500).addClass('hovered', 500).delay(500).removeClass('hovered', 500)
lastButton = @$el.find('#multiplayer .game-mode-wrapper').delay(1000).addClass('hovered', 500).delay(500).removeClass('hovered', 500)
$('#page-container').animate {scrollTop: firstButton.offset().top - 100, easing: 'easeInOutCubic'}, 500
@updateLanguageLogos codeLanguage

View file

@ -28,7 +28,7 @@ module.exports = class ControlBarView extends View
'click #next-game-button': ->
Backbone.Mediator.publish 'next-game-pressed'
'click': -> Backbone.Mediator.publish 'focus-editor'
'click': -> Backbone.Mediator.publish 'tome:focus-editor'
constructor: (options) ->
@worldName = options.worldName

View file

@ -31,7 +31,7 @@ module.exports = class HUDView extends View
@$el.addClass 'no-selection'
onClick: (e) ->
Backbone.Mediator.publish 'focus-editor' unless $(e.target).parents('.thang-props').length
Backbone.Mediator.publish 'tome:focus-editor' unless $(e.target).parents('.thang-props').length
onFrameChanged: (e) ->
@timeProgress = e.progress
@ -126,7 +126,7 @@ module.exports = class HUDView extends View
if thangType.get('raster')
wrapper.empty().append($('<img />').attr('src', '/file/'+thangType.get('raster')))
else
stage = thangType.getPortraitStage options
return unless stage = thangType.getPortraitStage options
newCanvas = $(stage.canvas).addClass('thang-canvas')
wrapper.empty().append(newCanvas)
stage.update()

View file

@ -36,7 +36,7 @@ module.exports = class PlaybackView extends View
'click #zoom-out-button': -> Backbone.Mediator.publish('camera-zoom-out') unless @shouldIgnore()
'click #volume-button': 'onToggleVolume'
'click #play-button': 'onTogglePlay'
'click': -> Backbone.Mediator.publish 'focus-editor'
'click': -> Backbone.Mediator.publish 'tome:focus-editor'
'mouseenter #timeProgress': 'onProgressEnter'
'mouseleave #timeProgress': 'onProgressLeave'
'mousemove #timeProgress': 'onProgressHover'

View file

@ -46,7 +46,7 @@ module.exports = class CastButtonView extends View
Backbone.Mediator.publish 'tome:manual-cast', {}
onCastOptionsClick: (e) =>
Backbone.Mediator.publish 'focus-editor'
Backbone.Mediator.publish 'tome:focus-editor'
@castButtonGroup.removeClass 'open'
@setAutocastDelay $(e.target).attr 'data-delay'
false

View file

@ -0,0 +1,124 @@
popoverTemplate = require 'templates/play/level/tome/spell_palette_entry_popover'
{downTheChain} = require 'lib/world/world_utils'
window.Vector = require 'lib/world/vector' # So we can document it
safeJSONStringify = (input, maxDepth) ->
recursion = (input, path, depth) ->
output = {}
pPath = undefined
refIdx = undefined
path = path or ""
depth = depth or 0
depth++
return "{depth over " + maxDepth + "}" if maxDepth and depth > maxDepth
for p of input
pPath = ((if path then (path + ".") else "")) + p
if typeof input[p] is "function"
output[p] = "{function}"
else if typeof input[p] is "object"
refIdx = refs.indexOf(input[p])
if -1 isnt refIdx
output[p] = "{reference to " + refsPaths[refIdx] + "}"
else
refs.push input[p]
refsPaths.push pPath
output[p] = recursion(input[p], pPath, depth)
else
output[p] = input[p]
output
refs = []
refsPaths = []
maxDepth = maxDepth or 5
if typeof input is "object"
output = recursion(input)
else
output = input
JSON.stringify output, null, 1
module.exports = class DocFormatter
constructor: (@options) ->
@doc = _.cloneDeep options.doc
@fillOutDoc()
fillOutDoc: ->
if _.isString @doc
@doc = name: @doc, type: typeof @options.thang[@doc]
if @options.isSnippet
@doc.type = 'snippet'
@doc.owner = 'snippets'
@doc.shortName = @doc.shorterName = @doc.title = @doc.name
else
@doc.owner ?= 'this'
ownerName = @doc.ownerName = if @doc.owner isnt 'this' then @doc.owner else switch @options.language
when 'python', 'lua' then 'self'
when 'coffeescript' then '@'
else 'this'
if @doc.type is 'function'
sep = {clojure: ' '}[@options.language] ? ', '
argNames = (arg.name for arg in @doc.args ? []).join sep
argString = if argNames then '__ARGS__' else ''
@doc.shortName = switch @options.language
when 'coffeescript' then "#{ownerName}#{if ownerName is '@' then '' else '.'}#{@doc.name}#{if argString then ' ' + argString else '()'}"
when 'python' then "#{ownerName}.#{@doc.name}(#{argString})"
when 'lua' then "#{ownerName}:#{@doc.name}(#{argString})"
when 'clojure' then "(.#{@doc.name} #{ownerName}#{if argNames then ' ' + argString else ''})"
when 'io' then "#{if ownerName is 'this' then '' else ownerName + ' '}#{@doc.name}#{if argNames then '(' + argNames + ')' else ''}"
else "#{ownerName}.#{@doc.name}(#{argString});"
else
@doc.shortName = switch @options.language
when 'coffeescript' then "#{ownerName}#{if ownerName is '@' then '' else '.'}#{@doc.name}"
when 'python' then "#{ownerName}.#{@doc.name}"
when 'lua' then "#{ownerName}.#{@doc.name}"
when 'clojure' then "(.#{@doc.name} #{ownerName})"
when 'io' then "#{if ownerName is 'this' then '' else ownerName + ' '}#{@doc.name}"
else "#{ownerName}.#{@doc.name};"
@doc.shorterName = @doc.shortName
if @doc.type is 'function' and argString
@doc.shortName = @doc.shorterName.replace argString, argNames
@doc.shorterName = @doc.shorterName.replace argString, (if argNames.length > 6 then '...' else argNames)
if @options.language is 'javascript'
@doc.shorterName = @doc.shortName.replace ';', ''
if @doc.owner is 'this' or @options.tabbify
@doc.shorterName = @doc.shorterName.replace /^this\./, ''
@doc.title = if @options.shortenize then @doc.shorterName else @doc.shortName
# Grab the language-specific documentation for some sub-properties, if we have it.
toTranslate = [{obj: @doc, prop: 'example'}, {obj: @doc, prop: 'returns'}]
for arg in (@doc.args ? [])
toTranslate.push {obj: arg, prop: 'example'}, {obj: arg, prop: 'description'}
for {obj, prop} in toTranslate
if val = obj[prop]?[@options.language]
obj[prop] = val
else unless _.isString obj[prop]
obj[prop] = null
formatPopover: ->
content = popoverTemplate doc: @doc, language: @options.language, value: @formatValue(), marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in @doc.args ? [])
owner = if @doc.owner is 'this' then @options.thang else window[@doc.owner]
content = content.replace /#{spriteName}/g, @options.thang.type ? @options.thang.spriteName # Prefer type, and excluded the quotes we'd get with @formatValue
content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
formatValue: (v) ->
return null if @doc.type is 'snippet'
return @options.thang.now() if @doc.name is 'now'
return '[Function]' if not v and @doc.type is 'function'
unless v?
if @doc.owner is 'this'
v = @options.thang[@doc.name]
else
v = window[@doc.owner][@doc.name] # grab Math or Vector
if @doc.type is 'number' and not isNaN v
if v == Math.round v
return v
return v.toFixed 2
if _.isString v
return "\"#{v}\""
if v?.id
return v.id
if v?.name
return v.name
if _.isArray v
return '[' + (@formatValue v2 for v2 in v).join(', ') + ']'
if _.isPlainObject v
return safeJSONStringify v, 2
v

View file

@ -41,7 +41,7 @@ module.exports = class Spell
@thangs = {}
@view = new SpellView {spell: @, session: @session, worker: @worker}
@view.render() # Get it ready and code loaded in advance
@tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel
@tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel, language: @language
@tabView.render()
@team = @permissions.readwrite[0] ? "common"
Backbone.Mediator.publish 'tome:spell-created', spell: @
@ -153,6 +153,7 @@ module.exports = class Spell
for thangId, spellThang of @thangs
spellThang.aether?.setLanguage @language
spellThang.castAether = null
Backbone.Mediator.publish 'tome:spell-changed-language', spell: @, language: @language
workerMessage =
function: "updateLanguageAether"
newLanguage: @language

View file

@ -13,6 +13,7 @@ module.exports = class SpellListEntryView extends View
subscriptions:
'tome:problems-updated': "onProblemsUpdated"
'tome:spell-changed-language': 'onSpellChangedLanguage'
'level-disable-controls': 'onDisableControls'
'level-enable-controls': 'onEnableControls'
'god:new-world-created': 'onNewWorld'
@ -30,11 +31,38 @@ module.exports = class SpellListEntryView extends View
getRenderData: (context={}) ->
context = super context
context.spell = @spell
context.parameters = (@spell.parameters or []).join ', '
context.methodSignature = @createMethodSignature()
context.thangNames = (thangID for thangID, spellThang of @spell.thangs when spellThang.thang.exists).join(', ') # + ", Marcus, Robert, Phoebe, Will Smith, Zap Brannigan, You, Gandaaaaalf"
context.showTopDivider = @showTopDivider
context
createMethodSignature: ->
parameters = (@spell.parameters or []).slice()
if @spell.language in ['python', 'lua']
parameters.unshift 'self'
else if @spell.language is 'io'
parameters.unshift '...'
paramString = parameters.join ', '
name = @spell.name
switch @spell.language
when 'io'
"#{name} := method(#{paramString})"
when 'clojure'
"(defn #{name} [#{paramString}] ...)"
when 'python'
"def #{name}(#{paramString}):"
when 'lua'
"function #{name}(#{paramString}) ... end"
when 'coffeescript'
if parameters.length
"@#{name} = (#{paramString}) ->"
else
"@#{name} = ->"
when 'javascript'
"function #{name}(#{paramString}) { ... }"
else
"#{name}(#{paramString})"
getPrimarySpellThang: ->
if @lastSelectedThang
spellThang = _.find @spell.thangs, (spellThang) => spellThang.thang.id is @lastSelectedThang.id
@ -42,7 +70,7 @@ module.exports = class SpellListEntryView extends View
for thangID, spellThang of @spell.thangs
continue unless spellThang.thang.exists
return spellThang # Just do the first one else
afterRender: ->
super()
return unless @options.showTopDivider # Don't repeat Thang avatars when not changed from previous entry
@ -92,6 +120,10 @@ module.exports = class SpellListEntryView extends View
return unless e.spell is @spell
@$el.toggleClass "user-code-problem", e.problems.length
onSpellChangedLanguage: (e) ->
return unless e.spell is @spell
@render() # So that we can update parameters if needed
onDisableControls: (e) -> @toggleControls e, false
onEnableControls: (e) -> @toggleControls e, true
toggleControls: (e, enabled) ->
@ -105,7 +137,7 @@ module.exports = class SpellListEntryView extends View
onNewWorld: (e) ->
@lastSelectedThang = e.world.thangMap[@lastSelectedThang.id] if @lastSelectedThang
destroy: ->
@avatar?.destroy()
super()

View file

@ -1,9 +1,8 @@
SpellListEntryView = require './spell_list_entry_view'
ThangAvatarView = require 'views/play/level/thang_avatar_view'
template = require 'templates/play/level/tome/spell_list_tab_entry'
popoverTemplate = require 'templates/play/level/tome/spell_palette_entry_popover'
LevelComponent = require 'models/LevelComponent'
{downTheChain} = require 'lib/world/world_utils'
DocFormatter = require './doc_formatter'
module.exports = class SpellListTabEntryView extends SpellListEntryView
template: template
@ -13,6 +12,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
'tome:spell-loaded': "onSpellLoaded"
'tome:spell-changed': "onSpellChanged"
'god:new-world-created': 'onNewWorld'
'tome:spell-changed-language': 'onSpellChangedLanguage'
events:
'click .spell-list-button': 'onDropdownClick'
@ -60,43 +60,16 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
found = true
break
return unless found
doc = _.clone doc
doc.owner = 'this'
doc.shortName = doc.shorterName = doc.title = "this.#{doc.name}();"
docFormatter = new DocFormatter doc: doc, thang: @thang, language: @options.language
@$el.find('code').popover(
animation: true
html: true
placement: 'bottom'
trigger: 'hover'
content: @formatPopover doc
content: docFormatter.formatPopover()
container: @$el.parent()
)
formatPopover: (doc) ->
content = popoverTemplate doc: doc, marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in doc.args ? [])
owner = @thang
content = content.replace /#{spriteName}/g, @thang.type ? @thang.spriteName # Prefer type, and excluded the quotes we'd get with @formatValue
content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
formatValue: (v) ->
# TODO: refactor and move spell_palette_entry_view version of this somewhere else
# maybe think about making it common with what Aether does and the SpellDebugView, too
if _.isNumber v
if v == Math.round v
return v
return v.toFixed 2
if _.isString v
return "\"#{v}\""
if v?.id
return v.id
if v?.name
return v.name
if _.isArray v
return '[' + (@formatValue v2 for v2 in v).join(', ') + ']'
if _.isPlainObject v
return safeJSONStringify v, 2
v
onMouseEnterAvatar: (e) -> # Don't call super
onMouseLeaveAvatar: (e) -> # Don't call super
onClick: (e) -> # Don't call super
@ -125,6 +98,14 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
return unless e.spell is @spell
@updateReloadButton()
onSpellChangedLanguage: (e) ->
return unless e.spell is @spell
@options.language = e.language
@$el.find('code').popover 'destroy'
@render()
@docsBuilt = false
@buildDocs() if @thang
toggleControls: (e, enabled) ->
# Don't call super; do it differently
return if e.controls and not ('editor' in e.controls)

View file

@ -1,57 +1,8 @@
View = require 'views/kinds/CocoView'
template = require 'templates/play/level/tome/spell_palette_entry'
popoverTemplate = require 'templates/play/level/tome/spell_palette_entry_popover'
{me} = require 'lib/auth'
filters = require 'lib/image_filter'
{downTheChain} = require 'lib/world/world_utils'
window.Vector = require 'lib/world/vector' # So we can document it
safeJSONStringify = (input, maxDepth) ->
recursion = (input, path, depth) ->
output = {}
pPath = undefined
refIdx = undefined
path = path or ""
depth = depth or 0
depth++
return "{depth over " + maxDepth + "}" if maxDepth and depth > maxDepth
for p of input
pPath = ((if path then (path + ".") else "")) + p
if typeof input[p] is "function"
output[p] = "{function}"
else if typeof input[p] is "object"
refIdx = refs.indexOf(input[p])
if -1 isnt refIdx
output[p] = "{reference to " + refsPaths[refIdx] + "}"
else
refs.push input[p]
refsPaths.push pPath
output[p] = recursion(input[p], pPath, depth)
else
output[p] = input[p]
output
refs = []
refsPaths = []
maxDepth = maxDepth or 5
if typeof input is "object"
output = recursion(input)
else
output = input
JSON.stringify output, null, 1
# http://stackoverflow.com/a/987376/540620
$.fn.selectText = ->
el = @[0]
if document.body.createTextRange
range = document.body.createTextRange()
range.moveToElementText(el)
range.select()
else if window.getSelection
selection = window.getSelection()
range = document.createRange()
range.selectNodeContents(el)
selection.removeAllRanges()
selection.addRange(range)
DocFormatter = require './doc_formatter'
module.exports = class SpellPaletteEntryView extends View
tagName: 'div' # Could also try <code> instead of <div>, but would need to adjust colors
@ -73,25 +24,8 @@ module.exports = class SpellPaletteEntryView extends View
constructor: (options) ->
super options
@thang = options.thang
@doc = options.doc
if _.isString @doc
@doc = name: @doc, type: typeof @thang[@doc]
if options.isSnippet
@doc.type = @doc.owner = 'snippet'
@doc.shortName = @doc.shorterName = @doc.title = @doc.name
else
@doc.owner ?= 'this'
suffix = ''
if @doc.type is 'function'
argNames = (arg.name for arg in @doc.args ? []).join(', ')
argNames = '...' if argNames.length > 6
suffix = "(#{argNames})"
@doc.shortName = "#{@doc.owner}.#{@doc.name}#{suffix};"
if @doc.owner is 'this' or options.tabbify
@doc.shorterName = "#{@doc.name}#{suffix}"
else
@doc.shorterName = @doc.shortName.replace ';', ''
@doc.title = if options.shortenize then @doc.shorterName else @doc.shortName
@docFormatter = new DocFormatter options
@doc = @docFormatter.doc
getRenderData: ->
c = super()
@ -106,46 +40,15 @@ module.exports = class SpellPaletteEntryView extends View
html: true
placement: 'top'
trigger: 'manual' # Hover, until they click, which will then pin it until unclick.
content: @formatPopover()
content: @docFormatter.formatPopover()
container: '#tome-view'
)
@$el.on 'show.bs.popover', =>
Backbone.Mediator.publish 'tome:palette-hovered', thang: @thang, prop: @doc.name, entry: @
formatPopover: ->
content = popoverTemplate doc: @doc, value: @formatValue(), marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in @doc.args ? [])
owner = if @doc.owner is 'this' then @thang else window[@doc.owner]
content = content.replace /#{spriteName}/g, @thang.type ? @thang.spriteName # Prefer type, and excluded the quotes we'd get with @formatValue
content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
formatValue: (v) ->
return null if @doc.type is 'snippet'
return @thang.now() if @doc.name is 'now'
return '[Function]' if not v and @doc.type is 'function'
unless v?
if @doc.owner is 'this'
v = @thang[@doc.name]
else
v = window[@doc.owner][@doc.name] # grab Math or Vector
if @doc.type is 'number' and not isNaN v
if v == Math.round v
return v
return v.toFixed 2
if _.isString v
return "\"#{v}\""
if v?.id
return v.id
if v?.name
return v.name
if _.isArray v
return '[' + (@formatValue v2 for v2 in v).join(', ') + ']'
if _.isPlainObject v
return safeJSONStringify v, 2
v
onMouseEnter: (e) ->
# Make sure the doc has the updated Thang so it can regenerate its prop value
@$el.data('bs.popover').options.content = @formatPopover()
@$el.data('bs.popover').options.content = @docFormatter.formatPopover()
@$el.popover('setContent')
@$el.popover 'show' unless @popoverPinned or @otherPopoverPinned
@ -173,7 +76,7 @@ module.exports = class SpellPaletteEntryView extends View
onFrameChanged: (e) ->
return unless e.selectedThang?.id is @thang.id
@options.thang = @thang = e.selectedThang # Update our thang to the current version
@options.thang = @thang = @docFormatter.options.thang = e.selectedThang # Update our thang to the current version
onPaletteHovered: (e) ->
return if e.entry is @

View file

@ -4,6 +4,7 @@ template = require 'templates/play/level/tome/spell_palette'
filters = require 'lib/image_filter'
SpellPaletteEntryView = require './spell_palette_entry_view'
LevelComponent = require 'models/LevelComponent'
EditorConfigModal = require '../modal/editor_config_modal'
N_ROWS = 4
@ -16,6 +17,10 @@ module.exports = class SpellPaletteView extends View
'level-disable-controls': 'onDisableControls'
'level-enable-controls': 'onEnableControls'
'surface:frame-changed': "onFrameChanged"
'tome:change-language': 'onTomeChangedLanguage'
events:
'click .code-language-logo': 'onEditEditorConfig'
constructor: (options) ->
super options
@ -26,6 +31,7 @@ module.exports = class SpellPaletteView extends View
c = super()
c.entryGroups = @entryGroups
c.entryGroupSlugs = @entryGroupSlugs
c.entryGroupNames = @entryGroupNames
c.tabbed = _.size(@entryGroups) > 1
c.defaultGroupSlug = @defaultGroupSlug
c
@ -39,14 +45,18 @@ module.exports = class SpellPaletteView extends View
for entry in entryColumn
col.append entry.el
entry.render() # Render after appending so that we can access parent container for popover
$('.nano').nanoScroller()
$('.nano').nanoScroller()
@updateCodeLanguage @options.language
updateCodeLanguage: (language) ->
@options.language = language
@$el.find('.code-language-logo').removeClass().addClass 'code-language-logo ' + language
createPalette: ->
lcs = @supermodel.getModels LevelComponent
allDocs = {}
for lc in lcs
for doc in (lc.get('propertyDocumentation') ? [])
doc = _.clone doc
allDocs['__' + doc.name] ?= []
allDocs['__' + doc.name].push doc
if doc.type is 'snippet' then doc.owner = 'snippets'
@ -90,7 +100,7 @@ module.exports = class SpellPaletteView extends View
return 'more' if entry.doc.owner is 'this' and entry.doc.name in (propGroups.more ? [])
entry.doc.owner
@entries = _.sortBy @entries, (entry) ->
order = ['this', 'more', 'Math', 'Vector', 'snippets']
order = ['this', 'more', 'Math', 'Vector', 'String', 'Object', 'Array', 'Function', 'snippets']
index = order.indexOf groupForEntry entry
index = String.fromCharCode if index is -1 then order.length else index
index += entry.doc.name
@ -102,13 +112,18 @@ module.exports = class SpellPaletteView extends View
@entryGroups[defaultGroup] = @entries
@defaultGroupSlug = _.string.slugify defaultGroup
@entryGroupSlugs = {}
@entryGroupNames = {}
for group, entries of @entryGroups
@entryGroupSlugs[group] = _.string.slugify group
@entryGroups[group] = _.groupBy entries, (entry, i) -> Math.floor i / N_ROWS
@entryGroupSlugs[group] = _.string.slugify group
@entryGroupNames[group] = group
if thisName = {coffeescript: '@', lua: 'self', clojure: 'self'}[@options.language]
if @entryGroupNames.this
@entryGroupNames.this = thisName
null
addEntry: (doc, shortenize, tabbify, isSnippet=false) ->
new SpellPaletteEntryView doc: doc, thang: @thang, shortenize: shortenize, tabbify: tabbify, isSnippet: isSnippet
new SpellPaletteEntryView doc: doc, thang: @thang, shortenize: shortenize, tabbify: tabbify, isSnippet: isSnippet, language: @options.language
onDisableControls: (e) -> @toggleControls e, false
onEnableControls: (e) -> @toggleControls e, true
@ -132,6 +147,15 @@ module.exports = class SpellPaletteView extends View
return unless e.selectedThang?.id is @thang.id
@options.thang = @thang = e.selectedThang # Update our thang to the current version
onTomeChangedLanguage: (e) ->
@updateCodeLanguage e.language
entry.destroy() for entry in @entries
@createPalette()
@render()
onEditEditorConfig: (e) ->
@openModalView new EditorConfigModal session: @options.session
destroy: ->
entry.destroy() for entry in @entries
@toggleBackground = null

View file

@ -42,7 +42,7 @@ module.exports = class SpellView extends View
'tome:spell-changed': 'onSpellChanged'
'level:session-will-save': 'onSessionWillSave'
'modal-closed': 'focus'
'focus-editor': 'focus'
'tome:focus-editor': 'focus'
'tome:spell-statement-index-updated': 'onStatementIndexUpdated'
'tome:change-language': 'onChangeLanguage'
'tome:change-config': 'onChangeEditorConfig'
@ -299,7 +299,10 @@ module.exports = class SpellView extends View
else
@ace.setValue source
@eventsSuppressed = false
@ace.resize true # hack: @ace may not have updated its text properly, so we force it to refresh
try
@ace.resize true # hack: @ace may not have updated its text properly, so we force it to refresh
catch error
console.warn "Error resizing ACE after an update:", error
# Called from CastButtonView initially and whenever the delay is changed
setAutocastDelay: (@autocastDelay) ->

View file

@ -163,7 +163,7 @@ module.exports = class TomeView extends View
@spellList.$el.hide()
onClick: (e) ->
Backbone.Mediator.publish 'focus-editor' unless $(e.target).parents('.popover').length
Backbone.Mediator.publish 'tome:focus-editor' unless $(e.target).parents('.popover').length
clearSpellView: ->
@spellView?.dismiss()
@ -202,7 +202,7 @@ module.exports = class TomeView extends View
updateSpellPalette: (thang, spell) ->
return unless thang and @spellPaletteView?.thang isnt thang and thang.programmableProperties or thang.apiProperties
@spellPaletteView = @insertSubView new SpellPaletteView thang: thang, supermodel: @supermodel, programmable: spell?.canRead()
@spellPaletteView = @insertSubView new SpellPaletteView thang: thang, supermodel: @supermodel, programmable: spell?.canRead(), language: spell?.language ? @options.session.get('codeLanguage'), session: @options.session
@spellPaletteView.toggleControls {}, spell.view.controlsEnabled if spell # TODO: know when palette should have been disabled but didn't exist
spellFor: (thang, spellName) ->