ng2-ckeditor.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. import { __decorate, __metadata } from 'tslib';
  2. import { EventEmitter, Output, Input, Directive, ContentChildren, QueryList, NgZone, ViewChild, Component, forwardRef, NgModule } from '@angular/core';
  3. import { CommonModule } from '@angular/common';
  4. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  5. /**
  6. * CKGroup component
  7. * Usage :
  8. * <ckeditor [(ngModel)]="data" [config]="{...}" debounce="500">
  9. * <ckbutton [name]="'SaveButton'" [command]="'saveCommand'" (click)="save($event)"
  10. * [icon]="'/save.png'" [toolbar]="'customGroup,1'" [label]="'Save'">
  11. * </ckbutton>
  12. * </ckeditor>
  13. */
  14. let CKButtonDirective = class CKButtonDirective {
  15. /**
  16. * CKGroup component
  17. * Usage :
  18. * <ckeditor [(ngModel)]="data" [config]="{...}" debounce="500">
  19. * <ckbutton [name]="'SaveButton'" [command]="'saveCommand'" (click)="save($event)"
  20. * [icon]="'/save.png'" [toolbar]="'customGroup,1'" [label]="'Save'">
  21. * </ckbutton>
  22. * </ckeditor>
  23. */
  24. constructor() {
  25. this.click = new EventEmitter();
  26. }
  27. initialize(editor) {
  28. editor.instance.addCommand(this.command, {
  29. exec: (evt) => {
  30. this.click.emit(evt);
  31. },
  32. });
  33. editor.instance.ui.addButton(this.name, {
  34. label: this.label,
  35. command: this.command,
  36. toolbar: this.toolbar,
  37. icon: this.icon,
  38. });
  39. }
  40. ngOnInit() {
  41. if (!this.name)
  42. throw new Error('Attribute "name" is required on <ckbutton>');
  43. if (!this.command)
  44. throw new Error('Attribute "command" is required on <ckbutton>');
  45. }
  46. };
  47. __decorate([
  48. Output(),
  49. __metadata("design:type", Object)
  50. ], CKButtonDirective.prototype, "click", void 0);
  51. __decorate([
  52. Input(),
  53. __metadata("design:type", String)
  54. ], CKButtonDirective.prototype, "label", void 0);
  55. __decorate([
  56. Input(),
  57. __metadata("design:type", String)
  58. ], CKButtonDirective.prototype, "command", void 0);
  59. __decorate([
  60. Input(),
  61. __metadata("design:type", String)
  62. ], CKButtonDirective.prototype, "toolbar", void 0);
  63. __decorate([
  64. Input(),
  65. __metadata("design:type", String)
  66. ], CKButtonDirective.prototype, "name", void 0);
  67. __decorate([
  68. Input(),
  69. __metadata("design:type", String)
  70. ], CKButtonDirective.prototype, "icon", void 0);
  71. CKButtonDirective = __decorate([
  72. Directive({
  73. selector: 'ckbutton',
  74. })
  75. ], CKButtonDirective);
  76. /**
  77. * CKGroup component
  78. * Usage :
  79. * <ckeditor [(ngModel)]="data" [config]="{...}" debounce="500">
  80. * <ckgroup [name]="'exampleGroup2'" [previous]="'1'" [subgroupOf]="'exampleGroup1'">
  81. * .
  82. * .
  83. * </ckgroup>
  84. * </ckeditor>
  85. */
  86. let CKGroupDirective = class CKGroupDirective {
  87. ngAfterContentInit() {
  88. // Reconfigure each button's toolbar property within ckgroup to hold its parent's name
  89. this.toolbarButtons.forEach(button => (button.toolbar = this.name));
  90. }
  91. initialize(editor) {
  92. editor.instance.ui.addToolbarGroup(this.name, this.previous, this.subgroupOf);
  93. // Initialize each button within ckgroup
  94. this.toolbarButtons.forEach(button => {
  95. button.initialize(editor);
  96. });
  97. }
  98. };
  99. __decorate([
  100. Input(),
  101. __metadata("design:type", String)
  102. ], CKGroupDirective.prototype, "name", void 0);
  103. __decorate([
  104. Input(),
  105. __metadata("design:type", Object)
  106. ], CKGroupDirective.prototype, "previous", void 0);
  107. __decorate([
  108. Input(),
  109. __metadata("design:type", String)
  110. ], CKGroupDirective.prototype, "subgroupOf", void 0);
  111. __decorate([
  112. ContentChildren(CKButtonDirective),
  113. __metadata("design:type", QueryList)
  114. ], CKGroupDirective.prototype, "toolbarButtons", void 0);
  115. CKGroupDirective = __decorate([
  116. Directive({
  117. selector: 'ckgroup',
  118. })
  119. ], CKGroupDirective);
  120. var CKEditorComponent_1;
  121. /**
  122. * CKEditor component
  123. * Usage :
  124. * <ckeditor [(ngModel)]="data" [config]="{...}" debounce="500"></ckeditor>
  125. */
  126. let CKEditorComponent = CKEditorComponent_1 = class CKEditorComponent {
  127. /**
  128. * Constructor
  129. */
  130. constructor(zone) {
  131. this.zone = zone;
  132. this.change = new EventEmitter();
  133. this.editorChange = new EventEmitter();
  134. this.ready = new EventEmitter();
  135. this.blur = new EventEmitter();
  136. this.focus = new EventEmitter();
  137. this.contentDom = new EventEmitter();
  138. this.fileUploadRequest = new EventEmitter();
  139. this.fileUploadResponse = new EventEmitter();
  140. this.paste = new EventEmitter();
  141. this.drop = new EventEmitter();
  142. this._value = '';
  143. }
  144. get value() {
  145. return this._value;
  146. }
  147. set value(v) {
  148. if (v !== this._value) {
  149. this._value = v;
  150. this.onChange(v);
  151. }
  152. }
  153. ngOnChanges(changes) {
  154. if (changes.readonly && this.instance) {
  155. this.instance.setReadOnly(changes.readonly.currentValue);
  156. }
  157. }
  158. /**
  159. * On component destroy
  160. */
  161. ngOnDestroy() {
  162. if (this.instance) {
  163. this.instance.removeAllListeners();
  164. CKEDITOR.instances[this.instance.name].destroy();
  165. this.instance.destroy();
  166. this.instance = null;
  167. }
  168. }
  169. /**
  170. * On component view init
  171. */
  172. ngAfterViewInit() {
  173. this.ckeditorInit(this.config || {});
  174. }
  175. /**
  176. * On component view checked
  177. */
  178. ngAfterViewChecked() {
  179. this.ckeditorInit(this.config || {});
  180. }
  181. /**
  182. * Value update process
  183. */
  184. updateValue(value) {
  185. this.zone.run(() => {
  186. this.value = value;
  187. this.onChange(value);
  188. this.onTouched();
  189. this.change.emit(value);
  190. });
  191. }
  192. /**
  193. * CKEditor init
  194. */
  195. ckeditorInit(config) {
  196. if (typeof CKEDITOR === 'undefined') {
  197. console.warn('CKEditor 4.x is missing (http://ckeditor.com/)');
  198. }
  199. else {
  200. // Check textarea exists
  201. if (this.instance || !this.documentContains(this.host.nativeElement)) {
  202. return;
  203. }
  204. if (this.readonly) {
  205. config.readOnly = this.readonly;
  206. }
  207. // CKEditor replace textarea
  208. this.instance = CKEDITOR.replace(this.host.nativeElement, config);
  209. // Set initial value
  210. this.instance.setData(this.value);
  211. // listen for instanceReady event
  212. this.instance.on('instanceReady', (evt) => {
  213. // if value has changed while instance loading
  214. // update instance with current component value
  215. if (this.instance.getData() !== this.value) {
  216. this.instance.setData(this.value);
  217. }
  218. // send the evt to the EventEmitter
  219. this.ready.emit(evt);
  220. });
  221. // CKEditor change event
  222. this.instance.on('change', (evt) => {
  223. this.onTouched();
  224. let value = this.instance.getData();
  225. if (this.value !== value) {
  226. // Debounce update
  227. if (this.debounce) {
  228. if (this.debounceTimeout)
  229. clearTimeout(this.debounceTimeout);
  230. this.debounceTimeout = setTimeout(() => {
  231. this.updateValue(value);
  232. this.debounceTimeout = null;
  233. }, parseInt(this.debounce));
  234. // Live update
  235. }
  236. else {
  237. this.updateValue(value);
  238. }
  239. }
  240. // Original ckeditor event dispatch
  241. this.editorChange.emit(evt);
  242. });
  243. // CKEditor blur event
  244. this.instance.on('blur', (evt) => {
  245. this.blur.emit(evt);
  246. });
  247. // CKEditor focus event
  248. this.instance.on('focus', (evt) => {
  249. this.focus.emit(evt);
  250. });
  251. // CKEditor contentDom event
  252. this.instance.on('contentDom', (evt) => {
  253. this.contentDom.emit(evt);
  254. });
  255. // CKEditor fileUploadRequest event
  256. this.instance.on('fileUploadRequest', (evt) => {
  257. this.fileUploadRequest.emit(evt);
  258. });
  259. // CKEditor fileUploadResponse event
  260. this.instance.on('fileUploadResponse', (evt) => {
  261. this.fileUploadResponse.emit(evt);
  262. });
  263. // CKEditor paste event
  264. this.instance.on('paste', (evt) => {
  265. this.paste.emit(evt);
  266. });
  267. // CKEditor drop event
  268. this.instance.on('drop', (evt) => {
  269. this.drop.emit(evt);
  270. });
  271. // Add Toolbar Groups to Editor. This will also add Buttons within groups.
  272. this.toolbarGroups.forEach(group => {
  273. group.initialize(this);
  274. });
  275. // Add Toolbar Buttons to Editor.
  276. this.toolbarButtons.forEach(button => {
  277. button.initialize(this);
  278. });
  279. }
  280. }
  281. /**
  282. * Implements ControlValueAccessor
  283. */
  284. writeValue(value) {
  285. this._value = value;
  286. if (this.instance)
  287. this.instance.setData(value);
  288. }
  289. onChange(_) { }
  290. onTouched() { }
  291. registerOnChange(fn) {
  292. this.onChange = fn;
  293. }
  294. registerOnTouched(fn) {
  295. this.onTouched = fn;
  296. }
  297. documentContains(node) {
  298. return document.contains ? document.contains(node) : document.body.contains(node);
  299. }
  300. };
  301. CKEditorComponent.ctorParameters = () => [
  302. { type: NgZone }
  303. ];
  304. __decorate([
  305. Input(),
  306. __metadata("design:type", Object)
  307. ], CKEditorComponent.prototype, "config", void 0);
  308. __decorate([
  309. Input(),
  310. __metadata("design:type", Boolean)
  311. ], CKEditorComponent.prototype, "readonly", void 0);
  312. __decorate([
  313. Input(),
  314. __metadata("design:type", String)
  315. ], CKEditorComponent.prototype, "debounce", void 0);
  316. __decorate([
  317. Output(),
  318. __metadata("design:type", Object)
  319. ], CKEditorComponent.prototype, "change", void 0);
  320. __decorate([
  321. Output(),
  322. __metadata("design:type", Object)
  323. ], CKEditorComponent.prototype, "editorChange", void 0);
  324. __decorate([
  325. Output(),
  326. __metadata("design:type", Object)
  327. ], CKEditorComponent.prototype, "ready", void 0);
  328. __decorate([
  329. Output(),
  330. __metadata("design:type", Object)
  331. ], CKEditorComponent.prototype, "blur", void 0);
  332. __decorate([
  333. Output(),
  334. __metadata("design:type", Object)
  335. ], CKEditorComponent.prototype, "focus", void 0);
  336. __decorate([
  337. Output(),
  338. __metadata("design:type", Object)
  339. ], CKEditorComponent.prototype, "contentDom", void 0);
  340. __decorate([
  341. Output(),
  342. __metadata("design:type", Object)
  343. ], CKEditorComponent.prototype, "fileUploadRequest", void 0);
  344. __decorate([
  345. Output(),
  346. __metadata("design:type", Object)
  347. ], CKEditorComponent.prototype, "fileUploadResponse", void 0);
  348. __decorate([
  349. Output(),
  350. __metadata("design:type", Object)
  351. ], CKEditorComponent.prototype, "paste", void 0);
  352. __decorate([
  353. Output(),
  354. __metadata("design:type", Object)
  355. ], CKEditorComponent.prototype, "drop", void 0);
  356. __decorate([
  357. ViewChild('host', { static: false }),
  358. __metadata("design:type", Object)
  359. ], CKEditorComponent.prototype, "host", void 0);
  360. __decorate([
  361. ContentChildren(CKButtonDirective),
  362. __metadata("design:type", QueryList)
  363. ], CKEditorComponent.prototype, "toolbarButtons", void 0);
  364. __decorate([
  365. ContentChildren(CKGroupDirective),
  366. __metadata("design:type", QueryList)
  367. ], CKEditorComponent.prototype, "toolbarGroups", void 0);
  368. __decorate([
  369. Input(),
  370. __metadata("design:type", Object),
  371. __metadata("design:paramtypes", [Object])
  372. ], CKEditorComponent.prototype, "value", null);
  373. CKEditorComponent = CKEditorComponent_1 = __decorate([
  374. Component({
  375. selector: 'ckeditor',
  376. providers: [
  377. {
  378. provide: NG_VALUE_ACCESSOR,
  379. useExisting: forwardRef(() => CKEditorComponent_1),
  380. multi: true,
  381. },
  382. ],
  383. template: `
  384. <textarea #host></textarea>
  385. `
  386. }),
  387. __metadata("design:paramtypes", [NgZone])
  388. ], CKEditorComponent);
  389. /**
  390. * CKEditorModule
  391. */
  392. let CKEditorModule = class CKEditorModule {
  393. };
  394. CKEditorModule = __decorate([
  395. NgModule({
  396. imports: [CommonModule],
  397. declarations: [CKEditorComponent, CKButtonDirective, CKGroupDirective],
  398. exports: [CKEditorComponent, CKButtonDirective, CKGroupDirective],
  399. })
  400. ], CKEditorModule);
  401. /**
  402. * Generated bundle index. Do not edit.
  403. */
  404. export { CKEditorModule, CKEditorComponent as ɵa, CKButtonDirective as ɵb, CKGroupDirective as ɵc };
  405. //# sourceMappingURL=ng2-ckeditor.js.map