2015-05-01 09:32:37 -04:00
// Simulate the bare minimum of the view that exists on the main site
var Scratch = Scratch || { } ;
Scratch . FlashApp = Scratch . FlashApp || { } ;
2015-05-08 10:06:50 -04:00
var editorId = "scratch" ;
2015-05-09 14:29:40 -04:00
var initialID = "home" ;
var ShortURL = {
key : "AIzaSyBlaftRUIOLFVs8nfrWvp4IBrqq9-az46A" ,
api : "https://www.googleapis.com/urlshortener/v1/url" ,
domain : "http://goo.gl"
}
2015-05-08 10:06:50 -04:00
2015-05-01 09:32:37 -04:00
function handleEmbedStatus ( e ) {
$ ( '#scratch-loader' ) . hide ( ) ;
2015-05-08 10:06:50 -04:00
var scratch = $ ( '#' + editorId ) ;
2015-05-01 09:32:37 -04:00
if ( ! e . success ) {
scratch . css ( 'marginTop' , '10' ) ;
scratch . find ( 'IMG.proj_thumb' ) . css ( 'width' , '179px' ) ;
scratch . find ( 'DIV.scratch_unsupported' ) . show ( ) ;
scratch . find ( 'DIV.scratch_loading' ) . hide ( ) ;
} else {
Scratch . FlashApp . ASobj = scratch [ 0 ] ;
}
}
// enables the SWF to log errors
function JSthrowError ( e ) {
if ( window . onerror ) window . onerror ( e , 'swf' , 0 ) ;
else console . error ( e ) ;
}
function JSeditorReady ( ) {
try {
handleParameters ( ) ;
2015-05-08 10:06:50 -04:00
$ ( "#" + editorId ) . trigger ( "editorReady" ) ;
2015-05-01 09:32:37 -04:00
return true ;
} catch ( error ) {
console . error ( error . message , "\n" , error . stack ) ;
throw error ;
}
}
function JSprojectLoaded ( ) {
loadExtensionQueue ( ) ;
}
2015-05-07 17:06:35 -04:00
function JSshowExtensionDialog ( ) {
showModal ( "dialogs" ) ;
}
2015-05-01 09:32:37 -04:00
var extensionQueue = [ ] ;
function handleParameters ( ) {
var project ;
var queryString = window . location . search . substring ( 1 ) ;
var queryVars = queryString . split ( /[&;]/ ) ;
for ( var i = 0 ; i < queryVars . length ; i ++ ) {
var nameVal = queryVars [ i ] . split ( '=' ) ;
switch ( nameVal [ 0 ] ) {
case 'ext' :
extensionQueue . push ( nameVal [ 1 ] ) ;
break ;
case 'proj' :
project = nameVal [ 1 ] ;
break ;
}
}
if ( project ) {
Scratch . FlashApp . ASobj . ASloadSBXFromURL ( project ) ;
}
else {
loadExtensionQueue ( ) ;
}
}
function loadExtensionQueue ( ) {
for ( var i = 0 ; i < extensionQueue . length ; ++ i ) {
var extensionURL = extensionQueue [ i ] ;
ScratchExtensions . loadExternalJS ( extensionURL ) ;
}
extensionQueue = [ ] ;
}
var flashVars = {
autostart : 'false' ,
extensionDevMode : 'true' ,
server : encodeURIComponent ( location . host ) ,
cloudToken : '4af4863d-a921-4004-b2cb-e0ad00ee1927' ,
cdnToken : '34f16bc63e8ada7dfd7ec12c715d0c94' ,
urlOverrides : {
sitePrefix : "http://scratch.mit.edu/" ,
siteCdnPrefix : "http://cdn.scratch.mit.edu/" ,
assetPrefix : "http://assets.scratch.mit.edu/" ,
assetCdnPrefix : "http://cdn.assets.scratch.mit.edu/" ,
projectPrefix : "http://projects.scratch.mit.edu/" ,
projectCdnPrefix : "http://cdn.projects.scratch.mit.edu/" ,
internalAPI : "internalapi/" ,
siteAPI : "site-api/" ,
staticFiles : "scratchr2/static/"
} ,
inIE : ( navigator . userAgent . indexOf ( 'MSIE' ) > - 1 )
} ;
var params = {
allowscriptaccess : 'always' ,
allowfullscreen : 'true' ,
wmode : 'direct' ,
menu : 'false'
} ;
$ . each ( flashVars , function ( prop , val ) {
if ( $ . isPlainObject ( val ) )
flashVars [ prop ] = encodeURIComponent ( JSON . stringify ( val ) ) ;
} ) ;
swfobject . switchOffAutoHideShow ( ) ;
2015-05-08 10:06:50 -04:00
swfobject . embedSWF ( 'Scratch.swf' , 'scratch' , '100%' , '100%' , '11.7.0' , 'libs/expressInstall.swf' ,
2015-05-01 09:32:37 -04:00
flashVars , params , null , handleEmbedStatus ) ;
2015-05-05 16:53:44 -04:00
2015-05-06 10:18:15 -04:00
/* File uploads */
2015-05-06 19:36:53 -04:00
function sendFileToFlash ( file ) {
2015-05-06 20:44:24 -04:00
/ *
* Use the HTML5 FileReader API to send base - 64 encoded file
* contents to Flash via ASloadBase64SBX ( or do it when the SWF
* is ready ) .
* /
2015-05-06 13:58:03 -04:00
var fileReader = new FileReader ( ) ;
2015-05-06 14:30:40 -04:00
fileReader . onload = function ( e ) {
var fileAsB64 = ab _to _b64 ( fileReader . result ) ;
2015-05-08 10:06:50 -04:00
showPage ( editorId ) ;
2015-05-06 14:30:40 -04:00
if ( Scratch . FlashApp . ASobj . ASloadBase64SBX !== undefined ) {
Scratch . FlashApp . ASobj . ASloadBase64SBX ( fileAsB64 ) ;
} else {
2015-05-06 20:17:43 -04:00
$ ( document ) . on ( "editorReady" , function ( e ) {
2015-05-06 14:30:40 -04:00
Scratch . FlashApp . ASobj . ASloadBase64SBX ( fileAsB64 ) ;
2015-05-06 20:17:43 -04:00
$ ( this ) . off ( e ) ;
} ) ;
2015-05-06 14:30:40 -04:00
}
}
2015-05-06 19:36:53 -04:00
fileReader . readAsArrayBuffer ( file ) ;
2015-05-06 10:18:15 -04:00
}
2015-05-08 21:18:44 -04:00
var loadFileListener = function ( e ) {
2015-05-06 20:44:24 -04:00
/ *
* Buttons with data - action = "load-file" trigger a file input
* prompt , passed to a handler that passes the file to Flash .
* /
$ ( '<input type="file" />' ) . on ( 'change' , function ( ) {
sendFileToFlash ( this . files [ 0 ] )
} ) . click ( ) ;
2015-05-08 21:18:44 -04:00
}
2015-05-06 10:18:15 -04:00
2015-05-08 20:07:05 -04:00
function sendURLtoFlash ( ) {
2015-05-06 20:44:24 -04:00
/ *
* Send a URL to Flash with ASloadGithubURL , or do it when the
* editor is ready .
* /
2015-05-08 20:48:53 -04:00
var urls = [ ] ;
for ( var i = 0 ; i < arguments . length ; i ++ ) {
urls . push ( arguments [ i ] ) ;
}
if ( urls . length <= 0 ) return ;
2015-05-06 19:36:53 -04:00
if ( Scratch . FlashApp . ASobj . ASloadGithubURL !== undefined ) {
2015-05-08 20:48:53 -04:00
Scratch . FlashApp . ASobj . ASloadGithubURL ( urls ) ;
2015-05-06 14:30:40 -04:00
} else {
2015-05-06 20:17:43 -04:00
$ ( document ) . on ( "editorReady" , function ( e ) {
2015-05-08 20:48:53 -04:00
Scratch . FlashApp . ASobj . ASloadGithubURL ( urls ) ;
2015-05-06 20:17:43 -04:00
$ ( this ) . off ( e ) ;
} ) ;
2015-05-06 14:30:40 -04:00
}
2015-05-06 10:18:15 -04:00
}
2015-05-06 20:44:24 -04:00
/* Load from URL */
2015-05-08 21:18:44 -04:00
var loadURLlistener = function ( e ) {
2015-05-06 20:44:24 -04:00
/ *
* Links with data - action = "load-url" send their href to Flash
* So use like ...
* < a href = "?url=urlToLoad" data - action = "load-url" > Load this < / a >
* /
2015-05-06 19:55:28 -04:00
e . preventDefault ( ) ;
2015-05-08 10:06:50 -04:00
showPage ( editorId ) ;
2015-05-08 10:09:55 -04:00
loadFromURLParameter ( $ ( this ) . attr ( "href" ) ) ;
2015-05-08 21:18:44 -04:00
}
2015-05-06 19:55:28 -04:00
2015-05-08 21:18:44 -04:00
var loadURLformListener = function ( e ) {
2015-05-06 20:44:24 -04:00
// Load text input value on submit
2015-05-06 14:59:37 -04:00
e . preventDefault ( ) ;
2015-05-08 10:06:50 -04:00
showPage ( editorId ) ;
2015-05-06 14:59:37 -04:00
sendURLtoFlash ( $ ( 'input[type="text"]' , this ) . val ( ) ) ;
2015-05-08 21:18:44 -04:00
}
2015-05-06 10:18:15 -04:00
2015-05-08 10:09:55 -04:00
function loadFromURLParameter ( queryString ) {
2015-05-06 20:44:24 -04:00
/ *
* Get all url = urlToLoad from the querystring and send to Flash
* Use like ...
* http : //scratchx.org/?url=urlToLoad1&url=urlToLoad2
* /
2015-05-08 10:09:55 -04:00
var paramString = queryString . replace ( /^\?|\/$/g , '' ) ;
2015-05-06 19:36:53 -04:00
var vars = paramString . split ( "&" ) ;
var showedEditor = false ;
2015-05-08 20:07:05 -04:00
var urls = [ ] ;
2015-05-06 19:36:53 -04:00
for ( var i = 0 ; i < vars . length ; i ++ ) {
var pair = vars [ i ] . split ( "=" ) ;
if ( pair . length > 1 && pair [ 0 ] == "url" ) {
if ( ! showedEditor ) {
2015-05-06 20:44:24 -04:00
// Only try to switch to the editor once
2015-05-08 10:06:50 -04:00
showPage ( editorId ) ;
2015-05-06 19:36:53 -04:00
showedEditor = true ;
}
2015-05-08 20:07:05 -04:00
urls . push ( pair [ 1 ] ) ;
2015-05-06 19:36:53 -04:00
}
}
2015-05-08 20:07:05 -04:00
if ( urls . length > 0 ) sendURLtoFlash . apply ( window , urls ) ;
2015-05-06 19:36:53 -04:00
}
2015-05-06 10:18:15 -04:00
2015-05-07 17:06:35 -04:00
/* Modals */
2015-05-07 11:00:47 -04:00
2015-05-09 14:29:40 -04:00
function getOrCreateFromTemplate ( elementId , templateId , elementType , appendTo , wrapper , data ) {
elementType = elementType || "div" ;
appendTo = appendTo || "body" ;
data = data || { } ;
2015-05-07 11:00:47 -04:00
var $element = $ ( "#" + elementId ) ;
if ( ! $element . length ) {
2015-05-09 14:29:40 -04:00
$template = _ . template ( $ ( "#" + templateId ) . html ( ) ) ;
2015-05-07 17:06:35 -04:00
$element = $ ( "<" + elementType + "></" + elementType + ">" )
2015-05-07 11:00:47 -04:00
. attr ( "id" , elementId )
2015-05-09 14:29:40 -04:00
. html ( $template ( data ) ) ;
2015-05-07 17:06:35 -04:00
if ( wrapper ) $element . wrapInner ( wrapper ) ;
$element . appendTo ( appendTo )
2015-05-07 11:00:47 -04:00
}
return $element ;
} ;
2015-05-09 14:29:40 -04:00
function showModal ( templateId , data ) {
2015-05-07 11:00:47 -04:00
/ *
* Copies the HTML referenced by data - template into a new element ,
2015-05-07 17:06:35 -04:00
* with id = "modal-[template value]" and creates an overlay on the
2015-05-07 11:00:47 -04:00
* page , which when clicked will close the popup .
* /
var zIndex = 100 ;
2015-05-07 17:06:35 -04:00
var modalId = "modal-" + templateId ;
$modalwrapper = $ ( "<div class='modal-fade-screen'><div class='modal-inner'></div></div>" ) ;
2015-05-09 14:29:40 -04:00
var $modal = getOrCreateFromTemplate ( modalId , templateId , "dialog" , "body" , $modalwrapper , data ) ;
2015-05-07 17:06:35 -04:00
$modal . addClass ( "modal" ) ;
$ ( ".modal-fade-screen" , $modal )
. addClass ( "visible" )
. click ( function ( e ) { $ ( this ) . trigger ( "modal:exit" ) } ) ;
2015-05-09 14:29:40 -04:00
2015-05-07 17:06:35 -04:00
$ ( "body" ) . addClass ( "modal-open" ) ;
2015-05-09 14:29:40 -04:00
2015-05-08 21:18:44 -04:00
attachListeners ( ) ;
var triggerExit = function ( e ) { $ ( this ) . trigger ( "modal:exit" ) ; }
2015-05-09 14:29:40 -04:00
$ ( ".modal-inner" , $modal ) . click ( function ( e ) { e . stopPropagation ( ) ; } )
2015-05-08 21:18:44 -04:00
$ ( document ) . on ( "click" , "[data-action='load-file'], [data-action='load-url'], [data-action='show']" , triggerExit ) ;
$ ( document ) . on ( "submit" , ".url-load-form" , triggerExit )
2015-05-07 17:06:35 -04:00
$ ( document ) . on ( "modal:exit" , function ( ) {
$ ( "body" ) . removeClass ( "modal-open" ) ;
2015-05-08 15:34:00 -04:00
Scratch . FlashApp . ASobj . ASsetModalOverlay ( false ) ;
2015-05-09 14:29:40 -04:00
$modal . remove ( ) ;
2015-05-07 11:00:47 -04:00
$ ( this ) . off ( ) ;
} ) ;
2015-05-09 14:29:40 -04:00
2015-05-08 18:53:57 -04:00
return $modal ;
2015-05-07 17:06:35 -04:00
}
2015-05-08 10:09:16 -04:00
$ ( document ) . keyup ( function ( e ) {
// Exit modals with esc key
if ( e . keyCode == 27 ) $ ( document ) . trigger ( "modal:exit" ) ;
} ) ;
2015-05-08 13:12:45 -04:00
$ ( document ) . on ( "modal:exit" , function ( e ) { Scratch . FlashApp . ASobj . ASsetModalOverlay ( false ) ; } ) ;
2015-05-08 10:08:20 -04:00
$ ( document ) . on ( 'click' , "[data-action='modal']" , function ( e ) {
2015-05-07 17:06:35 -04:00
/ *
* Usage :
* < a href = "#content" data - action = "modal" data - template = "id-for-content" > Popup < / a >
* /
e . preventDefault ( ) ;
showModal ( $ ( this ) . data ( "template" ) ) ;
2015-05-07 11:00:47 -04:00
} ) ;
2015-05-08 18:53:57 -04:00
function JSshowWarning ( extensionData ) {
$modal = showModal ( "template-warning" ) ;
$ ( "button, .modal-close" , $modal ) . click ( function ( e ) {
e . preventDefault ( ) ;
$ ( document ) . trigger ( "modal:exit" )
} ) ;
}
2015-05-07 11:00:47 -04:00
2015-05-06 10:17:51 -04:00
/* Page switching */
2015-05-08 21:18:44 -04:00
var showClickListener = function ( e ) {
2015-05-06 20:44:24 -04:00
/ *
2015-05-08 21:39:43 -04:00
* Links with data - action = "static-link" should switch the view
2015-05-06 20:44:24 -04:00
* to that page . Works like tabs sort of . Use like ...
* <!-- Makes a link to the Privacy Policy section -- >
2015-05-08 21:39:43 -04:00
* < a href = "#privacy-policy" data - action = "static-link" > Privacy Policy < / a >
2015-05-06 20:44:24 -04:00
*
* /
2015-05-08 21:39:43 -04:00
var path = $ ( this ) . attr ( "href" ) . substring ( 1 ) ;
showPage ( path ) ;
} ;
2015-05-06 10:17:51 -04:00
2015-05-08 16:24:12 -06:00
$ ( window ) . bind ( 'hashchange' , function ( e ) {
2015-05-08 21:39:43 -04:00
if ( document . location . hash == '' ) showPage ( 'home' ) ;
2015-05-08 16:24:12 -06:00
} ) ;
2015-05-05 16:53:44 -04:00
function showPage ( path ) {
2015-05-06 20:44:24 -04:00
/ *
* Show a part of the page . The site is set up like
* body
* main
* article # home
* article # privacy - policy
* ...
* editor
*
* Each < article > is a "page" of the site , plus one special
* view , which is the editor .
*
* The editor is not actually hidden , but located - 9999 px above
* the viewport . This is because if it 's hidden, it doesn' t load
* when the page is loaded .
*
* So first we have to hide everything that we ' re not going to show
* or move the editor up , then display everything we ' re going to show
* if it ' s hidden .
*
* If we are linking to an anchor within a page , then show its parent .
* /
2015-05-06 15:06:32 -04:00
var toHide = "body > main, body > main > article" ;
2015-05-05 16:53:44 -04:00
var toShow = "#" + path ;
2015-05-06 15:06:32 -04:00
var $toShow = $ ( toShow ) ;
2015-05-05 16:53:44 -04:00
2015-05-07 17:06:58 -04:00
if ( ! $toShow . length ) return ;
2015-05-06 19:36:53 -04:00
$ ( toHide ) . filter ( ":visible" ) . hide ( ) ;
2015-05-08 10:06:50 -04:00
if ( toShow != "#" + editorId ) $ ( "#" + editorId ) . css ( { top : "-9999px" } ) ;
2015-05-06 15:06:32 -04:00
$ ( "body > main, body > main > article" ) . has ( $toShow ) . show ( ) ;
$toShow . show ( ) ;
2015-05-08 10:06:50 -04:00
if ( path == editorId ) {
2015-05-06 15:06:32 -04:00
$toShow . css ( { top : 0 } ) ;
}
2015-05-05 16:53:44 -04:00
}
2015-05-09 14:29:40 -04:00
/* URL Shortening */
function shorten ( url , done ) {
var data = { longUrl : url } ;
$ . ajax ( {
url : ShortURL . api + '?' + $ . param ( { key : ShortURL . key } ) ,
type : "post" ,
data : JSON . stringify ( data ) ,
dataType : "json" ,
contentType : "application/json"
} ) . done ( done ) ;
}
function getUrlFor ( extensions ) {
return document . location . origin + '/?' + $ . param (
extensions . map ( function ( url ) {
return { name : 'url' , value : url }
} )
) ;
}
function UrlParser ( url ) {
parser = document . createElement ( 'a' ) ;
parser . href = url ;
return parser
}
function showShortUrl ( url ) {
shorten ( url , function ( data ) {
var parser = UrlParser ( data . id ) ;
var id = parser . pathname . replace ( '/' , '' ) ;
parser . href = window . location . origin ;
parser . hash = "#!" + id ;
var shortUrl = parser . href ;
var context = {
longUrl : data . longUrl ,
shortUrl : shortUrl
}
$modal = showModal ( "template-short-url" , context ) ;
var client = new ZeroClipboard ( $ ( 'button' , $modal ) ) ;
} ) ;
}
function JSshowShortUrlFor ( ) {
showShortUrl ( getUrlFor ( Array . prototype . slice . call ( arguments ) ) ) ;
}
function decompress ( id , done ) {
var data = { shortUrl : ShortURL . domain + id }
$ . ajax ( {
url : ShortURL . api + '?' + $ . param ( {
key : ShortURL . key ,
shortUrl : ShortURL . domain + '/' + id } ) ,
dataType : "json" ,
contentType : "application/json"
} ) . done ( done ) ;
}
/* Setup */
2015-05-08 21:18:44 -04:00
function attachListeners ( ) {
$ ( "[data-action='load-file']" ) . on ( 'click' , loadFileListener ) ;
$ ( "[data-action='load-url']" ) . on ( 'click' , loadURLlistener ) ;
$ ( ".url-load-form" ) . on ( 'submit' , loadURLformListener ) ;
$ ( "[data-action='show']" ) . on ( 'click' , showClickListener ) ;
}
2015-05-06 09:53:59 -04:00
function initPage ( ) {
2015-05-06 20:44:24 -04:00
/ *
* On load , show the page identified by the URL fragment . Default to # home .
* /
2015-05-08 21:18:44 -04:00
attachListeners ( ) ;
2015-05-09 14:29:40 -04:00
if ( window . location . hash ) {
if ( window . location . hash . charAt ( 1 ) == "!" ) {
decompress ( window . location . hash . substr ( 2 ) , function ( data ) {
var parser = UrlParser ( data . longUrl ) ;
if ( parser . hostname == window . location . hostname ) window . location = data . longUrl ;
return ;
} ) ;
} else {
initialID = window . location . hash . substr ( 1 ) ;
}
}
2015-05-06 09:53:59 -04:00
showPage ( initialID ) ;
2015-05-08 10:09:55 -04:00
loadFromURLParameter ( window . location . search ) ;
2015-05-06 09:53:59 -04:00
}
$ ( initPage ) ;