unique css ids

and bug fix test: editing comment: button label "save" instead of "edit comment"
This commit is contained in:
Katja Suess 2020-01-16 15:32:46 +01:00
parent 6794d95f85
commit f7ae6e49a5
4 changed files with 258 additions and 240 deletions

View File

@ -1,3 +1,3 @@
Extended existing review workflow by stati ``rejected`` and ``spam``
Moderation view extended to handle four workflow states.
[ksuess]
[ksuess and precious input of agitator]

View File

@ -32,6 +32,7 @@
<div class="comment"
tal:define="reply reply_dict/comment;
comment_id reply/getId;
depth reply_dict/depth|python:0;
depth python: depth > 10 and '10' or depth;
author_home_url python:view.get_commenter_home_url(username=reply.author_username);
@ -42,7 +43,7 @@
canDelete python:view.can_delete(reply);
colorclass python:lambda x: 'state-private' if x=='rejected' else ('state-internal' if x=='spam' else 'state-'+x);"
tal:attributes="class python:'comment replyTreeLevel{depth} {state}'.format(depth= depth, state=colorclass(review_state));
id string:${reply/getId}"
id comment_id"
tal:condition="python:canReview or review_state == 'published'">
<div class="commentImage" tal:condition="showCommenterImage">
@ -95,7 +96,8 @@
class="commentactionsform"
tal:condition="python:not canDelete and isDeleteOwnCommentAllowed and view.could_delete_own(reply)"
tal:attributes="action string:${reply/absolute_url}/@@delete-own-comment;
style python:view.can_delete_own(reply) and 'display: inline' or 'display: none'">
style python:view.can_delete_own(reply) and 'display: inline' or 'display: none';
id string:delete-${comment_id}">
<input name="form.button.DeleteComment"
class="destructive"
type="submit"
@ -108,7 +110,8 @@
method="post"
class="commentactionsform"
tal:condition="python:canDelete"
tal:attributes="action string:${reply/absolute_url}/@@moderate-delete-comment">
tal:attributes="action string:${reply/absolute_url}/@@moderate-delete-comment;
id string:delete-${comment_id}">
<input name="form.button.DeleteComment"
class="destructive"
type="submit"
@ -120,7 +123,7 @@
<tal:edit tal:condition="python:isEditCommentAllowed and canEdit">
<!-- plone 5 will have auth_token available
so we'll use modal pattern -->
<a class="pat-plone-modal context"
<a class="pat-plone-modal context commentactionsform"
tal:condition="auth_token"
tal:attributes="href string:${reply/absolute_url}/@@edit-comment?_authenticator=${auth_token}"
i18n:translate="Edit">Edit</a>
@ -129,7 +132,8 @@
method="get"
class="commentactionsform"
tal:condition="not: auth_token"
tal:attributes="action string:${reply/absolute_url}/@@edit-comment">
tal:attributes="action string:${reply/absolute_url}/@@edit-comment;
id string:edit-${comment_id}">
<input name="form.button.EditComment"
class="context"
type="submit"
@ -148,7 +152,8 @@
tal:condition="canReview"
tal:repeat="action reply_dict/actions|nothing"
tal:attributes="action string:${reply/absolute_url}/@@transmit-comment;
name action/id">
name action/id;
id string:${action/id}-${comment_id}">
<input type="hidden" name="workflow_action" tal:attributes="value action/id" />
<input name="form.button.TransmitComment"
class="context"

View File

@ -5,263 +5,276 @@
******************************************************************************/
/* global require */
if(require === undefined){
require = function(reqs, torun){ // jshint ignore:line
'use strict';
return torun(window.jQuery);
};
if (require === undefined) {
require = function(reqs, torun) {
// jshint ignore:line
"use strict";
return torun(window.jQuery);
};
}
require([ // jshint ignore:line
'jquery'
], function ($) {
'use strict';
require([
// jshint ignore:line
"jquery"
], function($) {
"use strict";
// This unnamed function allows us to use $ inside of a block of code
// without permanently overwriting $.
// http://docs.jquery.com/Using_jQuery_with_Other_Libraries
/**************************************************************************
* Create a reply-to-comment form right beneath the form that is passed to
* the function. We do this by copying the regular comment form and
* adding a hidden in_reply_to field to the form.
**************************************************************************/
$.createReplyForm = function (comment_div) {
// This unnamed function allows us to use $ inside of a block of code
// without permanently overwriting $.
// http://docs.jquery.com/Using_jQuery_with_Other_Libraries
/**************************************************************************
* Create a reply-to-comment form right beneath the form that is passed to
* the function. We do this by copying the regular comment form and
* adding a hidden in_reply_to field to the form.
**************************************************************************/
$.createReplyForm = function(comment_div) {
var comment_id = comment_div.attr("id");
var comment_id = comment_div.attr('id');
var reply_button = comment_div.find(".reply-to-comment-button");
var reply_button = comment_div.find('.reply-to-comment-button');
/* Clone the reply div at the end of the page template that contains
* the regular comment form.
*/
var reply_div = $("#commenting").clone(true);
/* Clone the reply div at the end of the page template that contains
* the regular comment form.
*/
var reply_div = $('#commenting').clone(true);
/* Remove the ReCaptcha JS code before appending the form. If not
* removed, this causes problems
*/
reply_div
.find("#formfield-form-widgets-captcha")
.find("script")
.remove();
/* Remove the ReCaptcha JS code before appending the form. If not
* removed, this causes problems
*/
reply_div.find('#formfield-form-widgets-captcha')
.find('script')
.remove();
/* Insert the cloned comment form right after the reply button of the
* current comment.
*/
reply_div.appendTo(comment_div).css("display", "none");
/* Insert the cloned comment form right after the reply button of the
* current comment.
*/
reply_div.appendTo(comment_div).css('display', 'none');
/* Remove id='commenting' attribute, since we use it to uniquely define
/* Remove id='commenting' attribute, since we use it to uniquely define
the main reply form. */
// Still belongs to class='reply'
reply_div.removeAttr('id');
// Still belongs to class='reply'
reply_div.removeAttr("id");
/* Hide the reply button (only hide, because we may want to show it
* again if the user hits the cancel button).
*/
$(reply_button).css('display', 'none');
/* Hide the reply button (only hide, because we may want to show it
* again if the user hits the cancel button).
*/
$(reply_button).css("display", "none");
/* Fetch the reply form inside the reply div */
var reply_form = reply_div.find('form');
/* Fetch the reply form inside the reply div */
var reply_form = reply_div.find("form");
/* Change the id of the textarea of the reply form
* To avoid conflict later between textareas with same id 'form-widgets-comment-text' while implementing a seperate instance of TinyMCE
* */
reply_form.find('#formfield-form-widgets-comment-text').attr('id', 'formfield-form-widgets-new-textarea'+comment_id );
reply_form.find('#form-widgets-comment-text').attr('id', 'form-widgets-new-textarea'+comment_id );
/* Change the id of the textarea of the reply form
* To avoid conflict later between textareas with same id 'form-widgets-comment-text' while implementing a seperate instance of TinyMCE
* */
reply_form
.find("#formfield-form-widgets-comment-text")
.attr("id", "formfield-form-widgets-new-textarea" + comment_id);
reply_form
.find("#form-widgets-comment-text")
.attr("id", "form-widgets-new-textarea" + comment_id);
/* Populate the hidden 'in_reply_to' field with the correct comment
/* Populate the hidden 'in_reply_to' field with the correct comment
id */
reply_form.find('input[name="form.widgets.in_reply_to"]')
.val(comment_id);
reply_form.find('input[name="form.widgets.in_reply_to"]').val(comment_id);
/* Add a remove-reply-to-comment Javascript function to remove the
/* Add a remove-reply-to-comment Javascript function to remove the
form */
var cancel_reply_button = reply_div.find('.cancelreplytocomment');
cancel_reply_button.attr('id', comment_id);
var cancel_reply_button = reply_div.find(".cancelreplytocomment");
cancel_reply_button.attr("id", comment_id);
/* Show the cancel buttons. */
reply_form.find('input[name="form.buttons.cancel"]')
.css('display', 'inline');
/* Show the cancel buttons. */
reply_form
.find('input[name="form.buttons.cancel"]')
.css("display", "inline");
/* Show the reply layer with a slide down effect */
reply_div.slideDown('slow');
/* Show the reply layer with a slide down effect */
reply_div.slideDown("slow");
/* Show the cancel button in the reply-to-comment form */
cancel_reply_button.css('display', 'inline');
};
/* Show the cancel button in the reply-to-comment form */
cancel_reply_button.css("display", "inline");
};
/**************************************************************************
* Remove all error messages and field values from the form that is passed
* to the function.
**************************************************************************/
$.clearForm = function(form_div) {
form_div.find(".error").removeClass("error");
form_div.find(".fieldErrorBox").remove();
form_div.find('input[type="text"]').attr("value", "");
form_div.find("textarea").attr("value", "");
/* XXX: Clean all additional form extender fields. */
};
/**************************************************************************
* Remove all error messages and field values from the form that is passed
* to the function.
**************************************************************************/
$.clearForm = function (form_div) {
form_div.find('.error').removeClass('error');
form_div.find('.fieldErrorBox').remove();
form_div.find('input[type="text"]').attr('value', '');
form_div.find('textarea').attr('value', '');
/* XXX: Clean all additional form extender fields. */
};
//#JSCOVERAGE_IF 0
//#JSCOVERAGE_IF 0
/**************************************************************************
* Window Load Function: Executes when complete page is fully loaded,
* including all frames,
**************************************************************************/
$(window).load(function () {
/**********************************************************************
* If the user has hit the reply button of a reply-to-comment form
* (form was submitted with a value for the 'in_reply_to' field in the
* request), create a reply-to-comment form right under this comment.
**********************************************************************/
var post_comment_div = $('#commenting');
var in_reply_to_field =
post_comment_div.find('input[name="form.widgets.in_reply_to"]');
if (in_reply_to_field.length !== 0 && in_reply_to_field.val() !== '') {
var current_reply_id = '#' + in_reply_to_field.val();
var current_reply_to_div = $('.discussion').find(current_reply_id);
$.createReplyForm(current_reply_to_div);
$.clearForm(post_comment_div);
}
/**********************************************************************
* If the user hits the 'reply' button of an existing comment, create a
* reply form right beneath this comment.
**********************************************************************/
$('.reply-to-comment-button').bind('click', function (e) { // jshint ignore:line
var comment_div = $(this).parents().filter('.comment');
$.createReplyForm(comment_div);
$.clearForm(comment_div);
});
/**********************************************************************
* If the user hits the 'clear' button of an open reply-to-comment form,
* remove the form and show the 'reply' button again.
**********************************************************************/
$('#commenting #form-buttons-cancel').bind('click', function (e) {
e.preventDefault();
var reply_to_comment_button = $(this).
parents().
filter('.comment').
find('.reply-to-comment-button');
/* Find the reply-to-comment form and hide and remove it again. */
$.reply_to_comment_form = $(this).parents().filter('.reply');
$.reply_to_comment_form.slideUp('slow', function () {
$(this).remove();
});
/* Show the reply-to-comment button again. */
reply_to_comment_button.css('display', 'inline');
});
/**********************************************************************
* Transmit a single comment.
**********************************************************************/
$('input[name="form.button.TransmitComment"]').on('click', function () {
var trigger = this;
var form = $(this).parents('form');
var data = $(form).serialize();
var form_url = $(form).attr('action');
$.ajax({
type: 'GET',
url: form_url,
data: data,
context: trigger,
success: function (msg) { // jshint ignore:line
// remove button (trigger object can't be directly removed)
form.find('input[name="form.button.TransmitComment"]').remove();
form.parents('.state-pending').toggleClass('state-pending').toggleClass('state-published');
},
error: function (msg) { // jshint ignore:line
return true;
}
});
return false;
});
/**********************************************************************
* Edit a comment
**********************************************************************/
if($.fn.prepOverlay){
$('form[name="edit"]').prepOverlay({
cssclass: 'overlay-edit-comment',
width: '60%',
subtype: 'ajax',
filter: '#content>*'
});
}
/**********************************************************************
* Delete a comment and its answers.
**********************************************************************/
$('input[name="form.button.DeleteCommentComment"]').on('click', function () {
var trigger = this;
var form = $(this).parents('form');
var data = $(form).serialize();
var form_url = $(form).attr('action');
$.ajax({
type: 'POST',
url: form_url,
data: data,
context: $(trigger).parents('.comment'),
success: function (data) { // jshint ignore:line
var comment = $(this);
var clss = comment.attr('class');
// remove replies
var treelevel = parseInt(clss[clss.indexOf('replyTreeLevel') + 'replyTreeLevel'.length], 10);
// selector for all the following elements of lower level
var selector = '.replyTreeLevel' + treelevel;
for (var i = 0; i < treelevel; i++) {
selector += ', .replyTreeLevel' + i;
}
comment.nextUntil(selector).each(function () {
$(this).fadeOut('fast', function () {
$(this).remove();
});
});
// Add delete button to the parent
var parent = comment.prev('[class*="replyTreeLevel' + (treelevel - 1) + '"]');
parent.find('form[name="delete"]').css('display', 'inline');
// remove comment
$(this).fadeOut('fast', function () {
$(this).remove();
});
},
error: function (req, error) { // jshint ignore:line
return true;
}
});
return false;
});
/**********************************************************************
* By default, hide the reply and the cancel button for the regular add
* comment form.
**********************************************************************/
$('.reply').find('input[name="form.buttons.reply"]')
.css('display', 'none');
$('.reply').find('input[name="form.buttons.cancel"]')
.css('display', 'none');
/**********************************************************************
* By default, show the reply button only when Javascript is enabled.
* Otherwise hide it, since the reply functions only work with JS
* enabled.
**********************************************************************/
$('.reply-to-comment-button').removeClass('hide');
/**************************************************************************
* Window Load Function: Executes when complete page is fully loaded,
* including all frames,
**************************************************************************/
$(window).load(function() {
/**********************************************************************
* If the user has hit the reply button of a reply-to-comment form
* (form was submitted with a value for the 'in_reply_to' field in the
* request), create a reply-to-comment form right under this comment.
**********************************************************************/
var post_comment_div = $("#commenting");
var in_reply_to_field = post_comment_div.find(
'input[name="form.widgets.in_reply_to"]'
);
if (in_reply_to_field.length !== 0 && in_reply_to_field.val() !== "") {
var current_reply_id = "#" + in_reply_to_field.val();
var current_reply_to_div = $(".discussion").find(current_reply_id);
$.createReplyForm(current_reply_to_div);
$.clearForm(post_comment_div);
}
/**********************************************************************
* If the user hits the 'reply' button of an existing comment, create a
* reply form right beneath this comment.
**********************************************************************/
$(".reply-to-comment-button").bind("click", function(e) {
// jshint ignore:line
var comment_div = $(this)
.parents()
.filter(".comment");
$.createReplyForm(comment_div);
$.clearForm(comment_div);
});
/**********************************************************************
* If the user hits the 'clear' button of an open reply-to-comment form,
* remove the form and show the 'reply' button again.
**********************************************************************/
$("#commenting #form-buttons-cancel").bind("click", function(e) {
e.preventDefault();
var reply_to_comment_button = $(this)
.parents()
.filter(".comment")
.find(".reply-to-comment-button");
//#JSCOVERAGE_ENDIF
/* Find the reply-to-comment form and hide and remove it again. */
$.reply_to_comment_form = $(this)
.parents()
.filter(".reply");
$.reply_to_comment_form.slideUp("slow", function() {
$(this).remove();
});
/* Show the reply-to-comment button again. */
reply_to_comment_button.css("display", "inline");
});
/**********************************************************************
* Transmit a single comment.
**********************************************************************/
$('input[name="form.button.TransmitComment"]').on("click", function() {
var trigger = this;
var form = $(this).parents("form");
var data = $(form).serialize();
var form_url = $(form).attr("action");
$.ajax({
type: "GET",
url: form_url,
data: data,
context: trigger,
success: function(msg) {
// jshint ignore:line
// remove button (trigger object can't be directly removed)
form.find('input[name="form.button.TransmitComment"]').remove();
form
.parents(".state-pending")
.toggleClass("state-pending")
.toggleClass("state-published");
},
error: function(msg) {
// jshint ignore:line
return true;
}
});
return false;
});
/**********************************************************************
* Edit a comment
**********************************************************************/
if ($.fn.prepOverlay) {
$('form[name="edit"]').prepOverlay({
cssclass: "overlay-edit-comment",
width: "60%",
subtype: "ajax",
filter: "#content>*"
});
}
/**********************************************************************
* Delete a comment and its answers.
**********************************************************************/
$('input[name="form.button.DeleteComment"]').on("click", function() {
var trigger = this;
var form = $(this).parents("form");
var data = $(form).serialize();
var form_url = $(form).attr("action");
$.ajax({
type: "POST",
url: form_url,
data: data,
context: $(trigger).parents(".comment"),
success: function(data) {
// jshint ignore:line
var comment = $(this);
var clss = comment.attr("class");
// remove replies
var treelevel = parseInt(
clss[clss.indexOf("replyTreeLevel") + "replyTreeLevel".length],
10
);
// selector for all the following elements of lower level
var selector = ".replyTreeLevel" + treelevel;
for (var i = 0; i < treelevel; i++) {
selector += ", .replyTreeLevel" + i;
}
comment.nextUntil(selector).each(function() {
$(this).fadeOut("fast", function() {
$(this).remove();
});
});
// Add delete button to the parent
var parent = comment.prev(
'[class*="replyTreeLevel' + (treelevel - 1) + '"]'
);
parent.find('form[name="delete"]').css("display", "inline");
// remove comment
$(this).fadeOut("fast", function() {
$(this).remove();
});
},
error: function(req, error) {
// jshint ignore:line
return true;
}
});
return false;
});
/**********************************************************************
* By default, hide the reply and the cancel button for the regular add
* comment form.
**********************************************************************/
$(".reply")
.find('input[name="form.buttons.reply"]')
.css("display", "none");
$(".reply")
.find('input[name="form.buttons.cancel"]')
.css("display", "none");
/**********************************************************************
* By default, show the reply button only when Javascript is enabled.
* Otherwise hide it, since the reply functions only work with JS
* enabled.
**********************************************************************/
$(".reply-to-comment-button").removeClass("hide");
});
//#JSCOVERAGE_ENDIF
});

View File

@ -285,7 +285,7 @@ Open the edit comment view
Change and save the comment
>>> ctrl.value = 'Comment from admin / was edited'
>>> browser.getControl('Edit comment').click()
>>> browser.getControl('Save').click()
This used to trigger permissions problems in some portlet configurations.
Check it ain't so.