ui-default: init

将ui-default合并至主存储库便于维护
This commit is contained in:
undefined committed 2021-04-03 01:44:22 +08:00
1 parent 6317c9057f
commit 5faa54c7ca
564 files changed
+23083 -14

No files matched your search

@@ -0,0 +1,105 @@
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import request from 'vj/utils/request';
import TextareaHandler from 'vj/components/cmeditor/textareaHandler';
import Notification from 'vj/components/notification';
let initialized = false;
const $template = $('.dczcomments__box').eq(0).clone();
function getClosestInstance($dom) {
return $dom.closest('.dczcomments__box').data('instance');
}
function onBoxCancel(ev) {
const commentBox = getClosestInstance($(ev.currentTarget));
if (commentBox) commentBox.onCancel(ev);
}
function onBoxSubmit(ev) {
const commentBox = getClosestInstance($(ev.currentTarget));
if (commentBox) commentBox.onSubmit(ev);
ev.preventDefault();
}
function init() {
if (initialized) return;
$(document).on('submit', '[name="dczcomments__box__form"]', onBoxSubmit);
$(document).on('vjCommentBoxCancel', '[name="dczcomments__box__form"]', onBoxCancel);
$(document).on('click', '[name="dczcomments__box__cancel"]', onBoxCancel);
initialized = true;
}
export default class CommentBox extends DOMAttachedObject {
static DOMAttachKey = 'vjCommentBoxInstance';
constructor($dom, options = {}) {
super($dom);
init();
this.$box = $template.clone();
this.$box.data('instance', this);
this.options = {
initialText: null,
mode: null,
form: null,
onCancel: () => null,
...options,
};
if (this.options.initialText) this.setText(this.options.initialText);
if (this.options.mode) {
const submitButton = this.$box.find('.dczcomments__box__submit');
submitButton.val(submitButton.attr(`data-value-${this.options.mode}`));
}
}
getTextareaHandler() {
const $textarea = this.$box.find('textarea');
return TextareaHandler.getOrConstruct($textarea);
}
focus() {
this.getTextareaHandler().focus();
return this;
}
setText(text) {
this.getTextareaHandler().val(text);
return this;
}
getText() {
return this.getTextareaHandler().val();
}
insertText(text) {
const handler = this.getTextareaHandler();
handler.val(handler.val() + text);
return this;
}
appendTo($dom) {
this.$box.appendTo($dom);
this.$box.trigger('vjContentNew');
return this;
}
async onSubmit() {
try {
await request.post('', {
...this.options.form,
content: this.getText(),
});
window.location.reload();
} catch (error) {
Notification.error(error.message);
}
}
async onCancel(ev) {
await this.options.onCancel(ev);
this.$box.remove();
this.detach();
}
}
_.assign(CommentBox, DOMAttachedObject);
@@ -0,0 +1,206 @@
import 'jquery.easing';
import { AutoloadPage } from 'vj/misc/Page';
import CommentBox from 'vj/components/discussion/CommentBox';
import { ConfirmDialog } from 'vj/components/dialog';
import delay from 'vj/utils/delay';
import { slideDown, slideUp } from 'vj/utils/slide';
import request from 'vj/utils/request';
import i18n from 'vj/utils/i18n';
import tpl from 'vj/utils/tpl';
const $replyTemplate = $('.commentbox-container').eq(0).clone();
function createReplyContainer($parent) {
const $container = $replyTemplate
.clone()
.hide()
.prependTo($parent.find('.commentbox-reply-target').eq(0))
.trigger('vjContentNew');
return $container.find('.commentbox-placeholder');
}
async function showReplyContainer($parent) {
const $container = $parent.find('.commentbox-container');
// TODO: fix ugly hack. cannot get $container rect because it is invisible
const rect = $container.parent()[0].getBoundingClientRect();
const rectBody = document.body.getBoundingClientRect();
if (rect.top < 100 || rect.top + 100 > window.innerHeight) {
const targetScrollTop = rect.top - rectBody.top - window.innerHeight * 0.382;
$('html, body').stop().animate({ scrollTop: targetScrollTop }, 400, 'easeOutCubic');
await delay(300);
// delay duration is set smaller than animation duration intentionally
}
$container.css('opacity', 0);
await slideDown($container, 300);
await $container.transition({ opacity: 1 }, { duration: 200 }).promise();
$container.removeAttr('style');
}
async function destroyReplyContainer($parent) {
const $container = $parent.find('.commentbox-container');
$container.css('opacity', 1);
await $container.transition({ opacity: 0 }, { duration: 200 }).promise();
await slideUp($container, 300);
$container.remove();
}
function onClickDummyBox(ev) {
const $evTarget = $(ev.currentTarget);
if (CommentBox.get($evTarget)) {
CommentBox
.get($evTarget)
.focus();
return;
}
const $mediaBody = $evTarget.closest('.media__body');
const opt = {
form: JSON.parse($evTarget.attr('data-form')),
mode: 'comment',
onCancel: () => {
$mediaBody.removeClass('is-editing');
},
};
$mediaBody.addClass('is-editing');
CommentBox
.getOrConstruct($evTarget, opt)
.appendTo($mediaBody.find('.commentbox-placeholder').eq(0))
.focus();
}
async function onCommentClickReplyComment(ev, options = {}) {
const $evTarget = $(ev.currentTarget);
if (CommentBox.get($evTarget)) {
// If comment box is already expanded,
// we should insert "initialText"
CommentBox
.get($evTarget)
.insertText(options.initialText || '')
.focus();
return;
}
const $mediaBody = $evTarget.closest('.media__body');
const opt = {
initialText: '',
mode: 'reply',
...options,
onCancel: async () => {
await destroyReplyContainer($mediaBody);
},
};
const cbox = CommentBox
.getOrConstruct($evTarget, {
form: JSON.parse($evTarget.attr('data-form')),
...opt,
})
.appendTo(createReplyContainer($mediaBody));
await showReplyContainer($mediaBody);
cbox.focus();
}
async function onCommentClickReplyReply(ev) {
const $evTarget = $(ev.currentTarget);
const $mediaBody = $evTarget.closest('.media__body');
const username = $mediaBody
.find('.user-profile-name').eq(0)
.text();
$evTarget
.closest('.dczcomments__item')
.find('[name="dczcomments__op-reply-comment"]').eq(0)
.trigger('click', { initialText: `@${username}: ` });
}
async function onCommentClickEdit(mode, ev) {
const $evTarget = $(ev.currentTarget);
if (CommentBox.get($evTarget)) {
CommentBox
.get($evTarget)
.focus();
return;
}
const $mediaBody = $evTarget.closest('.media__body');
const raw = await request.get(
$mediaBody.find('.typo').eq(0).attr('data-raw-url'),
{},
{ dataType: 'text' },
);
const opt = {
initialText: raw,
form: JSON.parse($evTarget.attr('data-form')),
mode,
onCancel: () => {
$mediaBody.removeClass('is-editing');
},
};
$mediaBody.addClass('is-editing');
CommentBox
.getOrConstruct($evTarget, opt)
.appendTo($mediaBody.find('.commentbox-edit-target').eq(0))
.focus();
}
function onCommentClickEditComment(ev) {
return onCommentClickEdit('comment-update', ev);
}
function onCommentClickEditReply(ev) {
return onCommentClickEdit('reply-update', ev);
}
async function onCommentClickDelete(type, ev) {
const message = (type === 'comment')
? 'Confirm deleting this comment? Its replies will be deleted as well.'
: 'Confirm deleting this reply?';
const action = await new ConfirmDialog({
$body: tpl`
<div class="typo">
<p>${i18n(message)}</p>
</div>`,
}).open();
if (action !== 'yes') {
return;
}
const $evTarget = $(ev.currentTarget);
const form = JSON.parse($evTarget.attr('data-form'));
await request.post('', form);
window.location.reload();
}
function onCommentClickDeleteComment(ev) {
onCommentClickDelete('comment', ev);
}
function onCommentClickDeleteReply(ev) {
onCommentClickDelete('reply', ev);
}
const commentsPage = new AutoloadPage('commentsPage', () => {
$(document).on('click', '[name="dczcomments__dummy-box"]', onClickDummyBox);
$(document).on('click', '[name="dczcomments__op-reply-comment"]', onCommentClickReplyComment);
$(document).on('click', '[name="dczcomments__op-reply-reply"]', onCommentClickReplyReply);
$(document).on('click', '[name="dczcomments__op-edit-comment"]', onCommentClickEditComment);
$(document).on('click', '[name="dczcomments__op-edit-reply"]', onCommentClickEditReply);
$(document).on('click', '[name="dczcomments__op-delete-comment"]', onCommentClickDeleteComment);
$(document).on('click', '[name="dczcomments__op-delete-reply"]', onCommentClickDeleteReply);
});
export default commentsPage;
@@ -0,0 +1,125 @@
$upvote-color = green
$downvote-color = red
.dczcomments__item .is-editing
[name="dczcomments__dummy-box"]
display: none
> .typo
display: none
.dczcomments__box .textbox
height: rem(180px)
resize: vertical
.textbox[name="dczcomments__dummy-box"]
height: rem(60px)
resize: none
font-size: rem($font-size-title)
color: $comment-placeholder-color
padding: rem(10px)
.dczcomments__item,
.dczcomments__reply
border-top: 1px solid $table-border-color
>.media
padding: rem(20px 0)
&:first-child
border-top: 0
.dczcomments__reply
&:last-child
>.media
padding-bottom: 0
.dczcomments__supplementary
float: left
margin-bottom: rem(5px)
.dczcomments__operations
font-size: rem($font-size)
float: right
vertical-align: top
color: $comment-op-color
a, a:visited
color: $comment-op-link-color
margin-left: rem(3px)
a:hover
color: $primary-color
text-decoration: none
.view--solution .dczcomments__replies
margin-left: rem(50px)
.dczcomments__item
.vote-number
width: rem(82px)
text-align: center
font-size: rem(25px)
font-weight: 300
margin-bottom: rem(10px)
.vote-op
position: relative
border: 1px solid transparent
border-radius: rem(14px)
transition: border-color .2s linear, opacity .2s linear
opacity: 0.5
&>form
width: rem(40px)
float: left
position: relative
&:hover .vote-op
opacity: 1
border-color: $supplementary-border-color
.vote-button
appearance: none
border: 0
background: none
width: 100%
outline: 0
font-size: rem($font-size-icon)
line-height: rem(26px)
color: #AAA
transition: color .2s linear, background-color .2s linear, box-shadow .2s linear
&.upvote
border-radius: rem(13px 0 0 13px)
padding-left: rem(7px)
&:hover
background: $upvote-color
color: #FFF
box-shadow: 0 2px 10px rgba($upvote-color, 0.4)
&.active
color: $upvote-color
&.downvote
border-radius: rem(0 13px 13px 0)
padding-right: rem(7px)
&:hover
background: $downvote-color
color: #FFF
box-shadow: 0 2px 10px rgba($downvote-color, 0.4)
&.active
color: $downvote-color
&.active
background: transparent !important
box-shadow: none !important
cursor: default
+mobile()
.dczcomments__item
.media__left
display: none
@@ -0,0 +1,17 @@
.discussion-node-tag
font-size: rem($font-size-small)
display: inline-block
line-height: rem(22px)
padding: rem(0 10px)
vertical-align: middle
border-radius: rem(12px)
border: 1px solid $supplementary-border-color
&:hover
background: $primary-color
color: #FFF !important
text-decoration: none
border-color: $primary-color
.icon
margin-right: rem(5px)