From 0b6742873e1365c54a3626d183ed6369e430eb95 Mon Sep 17 00:00:00 2001 From: benweet Date: Wed, 19 Mar 2014 22:10:59 +0000 Subject: [PATCH] Fixes for new editor --- public/res/classes/preEditor copy.js | 183 ---------------------- public/res/core.js | 12 +- public/res/editor.js | 66 +++++--- public/res/extensions/buttonFocusMode.js | 45 +----- public/res/extensions/workingIndicator.js | 45 +++++- public/res/helpers/googleHelper.js | 14 +- public/res/html/bodyIndex.html | 54 +++---- public/res/libs/prism-markdown.js | 40 ++--- public/res/styles/main.less | 40 ++--- public/res/utils.js | 12 +- 10 files changed, 175 insertions(+), 336 deletions(-) delete mode 100644 public/res/classes/preEditor copy.js diff --git a/public/res/classes/preEditor copy.js b/public/res/classes/preEditor copy.js deleted file mode 100644 index 70a7e74b..00000000 --- a/public/res/classes/preEditor copy.js +++ /dev/null @@ -1,183 +0,0 @@ -define(['jquery'], function($) { - function PreEditor(preElt) { - this.selectionStart = 0; - this.selectionEnd = 0; - this.scrollTop = 0; - this.$preContentElt = $('
'); - - preElt.appendChild(this.$preContentElt[0]); - - preElt.focus = function() { - this.$preContentElt.focus(); - this.setSelectionRange(this.selectionStart, this.selectionEnd); - preElt.scrollTop = this.scrollTop; - }; - this.$preContentElt.focus(function() { - preElt.focused = true; - }); - this.$preContentElt.blur(function() { - preElt.focused = false; - }); - Object.defineProperty(preElt, 'value', { - get: function() { - return this.$preContentElt.text(); - }, - set: function(value) { - this.$preContentElt.text(value); - } - }); - - Object.defineProperty(preElt, 'value', { - get: function() { - return this.$preContentElt.text(); - }, - set: function(value) { - this.$preContentElt.text(value); - } - }); - Object.defineProperty(preElt, 'selectionStart', { - get: function() { - var selection = window.getSelection(); - - if(selection.rangeCount) { - var range = selection.getRangeAt(0), - element = range.startContainer, - container = element, - offset = range.startOffset; - - if(!(this.compareDocumentPosition(element) & 0x10)) { - return 0; - } - - do { - while(element = element.previousSibling) { - if(element.textContent) { - offset += element.textContent.length; - } - } - - element = container = container.parentNode; - } while(element && element != this); - - return offset; - } - else { - return 0; - } - }, - set: function(value) { - preElt.setSelectionRange(value, this.selectionEnd); - }, - - enumerable: true, - configurable: true - }); - - Object.defineProperty(preElt, 'selectionEnd', { - get: function() { - var selection = window.getSelection(); - - if(selection.rangeCount) { - return this.selectionStart + (selection.getRangeAt(0) + '').length; - } - else { - return 0; - } - }, - set: function(value) { - preElt.setSelectionRange(this.selectionStart, value); - }, - - enumerable: true, - configurable: true - }); - - preElt.setSelectionRange = function(ss, se) { - this.selectionStart = ss; - this.selectionEnd = se; - function findOffset(root, ss) { - if(!root) { - return null; - } - - var offset = 0, - element = root, - container; - - do { - container = element; - element = element.firstChild; - - if(element) { - do { - var len = element.textContent.length; - - if(offset <= ss && offset + len > ss) { - break; - } - - offset += len; - } while(element = element.nextSibling); - } - - if(!element) { - // It's the container's lastChild - break; - } - } while(element && element.hasChildNodes() && element.nodeType != 3); - - if(element) { - return { - element: element, - offset: ss - offset - }; - } - else if(container) { - element = container; - - while(element && element.lastChild) { - element = element.lastChild; - } - - if(element.nodeType === 3) { - return { - element: element, - offset: element.textContent.length - }; - } - else { - return { - element: element, - offset: 0 - }; - } - } - - return { - element: root, - offset: 0, - error: true - }; - } - - var range = document.createRange(), - offset = findOffset(this, ss); - - range.setStart(offset.element, offset.offset); - - if(se && se != ss) { - offset = findOffset(this, se); - } - - range.setEnd(offset.element, offset.offset); - - var selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(range); - }; - - } - - - return PreEditor; -}); \ No newline at end of file diff --git a/public/res/core.js b/public/res/core.js index 7fb3a65f..ecb7710b 100644 --- a/public/res/core.js +++ b/public/res/core.js @@ -726,7 +726,9 @@ define([ }); // Apply dynamic stylesheet - var style = document.createElement("style"); + var style = crel('style', { + type : 'text/css' + }); style.innerHTML = styleContent; document.head.appendChild(style); @@ -773,7 +775,7 @@ define([ menuPanelBackdropElt = utils.createBackdrop('collapse', '.menu-panel'); $menuPanelElt.addClass('move-to-front'); // To avoid opening delay - setTimeout(function() { + $.support.transition && setTimeout(function() { $menuPanelElt.trigger($.support.transition.end); }, 50); } @@ -784,7 +786,7 @@ define([ }).on('hide.bs.collapse', function(e) { if(e.target === $menuPanelElt[0]) { isMenuPanelShown = false; - menuPanelBackdropElt.parentNode.removeChild(menuPanelBackdropElt); + menuPanelBackdropElt.removeBackdrop(); $menuPanelElt.removeClass('move-to-front'); aceEditor ? aceEditor.focus() : $editorElt.focus(); } @@ -805,7 +807,7 @@ define([ documentPanelBackdropElt = utils.createBackdrop('collapse', '.document-panel'); $documentPanelElt.addClass('move-to-front'); // To avoid opening delay - setTimeout(function() { + $.support.transition && setTimeout(function() { $documentPanelElt.trigger($.support.transition.end); }, 50); } @@ -816,7 +818,7 @@ define([ }).on('hide.bs.collapse', function(e) { if(e.target === $documentPanelElt[0]) { isDocumentPanelShown = false; - documentPanelBackdropElt.parentNode.removeChild(documentPanelBackdropElt); + documentPanelBackdropElt.removeBackdrop(); $documentPanelElt.removeClass('move-to-front'); aceEditor ? aceEditor.focus() : $editorElt.focus(); } diff --git a/public/res/editor.js b/public/res/editor.js index d4373790..7e5b6788 100644 --- a/public/res/editor.js +++ b/public/res/editor.js @@ -20,6 +20,7 @@ define([ var selectionEnd = 0; var scrollTop = 0; var inputElt; + var $inputElt; var previewElt; var pagedownEditor; var refreshPreviewLater = (function() { @@ -93,7 +94,7 @@ define([ } function adjustCursorPosition() { - setTimeout(function() { + inputElt && setTimeout(function() { selectionStart = inputElt.selectionStart; selectionEnd = inputElt.selectionEnd; @@ -114,14 +115,13 @@ define([ cursorY = container.parentNode.offsetTop + container.parentNode.offsetHeight / 2 - inputElt.scrollTop; } else { - if(selectionStart === selectionEnd) { - var selectedChar = inputElt.textContent[selectionStart]; - if(selectedChar === undefined || selectedChar == '\n') { - selectionRange = createRange(selectionStart - 1, selectionEnd); - } - else { - selectionRange = createRange(selectionStart, selectionEnd + 1); - } + var cursorOffset = backwards ? selectionStart : selectionEnd; + var selectedChar = inputElt.textContent[cursorOffset]; + if(selectedChar === undefined || selectedChar == '\n') { + selectionRange = createRange(cursorOffset - 1, cursorOffset); + } + else { + selectionRange = createRange(cursorOffset, cursorOffset + 1); } var selectionRect = selectionRange.getBoundingClientRect(); cursorY = selectionRect.top + selectionRect.height / 2 - inputElt.offsetTop; @@ -146,9 +146,10 @@ define([ editor.init = function(elt1, elt2) { inputElt = elt1; + $inputElt = $(inputElt); previewElt = elt2; editor.contentElt = crel('div', { - class: 'pre-content', + class: 'editor-content', contenteditable: true }); editor.$contentElt = $(editor.contentElt); @@ -279,10 +280,11 @@ define([ selection.addRange(range); }; + var clearNewline = false; editor.$contentElt.on('keydown', function (evt) { var cmdOrCtrl = evt.metaKey || evt.ctrlKey; - if(!cmdOrCtrl && !event.altKey && !event.shiftKey) { + if(!cmdOrCtrl && !event.altKey && !(event.shiftKey && evt.keyCode === 16)) { adjustCursorPosition(); } @@ -308,6 +310,9 @@ define([ } break; } + if(evt.keyCode !== 13) { + clearNewline = false; + } }); editor.$contentElt.on('paste', function () { @@ -339,12 +344,9 @@ define([ }; actions[action](state, options); - inputElt.value = state.before + state.selection + state.after; - inputElt.setSelectionRange(state.ss, state.se); - - inputElt.dispatchEvent(new window.Event('input')); + $inputElt.trigger('input'); }; var actions = { @@ -382,14 +384,30 @@ define([ newline: function (state) { var lf = state.before.lastIndexOf('\n') + 1; - var indent = (state.before.slice(lf).match(/^\s+/) || [''])[0]; + if(clearNewline) { + state.before = state.before.substring(0, lf); + state.selection = ''; + state.ss = lf; + state.se = lf; + clearNewline = false; + return; + } + clearNewline = false; + var previousLine = state.before.slice(lf); + var indentMatch = previousLine.match(/^ {0,3}>[ ]*|^[ \t]*(?:[*+\-]|(\d+)\.)[ \t]|^\s+/); + var indent = (indentMatch || [''])[0]; + if(indentMatch && indentMatch[1]) { + var number = parseInt(indentMatch[1], 10); + indent = indent.replace(/\d+/, number + 1); + } + if(indent.length) { + clearNewline = true; + } pagedownEditor.undoManager.setMode("newlines"); state.before += '\n' + indent; - state.selection = ''; - state.ss += indent.length + 1; state.se = state.ss; }, @@ -504,12 +522,20 @@ define([ } function highlight(section) { - var text = section.textWithFrontMatter.replace(/&/g, '&').replace(/\n'); + text = '' + frontMatter + '' + text; + } var sectionElt = crel('span', { id: 'wmd-input-section-' + section.id, class: 'wmd-input-section' }); - sectionElt.innerHTML = Prism.highlight(text, Prism.languages.md); + sectionElt.innerHTML = text; section.highlightedContent = sectionElt; } diff --git a/public/res/extensions/buttonFocusMode.js b/public/res/extensions/buttonFocusMode.js index f7380137..e1e7d101 100644 --- a/public/res/extensions/buttonFocusMode.js +++ b/public/res/extensions/buttonFocusMode.js @@ -1,10 +1,9 @@ define([ "jquery", "underscore", - "caret", "crel", "classes/Extension" -], function($, _, caret, crel, Extension) { +], function($, _, crel, Extension) { var buttonFocusMode = new Extension("buttonFocusMode", 'Button "Focus Mode"', true, true); buttonFocusMode.settingsBlock = "When typing, scrolls automatically the editor to always have the caret centered verticaly."; @@ -25,41 +24,7 @@ define([ aceEditor.session.setScrollTop((positionInScreen.row + 0.5) * aceEditor.renderer.lineHeight - aceEditor.renderer.$size.scrollerHeight / 2); } } - - var $editorElt; - //var $positionHelper = $('').css('display', 'inline-block'); - var coef = 0.2; - function doFocus() { - setTimeout(function() { - if(!($editorElt && $editorElt[0].focused)) { - return; - } - /* - var range = window.getSelection().getRangeAt(0); - range.insertNode($positionHelper[0]); - var parentNode = $positionHelper[0].parentNode; - */ - var editorHeight = $editorElt.height(); - var cursorMinY = coef*editorHeight; - var cursorMaxY = (1-coef)*editorHeight; - var cursorY = $editorElt.caret('offset').top - $editorElt.offset().top; - //console.log($editorElt.find('.pre-content').caret('offset')); - //console.log(window.getSelection().getRangeAt(0).getBoundingClientRect()); - //$positionHelper.detach(); - //parentNode.normalize(); - /* - if(cursorY < cursorMinY) { - $editorElt.scrollTop($editorElt.scrollTop() - cursorMinY + cursorY); - } - else if(cursorY > cursorMaxY) { - $editorElt.scrollTop($editorElt.scrollTop() + cursorY - cursorMaxY); - } - */ - }, 0); - } - buttonFocusMode.onLayoutResize = doFocus; - buttonFocusMode.onReady = function() { if(aceEditor) { aceEditor.getSession().selection.on('changeCursor', doFocusMode); @@ -71,15 +36,7 @@ define([ }, true); return; } - $editorElt = $('#wmd-input').on('keydown', function(event) { - if(event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) { - return; - } - doFocus(); - }); }; return buttonFocusMode; }); - - diff --git a/public/res/extensions/workingIndicator.js b/public/res/extensions/workingIndicator.js index f983fdc7..639fc7a1 100644 --- a/public/res/extensions/workingIndicator.js +++ b/public/res/extensions/workingIndicator.js @@ -1,29 +1,64 @@ define([ "jquery", "underscore", + "crel", "classes/Extension" -], function ($, _, Extension) { +], function ($, _, crel, Extension) { var workingIndicator = new Extension("workingIndicator", "Working Indicator"); + var keyframeTemlate = [ + '@<%= prefix %>keyframes <%= name %> {', + ' 0% { opacity:<%= z %>; }', + ' <%= start %>.01% { opacity:<%= alpha %>; }', + ' <%= start %>.02% { opacity:1; }', + ' <%= ((start + trail) % 100) %>.01% { opacity:<%= alpha %>; }', + ' 100% { opacity:<%= z %>; }', + '}' + ].join('\n'); + var $bodyElt; var $workingIndicatorElt; workingIndicator.onAsyncRunning = function (isRunning) { $bodyElt.toggleClass("working", isRunning); $workingIndicatorElt.toggleClass("hide", !isRunning); }; - + workingIndicator.onReady = function () { + var styleContent = ''; + + function addKeyframe(params) { + params.z = Math.max(1 - (1-params.alpha) / params.trail * (100-params.start), params.alpha); + styleContent += _.template(keyframeTemlate, _.extend({ + prefix: '' + }, params)); + styleContent += _.template(keyframeTemlate, _.extend({ + prefix: '-webkit-' + }, params)); + } $bodyElt = $(document.body); $workingIndicatorElt = $('
'); $('.working-indicator').append($workingIndicatorElt); for (var i = 0; i < 3; i++) { + var name = 'working-indicator-bar' + i; + addKeyframe({ + name: name, + alpha: 0.25, + start: 20 * i, + trail: 50 + }); + var animation = name + ' 0.7s linear infinite'; $workingIndicatorElt.append($('
').css({ - 'animation-delay': (i*15/100).toPrecision(3) + 's', - '-webkit-animation-delay': (i*15/100).toPrecision(3) + 's', + 'animation': animation, + '-webkit-animation': animation, })); } + var styleElt = crel('style', { + type : 'text/css' + }); + document.head.appendChild(styleElt); + styleElt.innerHTML = styleContent; }; return workingIndicator; -}); \ No newline at end of file +}); diff --git a/public/res/helpers/googleHelper.js b/public/res/helpers/googleHelper.js index 1b2448c1..43a7a86a 100644 --- a/public/res/helpers/googleHelper.js +++ b/public/res/helpers/googleHelper.js @@ -215,7 +215,7 @@ define([ authenticate(task, 'gdrive', accountId); task.enqueue(); }; - + function runWithToken(accountId, functionToRun) { var currentToken = gapi.auth.getToken(); var authorizationMgr = authorizationMgrMap[accountId]; @@ -262,7 +262,7 @@ define([ // if(etag !== undefined) { // headers["If-Match"] = etag; // } - + var base64Data = utils.encodeBase64(content); var multipartRequestBody = [ delimiter, @@ -277,7 +277,7 @@ define([ base64Data, close_delim ].join(""); - + runWithToken(accountId, function() { var request = gapi.client.request({ 'path': path, @@ -320,7 +320,7 @@ define([ }); task.enqueue(); }; - + googleHelper.rename = function(fileId, title, accountId, callback) { var result; var task = new AsyncTask(); @@ -424,7 +424,7 @@ define([ 'pageToken': nextPageToken }); } - + request.execute(function(response) { if(!response || !response.largestChangeId) { // Handle error @@ -1037,7 +1037,7 @@ define([ }); task.enqueue(); }; - + // Use by Google's client.js window.delayedFunction = undefined; window.runDelayedFunction = function() { @@ -1045,6 +1045,6 @@ define([ window.delayedFunction(); } }; - + return googleHelper; }); diff --git a/public/res/html/bodyIndex.html b/public/res/html/bodyIndex.html index c45b634b..dbf89462 100644 --- a/public/res/html/bodyIndex.html +++ b/public/res/html/bodyIndex.html @@ -58,7 +58,7 @@ StackEdit Viewer - +
@@ -104,7 +104,7 @@
+ class="action-reset-input list-group-item"> Sharing links Export to disk @@ -189,7 +189,7 @@
-