S2OJ/web/js/blog-editor/blog-editor.js

330 lines
8.9 KiB
JavaScript
Raw Normal View History

2016-07-18 16:39:37 +00:00
function blog_editor_init(name, editor_config) {
if (editor_config === undefined) {
editor_config = {};
}
editor_config = $.extend({
type: 'blog'
}, editor_config);
var input_title = $("#input-" + name + "_title");
var input_tags = $("#input-" + name + "_tags");
var input_content_md = $("#input-" + name + "_content_md");
var input_is_hidden = $("#input-" + name + "_is_hidden");
2022-09-18 11:34:17 +00:00
var this_form = input_is_hidden[0].form;
2016-07-18 16:39:37 +00:00
var is_saved;
var last_save_done = true;
// init buttons
var save_btn = $('<button type="button" class="btn btn-sm"></button>');
var preview_btn = $('<button type="button" class="btn btn-secondary btn-sm">' + (isBootstrap5Page ? '<i class="bi bi-eye"></i>' : '<span class="glyphicon glyphicon-eye-open"></span>') + '</button>');
var bold_btn = $('<button type="button" class="btn btn-secondary btn-sm ml-2">' + (isBootstrap5Page ? '<i class="bi bi-type-bold"></i>' : '<span class="glyphicon glyphicon-bold"></span>') + '</button>');
var italic_btn = $('<button type="button" class="btn btn-secondary btn-sm">' + (isBootstrap5Page ? '<i class="bi bi-type-italic"></i>' : '<span class="glyphicon glyphicon-italic"></span>') + '</button>');
if (typeof isBootstrap5Page !== 'undefined' && isBootstrap5Page) {
save_btn.get().map(el => new bootstrap.Tooltip(el, { container: 'body', title: '保存 (Ctrl-S)' }));
preview_btn.get().map(el => new bootstrap.Tooltip(el, { container: 'body', title: '预览 (Ctrl-D)' }));
bold_btn.get().map(el => new bootstrap.Tooltip(el, { container: 'body', title: '粗体 (Ctrl-B)' }));
italic_btn.get().map(el => new bootstrap.Tooltip(el, { container: 'body', title: '斜体 (Ctrl-I)' }));
} else {
save_btn.tooltip({ container: 'body', title: '保存 (Ctrl-S)' });
preview_btn.tooltip({ container: 'body', title: '预览 (Ctrl-D)' });
bold_btn.tooltip({ container: 'body', title: '粗体 (Ctrl-B)' });
italic_btn.tooltip({ container: 'body', title: '斜体 (Ctrl-I)' });
}
2016-07-18 16:39:37 +00:00
var all_btn = [save_btn, preview_btn, bold_btn, italic_btn];
// init toolbar
var toolbar = $('<div class="btn-toolbar"></div>');
toolbar.append($('<div class="btn-group me-2"></div>')
2016-07-18 16:39:37 +00:00
.append(save_btn)
.append(preview_btn)
);
toolbar.append($('<div class="btn-group"></div>')
.append(bold_btn)
.append(italic_btn)
);
function set_saved(val) {
is_saved = val;
if (val) {
save_btn.removeClass('btn-warning');
save_btn.addClass('btn-success');
save_btn.html(isBootstrap5Page ? '<i class="bi bi-save-fill"></i>' : '<span class="glyphicon glyphicon-saved"></span>');
2016-07-18 16:39:37 +00:00
before_window_unload_message = null;
} else {
save_btn.removeClass('btn-success');
save_btn.addClass('btn-warning');
save_btn.html(isBootstrap5Page ? '<i class="bi bi-save"></i>' : '<span class="glyphicon glyphicon-save"></span>');
2016-07-18 16:39:37 +00:00
before_window_unload_message = '您所编辑的内容尚未保存';
}
}
function set_preview_status(status) {
// 0: normal
// 1: loading
// 2: loaded
if (status == 0) {
preview_btn.removeClass('active');
for (var i = 0; i < all_btn.length; i++) {
if (all_btn[i] != preview_btn) {
all_btn[i].prop('disabled', false);
}
}
} else if (status == 1) {
for (var i = 0; i < all_btn.length; i++) {
if (all_btn[i] != preview_btn) {
all_btn[i].prop('disabled', true);
}
}
preview_btn.addClass('active');
}
}
set_saved(true);
// init codemirror
2022-09-18 11:34:17 +00:00
if (input_content_md[0]) {
input_content_md.wrap('<div class="blog-content-md-editor"></div>');
var blog_contend_md_editor = input_content_md.parent();
input_content_md.before($('<div class="blog-content-md-editor-toolbar"></div>')
.append(toolbar)
);
input_content_md.wrap('<div class="blog-content-md-editor-in"></div>');
var codeeditor;
if (editor_config.type == 'blog') {
codeeditor = CodeMirror.fromTextArea(input_content_md[0], {
mode: 'gfm',
lineNumbers: true,
matchBrackets: true,
lineWrapping: true,
styleActiveLine: true,
theme: 'default'
});
} else if (editor_config.type == 'slide') {
codeeditor = CodeMirror.fromTextArea(input_content_md[0], {
mode: 'plain',
lineNumbers: true,
matchBrackets: true,
lineWrapping: true,
styleActiveLine: true,
theme: 'default'
});
}
2016-07-18 16:39:37 +00:00
}
2022-09-18 11:34:17 +00:00
2016-07-18 16:39:37 +00:00
function preview(html) {
var iframe = $('<iframe frameborder="0"></iframe>');
blog_contend_md_editor.append(
$('<div class="blog-content-md-editor-preview" style="display: none;"></div>')
.append(iframe)
);
var iframe_document = iframe[0].contentWindow.document;
iframe_document.open();
iframe_document.write(html);
iframe_document.close();
$(iframe_document).bind('keydown', 'ctrl+d', function() {
preview_btn.click();
return false;
});
blog_contend_md_editor.find('.blog-content-md-editor-in').slideUp('fast');
blog_contend_md_editor.find('.blog-content-md-editor-preview').slideDown('fast', function() {
set_preview_status(2);
iframe.focus();
iframe.find('body').focus();
});
}
function save(config) {
if (config == undefined) {
config = {};
}
config = $.extend({
need_preview: false,
fail: function() {
},
done: function() {
}
}, config);
if (!last_save_done) {
config.fail();
config.done();
return;
}
last_save_done = false;
if (config.need_preview) {
set_preview_status(1);
}
var post_data = {};
$($(this_form).serializeArray()).each(function() {
post_data[this["name"]] = this["value"];
});
if (config.need_preview) {
post_data['need_preview'] = 'on';
}
post_data["save-" + name] = '';
2016-07-18 16:39:37 +00:00
$.ajax({
type : 'POST',
data : post_data,
url : window.location.href,
success : function(data) {
try {
data = JSON.parse(data)
} catch (e) {
alert(data);
if (config.need_preview) {
set_preview_status(0);
}
config.fail();
return;
}
var ok = true;
$(['title', 'content_md', 'tags']).each(function() {
ok &= showErrorHelp(name + '_' + this, data[this]);
});
if (data.extra !== undefined) {
alert(data.extra);
ok = false;
}
if (!ok) {
if (config.need_preview) {
set_preview_status(0);
}
config.fail();
return;
}
set_saved(true);
if (config.need_preview) {
preview(data.html);
}
if (data.blog_write_url) {
window.history.replaceState({}, document.title, data.blog_write_url);
}
if (data.blog_url) {
$('#a-' + name + '_view_blog').attr('href', data.blog_url).show();
}
2022-10-16 12:38:03 +00:00
if (data.blog_id) {
$('#div-blog-id').html('<small>博客 ID<b>' + data.blog_id + '</b></small>').show();
}
2016-07-18 16:39:37 +00:00
}
}).fail(function() {
if (config.need_preview) {
set_preview_status(0);
}
config.fail();
}).always(function() {
last_save_done = true;
config.done();
});
}
function add_around(sl, sr) {
codeeditor.replaceSelection(sl + codeeditor.getSelection() + sr);
}
// event
2022-09-18 11:34:17 +00:00
if (input_content_md[0]) {
codeeditor.on('change', function() {
codeeditor.save();
set_saved(false);
});
}
2016-07-18 16:39:37 +00:00
$.merge(input_title, input_tags).on('input', function() {
set_saved(false);
});
2022-09-18 11:34:17 +00:00
$('#a-' + name + '_save').click(function (e) {
e.preventDefault();
save({
done: function () {
location.reload();
}
});
});
2016-07-18 16:39:37 +00:00
save_btn.click(function() {
save();
});
preview_btn.click(function() {
if (preview_btn.hasClass('active')) {
set_preview_status(0);
blog_contend_md_editor.find('.blog-content-md-editor-in').slideDown('fast');
blog_contend_md_editor.find('.blog-content-md-editor-preview').slideUp('fast', function() {
$(this).remove();
});
codeeditor.focus();
} else {
save({need_preview: true});
}
});
bold_btn.click(function() {
add_around("**", "**");
codeeditor.focus();
});
italic_btn.click(function() {
add_around("*", "*");
codeeditor.focus();
});
input_is_hidden.on('switchChange.bootstrapSwitch', function(e, state) {
var ok = true;
if (!state && !confirm("你确定要公开吗?")) {
ok = false;
}
if (!ok) {
input_is_hidden.bootstrapSwitch('toggleState', true);
} else {
input_is_hidden.bootstrapSwitch('readonly', true);
var succ = true;
save({
fail: function() {
succ = false;
},
done: function() {
input_is_hidden.bootstrapSwitch('readonly', false);
if (!succ) {
input_is_hidden.bootstrapSwitch('toggleState', true);
}
}
});
}
});
// init hot keys
2022-09-18 11:34:17 +00:00
if (input_content_md[0]) {
codeeditor.setOption("extraKeys", {
"Ctrl-S": function(cm) {
save_btn.click();
},
"Ctrl-B": function(cm) {
bold_btn.click();
},
"Ctrl-D": function(cm) {
preview_btn.click();
},
"Ctrl-I": function(cm) {
italic_btn.click();
}
});
}
2016-07-18 16:39:37 +00:00
$(document).bind('keydown', 'ctrl+d', function() {
preview_btn.click();
return false;
});
$.merge(input_title, input_tags).bind('keydown', 'ctrl+s', function() {
save_btn.click();
return false;
});
if (this_form) {
$(this_form).submit(function() {
before_window_unload_message = null;
});
}
}