2014-05-07 13:06:24 +08:00
new function ( $ ) {
$ . fn . setCursorPosition = function ( pos ) {
if ( $ ( this ) . get ( 0 ) . setSelectionRange ) {
$ ( this ) . get ( 0 ) . setSelectionRange ( pos , pos ) ;
} else if ( $ ( this ) . get ( 0 ) . createTextRange ) {
var range = $ ( this ) . get ( 0 ) . createTextRange ( ) ;
range . collapse ( true ) ;
range . moveEnd ( 'character' , pos ) ;
range . moveStart ( 'character' , pos ) ;
range . select ( ) ;
}
$ ( this ) . focus ( ) ;
}
$ . fn . tabHandler = function ( ) {
$ ( this ) . keydown ( function ( e ) {
if ( e . keyCode === 9 ) { // tab was pressed
// get caret position/selection
var start = this . selectionStart ;
var end = this . selectionEnd ;
var $this = $ ( this ) ;
var value = $this . val ( ) ;
// set textarea value to: text before caret + four spaces + text after caret
$this . val ( value . substring ( 0 , start )
+ " "
+ value . substring ( end ) ) ;
// put caret at right position again (add four for the spaces)
this . selectionStart = this . selectionEnd = start + 4 ;
// prevent the focus lose
e . preventDefault ( ) ;
}
} ) ;
}
} ( jQuery ) ;
// full screen api
/ *
( function ( ) {
var
fullScreenApi = {
supportsFullScreen : false ,
isFullScreen : function ( ) { return false ; } ,
requestFullScreen : function ( ) { } ,
cancelFullScreen : function ( ) { } ,
fullScreenEventName : '' ,
prefix : ''
} ,
browserPrefixes = 'webkit moz o ms khtml' . split ( ' ' ) ;
// check for native support
if ( typeof document . cancelFullScreen != 'undefined' ) {
fullScreenApi . supportsFullScreen = true ;
} else {
// check for fullscreen support by vendor prefix
for ( var i = 0 , il = browserPrefixes . length ; i < il ; i ++ ) {
fullScreenApi . prefix = browserPrefixes [ i ] ;
if ( typeof document [ fullScreenApi . prefix + 'CancelFullScreen' ] != 'undefined' ) {
fullScreenApi . supportsFullScreen = true ;
break ;
}
}
}
// update methods to do something useful
if ( fullScreenApi . supportsFullScreen ) {
fullScreenApi . fullScreenEventName = fullScreenApi . prefix + 'fullscreenchange' ;
fullScreenApi . isFullScreen = function ( ) {
switch ( this . prefix ) {
case '' :
return document . fullScreen ;
case 'webkit' :
return document . webkitIsFullScreen ;
default :
return document [ this . prefix + 'FullScreen' ] ;
}
}
fullScreenApi . requestFullScreen = function ( el ) {
return ( this . prefix === '' ) ? el . requestFullScreen ( ) : el [ this . prefix + 'RequestFullScreen' ] ( ) ;
}
fullScreenApi . cancelFullScreen = function ( el ) {
return ( this . prefix === '' ) ? document . cancelFullScreen ( ) : document [ this . prefix + 'CancelFullScreen' ] ( ) ;
}
}
// jQuery plugin
if ( typeof jQuery != 'undefined' ) {
jQuery . fn . requestFullScreen = function ( ) {
return this . each ( function ( ) {
if ( fullScreenApi . supportsFullScreen ) {
fullScreenApi . requestFullScreen ( this ) ;
}
} ) ;
} ;
}
// export api
window . fullScreenApi = fullScreenApi ;
} ) ( ) ;
* /
( function ( ) {
// handle Tab keystroke
$ ( '#wmd-input' ) . tabHandler ( ) ;
var converter1 = Markdown . getSanitizingConverter ( ) ;
Converter = converter1 ;
// tell the converter to use Markdown Extra for tables, fenced_code_gfm, def_list
Markdown . Extra . init ( converter1 , { extensions : [ "tables" , "fenced_code_gfm" , "def_list" ] , highlighter : "prettify" } ) ;
// To handle LaTeX expressions, to avoid the expression fail to work because of markdown syntax. inspired by stackeditor
// This will handle $$LaTeX expression$$ only, so that $LaTeX expression$ could fail to handle either.
bindMathJaxHooks ( converter1 ) ;
// 弹框显示markdown语法
var markdownHelp = function ( ) {
window . open ( "http://www.leanote.com/blog/view/531b263bdfeb2c0ea9000002" ) ;
return ;
}
var options = {
helpButton : { handler : markdownHelp } ,
strings : Markdown . local . zh
} ;
var editor1 = new Markdown . Editor ( converter1 , null , options ) ;
MarkdownEditor = editor1 ;
var scrollLink = getScrollLink ( ) ;
ScrollLink = scrollLink ;
scrollLink . onLayoutCreated ( ) ;
editor1 . hooks . chain ( "onPreviewRefresh" , function ( ) {
2015-01-08 00:36:28 +08:00
$ ( "#left-column pre" ) . addClass ( "prettyprint linenums" ) ;
2014-05-07 13:06:24 +08:00
prettyPrint ( ) ;
// Call onPreviewFinished callbacks when all async preview are finished, make sure sync actions have been ABOVE the line below.
var counter = 0 ;
var nbAsyncPreviewCallback = 2 ; // 1 for waitForImages below and 1 for MathJax below, they are both time consuming task, if only they are both done, begin to caculate md section and scroll bar.
function tryFinished ( ) {
if ( ++ counter === nbAsyncPreviewCallback ) {
scrollLink . onPreviewFinished ( ) ;
}
}
// We assume images are loading in the preview
$ ( "#wmd-preview" ) . waitForImages ( tryFinished ) ;
// TODO: could we cache the result to speed up ? This action is slow, especially, when there are multiple LaTeX expression on the page, google solution.
if ( typeof MathJax != "undefined" ) {
MathJax . Hub . Queue ( [ "Typeset" , MathJax . Hub , "wmd-preview" ] ) ;
MathJax . Hub . Queue ( tryFinished ) ;
} else {
scrollLink . onPreviewFinished ( ) ;
}
} ) ;
scrollLink . onEditorConfigure ( editor1 ) ;
function popupEditorDialog ( title , body , imageClass , placeholder ) {
$ ( '#editorDialog' ) . find ( '.modal-body input' ) . val ( "" ) ;
$ ( '#editorDialog' ) . find ( '.modal-body input' ) . attr ( "placeholder" , placeholder ) ;
$ ( '#editorDialog' ) . find ( '#editorDialog-title' ) . text ( title ) ;
$ ( '#editorDialog' ) . find ( '.modal-body p' ) . text ( body ) ;
$ ( '#editorDialog' ) . find ( '.modal-body i' ) . removeClass ( ) . addClass ( imageClass ) ;
$ ( '#editorDialog' ) . modal ( { keyboard : true } ) ;
}
// Custom insert link dialog
editor1 . hooks . set ( "insertLinkDialog" , function ( callback ) {
popupEditorDialog ( '链接' , '请输入链接地址' , 'fa fa-link' , 'http://example.com/ "可选标题"' ) ;
editorDialogCallback = callback ;
return true ; // tell the editor that we'll take care of getting the link url
} ) ;
// Custom insert image dialog
var editorDialogCallback = null ;
editor1 . hooks . set ( "insertImageDialog" , function ( callback ) {
popupEditorDialog ( '图片' , '请输入图片地址' , 'fa fa-picture-o' , 'http://example.com/images/diagram.jpg "可选标题"' ) ;
editorDialogCallback = callback ;
return true ; // tell the editor that we'll take care of getting the image url
} ) ;
$ ( '#editorDialog' ) . on ( 'hidden.bs.modal' , function ( ) {
if ( editorDialogCallback ) {
var url = $ ( '#editorDialog-confirm' ) . data ( 'url' ) ;
if ( url ) {
$ ( '#editorDialog-confirm' ) . removeData ( 'url' ) ;
editorDialogCallback ( url ) ;
} else {
editorDialogCallback ( null ) ;
}
}
} ) ;
$ ( '#editorDialog-confirm' ) . click ( function ( event ) {
var url = $ ( '#editorDialog' ) . find ( '.modal-body input' ) . val ( ) ;
if ( url ) {
$ ( this ) . data ( 'url' , url ) ;
}
$ ( '#editorDialog' ) . modal ( 'hide' ) ;
} ) ;
$ ( '#editorDialog' ) . on ( 'shown.bs.modal' , function ( ) {
$ ( '#editorDialog' ) . find ( '.modal-body input' ) . focus ( ) ;
} ) ;
// Make preview if it's inactive in 500ms to reduce the calls in onPreviewRefresh chains above and cpu cost.
documentContent = undefined ;
var previewWrapper ;
previewWrapper = function ( makePreview ) {
var debouncedMakePreview = _ . debounce ( makePreview , 500 ) ;
return function ( ) {
if ( documentContent === undefined ) {
makePreview ( ) ;
documentContent = '' ;
} else {
debouncedMakePreview ( ) ;
}
} ;
} ;
$ ( window ) . resize ( function ( ) {
scrollLink . buildSections ( ) ;
} ) ;
// 渲染编辑器
mainHandler ( ) ;
function mainHandler ( data ) {
var article = null ;
var cursorPosition = 0 ;
// start editor.
editor1 . run ( previewWrapper ) ;
// Load awesome font to button
$ ( '#wmd-bold-button > span' ) . addClass ( 'fa fa-bold' ) ;
$ ( '#wmd-italic-button > span' ) . addClass ( 'fa fa-italic' ) ;
$ ( '#wmd-link-button > span' ) . addClass ( 'fa fa-link' ) ;
$ ( '#wmd-quote-button > span' ) . addClass ( 'fa fa-quote-left' ) ;
$ ( '#wmd-code-button > span' ) . addClass ( 'fa fa-code' ) ;
$ ( '#wmd-image-button > span' ) . addClass ( 'fa fa-picture-o' ) ;
$ ( '#wmd-olist-button > span' ) . addClass ( 'fa fa-list-ol' ) ;
$ ( '#wmd-ulist-button > span' ) . addClass ( 'fa fa-list-ul' ) ;
$ ( '#wmd-heading-button > span' ) . addClass ( 'fa fa-list-alt' ) ;
$ ( '#wmd-hr-button > span' ) . addClass ( 'fa fa-minus' ) ;
$ ( '#wmd-undo-button > span' ) . addClass ( 'fa fa-undo' ) ;
$ ( '#wmd-redo-button > span' ) . addClass ( 'fa fa-repeat' ) ;
$ ( '#wmd-help-button > span' ) . addClass ( 'fa fa-question-circle' ) ;
function buttonBinding ( rowClassName , spanClassName ) {
// change color when hovering.
$ ( rowClassName ) . hover ( function ( ) {
$ ( spanClassName ) . animate ( { color : '#F9F9F5' } , 400 ) ;
} ,
function ( ) {
$ ( spanClassName ) . animate ( { color : '#BBBBBB' } , 400 ) ;
} ) ;
// enlarge the icon when hovering.
$ ( spanClassName ) . hover ( function ( ) {
$ ( this ) . addClass ( 'icon-large' ) ;
} ,
function ( ) {
$ ( this ) . removeClass ( 'icon-large' ) ;
} ) ;
}
buttonBinding ( '.wmd-button-row' , '.wmd-button > span' ) ;
buttonBinding ( '.preview-button-row' , '.preview-button > span' ) ;
function getCurrentMode ( ) {
var currentMode = { isFullEditor : false , isFullReader : false , isEditorReader : false } ;
return currentMode ;
}
/* ============================= Handle customized shortcut key binding. ========================================= */
browserType = {
isIE : /msie/ . test ( window . navigator . userAgent . toLowerCase ( ) ) ,
isIE _5or6 : /msie 6/ . test ( window . navigator . userAgent . toLowerCase ( ) ) || /msie 5/ . test ( window . navigator . userAgent . toLowerCase ( ) ) ,
isOpera : /opera/ . test ( window . navigator . userAgent . toLowerCase ( ) ) ,
isFirefox : /firefox/ . test ( window . navigator . userAgent . toLowerCase ( ) ) ,
isChrome : /(chrome|chromium)/ . test ( window . navigator . userAgent . toLowerCase ( ) )
} ;
var keyEvent = 'keydown' ;
if ( browserType . isOpera || browserType . isFirefox ) {
keyEvent = 'keypress' ;
}
$ ( document ) . on ( keyEvent , function ( key ) {
// Check to see if we have a button key and, if so execute the callback.
if ( ( key . ctrlKey || key . metaKey ) && ! key . shiftKey ) {
var currentMode = getCurrentMode ( ) ;
var keyCode = key . charCode || key . keyCode ;
var keyCodeStr = String . fromCharCode ( keyCode ) . toLowerCase ( ) ;
switch ( keyCodeStr ) {
/ *
case "m" :
if ( ! key . altKey ) { // 'ctrl + m' for switching normal/full editor
if ( currentMode . isEditorReader ) {
switchFullEditorMode ( ) ;
} else if ( currentMode . isFullEditor ) {
switchNormalModeFromFullEditorMode ( ) ;
}
} else { // 'ctrl + alt + m' for switching normal/full reader
if ( currentMode . isEditorReader ) {
switchFullReaderMode ( ) ;
} else if ( currentMode . isFullReader ) {
switchNormalModeFromFullReaderMode ( ) ;
}
}
break ;
case "j" :
if ( key . altKey ) { // 'ctrl + alt + j' for switching site theme.
switchSiteTheme ( ) ;
break ;
}
case "h" :
if ( key . altKey ) { // 'ctrl + alt + h' for markdown help.
markdownHelp ( ) ;
break ;
}
case "n" :
if ( key . altKey ) { // 'ctrl + alt + n' for markdown help.
clearAndNewFile ( ) ;
break ;
}
* /
default :
return ;
}
if ( key . preventDefault ) {
key . preventDefault ( ) ;
}
if ( window . event ) {
window . event . returnValue = false ;
}
}
} ) ;
// Switch mode if there is.
var currentMode = getCurrentMode ( ) ;
if ( currentMode . isFullEditor ) {
$ ( '#wmd-input' ) . setCursorPosition ( cursorPosition ) ;
switchFullEditorMode ( ) ;
} else if ( currentMode . isFullReader ) { // Don't set focus on '#wmd-input', otherwise, when first time press pagedown key on full reader page, Firefox can't scroll.
switchFullReaderMode ( ) ;
} else { // normal mode
$ ( '#wmd-input' ) . setCursorPosition ( cursorPosition ) ;
}
} // mainHander
} ) ( ) ;