content module. New description, private and public methods (#175)

* content module. New description, private and public methods

* clear from anchors and covers

* clear from example

* cleared services
This commit is contained in:
khaydarov 2017-03-03 19:39:56 +04:00 committed by Peter Savchenko
parent 83f0407ee2
commit c8808e802b
12 changed files with 57 additions and 327 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -28,7 +28,6 @@ module.exports = (function (editor) {
editor.notifications = require('./modules/notifications');
editor.parser = require('./modules/parser');
editor.sanitizer = require('./modules/sanitizer');
editor.anchors = require('./modules/anchors');
editor.listeners = require('./modules/listeners');
editor.destroyer = require('./modules/destroyer');
editor.paste = require('./modules/paste');

View file

@ -215,15 +215,14 @@
type : 'paragraph',
data : {
text : 'Пишите нам на team@ifmo.su'
},
anchor: 'Update',
}
},
{
type : 'list',
data : {
type : 'OL',
items : [1,3,4]
},
}
}
],
count: 3

View file

@ -2,8 +2,12 @@
* Codex Editor Content Module
* Works with DOM
*
* @module Codex Editor content module
*
* @author Codex Team
* @version 1.3.12
* @version 1.3.13
*
* @description Module works with Elements that have been appended to the main DOM
*/
module.exports = (function (content) {
@ -23,6 +27,7 @@ module.exports = (function (content) {
content.editorAreaHightlighted = null;
/**
* @deprecated
* Synchronizes redactor with original textarea
*/
content.sync = function () {
@ -36,57 +41,10 @@ module.exports = (function (content) {
};
/**
* @deprecated
*/
content.getNodeFocused = function () {
var selection = window.getSelection(),
focused;
if (selection.anchorNode === null) {
return null;
}
if ( selection.anchorNode.nodeType == editor.core.nodeTypes.TAG ) {
focused = selection.anchorNode;
} else {
focused = selection.focusNode.parentElement;
}
if ( !editor.parser.isFirstLevelBlock(focused) ) {
/** Iterate with parent nodes to find first-level*/
var parent = focused.parentNode;
while (parent && !editor.parser.isFirstLevelBlock(parent)) {
parent = parent.parentNode;
}
focused = parent;
}
if (focused != editor.nodes.redactor) {
return focused;
}
return null;
};
/**
* Appends background to the block
*
* @description add CSS class to highlight visually first-level block area
*/
content.markBlock = function () {
@ -96,6 +54,8 @@ module.exports = (function (content) {
/**
* Clear background
*
* @description clears styles that highlights block
*/
content.clearMark = function () {
@ -108,10 +68,13 @@ module.exports = (function (content) {
};
/**
* @private
*
* Finds first-level block
*
* @param {Element} node - selected or clicked in redactors area node
* @protected
*
* @description looks for first-level block.
* gets parent while node is not first-level
*/
content.getFirstLevelBlock = function (node) {
@ -142,7 +105,9 @@ module.exports = (function (content) {
/**
* Trigger this event when working node changed
* @param {Element} targetNode - first-level of this node will be current
* If targetNode is first-level then we set it as current else we look for parents to find first-level
* @protected
*
* @description If targetNode is first-level then we set it as current else we look for parents to find first-level
*/
content.workingNodeChanged = function (targetNode) {
@ -185,27 +150,6 @@ module.exports = (function (content) {
}
/**
* Check is this block was in feed
* If true, than set switched block also covered
*/
if (targetBlock.classList.contains(editor.ui.className.BLOCK_IN_FEED_MODE)) {
newBlock.classList.add(editor.ui.className.BLOCK_IN_FEED_MODE);
}
if (targetBlock.classList.contains(editor.ui.className.BLOCK_WITH_ANCHOR)) {
newBlock.classList.add(editor.ui.className.BLOCK_WITH_ANCHOR);
}
/**
* Saving anchor
*/
newBlock.dataset.anchor = targetBlock.dataset.anchor;
/** Replacing */
editor.nodes.redactor.replaceChild(newBlock, targetBlock);
@ -227,7 +171,7 @@ module.exports = (function (content) {
};
/**
* @private
* @protected
*
* Inserts new block to redactor
* Wrapps block into a DIV with BLOCK_CLASSNAME class
@ -243,23 +187,9 @@ module.exports = (function (content) {
var workingBlock = editor.content.currentNode,
newBlockContent = blockData.block,
blockType = blockData.type,
cover = blockData.cover,
anchor = blockData.anchor,
isStretched = blockData.stretched;
var newBlock = editor.content.composeNewBlock(newBlockContent, blockType, isStretched, anchor);
if (cover === true) {
newBlock.classList.add(editor.ui.className.BLOCK_IN_FEED_MODE);
}
if (anchor) {
newBlock.classList.add(editor.ui.className.BLOCK_WITH_ANCHOR);
}
var newBlock = composeNewBlock_(newBlockContent, blockType, isStretched);
if (workingBlock) {
@ -348,7 +278,7 @@ module.exports = (function (content) {
content.switchBlock = function (blockToReplace, newBlock, tool) {
tool = tool || editor.content.currentNode.dataset.tool;
var newBlockComposed = editor.content.composeNewBlock(newBlock, tool);
var newBlockComposed = composeNewBlock_(newBlock, tool);
/** Replacing */
editor.content.replaceBlock(blockToReplace, newBlockComposed);
@ -360,7 +290,8 @@ module.exports = (function (content) {
/**
* Iterates between child noted and looking for #text node on deepest level
* @private
* @protected
*
* @param {Element} block - node where find
* @param {int} postiton - starting postion
* Example: childNodex.length to find from the end
@ -452,8 +383,13 @@ module.exports = (function (content) {
/**
* @private
* @param {Element} block - current plugins render
* @param {String} tool - plugins name
* @param {Boolean} isStretched - make stretched block or not
*
* @description adds necessary information to wrap new created block by first-level holder
*/
content.composeNewBlock = function (block, tool, isStretched, anchor) {
var composeNewBlock_ = function (block, tool, isStretched) {
var newBlock = editor.draw.node('DIV', editor.ui.className.BLOCK_CLASSNAME, {}),
blockContent = editor.draw.node('DIV', editor.ui.className.BLOCK_CONTENT, {});
@ -468,13 +404,13 @@ module.exports = (function (content) {
}
newBlock.dataset.tool = tool;
newBlock.dataset.anchor = anchor || '';
return newBlock;
};
/**
* Returns Range object of current selection
* @protected
*/
content.getRange = function () {
@ -486,8 +422,12 @@ module.exports = (function (content) {
/**
* Divides block in two blocks (after and before caret)
* @private
* @param {Int} inputIndex - target input index
*
* @protected
* @param {int} inputIndex - target input index
*
* @description splits current input content to the separate blocks
* When enter is pressed among the words, that text will be splited.
*/
content.splitBlock = function (inputIndex) {
@ -594,6 +534,12 @@ module.exports = (function (content) {
/**
* Merges two blocks current and target
* If target index is not exist, then previous will be as target
*
* @protected
* @param {int} currentInputIndex
* @param {int} targetInputIndex
*
* @description gets two inputs indexes and merges into one
*/
content.mergeBlocks = function (currentInputIndex, targetInputIndex) {
@ -622,7 +568,7 @@ module.exports = (function (content) {
};
/**
* @private
* @deprecated
*
* Callback for HTML Mutations
* @param {Array} mutation - Mutation Record
@ -645,7 +591,7 @@ module.exports = (function (content) {
};
/**
* @private
* @deprecated
*
* gets only text/plain content of node
* @param {Element} target - HTML node
@ -680,7 +626,7 @@ module.exports = (function (content) {
};
/**
* @private
* @deprecated
*
* Sanitizes HTML content
* @param {Element} target - inserted element

View file

@ -149,9 +149,7 @@ module.exports = (function (renderer) {
/** New parser */
var block,
tool = toolData.tool,
pluginName = tool.type,
anchor = tool.anchor,
cover = tool.cover;
pluginName = tool.type;
/** Get first key of object that stores plugin name */
// for (var pluginName in blockData) break;
@ -195,9 +193,7 @@ module.exports = (function (renderer) {
return {
type : pluginName,
block : block,
stretched : stretched,
cover : cover,
anchor : anchor
stretched : stretched
};
};

View file

@ -86,8 +86,7 @@ module.exports = (function (saver) {
saver.makeFormDataFromBlocks = function (block) {
var pluginName = block.dataset.tool,
anchor = block.dataset.anchor;
var pluginName = block.dataset.tool;
/** Check for plugin existance */
if (!editor.tools[pluginName]) {
@ -108,22 +107,17 @@ module.exports = (function (saver) {
pluginsContent = blockContent.childNodes[0],
savedData,
position,
output,
coverFlag = false;
output;
/** If plugin wasn't available then return data from cache */
if ( editor.tools[pluginName].available === false ) {
position = pluginsContent.dataset.inputPosition;
savedData = codex.editor.state.blocks.items[position].data;
coverFlag = codex.editor.state.blocks.items[position].cover;
anchor = codex.editor.state.blocks.items[position].anchor;
} else {
savedData = editor.tools[pluginName].save(pluginsContent);
coverFlag = block.classList.contains(editor.ui.className.BLOCK_IN_FEED_MODE);
if (editor.tools[pluginName].validate) {
@ -141,13 +135,9 @@ module.exports = (function (saver) {
output = {
type : pluginName,
anchor : anchor,
data : savedData
};
/** Marks Blocks that will be in main page */
output.cover = coverFlag;
editor.state.jsonOutput.push(output);
};

View file

@ -13,8 +13,6 @@ module.exports = (function (settings) {
settings.setting = null;
settings.actions = null;
settings.cover = null;
/**
* Append and open settings
*/
@ -27,7 +25,7 @@ module.exports = (function (settings) {
if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings ) {
editor.core.log(`Plugin «${toolType}» has no settings`, 'warn');
// editor.nodes.pluginSettings.innerHTML = `Плагин «${toolType}» не имеет настроек`;
editor.nodes.pluginSettings.innerHTML = `Плагин «${toolType}» не имеет настроек`;
} else {
@ -42,7 +40,6 @@ module.exports = (function (settings) {
/** Open settings block */
editor.nodes.blockSettings.classList.add('opened');
editor.toolbar.settings.addDefaultSettings();
this.opened = true;
};
@ -67,7 +64,6 @@ module.exports = (function (settings) {
if ( !this.opened ) {
this.open(toolType);
editor.anchors.settingsOpened(editor.content.currentNode);
} else {
@ -77,125 +73,6 @@ module.exports = (function (settings) {
};
/**
* This function adds default core settings
*/
settings.addDefaultSettings = function () {
/** list of default settings */
var feedModeToggler,
anchorInput;
/** Clear block and append initialized settings */
editor.nodes.defaultSettings.innerHTML = '';
/** Init all default setting buttons */
feedModeToggler = editor.toolbar.settings.makeFeedModeToggler();
anchorInput = editor.toolbar.settings.makeAnchorInput();
/**
* Fill defaultSettings
*/
/**
* Input for anchor for block
*/
editor.nodes.defaultSettings.appendChild(anchorInput);
/**
* Button that enables/disables Feed-mode
* Feed-mode means that block will be showed in articles-feed like cover
*/
editor.nodes.defaultSettings.appendChild(feedModeToggler);
};
/**
* Cover setting.
* This tune highlights block, so that it may be used for showing target block on main page
* Draw different setting when block is marked for main page
* If TRUE, then we show button that removes this selection
* Also defined setting "Click" events will be listened and have separate callbacks
*
* @return {Element} node/button that we place in default settings block
*/
settings.makeFeedModeToggler = function () {
var isFeedModeActivated = editor.toolbar.settings.isFeedModeActivated(),
setting,
data;
if (!isFeedModeActivated) {
data = {
innerHTML : '<i class="ce-icon-newspaper"></i>Вывести в ленте'
};
} else {
data = {
innerHTML : '<i class="ce-icon-newspaper"></i>Не выводить в ленте'
};
}
setting = editor.draw.node('DIV', editor.ui.className.SETTINGS_ITEM, data);
editor.listeners.add(setting, 'click', editor.toolbar.settings.updateFeedMode, false);
return setting;
};
/**
* Updates Feed-mode
*/
settings.updateFeedMode = function () {
var currentNode = editor.content.currentNode;
currentNode.classList.toggle(editor.ui.className.BLOCK_IN_FEED_MODE);
editor.toolbar.settings.close();
};
settings.isFeedModeActivated = function () {
var currentBlock = editor.content.currentNode;
if (currentBlock) {
return currentBlock.classList.contains(editor.ui.className.BLOCK_IN_FEED_MODE);
} else {
return false;
}
};
settings.makeAnchorInput = function () {
var anchorWrapper = editor.draw.node('div', 'ce-settings__anchor-wrapper ce-settings__item', {}),
hash = editor.draw.node('i', 'ce-settings__anchor-hash', {}),
anchor = editor.draw.node('input', 'ce-settings__anchor-input', { placeholder: 'Якорь' });
editor.listeners.add(anchor, 'keydown', editor.anchors.keyDownOnAnchorInput );
editor.listeners.add(anchor, 'keyup', editor.anchors.keyUpOnAnchorInput );
editor.listeners.add(anchor, 'input', editor.anchors.anchorChanged );
editor.listeners.add(anchor, 'blur', editor.anchors.anchorChanged );
anchorWrapper.appendChild(hash);
anchorWrapper.appendChild(anchor);
editor.anchors.input = anchor;
return anchorWrapper;
};
/**
* Here we will draw buttons and add listeners to components
*/

View file

@ -34,16 +34,6 @@ module.exports = (function (ui) {
*/
BLOCK_HIGHLIGHTED : 'ce-block--focused',
/**
* @const {String} - highlights covered blocks
*/
BLOCK_IN_FEED_MODE : 'ce-block--feed-mode',
/**
* @const {String} - Block with anchor
*/
BLOCK_WITH_ANCHOR : 'ce-block--anchor',
/**
* @const {String} - for all default settings
*/
@ -296,8 +286,6 @@ module.exports = (function (ui) {
}
editor.toolbar.settings.addDefaultSettings();
};
/**

View file

@ -1,6 +1,6 @@
{
"name": "codex.editor",
"version": "1.5.7",
"version": "1.5.8",
"description": "Codex Editor. Native JS, based on API and Open Source",
"main": "index.js",
"scripts": {

View file

@ -48,76 +48,11 @@ var embed = function(embed_plugin){
};
var services = {
vimeo: {
regex: /(?:http[s]?:\/\/)?(?:www.)?vimeo\.co(?:.+\/([^\/]\d+)(?:#t=[\d]+)?s?$)/,
html: "<iframe src=\"https://player.vimeo.com/video/<%= remote_id %>?title=0&byline=0\" style=\"width:100%;\" height=\"320\" frameborder=\"0\"></iframe>",
height: 320,
width: 580
},
youtube: {
regex: /^.*(?:(?:youtu\.be\/)|(?:youtube\.com)\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*)(?:[\?\&]t\=(\d*)|)/,
html: "<iframe src=\"https://www.youtube.com/embed/<%= remote_id %>\" style=\"width:100%;\" height=\"320\" frameborder=\"0\" allowfullscreen></iframe>",
height: 320,
width: 580
},
vk : {
regex: /^https?.+vk?.com\/feed\?w=wall\d+_\d+/,
html: "<iframe src=\"https://tjournal.ru/proxy/video/<%= remote_id %>?rel=0&showinfo=0&enablejsapi=1&autoplay=1\" width=\"580\" height=\"320\" frameborder=\"0\" allowfullscreen></iframe>"
},
coub: {
regex: /https?:\/\/coub\.com\/view\/([^\/\?\&]+)/,
html: "<iframe src=\"//coub.com/embed/<%= remote_id %>\" style=\"width:100%;\" height=\"320\" frameborder=\"0\" allowfullscreen></iframe>",
height: 320,
width: 580
},
vine: {
regex: /https?:\/\/vine\.co\/v\/([^\/\?\&]+)/,
html: "<iframe src=\"https://vine.co/v/<%= remote_id %>/embed/simple/\" style=\"width:100%;\" height=\"320\" frameborder=\"0\" allowfullscreen></iframe>",
height: 320,
width: 580
},
imgur: {
regex: /https?:\/\/(?:i\.)?imgur\.com.*\/([a-zA-Z0-9]+)(?:\.gifv)?/,
html: "<iframe allowfullscreen=\"true\" scrolling=\"no\" src=\"http://imgur.com/<%= remote_id %>/embed\" id=\"imgur-embed-iframe-pub-<%= remote_id %>\" class=\"imgur-embed-iframe-pub\" style=\"height: 500px; width: 100%; border: 1px solid #000\"></iframe>",
height: 500,
width: 540
},
gfycat: {
regex: /https?:\/\/gfycat\.com(?:\/detail)?\/([a-zA-Z]+)/,
html: "<iframe src='https://gfycat.com/ifr/<%= remote_id %>' frameborder='0' scrolling='no' style=\"width:100%;\" height='436' allowfullscreen ></iframe>",
height: 436,
width: 580
},
'twitch-channel': {
regex: /https?:\/\/www.twitch.tv\/([^\/\?\&]*)/,
html: "<iframe src=\"https://player.twitch.tv/?channel=<%= remote_id %>\" frameborder=\"0\" allowfullscreen=\"true\" scrolling=\"no\" height=\"366\" style=\"width:100%;\"></iframe>",
height: 366,
width: 600
},
'twitch-video': {
regex: /https?:\/\/www.twitch.tv\/(?:[^\/\?\&]*\/v|videos)\/([0-9]*)/,
html: "<iframe src=\"https://player.twitch.tv/?video=v<%= remote_id %>\" frameborder=\"0\" allowfullscreen=\"true\" scrolling=\"no\" height=\"366\" style=\"width:100%;\"></iframe>",
height: 366,
width: 600
},
'yandex-music-album': {
regex: /https?:\/\/music.yandex.ru\/album\/([0-9]*)/,
html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:400px;\" style=\"width:100%;\" height=\"400\" src=\"https://music.yandex.ru/iframe/#album/<%= remote_id %>/\"></iframe>",
height: 400,
width: 540
},
'yandex-music-track': {
regex: /https?:\/\/music.yandex.ru\/album\/([0-9]*)\/track\/([0-9]*)/,
html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:100px;\" style=\"width:100%;\" height=\"100\" src=\"https://music.yandex.ru/iframe/#track/<%= remote_id %>/\"></iframe>",
height: 100,
width: 540
},
'yandex-music-playlist': {
regex: /https?:\/\/music.yandex.ru\/users\/([^\/\?\&]*)\/playlists\/([0-9]*)/,
html: "<iframe frameborder=\"0\" style=\"border:none;width:540px;height:400px;\" width=\"540\" height=\"400\" src=\"https://music.yandex.ru/iframe/#playlist/<%= remote_id %>/show/cover/description/\"></iframe>",
height: 400,
width: 540
}
};

File diff suppressed because one or more lines are too long