diff --git a/tamguo-bms/src/main/java/com/tamguo/web/member/DocumentController.java b/tamguo-bms/src/main/java/com/tamguo/web/member/DocumentController.java
index 3076433..bfe0b04 100644
--- a/tamguo-bms/src/main/java/com/tamguo/web/member/DocumentController.java
+++ b/tamguo-bms/src/main/java/com/tamguo/web/member/DocumentController.java
@@ -194,6 +194,9 @@ public class DocumentController {
}
}
+ /**
+ * 移除文件
+ */
@RequestMapping(value = "removeFile" , method = RequestMethod.POST)
@ResponseBody
public Result removeFile(String id) {
@@ -202,6 +205,7 @@ public class DocumentController {
} catch (Exception e) {
return Result.result(1, null, "删除失败");
}
- return Result.successResult("删除成功");
+ return Result.result(0, null, "删除成功");
}
+
}
diff --git a/tamguo-bms/src/main/java/com/tamguo/web/member/HistoryDocController.java b/tamguo-bms/src/main/java/com/tamguo/web/member/HistoryDocController.java
new file mode 100644
index 0000000..d245a14
--- /dev/null
+++ b/tamguo-bms/src/main/java/com/tamguo/web/member/HistoryDocController.java
@@ -0,0 +1,91 @@
+package com.tamguo.web.member;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.baomidou.mybatisplus.mapper.Condition;
+import com.tamguo.common.utils.Result;
+import com.tamguo.modules.book.model.DocumentEntity;
+import com.tamguo.modules.book.model.enums.DocumentStatusEnum;
+import com.tamguo.modules.book.service.IDocumentService;
+
+@Controller
+@RequestMapping(value="member/document")
+public class HistoryDocController {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+ @Autowired
+ private IDocumentService iDocumentService;
+
+ /**
+ * 历史记录
+ */
+ @SuppressWarnings("unchecked")
+ @RequestMapping(value = "history" , method = RequestMethod.POST)
+ public ModelAndView history(String id , ModelAndView model) {
+ model.setViewName("member/book/history");
+ DocumentEntity document = iDocumentService.selectById(id);
+ model.addObject("document", document);
+ model.addObject("historyList", iDocumentService.selectList(Condition.create().eq("batch_no", document.getBatchNo()).eq("status", DocumentStatusEnum.HISTORY.getValue()).orderDesc(Arrays.asList("create_date"))));
+ return model;
+ }
+
+ /**
+ * 删除
+ */
+ @RequestMapping(value = "history/delete" , method = RequestMethod.POST)
+ @ResponseBody
+ public Result delete(String id) {
+ try {
+ iDocumentService.deleteById(id);
+ } catch (Exception e) {
+ logger.error(e.getMessage() , e);
+ return Result.failResult("删除失败!");
+ }
+ return Result.successResult("删除成功!");
+ }
+
+ /**
+ * 恢复
+ */
+ @SuppressWarnings("unchecked")
+ @RequestMapping(value = "history/restore" , method = RequestMethod.POST)
+ @ResponseBody
+ public Result restore(String id) {
+ try {
+ DocumentEntity history = iDocumentService.selectById(id);
+
+ String content = history.getContent();
+ String markdown = history.getMarkdown();
+ DocumentEntity document = iDocumentService.selectOne(Condition.create().eq("batch_no", history.getBatchNo()).eq("status", DocumentStatusEnum.NORMAL.getValue()));
+ document.setContent(content);
+ document.setMarkdown(markdown);
+ document.setCover("no");
+ iDocumentService.modify(document);
+ return Result.successResult(document);
+ } catch (Exception e) {
+ logger.error(e.getMessage() , e);
+ return Result.failResult("恢复失败!");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @RequestMapping(value = "history/compare/{id}" , method = RequestMethod.POST)
+ @ResponseBody
+ public ModelAndView compare(@PathVariable String id , ModelAndView model) {
+ model.setViewName("member/book/compare");
+ DocumentEntity history = iDocumentService.selectById(id);
+ model.addObject("history", history);
+ model.addObject("document", iDocumentService.selectOne(Condition.create().eq("status", DocumentStatusEnum.NORMAL.getValue()).eq("batch_no", history.getBatchNo())));
+ return model;
+ }
+}
diff --git a/tamguo-bms/src/main/resources/static/fonts/notosans.css b/tamguo-bms/src/main/resources/static/fonts/notosans.css
new file mode 100644
index 0000000..a6b6d74
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/fonts/notosans.css
@@ -0,0 +1,128 @@
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/C7bP6N8yXZ-PGLzbFLtQKRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/iLJc6PpCnnbQjYc1Jq4v0xJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* devanagari */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/5pCv5Yz4eMu9gmvX8nNhfRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+02BC, U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200B-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
+}
+/* greek-ext */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/gEkd0pn-sMtQ_P4HUpi6WBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/iPF-u8L1qkTPHaKjvXERnxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/mTzVK0-EJOCaJiOPeaz-hxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/erE3KsIWUumgD1j_Ca-V-xJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Noto Sans'), local('NotoSans'), url(notosans/v6/LeFlHvsZjXu2c3ZRgBq9nFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
+/* cyrillic-ext */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ16-j2U0lmluP9RWlSytm3ho.woff2) format('woff2');
+ unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
+}
+/* cyrillic */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ15X5f-9o1vgP2EXwfjgl7AY.woff2) format('woff2');
+ unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* devanagari */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ10Tj6bCwSDA5u__Fbjwz3f0.woff2) format('woff2');
+ unicode-range: U+02BC, U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200B-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
+}
+/* greek-ext */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ1xWV49_lSm1NYrwo-zkhivY.woff2) format('woff2');
+ unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ16aRobkAwv3vxw3jMhVENGA.woff2) format('woff2');
+ unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ1_8zf_FOSsgRmwsS7Aa9k2w.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ1z0LW-43aMEzIO6XUTLjad8.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Noto Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Noto Sans Bold'), local('NotoSans-Bold'), url(notosans/v6/PIbvSEyHEdL91QLOQRnZ1-gdm0LZdjqr5-oayXSOefg.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
\ No newline at end of file
diff --git a/tamguo-bms/src/main/resources/static/js/editor.js b/tamguo-bms/src/main/resources/static/js/editor.js
index f006f71..800e93a 100644
--- a/tamguo-bms/src/main/resources/static/js/editor.js
+++ b/tamguo-bms/src/main/resources/static/js/editor.js
@@ -306,7 +306,7 @@ window.documentHistory = function() {
shadeClose: true,
shade: 0.8,
area: ['700px','80%'],
- content: window.historyURL + "?identify=" + window.book.identify + "&doc_id=" + window.selectNode.id,
+ content: window.historyURL + "?id=" + window.selectNode.id,
end : function () {
if(window.SelectedId){
var selected = {node:{
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/editor.css b/tamguo-bms/src/main/resources/static/mergely/editor/editor.css
new file mode 100644
index 0000000..bc784c9
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/editor.css
@@ -0,0 +1,85 @@
+body { margin: 0; }
+#banner { background: transparent url(images/banner.png); width: 33px; height: 30px; position: absolute; left: 3px; top: 3px; }
+.wicked-menu { font-family: 'Noto Sans', sans-serif; margin: 2px 0 2px 40px; }
+.wicked-menu a.link { margin-left: 10px; }
+.ui-widget { font-size:13px; }
+
+/* color dialog */
+#dialog-colors { }
+#dialog-colors label { width: 85px; display: inline-block; font-weight: bold; padding: 5px; }
+#dialog-colors input[type=text] { width: 70px; border: 1px solid #444; float:right; }
+#dialog-colors fieldset { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; border: 1px solid #ccc; width: 222px; padding-right: 15px; }
+
+/* import dialog */
+#dialog-upload label { font-weight: bold; display: inline-block; width: 80px; line-height: 1.5em; }
+.no-title .ui-dialog-titlebar { display:none; }
+.no-title .ui-dialog-content { padding: 0; }
+#file-lhs-progress,
+#file-rhs-progress { height: 22px; width: 240px; vertical-align: middle; line-height: 1.5em; display: none; }
+.progress-label { float: left; width: 100%; color: #fff; font-weight: bold; font-size: .8em; padding-left: 10px; }
+
+/* icons */
+.icon-undo { background-image: url(images/undo.png); }
+.icon-redo { background-image: url(images/redo.png); }
+.icon-save { background-image: url(images/download.png); }
+.icon-check { background-image: url(images/check.png); }
+.icon-import { background-image: url(images/upload.png); }
+.icon-swap { background-image: url(images/swap.png); }
+.icon-arrow-right { background-image: url(images/arrow-right.png); }
+.icon-arrow-right-v { background-image: url(images/arrow-right-v.png); }
+.icon-arrow-right-vv { background-image: url(images/arrow-right-vv.png); }
+.icon-arrow-left-v { background-image: url(images/arrow-left-v.png); }
+.icon-arrow-left-vv { background-image: url(images/arrow-left-vv.png); }
+.icon-arrow-up { background-image: url(images/arrow-up-v.png); }
+.icon-arrow-down { background-image: url(images/arrow-down-v.png); }
+.icon-x-mark { background-image: url(images/x-mark.png); }
+.icon-share { background-image: url(images/share.png); }
+
+
+.tipsy-inner {
+ padding: 8px;
+ text-align: center;
+ max-width: 250px;
+ font-family: arial, sans-serif;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.find {
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ z-index: 4;
+ padding: 10px 20px 10px 10px;
+ background-color: #f5f5f5;
+ float: right;
+ border-left: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ border-bottom-left-radius: 10px;
+ max-height: 26px;
+ -webkit-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
+ -moz-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
+ box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
+ display: none;
+}
+.find > button {
+ padding: 3px 0px;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ height: 25px;
+ width: 26px;
+ vertical-align: top;
+ cursor: pointer;
+}
+.find > button:hover {
+ background-color: #f5f5f5;
+ border: 1px solid #aaa;
+}
+
+.find > button > span.icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ text-align: center;
+ background-position: center center;
+}
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/editor.js b/tamguo-bms/src/main/resources/static/mergely/editor/editor.js
new file mode 100644
index 0000000..96e694c
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/editor.js
@@ -0,0 +1,699 @@
+$(document).ready(function() {
+ function getParameters() {
+ var parameters = {};
+ window.location.search.substr(1).split('&').forEach(function(pair) {
+ if (pair === '') return;
+ var parts = pair.split('=');
+ if (parts.length === 2 && parts[1].search(/^(true|1)$/i) >= 0) {
+ parameters[parts[0]] = true;
+ }
+ else if (parts.length === 2 && parts[1].search(/^(false|0)$/i) >= 0) {
+ parameters[parts[0]] = false;
+ }
+ else parameters[parts[0]] = parts[1] && decodeURIComponent(parts[1].replace(/\+/g, ' '));
+ });
+ return {
+ get: function(name, defaultValue) {
+ if (parameters.hasOwnProperty(name)) return parameters[name];
+ return defaultValue;
+ }
+ };
+ }
+ var parameters = getParameters();
+ if (parameters.get('test', false)) {
+ var li = $('
Tests');
+ var ul = $('');
+ for (var i = 1; i <= 8; ++i) {
+ ul.append($('- Test ' + i + '
'));
+ }
+ li.append(ul);
+ $('#main-menu').append(li);
+ }
+
+ function handleFind(column) {
+ if (!column.length) {
+ return false;
+ }
+ var ed = $('#mergely');
+ var find = column.find('.find');
+ var input = find.find('input[type="text"]');
+ var side = column.attr('id').indexOf('-lhs') > 0 ? 'lhs' : 'rhs';
+ var origautoupdate = ed.mergely('options').autoupdate;
+ find.slideDown('fast', function() {
+ input.focus();
+ // disable autoupdate, clear both sides of diff
+ ed.mergely('options', {autoupdate: false});
+ ed.mergely('unmarkup');
+ });
+ find.find('.find-prev').click(function() {
+ ed.mergely('search', side, input.val(), 'prev');
+ });
+ find.find('.find-next').click(function() {
+ ed.mergely('search', side, input.val(), 'next');
+ });
+ find.find('.find-close').click(function() {
+ find.css('display', 'none')
+ ed.mergely('options', {autoupdate: origautoupdate});
+ });
+
+ input.keydown(function(evt) {
+ if (evt.which != 13 && evt.which != 27) return true;
+ if (evt.which == 27) {
+ find.css('display', 'none');
+ ed.mergely('options', {autoupdate: origautoupdate});
+ }
+ ed.mergely('search', side, input.val());
+ return false;
+ });
+ }
+
+ $(document).keydown(function(event) {
+ if (!( String.fromCharCode(event.which).toLowerCase() == 'f' && event.ctrlKey)) return true;
+ event.preventDefault();
+ var range = window.getSelection().getRangeAt(0);
+ var column = $(range.commonAncestorContainer).parents('.mergely-column');
+ handleFind(column);
+ return false;
+ });
+
+ String.prototype.random = function(length) {
+ var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+ var randomstring = ''
+ for (var i=0; i= 0) {
+ iconconf[id].set(!iconconf[id].get());
+ menu.wickedmenu('update', id);
+ }
+ else if (id == 'edit-left-clear') {
+ ed.mergely('clear', 'lhs');
+ }
+ else if (id == 'edit-right-find') {
+ handleFind(ed.find('#mergely-editor-rhs'));
+ }
+ else if (id == 'edit-right-merge-left') {
+ ed.mergely('mergeCurrentChange', 'lhs');
+ }
+ else if (id == 'edit-right-merge-left-file') {
+ ed.mergely('merge', 'lhs');
+ }
+ else if (id == 'edit-right-clear') {
+ ed.mergely('clear', 'rhs');
+ }
+ else if (id == 'options-colors') {
+ colorSettings(ed);
+ }
+ else if (id == 'view-swap') {
+ ed.mergely('swap');
+ }
+ else if (id == 'view-refresh') {
+ ed.mergely('update');
+ }
+ else if (id == 'view-change-next') {
+ ed.mergely('scrollToDiff', 'next');
+ }
+ else if (id == 'view-change-prev') {
+ ed.mergely('scrollToDiff', 'prev');
+ }
+ else if (id == 'view-clear') {
+ ed.mergely('unmarkup');
+ }
+ else if (id.indexOf('examples-') == 0) {
+ var test_config = {
+ test1: {lhs: 'one\ntwo\nthree', rhs: 'two\nthree'},
+ test2: {lhs: 'two\nthree', rhs: 'one\ntwo\nthree'},
+ test3: {lhs: 'one\nthree', rhs: 'one\ntwo\nthree'},
+ test4: {lhs: 'one\ntwo\nthree', rhs: 'one\nthree'},
+ test5: {lhs: 'to bee, or not to be', rhs: 'to be, or not to bee'},
+ test6: {lhs: 'to be, or not to be z', rhs: 'to be, to be'},
+ test7: {lhs: 'remained, & to assume', rhs: 'and to assume'},
+ test8: {lhs: 'to be, or not to be', rhs: 'to be, or not to be'}
+ };
+ var test = id.split('examples-')[1];
+ ed.mergely('lhs', test_config[test]['lhs']);
+ ed.mergely('rhs', test_config[test]['rhs']);
+ }
+ return false;
+ }
+
+ menu.wickedmenu(menu_opts).bind('selected', function(ev, id) {
+ return handle_operation(id);
+ });
+
+ toolbar.wickedtoolbar({}).bind('selected', function(ev, id) {
+ if (!id) return false;
+ return handle_operation(id.replace(/^tb-/, ''));
+ });
+
+ toolbar.find('li[title]').tipsy({opacity: 1});
+ menu.find('li[title]').tipsy({opacity: 1, delayIn: 1000, gravity: 'w'});
+
+ function handleShare(ed) {
+ var fork = $(this).attr('id') == 'fork';
+ if (key == '') key = ''.random(8);
+ var count = 0;
+ function post_save(side, text) {
+ $.ajax({
+ type: 'POST', async: true, dataType: 'text',
+ url: '/ajax/handle_file.php',
+ data: { 'key': key, 'name': side, 'content': text },
+ success: function (nkey) {
+ ++count;
+ if (count == 2) {
+ var url = '/ajax/handle_save.php?key=' + key;
+ if (fork) url += '&nkey=' + ''.random(8);
+ $.ajax({
+ type: 'GET', async: false, dataType: 'text',
+ url: url,
+ success: function (nkey) {
+ // redirect
+ if (nkey.length) window.location.href = '/' + $.trim(nkey) + '/';
+ },
+ error: function(xhr, ajaxOptions, thrownError){
+ }
+ });
+ }
+ },
+ error: function(xhr, ajaxOptions, thrownError){
+ alert(thrownError);
+ }
+ });
+ }
+ function save_files() {
+ var lhs = ed.mergely('get', 'lhs');
+ var rhs = ed.mergely('get', 'rhs');
+ post_save('lhs', lhs);
+ post_save('rhs', rhs);
+ }
+
+ $( '#dialog-confirm' ).dialog({
+ resizable: false, width: 350, modal: true,
+ buttons: {
+ 'Save for Sharing': function() {
+ $( this ).dialog( 'close' );
+ save_files();
+ },
+ Cancel: function() {
+ $( this ).dialog( 'close' );
+ }
+ }
+ });
+ }
+
+ function crossdomainGET(ed, side, url) {
+ $.ajax({
+ type: 'GET', dataType: 'text',
+ data: {url: url},
+ url: '/ajax/handle_crossdomain.php',
+ contentType: 'text/plain',
+ success: function (response) {
+ ed.mergely(side, response);
+ },
+ error: function(xhr, ajaxOptions, thrownError){
+ console.error('error', xhr, ajaxOptions, thrownError);
+ }
+ });
+ }
+
+ function importFiles(ed) {
+ // -------------
+ // file uploader - html5 file upload to browser
+ function file_load(target, side) {
+ var file = target.files[0];
+ var reader = new FileReader();
+ var $target = $(target);
+ function trigger(name, event) { $target.trigger(name, event); }
+ reader.onloadstart = function(evt) { trigger('start'); }
+ reader.onprogress = function(evt) { trigger('progress', evt); }
+ reader.onload = function(evt) { trigger('loaded', evt.target.result); }
+ reader.onerror = function (evt) {
+ alert(evt.target.error.name);
+ }
+ try {
+ reader.readAsText(file, 'UTF-8');
+ }
+ catch (e) {
+ console.error(e);
+ alert(e);
+ }
+ }
+ var file_data = {};
+ $('#file-lhs, #file-rhs').change(function (evt) {
+ var re = new RegExp('.*[\\\\/](.*)$');
+ var match = re.exec($(this).val());
+ var fname = match ? match[1] : 'unknown';
+
+ var progressbar = $('#' + evt.target.id + '-progress');
+
+ file_load(evt.target);
+ $(evt.target).bind('start', function(ev){
+ $(evt.target).css('display', 'none');
+ progressbar.css('display', 'inline-block');
+ });
+ $(evt.target).bind('progress', function(ev, progress){
+ var loaded = (progress.loaded / progress.total) * 100;
+ progressbar.find('> .progress-label').text(loaded + '%');
+ progressbar.progressbar('value', loaded);
+ });
+ $(evt.target).bind('loaded', function(ev, file){
+ progressbar.progressbar('value', 100);
+ progressbar.find('> .progress-label').text(fname);
+ file_data[evt.target.id] = file;
+ });
+ });
+
+ $('#file-lhs-progress').progressbar({value: 0});
+ $('#file-rhs-progress').progressbar({value: 0});
+ $('#dialog-upload .tabs').tabs();
+ function callbackName(data) {
+ console.log('callbackName', data);
+ }
+ $('#dialog-upload').dialog({
+ dialogClass: 'no-title',
+ resizable: false,
+ width: '450px',
+ modal: true,
+ buttons: {
+ Import: function() {
+ $(this).dialog('close');
+
+ var urls = { lhs: $('#url-lhs').val(), rhs: $('#url-rhs').val() };
+ for (var side in urls) {
+ var url = urls[side];
+ if (!url) continue;
+ crossdomainGET(ed, side, url);
+ }
+
+ if (file_data.hasOwnProperty('file-lhs')) {
+ ed.mergely('lhs', file_data['file-lhs']);
+ }
+ if (file_data.hasOwnProperty('file-rhs')) {
+ ed.mergely('rhs', file_data['file-rhs']);
+ }
+ },
+ Cancel: function() {
+ $(this).dialog('close');
+ }
+ }
+ });
+ }
+ function colorSettings(ed) {
+ // get current settings
+ var sd = $('C');
+ var sa = $('C');
+ var sc = $('C');
+ $('body').append(sd);
+ $('body').append(sa);
+ $('body').append(sc);
+ var conf = {
+ 'c-border': {id: '#c-border', getColor: function() { return sc.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
+ 'c-bg': {id: '#c-bg', getColor: function() { return sc.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
+ 'a-border': {id: '#a-border', getColor: function() { return sa.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
+ 'a-bg': {id: '#a-bg', getColor: function() { return sa.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
+ 'd-border': {id: '#d-border', getColor: function() { return sd.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
+ 'd-bg': {id: '#d-bg', getColor: function() { return sd.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }}
+ };
+ $.each(conf, function(key, item){$(item.id).val(item.getColor()); });
+ var f = $.farbtastic('#picker');
+ $('.colorwell').each(function(){ f.linkTo(this); }).focus(function(){
+ var tthis = $(this);
+ f.linkTo(this);
+ var item = conf[tthis.attr('id')];
+ f.setColor(item.getColor());
+ });
+
+ $('#dialog-colors').dialog({
+ width: 490, modal: true,
+ buttons: {
+ Apply: function() {
+ var cborder = $('#c-border').val();
+ var aborder = $('#a-border').val();
+ var dborder = $('#d-border').val();
+ var abg = $('#a-bg').val();
+ var dbg = $('#d-bg').val();
+ var cbg = $('#c-bg').val();
+ var textCss = makeColorCss(cborder, cbg, aborder, abg, dborder, dbg);
+ applyColorCss(textCss, cborder, cbg, aborder, abg, dborder, dbg, true);
+ },
+ Reset: function() {
+ },
+ Close: function() {
+ $(this).dialog('close');
+ }
+ }
+ });
+ }
+ function makeColorCss(changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground) {
+ var text =
+ '.mergely.a.rhs.start{border-top-color:' + addedBorder + ';}\n\
+ .mergely.a.lhs.start.end,\n\
+ .mergely.a.rhs.end{border-bottom-color:' + addedBorder + ';}\n\
+ .mergely.a.rhs{background-color:' + addedBackground + ';}\n\
+ .mergely.d.lhs{background-color:' + deletedBackground + ';}\n\
+ .mergely.d.lhs.end,\n\
+ .mergely.d.rhs.start.end{border-bottom-color:' + deletedBorder + ';}\n\
+ .mergely.d.rhs.start.end.first{border-top-color:' + deletedBorder + ';}\n\
+ .mergely.d.lhs.start{border-top-color:' + deletedBorder + ';}\n\
+ .mergely.c.lhs,\n\
+ .mergely.c.rhs{background-color:' + changeBackground + ';}\n\
+ .mergely.c.lhs.start,\n\
+ .mergely.c.rhs.start{border-top-color:' + changeBorder + ';}\n\
+ .mergely.c.lhs.end,\n\
+ .mergely.c.rhs.end{border-bottom-color:' + changeBorder + ';}\n\
+ .mergely.ch.a.rhs{background-color:' + addedBackground + ';}\n\
+ .mergely.ch.d.lhs{background-color:' + deletedBackground + ';color: #888;}';
+ return text;
+ }
+ function applyParameterCss(saveState) {
+ var cb = '#' + parameters.get('cb',color_defaults.cb),
+ cg = '#' + parameters.get('cg',color_defaults.cg),
+ ab = '#' + parameters.get('ab',color_defaults.ab),
+ ag = '#' + parameters.get('ag',color_defaults.ag),
+ db = '#' + parameters.get('db',color_defaults.db),
+ dg = '#' + parameters.get('dg',color_defaults.dg);
+ applyColorCss(makeColorCss(cb, cg, ab, ag, db, dg), cb, cg, ab, ag, db, dg, saveState);
+ }
+ function applyColorCss(cssText, changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground, saveState) {
+ $('').appendTo('head');
+ ed.mergely('options', {
+ fgcolor:{a:addedBorder,c:changeBorder,d:deletedBorder}
+ });
+ var params = updateQueryStringParam('cb', changeBorder.replace(/#/g, ''), color_defaults.cb);
+ params = updateQueryStringParam('cg', changeBackground.replace(/#/g, ''), color_defaults.cg, params);
+ params = updateQueryStringParam('ab', addedBorder.replace(/#/g, ''), color_defaults.ab, params);
+ params = updateQueryStringParam('ag', addedBackground.replace(/#/g, ''), color_defaults.ag, params);
+ params = updateQueryStringParam('db', deletedBorder.replace(/#/g, ''), color_defaults.db, params);
+ params = updateQueryStringParam('dg', deletedBackground.replace(/#/g, ''), color_defaults.dg, params);
+
+ if (saveState) {
+ updateHistory(params);
+ }
+ }
+ function updateHistory(params) {
+ var baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
+ window.history.pushState({}, null, baseUrl + params);
+ }
+ // Explicitly save/update a url parameter using HTML5's replaceState().
+ function updateQueryStringParam(key, value, defaultValue, urlQueryString) {
+ urlQueryString = urlQueryString || document.location.search;
+ var parts = urlQueryString.replace(/^\?/, '').split(/&/), found = false;
+ for (var i in parts) {
+ if (parts[i].startsWith(key + '=')) {
+ found = true;
+ if (value === defaultValue) {
+ // value is default value, remove option
+ parts.splice(i, 1);
+ }
+ else {
+ // make new value
+ parts[i] = key + '=' + value;
+ }
+ break;
+ }
+ else if (parts[i].length === 0) {
+ parts.splice(i, 1);
+ break;
+ }
+ }
+ if (!found) {
+ parts.push(key + '=' + value);
+ }
+ return (parts.length) ? '?' + parts.join('&') : '';
+ }
+});
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-down-v.png b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-down-v.png
new file mode 100644
index 0000000..4c0d5eb
Binary files /dev/null and b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-down-v.png differ
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-left-v.png b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-left-v.png
new file mode 100644
index 0000000..fac91b8
Binary files /dev/null and b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-left-v.png differ
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-right-v.png b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-right-v.png
new file mode 100644
index 0000000..5df2466
Binary files /dev/null and b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-right-v.png differ
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-up-v.png b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-up-v.png
new file mode 100644
index 0000000..6d3d95e
Binary files /dev/null and b/tamguo-bms/src/main/resources/static/mergely/editor/images/arrow-up-v.png differ
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/images/download.png b/tamguo-bms/src/main/resources/static/mergely/editor/images/download.png
new file mode 100644
index 0000000..304b6f4
Binary files /dev/null and b/tamguo-bms/src/main/resources/static/mergely/editor/images/download.png differ
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/images/swap.png b/tamguo-bms/src/main/resources/static/mergely/editor/images/swap.png
new file mode 100644
index 0000000..fca21f4
Binary files /dev/null and b/tamguo-bms/src/main/resources/static/mergely/editor/images/swap.png differ
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/lib/farbtastic/farbtastic.css b/tamguo-bms/src/main/resources/static/mergely/editor/lib/farbtastic/farbtastic.css
new file mode 100644
index 0000000..45ad3d5
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/lib/farbtastic/farbtastic.css
@@ -0,0 +1,51 @@
+/**
+ * Farbtastic Color Picker 1.2
+ * © 2008 Steven Wittens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+.farbtastic {
+ position: relative;
+}
+.farbtastic * {
+ position: absolute;
+ cursor: crosshair;
+}
+.farbtastic, .farbtastic .wheel {
+ width: 195px;
+ height: 195px;
+}
+.farbtastic .color, .farbtastic .overlay {
+ top: 47px;
+ left: 47px;
+ width: 101px;
+ height: 101px;
+}
+.farbtastic .wheel {
+ background: url(wheel.png) no-repeat;
+ width: 195px;
+ height: 195px;
+}
+.farbtastic .overlay {
+ background: url(mask.png) no-repeat;
+}
+.farbtastic .marker {
+ width: 17px;
+ height: 17px;
+ margin: -8px 0 0 -8px;
+ overflow: hidden;
+ background: url(marker.png) no-repeat;
+}
+
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/lib/farbtastic/farbtastic.js b/tamguo-bms/src/main/resources/static/mergely/editor/lib/farbtastic/farbtastic.js
new file mode 100644
index 0000000..39d7d14
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/lib/farbtastic/farbtastic.js
@@ -0,0 +1,367 @@
+/**
+ * Farbtastic Color Picker 1.2
+ * © 2008 Steven Wittens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+jQuery.fn.farbtastic = function (callback) {
+ $.farbtastic(this, callback);
+ return this;
+};
+
+jQuery.farbtastic = function (container, callback) {
+ var container = $(container).get(0);
+ return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
+}
+
+jQuery._farbtastic = function (container, callback) {
+ // Store farbtastic object
+ var fb = this;
+
+ // Insert markup
+ $(container).html('');
+ var e = $('.farbtastic', container);
+ fb.wheel = $('.wheel', container).get(0);
+ // Dimensions
+ fb.radius = 84;
+ fb.square = 100;
+ fb.width = 194;
+
+ // Fix background PNGs in IE6
+ if (navigator.appVersion.match(/MSIE [0-6]\./)) {
+ $('*', e).each(function () {
+ if (this.currentStyle.backgroundImage != 'none') {
+ var image = this.currentStyle.backgroundImage;
+ image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
+ $(this).css({
+ 'backgroundImage': 'none',
+ 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
+ });
+ }
+ });
+ }
+
+ /**
+ * Link to the given element(s) or callback.
+ */
+ fb.linkTo = function (callback) {
+ // Unbind previous nodes
+ if (typeof fb.callback == 'object') {
+ $(fb.callback).unbind('keyup', fb.updateValue);
+ }
+
+ // Reset color
+ fb.color = null;
+
+ // Bind callback or elements
+ if (typeof callback == 'function') {
+ fb.callback = callback;
+ }
+ else if (typeof callback == 'object' || typeof callback == 'string') {
+ fb.callback = $(callback);
+ fb.callback.bind('keyup', fb.updateValue);
+ if (fb.callback.get(0).value) {
+ fb.setColor(fb.callback.get(0).value);
+ }
+ }
+ return this;
+ }
+ fb.updateValue = function (event) {
+ if (this.value && this.value != fb.color) {
+ fb.setColor(this.value);
+ }
+ }
+
+ /**
+ * Change color with HTML syntax #123456
+ */
+ fb.setColor = function (color) {
+ var unpack = fb.unpack(color);
+ // JAMIE WAS HERE rgb(r, g, b) modification
+ if (!unpack && color) {
+ color = fb.RGBToHex(color);
+ if (color) unpack = fb.unpack(color);
+ }
+ // JAMIE WAS HERE rgb(r, g, b) modification
+ if (fb.color != color && unpack) {
+ fb.color = color;
+ fb.rgb = unpack;
+ fb.hsl = fb.RGBToHSL(fb.rgb);
+ fb.updateDisplay();
+ }
+ return this;
+ }
+
+ /**
+ * Change color with HSL triplet [0..1, 0..1, 0..1]
+ */
+ fb.setHSL = function (hsl) {
+ fb.hsl = hsl;
+ fb.rgb = fb.HSLToRGB(hsl);
+ fb.color = fb.pack(fb.rgb);
+ fb.updateDisplay();
+ return this;
+ }
+
+ /////////////////////////////////////////////////////
+
+ /**
+ * Retrieve the coordinates of the given event relative to the center
+ * of the widget.
+ */
+ fb.widgetCoords = function (event) {
+ var x, y;
+ var el = event.target || event.srcElement;
+ var reference = fb.wheel;
+
+ if (typeof event.offsetX != 'undefined') {
+ // Use offset coordinates and find common offsetParent
+ var pos = { x: event.offsetX, y: event.offsetY };
+
+ // Send the coordinates upwards through the offsetParent chain.
+ var e = el;
+ while (e) {
+ e.mouseX = pos.x;
+ e.mouseY = pos.y;
+ pos.x += e.offsetLeft;
+ pos.y += e.offsetTop;
+ e = e.offsetParent;
+ }
+
+ // Look for the coordinates starting from the wheel widget.
+ var e = reference;
+ var offset = { x: 0, y: 0 }
+ while (e) {
+ if (typeof e.mouseX != 'undefined') {
+ x = e.mouseX - offset.x;
+ y = e.mouseY - offset.y;
+ break;
+ }
+ offset.x += e.offsetLeft;
+ offset.y += e.offsetTop;
+ e = e.offsetParent;
+ }
+
+ // Reset stored coordinates
+ e = el;
+ while (e) {
+ e.mouseX = undefined;
+ e.mouseY = undefined;
+ e = e.offsetParent;
+ }
+ }
+ else {
+ // Use absolute coordinates
+ var pos = fb.absolutePosition(reference);
+ x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x;
+ y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y;
+ }
+ // Subtract distance to middle
+ return { x: x - fb.width / 2, y: y - fb.width / 2 };
+ }
+
+ /**
+ * Mousedown handler
+ */
+ fb.mousedown = function (event) {
+ // Capture mouse
+ if (!document.dragging) {
+ $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
+ document.dragging = true;
+ }
+
+ // Check which area is being dragged
+ var pos = fb.widgetCoords(event);
+ fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
+
+ // Process
+ fb.mousemove(event);
+ return false;
+ }
+
+ /**
+ * Mousemove handler
+ */
+ fb.mousemove = function (event) {
+ // Get coordinates relative to color picker center
+ var pos = fb.widgetCoords(event);
+
+ // Set new HSL parameters
+ if (fb.circleDrag) {
+ var hue = Math.atan2(pos.x, -pos.y) / 6.28;
+ if (hue < 0) hue += 1;
+ fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
+ }
+ else {
+ var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
+ var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
+ fb.setHSL([fb.hsl[0], sat, lum]);
+ }
+ return false;
+ }
+
+ /**
+ * Mouseup handler
+ */
+ fb.mouseup = function () {
+ // Uncapture mouse
+ $(document).unbind('mousemove', fb.mousemove);
+ $(document).unbind('mouseup', fb.mouseup);
+ document.dragging = false;
+ }
+
+ /**
+ * Update the markers and styles
+ */
+ fb.updateDisplay = function () {
+ // Markers
+ var angle = fb.hsl[0] * 6.28;
+ $('.h-marker', e).css({
+ left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
+ top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
+ });
+
+ $('.sl-marker', e).css({
+ left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
+ top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
+ });
+
+ // Saturation/Luminance gradient
+ $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
+
+ // Linked elements or callback
+ if (typeof fb.callback == 'object') {
+ // Set background/foreground color
+ $(fb.callback).css({
+ backgroundColor: fb.color,
+ color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
+ });
+
+ // Change linked value
+ $(fb.callback).each(function() {
+ if (this.value && this.value != fb.color) {
+ this.value = fb.color;
+ }
+ });
+ }
+ else if (typeof fb.callback == 'function') {
+ fb.callback.call(fb, fb.color);
+ }
+ }
+
+ /**
+ * Get absolute position of element
+ */
+ fb.absolutePosition = function (el) {
+ var r = { x: el.offsetLeft, y: el.offsetTop };
+ // Resolve relative to offsetParent
+ if (el.offsetParent) {
+ var tmp = fb.absolutePosition(el.offsetParent);
+ r.x += tmp.x;
+ r.y += tmp.y;
+ }
+ return r;
+ };
+
+ /* Various color utility functions */
+ fb.pack = function (rgb) {
+ var r = Math.round(rgb[0] * 255);
+ var g = Math.round(rgb[1] * 255);
+ var b = Math.round(rgb[2] * 255);
+ return '#' + (r < 16 ? '0' : '') + r.toString(16) +
+ (g < 16 ? '0' : '') + g.toString(16) +
+ (b < 16 ? '0' : '') + b.toString(16);
+ }
+
+ fb.unpack = function (color) {
+ if (color.length == 7) {
+ return [parseInt('0x' + color.substring(1, 3)) / 255,
+ parseInt('0x' + color.substring(3, 5)) / 255,
+ parseInt('0x' + color.substring(5, 7)) / 255];
+ }
+ else if (color.length == 4) {
+ return [parseInt('0x' + color.substring(1, 2)) / 15,
+ parseInt('0x' + color.substring(2, 3)) / 15,
+ parseInt('0x' + color.substring(3, 4)) / 15];
+ }
+ }
+
+ fb.HSLToRGB = function (hsl) {
+ var m1, m2, r, g, b;
+ var h = hsl[0], s = hsl[1], l = hsl[2];
+ m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
+ m1 = l * 2 - m2;
+ return [this.hueToRGB(m1, m2, h+0.33333),
+ this.hueToRGB(m1, m2, h),
+ this.hueToRGB(m1, m2, h-0.33333)];
+ }
+
+ fb.hueToRGB = function (m1, m2, h) {
+ h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
+ if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
+ if (h * 2 < 1) return m2;
+ if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
+ return m1;
+ }
+
+ // JAMIE WAS HERE
+ fb.RGBToHex = function(color) {
+ var exp = new RegExp(/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3}\s*)\)/i);
+ if(exp.test(color)) {
+ var results = exp.exec(color);
+ var r = parseInt(results[1]).toString(16);
+ var g = parseInt(results[2]).toString(16);
+ var b = parseInt(results[3]).toString(16);
+ if (r.length < 2) r = '0' + r;
+ if (g.length < 2) g = '0' + g;
+ if (b.length < 2) b = '0' + b;
+ return '#' + r + g + b;
+ }
+ }
+ // JAMIE WAS HERE
+
+ fb.RGBToHSL = function (rgb) {
+ var min, max, delta, h, s, l;
+ var r = rgb[0], g = rgb[1], b = rgb[2];
+ min = Math.min(r, Math.min(g, b));
+ max = Math.max(r, Math.max(g, b));
+ delta = max - min;
+ l = (min + max) / 2;
+ s = 0;
+ if (l > 0 && l < 1) {
+ s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
+ }
+ h = 0;
+ if (delta > 0) {
+ if (max == r && max != g) h += (g - b) / delta;
+ if (max == g && max != b) h += (2 + (b - r) / delta);
+ if (max == b && max != r) h += (4 + (r - g) / delta);
+ h /= 6;
+ }
+ return [h, s, l];
+ }
+
+ // Install mousedown handler (the others are set on the document on-demand)
+ $('*', e).mousedown(fb.mousedown);
+
+ // Init color
+ fb.setColor('#000000');
+
+ // Set linked elements/callback
+ if (callback) {
+ fb.linkTo(callback);
+ }
+}
\ No newline at end of file
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/lib/tipsy/jquery.tipsy.js b/tamguo-bms/src/main/resources/static/mergely/editor/lib/tipsy/jquery.tipsy.js
new file mode 100644
index 0000000..c90f259
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/lib/tipsy/jquery.tipsy.js
@@ -0,0 +1,258 @@
+// tipsy, facebook style tooltips for jquery
+// version 1.0.0a
+// (c) 2008-2010 jason frame [jason@onehackoranother.com]
+// released under the MIT license
+
+(function($) {
+
+ function maybeCall(thing, ctx) {
+ return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
+ };
+
+ function isElementInDOM(ele) {
+ while (ele = ele.parentNode) {
+ if (ele == document) return true;
+ }
+ return false;
+ };
+
+ function Tipsy(element, options) {
+ this.$element = $(element);
+ this.options = options;
+ this.enabled = true;
+ this.fixTitle();
+ };
+
+ Tipsy.prototype = {
+ show: function() {
+ var title = this.getTitle();
+ if (title && this.enabled) {
+ var $tip = this.tip();
+
+ $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
+ $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
+ $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
+
+ var pos = $.extend({}, this.$element.offset(), {
+ width: this.$element[0].offsetWidth,
+ height: this.$element[0].offsetHeight
+ });
+
+ var actualWidth = $tip[0].offsetWidth,
+ actualHeight = $tip[0].offsetHeight,
+ gravity = maybeCall(this.options.gravity, this.$element[0]);
+
+ var tp;
+ switch (gravity.charAt(0)) {
+ case 'n':
+ tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+ break;
+ case 's':
+ tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+ break;
+ case 'e':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
+ break;
+ case 'w':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
+ break;
+ }
+
+ if (gravity.length == 2) {
+ if (gravity.charAt(1) == 'w') {
+ tp.left = pos.left + pos.width / 2 - 15;
+ } else {
+ tp.left = pos.left + pos.width / 2 - actualWidth + 15;
+ }
+ }
+
+ $tip.css(tp).addClass('tipsy-' + gravity);
+ $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
+ if (this.options.className) {
+ $tip.addClass(maybeCall(this.options.className, this.$element[0]));
+ }
+
+ if (this.options.fade) {
+ $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
+ } else {
+ $tip.css({visibility: 'visible', opacity: this.options.opacity});
+ }
+ }
+ },
+
+ hide: function() {
+ if (this.options.fade) {
+ this.tip().stop().fadeOut(function() { $(this).remove(); });
+ } else {
+ this.tip().remove();
+ }
+ },
+
+ fixTitle: function() {
+ var $e = this.$element;
+ if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
+ $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
+ }
+ },
+
+ getTitle: function() {
+ var title, $e = this.$element, o = this.options;
+ this.fixTitle();
+ var title, o = this.options;
+ if (typeof o.title == 'string') {
+ title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
+ } else if (typeof o.title == 'function') {
+ title = o.title.call($e[0]);
+ }
+ title = ('' + title).replace(/(^\s*|\s*$)/, "");
+ return title || o.fallback;
+ },
+
+ tip: function() {
+ if (!this.$tip) {
+ this.$tip = $('').html('');
+ this.$tip.data('tipsy-pointee', this.$element[0]);
+ }
+ return this.$tip;
+ },
+
+ validate: function() {
+ if (!this.$element[0].parentNode) {
+ this.hide();
+ this.$element = null;
+ this.options = null;
+ }
+ },
+
+ enable: function() { this.enabled = true; },
+ disable: function() { this.enabled = false; },
+ toggleEnabled: function() { this.enabled = !this.enabled; }
+ };
+
+ $.fn.tipsy = function(options) {
+
+ if (options === true) {
+ return this.data('tipsy');
+ } else if (typeof options == 'string') {
+ var tipsy = this.data('tipsy');
+ if (tipsy) tipsy[options]();
+ return this;
+ }
+
+ options = $.extend({}, $.fn.tipsy.defaults, options);
+
+ function get(ele) {
+ var tipsy = $.data(ele, 'tipsy');
+ if (!tipsy) {
+ tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
+ $.data(ele, 'tipsy', tipsy);
+ }
+ return tipsy;
+ }
+
+ function enter() {
+ var tipsy = get(this);
+ tipsy.hoverState = 'in';
+ if (options.delayIn == 0) {
+ tipsy.show();
+ } else {
+ tipsy.fixTitle();
+ setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
+ }
+ };
+
+ function leave() {
+ var tipsy = get(this);
+ tipsy.hoverState = 'out';
+ if (options.delayOut == 0) {
+ tipsy.hide();
+ } else {
+ setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
+ }
+ };
+
+ if (!options.live) this.each(function() { get(this); });
+
+ if (options.trigger != 'manual') {
+ var binder = options.live ? 'live' : 'bind',
+ eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
+ eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
+ this[binder](eventIn, enter)[binder](eventOut, leave);
+ }
+
+ return this;
+
+ };
+
+ $.fn.tipsy.defaults = {
+ className: null,
+ delayIn: 0,
+ delayOut: 0,
+ fade: false,
+ fallback: '',
+ gravity: 'n',
+ html: false,
+ live: false,
+ offset: 0,
+ opacity: 0.8,
+ title: 'title',
+ trigger: 'hover'
+ };
+
+ $.fn.tipsy.revalidate = function() {
+ $('.tipsy').each(function() {
+ var pointee = $.data(this, 'tipsy-pointee');
+ if (!pointee || !isElementInDOM(pointee)) {
+ $(this).remove();
+ }
+ });
+ };
+
+ // Overwrite this method to provide options on a per-element basis.
+ // For example, you could store the gravity in a 'tipsy-gravity' attribute:
+ // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
+ // (remember - do not modify 'options' in place!)
+ $.fn.tipsy.elementOptions = function(ele, options) {
+ return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
+ };
+
+ $.fn.tipsy.autoNS = function() {
+ return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
+ };
+
+ $.fn.tipsy.autoWE = function() {
+ return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
+ };
+
+ /**
+ * yields a closure of the supplied parameters, producing a function that takes
+ * no arguments and is suitable for use as an autogravity function like so:
+ *
+ * @param margin (int) - distance from the viewable region edge that an
+ * element should be before setting its tooltip's gravity to be away
+ * from that edge.
+ * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
+ * if there are no viewable region edges effecting the tooltip's
+ * gravity. It will try to vary from this minimally, for example,
+ * if 'sw' is preferred and an element is near the right viewable
+ * region edge, but not the top edge, it will set the gravity for
+ * that element's tooltip to be 'se', preserving the southern
+ * component.
+ */
+ $.fn.tipsy.autoBounds = function(margin, prefer) {
+ return function() {
+ var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
+ boundTop = $(document).scrollTop() + margin,
+ boundLeft = $(document).scrollLeft() + margin,
+ $this = $(this);
+
+ if ($this.offset().top < boundTop) dir.ns = 'n';
+ if ($this.offset().left < boundLeft) dir.ew = 'w';
+ if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
+ if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
+
+ return dir.ns + (dir.ew ? dir.ew : '');
+ }
+ };
+
+})(jQuery);
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/lib/tipsy/tipsy.css b/tamguo-bms/src/main/resources/static/mergely/editor/lib/tipsy/tipsy.css
new file mode 100644
index 0000000..da87a22
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/lib/tipsy/tipsy.css
@@ -0,0 +1,25 @@
+.tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; }
+ .tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; }
+
+ /* Rounded corners */
+ .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
+
+ /* Uncomment for shadow */
+ /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/
+
+ .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
+
+ /* Rules to colour arrows */
+ .tipsy-arrow-n { border-bottom-color: #000; }
+ .tipsy-arrow-s { border-top-color: #000; }
+ .tipsy-arrow-e { border-left-color: #000; }
+ .tipsy-arrow-w { border-right-color: #000; }
+
+ .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
+ .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
+ .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
+ .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
+ .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
+ .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
+ .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
+ .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/lib/wicked-ui.css b/tamguo-bms/src/main/resources/static/mergely/editor/lib/wicked-ui.css
new file mode 100644
index 0000000..54734d2
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/lib/wicked-ui.css
@@ -0,0 +1,152 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2013 jamie.peabody@gmail.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/* menu configurable options */
+.wicked-menu { z-index: 7; } /* cm uses index <= 6 */
+.wicked-menu { font-size: 13px; }
+.wicked-menu, .wicked-menu ul, .wicked-menu li > a.menu-item {
+ color: #333; /* text color */
+}
+.wicked-menu li > a { color: #000; text-decoration:none;} /* regular link color */
+.wicked-menu li > a:hover { text-decoration:underline; } /* regular link:hover */
+.wicked-menu > li.hover > a.menu-item,
+.wicked-menu, .wicked-menu ul {
+ background-color: #fff; /* background color */
+}
+.wicked-menu > li.hover,
+.wicked-menu ul li:hover > ul,
+.wicked-menu ul {
+ border: 1px solid #cbcbcb; /* menu border color */
+}
+.wicked-menu li:hover { background: #efefef; } /* hover menu background color */
+.wicked-menu ul,
+.wicked-menu > li.hover,
+.wicked-menu ul li:hover > ul { /* drop shadow */
+ -webkit-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
+ -moz-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
+ box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
+}
+/* -- global settings -- */
+.wicked-menu { margin: 0px; padding: 0px; }
+.wicked-menu, .wicked-menu ul { margin: 0; padding: 0; }
+.wicked-menu li { display: inline-block; list-style-type: none; cursor:pointer; }
+.wicked-menu li > a.menu-item { text-decoration: none; }
+.wicked-menu ul { display: none; }
+.wicked-menu ul li { width: 100%; position: relative; }
+.wicked-menu ul li > a.menu-item > span { padding-left: 10px; }
+
+/* top menu */
+.wicked-menu > li > a > *, .wicked-menu > li { display: inline-block; }
+.wicked-menu li > ul > li > * { padding: 5px; display: inline-block; } /* padding other menu-item */
+.wicked-menu > li > a.menu-item > * { padding: 7px 7px; }
+.wicked-menu > li { position: relative; border: 1px solid transparent; }
+.wicked-menu > li.hover > a.menu-item > * { padding: 7px 7px 3px 7px; }
+.wicked-menu > li.hover > a.menu-item {
+ /* lose the top-level focus indicator on hover */
+ outline: none;
+ position: relative;
+ display: inline-block;
+ z-index: 8;
+}
+
+/* menu items */
+.wicked-menu li.hover > ul,
+.wicked-menu ul li:hover > ul { display: block; position: absolute; }
+.wicked-menu ul li:hover > ul { margin-top: 5px; }
+/* drop menu */
+.wicked-menu ul { z-index: 7; min-width: 210px; top: 2.1em; left: -1px; }
+
+.wicked-menu > li.hover {
+ /* for the top-level menu, after hovering do not show background */
+ background: transparent; position: relative;
+}
+
+.wicked-menu ul > li > a.menu-item { line-height: 2.35em; display:inline-block; width:100%; padding: 0; }
+
+/* menu layout for icons and hotkeys */
+.wicked-menu span.hotkey { float: right; margin-right: 10px; }
+.wicked-menu ul > li > a.menu-item > span.icon {
+padding-left: 31px;
+ background-position: 7px center;
+ background-color: transparent;
+ background-repeat: no-repeat;
+}
+
+.wicked-menu ul li:hover > ul { min-width: 210px; top: 0px; left: 100%; }
+
+.wicked-menu li.separator { border-top: 1px solid #e5e5e5; height: 3px; display: block; line-height: 3em; margin-top: 3px; }
+.wicked-menu li.separator:hover { background: transparent; cursor:default; }
+
+/* -------------------------------------------------------------------------- */
+
+/* toolbar configurable options */
+.wicked-toolbar {
+ background-color: #f5f5f5;
+ height: 30px;
+ border: 1px solid #e5e5e5;
+ border-right: 0;
+ border-left: 0;
+ margin: 0;
+}
+.wicked-toolbar li span {
+ width: 1px;
+ color: transparent;
+ display: inline-block;
+}
+.wicked-toolbar li {
+ height: 22px;
+ width: 28px;
+ margin: 3px;
+ vertical-align: middle;
+ display: inline-block;
+ text-align: center;
+ border: 1px solid transparent;
+}
+.wicked-toolbar li.separator {
+ border-right:1px solid #e5e5e5;
+ width: 1px;
+}
+.wicked-toolbar li.hover {
+ border: 1px solid #ccc;
+ border-radius: 2px;
+ box-shadow: rgba(0, 0, 0, .1) 0 1px 3px 0;
+ -webkit-transition: all 0.25s ease;
+ -moz-transition: all 0.25s ease;
+ -o-transition: all 0.25s ease;
+ transition: all 0.25s ease;
+}
+.wicked-toolbar .icon {
+ width: 16px;
+ height: 16px;
+ background-position: center center;
+ background-color: transparent;
+ background-repeat: no-repeat;
+ vertical-align: middle;
+}
+.wicked-toolbar a {
+ display: block;
+ vertical-align: middle;
+ height: 100%;
+ text-decoration: none;
+}
diff --git a/tamguo-bms/src/main/resources/static/mergely/editor/lib/wicked-ui.js b/tamguo-bms/src/main/resources/static/mergely/editor/lib/wicked-ui.js
new file mode 100644
index 0000000..962bce6
--- /dev/null
+++ b/tamguo-bms/src/main/resources/static/mergely/editor/lib/wicked-ui.js
@@ -0,0 +1,288 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2013 jamie.peabody@gmail.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+;(function( $, window, document, undefined ){
+ var pluginName = 'wickedtoolbar';
+ var SHIFT = new RegExp(/shift/i);
+ var ALT = new RegExp(/alt/i);
+ var CTRL = new RegExp(/ctrl/i);
+ var ARROW_DOWN = new RegExp(/↓/);
+ var ARROW_UP = new RegExp(/↑/);
+ var ARROW_LEFT = new RegExp(/←/);
+ var ARROW_RIGHT = new RegExp(/→/);
+
+ var keys = {
+ shift: 16,
+ alt: 17,
+ ctrl: 18,
+ meta: 91,
+ arrow_up: 38,
+ arrow_down: 40,
+ arrow_left: 37,
+ arrow_right: 39
+ };
+
+ var defaults = {
+ hasIcon: function(id) { },
+ getIcon: function(id) { }
+ };
+
+ function MenuBase(element, options) {
+ var self = this;
+
+ this.element = $(element);
+ this.settings = $.extend({}, defaults, options);
+ this.bindings = [];
+ // for each menu item, modify and wrap in div
+ this.element.find('li').each(function () {
+ var tthis = $(this);
+
+ // since the DOM is modifying wrt to icons, it can match the li[data-cion] from
+ // the HTML definition, or the span.icon from the modified DOM
+ var icons = tthis.closest('ul').find('li[data-icon], span.icon').length > 0;
+
+ var tnode = tthis.contents().filter(function() { return this.nodeType == 3; }).first();
+ var text = tnode.text().trim();
+
+ // remove the text node
+ tnode.remove();
+
+ if (!text || !text.length) return; // not a regular menu item
+
+ // change: - Text
+ // to: -
+ //
+ // Text
+ //
+ //
+ var li = tthis;
+ var div = $('