記事フォームに tinymce (4.0.6) を使用しています。img の「タイトル」属性をサポートするように画像プラグインを更新しました。記事の画像の下にキャプション テキストを配置するために使用するカスタム データ属性「data-caption」をサポートしたいと考えています。
これは私の更新されたイメージ plugin.min.js です:
tinymce.PluginManager.add("image",function(t){function e(t,e){function n(t,n){i.parentNode.removeChild(i),e({width:t,height:n})}var i=document.createElement("img");i.onload=function(){n(i.clientWidth,i.clientHeight)},i.onerror=function(){n()},i.src=t;var a=i.style;a.visibility="hidden",a.position="fixed",a.bottom=a.left=0,a.width=a.height="auto",document.body.appendChild(i)}function n(e){return function(){var n=t.settings.image_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(t){e(tinymce.util.JSON.parse(t))}}):e(n)}}function i(n){function i(){var t=[{text:"None",value:""}];return tinymce.each(n,function(e){t.push({text:e.text||e.title,value:e.value||e.url,menu:e.menu})}),t}function a(t){var e,n,i,a;e=s.find("#width")[0],n=s.find("#height")[0],i=e.value(),a=n.value(),s.find("#constrain")[0].checked()&&h&&u&&i&&a&&(t.control==e?(a=Math.round(i/h*a),n.value(a)):(i=Math.round(a/u*i),e.value(i))),h=i,u=a}function o(){function e(e){function i(){e.onload=e.onerror=null,t.selection.select(e),t.nodeChanged()}e.onload=function(){n.width||n.height||m.setAttribs(e,{width:e.clientWidth,height:e.clientHeight}),i()},e.onerror=i}var n=s.toJSON();""===n.width&&(n.width=null),""===n.height&&(n.height=null),""===n.style&&(n.style=null),n={src:n.src,alt:n.alt,caption:n.caption,title:n.title,width:n.width,height:n.height,style:n.style},t.undoManager.transact(function(){return n.src?(p?m.setAttribs(p,n):(n.id="__mcenew",t.selection.setContent(m.createHTML("img",n)),p=m.get("__mcenew"),m.setAttrib(p,"id",null)),e(p),void 0):(p&&(m.remove(p),t.nodeChanged()),void 0)})}function l(t){return t&&(t=t.replace(/px$/,"")),t}function r(){e(this.value(),function(t){t.width&&t.height&&(h=t.width,u=t.height,s.find("#width").value(h),s.find("#height").value(u))})}function c(){function t(t){return t.length>0&&/^[0-9]+$/.test(t)&&(t+="px"),t}var e=s.toJSON(),n=m.parseStyle(e.style);m.setAttrib(p,"style",""),delete n.margin,n["margin-top"]=n["margin-bottom"]=t(e.vspace),n["margin-left"]=n["margin-right"]=t(e.hspace),n["border-width"]=t(e.border),s.find("#style").value(m.serializeStyle(m.parseStyle(m.serializeStyle(n))))}var s,d,h,u,g,m=t.dom,p=t.selection.getNode();h=m.getAttrib(p,"width"),u=m.getAttrib(p,"height"),"IMG"!=p.nodeName||p.getAttribute("data-mce-object")?p=null:d={src:m.getAttrib(p,"src"),alt:m.getAttrib(p,"alt"),caption:m.getAttrib(p,"data-caption"),title:m.getAttrib(p,"title"),width:h,height:u},n&&(g={name:"target",type:"listbox",label:"Image list",values:i(),onselect:function(t){var e=s.find("#alt");(!e.value()||t.lastControl&&e.value()==t.lastControl.text())&&e.value(t.control.text()),s.find("#src").value(t.control.value())}});var y=[{name:"src",type:"filepicker",filetype:"image",label:"Source",autofocus:!0,onchange:r},g,{name:"alt",type:"textbox",label:"Image description"},{name:"data-caption",type:"textbox",label:"Caption"},{name:"title",type:"textbox",label:"Title"},{type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:3,size:3,onchange:a},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:3,size:3,onchange:a},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}];t.settings.image_advtab?(p&&(d.hspace=l(p.style.marginLeft||p.style.marginRight),d.vspace=l(p.style.marginTop||p.style.marginBottom),d.border=l(p.style.borderWidth),d.style=t.dom.serializeStyle(t.dom.parseStyle(t.dom.getAttrib(p,"style")))),s=t.windowManager.open({title:"Insert/edit image",data:d,bodyType:"tabpanel",body:[{title:"General",type:"form",items:y},{title:"Advanced",type:"form",pack:"start",items:[{label:"Style",name:"style",type:"textbox"},{type:"form",layout:"grid",packV:"start",columns:2,padding:0,alignH:["left","right"],defaults:{type:"textbox",maxWidth:50,onchange:c},items:[{label:"Vertical space",name:"vspace"},{label:"Horizontal space",name:"hspace"},{label:"Border",name:"border"}]}]}],onSubmit:o})):s=t.windowManager.open({title:"Insert/edit image",data:d,body:y,onSubmit:o})}t.addButton("image",{icon:"image",tooltip:"Insert/edit image",onclick:n(i),stateSelector:"img:not([data-mce-object])"}),t.addMenuItem("image",{icon:"image",text:"Insert image",onclick:n(i),context:"insert",prependToContext:!0})});
JS Beautifier で実行すると、次のようになります。
tinymce.PluginManager.add("image", function (t) {
function e(t, e) {
function n(t, n) {
i.parentNode.removeChild(i), e({
width: t,
height: n
})
}
var i = document.createElement("img");
i.onload = function () {
n(i.clientWidth, i.clientHeight)
}, i.onerror = function () {
n()
}, i.src = t;
var a = i.style;
a.visibility = "hidden", a.position = "fixed", a.bottom = a.left = 0, a.width = a.height = "auto", document.body.appendChild(i)
}
function n(e) {
return function () {
var n = t.settings.image_list;
"string" == typeof n ? tinymce.util.XHR.send({
url: n,
success: function (t) {
e(tinymce.util.JSON.parse(t))
}
}) : e(n)
}
}
function i(n) {
function i() {
var t = [{
text: "None",
value: ""
}];
return tinymce.each(n, function (e) {
t.push({
text: e.text || e.title,
value: e.value || e.url,
menu: e.menu
})
}), t
}
function a(t) {
var e, n, i, a;
e = s.find("#width")[0], n = s.find("#height")[0], i = e.value(), a = n.value(), s.find("#constrain")[0].checked() && h && u && i && a && (t.control == e ? (a = Math.round(i / h * a), n.value(a)) : (i = Math.round(a / u * i), e.value(i))), h = i, u = a
}
function o() {
function e(e) {
function i() {
e.onload = e.onerror = null, t.selection.select(e), t.nodeChanged()
}
e.onload = function () {
n.width || n.height || m.setAttribs(e, {
width: e.clientWidth,
height: e.clientHeight
}), i()
}, e.onerror = i
}
var n = s.toJSON();
"" === n.width && (n.width = null), "" === n.height && (n.height = null), "" === n.style && (n.style = null), n = {
src: n.src,
alt: n.alt,
caption: n.caption,
title: n.title,
width: n.width,
height: n.height,
style: n.style
}, t.undoManager.transact(function () {
return n.src ? (p ? m.setAttribs(p, n) : (n.id = "__mcenew", t.selection.setContent(m.createHTML("img", n)), p = m.get("__mcenew"), m.setAttrib(p, "id", null)), e(p), void 0) : (p && (m.remove(p), t.nodeChanged()), void 0)
})
}
function l(t) {
return t && (t = t.replace(/px$/, "")), t
}
function r() {
e(this.value(), function (t) {
t.width && t.height && (h = t.width, u = t.height, s.find("#width").value(h), s.find("#height").value(u))
})
}
function c() {
function t(t) {
return t.length > 0 && /^[0-9]+$/.test(t) && (t += "px"), t
}
var e = s.toJSON(),
n = m.parseStyle(e.style);
m.setAttrib(p, "style", ""), delete n.margin, n["margin-top"] = n["margin-bottom"] = t(e.vspace), n["margin-left"] = n["margin-right"] = t(e.hspace), n["border-width"] = t(e.border), s.find("#style").value(m.serializeStyle(m.parseStyle(m.serializeStyle(n))))
}
var s, d, h, u, g, m = t.dom,
p = t.selection.getNode();
h = m.getAttrib(p, "width"), u = m.getAttrib(p, "height"), "IMG" != p.nodeName || p.getAttribute("data-mce-object") ? p = null : d = {
src: m.getAttrib(p, "src"),
alt: m.getAttrib(p, "alt"),
caption: m.getAttrib(p, "data-caption"),
title: m.getAttrib(p, "title"),
width: h,
height: u
}, n && (g = {
name: "target",
type: "listbox",
label: "Image list",
values: i(),
onselect: function (t) {
var e = s.find("#alt");
(!e.value() || t.lastControl && e.value() == t.lastControl.text()) && e.value(t.control.text()), s.find("#src").value(t.control.value())
}
});
var y = [{
name: "src",
type: "filepicker",
filetype: "image",
label: "Source",
autofocus: !0,
onchange: r
},
g, {
name: "alt",
type: "textbox",
label: "Image description"
}, {
name: "data-caption",
type: "textbox",
label: "Caption"
}, {
name: "title",
type: "textbox",
label: "Title"
}, {
type: "container",
label: "Dimensions",
layout: "flex",
direction: "row",
align: "center",
spacing: 5,
items: [{
name: "width",
type: "textbox",
maxLength: 3,
size: 3,
onchange: a
}, {
type: "label",
text: "x"
}, {
name: "height",
type: "textbox",
maxLength: 3,
size: 3,
onchange: a
}, {
name: "constrain",
type: "checkbox",
checked: !0,
text: "Constrain proportions"
}]
}
];
t.settings.image_advtab ? (p && (d.hspace = l(p.style.marginLeft || p.style.marginRight), d.vspace = l(p.style.marginTop || p.style.marginBottom), d.border = l(p.style.borderWidth), d.style = t.dom.serializeStyle(t.dom.parseStyle(t.dom.getAttrib(p, "style")))), s = t.windowManager.open({
title: "Insert/edit image",
data: d,
bodyType: "tabpanel",
body: [{
title: "General",
type: "form",
items: y
}, {
title: "Advanced",
type: "form",
pack: "start",
items: [{
label: "Style",
name: "style",
type: "textbox"
}, {
type: "form",
layout: "grid",
packV: "start",
columns: 2,
padding: 0,
alignH: ["left", "right"],
defaults: {
type: "textbox",
maxWidth: 50,
onchange: c
},
items: [{
label: "Vertical space",
name: "vspace"
}, {
label: "Horizontal space",
name: "hspace"
}, {
label: "Border",
name: "border"
}]
}]
}],
onSubmit: o
})) : s = t.windowManager.open({
title: "Insert/edit image",
data: d,
body: y,
onSubmit: o
})
}
t.addButton("image", {
icon: "image",
tooltip: "Insert/edit image",
onclick: n(i),
stateSelector: "img:not([data-mce-object])"
}), t.addMenuItem("image", {
icon: "image",
text: "Insert image",
onclick: n(i),
context: "insert",
prependToContext: !0
})
});
私はtinymceの初期化でこれを持っています:
extended_valid_elements : "img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name|data-caption]"
title 属性は期待どおりに機能していますが、画像ダイアログが送信されると data-caption 属性が削除されます。[ツール] -> [ソース コード] ボックスをチェックインすると、結果の img タグに title 属性が存在しますが、data-caption は存在しません。
これは、行のキャプションなど、属性の値を渡す関数の一部と関係があると思います: n.caption,. ここで data-caption が変数名として正しく評価されるとは思わなかったので、これを行いました。
tinymce 4 の画像プラグインを使用して、画像にデータ属性を追加しようとした人はいますか? または、データ キャプション属性を img タグに追加する別の方法はありますか (ソース コード ウィンドウで編集する方法はありません)。私はこれをコンテンツ作成者にとって使いやすくしたいと思っています (tinymce を使用することの要点)。他のカスタム関数を作成することで大きな成功を収めましたが、これがハングアップして困惑しています。
お早めにどうぞ!