plugin.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. (function() {
  6. "use strict";
  7. CKEDITOR.plugins.add("stylescombo", {
  8. requires: "richcombo",
  9. // jscs:disable maximumLineLength
  10. lang:
  11. "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%
  12. // jscs:enable maximumLineLength
  13. init: function(editor) {
  14. var config = editor.config,
  15. lang = editor.lang.stylescombo,
  16. styles = {},
  17. stylesList = [],
  18. combo,
  19. allowedContent = [];
  20. editor.on("stylesSet", function(evt) {
  21. var stylesDefinitions = evt.data.styles;
  22. if (!stylesDefinitions) return;
  23. var style, styleName, styleType;
  24. // Put all styles into an Array.
  25. for (var i = 0, count = stylesDefinitions.length; i < count; i++) {
  26. var styleDefinition = stylesDefinitions[i];
  27. if (
  28. (editor.blockless &&
  29. styleDefinition.element in CKEDITOR.dtd.$block) ||
  30. (typeof styleDefinition.type == "string" &&
  31. !CKEDITOR.style.customHandlers[styleDefinition.type])
  32. ) {
  33. continue;
  34. }
  35. styleName = styleDefinition.name;
  36. style = new CKEDITOR.style(styleDefinition);
  37. if (!editor.filter.customConfig || editor.filter.check(style)) {
  38. style._name = styleName;
  39. style._.enterMode = config.enterMode;
  40. // Get the type (which will be used to assign style to one of 3 groups) from assignedTo if it's defined.
  41. style._.type = styleType = style.assignedTo || style.type;
  42. // Weight is used to sort styles (https://dev.ckeditor.com/ticket/9029).
  43. style._.weight =
  44. i +
  45. (styleType == CKEDITOR.STYLE_OBJECT
  46. ? 1
  47. : styleType == CKEDITOR.STYLE_BLOCK
  48. ? 2
  49. : 3) *
  50. 1000;
  51. styles[styleName] = style;
  52. stylesList.push(style);
  53. allowedContent.push(style);
  54. }
  55. }
  56. // Sorts the Array, so the styles get grouped by type in proper order (https://dev.ckeditor.com/ticket/9029).
  57. stylesList.sort(function(styleA, styleB) {
  58. return styleA._.weight - styleB._.weight;
  59. });
  60. });
  61. editor.ui.addRichCombo("Styles", {
  62. label: lang.label,
  63. title: lang.panelTitle,
  64. toolbar: "styles,10",
  65. allowedContent: allowedContent,
  66. panel: {
  67. css: [CKEDITOR.skin.getPath("editor")].concat(config.contentsCss),
  68. multiSelect: true,
  69. attributes: { "aria-label": lang.panelTitle }
  70. },
  71. init: function() {
  72. var style, styleName, lastType, type, i, count;
  73. // Loop over the Array, adding all items to the
  74. // combo.
  75. for (i = 0, count = stylesList.length; i < count; i++) {
  76. style = stylesList[i];
  77. styleName = style._name;
  78. type = style._.type;
  79. if (type != lastType) {
  80. this.startGroup(lang["panelTitle" + String(type)]);
  81. lastType = type;
  82. }
  83. this.add(
  84. styleName,
  85. style.type == CKEDITOR.STYLE_OBJECT
  86. ? styleName
  87. : style.buildPreview(),
  88. styleName
  89. );
  90. }
  91. this.commit();
  92. },
  93. onClick: function(value) {
  94. editor.focus();
  95. editor.fire("saveSnapshot");
  96. var style = styles[value],
  97. elementPath = editor.elementPath();
  98. // When more then one style from the same group is active ( which is not ok ),
  99. // remove all other styles from this group and apply selected style.
  100. if (style.group && style.removeStylesFromSameGroup(editor)) {
  101. editor.applyStyle(style);
  102. } else {
  103. editor[
  104. style.checkActive(elementPath, editor)
  105. ? "removeStyle"
  106. : "applyStyle"
  107. ](style);
  108. }
  109. editor.fire("saveSnapshot");
  110. },
  111. onRender: function() {
  112. editor.on(
  113. "selectionChange",
  114. function(ev) {
  115. var currentValue = this.getValue(),
  116. elementPath = ev.data.path,
  117. elements = elementPath.elements;
  118. // For each element into the elements path.
  119. for (
  120. var i = 0, count = elements.length, element;
  121. i < count;
  122. i++
  123. ) {
  124. element = elements[i];
  125. // Check if the element is removable by any of
  126. // the styles.
  127. for (var value in styles) {
  128. if (
  129. styles[value].checkElementRemovable(element, true, editor)
  130. ) {
  131. if (value != currentValue) this.setValue(value);
  132. return;
  133. }
  134. }
  135. }
  136. // If no styles match, just empty it.
  137. this.setValue("");
  138. },
  139. this
  140. );
  141. },
  142. onOpen: function() {
  143. var selection = editor.getSelection(),
  144. // When editor is focused but is returned `null` as selected element, then return editable (#646).
  145. // In case when selection dosen't cover whole element, we try to return element where selection starts (#862).
  146. element =
  147. selection.getSelectedElement() ||
  148. selection.getStartElement() ||
  149. editor.editable(),
  150. elementPath = editor.elementPath(element),
  151. counter = [0, 0, 0, 0];
  152. this.showAll();
  153. this.unmarkAll();
  154. for (var name in styles) {
  155. var style = styles[name],
  156. type = style._.type;
  157. if (style.checkApplicable(elementPath, editor, editor.activeFilter))
  158. counter[type]++;
  159. else this.hideItem(name);
  160. if (style.checkActive(elementPath, editor)) this.mark(name);
  161. }
  162. if (!counter[CKEDITOR.STYLE_BLOCK])
  163. this.hideGroup(lang["panelTitle" + String(CKEDITOR.STYLE_BLOCK)]);
  164. if (!counter[CKEDITOR.STYLE_INLINE])
  165. this.hideGroup(lang["panelTitle" + String(CKEDITOR.STYLE_INLINE)]);
  166. if (!counter[CKEDITOR.STYLE_OBJECT])
  167. this.hideGroup(lang["panelTitle" + String(CKEDITOR.STYLE_OBJECT)]);
  168. },
  169. refresh: function() {
  170. var elementPath = editor.elementPath();
  171. if (!elementPath) return;
  172. for (var name in styles) {
  173. var style = styles[name];
  174. if (style.checkApplicable(elementPath, editor, editor.activeFilter))
  175. return;
  176. }
  177. this.setState(CKEDITOR.TRISTATE_DISABLED);
  178. },
  179. // Force a reload of the data
  180. reset: function() {
  181. if (combo) {
  182. delete combo._.panel;
  183. delete combo._.list;
  184. combo._.committed = 0;
  185. combo._.items = {};
  186. combo._.state = CKEDITOR.TRISTATE_OFF;
  187. }
  188. styles = {};
  189. stylesList = [];
  190. }
  191. });
  192. }
  193. });
  194. })();