fairycat

Created:
Updated:
Fairycat

Simditor编辑器,首行缩进功能

最近尝试使用Simditor编辑器,想使用段落首行缩进,没找到这个动能。所以用该编辑器自带的向右缩进功能作为参照,做出了首行缩进的插件。

想要让首行缩进的样式不被过滤掉,在编辑器的设置里边需要给P标签添加text-indent,设置项为allowedStyles。具体设置方法可以查看Simditor官方网站。

设置允许样式的时候,要保留编辑器默认的设置。p标签的默认样式有左边距和对齐方式:

this._allowedStyles = $.extend({
  ...,
  p: ['margin-left', 'text-align'],
  ...,
}, this.opts.allowedStyles);

那么,在建立编辑器时的设置,p标签允许的样式再添加一项,text-indent。三个都写全才行。还有,在工具栏添加相应的按钮。按钮的命名在插件js文件中定义。

new Simditor({
  ...,
  allowedStyles: {
    ...,
    p: ['margin-left', 'text-align', 'text-indent']
    ...,
  },
  toolbar: [
    ...,
    'indentfl',
    'indentfr',
    ...,
  ],
  ...,
});

允许的样式和工具栏按钮已经设置好了,可以添加插件了。插件js文件,在引入编辑器主文件之后任意位置引入就行了。

以下是插件js文件,我给它取文件名为simditor-indentfirstline.js:

(function() {
    var SimditorIndentfl,SimditorIndentfr,
    hasProp = {}.hasOwnProperty,
    extend = function(child, parent) {
        for (var key in parent) {
            if (hasProp.call(parent, key)) child[key] = parent[key];
        }
        function ctor() {
            this.constructor = child;
        }
        ctor.prototype = parent.prototype;
        child.prototype = new ctor();
        child.__super__ = parent.prototype;
        return child;
    };

    SimditorIndentfr = (function(superClass) {
        extend(SimditorIndentfr, superClass);

        function SimditorIndentfr() {
            return SimditorIndentfr.__super__.constructor.apply(this, arguments);
        }

        SimditorIndentfr.prototype.name = 'indentfr';

        SimditorIndentfr.prototype.title = 'indentfr';

        SimditorIndentfr.prototype.icon = 'indentfr';

        SimditorIndentfr.prototype.opts = {
                indentWidth: 2,
                indentUnit: 'em'
        };

        SimditorIndentfr.prototype._init = function() {
            SimditorIndentfr.__super__._init.apply(this, arguments);
            return this.setIcon("angle-double-right");
        };

        SimditorIndentfr.prototype.setIcon = function(icon) {
            return this.el.find("span").removeClass().addClass("fa fa-" + icon);
        };

        SimditorIndentfr.prototype.command = function() {
            var $blockNodes, $endNodes, $startNodes, nodes, result;
            $startNodes = this.editor.selection.startNodes();
            $endNodes = this.editor.selection.endNodes();
            $blockNodes = this.editor.selection.blockNodes();
            nodes = [];
            $blockNodes = $blockNodes.each(function(i, node) {
                var include, j, k, len, n;
                include = true;
                for (j = k = 0, len = nodes.length; k < len; j = ++k) {
                    n = nodes[j];
                    if ($.contains(node, n)) {
                        include = false;
                        break;
                    } else if ($.contains(n, node)) {
                        nodes.splice(j, 1, node);
                        include = false;
                        break;
                    }
                }
                if (include) {
                    return nodes.push(node);
                }
            });
            $blockNodes = $(nodes);
            result = false;
            $blockNodes.each((function(_this) {
                return function(i, blockEl) {
                    var r;
                    r = _this.indentBlock(blockEl);
                    if (r) {
                        return result = r;
                    }
                };
            })(this));
            return result;
        }

        SimditorIndentfr.prototype.indentBlock = function(blockEl) {
            var $blockEl, $childList, $nextTd, $nextTr, $parentLi, $pre, $td, $tr, marginLeft, tagName;
            $blockEl = $(blockEl);
            if (!$blockEl.length) {
                return;
            }
            if ($blockEl.is('p, h1, h2, h3, h4')) {
                $blockEl.css('text-indent', this.opts.indentWidth+this.opts.indentUnit);
            } else {
                return false;
            }
            return true;
        }

        SimditorIndentfr.prototype.indentText = function(range) {
            var text, textNode;
            text = range.toString().replace(/^(?=.+)/mg, '\u00A0\u00A0');
            textNode = document.createTextNode(text || '\u00A0\u00A0');
            range.deleteContents();
            range.insertNode(textNode);
            if (text) {
                range.selectNode(textNode);
                return this.editor.selection.range(range);
            } else {
                return this.editor.selection.setRangeAfter(textNode);
            }
        };

        return SimditorIndentfr;

    })(Simditor.Button);

    SimditorIndentfl = (function(superClass) {
        extend(SimditorIndentfl, superClass);

        function SimditorIndentfl() {
            return SimditorIndentfl.__super__.constructor.apply(this, arguments);
        }

        SimditorIndentfl.prototype.name = 'indentfl';

        SimditorIndentfl.prototype.title = 'indentfl';

        SimditorIndentfl.prototype.icon = 'indentfl';

        SimditorIndentfl.prototype.opts = {
                indentWidth: 2,
                indentUnit: 'em'
        };

        SimditorIndentfl.prototype._init = function() {
            SimditorIndentfl.__super__._init.apply(this, arguments);
            return this.setIcon("angle-double-left");
        };

        SimditorIndentfl.prototype.setIcon = function(icon) {
            return this.el.find("span").removeClass().addClass("fa fa-" + icon);
        };

        SimditorIndentfl.prototype.command = function() {
            var $blockNodes, $endNodes, $startNodes, nodes, result;
            $startNodes = this.editor.selection.startNodes();
            $endNodes = this.editor.selection.endNodes();
            $blockNodes = this.editor.selection.blockNodes();
            nodes = [];
            $blockNodes = $blockNodes.each(function(i, node) {
                var include, j, k, len, n;
                include = true;
                for (j = k = 0, len = nodes.length; k < len; j = ++k) {
                    n = nodes[j];
                    if ($.contains(node, n)) {
                        include = false;
                        break;
                    } else if ($.contains(n, node)) {
                        nodes.splice(j, 1, node);
                        include = false;
                        break;
                    }
                }
                if (include) {
                    return nodes.push(node);
                }
            });
            $blockNodes = $(nodes);
            result = false;
            $blockNodes.each((function(_this) {
                return function(i, blockEl) {
                    var r;
                    r = _this.outdentBlock(blockEl);
                    if (r) {
                        return result = r;
                    }
                };
            })(this));
            return result;
        }

        SimditorIndentfl.prototype.outdentBlock = function(blockEl) {
            var $blockEl, $parent, $parentLi, $pre, $prevTd, $prevTr, $td, $tr, marginLeft, range;
            $blockEl = $(blockEl);
            if (!($blockEl && $blockEl.length > 0)) {
                return;
            }
            if ($blockEl.is('p, h1, h2, h3, h4')) {
                /*marginLeft = parseInt($blockEl.css('margin-left')) || 0;
                marginLeft = Math.max(Math.round(marginLeft
                        / this.opts.indentWidth) - 1, 0)
                        * this.opts.indentWidth;*/
                $blockEl.css('text-indent', '');
            } else {
                return false;
            }
            return true;
        };

        SimditorIndentfl.prototype.outdentText = function(range) {};

        return SimditorIndentfl;

    })(Simditor.Button);

    Simditor.Toolbar.addButton(SimditorIndentfr);
    Simditor.Toolbar.addButton(SimditorIndentfl);

}).call(this);

outdentText和indentText两个函数的作用我没有看全,似乎没有用到,但我也没有删除。插件允许首行缩进的标签有p标签和h系列标签,但在建立编辑器的时候,只添加了p标签的允许样式text-indent,所以也只有p标签能用这个功能了。

工具栏按钮我没有找到合适的图标,暂时用双尖括号表示了。

评论

Name

Email

Website

Subject