Browse Source

Wysiwyg editor

Vova Tkach 5 years ago
parent
commit
7a53fcca9e

+ 10 - 0
assets/assets.go

@@ -42,4 +42,14 @@ func PopulateResources(res *resource.Resource) {
 		"text/css",
 		SysStylesCss,
 	)
+	res.Add(
+		consts.AssetsCpWysiwygPellJs,
+		"application/javascript; charset=utf-8",
+		CpWysiwygPellJs,
+	)
+	res.Add(
+		consts.AssetsCpWysiwygPellCss,
+		"text/css",
+		CpWysiwygPellCss,
+	)
 }

+ 31 - 0
assets/cp.wysiwyg.pell.css

@@ -0,0 +1,31 @@
+.pell {
+	border: 1px solid rgba(10, 10, 10, 0.1);
+	box-sizing: border-box;
+}
+
+.pell-content {
+	box-sizing: border-box;
+	height: 300px;
+	outline: 0;
+	overflow-y: auto;
+	padding: 10px;
+}
+
+.pell-actionbar {
+	background-color: #FFF;
+	border-bottom: 1px solid rgba(10, 10, 10, 0.1);
+}
+
+.pell-button {
+	background-color: transparent;
+	border: none;
+	cursor: pointer;
+	height: 30px;
+	outline: 0;
+	width: 30px;
+	vertical-align: bottom;
+}
+
+.pell-button-selected {
+	background-color: #F0F0F0;
+}

+ 3 - 0
assets/cp.wysiwyg.pell.css.go

@@ -0,0 +1,3 @@
+package assets
+
+var CpWysiwygPellCss = []byte(`.pell{border:1px solid hsla(0,0%,4%,.1)}.pell,.pell-content{box-sizing:border-box}.pell-content{height:300px;outline:0;overflow-y:auto;padding:10px}.pell-actionbar{background-color:#fff;border-bottom:1px solid hsla(0,0%,4%,.1)}.pell-button{background-color:transparent;border:none;cursor:pointer;height:30px;outline:0;width:30px;vertical-align:bottom}.pell-button-selected{background-color:#f0f0f0}`)

+ 224 - 0
assets/cp.wysiwyg.pell.js

@@ -0,0 +1,224 @@
+(function (global, factory) {
+	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+	typeof define === 'function' && define.amd ? define(['exports'], factory) :
+	(factory((global.pell = {})));
+}(this, (function (exports) { 'use strict';
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var defaultParagraphSeparatorString = 'defaultParagraphSeparator';
+var formatBlock = 'formatBlock';
+var addEventListener = function addEventListener(parent, type, listener) {
+	return parent.addEventListener(type, listener);
+};
+var appendChild = function appendChild(parent, child) {
+	return parent.appendChild(child);
+};
+var createElement = function createElement(tag) {
+	return document.createElement(tag);
+};
+var queryCommandState = function queryCommandState(command) {
+	return document.queryCommandState(command);
+};
+var queryCommandValue = function queryCommandValue(command) {
+	return document.queryCommandValue(command);
+};
+
+var exec = function exec(command) {
+	var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+	return document.execCommand(command, false, value);
+};
+
+var defaultActions = {
+	bold: {
+		icon: '<b>B</b>',
+		title: 'Bold',
+		state: function state() {
+			return queryCommandState('bold');
+		},
+		result: function result() {
+			return exec('bold');
+		}
+	},
+	italic: {
+		icon: '<i>I</i>',
+		title: 'Italic',
+		state: function state() {
+			return queryCommandState('italic');
+		},
+		result: function result() {
+			return exec('italic');
+		}
+	},
+	underline: {
+		icon: '<u>U</u>',
+		title: 'Underline',
+		state: function state() {
+			return queryCommandState('underline');
+		},
+		result: function result() {
+			return exec('underline');
+		}
+	},
+	strikethrough: {
+		icon: '<strike>S</strike>',
+		title: 'Strike-through',
+		state: function state() {
+			return queryCommandState('strikeThrough');
+		},
+		result: function result() {
+			return exec('strikeThrough');
+		}
+	},
+	heading1: {
+		icon: '<b>H<sub>1</sub></b>',
+		title: 'Heading 1',
+		result: function result() {
+			return exec(formatBlock, '<h1>');
+		}
+	},
+	heading2: {
+		icon: '<b>H<sub>2</sub></b>',
+		title: 'Heading 2',
+		result: function result() {
+			return exec(formatBlock, '<h2>');
+		}
+	},
+	paragraph: {
+		icon: '&#182;',
+		title: 'Paragraph',
+		result: function result() {
+			return exec(formatBlock, '<p>');
+		}
+	},
+	quote: {
+		icon: '&#8220; &#8221;',
+		title: 'Quote',
+		result: function result() {
+			return exec(formatBlock, '<blockquote>');
+		}
+	},
+	olist: {
+		icon: '&#35;',
+		title: 'Ordered List',
+		result: function result() {
+			return exec('insertOrderedList');
+		}
+	},
+	ulist: {
+		icon: '&#8226;',
+		title: 'Unordered List',
+		result: function result() {
+			return exec('insertUnorderedList');
+		}
+	},
+	code: {
+		icon: '&lt;/&gt;',
+		title: 'Code',
+		result: function result() {
+			return exec(formatBlock, '<pre>');
+		}
+	},
+	line: {
+		icon: '&#8213;',
+		title: 'Horizontal Line',
+		result: function result() {
+			return exec('insertHorizontalRule');
+		}
+	},
+	link: {
+		icon: '&#128279;',
+		title: 'Link',
+		result: function result() {
+			var url = window.prompt('Enter the link URL');
+			if (url) exec('createLink', url);
+		}
+	},
+	image: {
+		icon: '&#128247;',
+		title: 'Image',
+		result: function result() {
+			var url = window.prompt('Enter the image URL');
+			if (url) exec('insertImage', url);
+		}
+	}
+};
+
+var defaultClasses = {
+	actionbar: 'pell-actionbar',
+	button: 'pell-button',
+	content: 'pell-content',
+	selected: 'pell-button-selected'
+};
+
+var init = function init(settings) {
+	var actions = settings.actions ? settings.actions.map(function (action) {
+		if (typeof action === 'string') return defaultActions[action];else if (defaultActions[action.name]) return _extends({}, defaultActions[action.name], action);
+		return action;
+	}) : Object.keys(defaultActions).map(function (action) {
+		return defaultActions[action];
+	});
+
+	var classes = _extends({}, defaultClasses, settings.classes);
+
+	var defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div';
+
+	var actionbar = createElement('div');
+	actionbar.className = classes.actionbar;
+	appendChild(settings.element, actionbar);
+
+	var content = settings.element.content = createElement('div');
+	content.contentEditable = true;
+	content.className = classes.content;
+	content.oninput = function (_ref) {
+		var firstChild = _ref.target.firstChild;
+
+		if (firstChild && firstChild.nodeType === 3) exec(formatBlock, '<' + defaultParagraphSeparator + '>');else if (content.innerHTML === '<br>') content.innerHTML = '';
+		settings.onChange(content.innerHTML);
+	};
+	content.onkeydown = function (event) {
+		if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
+			setTimeout(function () {
+				return exec(formatBlock, '<' + defaultParagraphSeparator + '>');
+			}, 0);
+		}
+	};
+	appendChild(settings.element, content);
+
+	actions.forEach(function (action) {
+		var button = createElement('button');
+		button.className = classes.button;
+		button.innerHTML = action.icon;
+		button.title = action.title;
+		button.setAttribute('type', 'button');
+		button.onclick = function () {
+			return action.result() && content.focus();
+		};
+
+		if (action.state) {
+			var handler = function handler() {
+				return button.classList[action.state() ? 'add' : 'remove'](classes.selected);
+			};
+			addEventListener(content, 'keyup', handler);
+			addEventListener(content, 'mouseup', handler);
+			addEventListener(button, 'click', handler);
+		}
+
+		appendChild(actionbar, button);
+	});
+
+	if (settings.styleWithCSS) exec('styleWithCSS');
+	exec(defaultParagraphSeparatorString, defaultParagraphSeparator);
+
+	return settings.element;
+};
+
+var pell = { exec: exec, init: init };
+
+exports.exec = exec;
+exports.init = init;
+exports['default'] = pell;
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+})));

File diff suppressed because it is too large
+ 2 - 0
assets/cp.wysiwyg.pell.js.go


+ 5 - 1
consts/consts.go

@@ -5,7 +5,7 @@ import (
 )
 
 const ServerVersion = "1.0.5"
-const AssetsVersion = "21"
+const AssetsVersion = "22"
 const AssetsPath = "assets"
 const DirIndexFile = "index.html"
 
@@ -24,6 +24,10 @@ const AssetsSysLogoPng = AssetsPath + "/sys/logo.png"
 const AssetsSysLogoSvg = AssetsPath + "/sys/logo.svg"
 const AssetsSysStylesCss = AssetsPath + "/sys/styles.css"
 
+// Wysiwyg editor
+const AssetsCpWysiwygPellJs = AssetsPath + "/cp/wysiwyg/pell.js"
+const AssetsCpWysiwygPellCss = AssetsPath + "/cp/wysiwyg/pell.css"
+
 // Make global for other packages
 var ParamHost string
 var ParamPort int

Some files were not shown because too many files changed in this diff