2013-11-07 23:10:38 +00:00
/*globals Markdown, requirejs */
2013-05-26 22:59:03 +00:00
define ( [
"jquery" ,
2013-05-29 19:55:23 +00:00
"underscore" ,
2013-08-08 23:32:03 +00:00
"crel" ,
2013-09-09 00:08:55 +00:00
"ace" ,
2013-11-05 23:03:38 +00:00
"constants" ,
2013-05-26 22:59:03 +00:00
"utils" ,
2013-11-05 23:03:38 +00:00
"storage" ,
2013-05-27 19:45:33 +00:00
"settings" ,
2013-07-30 08:46:36 +00:00
"eventMgr" ,
2013-09-30 00:16:01 +00:00
"shortcutMgr" ,
2013-06-10 21:22:32 +00:00
"mousetrap" ,
2013-08-04 15:49:14 +00:00
"text!html/bodyIndex.html" ,
"text!html/bodyViewer.html" ,
2013-06-10 21:22:32 +00:00
"text!html/settingsTemplateTooltip.html" ,
2013-07-07 20:07:11 +00:00
"text!html/settingsUserCustomExtensionTooltip.html" ,
2013-05-26 22:59:03 +00:00
"storage" ,
2013-08-30 22:45:29 +00:00
"uilayout" ,
2013-09-15 14:14:42 +00:00
'pagedown-ace' ,
2013-12-05 00:25:17 +00:00
'pagedown-light' ,
2013-09-14 16:59:40 +00:00
'libs/ace_mode' ,
'ace/requirejs/text!ace/css/editor.css' ,
'ace/requirejs/text!ace/theme/textmate.css' ,
2013-09-19 19:48:21 +00:00
'ace/ext/spellcheck' ,
2013-09-21 11:03:29 +00:00
'ace/ext/searchbox'
2013-09-14 16:59:40 +00:00
2013-11-05 23:03:38 +00:00
] , function ( $ , _ , crel , ace , constants , utils , storage , settings , eventMgr , shortcutMgr , mousetrap , bodyIndexHTML , bodyViewerHTML , settingsTemplateTooltipHTML , settingsUserCustomExtensionTooltipHTML ) {
2013-04-02 18:42:47 +00:00
2013-05-29 19:55:23 +00:00
var core = { } ;
2014-04-21 17:21:03 +00:00
2013-05-29 19:55:23 +00:00
// Used for periodic tasks
2013-11-07 23:10:38 +00:00
var intervalId ;
2013-05-29 19:55:23 +00:00
// Used to detect user activity
2013-08-04 00:53:46 +00:00
var isUserReal = false ;
2013-05-29 19:55:23 +00:00
var userActive = false ;
var windowUnique = true ;
var userLastActivity = 0 ;
function setUserActive ( ) {
2013-08-04 00:53:46 +00:00
isUserReal = true ;
2013-05-29 19:55:23 +00:00
userActive = true ;
2013-08-04 00:53:46 +00:00
var currentTime = utils . currentTime ;
if ( currentTime > userLastActivity + 1000 ) {
userLastActivity = currentTime ;
eventMgr . onUserActive ( ) ;
}
2013-05-29 19:55:23 +00:00
}
function isUserActive ( ) {
2013-11-05 23:03:38 +00:00
if ( utils . currentTime - userLastActivity > constants . USER _IDLE _THRESHOLD ) {
2013-05-29 19:55:23 +00:00
userActive = false ;
}
return userActive && windowUnique ;
}
2014-04-21 17:21:03 +00:00
2013-05-29 19:55:23 +00:00
// Used to only have 1 window of the application in the same browser
2013-11-07 23:10:38 +00:00
var windowId ;
2013-05-29 19:55:23 +00:00
function checkWindowUnique ( ) {
2013-08-04 00:53:46 +00:00
if ( isUserReal === false || windowUnique === false ) {
2013-05-29 19:55:23 +00:00
return ;
}
if ( windowId === undefined ) {
windowId = utils . randomString ( ) ;
2013-11-05 23:03:38 +00:00
storage . frontWindowId = windowId ;
2013-05-29 19:55:23 +00:00
}
2013-11-05 23:03:38 +00:00
var frontWindowId = storage . frontWindowId ;
2013-05-29 19:55:23 +00:00
if ( frontWindowId != windowId ) {
windowUnique = false ;
if ( intervalId !== undefined ) {
clearInterval ( intervalId ) ;
}
$ ( ".modal" ) . modal ( "hide" ) ;
2013-09-19 21:54:50 +00:00
$ ( '.modal-non-unique' ) . modal ( "show" ) ;
2013-12-14 22:44:59 +00:00
// Attempt to close the window
window . close ( ) ;
2013-05-29 19:55:23 +00:00
}
}
// Offline management
2013-08-04 00:53:46 +00:00
var isOffline = false ;
2013-05-29 19:55:23 +00:00
var offlineTime = utils . currentTime ;
core . setOffline = function ( ) {
offlineTime = utils . currentTime ;
2013-08-04 00:53:46 +00:00
if ( isOffline === false ) {
isOffline = true ;
2013-07-30 08:46:36 +00:00
eventMgr . onOfflineChanged ( true ) ;
2013-05-29 19:55:23 +00:00
}
} ;
function setOnline ( ) {
2013-08-04 00:53:46 +00:00
if ( isOffline === true ) {
isOffline = false ;
2013-07-30 08:46:36 +00:00
eventMgr . onOfflineChanged ( false ) ;
2013-05-29 19:55:23 +00:00
}
}
function checkOnline ( ) {
// Try to reconnect if we are offline but we have some network
2013-11-05 23:03:38 +00:00
if ( isOffline === true && navigator . onLine === true && offlineTime + constants . CHECK _ONLINE _PERIOD < utils . currentTime ) {
2013-05-29 19:55:23 +00:00
offlineTime = utils . currentTime ;
// Try to download anything to test the connection
$ . ajax ( {
url : "//www.google.com/jsapi" ,
2013-11-05 23:03:38 +00:00
timeout : constants . AJAX _TIMEOUT ,
2013-05-29 19:55:23 +00:00
dataType : "script"
} ) . done ( function ( ) {
setOnline ( ) ;
} ) ;
}
}
// Load settings in settings dialog
2013-11-07 23:10:38 +00:00
var $themeInputElt ;
2013-05-29 19:55:23 +00:00
function loadSettings ( ) {
// Layout orientation
utils . setInputRadio ( "radio-layout-orientation" , settings . layoutOrientation ) ;
// Theme
2013-11-07 23:10:38 +00:00
utils . setInputValue ( $themeInputElt , window . theme ) ;
2013-08-20 22:40:19 +00:00
$themeInputElt . change ( ) ;
2013-05-29 19:55:23 +00:00
// Lazy rendering
utils . setInputChecked ( "#input-settings-lazy-rendering" , settings . lazyRendering ) ;
2013-06-27 23:10:04 +00:00
// Editor font family
utils . setInputValue ( "#input-settings-editor-font-family" , settings . editorFontFamily ) ;
2013-05-29 19:55:23 +00:00
// Editor font size
utils . setInputValue ( "#input-settings-editor-font-size" , settings . editorFontSize ) ;
2013-09-15 01:35:58 +00:00
// Max width
utils . setInputValue ( "#input-settings-max-width" , settings . maxWidth ) ;
2013-05-29 19:55:23 +00:00
// Default content
utils . setInputValue ( "#textarea-settings-default-content" , settings . defaultContent ) ;
2013-12-05 20:59:57 +00:00
// Mode
utils . setInputRadio ( "radio-settings-mode" , storage . mode || '_ace_' ) ;
2013-05-29 19:55:23 +00:00
// Commit message
utils . setInputValue ( "#input-settings-publish-commit-msg" , settings . commitMsg ) ;
2013-12-23 22:41:33 +00:00
// Gdrive multi-accounts
utils . setInputValue ( "#input-settings-gdrive-multiaccount" , settings . gdriveMultiAccount ) ;
2013-10-06 14:34:40 +00:00
// Gdrive full access
utils . setInputChecked ( "#input-settings-gdrive-full-access" , settings . gdriveFullAccess ) ;
2013-12-23 22:41:33 +00:00
// Dropbox full access
utils . setInputChecked ( "#input-settings-dropbox-full-access" , settings . dropboxFullAccess ) ;
2013-12-27 21:12:04 +00:00
// GitHub full access
utils . setInputChecked ( "#input-settings-github-full-access" , settings . githubFullAccess ) ;
2013-05-29 19:55:23 +00:00
// Template
utils . setInputValue ( "#textarea-settings-publish-template" , settings . template ) ;
2013-09-23 22:12:35 +00:00
// PDF template
2013-10-27 19:19:56 +00:00
utils . setInputValue ( "#textarea-settings-pdf-template" , settings . pdfTemplate ) ;
// PDF page size
utils . setInputValue ( "#input-settings-pdf-page-size" , settings . pdfPageSize ) ;
2013-05-29 19:55:23 +00:00
// SSH proxy
utils . setInputValue ( "#input-settings-ssh-proxy" , settings . sshProxy ) ;
2014-04-21 17:21:03 +00:00
2013-09-30 22:37:58 +00:00
// Load shortcuts settings
shortcutMgr . loadSettings ( ) ;
2013-05-29 19:55:23 +00:00
// Load extension settings
2013-07-30 08:46:36 +00:00
eventMgr . onLoadSettings ( ) ;
2013-05-29 19:55:23 +00:00
}
// Save settings from settings dialog
function saveSettings ( event ) {
var newSettings = { } ;
// Layout orientation
newSettings . layoutOrientation = utils . getInputRadio ( "radio-layout-orientation" ) ;
// Theme
2013-08-20 22:40:19 +00:00
var theme = utils . getInputValue ( $themeInputElt ) ;
2013-05-29 19:55:23 +00:00
// Lazy Rendering
newSettings . lazyRendering = utils . getInputChecked ( "#input-settings-lazy-rendering" ) ;
2013-06-27 23:10:04 +00:00
// Editor font family
newSettings . editorFontFamily = utils . getInputTextValue ( "#input-settings-editor-font-family" , event ) ;
2013-05-29 19:55:23 +00:00
// Editor font size
newSettings . editorFontSize = utils . getInputIntValue ( "#input-settings-editor-font-size" , event , 1 , 99 ) ;
2013-09-15 01:35:58 +00:00
// Max width
newSettings . maxWidth = utils . getInputIntValue ( "#input-settings-max-width" , event , 1 ) ;
2013-05-29 19:55:23 +00:00
// Default content
newSettings . defaultContent = utils . getInputValue ( "#textarea-settings-default-content" ) ;
2013-12-05 20:59:57 +00:00
// Mode
var mode = utils . getInputRadio ( "radio-settings-mode" ) ;
2013-05-29 19:55:23 +00:00
// Commit message
newSettings . commitMsg = utils . getInputTextValue ( "#input-settings-publish-commit-msg" , event ) ;
2013-12-23 22:41:33 +00:00
// Gdrive multi-accounts
newSettings . gdriveMultiAccount = utils . getInputIntValue ( "#input-settings-gdrive-multiaccount" ) ;
2013-10-06 14:34:40 +00:00
// Gdrive full access
newSettings . gdriveFullAccess = utils . getInputChecked ( "#input-settings-gdrive-full-access" ) ;
2013-12-23 22:41:33 +00:00
// Drobox full access
newSettings . dropboxFullAccess = utils . getInputChecked ( "#input-settings-dropbox-full-access" ) ;
2013-12-27 21:12:04 +00:00
// GitHub full access
newSettings . githubFullAccess = utils . getInputChecked ( "#input-settings-github-full-access" ) ;
2013-05-29 19:55:23 +00:00
// Template
newSettings . template = utils . getInputTextValue ( "#textarea-settings-publish-template" , event ) ;
2013-09-23 22:12:35 +00:00
// PDF template
2013-10-27 19:19:56 +00:00
newSettings . pdfTemplate = utils . getInputTextValue ( "#textarea-settings-pdf-template" , event ) ;
// PDF page size
newSettings . pdfPageSize = utils . getInputValue ( "#input-settings-pdf-page-size" ) ;
2013-05-29 19:55:23 +00:00
// SSH proxy
newSettings . sshProxy = utils . checkUrl ( utils . getInputTextValue ( "#input-settings-ssh-proxy" , event ) , true ) ;
2013-10-11 21:47:00 +00:00
// Save shortcuts settings
shortcutMgr . saveSettings ( newSettings ) ;
2013-05-29 19:55:23 +00:00
// Save extension settings
newSettings . extensionSettings = { } ;
2013-07-30 08:46:36 +00:00
eventMgr . onSaveSettings ( newSettings . extensionSettings , event ) ;
2013-05-29 19:55:23 +00:00
if ( ! event . isPropagationStopped ( ) ) {
2013-12-23 22:41:33 +00:00
if ( settings . dropboxFullAccess !== newSettings . dropboxFullAccess ) {
storage . removeItem ( 'dropbox.lastChangeId' ) ;
}
2013-05-29 19:55:23 +00:00
$ . extend ( settings , newSettings ) ;
2013-11-05 23:03:38 +00:00
storage . settings = JSON . stringify ( settings ) ;
2013-12-02 23:29:48 +00:00
storage . themeV3 = theme ;
2013-12-05 20:59:57 +00:00
storage . mode = mode ;
2013-05-29 19:55:23 +00:00
}
}
2013-08-10 11:34:30 +00:00
// Set the panels visibility
2013-11-07 23:10:38 +00:00
var layout ;
var $menuPanelElt ;
var $documentPanelElt ;
2013-08-10 11:34:30 +00:00
function setPanelVisibility ( forceHide ) {
if ( forceHide === true || layout . state . north . isClosed ) {
2013-08-22 00:19:59 +00:00
$menuPanelElt . hide ( ) ;
$documentPanelElt . hide ( ) ;
2013-08-10 11:34:30 +00:00
}
else {
2013-08-22 00:19:59 +00:00
$menuPanelElt . show ( ) ;
$documentPanelElt . show ( ) ;
2013-08-10 11:34:30 +00:00
}
}
2013-08-13 00:03:38 +00:00
2013-08-10 11:34:30 +00:00
// Set the preview button visibility
2013-11-07 23:10:38 +00:00
var $previewButtonsElt ;
2013-08-08 23:32:03 +00:00
function setPreviewButtonsVisibility ( forceHide ) {
if ( forceHide === true || layout . state . east . isClosed ) {
2013-08-22 00:19:59 +00:00
$previewButtonsElt . hide ( ) ;
2013-08-08 23:32:03 +00:00
}
else {
2013-08-22 00:19:59 +00:00
$previewButtonsElt . show ( ) ;
2013-08-08 23:32:03 +00:00
}
}
2013-08-08 21:53:15 +00:00
2013-09-09 23:32:24 +00:00
// Create ACE editor
2013-11-07 23:10:38 +00:00
var aceEditor ;
2013-09-09 23:32:24 +00:00
function createAceEditor ( ) {
2013-09-09 00:08:55 +00:00
aceEditor = ace . edit ( "wmd-input" ) ;
2013-09-19 19:48:21 +00:00
aceEditor . setOption ( "spellcheck" , true ) ;
2013-09-09 00:08:55 +00:00
aceEditor . renderer . setShowGutter ( false ) ;
aceEditor . renderer . setPrintMarginColumn ( false ) ;
2013-11-05 23:03:38 +00:00
aceEditor . renderer . setPadding ( constants . EDITOR _DEFAULT _PADDING ) ;
2013-09-09 00:08:55 +00:00
aceEditor . session . setUseWrapMode ( true ) ;
2013-09-21 00:41:41 +00:00
aceEditor . session . setNewLineMode ( "unix" ) ;
2013-09-14 16:59:40 +00:00
aceEditor . session . setMode ( "libs/ace_mode" ) ;
2013-12-27 11:27:08 +00:00
aceEditor . session . $selectLongWords = true ;
2013-09-15 01:35:58 +00:00
// Make bold titles...
2013-09-09 23:32:24 +00:00
( function ( self ) {
2013-09-15 01:35:58 +00:00
function checkLine ( currentLine ) {
var line = self . lines [ currentLine ] ;
if ( line . length !== 0 ) {
if ( line [ 0 ] . type . indexOf ( "markup.heading.multi" ) === 0 ) {
_ . each ( self . lines [ currentLine - 1 ] , function ( previousLineObject ) {
previousLineObject . type = "markup.heading.prev.multi" ;
} ) ;
}
}
}
2013-09-09 23:32:24 +00:00
function customWorker ( ) {
2013-09-15 01:35:58 +00:00
// Duplicate from background_tokenizer.js
if ( ! self . running ) {
return ;
}
2013-09-09 23:32:24 +00:00
var workerStart = new Date ( ) ;
2013-09-15 01:35:58 +00:00
var currentLine = self . currentLine ;
var endLine = - 1 ;
2013-09-09 23:32:24 +00:00
var doc = self . doc ;
2013-09-15 01:35:58 +00:00
while ( self . lines [ currentLine ] ) {
currentLine ++ ;
}
var startLine = currentLine ;
2013-09-09 23:32:24 +00:00
var len = doc . getLength ( ) ;
2013-09-15 01:35:58 +00:00
var processedLines = 0 ;
self . running = false ;
while ( currentLine < len ) {
self . $tokenizeRow ( currentLine ) ;
endLine = currentLine ;
do {
checkLine ( currentLine ) ; // benweet
currentLine ++ ;
} while ( self . lines [ currentLine ] ) ;
2013-09-09 00:08:55 +00:00
2013-09-09 23:32:24 +00:00
// only check every 5 lines
2013-09-15 01:35:58 +00:00
processedLines ++ ;
2013-09-30 00:16:01 +00:00
if ( ( processedLines % 5 === 0 ) && ( new Date ( ) - workerStart ) > 20 ) {
2013-09-15 01:35:58 +00:00
self . running = setTimeout ( customWorker , 20 ) ; // benweet
self . currentLine = currentLine ;
2013-09-09 23:32:24 +00:00
return ;
}
}
2013-09-15 01:35:58 +00:00
self . currentLine = currentLine ;
2013-09-09 23:32:24 +00:00
2013-11-07 23:10:38 +00:00
if ( startLine <= endLine ) {
2013-09-15 01:35:58 +00:00
self . fireUpdateEvent ( startLine , endLine ) ;
2013-11-07 23:10:38 +00:00
}
2013-09-09 23:32:24 +00:00
}
self . $worker = function ( ) {
2013-09-15 01:35:58 +00:00
self . lines . splice ( 0 , self . lines . length ) ;
self . states . splice ( 0 , self . states . length ) ;
self . currentLine = 0 ;
2013-09-09 23:32:24 +00:00
customWorker ( ) ;
} ;
2013-09-15 01:35:58 +00:00
2013-09-09 23:32:24 +00:00
} ) ( aceEditor . session . bgTokenizer ) ;
2013-09-15 01:35:58 +00:00
2013-09-30 00:16:01 +00:00
shortcutMgr . configureAce ( aceEditor ) ;
2013-09-09 23:32:24 +00:00
eventMgr . onAceCreated ( aceEditor ) ;
}
2013-09-15 01:35:58 +00:00
2013-09-09 23:32:24 +00:00
// Create the layout
2013-11-07 23:10:38 +00:00
var $editorButtonsElt ;
2013-09-09 23:32:24 +00:00
function createLayout ( ) {
2013-05-29 19:55:23 +00:00
var layoutGlobalConfig = {
2013-08-10 11:34:30 +00:00
closable : true ,
2013-05-29 19:55:23 +00:00
resizable : false ,
slidable : false ,
livePaneResizing : true ,
enableCursorHotkey : false ,
2013-08-18 00:02:23 +00:00
resizerDblClickToggle : false ,
2013-12-01 15:43:46 +00:00
resizeWithWindow : false ,
2013-11-30 01:40:26 +00:00
north _ _spacing _open : 1 ,
north _ _spacing _closed : 1 ,
2013-08-10 00:28:48 +00:00
spacing _open : 35 ,
spacing _closed : 35 ,
togglerLength _open : 60 ,
togglerLength _closed : 60 ,
2013-05-29 19:55:23 +00:00
stateManagement _ _enabled : false ,
2013-12-01 15:43:46 +00:00
north _ _minSize : 49 ,
2013-12-06 22:15:51 +00:00
center _ _minWidth : 250 ,
2013-12-14 18:15:35 +00:00
center _ _minHeight : 180 ,
2013-10-11 21:47:00 +00:00
fxSettings : {
easing : "easeInOutQuad" ,
duration : 350
} ,
2013-08-06 23:52:58 +00:00
onopen : function ( ) {
2013-08-10 11:34:30 +00:00
setPanelVisibility ( ) ;
2013-08-08 23:32:03 +00:00
setPreviewButtonsVisibility ( ) ;
2013-08-06 23:52:58 +00:00
} ,
onclose _start : function ( paneName ) {
2013-08-10 11:34:30 +00:00
if ( paneName == 'north' ) {
setPanelVisibility ( true ) ;
}
else if ( paneName == 'east' ) {
2013-08-08 23:32:03 +00:00
setPreviewButtonsVisibility ( true ) ;
}
2013-08-06 23:52:58 +00:00
} ,
2013-09-12 23:25:25 +00:00
onresize _end : function ( paneName ) {
if ( aceEditor !== undefined && paneName == 'center' ) {
aceEditor . resize ( ) ;
2013-09-15 01:35:58 +00:00
var bottomMargin = ( aceEditor . renderer . $size . scrollerHeight - aceEditor . renderer . lineHeight ) / 2 ;
bottomMargin < 0 && ( bottomMargin = 0 ) ;
aceEditor . renderer . setScrollMargin ( 0 , bottomMargin , 0 , 0 ) ;
2013-09-12 23:25:25 +00:00
setTimeout ( function ( ) {
2013-09-15 01:35:58 +00:00
var padding = ( aceEditor . renderer . $size . scrollerWidth - settings . maxWidth ) / 2 ;
2013-11-05 23:03:38 +00:00
if ( padding < constants . EDITOR _DEFAULT _PADDING ) {
padding = constants . EDITOR _DEFAULT _PADDING ;
2013-09-12 23:25:25 +00:00
}
if ( padding !== aceEditor . renderer . $padding ) {
aceEditor . renderer . setPadding ( padding ) ;
aceEditor . resize ( true ) ;
}
} , 5 ) ;
2013-09-15 01:35:58 +00:00
}
2013-09-12 23:25:25 +00:00
eventMgr . onLayoutResize ( paneName ) ;
2013-09-09 00:08:55 +00:00
} ,
2013-05-29 19:55:23 +00:00
} ;
2013-07-30 08:46:36 +00:00
eventMgr . onLayoutConfigure ( layoutGlobalConfig ) ;
2013-05-29 19:55:23 +00:00
if ( settings . layoutOrientation == "horizontal" ) {
$ ( ".ui-layout-south" ) . remove ( ) ;
2013-08-08 23:32:03 +00:00
$ ( ".preview-container" ) . html ( '<div id="preview-contents"><div id="wmd-preview" class="preview-content"></div></div>' ) ;
2013-05-29 19:55:23 +00:00
layout = $ ( 'body' ) . layout ( $ . extend ( layoutGlobalConfig , {
east _ _resizable : true ,
2013-09-30 00:16:01 +00:00
east _ _size : 0.5 ,
2013-12-01 15:43:46 +00:00
east _ _minSize : 300
2013-05-29 19:55:23 +00:00
} ) ) ;
}
else if ( settings . layoutOrientation == "vertical" ) {
$ ( ".ui-layout-east" ) . remove ( ) ;
2013-08-08 23:32:03 +00:00
$ ( ".preview-container" ) . html ( '<div id="preview-contents"><div id="wmd-preview" class="preview-content"></div></div>' ) ;
2013-05-29 19:55:23 +00:00
layout = $ ( 'body' ) . layout ( $ . extend ( layoutGlobalConfig , {
south _ _resizable : true ,
2013-09-30 00:16:01 +00:00
south _ _size : 0.5 ,
2013-05-29 19:55:23 +00:00
south _ _minSize : 200
} ) ) ;
}
2013-09-15 01:35:58 +00:00
settings . maxWidth && $ ( '#preview-contents' ) . css ( 'max-width' , ( settings . maxWidth + 30 ) + 'px' ) ;
2013-07-20 01:08:17 +00:00
$ ( ".navbar" ) . click ( function ( ) {
2013-05-29 19:55:23 +00:00
layout . allowOverflow ( 'north' ) ;
} ) ;
2013-08-10 00:28:48 +00:00
$ ( ".ui-layout-toggler-south" ) . addClass ( "btn btn-info" ) . html ( '<i class="icon-none"></i>' ) ;
$ ( ".ui-layout-toggler-east" ) . addClass ( "btn btn-info" ) . html ( '<i class="icon-none"></i>' ) ;
2013-12-02 01:20:38 +00:00
var $northTogglerElt = $ ( ".ui-layout-toggler-north" ) . addClass ( "btn btn-info" ) . html ( '<i class="icon-th"></i>' ) ;
2013-08-13 00:03:38 +00:00
// We attach the preview buttons to the UI layout resizer in order to
// have fixed position
// We also move the north toggler to the east or south resizer as the
// north resizer is very small
2013-09-15 01:35:58 +00:00
// var $previewButtonsContainerElt = $('<div
// class="preview-button-container">');
2013-09-30 00:16:01 +00:00
var $resizerDecorator = $ ( '<div class="resizer-decorator">' ) ;
2013-09-15 01:35:58 +00:00
$previewButtonsElt = $ ( '<div class="extension-preview-buttons">' ) ;
2013-09-11 23:26:47 +00:00
$editorButtonsElt = $ ( '<div class="extension-editor-buttons">' ) ;
2013-11-07 23:10:38 +00:00
if ( window . viewerMode || settings . layoutOrientation == "horizontal" ) {
2013-11-28 01:04:41 +00:00
$ ( '.ui-layout-resizer-north' ) . append ( $previewButtonsElt ) ;
$ ( '.ui-layout-resizer-east' ) . append ( $resizerDecorator ) . append ( $northTogglerElt ) . append ( $editorButtonsElt ) ;
2013-08-08 23:32:03 +00:00
}
else {
2013-11-28 01:04:41 +00:00
$ ( '.ui-layout-resizer-south' ) . append ( $resizerDecorator ) . append ( $previewButtonsElt ) . append ( $editorButtonsElt ) . append ( $northTogglerElt ) ;
2013-08-08 23:32:03 +00:00
}
2013-08-10 11:34:30 +00:00
setPanelVisibility ( ) ;
2013-08-08 23:32:03 +00:00
setPreviewButtonsVisibility ( ) ;
2013-05-29 19:55:23 +00:00
2013-07-30 08:46:36 +00:00
eventMgr . onLayoutCreated ( layout ) ;
2013-07-03 22:29:53 +00:00
}
2013-05-29 19:55:23 +00:00
2013-12-01 15:43:46 +00:00
var $navbarElt ;
var $leftBtnElts ;
var $rightBtnElts ;
var $leftBtnDropdown ;
var $rightBtnDropdown ;
2013-12-05 20:59:57 +00:00
var marginWidth = 36 + 25 + 25 ;
var titleWidth = 18 + 348 ;
var leftButtonsWidth = 72 + 83 + 166 + 167 + 83 ;
var rightButtonsWidth = 36 + 84 + 83 ;
var rightButtonsDropdown = 42 ;
2013-12-01 15:43:46 +00:00
function adjustWindow ( ) {
2013-12-02 00:09:39 +00:00
if ( ! window . viewerMode ) {
2013-12-05 20:59:57 +00:00
var maxWidth = $navbarElt . width ( ) - 5 ;
2013-12-02 00:09:39 +00:00
if ( marginWidth + titleWidth + leftButtonsWidth + rightButtonsWidth > maxWidth ) {
$rightBtnDropdown . show ( ) . find ( '.dropdown-menu' ) . append ( $rightBtnElts ) ;
if ( marginWidth + titleWidth + leftButtonsWidth + rightButtonsDropdown > maxWidth ) {
$leftBtnDropdown . show ( ) . find ( '.dropdown-menu' ) . append ( $leftBtnElts ) ;
}
else {
$leftBtnDropdown . hide ( ) . after ( $leftBtnElts ) ;
}
2013-12-01 15:43:46 +00:00
}
else {
$leftBtnDropdown . hide ( ) . after ( $leftBtnElts ) ;
2013-12-02 00:09:39 +00:00
$rightBtnDropdown . hide ( ) . after ( $rightBtnElts ) ;
}
2013-12-01 15:43:46 +00:00
}
layout . resizeAll ( ) ;
}
2014-04-21 17:21:03 +00:00
2013-05-29 19:55:23 +00:00
// Create the PageDown editor
2013-11-07 23:10:38 +00:00
var editor ;
var $editorElt ;
var fileDesc ;
var documentContent ;
2013-09-09 23:32:24 +00:00
var UndoManager = require ( "ace/undomanager" ) . UndoManager ;
2013-06-19 20:33:46 +00:00
core . initEditor = function ( fileDescParam ) {
2013-07-18 00:07:22 +00:00
if ( fileDesc !== undefined ) {
2013-07-30 08:46:36 +00:00
eventMgr . onFileClosed ( fileDesc ) ;
2013-07-18 00:07:22 +00:00
}
2013-06-03 22:19:52 +00:00
fileDesc = fileDescParam ;
2013-06-02 00:38:23 +00:00
documentContent = undefined ;
2013-06-03 22:19:52 +00:00
var initDocumentContent = fileDesc . content ;
2013-09-09 00:08:55 +00:00
2013-09-12 23:25:25 +00:00
if ( aceEditor !== undefined ) {
aceEditor . setValue ( initDocumentContent , - 1 ) ;
aceEditor . getSession ( ) . setUndoManager ( new UndoManager ( ) ) ;
}
else {
$editorElt . val ( initDocumentContent ) ;
}
2013-09-15 01:35:58 +00:00
2013-06-02 00:38:23 +00:00
if ( editor !== undefined ) {
2013-06-03 22:19:52 +00:00
// If the editor is already created
2013-09-14 16:59:40 +00:00
aceEditor && aceEditor . selection . setSelectionRange ( fileDesc . editorSelectRange ) ;
2013-12-05 20:59:57 +00:00
aceEditor ? aceEditor . focus ( ) : $editorElt . focus ( ) ;
2013-07-28 10:35:04 +00:00
editor . refreshPreview ( ) ;
2013-06-02 00:38:23 +00:00
return ;
}
2013-09-09 00:08:55 +00:00
2013-08-22 00:19:59 +00:00
var $previewContainerElt = $ ( ".preview-container" ) ;
2013-06-10 21:22:32 +00:00
2013-12-05 00:25:17 +00:00
if ( window . lightMode ) {
// Store editor scrollTop on scroll event
$editorElt . scroll ( function ( ) {
if ( documentContent !== undefined ) {
fileDesc . editorScrollTop = $ ( this ) . scrollTop ( ) ;
}
} ) ;
// Store editor selection on change
$editorElt . bind ( "keyup mouseup" , function ( ) {
if ( documentContent !== undefined ) {
fileDesc . editorStart = this . selectionStart ;
fileDesc . editorEnd = this . selectionEnd ;
}
} ) ;
}
else {
2013-09-12 23:25:25 +00:00
// Store editor scrollTop on scroll event
2013-09-16 00:03:17 +00:00
var saveScroll = _ . debounce ( function ( ) {
2013-09-12 23:25:25 +00:00
if ( documentContent !== undefined ) {
2013-09-16 00:03:17 +00:00
fileDesc . editorScrollTop = aceEditor . renderer . getScrollTop ( ) ;
2013-09-12 23:25:25 +00:00
}
2013-09-16 00:03:17 +00:00
} , 100 ) ;
aceEditor . session . on ( 'changeScrollTop' , saveScroll ) ;
2013-09-12 23:25:25 +00:00
// Store editor selection on change
2013-09-16 00:03:17 +00:00
var saveSelection = _ . debounce ( function ( ) {
2013-09-12 23:25:25 +00:00
if ( documentContent !== undefined ) {
fileDesc . editorSelectRange = aceEditor . getSelectionRange ( ) ;
}
2013-09-16 00:03:17 +00:00
} , 100 ) ;
aceEditor . session . selection . on ( 'changeSelection' , saveSelection ) ;
aceEditor . session . selection . on ( 'changeCursor' , saveSelection ) ;
2013-09-12 23:25:25 +00:00
}
2013-12-05 00:25:17 +00:00
// Store preview scrollTop on scroll event
$previewContainerElt . scroll ( function ( ) {
if ( documentContent !== undefined ) {
fileDesc . previewScrollTop = $previewContainerElt . scrollTop ( ) ;
}
} ) ;
2013-06-10 21:22:32 +00:00
// Create the converter and the editor
2013-05-29 19:55:23 +00:00
var converter = new Markdown . Converter ( ) ;
2013-12-27 20:07:49 +00:00
var options = {
_DoItalicsAndBold : function ( text ) {
// Restore original markdown implementation
text = text . replace ( /(\*\*|__)(?=\S)(.+?[*_]*)(?=\S)\1/g ,
"<strong>$2</strong>" ) ;
text = text . replace ( /(\*|_)(?=\S)(.+?)(?=\S)\1/g ,
"<em>$2</em>" ) ;
return text ;
}
} ;
converter . setOptions ( options ) ;
2013-09-15 01:35:58 +00:00
2013-09-14 16:59:40 +00:00
function checkDocumentChanges ( ) {
var newDocumentContent = $editorElt . val ( ) ;
if ( aceEditor !== undefined ) {
newDocumentContent = aceEditor . getValue ( ) ;
}
if ( documentContent !== undefined && documentContent != newDocumentContent ) {
fileDesc . content = newDocumentContent ;
eventMgr . onContentChanged ( fileDesc ) ;
}
documentContent = newDocumentContent ;
}
2014-04-21 17:21:03 +00:00
2013-11-07 23:10:38 +00:00
var previewWrapper ;
2013-12-05 00:25:17 +00:00
if ( window . lightMode ) {
editor = new Markdown . EditorLight ( converter ) ;
}
else {
2013-10-12 19:13:29 +00:00
editor = new Markdown . Editor ( converter , undefined , {
keyStrokes : shortcutMgr . getPagedownKeyStrokes ( )
} ) ;
2013-12-05 00:25:17 +00:00
}
// Custom insert link dialog
editor . hooks . set ( "insertLinkDialog" , function ( callback ) {
core . insertLinkCallback = callback ;
utils . resetModalInputs ( ) ;
$ ( ".modal-insert-link" ) . modal ( ) ;
return true ;
} ) ;
// Custom insert image dialog
editor . hooks . set ( "insertImageDialog" , function ( callback ) {
core . insertLinkCallback = callback ;
if ( core . catchModal ) {
2013-09-12 23:25:25 +00:00
return true ;
2013-12-05 00:25:17 +00:00
}
utils . resetModalInputs ( ) ;
$ ( ".modal-insert-image" ) . modal ( ) ;
return true ;
} ) ;
2014-04-21 17:21:03 +00:00
2013-12-05 00:25:17 +00:00
if ( settings . lazyRendering === true ) {
previewWrapper = function ( makePreview ) {
var debouncedMakePreview = _ . debounce ( makePreview , 500 ) ;
return function ( ) {
if ( documentContent === undefined ) {
makePreview ( ) ;
eventMgr . onFileOpen ( fileDesc ) ;
$previewContainerElt . scrollTop ( fileDesc . previewScrollTop ) ;
if ( window . lightMode ) {
$editorElt . scrollTop ( fileDesc . editorScrollTop ) ;
}
else {
2013-11-07 23:10:38 +00:00
_ . defer ( function ( ) {
aceEditor . renderer . scrollToY ( fileDesc . editorScrollTop ) ;
} ) ;
}
2013-12-05 00:25:17 +00:00
}
else {
debouncedMakePreview ( ) ;
}
checkDocumentChanges ( ) ;
2013-11-07 23:10:38 +00:00
} ;
2013-12-05 00:25:17 +00:00
} ;
}
else {
previewWrapper = function ( makePreview ) {
return function ( ) {
makePreview ( ) ;
if ( documentContent === undefined ) {
eventMgr . onFileOpen ( fileDesc ) ;
$previewContainerElt . scrollTop ( fileDesc . previewScrollTop ) ;
if ( window . lightMode ) {
$editorElt . scrollTop ( fileDesc . editorScrollTop ) ;
}
else {
2013-11-07 23:10:38 +00:00
_ . defer ( function ( ) {
aceEditor . renderer . scrollToY ( fileDesc . editorScrollTop ) ;
} ) ;
}
2013-12-05 00:25:17 +00:00
}
checkDocumentChanges ( ) ;
2013-11-07 23:10:38 +00:00
} ;
2013-09-12 23:25:25 +00:00
} ;
}
2013-05-29 19:55:23 +00:00
2013-09-09 23:32:24 +00:00
eventMgr . onPagedownConfigure ( editor ) ;
2013-07-30 08:46:36 +00:00
editor . hooks . chain ( "onPreviewRefresh" , eventMgr . onAsyncPreview ) ;
2013-12-05 00:25:17 +00:00
if ( window . lightMode ) {
editor . run ( previewWrapper ) ;
editor . undoManager . reinit ( initDocumentContent , fileDesc . editorStart , fileDesc . editorEnd , fileDesc . editorScrollTop ) ;
$editorElt . focus ( ) ;
}
else {
editor . run ( aceEditor , previewWrapper ) ;
aceEditor . selection . setSelectionRange ( fileDesc . editorSelectRange ) ;
aceEditor . focus ( ) ;
}
2013-05-29 19:55:23 +00:00
// Hide default buttons
2013-08-10 01:19:32 +00:00
$ ( ".wmd-button-row li" ) . addClass ( "btn btn-success" ) . css ( "left" , 0 ) . find ( "span" ) . hide ( ) ;
2013-05-29 19:55:23 +00:00
// Add customized buttons
2013-08-22 00:19:59 +00:00
var $btnGroupElt = $ ( '.wmd-button-group1' ) ;
$ ( "#wmd-bold-button" ) . append ( $ ( '<i class="icon-bold">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-italic-button" ) . append ( $ ( '<i class="icon-italic">' ) ) . appendTo ( $btnGroupElt ) ;
2013-11-07 23:10:38 +00:00
$btnGroupElt = $ ( '.wmd-button-group2' ) ;
2013-08-22 00:19:59 +00:00
$ ( "#wmd-link-button" ) . append ( $ ( '<i class="icon-globe">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-quote-button" ) . append ( $ ( '<i class="icon-indent-right">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-code-button" ) . append ( $ ( '<i class="icon-code">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-image-button" ) . append ( $ ( '<i class="icon-picture">' ) ) . appendTo ( $btnGroupElt ) ;
2013-11-07 23:10:38 +00:00
$btnGroupElt = $ ( '.wmd-button-group3' ) ;
2013-08-22 00:19:59 +00:00
$ ( "#wmd-olist-button" ) . append ( $ ( '<i class="icon-list-numbered">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-ulist-button" ) . append ( $ ( '<i class="icon-list-bullet">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-heading-button" ) . append ( $ ( '<i class="icon-text-height">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-hr-button" ) . append ( $ ( '<i class="icon-ellipsis">' ) ) . appendTo ( $btnGroupElt ) ;
2013-11-07 23:10:38 +00:00
$btnGroupElt = $ ( '.wmd-button-group4' ) ;
2013-08-22 00:19:59 +00:00
$ ( "#wmd-undo-button" ) . append ( $ ( '<i class="icon-reply">' ) ) . appendTo ( $btnGroupElt ) ;
$ ( "#wmd-redo-button" ) . append ( $ ( '<i class="icon-forward">' ) ) . appendTo ( $btnGroupElt ) ;
2013-07-18 23:30:28 +00:00
} ;
2014-04-21 17:21:03 +00:00
2013-08-04 15:49:14 +00:00
// Initialize multiple things and then fire eventMgr.onReady
2013-08-14 23:44:51 +00:00
var isDocumentPanelShown = false ;
var isMenuPanelShown = false ;
2013-08-04 15:49:14 +00:00
core . onReady = function ( ) {
2013-11-07 23:10:38 +00:00
if ( window . viewerMode === true ) {
2013-08-22 00:19:59 +00:00
document . body . innerHTML = bodyViewerHTML ;
2013-08-04 15:49:14 +00:00
}
else {
2013-08-22 00:19:59 +00:00
document . body . innerHTML = bodyIndexHTML ;
2013-08-04 15:49:14 +00:00
}
2013-12-01 15:43:46 +00:00
$navbarElt = $ ( '.navbar' ) ;
$leftBtnElts = $navbarElt . find ( '.left-buttons' ) ;
$rightBtnElts = $navbarElt . find ( '.right-buttons' ) ;
$leftBtnDropdown = $navbarElt . find ( '.left-buttons-dropdown' ) ;
$rightBtnDropdown = $navbarElt . find ( '.right-buttons-dropdown' ) ;
$ ( window ) . bind ( "resize" , adjustWindow ) ;
2014-04-21 17:21:03 +00:00
2014-01-13 18:57:59 +00:00
// Initialize utils library
utils . init ( ) ;
2014-04-21 17:21:03 +00:00
2013-09-30 22:37:58 +00:00
// Populate shortcuts in settings
shortcutMgr . addSettingEntries ( ) ;
2014-04-21 17:21:03 +00:00
2014-01-21 23:48:42 +00:00
// Hide shortcuts settings if light mode
if ( window . lightMode ) {
$ ( '.tab-settings-shortcuts' ) . hide ( ) ;
}
2013-05-29 19:55:23 +00:00
// listen to online/offline events
$ ( window ) . on ( 'offline' , core . setOffline ) ;
$ ( window ) . on ( 'online' , setOnline ) ;
if ( navigator . onLine === false ) {
core . setOffline ( ) ;
}
// Detect user activity
$ ( document ) . mousemove ( setUserActive ) . keypress ( setUserActive ) ;
// Avoid dropdown to close when clicking on submenu
$ ( ".dropdown-submenu > a" ) . click ( function ( e ) {
e . stopPropagation ( ) ;
} ) ;
2013-08-08 21:53:15 +00:00
2013-08-22 00:19:59 +00:00
$menuPanelElt = $ ( '.menu-panel' ) . collapse ( {
2013-08-13 00:03:38 +00:00
toggle : false
} ) ;
2013-11-07 23:10:38 +00:00
var menuPanelBackdropElt ;
2013-08-22 00:19:59 +00:00
$menuPanelElt . on ( 'show.bs.collapse' , function ( e ) {
if ( e . target === $menuPanelElt [ 0 ] ) {
2013-08-12 22:08:22 +00:00
isMenuPanelShown = true ;
2013-08-25 20:38:44 +00:00
menuPanelBackdropElt = utils . createBackdrop ( 'collapse' , '.menu-panel' ) ;
2013-08-25 00:45:14 +00:00
$menuPanelElt . addClass ( 'move-to-front' ) ;
2013-12-02 22:11:17 +00:00
// To avoid opening delay
setTimeout ( function ( ) {
$menuPanelElt . trigger ( $ . support . transition . end ) ;
} , 50 ) ;
2013-08-12 22:08:22 +00:00
}
2013-08-13 00:03:38 +00:00
else {
// Close all open sub-menus when one submenu opens
2013-08-22 00:19:59 +00:00
$menuPanelElt . find ( '.in' ) . collapse ( 'hide' ) ;
2013-08-13 00:03:38 +00:00
}
} ) . on ( 'hide.bs.collapse' , function ( e ) {
2013-08-22 00:19:59 +00:00
if ( e . target === $menuPanelElt [ 0 ] ) {
2013-08-13 00:03:38 +00:00
isMenuPanelShown = false ;
2013-08-25 21:11:07 +00:00
menuPanelBackdropElt . parentNode . removeChild ( menuPanelBackdropElt ) ;
2013-08-25 00:45:14 +00:00
$menuPanelElt . removeClass ( 'move-to-front' ) ;
2013-12-05 20:59:57 +00:00
aceEditor ? aceEditor . focus ( ) : $editorElt . focus ( ) ;
2013-08-13 00:03:38 +00:00
}
2013-08-12 22:08:22 +00:00
} ) . on ( 'hidden.bs.collapse' , function ( e ) {
2013-08-22 00:19:59 +00:00
if ( e . target === $menuPanelElt [ 0 ] ) {
2013-08-13 00:03:38 +00:00
// Close all open sub-menus when menu panel is closed
2013-08-22 00:19:59 +00:00
$menuPanelElt . find ( '.in' ) . collapse ( 'hide' ) ;
2013-08-12 22:08:22 +00:00
}
2013-08-06 00:28:21 +00:00
} ) ;
2013-08-08 21:53:15 +00:00
2013-08-22 00:19:59 +00:00
$documentPanelElt = $ ( '.document-panel' ) . collapse ( {
2013-08-13 00:03:38 +00:00
toggle : false
} ) ;
2013-11-07 23:10:38 +00:00
var documentPanelBackdropElt ;
2013-08-22 00:19:59 +00:00
$documentPanelElt . on ( 'show.bs.collapse' , function ( e ) {
if ( e . target === $documentPanelElt [ 0 ] ) {
2013-08-12 22:08:22 +00:00
isDocumentPanelShown = true ;
2013-08-13 00:03:38 +00:00
documentPanelBackdropElt = utils . createBackdrop ( 'collapse' , '.document-panel' ) ;
2013-08-25 00:45:14 +00:00
$documentPanelElt . addClass ( 'move-to-front' ) ;
2013-12-02 22:11:17 +00:00
// To avoid opening delay
setTimeout ( function ( ) {
$documentPanelElt . trigger ( $ . support . transition . end ) ;
} , 50 ) ;
2013-08-13 00:03:38 +00:00
}
else {
// Close all open sub-menus when one submenu opens
2013-08-22 00:19:59 +00:00
$documentPanelElt . find ( '.in' ) . collapse ( 'hide' ) ;
2013-08-13 00:03:38 +00:00
}
} ) . on ( 'hide.bs.collapse' , function ( e ) {
2013-08-22 00:19:59 +00:00
if ( e . target === $documentPanelElt [ 0 ] ) {
2013-08-13 00:03:38 +00:00
isDocumentPanelShown = false ;
2013-08-25 21:11:07 +00:00
documentPanelBackdropElt . parentNode . removeChild ( documentPanelBackdropElt ) ;
2013-08-25 00:45:14 +00:00
$documentPanelElt . removeClass ( 'move-to-front' ) ;
2013-12-05 20:59:57 +00:00
aceEditor ? aceEditor . focus ( ) : $editorElt . focus ( ) ;
2013-08-12 22:08:22 +00:00
}
} ) . on ( 'hidden.bs.collapse' , function ( e ) {
2013-08-22 00:19:59 +00:00
if ( e . target === $documentPanelElt [ 0 ] ) {
2013-08-12 22:08:22 +00:00
// Close all open sub-menus when menu panel is closed
2013-08-22 00:19:59 +00:00
$documentPanelElt . find ( '.in' ) . collapse ( 'hide' ) ;
2013-08-12 22:08:22 +00:00
}
2013-08-06 00:28:21 +00:00
} ) ;
2013-08-08 21:53:15 +00:00
2013-10-22 22:12:38 +00:00
// Editor
2013-11-07 23:10:38 +00:00
if ( window . lightMode ) {
2013-10-22 22:12:38 +00:00
// In light mode, we replace ACE with a textarea
$ ( '#wmd-input' ) . replaceWith ( function ( ) {
return $ ( '<textarea id="wmd-input">' ) . addClass ( this . className ) . addClass ( 'form-control' ) ;
} ) ;
}
2014-04-21 17:21:03 +00:00
2013-12-05 00:25:17 +00:00
$editorElt = $ ( "#wmd-input, .textarea-helper" ) . css ( {
2013-08-04 00:53:46 +00:00
// Apply editor font
"font-family" : settings . editorFontFamily ,
"font-size" : settings . editorFontSize + "px" ,
2013-09-09 23:32:24 +00:00
"line-height" : Math . round ( settings . editorFontSize * ( 20 / 12 ) ) + "px"
2013-08-04 00:53:46 +00:00
} ) ;
2014-04-21 17:21:03 +00:00
2013-11-07 23:10:38 +00:00
if ( ! window . lightMode ) {
2013-10-22 22:12:38 +00:00
// ACE editor
createAceEditor ( ) ;
// Editor's element
$editorElt . find ( '.ace_content' ) . css ( {
"background-size" : "64px " + Math . round ( settings . editorFontSize * ( 20 / 12 ) ) + "px" ,
} ) ;
}
2013-08-04 00:53:46 +00:00
2013-09-09 23:32:24 +00:00
// UI layout
createLayout ( ) ;
2013-08-04 00:53:46 +00:00
// Do periodic tasks
intervalId = window . setInterval ( function ( ) {
utils . updateCurrentTime ( ) ;
checkWindowUnique ( ) ;
2013-11-07 23:10:38 +00:00
if ( isUserActive ( ) === true || window . viewerMode === true ) {
2013-08-04 00:53:46 +00:00
eventMgr . onPeriodicRun ( ) ;
checkOnline ( ) ;
}
} , 1000 ) ;
eventMgr . onReady ( ) ;
2013-12-01 15:43:46 +00:00
// Adjust the layout after the dom has changed
adjustWindow ( ) ;
2013-08-04 00:53:46 +00:00
} ;
// Other initialization that are not prioritary
eventMgr . addListener ( "onReady" , function ( ) {
2014-04-21 17:21:03 +00:00
2013-09-15 01:35:58 +00:00
// In vertical mode, we have to offset the editor buttons otherwise they hide the editor buttons
2013-11-07 23:10:38 +00:00
if ( ! window . viewerMode && settings . layoutOrientation == "vertical" ) {
2013-09-15 01:35:58 +00:00
$previewButtonsElt . css ( 'right' , parseInt ( $previewButtonsElt . css ( 'right' ) ) + $editorButtonsElt . width ( ) ) ;
}
2013-08-04 00:53:46 +00:00
2013-08-14 23:44:51 +00:00
var isModalShown = false ;
$ ( '.modal' ) . on ( 'show.bs.modal' , function ( ) {
// Close panel if open
2013-08-22 00:19:59 +00:00
$menuPanelElt . collapse ( 'hide' ) ;
$documentPanelElt . collapse ( 'hide' ) ;
2013-08-15 00:01:40 +00:00
isModalShown = true ;
2013-08-14 23:44:51 +00:00
} ) . on ( 'shown.bs.modal' , function ( ) {
2013-12-01 15:43:46 +00:00
var $elt = $ ( this ) ;
2013-09-09 23:32:24 +00:00
setTimeout ( function ( ) {
2013-12-01 15:43:46 +00:00
// When modal opens focus on the first button
$elt . find ( '.btn:first' ) . focus ( ) ;
// Or on the first link if any
$elt . find ( 'button:first' ) . focus ( ) ;
// Or on the first input if any
$elt . find ( "input:enabled:visible:first" ) . focus ( ) ;
2013-09-09 23:32:24 +00:00
} , 50 ) ;
2013-08-14 23:44:51 +00:00
} ) . on ( 'hidden.bs.modal' , function ( ) {
// Focus on the editor when modal is gone
isModalShown = false ;
2013-12-05 20:59:57 +00:00
aceEditor ? aceEditor . focus ( ) : $editorElt . focus ( ) ;
2013-09-03 12:01:26 +00:00
// Revert to current theme when settings modal is closed
2013-12-02 23:29:48 +00:00
applyTheme ( window . theme ) ;
2013-08-14 23:44:51 +00:00
} ) . keyup ( function ( e ) {
// Handle enter key in modals
if ( e . which == 13 && ! $ ( e . target ) . is ( "textarea" ) ) {
$ ( this ) . find ( ".modal-footer a:last" ) . click ( ) ;
}
} ) ;
2014-04-21 17:21:03 +00:00
2013-09-22 22:16:59 +00:00
// Hide menu panel when clicking 'Save as' button
$ ( '.collapse-save-as a' ) . click ( function ( ) {
$menuPanelElt . collapse ( 'hide' ) ;
} ) ;
2013-08-20 22:40:19 +00:00
2013-08-14 23:44:51 +00:00
// Configure Mousetrap
2013-11-07 23:10:38 +00:00
mousetrap . stopCallback = function ( e , element ) {
2013-09-14 16:59:40 +00:00
return isMenuPanelShown || isDocumentPanelShown || isModalShown || $ ( element ) . is ( "input, select, textarea:not(.ace_text-input)" ) ;
2013-08-14 23:44:51 +00:00
} ;
2013-05-29 19:55:23 +00:00
// Click events on "insert link" and "insert image" dialog buttons
$ ( ".action-insert-link" ) . click ( function ( e ) {
var value = utils . getInputTextValue ( $ ( "#input-insert-link" ) , e ) ;
if ( value !== undefined ) {
2013-06-02 00:38:23 +00:00
core . insertLinkCallback ( value ) ;
2013-06-02 19:35:44 +00:00
core . insertLinkCallback = undefined ;
2013-05-29 19:55:23 +00:00
}
} ) ;
$ ( ".action-insert-image" ) . click ( function ( e ) {
var value = utils . getInputTextValue ( $ ( "#input-insert-image" ) , e ) ;
if ( value !== undefined ) {
2013-06-02 00:38:23 +00:00
core . insertLinkCallback ( value ) ;
2013-06-02 19:35:44 +00:00
core . insertLinkCallback = undefined ;
2013-05-29 19:55:23 +00:00
}
} ) ;
2013-06-10 21:22:32 +00:00
2013-06-02 00:38:23 +00:00
// Hide events on "insert link" and "insert image" dialogs
2013-08-11 00:52:05 +00:00
$ ( ".modal-insert-link, .modal-insert-image" ) . on ( 'hidden.bs.modal' , function ( ) {
2013-06-02 00:38:23 +00:00
if ( core . insertLinkCallback !== undefined ) {
core . insertLinkCallback ( null ) ;
2013-06-02 19:35:44 +00:00
core . insertLinkCallback = undefined ;
2013-06-02 00:38:23 +00:00
}
2013-05-29 19:55:23 +00:00
} ) ;
// Settings loading/saving
$ ( ".action-load-settings" ) . click ( function ( ) {
loadSettings ( ) ;
} ) ;
$ ( ".action-apply-settings" ) . click ( function ( e ) {
saveSettings ( e ) ;
if ( ! e . isPropagationStopped ( ) ) {
window . location . reload ( ) ;
}
} ) ;
2013-08-20 22:40:19 +00:00
// Hot theme switcher in the settings
2013-11-07 23:10:38 +00:00
var currentTheme = window . theme ;
2013-08-20 22:40:19 +00:00
function applyTheme ( theme ) {
theme = theme || 'default' ;
if ( currentTheme != theme ) {
2013-08-23 23:50:14 +00:00
var themeModule = "less!themes/" + theme ;
2013-11-07 23:10:38 +00:00
if ( window . baseDir . indexOf ( '-min' ) !== - 1 ) {
2013-08-23 23:50:14 +00:00
themeModule = "css!themes/" + theme ;
}
2013-08-20 22:40:19 +00:00
// Undefine the module in RequireJS
requirejs . undef ( themeModule ) ;
// Then reload the style
require ( [
2013-08-23 23:50:14 +00:00
themeModule
2013-08-20 22:40:19 +00:00
] ) ;
currentTheme = theme ;
}
}
$themeInputElt = $ ( "#input-settings-theme" ) ;
$themeInputElt . on ( "change" , function ( ) {
applyTheme ( this . value ) ;
} ) ;
2013-10-12 23:10:14 +00:00
// Import docs and settings
2013-11-07 23:10:38 +00:00
$ ( ".action-import-docs-settings" ) . click ( function ( ) {
2013-10-12 23:10:14 +00:00
$ ( "#input-file-import-docs-settings" ) . click ( ) ;
2013-07-03 22:29:53 +00:00
} ) ;
2013-11-07 23:10:38 +00:00
var newstorage ;
2013-10-12 23:10:14 +00:00
$ ( "#input-file-import-docs-settings" ) . change ( function ( evt ) {
2013-07-03 22:29:53 +00:00
var files = ( evt . dataTransfer || evt . target ) . files ;
2013-08-11 00:52:05 +00:00
$ ( ".modal-settings" ) . modal ( "hide" ) ;
2013-07-03 22:29:53 +00:00
_ . each ( files , function ( file ) {
var reader = new FileReader ( ) ;
reader . onload = ( function ( importedFile ) {
return function ( e ) {
try {
2013-11-05 23:03:38 +00:00
newstorage = JSON . parse ( e . target . result ) ;
// Compare storage version
var newVersion = parseInt ( newstorage . version . match ( /^v(\d+)$/ ) [ 1 ] , 10 ) ;
var currentVersion = parseInt ( storage . version . match ( /^v(\d+)$/ ) [ 1 ] , 10 ) ;
2013-10-19 22:59:17 +00:00
if ( newVersion > currentVersion ) {
2013-11-05 23:03:38 +00:00
// We manage storage upgrade, not downgrade
2013-10-19 22:59:17 +00:00
eventMgr . onError ( "Incompatible version. Please upgrade StackEdit." ) ;
} else {
$ ( '.modal-import-docs-settings' ) . modal ( 'show' ) ;
2013-10-12 23:10:14 +00:00
}
2013-07-03 22:29:53 +00:00
}
2013-11-07 23:10:38 +00:00
catch ( exc ) {
2013-10-12 23:10:14 +00:00
eventMgr . onError ( "Wrong format: " + importedFile . name ) ;
2013-07-03 22:29:53 +00:00
}
2013-10-12 23:36:45 +00:00
$ ( "#input-file-import-docs-settings" ) . val ( '' ) ;
2013-07-03 22:29:53 +00:00
} ;
} ) ( file ) ;
2013-10-12 23:10:14 +00:00
reader . readAsText ( file ) ;
2013-07-03 22:29:53 +00:00
} ) ;
} ) ;
2013-11-07 23:10:38 +00:00
$ ( ".action-import-docs-settings-confirm" ) . click ( function ( ) {
2013-11-05 23:03:38 +00:00
storage . clear ( ) ;
2013-12-23 22:41:33 +00:00
var allowedKeys = /^file\.|^focusMode$|^folder\.|^publish\.|^settings$|^sync\.|^google\.|^themeV3$|^mode$|^version$|^welcomeTour$/ ;
2013-11-05 23:03:38 +00:00
_ . each ( newstorage , function ( value , key ) {
2013-10-12 23:10:14 +00:00
if ( allowedKeys . test ( key ) ) {
2013-11-05 23:03:38 +00:00
storage [ key ] = value ;
2013-10-12 23:10:14 +00:00
}
} ) ;
window . location . reload ( ) ;
} ) ;
2013-07-03 22:29:53 +00:00
// Export settings
2013-11-07 23:10:38 +00:00
$ ( ".action-export-docs-settings" ) . click ( function ( ) {
2013-11-05 23:03:38 +00:00
utils . saveAs ( JSON . stringify ( storage ) , "StackEdit local storage.json" ) ;
2013-07-03 22:29:53 +00:00
} ) ;
2013-05-29 19:55:23 +00:00
$ ( ".action-default-settings" ) . click ( function ( ) {
2013-11-05 23:03:38 +00:00
storage . removeItem ( "settings" ) ;
storage . removeItem ( "theme" ) ;
2014-01-13 01:39:28 +00:00
if ( ! settings . dropboxFullAccess ) {
storage . removeItem ( 'dropbox.lastChangeId' ) ;
}
2013-05-29 19:55:23 +00:00
window . location . reload ( ) ;
} ) ;
$ ( ".action-app-reset" ) . click ( function ( ) {
2013-11-05 23:03:38 +00:00
storage . clear ( ) ;
2013-05-29 19:55:23 +00:00
window . location . reload ( ) ;
} ) ;
2013-06-22 23:48:57 +00:00
// Reset inputs
$ ( ".action-reset-input" ) . click ( function ( ) {
utils . resetModalInputs ( ) ;
} ) ;
2013-05-29 19:55:23 +00:00
// Tooltips
2013-12-01 15:43:46 +00:00
var openedTooltip ;
2013-12-02 00:09:39 +00:00
function createTooltip ( selector , content ) {
_ . each ( document . querySelectorAll ( selector ) , function ( tooltipElt ) {
var $tooltipElt = $ ( tooltipElt ) ;
$tooltipElt . tooltip ( {
html : true ,
container : $tooltipElt . parents ( '.modal-content' ) ,
placement : 'right' ,
trigger : 'manual' ,
title : content
} ) . click ( function ( ) {
var elt = this ;
if ( openedTooltip && openedTooltip [ 0 ] === elt ) {
return ;
}
_ . defer ( function ( ) {
$ ( document ) . on ( "click.close-tooltip" , function ( ) {
openedTooltip && openedTooltip . tooltip ( 'hide' ) ;
openedTooltip = undefined ;
$ ( document ) . off ( "click.close-tooltip" ) ;
} ) ;
openedTooltip = $ ( elt ) . tooltip ( 'show' ) ;
} ) ;
2013-12-01 15:43:46 +00:00
} ) ;
} ) ;
}
2014-04-21 17:21:03 +00:00
2013-12-02 00:09:39 +00:00
createTooltip ( ".tooltip-lazy-rendering" , 'Disable preview rendering while typing in order to offload CPU. Refresh preview after 500 ms of inactivity.' ) ;
createTooltip ( ".tooltip-default-content" , [
'Thanks for supporting StackEdit by adding a backlink in your documents!<br/><br/>' ,
'<b class="text-danger">NOTE: Backlinks in Stack Exchange Q/A are not welcome.</b>'
] . join ( '' ) ) ;
createTooltip ( ".tooltip-usercustom-extension" , settingsUserCustomExtensionTooltipHTML ) ;
createTooltip ( ".tooltip-template" , settingsTemplateTooltipHTML ) ;
2013-08-04 00:53:46 +00:00
2013-07-07 17:12:25 +00:00
// Avoid dropdown panels to close on click
$ ( "div.dropdown-menu" ) . click ( function ( e ) {
e . stopPropagation ( ) ;
} ) ;
2013-09-09 00:08:55 +00:00
2013-09-19 21:54:50 +00:00
// Non unique window dialog
$ ( '.modal-non-unique' ) . modal ( {
backdrop : "static" ,
keyboard : false ,
show : false
} ) ;
2014-04-21 17:21:03 +00:00
2013-08-23 23:50:14 +00:00
// Load images
_ . each ( document . querySelectorAll ( 'img' ) , function ( imgElt ) {
var $imgElt = $ ( imgElt ) ;
var src = $imgElt . data ( 'stackeditSrc' ) ;
if ( src ) {
2013-11-07 23:10:38 +00:00
$imgElt . attr ( 'src' , window . baseDir + '/img/' + src ) ;
2013-08-23 23:50:14 +00:00
}
} ) ;
2013-05-29 19:55:23 +00:00
2013-11-07 23:10:38 +00:00
if ( window . viewerMode === false ) {
2013-08-21 00:16:10 +00:00
// Load theme list
2013-11-05 23:03:38 +00:00
var themeOptions = _ . reduce ( constants . THEME _LIST , function ( themeOptions , name , value ) {
2013-08-21 00:16:10 +00:00
return themeOptions + '<option value="' + value + '">' + name + '</option>' ;
} , '' ) ;
document . getElementById ( 'input-settings-theme' ) . innerHTML = themeOptions ;
}
2014-04-21 17:21:03 +00:00
$ ( '.modal-header' ) . append ( '<a class="dialog-header-message" href="https://stackedit-beta.herokuapp.com/" target="_blank">Try StackEdit 4 beta!</a>' ) ;
2013-05-29 19:55:23 +00:00
} ) ;
return core ;
} ) ;