辛苦的介绍完前两节后,我们来一个动态图看一下效果吧!
###③. summernote所在form表单的数据提交
这里,我们再回顾一下summernote所在的form表单,其中还包含了一个普通file的input标签,也就是说,该form还需要上传一张项目封面。
<form class="form-horizontal required-validate" action="#" enctype="multipart/form-data" method="post" οnsubmit="return iframeCallback(this, pageAjaxDone)">
先看一下form的属性:
enctype:“multipart/form-data”,表明为文件类型的form保存
iframeCallback方法,稍候详细介绍,主要是对有文件上传的form表单进行封装。
####1、iframeCallback
function iframeCallback(form, callback) { YUNM.debug("带文件上传处理"); var $form = $(form), $iframe = $("#callbackframe"); var data = $form.data('bootstrapValidator'); if (data) { if (!data.isValid()) { return false; } } // 富文本编辑器 $("div.summernote", $form).each(function() { var $this = $(this); if (!$this.summernote('isEmpty')) { var editor = "<input type='hidden' name='" + $this.attr("name") + "' value='" + $this.summernote('code') + "' />"; $form.append(editor); } else { $.showErr("请填写项目详情"); return false; } }); if ($iframe.size() == 0) { $iframe = $("<iframe id='callbackframe' name='callbackframe' src='about:blank' style='display:none'></iframe>").appendTo("body"); } if (!form.ajax) { $form.append('<input type="hidden" name="ajax" value="1" />'); } form.target = "callbackframe"; _iframeResponse($iframe[0], callback || YUNM.ajaxDone); } function _iframeResponse(iframe, callback) { var $iframe = $(iframe), $document = $(document); $document.trigger("ajaxStart"); $iframe.bind("load", function(event) { $iframe.unbind("load"); $document.trigger("ajaxStop"); if (iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" || // For // Safari iframe.src == "javascript:'<html></html>';") { // For FF, IE return; } var doc = iframe.contentDocument || iframe.document; // fixing Opera 9.26,10.00 if (doc.readyState && doc.readyState != 'complete') return; // fixing Opera 9.64 if (doc.body && doc.body.innerHTML == "false") return; var response; if (doc.XMLDocument) { // response is a xml document Internet Explorer property response = doc.XMLDocument; } else if (doc.body) { try { response = $iframe.contents().find("body").text(); response = jQuery.parseJSON(response); } catch (e) { // response is html document or plain text response = doc.body.innerHTML; } } else { // response is a xml document response = doc; } callback(response); }); }
贴上全部代码以供参考,但是这里我们只讲以下部分:
// 富文本编辑器 $("div.summernote", $form).each(function() { var $this = $(this); if (!$this.summernote('isEmpty')) { var editor = "<input type='hidden' name='" + $this.attr("name") + "' value='" + $this.summernote('code') + "' />"; $form.append(editor); } else { $.showErr("请填写项目详情"); return false; } });
通过form获取到summernote对象 t h i s 后 , 通 过 ‘ ‘ ‘ ! this 后,通过```! this后,通过‘‘‘!this.summernote(‘isEmpty’)```来判断用户是否对富文本编辑器有内容上的填写,保证不为空,为空时,就弹出提示信息。
$this.summernote('code')可获得summernote编辑器的html内容,将其封装到input对象中,name为前文中div提供的name,供后端使用。
这里其他地方就不做多解释了,详细可参照Bootstrap wysiwyg富文本数据如何保存到mysql。
保存到数据库中是什么样子呢?
<p><img src="http://localhost:8080/ymeng/upload/2016033117093076.jpeg" style=
####2、新版iframeCallback方法
var $form = $(form), $iframe = $("#callbackframe"); YUNM.debug("验证其他简单组件"); var data = $form.data('bootstrapValidator'); if (data) { if (!data.isValid()) { return false; } } // 富文本编辑器 $("div.summernote", $form).each(function() { var $this = $(this); if ($this.summernote('isEmpty')) { } else { YUNM.debug($this.summernote('code')); // 使用base64对内容进行编码 // 1.解决复制不闭合的html文档,保存后显示错乱的bug // 2.解决文本中特殊字符导致的bug var editor = "<input type='hidden' name='" + $this.attr("name") + "' value='" + $.base64.btoa($this.summernote('code')) + "' />"; $form.append(editor); } }); YUNM.debug("验证通过");
比对之前的代码,可以发现代码有两处发生了变化:
当summernote为空时,之前没有做在bootstrap的validator中,是因为还没有搞清楚summernote这种非input标签在validator中的使用,下面会做详细说明。
对summernote的内容加上了base64编码处理,这会有很多好处,稍候介绍。
3、base64的使用方法
js端我在Bootstrap wysiwyg富文本数据如何保存到mysql这篇文章中做了说明,此处不再说明。
可能会有同学需要javascript端的base64编码,而需要在springMVC后端使用base64的解码,那么此处介绍一个jar包(Java Base64.jar),使用方法很简单,下载好jar包后,就可以使用如下方法解码:
import it.sauronsoftware.base64.Base64;
deal.setDescription(StringEscapeUtils.escapeHtml(Base64.decode(description, "utf-8")));
1
2
3
首先,base64的import如上,来自于javabase64.jar包。
decode的编码前端js使用的utf-8,此处自然也用utf-8。
至于StringEscapeUtils类,也是一个非常实用的工具类,有兴趣的可详细关注一下(主要可以对html等等特殊标签进行转义)。
####4、summernote加入到bootstrap validator中
<div class="form-group"> <label for="" class="col-md-1 control-label">项目详情</label> <div class="col-md-10"> <div class="summernote" name="description" data-bv-excluded="false" data-bv-notempty placeholder="请对项目进行详细的描述,使更多的人了解你的云梦" action="${ctx}/file">${deal.description}</div> </div> </div>
注意data-bv-excluded=“false”(由于summernote使用了div作为form表单的呈现形式,非一般的input标签,所以此处要将该name="description"的field标识为非excluded,默认的validator是不对“[’:disabled’, ‘:hidden’, ‘:not(:visible)’]”三种标签做处理的,而summernote会默认作为disabled的一种,那么设置上data-bv-excluded=“false” 后,validator将会对summernote做非空的判断)、data-bv-notempty属性。
当然有了上述两个属性后,并不能保证validator的有效性,那么接下来,请继续看。
onChange : function(contents, $editable) { if ($this.parents().length > 0) { var $form = $this.parents().find("form.required-validate", $p); if ($form.length > 0) { var data = $form.data('bootstrapValidator'); YUNM.debug($this.summernote('isEmpty')); if ($this.summernote('isEmpty')) { data.updateStatus($this.attr("name"), 'INVALID'); } else { data.updateStatus($this.attr("name"), 'VALID'); } } } }, onInit : function() { if ($this.parents().length > 0) { var $form = $this.parents().find("form.required-validate", $p); if ($form.length > 0) { var data = $form.data('bootstrapValidator'); if (!$this.summernote('isEmpty')) { data.updateStatus($this.attr("name"), 'VALID'); } } } },
在summernote的callbacks中加入onChange 、onInit,当文本域发生变化、初始化时,对summernote在form中的验证字段进行状态的更新,validator中使用updateStatus方法。
/** * Update all validating results of field * * @param {String|jQuery} field The field name or field element * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators * @returns {BootstrapValidator} */ updateStatus: function(field, status, validatorName) {