Skip to content

Commit 3a78afe

Browse files
committed
Update quick modify to support Ctrl+Enter
Signed-off-by: John Rayes <[email protected]>
1 parent 1737bf4 commit 3a78afe

File tree

2 files changed

+151
-126
lines changed

2 files changed

+151
-126
lines changed

Themes/default/css/index.css

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,9 +1062,17 @@ a[class^="mobile_generic_menu_"] {
10621062

10631063
/* Styles for the standard button lists.
10641064
------------------------------------------------------- */
1065-
.buttonlist, .buttonrow, .pagelinks {
1066-
z-index: 100;
1067-
padding: 5px 0 5px 0;
1065+
.buttonlist, .buttonlistend, .buttonrow, .pagelinks, .pagesection {
1066+
align-items: baseline;
1067+
display: flex;
1068+
gap: .5em;
1069+
}
1070+
/* Items in mobile menu must be vertical. */
1071+
.popup_window .buttonlist {
1072+
flex-direction: column;
1073+
}
1074+
.buttonlistend {
1075+
justify-content: end;
10681076
}
10691077
.button, .quickbuttons > li > a, .inline_mod_check {
10701078
display: inline-block;
@@ -1495,11 +1503,6 @@ ul li.greeting {
14951503
width: 29ch;
14961504
}
14971505

1498-
.quickModifyMargin {
1499-
margin: 10px 0 5px 0;
1500-
padding-bottom: 5px;
1501-
}
1502-
15031506
/* Styles for edit event section
15041507
---------------------------------------------------- */
15051508
#post_event .roundframe {

Themes/default/scripts/topic.js

Lines changed: 140 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,10 @@ QuickReply.prototype.onQuoteReceived = function (oXMLDoc)
256256
for (var i = 0; i < oXMLDoc.getElementsByTagName('quote')[0].childNodes.length; i++)
257257
sQuoteText += oXMLDoc.getElementsByTagName('quote')[0].childNodes[i].nodeValue;
258258

259-
replaceText(sQuoteText, document.forms.postmodify.message);
259+
if (typeof sceditor !== 'undefined')
260+
sceditor.instance(document.forms.postmodify.message).insertText(sQuoteText);
261+
else
262+
replaceText(sQuoteText, document.forms.postmodify.message);
260263

261264
ajax_indicator(false);
262265
}
@@ -278,35 +281,16 @@ function QuickModify(oOptions)
278281
this.sCurMessageId = '';
279282
this.oCurMessageDiv = null;
280283
this.oCurSubjectDiv = null;
281-
this.sMessageBuffer = '';
282-
this.sSubjectBuffer = '';
283-
this.aAccessKeys = new Array();
284+
285+
for (const el of document.getElementsByClassName(this.opt.sClassName)) {
286+
el.hidden = false;
287+
el.addEventListener('click', this.modifyMsg.bind(this, el.id.match(/\d+/)));
288+
}
284289
}
285290

286291
// Function called when a user presses the edit button.
287292
QuickModify.prototype.modifyMsg = function (iMessageId)
288293
{
289-
// Add backwards compatibility with old themes.
290-
if (typeof(sSessionVar) == 'undefined')
291-
sSessionVar = 'sesc';
292-
293-
// Removes the accesskeys from the quickreply inputs and saves them in an array to use them later
294-
if (typeof(this.opt.sFormRemoveAccessKeys) != 'undefined')
295-
{
296-
if (typeof(document.forms[this.opt.sFormRemoveAccessKeys]))
297-
{
298-
var aInputs = document.forms[this.opt.sFormRemoveAccessKeys].getElementsByTagName('input');
299-
for (var i = 0; i < aInputs.length; i++)
300-
{
301-
if (aInputs[i].accessKey != '')
302-
{
303-
this.aAccessKeys[aInputs[i].name] = aInputs[i].accessKey;
304-
aInputs[i].accessKey = '';
305-
}
306-
}
307-
}
308-
}
309-
310294
// First cancel if there's another message still being edited.
311295
if (this.bInEditMode)
312296
this.modifyCancel();
@@ -316,7 +300,7 @@ QuickModify.prototype.modifyMsg = function (iMessageId)
316300

317301
// Send out the XMLhttp request to get more info
318302
ajax_indicator(true);
319-
sendXMLDocument.call(this, smf_prepareScriptUrl(smf_scripturl) + 'action=quotefast;quote=' + iMessageId + ';modify;xml;' + smf_session_var + '=' + smf_session_id, '', this.onMessageReceived);
303+
getXMLDocument.call(this, smf_prepareScriptUrl(smf_scripturl) + 'action=quotefast;quote=' + iMessageId + ';modify;xml;' + smf_session_var + '=' + smf_session_id, this.onMessageReceived);
320304

321305
// Jump to the message
322306
document.getElementById('msg' + iMessageId).scrollIntoView();
@@ -338,105 +322,125 @@ QuickModify.prototype.onMessageReceived = function (XMLDoc)
338322
return this.modifyCancel();
339323

340324
// Replace the body part.
341-
for (var i = 0; i < XMLDoc.getElementsByTagName("message")[0].childNodes.length; i++)
325+
for (let i = 0; i < XMLDoc.getElementsByTagName("message")[0].childNodes.length; i++)
342326
sBodyText += XMLDoc.getElementsByTagName("message")[0].childNodes[i].nodeValue;
343-
this.oCurMessageDiv = document.getElementById(this.sCurMessageId);
344-
this.sMessageBuffer = getInnerHTML(this.oCurMessageDiv);
345-
346-
// We have to force the body to lose its dollar signs thanks to IE.
347-
sBodyText = sBodyText.replace(/\$/g, '{&dollarfix;$}');
348-
349-
// Actually create the content, with a bodge for disappearing dollar signs.
350-
setInnerHTML(this.oCurMessageDiv, this.opt.sTemplateBodyEdit.replace(/%msg_id%/g, this.sCurMessageId.substr(4)).replace(/%body%/, sBodyText).replace(/\{&dollarfix;\$\}/g, '$'));
351-
352-
// Replace the subject part.
353-
this.oCurSubjectDiv = document.getElementById('subject_' + this.sCurMessageId.substr(4));
354-
this.sSubjectBuffer = getInnerHTML(this.oCurSubjectDiv);
355-
356-
sSubjectText = XMLDoc.getElementsByTagName('subject')[0].childNodes[0].nodeValue.replace(/\$/g, '{&dollarfix;$}');
357-
setInnerHTML(this.oCurSubjectDiv, this.opt.sTemplateSubjectEdit.replace(/%subject%/, sSubjectText).replace(/\{&dollarfix;\$\}/g, '$'));
358-
359-
// Field for editing reason.
360-
sReasonText = XMLDoc.getElementsByTagName('reason')[0].childNodes[0].nodeValue.replace(/\$/g, '{&dollarfix;$}');
361327

362-
$(this.oCurMessageDiv).prepend(this.opt.sTemplateReasonEdit.replace(/%modify_reason%/, sReasonText).replace(/\{&dollarfix;\$\}/g, '$'));
328+
this.oCurMessageDiv = document.getElementById(this.sCurMessageId);
329+
this.oCurSubjectDiv = document.getElementById('subject_' + this.sCurMessageId.substring(4));
330+
if (this.oCurSubjectDiv !== null)
331+
this.oCurSubjectDiv.hidden = true;
332+
this.oCurMessageDiv.hidden = true;
333+
334+
// Actually create the content.
335+
const form = document.createElement("form");
336+
form.id = "quickModifyForm";
337+
338+
var messageInput = document.createElement("textarea");
339+
messageInput.name = "message";
340+
messageInput.cols = "80";
341+
messageInput.rows = "10";
342+
messageInput.innerHTML = sBodyText;
343+
messageInput.addEventListener('keydown', function(e) {
344+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
345+
this.modifySave();
346+
}
347+
if (e.key === "Escape") {
348+
this.modifyCancel();
349+
}
350+
}.bind(this));
351+
352+
var subjectInput = document.createElement("input");
353+
subjectInput.name = "subject";
354+
subjectInput.maxLength = "80";
355+
subjectInput.size = "80";
356+
subjectInput.value = XMLDoc.getElementsByTagName('subject')[0].childNodes[0].nodeValue;
357+
358+
const reasonLabel = document.createElement("label");
359+
const reasonInput = document.createElement("input");
360+
reasonInput.name = "modify_reason";
361+
reasonInput.maxLength = "80";
362+
reasonInput.size = "80";
363+
reasonInput.value = XMLDoc.getElementsByTagName('reason')[0].childNodes[0].nodeValue;
364+
365+
const buttonGroup = document.createElement("div");
366+
buttonGroup.className = 'buttonlistend';
367+
368+
const cancelButton = document.createElement("button");
369+
cancelButton.className = 'button';
370+
cancelButton.textContent = this.opt.sCancelButtonText;
371+
cancelButton.addEventListener('click', this.modifyCancel.bind(this));
372+
373+
const saveButton = document.createElement("button");
374+
saveButton.className = 'button active';
375+
saveButton.textContent = this.opt.sSaveButtonText;
376+
saveButton.addEventListener('click', this.modifySave.bind(this));
377+
378+
reasonLabel.append(this.opt.sTemplateReasonEdit, reasonInput);
379+
buttonGroup.append(saveButton, cancelButton);
380+
form.append(subjectInput, messageInput, reasonLabel, buttonGroup);
381+
this.oCurMessageDiv.after(form);
382+
messageInput.focus();
383+
384+
//~ if (typeof sceditor !== 'undefined' && 'sceOptions' in window) {
385+
//~ var options = this.opt.sceOptions;
386+
//~ options.toolbarContainer = document.createElement("div");
387+
//~ options.smileyContainer = document.createElement("div");
388+
//~ options.toolbarContainer.id = "bbcBox_message";
389+
//~ document.forms.quickModifyForm.message.before(options.toolbarContainer, options.smileyContainer, document.forms.quickModifyForm.message);
390+
//~ sceditor.create(document.forms.quickModifyForm.message, options);
391+
//~ }
392+
393+
if (this.opt.funcOnAfterCreate) {
394+
this.opt.funcOnAfterCreate.call(this, form);
395+
}
363396

364397
return true;
365398
}
366399

367400
// Function in case the user presses cancel (or other circumstances cause it).
368401
QuickModify.prototype.modifyCancel = function ()
369402
{
370-
// Roll back the HTML to its original state.
371403
if (this.oCurMessageDiv)
372404
{
373-
this.oCurMessageDiv.innerHTML = this.sMessageBuffer;
374-
this.oCurSubjectDiv.innerHTML = this.sSubjectBuffer;
405+
this.oCurMessageDiv.hidden = false;
406+
if (this.oCurSubjectDiv !== null)
407+
this.oCurSubjectDiv.hidden = false;
408+
document.forms.quickModifyForm.remove();
375409
}
376410

377411
// No longer in edit mode, that's right.
378412
this.bInEditMode = false;
379413

380-
// Let's put back the accesskeys to their original place
381-
if (typeof(this.opt.sFormRemoveAccessKeys) != 'undefined')
382-
{
383-
if (typeof(document.forms[this.opt.sFormRemoveAccessKeys]))
384-
{
385-
var aInputs = document.forms[this.opt.sFormRemoveAccessKeys].getElementsByTagName('input');
386-
for (var i = 0; i < aInputs.length; i++)
387-
{
388-
if (typeof(this.aAccessKeys[aInputs[i].name]) != 'undefined')
389-
{
390-
aInputs[i].accessKey = this.aAccessKeys[aInputs[i].name];
391-
}
392-
}
393-
}
394-
}
395-
396414
return false;
397415
}
398416

399417
// The function called after a user wants to save his precious message.
400-
QuickModify.prototype.modifySave = function (sSessionId, sSessionVar)
418+
QuickModify.prototype.modifySave = function (e)
401419
{
420+
e && e.preventDefault && e.preventDefault();
421+
402422
// We cannot save if we weren't in edit mode.
403-
if (!this.bInEditMode)
423+
if (!this.bInEditMode) {
404424
return true;
425+
}
405426

406-
// Add backwards compatibility with old themes.
407-
if (typeof(sSessionVar) == 'undefined')
408-
sSessionVar = 'sesc';
427+
const x = [];
428+
submitThisOnce(document.forms.quickModifyForm);
429+
const form = document.forms.quickModifyForm;
409430

410-
// Let's put back the accesskeys to their original place
411-
if (typeof(this.opt.sFormRemoveAccessKeys) != 'undefined')
412-
{
413-
if (typeof(document.forms[this.opt.sFormRemoveAccessKeys]))
414-
{
415-
var aInputs = document.forms[this.opt.sFormRemoveAccessKeys].getElementsByTagName('input');
416-
for (var i = 0; i < aInputs.length; i++)
417-
{
418-
if (typeof(this.aAccessKeys[aInputs[i].name]) != 'undefined')
419-
{
420-
aInputs[i].accessKey = this.aAccessKeys[aInputs[i].name];
421-
}
422-
}
423-
}
431+
if (form.firstChild.className === 'errorbox') {
432+
form.firstChild.remove();
433+
form.message.style.border = '';
434+
form.subject.style.border = '';
424435
}
425436

426-
var i, x = new Array(),
427-
oCaller = this,
428-
formData = {
429-
subject : document.forms.quickModForm['subject'].value,
430-
message : document.forms.quickModForm['message'].value,
431-
topic : parseInt(document.forms.quickModForm.elements['topic'].value),
432-
msg : parseInt(document.forms.quickModForm.elements['msg'].value),
433-
modify_reason : document.forms.quickModForm.elements['modify_reason'].value
434-
};
437+
for (const el of form.elements) {
438+
x.push(el.name + '=' + el.value.php_to8bit().php_urlencode());
439+
}
435440

436441
// Send in the XMLhttp request and let's hope for the best.
437442
ajax_indicator(true);
438-
439-
sendXMLDocument.call(this, smf_prepareScriptUrl(this.opt.sScriptUrl) + "action=jsmodify;topic=" + this.opt.iTopicId + ";" + smf_session_var + "=" + smf_session_id + ";xml", formData, this.onModifyDone);
443+
sendXMLDocument.call(this, smf_prepareScriptUrl(this.opt.sScriptUrl) + "action=jsmodify;topic=" + this.opt.iTopicId + ";msg=" + this.oCurMessageDiv.id.match(/\d+/) + ";" + smf_session_var + "=" + smf_session_id + ";xml", x.join("&"), this.onModifyDone);
440444

441445
return false;
442446
}
@@ -450,9 +454,16 @@ QuickModify.prototype.onModifyDone = function (XMLDoc)
450454
// If we didn't get a valid document, just cancel.
451455
if (!XMLDoc || !XMLDoc.getElementsByTagName('smf')[0])
452456
{
457+
reActivateThis(document.forms.quickModifyForm);
458+
document.forms.quickModifyForm.message.focus();
459+
453460
// Mozilla will nicely tell us what's wrong.
454-
if (XMLDoc.childNodes.length > 0 && XMLDoc.firstChild.nodeName == 'parsererror')
455-
setInnerHTML(document.getElementById('error_box'), XMLDoc.firstChild.textContent);
461+
if (XMLDoc.childNodes.length > 0 && XMLDoc.firstChild.nodeName == 'parsererror') {
462+
const oDiv = document.createElement('div');
463+
oDiv.innerHTML = XMLDoc.firstChild.textContent;
464+
oDiv.className = 'errorbox';
465+
document.forms.quickModifyForm.prepend(oDiv);
466+
}
456467
else
457468
this.modifyCancel();
458469

@@ -465,40 +476,51 @@ QuickModify.prototype.onModifyDone = function (XMLDoc)
465476

466477
if (body)
467478
{
479+
this.bInEditMode = false;
468480
// Show new body.
469-
var bodyText = '';
470-
for (var i = 0; i < body.childNodes.length; i++)
481+
let bodyText = '';
482+
for (let i = 0; i < body.childNodes.length; i++)
471483
bodyText += body.childNodes[i].nodeValue;
472484

473-
this.sMessageBuffer = this.opt.sTemplateBodyNormal.replace(/%body%/, bodyText.replace(/\$/g, '{&dollarfix;$}')).replace(/\{&dollarfix;\$\}/g,'$');
474-
setInnerHTML(this.oCurMessageDiv, this.sMessageBuffer);
485+
this.oCurMessageDiv.innerHTML = bodyText;
486+
this.oCurMessageDiv.hidden = false;
487+
488+
// Show new subject div, update in case it changed.
489+
if (this.oCurSubjectDiv !== null) {
490+
let oSubject = message.getElementsByTagName('subject')[0],
491+
sSubjectText = oSubject.childNodes[0].nodeValue;
475492

476-
// Show new subject, but only if we want to...
477-
var oSubject = message.getElementsByTagName('subject')[0];
478-
var sSubjectText = oSubject.childNodes[0].nodeValue.replace(/\$/g, '{&dollarfix;$}');
479-
var sTopSubjectText = oSubject.childNodes[0].nodeValue.replace(/\$/g, '{&dollarfix;$}');
480-
this.sSubjectBuffer = this.opt.sTemplateSubjectNormal.replace(/%msg_id%/g, this.sCurMessageId.substr(4)).replace(/%subject%/, sSubjectText).replace(/\{&dollarfix;\$\}/g,'$');
481-
setInnerHTML(this.oCurSubjectDiv, this.sSubjectBuffer);
493+
this.oCurSubjectDiv.innerHTML = sSubjectText;
494+
this.oCurSubjectDiv.hidden = false;
495+
}
482496

483-
// If this is the first message, also update the topic subject.
484-
if (oSubject.getAttribute('is_first') == '1')
485-
setInnerHTML(document.getElementById('top_subject'), this.opt.sTemplateTopSubject.replace(/%subject%/, sTopSubjectText).replace(/\{&dollarfix;\$\}/g, '$'));
497+
document.forms.quickModifyForm.remove();
486498

487499
// Show this message as 'modified on x by y'.
488500
if (this.opt.bShowModify)
489-
$('#modified_' + this.sCurMessageId.substr(4)).html(message.getElementsByTagName('modified')[0].childNodes[0].nodeValue.replace(/\$/g, '{&dollarfix;$}'));
501+
{
502+
let modified = document.getElementById('modified_' + this.sCurMessageId.substring(4));
503+
modified.innerHTML = message.getElementsByTagName('modified')[0].childNodes[0].nodeValue;
504+
}
490505

491506
// Show a message indicating the edit was successfully done.
492-
$('<div/>',{
493-
text: message.getElementsByTagName('success')[0].childNodes[0].nodeValue.replace(/\$/g, '{&dollarfix;$}'),
494-
class: 'infobox'
495-
}).prependTo('#' + this.sCurMessageId).delay(5000).fadeOutAndRemove(400);
507+
const oDiv = document.createElement('div');
508+
oDiv.textContent = message.getElementsByTagName('success')[0].childNodes[0].nodeValue;
509+
oDiv.className = 'infobox';
510+
this.oCurMessageDiv.before(oDiv);
511+
setTimeout(() => oDiv.remove(), 4000);
496512
}
497513
else if (error)
498514
{
499-
setInnerHTML(document.getElementById('error_box'), error.childNodes[0].nodeValue);
500-
document.forms.quickModForm.message.style.border = error.getAttribute('in_body') == '1' ? this.opt.sErrorBorderStyle : '';
501-
document.forms.quickModForm.subject.style.border = error.getAttribute('in_subject') == '1' ? this.opt.sErrorBorderStyle : '';
515+
reActivateThis(document.forms.quickModifyForm);
516+
const oDiv = document.createElement('div');
517+
oDiv.innerHTML = error.childNodes[0].nodeValue;
518+
oDiv.className = 'errorbox';
519+
document.forms.quickModifyForm.prepend(oDiv);
520+
521+
document.forms.quickModifyForm.message.focus();
522+
document.forms.quickModifyForm.message.style.border = error.getAttribute('in_body') == '1' ? this.opt.sErrorBorderStyle : '';
523+
document.forms.quickModifyForm.subject.style.border = error.getAttribute('in_subject') == '1' ? this.opt.sErrorBorderStyle : '';
502524
}
503525
}
504526

0 commit comments

Comments
 (0)