// 主页渲染 //------------- var noCharCodes = [37, 38, 39, 40, 16, 17, 18, 91]; var Resize; // 写作模式 var Writting = { _mode: 'normal', // writting themeWrittingO: $('#themeWritting'), writtingToggleO: $('#writtingToggle'), bodyO: $('body'), isWriting: function() { return this._mode != 'normal'; }, init: function() { var me = this; me.writtingToggleO.click(function() { me.toggle(); }); }, // 初始化写作 // 主要是markdown两列宽度问题 initWritting: function() { var width = UserInfo.MdEditorWidthForWritting; // 设中间 if (!width) { width = this.bodyO.width() / 2; } Resize.setMdColumnWidth(width); // $("#mceToolbar").css("height", "40px"); resizeEditor(); // 切换到写模式 Note.toggleWriteable(); }, initNormal: function() { Resize.setMdColumnWidth(UserInfo.MdEditorWidth); // $("#mceToolbar").css("height", "30px"); resizeEditor(); }, toggle: function() { var me = this; me.themeWrittingO.attr('disabled', me._mode != 'normal'); me._mode = me._mode == 'normal' ? 'writting' : 'normal'; // 改变icon if (me._mode != 'normal') { $('body').addClass('writting'); me.writtingToggleO.find('.fa').removeClass('fa-expand').addClass('fa-compress'); me.initWritting(); } else { $('body').removeClass('writting'); me.writtingToggleO.find('.fa').removeClass('fa-compress').addClass('fa-expand'); me.initNormal(); } }, }; //---------------- // 拖拉改变变宽度 var Resize = { lineMove: false, mdLineMove: false, target: null, leftNotebook: $("#leftNotebook"), notebookSplitter: $("#notebookSplitter"), noteList: $("#noteList"), noteAndEditor: $("#noteAndEditor"), noteSplitter: $("#noteSplitter"), note: $("#note"), body: $("body"), leftColumn: $("#left-column"), rightColumn: $("#right-column"), // $("#preview-panel"), // mdSplitter: $("#mdSplitter2"), init: function() { var self = this; self.initEvent(); }, initEvent: function() { var self = this; // 鼠标点下 $(".noteSplit").bind("mousedown", function(event) { event.preventDefault(); // 防止选择文本 self.lineMove = true; $(this).css("background-color", "#ccc"); self.target = $(this).attr("id"); // 防止iframe捕获不了事件 $("#noteMask").css("z-index", 99999); // .css("background-color", // "#ccc"); }); // 鼠标点下 self.mdSplitter.bind("mousedown", function(event) { event.preventDefault(); // 防止选择文本 if ($(this).hasClass('open')) { self.mdLineMove = true; } // $(this).css("background-color", "#ccc"); }); // 鼠标移动时 self.body.bind("mousemove", function(event) { if (self.lineMove) { // 如果没有这个if会导致不能选择文本 event.preventDefault(); self.resize3Columns(event); } else if (self.mdLineMove) { event.preventDefault(); self.resizeMdColumns(event); } }); // 鼠标放开, 结束 self.body.bind("mouseup", function(event) { self.stopResize(); // 取消遮罩 $("#noteMask").css("z-index", -1); }); // 瞬间 var everLeftWidth; $('.layout-toggler-preview').click(function() { var $t = $(this); var $p = self.leftColumn.parent(); // 是开的 if ($t.hasClass('open')) { var totalWidth = $p.width(); var minRightWidth = 22; var leftWidth = totalWidth - minRightWidth; everLeftWidth = self.leftColumn.width(); self.leftColumn.width(leftWidth); self.rightColumn.css('left', 'auto').width(minRightWidth); // 禁止split $t.removeClass('open'); //.addClass('close'); self.rightColumn.find('.layout-resizer').removeClass('open'); // $('.preview-container').hide(); if (MD) { MD.resize(); } } else { $t.addClass('open'); self.rightColumn.find('.layout-resizer').addClass('open'); self.leftColumn.width(everLeftWidth); // $('.preview-container').show(); self.rightColumn.css('left', everLeftWidth).width('auto'); if (MD) { MD.resize(); } } }); }, // 停止, 保存数据 stopResize: function() { var self = this; if (self.lineMove || self.mdLineMove) { // ajax保存 UserService.updateG({ MdEditorWidth: UserInfo.MdEditorWidth, MdEditorWidthForWritting: UserInfo.MdEditorWidthForWritting, NotebookWidth: UserInfo.NotebookWidth, NoteListWidth: UserInfo.NoteListWidth }, function() { // alert(UserInfo.NotebookWidth); }); } self.lineMove = false; self.mdLineMove = false; $(".noteSplit").css("background", "none"); self.mdSplitter.css("background", "none"); }, // 最终调用该方法 set3ColumnsWidth: function(notebookWidth, noteListWidth) { var self = this; if (notebookWidth < 150 || noteListWidth < 100) { self.setTopDragWidth(); return; } var noteWidth = self.body.width() - notebookWidth - noteListWidth; if (noteWidth < 400) { self.setTopDragWidth(); return; } self.leftNotebook.width(notebookWidth); self.notebookSplitter.css("left", notebookWidth); self.noteAndEditor.css("left", notebookWidth); self.noteList.width(noteListWidth); self.noteSplitter.css("left", noteListWidth); self.note.css("left", noteListWidth + 2); UserInfo.NotebookWidth = notebookWidth; UserInfo.NoteListWidth = noteListWidth; self.setTopDragWidth(); }, resize3Columns: function(event, isFromeIfr) { var self = this; if (isFromeIfr) { event.clientX += self.body.width() - self.note.width(); } var notebookWidth, noteListWidth; if (self.lineMove) { if (self.target == "notebookSplitter") { notebookWidth = event.clientX; noteListWidth = self.noteList.width(); self.set3ColumnsWidth(notebookWidth, noteListWidth); } else { notebookWidth = self.leftNotebook.width(); noteListWidth = event.clientX - notebookWidth; self.set3ColumnsWidth(notebookWidth, noteListWidth); } resizeEditor(); } }, // mdeditor resizeMDInterval: null, resizeMdColumns: function(event) { var self = this; if (self.mdLineMove) { var mdEditorWidth = event.clientX - self.leftColumn.offset().left; // self.leftNotebook.width() - self.noteList.width(); self.setMdColumnWidth(mdEditorWidth); clearInterval(self.resizeMDInterval); self.resizeMDInterval = setTimeout(function() { MD.resize && MD.resize(); }, 50); } }, // 设置宽度 setMdColumnWidth: function(mdEditorWidth) { var self = this; var allWidth = $('#note').width(); if (mdEditorWidth > 100 && mdEditorWidth < allWidth - 80) { if (Writting.isWriting()) { UserInfo.MdEditorWidthForWritting = mdEditorWidth; } else { UserInfo.MdEditorWidth = mdEditorWidth; } self.leftColumn.width(mdEditorWidth); self.rightColumn.css("left", mdEditorWidth); } // 这样, scrollPreview 才会到正确的位置 if (MD) { MD.onResize(); } }, // 左+中 // 在atom中, 尽管title和tool的index比topDrag大也没用, 导致不能点击tool, 不能选择title setTopDragWidth: function() { if (!isMac()) { return; } var self = this; var width = UserInfo.NotebookWidth + UserInfo.noteListWidth; if (isNaN(width)) { width = self.leftNotebook.width() + self.noteList.width(); } var w = width - 60 - 50; w = w > 100 ? w : 100; $('#topDrag').width(w + 'px'); } }; //-------------------------- // 手机端访问之 Mobile = { // 点击之笔记 // 切换到编辑器模式 noteO: $("#note"), bodyO: $("body"), setMenuO: $("#setMenu"), // 弃用, 统一使用Pjax hashChange: function() { var self = Mobile; var hash = location.hash; // noteId if (hash.indexOf("noteId") != -1) { self.toEditor(false); var noteId = hash.substr(8); Note.changeNote(noteId, false, false); } else { // 笔记本和笔记列表 self.toNormal(false); } }, init: function() { var self = this; self.isMobile(); }, isMobile: function() { var u = navigator.userAgent; LEA.isMobile = false; LEA.isMobile = /Mobile|Android|iPhone|iPad/i.test(u); LEA.isIpad = /iPad/i.test(u); LEA.isIphone = /iPhone/i.test(u); if (!LEA.isMobile && $(document).width() <= 700) { LEA.isMobile = true } return LEA.isMobile; }, // 改变笔记, 此时切换到编辑器模式下 // note.js click事件处理, 先切换到纯编辑器下, 再调用Note.changeNote() changeNote: function(noteId) { var self = this; if (!LEA.isMobile) { return true; } self.toEditor(true, noteId); return false; }, toEditor: function(changeHash, noteId) { var self = this; self.bodyO.addClass("full-editor"); self.noteO.addClass("editor-show"); /* if(changeHash) { if(!noteId) { noteId = Note.curNoteId; } location.hash = "noteId=" + noteId; } */ }, toNormal: function(changeHash) { var self = this; self.bodyO.removeClass("full-editor"); self.noteO.removeClass("editor-show"); /* if(changeHash) { location.hash = "notebookAndNote"; } */ }, switchPage: function() { var self = this; if (!LEA.isMobile || LEA.isIpad) { return true; } if (self.bodyO.hasClass("full-editor")) { self.toNormal(true); } else { self.toEditor(true); } return false; } }; function initSlimScroll() { return; } //----------- // 初始化编辑器 function initEditor() { // editor // toolbar 下拉扩展, 也要resizeEditor var mceToobarEverHeight = 0; $("#moreBtn").click(function() { saveBookmark(); var $editor = $('#editor'); if ($editor.hasClass('all-tool')) { $editor.removeClass('all-tool'); } else { $editor.addClass('all-tool'); } restoreBookmark(); return; var height = $("#mceToolbar").height(); // 现在是折叠的 if (height < $("#popularToolbar").height()) { $("#mceToolbar").height($("#popularToolbar").height()); $(this).find("i").removeClass("fa-angle-down").addClass("fa-angle-up"); mceToobarEverHeight = height; } else { $("#mceToolbar").height(mceToobarEverHeight); $(this).find("i").removeClass("fa-angle-up").addClass("fa-angle-down"); } resizeEditor(); restoreBookmark(); }); // 初始化编辑器 tinymce.init({ inline: true, theme: 'leanote', // readonly : false, valid_children: "+pre[div|#text|p|span|textarea|i|b|strong]", // ace setup: function(ed) { // electron下有问题, Ace剪切导致行数减少, #16 ed.on('cut', function(e) { if ($(e.target).hasClass('ace_text-input')) { e.preventDefault(); return; } }); ed.on('keydown', function(e) { var num = e.which ? e.which : e.keyCode; // 如果是readony, 则不能做任何操作, 除了v, x, z if (Note.readOnly && ((e.ctrlKey || e.metaKey) && (num == 88 || num == 86 || num == 90))) { console.log('keydown preventDefault') e.preventDefault(); return; } // 没有ctrl, 直接输入x, <- if (Note.readOnly && !(e.ctrlKey || e.metaKey)) { console.log('keydown preventDefault') e.preventDefault(); return; } // 设置dirty, ctrl+c都设了 if (!Note.readOnly) { if (noCharCodes.indexOf(num) >= 0) { setEditorIsDirty(true); } } /* var num = e.which ? e.which : e.keyCode; if(e.ctrlKey || e.metaKey) { if(num == 86) { // ctrl + v // document.execCommand('paste'); } }; */ // 0.25.2必须要, 默认没有 // commonCmd(e); }); }, // fix TinyMCE Removes site base url // http://stackoverflow.com/questions/3360084/tinymce-removes-site-base-urls convert_urls: true, relative_urls: false, remove_script_host: false, selector: "#editorContent", // height: 100,//这个应该是文档的高度, 而其上层的高度是$("#content").height(), // parentHeight: $("#content").height(), // content_css : ["public/css/editor/editor.css"], // skin : "custom", language: Api.curLang.indexOf('zh') >= 0 ? 'zh' : 'en', // 语言 plugins: [ "autolink link image leaui_mindmap lists charmap hr", "paste", "searchreplace leanote_nav leanote_code tabfocus", "table directionality textcolor" ], // nonbreaking toolbar1: "formatselect | forecolor backcolor | bold italic underline strikethrough | image leaui_mindmap | leanote_code leanote_inline_code | bullist numlist | alignleft aligncenter alignright alignjustify", toolbar2: "outdent indent blockquote | link unlink | table | hr removeformat | subscript superscript | searchreplace | pastetext | leanote_ace_pre | fontselect fontsizeselect", // 使用tab键: http://www.tinymce.com/wiki.php/Plugin3x:nonbreaking // http://stackoverflow.com/questions/13543220/tiny-mce-how-to-allow-people-to-indent // nonbreaking_force_tab : true, menubar: false, toolbar_items_size: 'small', statusbar: false, url_converter: false, font_formats: "Arial=arial,helvetica,sans-serif;" + "Arial Black=arial black,avant garde;" + "Times New Roman=times new roman,times;" + "Courier New=courier new,courier;" + "Tahoma=tahoma,arial,helvetica,sans-serif;" + "Verdana=verdana,geneva;" + "宋体=SimSun;" + "新宋体=NSimSun;" + "黑体=SimHei;" + "Microsoft YaHei=Microsoft YaHei", block_formats: "Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Paragraph=p", // This option specifies whether data:url images (inline images) should be removed or not from the pasted contents. // Setting this to "true" will allow the pasted images, and setting this to "false" will disallow pasted images. // For example, Firefox enables you to paste images directly into any contentEditable field. This is normally not something people want, so this option is "false" by default. paste_data_images: true }); // 刷新时保存 参考autosave插件 window.onbeforeunload = function(e) { Note.curChangedSaveIt(true); }; // 全局ctrl + s $("body").on('keydown', Note.saveNote); } //----------------------- // 导航 var random = 1; function scrollTo(self, tagName, text) { var iframe = $("#editorContent"); // .contents(); if (Writting.isWriting()) { iframe = $('#editorContentWrap'); } var target = iframe.find(tagName + ":contains(" + text + ")"); random++; // 找到是第几个 // 在nav是第几个 var navs = $('#leanoteNavContent [data-a="' + tagName + '-' + encodeURI(text) + '"]'); // alert('#leanoteNavContent [data-a="' + tagName + '-' + encodeURI(text) + '"]') var len = navs.size(); for (var i = 0; i < len; ++i) { if (navs[i] == self) { break; } } if (target.size() >= i + 1) { target = target.eq(i); // 之前插入, 防止多行定位不准 // log(target.scrollTop()); var top = iframe.scrollTop() - iframe.offset().top + target.offset().top; // 相对于iframe的位置 // var nowTop = iframe.scrollTop(); // log(nowTop); // log(top); // iframe.scrollTop(top); iframe.animate({ scrollTop: top }, 300); // 有问题 return; } } // 设置宽度, 三栏 function setLayoutWidth() { //------------------------ // 界面设置, 左侧是否是隐藏的 UserInfo.NotebookWidth = UserInfo.NotebookWidth || $("#notebook").width(); UserInfo.NoteListWidth = UserInfo.NoteListWidth || $("#noteList").width(); Resize.init(); // alert(UserInfo.NotebookWidth); Resize.set3ColumnsWidth(UserInfo.NotebookWidth, UserInfo.NoteListWidth); Resize.setMdColumnWidth(UserInfo.MdEditorWidth); } //-------------- // 调用之 $(function() { // 窗口缩放时 $(window).resize(function() { Mobile.isMobile(); resizeEditor(); }); // 初始化编辑器 initEditor(); // 左侧, folder 展开与关闭 $(".folderHeader").click(function() { var body = $(this).next(); var p = $(this).parent(); if (!body.is(":hidden")) { $(".folderNote").removeClass("opened").addClass("closed"); // body.hide(); p.removeClass("opened").addClass("closed"); $(this).find(".fa-angle-down").removeClass("fa-angle-down").addClass("fa-angle-right"); } else { $(".folderNote").removeClass("opened").addClass("closed"); // body.show(); p.removeClass("closed").addClass("opened"); $(this).find(".fa-angle-right").removeClass("fa-angle-right").addClass("fa-angle-down"); } }); // 导航隐藏与显示 $(".leanoteNav h1").on("click", function(e) { var $leanoteNav = $(this).closest('.leanoteNav'); if (!$leanoteNav.hasClass("unfolder")) { $leanoteNav.addClass("unfolder"); } else { $leanoteNav.removeClass("unfolder"); } }); // 打开设置 function openSetInfoDialog(whichTab) { showDialogRemote("/user/account", { tab: whichTab }); } // 禁止双击选中文字 $("#notebook, #newMyNote, #myProfile, #topNav, #notesAndSort", "#leanoteNavTrigger").bind("selectstart", function(e) { e.preventDefault(); return false; }); // 得到最大dropdown高度 // 废弃 function getMaxDropdownHeight(obj) { var offset = $(obj).offset(); var maxHeight = $(document).height() - offset.top; maxHeight -= 70; if (maxHeight < 0) { maxHeight = 0; } var preHeight = $(obj).find("ul").height(); return preHeight < maxHeight ? preHeight : maxHeight; } // 内容下的a点击, 跳转 $('#editorContent').on('click', 'a', function(e) { e.preventDefault(); if (LEA.readOnly) { var url = $(this).attr('href'); if (isOtherSiteUrl(url)) { openExternal(url); } } return false; }); $('#preview-contents').on('click', 'a', function(e) { e.preventDefault(); var url = $(this).attr('href'); if (isOtherSiteUrl(url)) { openExternal(url); } }); // markdown编辑器paste $('#left-column').on('paste', function(e) { pasteImage(e); }); }); //------------ // pjax //------------ var Pjax = { init: function() { var me = this; // 当history改变时 window.addEventListener('popstate', function(evt) { var state = evt.state; if (!state) { return; } document.title = state.title || "Untitled"; log("pop"); me.changeNotebookAndNote(state.noteId); }, false); // ie9 if (!history.pushState) { $(window).on("hashchange", function() { var noteId = getHash("noteId");; if (noteId) { me.changeNotebookAndNote(noteId); } }); } }, // pjax调用 // popstate事件发生时, 转换到noteId下, 此时要转换notebookId changeNotebookAndNote: function(noteId) { var note = Note.getNote(noteId); if (!note) { return; } var isShare = note.Perm != undefined; var notebookId = note.NotebookId; // 如果是在当前notebook下, 就不要转换notebook了 if (Notebook.curNotebookId == notebookId) { // 不push state Note.changeNoteForPjax(noteId, false); return; } // 自己的 if (!isShare) { // 先切换到notebook下, 得到notes列表, 再changeNote Notebook.changeNotebook(notebookId, function(notes) { Note.renderNotes(notes); // 不push state Note.changeNoteForPjax(noteId, false, true); }); // 共享笔记 } else {} }, // ajax后调用 changeNote: function(noteInfo) { var me = this; // life return; log("push"); var noteId = noteInfo.NoteId; var title = noteInfo.Title; var url = '/note/' + noteId; if (location.hash) { url += location.hash; } // 如果支持pushState if (history.pushState) { var state = ({ url: url, noteId: noteId, title: title, }); history.pushState(state, title, url); document.title = title || 'Untitled'; // 不支持, 则用hash } else { setHash("noteId", noteId); } } }; $(function() { Pjax.init(); }); //---------- // aceEditor LeaAce = { // aceEditorID _aceId: 0, // {id=>ace} _aceEditors: {}, _isInit: false, _canAce: false, isAce: true, // 切换pre, 默认是true disableAddHistory: function() { tinymce.activeEditor.undoManager.setCanAdd(false); }, resetAddHistory: function() { tinymce.activeEditor.undoManager.setCanAdd(true); }, canAce: function() { return true; /* if(this._isInit) { return this._canAce; } if(getVendorPrefix() == "webkit" && !Mobile.isMobile()) { this._canAce = true; } else { this._canAce = false; } this._isInit = true; return this._canAce; */ }, canAndIsAce: function() { return this.canAce() && this.isAce; }, getAceId: function() { this.aceId++; return "leanote_ace_" + (new Date()).getTime() + "_" + this._aceId; }, initAce: function(id, val, force) { var me = this; if (!force && !me.canAndIsAce()) { return; } var $pre = $('#' + id); if ($pre.length == 0) { return; } var rawCode = $pre.html(); // 原生code try { me.disableAddHistory(); // 本身就有格式的, 防止之前有格式的显示为(ace下) var classes = $pre.attr('class') || ''; var isHtml = classes.indexOf('brush:html') != -1; if ($pre.attr('style')/* || (!isHtml && $pre.html().indexOf('