• rails使用bootstrap3-wysiwyg可视化编辑器并实现自定义图片上传插入功能


    之前在rails开发中使用了ckeditor作为可视化编辑器,不过感觉ckeditor过于庞大,有很多不需要的功能,而且图片上传功能不好控制不同用户可以互相删除图片,感觉很不好。于是考虑更改可视化编辑器,多方考虑选择了bootstrap3-wysiwyg,但是这个编辑器无法实现图片上传功能,还有换行使用br而不是p标签不是很好。于是考虑自定义完善其功能。

    个人原创,版权所有,转载请注明原文出处,并保留原文链接:

    https://www.embbnux.com/2015/03/17/rails_use_bootstrap3-wysiwyg_with_carrierwave_picture_upload

    一 bootstrap3-wysiwyg安装

    这里使用bootstrap-wysihtml5-rails集成到rails中,安装和配置具体见该github.

    在gemfile添加: gem ‘bootstrap-wysihtml5-rails‘,bundle install安装。

    在app/assets/stylesheets/application.css添加

    1
    *= require bootstrap-wysihtml5

    在app/assets/javascripts/application.js里添加

    1
    2
    //= require bootstrap-wysihtml5
    //= require bootstrap-wysihtml5/locales/zh-CN

    在要使用编辑器的地方添加”class=’wysihtml5′”,比如:

    1
    = f.text_area :content,class: "wysihtml5"

    然后在js文件里面初始化编辑器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $('.wysihtml5').each(function(i, elem) {
        $(elem).wysihtml5({
          toolbar: {
            "color": true,
            "size": 'sm'
          },
          "locale" : 'zh-CN',
        });
      });

    这样应该就可以了但是现在没办法实现图片上传,图片只能够插入链接的方式,如下

    选区_032

    上传图片功能还是很重要的,幸亏bootstrap3-wysiwyg提供了很好的扩展功能,可以自己实现上传功能.

    二 使用carrierwave实现图片上传功能

    首先要修改编辑器的图片弹窗,js配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    $(document).ready(function(){
      var csrf_token = $('meta[name=csrf-token]').attr('content');
      var csrf_param = $('meta[name=csrf-param]').attr('content');
      var customTemplates = {
        image : function(context) {
          var locale = context.locale;
          var options = context.options;
          return "<li>" +
            "<div class='bootstrap-wysihtml5-insert-image-modal modal fade' data-wysihtml5-dialog='insertImage'>" +
            "<div class='modal-dialog'>" +
            "<div class='modal-content'>" +
            "<div class='modal-header'>" +
            " <a class='close' data-dismiss='modal'>×</a>" +
            "<h3>" + locale.image.insert + "</h3>" +
            "</div>" +
            "<div class='modal-body'>" +
            "<div class='upload-picture'>" +
            "<form accept-charset='UTF-8' action='/images/upload' class='form-horizontal' id='wysiwyg_image_upload_form' method='post' enctype='multipart/form-data'>"+
            "<div style='display:none'>"+
            "<input name='utf8' value='✓' type='hidden'></input>"+
            "<input name='"+ csrf_param +"' value='"+ csrf_token +"' type='hidden'></input>" +
            "</div>" +
            "<div class='form-group'>" +
            "<div class='col-xs-9 col-md-10'>"+
            "<input value='' accept='image/jpeg,image/gif,image/png' class='form-control' id='wysiwyg_image_picture' name='image[picture]' type='file' required='required'></input>"+
            "</div>" +
            "<div class='col-xs-3 col-md-2'>"+
            "<input class='btn btn-primary' id='wysiwyg_image_submit' name='commit' type='submit' value='上传'></input>"+
            "</div>" +
            "</div>" +
            "</form>"+
            "</div>"+
            "<div class='form-group'>" +
            "<input value='http://' id='bootstrap-wysihtml5-picture-src' class='bootstrap-wysihtml5-insert-image-url form-control' data-wysihtml5-dialog-field='src'>"+
            "</div>" +
            "<div id='wysihtml5_upload_notice'>"+
            "</div>"+
            "</div>" +
            "<div class='modal-footer'>" +
            "<a href='#' class='btn btn-default' data-dismiss='modal'>" + locale.image.cancel + "</a>" +
            "<a class='btn btn-primary' data-dismiss='modal' data-wysihtml5-dialog-action='save' href='#'>" + locale.image.insert + "</a>"+
            "</div>" +
            "</div>" +
            "</div>" +
            "</div>" +
            "<a class='btn btn-sm btn-default' data-wysihtml5-command='insertImage' title='" + locale.image.insert + "' tabindex='-1'><span class='glyphicon glyphicon-picture'></span></a>" +
            "</li>";
        }
      };
      $('.wysihtml5').each(function(i, elem) {
        $(elem).wysihtml5({
          toolbar: {
            "color": true,
            "size": 'sm'
          },
          "locale" : 'zh-CN',
          customTemplates: customTemplates
        });
      });
     
    })

    这样编辑器图片弹窗就会变成下面这样:

    选区_033

    这只是前端view,controller和model层都得再实现

    MODEL: Image

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #migration:
     def change
        create_table :images do |t|
          t.string   :picture
          t.string   :title, default: 'www.embbnux.com'
          t.references :user, index: true
          t.timestamps
        end
      end
    #model
    class Image < ActiveRecord::Base
      belongs_to :user
      mount_uploader :picture, PictureUploader
      validates :user_id, presence: true
      validates :title, length: { maximum: 250 }
    end

    这里的图片上传使用carrierwave,具体使用请见该github readme

    Controller:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #routes
    post "/images/upload" => "images#upload"
     
    #controller
    class ImagesController < ApplicationController
      before_action :logged_in_user
      def upload
        @image = current_user.images.build(images_params)
        image_url = ""
        if @image.save
          image_url = "http://" << ENV["HOME_URL"] << @image.picture.url
          status = "上传成功!点击插入图片按钮插入."
        else
          status = "上传失败!"
        end
        respond_to do |format|
          format.json { render :json =>{:image_url => image_url,:status => status} }
        end
      end
      private
      def images_params
        params.require(:image).permit(:picture)
      end
    end

    这里的controller我使用ajax提交post代码,这样体验比较好,上传成功后把图片的地址传回客户端,自动放在原来的插入图片链接处:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    $('#wysiwyg_image_upload_form').on('submit',function(event){
        event.stopPropagation();
        event.preventDefault();
        $('#wysiwyg_image_submit').val('Uploading');
        var wysiwyg_file = $('#wysiwyg_image_picture')[0].files[0];
        var wysiwyg_formData = new FormData();
        wysiwyg_formData.append('utf8', "✓");
        wysiwyg_formData.append(csrf_param, csrf_token);
        wysiwyg_formData.append('image[picture]', wysiwyg_file,wysiwyg_file.name);
        $.ajax({
            url: '/images/upload',
            type: 'POST',
            data: wysiwyg_formData,
            dataType: 'json',
            processData: false,
            contentType: false,
            success: function(data, textStatus, jqXHR)
            {
              $('#wysiwyg_image_submit').val('上传');
              $('#wysiwyg_image_picture').val('');
              $('#bootstrap-wysihtml5-picture-src').val(data.image_url);
            },
            error: function(jqXHR, textStatus, errorThrown)
            {
            }
        });

    这样上传功能基本就完成了,ajax关键要提供csrf-token参数,其他都没问题

    最终效果可以到我开发的网站看:   huaborn.com

    三 替换br标签为p标签

    这个编辑器如果你键盘按回车键,他是自动加入br标签,感觉比较丑,段落之间还是使用p比较好看

    无意中发现要是原来文本编辑器里存在<p></p>它换行就会自动添加p标签而不是br标签。

    所以最终使用下面代码实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $('.wysihtml5').each(function(i, elem) {
        $(elem).wysihtml5({
          toolbar: {
            "color": true,
            "size": 'sm'
          },
          "locale" : 'zh-CN',
          customTemplates: customTemplates
        });
        var input_text = $(elem).html();
        $(elem).html(input_text+"<p>&nbsp</p>");
      });
  • 相关阅读:
    Constants and Variables
    随想
    C#基础篇之语言和框架介绍
    Python基础19 实例方法 类方法 静态方法 私有变量 私有方法 属性
    Python基础18 实例变量 类变量 构造方法
    Python基础17 嵌套函数 函数类型和Lambda表达式 三大基础函数 filter() map() reduce()
    Python基础16 函数返回值 作用区域 生成器
    Python基础11 List插入,删除,替换和其他常用方法 insert() remove() pop() reverse() copy() clear() index() count()
    Python基础15 函数的定义 使用关键字参数调用 参数默认值 可变参数
    Python基础14 字典的创建修改访问和遍历 popitem() keys() values() items()
  • 原文地址:https://www.cnblogs.com/ly-radiata/p/5849105.html
Copyright © 2020-2023  润新知