' +
- '
' +
- '
- ' +
- '
' +
- '- ' +
- '
' +
- '
' // whew, yuck!?
- ),
- selectedText = me.getSelectedText(),
- kbox;
-
- $html.find('li input[type="text"]').on('focus', function() {
- $(this).closest('li').find('input[type="radio"]').trigger("click");
+ '
' // whew, yuck!?
+ );
+
+ const $linkText = $html.find('input[name="link-text"]');
+ const $internal = $html.find('input[name="internal"]');
+ const $external = $html.find('input[name="external"]');
+ const $submitButton = $html.find('button[type="submit"]');
+
+ $html.find('li input[type="text"]').on('focus', function () {
+ $(this).closest('li').find('input[type="radio"]').trigger('click');
});
+ // Make the text input of the selected link-type radio required.
+ function updateRequiredTarget() {
+ const val = $html.find('input[name="link-type"]:checked').val();
+
+ $internal.prop('required', val === 'internal');
+ $external.prop('required', val === 'external');
+ }
+
+ $html.find('input[name="link-type"]').prop('required', true);
+ $html.find('input[name="link-type"]').on('change', updateRequiredTarget);
+
+ // Disable the Submit button while the form is invalid.
+ function updateSubmitButton() {
+ $submitButton.prop('disabled', !$html[0].checkValidity());
+ }
+
+ $html.find('li input[type="text"]').on('change', updateSubmitButton);
+ $html.find('input[name="link-type"]').on('change', updateSubmitButton);
+
// Perform a query for the sections of an article if
// last character is a pound:
- var performSectionSearch = function(request) {
- return (request.term.indexOf('#') === request.term.length - 1);
- };
+ function performSectionSearch(request) {
+ return request.term.endsWith('#');
+ }
- var results = [];
+ let results = [];
// Get the article URL by providing the article name:
- var getArticleURL = function(name) {
- for (var i = 0; i < results.length; i++) {
+ function getArticleURL(name) {
+ for (let i = 0; i < results.length; i++) {
if (name === results[i].label) {
return results[i].url;
}
}
return null;
- };
+ }
- var articleSearch = function(request, response) {
+ function articleSearch(request, response) {
results = [];
$.ajax({
url: '/en-US/search',
@@ -356,22 +436,22 @@ Marky.LinkButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
q: request.term,
a: 1,
w: 1,
- language: $('html').attr('lang')
+ language: $('html').attr('lang'),
},
dataType: 'json',
- success: function(data, textStatus) {
- $.map(data.results, function(val, i) {
+ success: function (data, textStatus) {
+ $.map(data.results, function (val, i) {
results.push({
label: val.title,
- url: val.url
+ url: val.url,
});
});
response(results);
- }
+ },
});
- };
+ }
- var sectionSearch = function(request, response) {
+ function sectionSearch(request, response) {
var articleName = request.term.split('#')[0];
var articleURL = getArticleURL(articleName);
@@ -382,107 +462,79 @@ Marky.LinkButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
$.ajax({
url: articleURL,
dataType: 'text',
- success: function(data, status) {
- var headings = $("[id^='w_']", data);
- var array = [];
+ success: function (data, status) {
+ const headings = $("[id^='w_']", data);
+ const array = [];
if (headings.length === 0) {
array.push({
label: gettext('No sections found'),
value: request.term.replace('#', ''),
- target: ''
+ target: '',
});
}
- headings.each(function() {
- var element = this.nodeName;
- var level = element.substring(1);
- var label = $(this).text();
- var target = $(this).attr('id');
- var value = request.term + target;
+ headings.each(function () {
+ const label = $(this).text();
+ const target = $(this).attr('id');
+ const value = request.term + target;
array.push({
label: label,
value: value,
- target: target
+ target: target,
});
});
response(array);
- }
+ },
});
- };
+ }
- $html.find('input[name="internal"]').autocomplete({
- source: function(request, response) {
+ $internal.autocomplete({
+ source: function (request, response) {
if (performSectionSearch(request)) {
sectionSearch(request, response);
} else {
articleSearch(request, response);
}
},
- select: function(event, ui) {
+ select: function (event, ui) {
if (!ui.item.target) {
return;
}
- var $linktext = $html.find('input[name=link-text]');
- if ($linktext.val() === '') {
- $linktext.val(ui.item.label);
+ if ($linkText.val() === '') {
+ $linkText.val(ui.item.label);
}
- }
+ },
});
- $html.find('button').text(gettext('Insert Link')).on("click", function(e) {
+ $html.on('submit', function (e) {
// Generate the wiki markup based on what the user has selected
// (interval vs external links) and entered into the textboxes,
// if anything.
- var val = $html.find('input[type="radio"]:checked').val(),
- text = $html.find('input[name=link-text]').val(),
- $internal = $html.find('input[name="internal"]'),
- $external = $html.find('input[name="external"]');
+ e.preventDefault();
+
+ const val = $html.find('input[type="radio"]:checked').val(),
+ text = $html.find('input[name=link-text]').val();
+
me.reset();
if (val === 'internal') {
- var title = $internal.val();
- if (title) {
- if (title === selectedText) {
- // The title wasn't changed, so lets keep it selected.
- me.openTag = '[[';
- me.closeTag = ']]';
- if (text) {
- me.closeTag = '|' + text + me.closeTag;
- }
- } else {
- // The title changed, so lets insert link before the cursor.
- me.openTag = '[[' + title;
- if (text) {
- me.openTag += '|' + text;
- }
- me.openTag += ']] ';
- me.closeTag = '';
- me.defaultText = '';
- }
+ const title = $internal.val() || gettext('Knowledge Base Article');
+ if (!text || title === text) {
+ me.markup = '[[' + title + ']]';
} else {
- me.openTag = '[[';
- me.closeTag = ']]';
- if (text) {
- me.closeTag = '|' + text + ']]';
- }
- me.defaultText = gettext('Knowledge Base Article');
+ me.markup = '[[' + title + '|' + text + ']]';
}
} else {
- var link = $external.val();
- if (link) {
- if (link.indexOf('http') !== 0) {
- link = 'http://' + link;
- }
- me.openTag = '[' + link + ' ';
- if (text) {
- me.openTag += text + '] ';
- me.closeTag = '';
- me.defaultText = '';
- }
- } else if (text) {
- me.defaultText = text;
+ let link = $external.val() || 'https://example.com';
+ if (link.indexOf('http') !== 0) {
+ link = 'http://' + link;
+ }
+ if (!text) {
+ me.markup = '[' + link + ']';
+ } else {
+ me.markup = '[' + link + ' ' + text + ']';
}
}
@@ -490,57 +542,42 @@ Marky.LinkButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
kbox.close();
});
+ const selectedText = me.getSelectedText();
if (selectedText) {
- // If there user has selected text, lets default to it being
- // the Article Title.
- $html.find('input[name="internal"]').val(selectedText).trigger("focus");
+ // If there is selected text, make it the link text.
+ $linkText.val(selectedText);
}
- kbox = new KBox($html, {
+ const kbox = new KBox($html, {
title: this.name,
destroy: true,
modal: true,
id: 'link-modal',
container: $('body'),
- position: 'none'
+ position: 'none',
});
kbox.open();
+ updateRequiredTarget();
+ updateSubmitButton();
+
+ // Focus the link text field to remove focus from the editor tools button.
+ $linkText.trigger('focus');
+
ev.preventDefault();
return false;
}
-});
-
-/*
- * The media helper.
- */
-Marky.MediaButton = function() {
- this.name = gettext('Insert media...');
- this.classes = 'btn-media';
- this.openTag = '';
- this.closeTag = '';
- this.defaultText = gettext('media');
- this.everyline = false;
-
- this.html = '
';
-};
+}
+
+/**
+ * The media helper.
+ */
+class MediaButton extends InsertButton {
+ constructor() {
+ super(gettext('Insert media...'), '', 'btn-media');
+ }
-Marky.MediaButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
- // Gets the DOM node for the button.
- node: function() {
- var me = this,
- $btn = this.render();
- $btn.on("click", function(e) {
- me.openModal(e);
- });
- return $btn[0];
- },
- reset: function() {
- this.openTag = '';
- this.closeTag = '';
- this.defaultText = '';
- },
- openModal: function(ev) {
+ openModal(ev) {
var me = this,
$editor = $(me.textarea).closest('.editor'),
mediaSearchUrl = $editor.data('media-search-url'),
@@ -615,8 +652,7 @@ Marky.MediaButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
return false;
}
- me.openTag = '[[Image';
- me.openTag += ':' + $selected.find('a').attr('title') + ']] ';
+ me.markup = '[[Image:' + $selected.find('a').attr('title') + ']]';
me.handleClick(e);
kbox.close();
@@ -668,41 +704,70 @@ Marky.MediaButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
ev.preventDefault();
return false;
}
-});
+}
-/*
- * The canned responses helper
- */
-Marky.CannedResponsesButton = function() {
- this.name = gettext('Common responses');
- this.classes = 'btn-cannedresponses';
- this.openTag = '';
- this.closeTag = '';
- this.defaultText = 'cannedresponses';
- this.everyline = false;
-
- this.html = '
';
-};
+/**
+ * The canned responses helper
+ */
+class CannedResponsesButton extends InsertButton {
+ permissionBits = [];
-Marky.CannedResponsesButton.prototype = $.extend({}, Marky.SimpleButton.prototype, {
- // Gets the DOM node for the button.
- node: function() {
- var me = this,
+ constructor() {
+ super(gettext('Common responses'), '', 'btn-cannedresponses');
+
+ this.html = '
';
+ }
+
+ /**
+ * Gets the DOM node for the button.
+ */
+ node() {
+ const me = this,
$btn = this.render();
- $btn.on("click", function(e) {
+ $btn.on('click', function(e) {
me.openModal(e);
});
me.getPermissionBits();
return $btn[0];
- },
- reset: function() {
- this.openTag = '';
- this.closeTag = '';
- this.defaultText = '';
- },
- openModal: function(e) {
+ }
+
+ getPermissionBits() {
+ var profile_link = $('#aux-nav .user').attr('href'),
+ me = this;
+ if (!profile_link || profile_link === '') {
+ return;
+ }
+
+ $.ajax({
+ url: profile_link,
+ dataType: 'html',
+ success: function(data, status) {
+ var userGroups = $('#groups li', data);
+ userGroups.each(function() {
+ var group = $(this).text();
+
+ // Contributors:
+ if (group === 'Contributors') {
+ me.permissionBits.push('c');
+ }
+
+ // Moderators:
+ if (group === 'Forum Moderators') {
+ me.permissionBits.push('m');
+ }
+
+ // Administrators:
+ if (group === 'Administrators') {
+ me.permissionBits.push('a');
+ }
+ });
+ }
+ });
+ }
+
+ openModal(e) {
var me = this,
$editor = $(me.textarea).closest('.editor'),
// TODO: look at using a js template solution (jquery-tmpl?)
@@ -826,14 +891,11 @@ Marky.CannedResponsesButton.prototype = $.extend({}, Marky.SimpleButton.prototyp
}
function insertResponse() {
- var sourceContent = $('#response-content').val();
var slug = $('#response-content').data('slug');
- var $responseTextbox = $('#id_content');
- var targetContent = $responseTextbox.val();
-
trackEvent('common_forum_response_insert', {slug});
- $responseTextbox.val(targetContent + sourceContent);
+ me.markup = $('#response-content').val();
+ me.handleClick(e);
}
function searchResponses(term) {
@@ -986,60 +1048,34 @@ Marky.CannedResponsesButton.prototype = $.extend({}, Marky.SimpleButton.prototyp
e.preventDefault();
return false;
- },
-
- permissionBits: [],
-
- getPermissionBits: function() {
- var profile_link = $('#aux-nav .user').attr('href'),
- me = this;
- if (!profile_link || profile_link === '') {
- return;
- }
-
- $.ajax({
- url: profile_link,
- dataType: 'html',
- success: function(data, status) {
- var userGroups = $('#groups li', data);
- userGroups.each(function() {
- var group = $(this).text();
-
- // Contributors:
- if (group === 'Contributors') {
- me.permissionBits.push('c');
- }
-
- // Moderators:
- if (group === 'Forum Moderators') {
- me.permissionBits.push('m');
- }
-
- // Administrators:
- if (group === 'Administrators') {
- me.permissionBits.push('a');
- }
- });
- }
- });
}
-});
-
-/*
- * The quote button helper
- */
-Marky.QuoteButton = function() {
- var name = gettext('Quote previous message...');
- var previousContent = $('#read-message').attr('data-message-content');
- var previousAuthor = $('.from a').text();
- var previousAuthorLink = $('.from a').attr('href');
- var quote = '[' + previousAuthorLink + ' ' + previousAuthor + '] ' +
- gettext('said') + '\r\n';
- quote += '
\r\n';
- quote += previousContent + '\r\n';
- quote += '
\r\n';
-
- return new Marky.SimpleButton(name, quote, '', '', 'btn-quote', true);
-};
+}
+
+/**
+ * The quote button helper (for private messages)
+ */
+class QuoteButton extends InsertButton {
+ constructor() {
+ var previousContent = $('#read-message').attr('data-message-content');
+ var previousAuthor = $('.from a').text();
+ var previousAuthorLink = $('.from a').attr('href');
+ var quote = '[' + previousAuthorLink + ' ' + previousAuthor + '] ' +
+ gettext('said') + '\r\n';
+ quote += '
\r\n';
+ quote += previousContent + '\r\n';
+ quote += '
\r\n';
+
+ super(gettext('Quote previous message...'), quote, 'btn-quote');
+ }
+}
+
+Marky.SimpleButton = SimpleButton;
+Marky.MarkupButton = MarkupButton;
+Marky.InsertButton = InsertButton;
+Marky.Separator = Separator;
+Marky.LinkButton = LinkButton;
+Marky.MediaButton = MediaButton;
+Marky.CannedResponsesButton = CannedResponsesButton;
+Marky.QuoteButton = QuoteButton;
export default Marky;