plugin.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /**
  2. * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. CKEDITOR.plugins.add("format", {
  6. requires: "richcombo",
  7. // jscs:disable maximumLineLength
  8. lang:
  9. "af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn", // %REMOVE_LINE_CORE%
  10. // jscs:enable maximumLineLength
  11. init: function(editor) {
  12. if (editor.blockless) return;
  13. var config = editor.config,
  14. lang = editor.lang.format;
  15. // Gets the list of tags from the settings.
  16. var tags = config.format_tags.split(";");
  17. // Create style objects for all defined styles.
  18. var styles = {},
  19. stylesCount = 0,
  20. allowedContent = [];
  21. for (var i = 0; i < tags.length; i++) {
  22. var tag = tags[i];
  23. var style = new CKEDITOR.style(config["format_" + tag]);
  24. if (!editor.filter.customConfig || editor.filter.check(style)) {
  25. stylesCount++;
  26. styles[tag] = style;
  27. styles[tag]._.enterMode = editor.config.enterMode;
  28. allowedContent.push(style);
  29. }
  30. }
  31. // Hide entire combo when all formats are rejected.
  32. if (stylesCount === 0) return;
  33. editor.ui.addRichCombo("Format", {
  34. label: lang.label,
  35. title: lang.panelTitle,
  36. toolbar: "styles,20",
  37. allowedContent: allowedContent,
  38. panel: {
  39. css: [CKEDITOR.skin.getPath("editor")].concat(config.contentsCss),
  40. multiSelect: false,
  41. attributes: { "aria-label": lang.panelTitle }
  42. },
  43. init: function() {
  44. this.startGroup(lang.panelTitle);
  45. for (var tag in styles) {
  46. var label = lang["tag_" + tag];
  47. // Add the tag entry to the panel list.
  48. this.add(tag, styles[tag].buildPreview(label), label);
  49. }
  50. },
  51. onClick: function(value) {
  52. editor.focus();
  53. editor.fire("saveSnapshot");
  54. var style = styles[value],
  55. elementPath = editor.elementPath();
  56. // Always apply style, do not allow to toggle it by clicking on corresponding list item (#584).
  57. if (!style.checkActive(elementPath, editor)) {
  58. editor.applyStyle(style);
  59. }
  60. // Save the undo snapshot after all changes are affected. (https://dev.ckeditor.com/ticket/4899)
  61. setTimeout(function() {
  62. editor.fire("saveSnapshot");
  63. }, 0);
  64. },
  65. onRender: function() {
  66. editor.on(
  67. "selectionChange",
  68. function(ev) {
  69. var currentTag = this.getValue(),
  70. elementPath = ev.data.path;
  71. this.refresh();
  72. for (var tag in styles) {
  73. if (styles[tag].checkActive(elementPath, editor)) {
  74. if (tag != currentTag)
  75. this.setValue(tag, editor.lang.format["tag_" + tag]);
  76. return;
  77. }
  78. }
  79. // If no styles match, just empty it.
  80. this.setValue("");
  81. },
  82. this
  83. );
  84. },
  85. onOpen: function() {
  86. this.showAll();
  87. for (var name in styles) {
  88. var style = styles[name];
  89. // Check if that style is enabled in activeFilter.
  90. if (!editor.activeFilter.check(style)) this.hideItem(name);
  91. }
  92. },
  93. refresh: function() {
  94. var elementPath = editor.elementPath();
  95. if (!elementPath) return;
  96. // Check if element path contains 'p' element.
  97. if (!elementPath.isContextFor("p")) {
  98. this.setState(CKEDITOR.TRISTATE_DISABLED);
  99. return;
  100. }
  101. // Check if there is any available style.
  102. for (var name in styles) {
  103. if (editor.activeFilter.check(styles[name])) return;
  104. }
  105. this.setState(CKEDITOR.TRISTATE_DISABLED);
  106. }
  107. });
  108. }
  109. });
  110. /**
  111. * A list of semicolon-separated style names (by default: tags) representing
  112. * the style definition for each entry to be displayed in the Format drop-down list
  113. * in the toolbar. Each entry must have a corresponding configuration in a
  114. * setting named `'format_(tagName)'`. For example, the `'p'` entry has its
  115. * definition taken from [config.format_p](#!/api/CKEDITOR.config-cfg-format_p).
  116. *
  117. * Read more in the {@glink features/format documentation}
  118. * and see the {@glink examples/format example}.
  119. *
  120. * config.format_tags = 'p;h2;h3;pre';
  121. *
  122. * @cfg {String} [format_tags='p;h1;h2;h3;h4;h5;h6;pre;address;div']
  123. * @member CKEDITOR.config
  124. */
  125. CKEDITOR.config.format_tags = "p;h1;h2;h3;h4;h5;h6;pre;address;div";
  126. /**
  127. * The style definition to be used to apply the `Normal` format.
  128. *
  129. * Read more in the {@glink features/format documentation}
  130. * and see the {@glink examples/format example}.
  131. *
  132. * config.format_p = { element: 'p', attributes: { 'class': 'normalPara' } };
  133. *
  134. * @cfg {Object} [format_p={ element: 'p' }]
  135. * @member CKEDITOR.config
  136. */
  137. CKEDITOR.config.format_p = { element: "p" };
  138. /**
  139. * The style definition to be used to apply the `Normal (DIV)` format.
  140. *
  141. * Read more in the {@glink features/format documentation}
  142. * and see the {@glink examples/format example}.
  143. *
  144. * config.format_div = { element: 'div', attributes: { 'class': 'normalDiv' } };
  145. *
  146. * @cfg {Object} [format_div={ element: 'div' }]
  147. * @member CKEDITOR.config
  148. */
  149. CKEDITOR.config.format_div = { element: "div" };
  150. /**
  151. * The style definition to be used to apply the `Formatted` format.
  152. *
  153. * Read more in the {@glink features/format documentation}
  154. * and see the {@glink examples/format example}.
  155. *
  156. * config.format_pre = { element: 'pre', attributes: { 'class': 'code' } };
  157. *
  158. * @cfg {Object} [format_pre={ element: 'pre' }]
  159. * @member CKEDITOR.config
  160. */
  161. CKEDITOR.config.format_pre = { element: "pre" };
  162. /**
  163. * The style definition to be used to apply the `Address` format.
  164. *
  165. * Read more in the {@glink features/format documentation}
  166. * and see the {@glink examples/format example}.
  167. *
  168. * config.format_address = { element: 'address', attributes: { 'class': 'styledAddress' } };
  169. *
  170. * @cfg {Object} [format_address={ element: 'address' }]
  171. * @member CKEDITOR.config
  172. */
  173. CKEDITOR.config.format_address = { element: "address" };
  174. /**
  175. * The style definition to be used to apply the `Heading 1` format.
  176. *
  177. * Read more in the {@glink features/format documentation}
  178. * and see the {@glink examples/format example}.
  179. *
  180. * config.format_h1 = { element: 'h1', attributes: { 'class': 'contentTitle1' } };
  181. *
  182. * @cfg {Object} [format_h1={ element: 'h1' }]
  183. * @member CKEDITOR.config
  184. */
  185. CKEDITOR.config.format_h1 = { element: "h1" };
  186. /**
  187. * The style definition to be used to apply the `Heading 2` format.
  188. *
  189. * Read more in the {@glink features/format documentation}
  190. * and see the {@glink examples/format example}.
  191. *
  192. * config.format_h2 = { element: 'h2', attributes: { 'class': 'contentTitle2' } };
  193. *
  194. * @cfg {Object} [format_h2={ element: 'h2' }]
  195. * @member CKEDITOR.config
  196. */
  197. CKEDITOR.config.format_h2 = { element: "h2" };
  198. /**
  199. * The style definition to be used to apply the `Heading 3` format.
  200. *
  201. * Read more in the {@glink features/format documentation}
  202. * and see the {@glink examples/format example}.
  203. *
  204. * config.format_h3 = { element: 'h3', attributes: { 'class': 'contentTitle3' } };
  205. *
  206. * @cfg {Object} [format_h3={ element: 'h3' }]
  207. * @member CKEDITOR.config
  208. */
  209. CKEDITOR.config.format_h3 = { element: "h3" };
  210. /**
  211. * The style definition to be used to apply the `Heading 4` format.
  212. *
  213. * Read more in the {@glink features/format documentation}
  214. * and see the {@glink examples/format example}.
  215. *
  216. * config.format_h4 = { element: 'h4', attributes: { 'class': 'contentTitle4' } };
  217. *
  218. * @cfg {Object} [format_h4={ element: 'h4' }]
  219. * @member CKEDITOR.config
  220. */
  221. CKEDITOR.config.format_h4 = { element: "h4" };
  222. /**
  223. * The style definition to be used to apply the `Heading 5` format.
  224. *
  225. * Read more in the {@glink features/format documentation}
  226. * and see the {@glink examples/format example}.
  227. *
  228. * config.format_h5 = { element: 'h5', attributes: { 'class': 'contentTitle5' } };
  229. *
  230. * @cfg {Object} [format_h5={ element: 'h5' }]
  231. * @member CKEDITOR.config
  232. */
  233. CKEDITOR.config.format_h5 = { element: "h5" };
  234. /**
  235. * The style definition to be used to apply the `Heading 6` format.
  236. *
  237. * Read more in the {@glink features/format documentation}
  238. * and see the {@glink examples/format example}.
  239. *
  240. * config.format_h6 = { element: 'h6', attributes: { 'class': 'contentTitle6' } };
  241. *
  242. * @cfg {Object} [format_h6={ element: 'h6' }]
  243. * @member CKEDITOR.config
  244. */
  245. CKEDITOR.config.format_h6 = { element: "h6" };