From 0667cbeefb49e212e767a180c9319471537cd117 Mon Sep 17 00:00:00 2001
From: Julia Casamitjana <62883011+JuliaCasamitjana@users.noreply.github.com>
Date: Thu, 11 Apr 2024 10:42:41 +0200
Subject: [PATCH] Drop pagedown-bootstrap library and all its related code
---
Gemfile | 1 -
Gemfile.lock | 3 -
app/assets/javascripts/application.js | 1 -
app/assets/javascripts/forms.js | 1 -
.../pagedown/markdown.editor.js.erb | 2131 -----------------
.../javascripts/pagedown/pagedown.js.erb | 43 -
app/assets/stylesheets/application.css | 1 -
app/assets/stylesheets/forms.css.scss | 4 -
8 files changed, 2185 deletions(-)
delete mode 100644 app/assets/javascripts/pagedown/markdown.editor.js.erb
delete mode 100644 app/assets/javascripts/pagedown/pagedown.js.erb
diff --git a/Gemfile b/Gemfile
index ac874ee9..db86ce0a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -32,7 +32,6 @@ gem 'net-imap', require: false
gem 'net-pop', require: false
gem 'net-smtp', require: false
gem 'nokogiri'
-gem 'pagedown-bootstrap-rails'
gem 'pg'
gem 'proformaxml', '~> 1.3.0'
gem 'prometheus_exporter'
diff --git a/Gemfile.lock b/Gemfile.lock
index fdae0ca8..d962657d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -291,8 +291,6 @@ GEM
snaky_hash (~> 2.0)
version_gem (~> 1.1)
package_json (0.1.0)
- pagedown-bootstrap-rails (2.1.4)
- railties (> 3.1)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
@@ -611,7 +609,6 @@ DEPENDENCIES
net-pop
net-smtp
nokogiri
- pagedown-bootstrap-rails
pg
proformaxml (~> 1.3.0)
prometheus_exporter
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index e41e63dc..2eeeb357 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -11,7 +11,6 @@
// about supported directives.
//
//= require turbolinks
-//= require pagedown_bootstrap
//= require rails-timeago
//= require locales/jquery.timeago.de.js
//
diff --git a/app/assets/javascripts/forms.js b/app/assets/javascripts/forms.js
index 2be40eba..86b1b211 100644
--- a/app/assets/javascripts/forms.js
+++ b/app/assets/javascripts/forms.js
@@ -52,5 +52,4 @@ $(document).on('turbolinks:load', function() {
// Remove some elements before going back to an older site. Otherwise, they might not work.
$(document).on('turbolinks:before-cache', function() {
$('.chosen-container').remove();
- $('#wmd-button-row-description').remove();
});
diff --git a/app/assets/javascripts/pagedown/markdown.editor.js.erb b/app/assets/javascripts/pagedown/markdown.editor.js.erb
deleted file mode 100644
index 888b5860..00000000
--- a/app/assets/javascripts/pagedown/markdown.editor.js.erb
+++ /dev/null
@@ -1,2131 +0,0 @@
-// needs Markdown.Converter.js at the moment
-
-(function () {
-
- var util = {},
- position = {},
- ui = {},
- doc = window.document,
- re = window.RegExp,
- nav = window.navigator,
- SETTINGS = { lineLength: 72 },
-
- // Used to work around some browser bugs where we can't use feature testing.
- uaSniffed = {
- isIE: /msie/.test(nav.userAgent.toLowerCase()),
- isIE_5or6: /msie 6/.test(nav.userAgent.toLowerCase()) || /msie 5/.test(nav.userAgent.toLowerCase()),
- isOpera: /opera/.test(nav.userAgent.toLowerCase())
- };
-
-
- // -------------------------------------------------------------------
- // YOUR CHANGES GO HERE
- //
- // I've tried to localize the things you are likely to change to
- // this area.
- // -------------------------------------------------------------------
-
- // The text that appears on the upper part of the dialog box when
- // entering links.
- var linkDialogTitle = "<%= I18n.t('components.markdown_editor.insert_link.dialog_title', default: 'Insert link') %>";
- var linkInputLabel = "<%= I18n.t('components.markdown_editor.insert_link.input_label', default: 'Link URL') %>";
- var linkInputPlaceholder = "https://example.com/ \"optional title\"";
- var linkInputHelp = "<%= I18n.t('components.markdown_editor.insert_link.input_help', default: 'Enter URL to point link to and optional title to display when mouse is placed over the link') %>";
-
- var imageDialogTitle = "<%= I18n.t('components.markdown_editor.insert_image.dialog_title', default: 'Insert image') %>";
- var imageInputLabel = "<%= I18n.t('components.markdown_editor.insert_image.input_label', default: 'Image URL') %>";
- var imageInputPlaceholder = "https://example.com/images/diagram.jpg \"optional title\"";
- var imageInputHelp = "<%= I18n.t('components.markdown_editor.insert_link.input_help', default: 'Enter URL where image is located and optional title to display when mouse is placed over the image') %>";
-
- var defaultHelpHoverTitle = "Markdown Editing Help";
-
- // -------------------------------------------------------------------
- // END OF YOUR CHANGES
- // -------------------------------------------------------------------
-
- // help, if given, should have a property "handler", the click handler for the help button,
- // and can have an optional property "title" for the button's tooltip (defaults to "Markdown Editing Help").
- // If help isn't given, not help button is created.
- //
- // The constructed editor object has the methods:
- // - getConverter() returns the markdown converter object that was passed to the constructor
- // - run() actually starts the editor; should be called after all necessary plugins are registered. Calling this more than once is a no-op.
- // - refreshPreview() forces the preview to be updated. This method is only available after run() was called.
- Markdown.Editor = function (markdownConverter, idPostfix, help) {
-
- idPostfix = idPostfix || "";
-
- var hooks = this.hooks = new Markdown.HookCollection();
- hooks.addNoop("onPreviewRefresh"); // called with no arguments after the preview has been refreshed
- hooks.addNoop("postBlockquoteCreation"); // called with the user's selection *after* the blockquote was created; should return the actual to-be-inserted text
- hooks.addFalse("insertImageDialog");
- /* called with one parameter: a callback to be called with the URL of the image. If the application creates
- * its own image insertion dialog, this hook should return true, and the callback should be called with the chosen
- * image url (or null if the user cancelled). If this hook returns false, the default dialog will be used.
- */
-
- this.getConverter = function () {
- return markdownConverter;
- }
-
- var that = this,
- cards;
-
- this.run = function () {
- if (cards)
- return; // already initialized
-
- cards = new CardCollection(idPostfix);
- var commandManager = new CommandManager(hooks);
- var previewManager = new PreviewManager(markdownConverter, cards, function () {
- hooks.onPreviewRefresh();
- });
- var undoManager, uiManager;
-
- if (!/\?noundo/.test(doc.location.href)) {
- undoManager = new UndoManager(function () {
- previewManager.refresh();
- if (uiManager) // not available on the first call
- uiManager.setUndoRedoButtonStates();
- }, cards);
- this.textOperation = function (f) {
- undoManager.setCommandMode();
- f();
- that.refreshPreview();
- }
- }
-
- uiManager = new UIManager(idPostfix, cards, undoManager, previewManager, commandManager, help);
- uiManager.setUndoRedoButtonStates();
-
- var forceRefresh = that.refreshPreview = function () {
- previewManager.refresh(true);
- };
-
- forceRefresh();
- };
-
- };
-
- // before: contains all the text in the input box BEFORE the selection.
- // after: contains all the text in the input box AFTER the selection.
- function Chunks() { }
-
- // startRegex: a regular expression to find the start tag
- // endRegex: a regular expresssion to find the end tag
- Chunks.prototype.findTags = function (startRegex, endRegex) {
-
- var chunkObj = this;
- var regex;
-
- if (startRegex) {
-
- regex = util.extendRegExp(startRegex, "", "$");
-
- this.before = this.before.replace(regex,
- function (match) {
- chunkObj.startTag = chunkObj.startTag + match;
- return "";
- });
-
- regex = util.extendRegExp(startRegex, "^", "");
-
- this.selection = this.selection.replace(regex,
- function (match) {
- chunkObj.startTag = chunkObj.startTag + match;
- return "";
- });
- }
-
- if (endRegex) {
-
- regex = util.extendRegExp(endRegex, "", "$");
-
- this.selection = this.selection.replace(regex,
- function (match) {
- chunkObj.endTag = match + chunkObj.endTag;
- return "";
- });
-
- regex = util.extendRegExp(endRegex, "^", "");
-
- this.after = this.after.replace(regex,
- function (match) {
- chunkObj.endTag = match + chunkObj.endTag;
- return "";
- });
- }
- };
-
- // If remove is false, the whitespace is transferred
- // to the before/after regions.
- //
- // If remove is true, the whitespace disappears.
- Chunks.prototype.trimWhitespace = function (remove) {
- var beforeReplacer, afterReplacer, that = this;
- if (remove) {
- beforeReplacer = afterReplacer = "";
- } else {
- beforeReplacer = function (s) {
- that.before += s;
- return "";
- };
- afterReplacer = function (s) { that.after = s + that.after; return ""; }
- }
-
- this.selection = this.selection.replace(/^(\s*)/, beforeReplacer).replace(/(\s*)$/, afterReplacer);
- };
-
-
- Chunks.prototype.skipLines = function (nLinesBefore, nLinesAfter, findExtraNewlines) {
-
- if (nLinesBefore === undefined) {
- nLinesBefore = 1;
- }
-
- if (nLinesAfter === undefined) {
- nLinesAfter = 1;
- }
-
- nLinesBefore++;
- nLinesAfter++;
-
- var regexText;
- var replacementText;
-
- // chrome bug ... documented at: https://meta.stackoverflow.com/questions/63307/blockquote-glitch-in-editor-in-chrome-6-and-7/65985#65985
- if (navigator.userAgent.match(/Chrome/)) {
- "X".match(/()./);
- }
-
- this.selection = this.selection.replace(/(^\n*)/, "");
-
- this.startTag = this.startTag + re.$1;
-
- this.selection = this.selection.replace(/(\n*$)/, "");
- this.endTag = this.endTag + re.$1;
- this.startTag = this.startTag.replace(/(^\n*)/, "");
- this.before = this.before + re.$1;
- this.endTag = this.endTag.replace(/(\n*$)/, "");
- this.after = this.after + re.$1;
-
- if (this.before) {
-
- regexText = replacementText = "";
-
- while (nLinesBefore--) {
- regexText += "\\n?";
- replacementText += "\n";
- }
-
- if (findExtraNewlines) {
- regexText = "\\n*";
- }
- this.before = this.before.replace(new re(regexText + "$", ""), replacementText);
- }
-
- if (this.after) {
-
- regexText = replacementText = "";
-
- while (nLinesAfter--) {
- regexText += "\\n?";
- replacementText += "\n";
- }
- if (findExtraNewlines) {
- regexText = "\\n*";
- }
-
- this.after = this.after.replace(new re(regexText, ""), replacementText);
- }
- };
-
- // end of Chunks
-
- // A collection of the important regions on the page.
- // Cached so we don't have to keep traversing the DOM.
- // Also holds ieCachedRange and ieCachedScrollTop, where necessary; working around
- // this issue:
- // Internet explorer has problems with CSS sprite buttons that use HTML
- // lists. When you click on the background image "button", IE will
- // select the non-existent link text and discard the selection in the
- // textarea. The solution to this is to cache the textarea selection
- // on the button's mousedown event and set a flag. In the part of the
- // code where we need to grab the selection, we check for the flag
- // and, if it's set, use the cached area instead of querying the
- // textarea.
- //
- // This ONLY affects Internet Explorer (tested on versions 6, 7
- // and 8) and ONLY on button clicks. Keyboard shortcuts work
- // normally since the focus never leaves the textarea.
- function CardCollection(postfix) {
- this.buttonBar = doc.getElementById("wmd-button-bar" + postfix);
- this.preview = doc.getElementById("wmd-preview" + postfix);
- this.input = doc.getElementById("wmd-input" + postfix);
- }
- // Returns true if the DOM element is visible, false if it's hidden.
- // Checks if display is anything other than none.
- util.isVisible = function (elem) {
-
- if (window.getComputedStyle) {
- // Most browsers
- return window.getComputedStyle(elem, null).getPropertyValue("display") !== "none";
- }
- else if (elem.currentStyle) {
- // IE
- return elem.currentStyle["display"] !== "none";
- }
- };
-
-
- // Adds a listener callback to a DOM element which is fired on a specified
- // event.
- util.addEvent = function (elem, event, listener) {
- if (elem.attachEvent) {
- // IE only. The "on" is mandatory.
- elem.attachEvent("on" + event, listener);
- }
- else {
- // Other browsers.
- elem.addEventListener(event, listener, false);
- }
- };
-
-
- // Removes a listener callback from a DOM element which is fired on a specified
- // event.
- util.removeEvent = function (elem, event, listener) {
- if (elem.detachEvent) {
- // IE only. The "on" is mandatory.
- elem.detachEvent("on" + event, listener);
- }
- else {
- // Other browsers.
- elem.removeEventListener(event, listener, false);
- }
- };
-
- // Converts \r\n and \r to \n.
- util.fixEolChars = function (text) {
- text = text.replace(/\r\n/g, "\n");
- text = text.replace(/\r/g, "\n");
- return text;
- };
-
- // Extends a regular expression. Returns a new RegExp
- // using pre + regex + post as the expression.
- // Used in a few functions where we have a base
- // expression and we want to pre- or append some
- // conditions to it (e.g. adding "$" to the end).
- // The flags are unchanged.
- //
- // regex is a RegExp, pre and post are strings.
- util.extendRegExp = function (regex, pre, post) {
-
- if (pre === null || pre === undefined) {
- pre = "";
- }
- if (post === null || post === undefined) {
- post = "";
- }
-
- var pattern = regex.toString();
- var flags;
-
- // Replace the flags with empty space and store them.
- pattern = pattern.replace(/\/([gim]*)$/, function (wholeMatch, flagsPart) {
- flags = flagsPart;
- return "";
- });
-
- // Remove the slash delimiters on the regular expression.
- pattern = pattern.replace(/(^\/|\/$)/g, "");
- pattern = pre + pattern + post;
-
- return new re(pattern, flags);
- };
-
- // UNFINISHED
- // The assignment in the while loop makes jslint cranky.
- // I'll change it to a better loop later.
- position.getTop = function (elem, isInner) {
- var result = elem.offsetTop;
- if (!isInner) {
- while (elem = elem.offsetParent) {
- result += elem.offsetTop;
- }
- }
- return result;
- };
-
- position.getHeight = function (elem) {
- return elem.offsetHeight || elem.scrollHeight;
- };
-
- position.getWidth = function (elem) {
- return elem.offsetWidth || elem.scrollWidth;
- };
-
- position.getPageSize = function () {
-
- var scrollWidth, scrollHeight;
- var innerWidth, innerHeight;
-
- // It's not very clear which blocks work with which browsers.
- if (self.innerHeight && self.scrollMaxY) {
- scrollWidth = doc.body.scrollWidth;
- scrollHeight = self.innerHeight + self.scrollMaxY;
- }
- else if (doc.body.scrollHeight > doc.body.offsetHeight) {
- scrollWidth = doc.body.scrollWidth;
- scrollHeight = doc.body.scrollHeight;
- }
- else {
- scrollWidth = doc.body.offsetWidth;
- scrollHeight = doc.body.offsetHeight;
- }
-
- if (self.innerHeight) {
- // Non-IE browser
- innerWidth = self.innerWidth;
- innerHeight = self.innerHeight;
- }
- else if (doc.documentElement && doc.documentElement.clientHeight) {
- // Some versions of IE (IE 6 w/ a DOCTYPE declaration)
- innerWidth = doc.documentElement.clientWidth;
- innerHeight = doc.documentElement.clientHeight;
- }
- else if (doc.body) {
- // Other versions of IE
- innerWidth = doc.body.clientWidth;
- innerHeight = doc.body.clientHeight;
- }
-
- var maxWidth = Math.max(scrollWidth, innerWidth);
- var maxHeight = Math.max(scrollHeight, innerHeight);
- return [maxWidth, maxHeight, innerWidth, innerHeight];
- };
-
- // Handles pushing and popping TextareaStates for undo/redo commands.
- // I should rename the stack variables to list.
- function UndoManager(callback, cards) {
-
- var undoObj = this;
- var undoStack = []; // A stack of undo states
- var stackPtr = 0; // The index of the current state
- var mode = "none";
- var lastState; // The last state
- var timer; // The setTimeout handle for cancelling the timer
- var inputStateObj;
-
- // Set the mode for later logic steps.
- var setMode = function (newMode, noSave) {
- if (mode != newMode) {
- mode = newMode;
- if (!noSave) {
- saveState();
- }
- }
-
- if (!uaSniffed.isIE || mode != "moving") {
- timer = setTimeout(refreshState, 1);
- }
- else {
- inputStateObj = null;
- }
- };
-
- var refreshState = function (isInitialState) {
- inputStateObj = new TextareaState(cards, isInitialState);
- timer = undefined;
- };
-
- this.setCommandMode = function () {
- mode = "command";
- saveState();
- timer = setTimeout(refreshState, 0);
- };
-
- this.canUndo = function () {
- return stackPtr > 1;
- };
-
- this.canRedo = function () {
- if (undoStack[stackPtr + 1]) {
- return true;
- }
- return false;
- };
-
- // Removes the last state and restores it.
- this.undo = function () {
-
- if (undoObj.canUndo()) {
- if (lastState) {
- // What about setting state -1 to null or checking for undefined?
- lastState.restore();
- lastState = null;
- }
- else {
- undoStack[stackPtr] = new TextareaState(cards);
- undoStack[--stackPtr].restore();
-
- if (callback) {
- callback();
- }
- }
- }
-
- mode = "none";
- cards.input.focus();
- refreshState();
- };
-
- // Redo an action.
- this.redo = function () {
-
- if (undoObj.canRedo()) {
-
- undoStack[++stackPtr].restore();
-
- if (callback) {
- callback();
- }
- }
-
- mode = "none";
- cards.input.focus();
- refreshState();
- };
-
- // Push the input area state to the stack.
- var saveState = function () {
- var currState = inputStateObj || new TextareaState(cards);
-
- if (!currState) {
- return false;
- }
- if (mode == "moving") {
- if (!lastState) {
- lastState = currState;
- }
- return;
- }
- if (lastState) {
- if (undoStack[stackPtr - 1].text != lastState.text) {
- undoStack[stackPtr++] = lastState;
- }
- lastState = null;
- }
- undoStack[stackPtr++] = currState;
- undoStack[stackPtr + 1] = null;
- if (callback) {
- callback();
- }
- };
-
- var handleCtrlYZ = function (event) {
-
- var handled = false;
-
- if (event.ctrlKey || event.metaKey) {
-
- // IE and Opera do not support charCode.
- var keyCode = event.charCode || event.keyCode;
- var keyCodeChar = String.fromCharCode(keyCode);
-
- switch (keyCodeChar) {
-
- case "y":
- undoObj.redo();
- handled = true;
- break;
-
- case "z":
- if (!event.shiftKey) {
- undoObj.undo();
- }
- else {
- undoObj.redo();
- }
- handled = true;
- break;
- }
- }
-
- if (handled) {
- if (event.preventDefault) {
- event.preventDefault();
- }
- if (window.event) {
- window.event.returnValue = false;
- }
- }
- };
-
- // Set the mode depending on what is going on in the input area.
- var handleModeChange = function (event) {
-
- if (!event.ctrlKey && !event.metaKey) {
-
- var keyCode = event.keyCode;
-
- if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) {
- // 33 - 40: page up/dn and arrow keys
- // 63232 - 63235: page up/dn and arrow keys on safari
- setMode("moving");
- }
- else if (keyCode == 8 || keyCode == 46 || keyCode == 127) {
- // 8: backspace
- // 46: delete
- // 127: delete
- setMode("deleting");
- }
- else if (keyCode == 13) {
- // 13: Enter
- setMode("newlines");
- }
- else if (keyCode == 27) {
- // 27: escape
- setMode("escape");
- }
- else if ((keyCode < 16 || keyCode > 20) && keyCode != 91) {
- // 16-20 are shift, etc.
- // 91: left window key
- // I think this might be a little messed up since there are
- // a lot of nonprinting keys above 20.
- setMode("typing");
- }
- }
- };
-
- var setEventHandlers = function () {
- util.addEvent(cards.input, "keypress", function (event) {
- // keyCode 89: y
- // keyCode 90: z
- if ((event.ctrlKey || event.metaKey) && (event.keyCode == 89 || event.keyCode == 90)) {
- event.preventDefault();
- }
- });
-
- var handlePaste = function () {
- if (uaSniffed.isIE || (inputStateObj && inputStateObj.text != cards.input.value)) {
- if (timer == undefined) {
- mode = "paste";
- saveState();
- refreshState();
- }
- }
- };
-
- util.addEvent(cards.input, "keydown", handleCtrlYZ);
- util.addEvent(cards.input, "keydown", handleModeChange);
- util.addEvent(cards.input, "mousedown", function () {
- setMode("moving");
- });
-
- cards.input.onpaste = handlePaste;
- cards.input.ondrop = handlePaste;
- };
-
- var init = function () {
- setEventHandlers();
- refreshState(true);
- saveState();
- };
-
- init();
- }
-
- // end of UndoManager
-
- // The input textarea state/contents.
- // This is used to implement undo/redo by the undo manager.
- function TextareaState(cards, isInitialState) {
-
- // Aliases
- var stateObj = this;
- var inputArea = cards.input;
- this.init = function () {
- if (!util.isVisible(inputArea)) {
- return;
- }
- if (!isInitialState && doc.activeElement && doc.activeElement !== inputArea) { // this happens when tabbing out of the input box
- return;
- }
-
- this.setInputAreaSelectionStartEnd();
- this.scrollTop = inputArea.scrollTop;
- if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) {
- this.text = inputArea.value;
- }
-
- };
-
- // Sets the selected text in the input box after we've performed an
- // operation.
- this.setInputAreaSelection = function () {
-
- if (!util.isVisible(inputArea)) {
- return;
- }
-
- if (inputArea.selectionStart !== undefined && !uaSniffed.isOpera) {
-
- inputArea.focus();
- inputArea.selectionStart = stateObj.start;
- inputArea.selectionEnd = stateObj.end;
- inputArea.scrollTop = stateObj.scrollTop;
- }
- else if (doc.selection) {
-
- if (doc.activeElement && doc.activeElement !== inputArea) {
- return;
- }
-
- inputArea.focus();
- var range = inputArea.createTextRange();
- range.moveStart("character", -inputArea.value.length);
- range.moveEnd("character", -inputArea.value.length);
- range.moveEnd("character", stateObj.end);
- range.moveStart("character", stateObj.start);
- range.select();
- }
- };
-
- this.setInputAreaSelectionStartEnd = function () {
-
- if (!cards.ieCachedRange && (inputArea.selectionStart || inputArea.selectionStart === 0)) {
-
- stateObj.start = inputArea.selectionStart;
- stateObj.end = inputArea.selectionEnd;
- }
- else if (doc.selection) {
-
- stateObj.text = util.fixEolChars(inputArea.value);
-
- // IE loses the selection in the textarea when buttons are
- // clicked. On IE we cache the selection. Here, if something is cached,
- // we take it.
- var range = cards.ieCachedRange || doc.selection.createRange();
-
- var fixedRange = util.fixEolChars(range.text);
- var marker = "\x07";
- var markedRange = marker + fixedRange + marker;
- range.text = markedRange;
- var inputText = util.fixEolChars(inputArea.value);
-
- range.moveStart("character", -markedRange.length);
- range.text = fixedRange;
-
- stateObj.start = inputText.indexOf(marker);
- stateObj.end = inputText.lastIndexOf(marker) - marker.length;
-
- var len = stateObj.text.length - util.fixEolChars(inputArea.value).length;
-
- if (len) {
- range.moveStart("character", -fixedRange.length);
- while (len--) {
- fixedRange += "\n";
- stateObj.end += 1;
- }
- range.text = fixedRange;
- }
-
- if (cards.ieCachedRange)
- stateObj.scrollTop = cards.ieCachedScrollTop; // this is set alongside with ieCachedRange
-
- cards.ieCachedRange = null;
-
- this.setInputAreaSelection();
- }
- };
-
- // Restore this state into the input area.
- this.restore = function () {
-
- if (stateObj.text != undefined && stateObj.text != inputArea.value) {
- inputArea.value = stateObj.text;
- }
- this.setInputAreaSelection();
- inputArea.scrollTop = stateObj.scrollTop;
- };
-
- // Gets a collection of HTML chunks from the inptut textarea.
- this.getChunks = function () {
-
- var chunk = new Chunks();
- chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start));
- chunk.startTag = "";
- chunk.selection = util.fixEolChars(stateObj.text.substring(stateObj.start, stateObj.end));
- chunk.endTag = "";
- chunk.after = util.fixEolChars(stateObj.text.substring(stateObj.end));
- chunk.scrollTop = stateObj.scrollTop;
-
- return chunk;
- };
-
- // Sets the TextareaState properties given a chunk of markdown.
- this.setChunks = function (chunk) {
-
- chunk.before = chunk.before + chunk.startTag;
- chunk.after = chunk.endTag + chunk.after;
-
- this.start = chunk.before.length;
- this.end = chunk.before.length + chunk.selection.length;
- this.text = chunk.before + chunk.selection + chunk.after;
- this.scrollTop = chunk.scrollTop;
- };
- this.init();
- }
- function PreviewManager(converter, cards, previewRefreshCallback) {
-
- var managerObj = this;
- var timeout;
- var elapsedTime;
- var oldInputText;
- var maxDelay = 3000;
- var startType = "delayed"; // The other legal value is "manual"
-
- // Adds event listeners to elements
- var setupEvents = function (inputElem, listener) {
-
- util.addEvent(inputElem, "input", listener);
- inputElem.onpaste = listener;
- inputElem.ondrop = listener;
-
- util.addEvent(inputElem, "keypress", listener);
- util.addEvent(inputElem, "keydown", listener);
- };
-
- var getDocScrollTop = function () {
-
- var result = 0;
-
- if (window.innerHeight) {
- result = window.pageYOffset;
- }
- else
- if (doc.documentElement && doc.documentElement.scrollTop) {
- result = doc.documentElement.scrollTop;
- }
- else
- if (doc.body) {
- result = doc.body.scrollTop;
- }
-
- return result;
- };
-
- var makePreviewHtml = function () {
-
- // If there is no registered preview card
- // there is nothing to do.
- if (!cards.preview)
- return;
-
-
- var text = cards.input.value;
- if (text && text == oldInputText) {
- return; // Input text hasn't changed.
- }
- else {
- oldInputText = text;
- }
-
- var prevTime = new Date().getTime();
-
- text = converter.makeHtml(text).replaceAll(/“|”/g, '"');
-
- // Calculate the processing time of the HTML creation.
- // It's used as the delay time in the event listener.
- var currTime = new Date().getTime();
- elapsedTime = currTime - prevTime;
-
- pushPreviewHtml(text);
- };
-
- // setTimeout is already used. Used as an event listener.
- var applyTimeout = function () {
-
- if (timeout) {
- clearTimeout(timeout);
- timeout = undefined;
- }
-
- if (startType !== "manual") {
-
- var delay = 0;
-
- if (startType === "delayed") {
- delay = elapsedTime;
- }
-
- if (delay > maxDelay) {
- delay = maxDelay;
- }
- timeout = setTimeout(makePreviewHtml, delay);
- }
- };
-
- var getScaleFactor = function (card) {
- if (card.scrollHeight <= card.clientHeight) {
- return 1;
- }
- return card.scrollTop / (card.scrollHeight - card.clientHeight);
- };
-
- var setCardScrollTops = function () {
- if (cards.preview) {
- cards.preview.scrollTop = (cards.preview.scrollHeight - cards.preview.clientHeight) * getScaleFactor(cards.preview);
- }
- };
-
- this.refresh = function (requiresRefresh) {
-
- if (requiresRefresh) {
- oldInputText = "";
- makePreviewHtml();
- }
- else {
- applyTimeout();
- }
- };
-
- this.processingTime = function () {
- return elapsedTime;
- };
-
- var isFirstTimeFilled = true;
-
- // IE doesn't let you use innerHTML if the element is contained somewhere in a table
- // (which is the case for inline editing) -- in that case, detach the element, set the
- // value, and reattach. Yes, that *is* ridiculous.
- var ieSafePreviewSet = function (text) {
- var preview = cards.preview;
- var parent = preview.parentNode;
- var sibling = preview.nextSibling;
- parent.removeChild(preview);
- preview.innerHTML = text;
- if (!sibling)
- parent.appendChild(preview);
- else
- parent.insertBefore(preview, sibling);
- };
-
- var nonSuckyBrowserPreviewSet = function (text) {
- cards.preview.innerHTML = text;
- };
-
- var previewSetter;
-
- var previewSet = function (text) {
- if (previewSetter)
- return previewSetter(text);
-
- try {
- nonSuckyBrowserPreviewSet(text);
- previewSetter = nonSuckyBrowserPreviewSet;
- } catch (e) {
- previewSetter = ieSafePreviewSet;
- previewSetter(text);
- }
- };
-
- var pushPreviewHtml = function (text) {
-
- var emptyTop = position.getTop(cards.input) - getDocScrollTop();
-
- if (cards.preview) {
- previewSet(text);
- previewRefreshCallback();
- }
-
- setCardScrollTops();
-
- if (isFirstTimeFilled) {
- isFirstTimeFilled = false;
- return;
- }
-
- var fullTop = position.getTop(cards.input) - getDocScrollTop();
-
- if (uaSniffed.isIE) {
- setTimeout(function () {
- window.scrollBy(0, fullTop - emptyTop);
- }, 0);
- }
- else {
- window.scrollBy(0, fullTop - emptyTop);
- }
- };
-
- var init = function () {
-
- setupEvents(cards.input, applyTimeout);
- makePreviewHtml();
-
- if (cards.preview) {
- cards.preview.scrollTop = 0;
- }
- };
-
- init();
- }
- // This simulates a modal dialog box and asks for the URL when you
- // click the hyperlink or image buttons.
- //
- // text: The html for the input box.
- // defaultInputText: The default value that appears in the input box.
- // callback: The function which is executed when the prompt is dismissed, either via OK or Cancel.
- // It receives a single argument; either the entered text (if OK was chosen) or null (if Cancel
- // was chosen).
- ui.prompt = function (title, inputLabel, inputPlaceholder, inputHelp, callback) {
-
- // These variables need to be declared at this level since they are used
- // in multiple functions.
- var dialog; // The dialog box.
- var input; // The text box where you enter the hyperlink.
-
-
- if (inputPlaceholder === undefined) {
- inputPlaceholder = "";
- }
-
- // Used as a keydown event handler. Esc dismisses the prompt.
- // Key code 27 is ESC.
- var checkEscape = function (key) {
- var code = (key.charCode || key.keyCode);
- if (code === 27) {
- close(true);
- }
- };
-
- // Dismisses the hyperlink input box.
- // isCancel is true if we don't care about the input text.
- // isCancel is false if we are going to keep the text.
- var close = function (isCancel) {
- util.removeEvent(doc.body, "keydown", checkEscape);
- var text = input.value;
-
- if (isCancel) {
- text = null;
- }
- else {
- // Fixes common pasting errors.
- text = text.replace(/^http:\/\/(https?|ftp):\/\//, '$1://');
- if (!/^(?:https?|ftp):\/\//.test(text))
- text = 'http://' + text;
- }
-
- bootstrap.Modal.getInstance($(dialog)).hide();
-
- callback(text);
- return false;
- };
-
-
-
- // Create the text input box form/window.
- var createDialog = function () {
- //