aboutsummaryrefslogtreecommitdiff
path: root/sources/plugins
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2017-01-20 00:55:51 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2017-01-20 00:55:51 +0100
commitc63493c899de714b05b0521bb38aab60d19030ef (patch)
treefcb2b261afa0f3c2bd6b48929b64724c71192bae /sources/plugins
downloadludivine-ckeditor-component-c63493c899de714b05b0521bb38aab60d19030ef.tar.gz
ludivine-ckeditor-component-c63493c899de714b05b0521bb38aab60d19030ef.tar.zst
ludivine-ckeditor-component-c63493c899de714b05b0521bb38aab60d19030ef.zip
Validation initiale4.6.2.1
Diffstat (limited to 'sources/plugins')
-rw-r--r--sources/plugins/a11yhelp/dialogs/a11yhelp.js217
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/_translationstatus.txt25
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/af.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ar.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/az.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/bg.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ca.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/cs.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/cy.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/da.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/de-ch.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/de.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/el.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/en-gb.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/en.js159
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/eo.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/es.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/et.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/eu.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fa.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fi.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fo.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fr-ca.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fr.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/gl.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/gu.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/he.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/hi.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/hr.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/hu.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/id.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/it.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ja.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/km.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ko.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ku.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/lt.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/lv.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/mk.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/mn.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/nb.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/nl.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/no.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/oc.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/pl.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/pt-br.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/pt.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ro.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ru.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/si.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sk.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sl.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sq.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sr-latn.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sr.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sv.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/th.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/tr.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/tt.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ug.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/uk.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/vi.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/zh-cn.js140
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/zh.js140
-rw-r--r--sources/plugins/a11yhelp/plugin.js51
-rw-r--r--sources/plugins/basicstyles/icons/bold.pngbin0 -> 580 bytes
-rw-r--r--sources/plugins/basicstyles/icons/hidpi/bold.pngbin0 -> 1207 bytes
-rw-r--r--sources/plugins/basicstyles/icons/hidpi/italic.pngbin0 -> 854 bytes
-rw-r--r--sources/plugins/basicstyles/icons/hidpi/strike.pngbin0 -> 1357 bytes
-rw-r--r--sources/plugins/basicstyles/icons/hidpi/subscript.pngbin0 -> 1189 bytes
-rw-r--r--sources/plugins/basicstyles/icons/hidpi/superscript.pngbin0 -> 1156 bytes
-rw-r--r--sources/plugins/basicstyles/icons/hidpi/underline.pngbin0 -> 1084 bytes
-rw-r--r--sources/plugins/basicstyles/icons/italic.pngbin0 -> 611 bytes
-rw-r--r--sources/plugins/basicstyles/icons/strike.pngbin0 -> 627 bytes
-rw-r--r--sources/plugins/basicstyles/icons/subscript.pngbin0 -> 584 bytes
-rw-r--r--sources/plugins/basicstyles/icons/superscript.pngbin0 -> 594 bytes
-rw-r--r--sources/plugins/basicstyles/icons/underline.pngbin0 -> 541 bytes
-rw-r--r--sources/plugins/basicstyles/lang/af.js12
-rw-r--r--sources/plugins/basicstyles/lang/ar.js12
-rw-r--r--sources/plugins/basicstyles/lang/az.js12
-rw-r--r--sources/plugins/basicstyles/lang/bg.js12
-rw-r--r--sources/plugins/basicstyles/lang/bn.js12
-rw-r--r--sources/plugins/basicstyles/lang/bs.js12
-rw-r--r--sources/plugins/basicstyles/lang/ca.js12
-rw-r--r--sources/plugins/basicstyles/lang/cs.js12
-rw-r--r--sources/plugins/basicstyles/lang/cy.js12
-rw-r--r--sources/plugins/basicstyles/lang/da.js12
-rw-r--r--sources/plugins/basicstyles/lang/de-ch.js12
-rw-r--r--sources/plugins/basicstyles/lang/de.js12
-rw-r--r--sources/plugins/basicstyles/lang/el.js12
-rw-r--r--sources/plugins/basicstyles/lang/en-au.js12
-rw-r--r--sources/plugins/basicstyles/lang/en-ca.js12
-rw-r--r--sources/plugins/basicstyles/lang/en-gb.js12
-rw-r--r--sources/plugins/basicstyles/lang/en.js12
-rw-r--r--sources/plugins/basicstyles/lang/eo.js12
-rw-r--r--sources/plugins/basicstyles/lang/es.js12
-rw-r--r--sources/plugins/basicstyles/lang/et.js12
-rw-r--r--sources/plugins/basicstyles/lang/eu.js12
-rw-r--r--sources/plugins/basicstyles/lang/fa.js12
-rw-r--r--sources/plugins/basicstyles/lang/fi.js12
-rw-r--r--sources/plugins/basicstyles/lang/fo.js12
-rw-r--r--sources/plugins/basicstyles/lang/fr-ca.js12
-rw-r--r--sources/plugins/basicstyles/lang/fr.js12
-rw-r--r--sources/plugins/basicstyles/lang/gl.js12
-rw-r--r--sources/plugins/basicstyles/lang/gu.js12
-rw-r--r--sources/plugins/basicstyles/lang/he.js12
-rw-r--r--sources/plugins/basicstyles/lang/hi.js12
-rw-r--r--sources/plugins/basicstyles/lang/hr.js12
-rw-r--r--sources/plugins/basicstyles/lang/hu.js12
-rw-r--r--sources/plugins/basicstyles/lang/id.js12
-rw-r--r--sources/plugins/basicstyles/lang/is.js12
-rw-r--r--sources/plugins/basicstyles/lang/it.js12
-rw-r--r--sources/plugins/basicstyles/lang/ja.js12
-rw-r--r--sources/plugins/basicstyles/lang/ka.js12
-rw-r--r--sources/plugins/basicstyles/lang/km.js12
-rw-r--r--sources/plugins/basicstyles/lang/ko.js12
-rw-r--r--sources/plugins/basicstyles/lang/ku.js12
-rw-r--r--sources/plugins/basicstyles/lang/lt.js12
-rw-r--r--sources/plugins/basicstyles/lang/lv.js12
-rw-r--r--sources/plugins/basicstyles/lang/mk.js12
-rw-r--r--sources/plugins/basicstyles/lang/mn.js12
-rw-r--r--sources/plugins/basicstyles/lang/ms.js12
-rw-r--r--sources/plugins/basicstyles/lang/nb.js12
-rw-r--r--sources/plugins/basicstyles/lang/nl.js12
-rw-r--r--sources/plugins/basicstyles/lang/no.js12
-rw-r--r--sources/plugins/basicstyles/lang/oc.js12
-rw-r--r--sources/plugins/basicstyles/lang/pl.js12
-rw-r--r--sources/plugins/basicstyles/lang/pt-br.js12
-rw-r--r--sources/plugins/basicstyles/lang/pt.js12
-rw-r--r--sources/plugins/basicstyles/lang/ro.js12
-rw-r--r--sources/plugins/basicstyles/lang/ru.js12
-rw-r--r--sources/plugins/basicstyles/lang/si.js12
-rw-r--r--sources/plugins/basicstyles/lang/sk.js12
-rw-r--r--sources/plugins/basicstyles/lang/sl.js12
-rw-r--r--sources/plugins/basicstyles/lang/sq.js12
-rw-r--r--sources/plugins/basicstyles/lang/sr-latn.js12
-rw-r--r--sources/plugins/basicstyles/lang/sr.js12
-rw-r--r--sources/plugins/basicstyles/lang/sv.js12
-rw-r--r--sources/plugins/basicstyles/lang/th.js12
-rw-r--r--sources/plugins/basicstyles/lang/tr.js12
-rw-r--r--sources/plugins/basicstyles/lang/tt.js12
-rw-r--r--sources/plugins/basicstyles/lang/ug.js12
-rw-r--r--sources/plugins/basicstyles/lang/uk.js12
-rw-r--r--sources/plugins/basicstyles/lang/vi.js12
-rw-r--r--sources/plugins/basicstyles/lang/zh-cn.js12
-rw-r--r--sources/plugins/basicstyles/lang/zh.js12
-rw-r--r--sources/plugins/basicstyles/plugin.js209
-rw-r--r--sources/plugins/button/lang/af.js8
-rw-r--r--sources/plugins/button/lang/ar.js8
-rw-r--r--sources/plugins/button/lang/az.js8
-rw-r--r--sources/plugins/button/lang/bg.js8
-rw-r--r--sources/plugins/button/lang/ca.js8
-rw-r--r--sources/plugins/button/lang/cs.js8
-rw-r--r--sources/plugins/button/lang/da.js8
-rw-r--r--sources/plugins/button/lang/de-ch.js8
-rw-r--r--sources/plugins/button/lang/de.js8
-rw-r--r--sources/plugins/button/lang/el.js8
-rw-r--r--sources/plugins/button/lang/en-gb.js8
-rw-r--r--sources/plugins/button/lang/en.js8
-rw-r--r--sources/plugins/button/lang/eo.js8
-rw-r--r--sources/plugins/button/lang/es.js8
-rw-r--r--sources/plugins/button/lang/eu.js8
-rw-r--r--sources/plugins/button/lang/fa.js8
-rw-r--r--sources/plugins/button/lang/fi.js8
-rw-r--r--sources/plugins/button/lang/fr.js8
-rw-r--r--sources/plugins/button/lang/gl.js8
-rw-r--r--sources/plugins/button/lang/he.js8
-rw-r--r--sources/plugins/button/lang/hu.js8
-rw-r--r--sources/plugins/button/lang/id.js8
-rw-r--r--sources/plugins/button/lang/it.js8
-rw-r--r--sources/plugins/button/lang/ja.js8
-rw-r--r--sources/plugins/button/lang/km.js8
-rw-r--r--sources/plugins/button/lang/ko.js8
-rw-r--r--sources/plugins/button/lang/ku.js8
-rw-r--r--sources/plugins/button/lang/lt.js8
-rw-r--r--sources/plugins/button/lang/nb.js8
-rw-r--r--sources/plugins/button/lang/nl.js8
-rw-r--r--sources/plugins/button/lang/no.js8
-rw-r--r--sources/plugins/button/lang/oc.js8
-rw-r--r--sources/plugins/button/lang/pl.js8
-rw-r--r--sources/plugins/button/lang/pt-br.js8
-rw-r--r--sources/plugins/button/lang/pt.js8
-rw-r--r--sources/plugins/button/lang/ro.js8
-rw-r--r--sources/plugins/button/lang/ru.js8
-rw-r--r--sources/plugins/button/lang/sk.js8
-rw-r--r--sources/plugins/button/lang/sl.js8
-rw-r--r--sources/plugins/button/lang/sq.js8
-rw-r--r--sources/plugins/button/lang/sv.js8
-rw-r--r--sources/plugins/button/lang/tr.js8
-rw-r--r--sources/plugins/button/lang/tt.js8
-rw-r--r--sources/plugins/button/lang/ug.js8
-rw-r--r--sources/plugins/button/lang/uk.js8
-rw-r--r--sources/plugins/button/lang/vi.js8
-rw-r--r--sources/plugins/button/lang/zh-cn.js8
-rw-r--r--sources/plugins/button/lang/zh.js8
-rw-r--r--sources/plugins/button/plugin.js389
-rw-r--r--sources/plugins/clipboard/dev/clipboard.html190
-rw-r--r--sources/plugins/clipboard/dev/console.js49
-rw-r--r--sources/plugins/clipboard/dev/dnd.html185
-rw-r--r--sources/plugins/clipboard/dialogs/paste.js254
-rw-r--r--sources/plugins/clipboard/icons/copy-rtl.pngbin0 -> 506 bytes
-rw-r--r--sources/plugins/clipboard/icons/copy.pngbin0 -> 506 bytes
-rw-r--r--sources/plugins/clipboard/icons/cut-rtl.pngbin0 -> 776 bytes
-rw-r--r--sources/plugins/clipboard/icons/cut.pngbin0 -> 776 bytes
-rw-r--r--sources/plugins/clipboard/icons/hidpi/copy-rtl.pngbin0 -> 759 bytes
-rw-r--r--sources/plugins/clipboard/icons/hidpi/copy.pngbin0 -> 759 bytes
-rw-r--r--sources/plugins/clipboard/icons/hidpi/cut-rtl.pngbin0 -> 1576 bytes
-rw-r--r--sources/plugins/clipboard/icons/hidpi/cut.pngbin0 -> 1576 bytes
-rw-r--r--sources/plugins/clipboard/icons/hidpi/paste-rtl.pngbin0 -> 854 bytes
-rw-r--r--sources/plugins/clipboard/icons/hidpi/paste.pngbin0 -> 854 bytes
-rw-r--r--sources/plugins/clipboard/icons/paste-rtl.pngbin0 -> 464 bytes
-rw-r--r--sources/plugins/clipboard/icons/paste.pngbin0 -> 464 bytes
-rw-r--r--sources/plugins/clipboard/lang/af.js15
-rw-r--r--sources/plugins/clipboard/lang/ar.js15
-rw-r--r--sources/plugins/clipboard/lang/az.js15
-rw-r--r--sources/plugins/clipboard/lang/bg.js15
-rw-r--r--sources/plugins/clipboard/lang/bn.js15
-rw-r--r--sources/plugins/clipboard/lang/bs.js15
-rw-r--r--sources/plugins/clipboard/lang/ca.js15
-rw-r--r--sources/plugins/clipboard/lang/cs.js15
-rw-r--r--sources/plugins/clipboard/lang/cy.js15
-rw-r--r--sources/plugins/clipboard/lang/da.js15
-rw-r--r--sources/plugins/clipboard/lang/de-ch.js15
-rw-r--r--sources/plugins/clipboard/lang/de.js15
-rw-r--r--sources/plugins/clipboard/lang/el.js15
-rw-r--r--sources/plugins/clipboard/lang/en-au.js15
-rw-r--r--sources/plugins/clipboard/lang/en-ca.js15
-rw-r--r--sources/plugins/clipboard/lang/en-gb.js15
-rw-r--r--sources/plugins/clipboard/lang/en.js15
-rw-r--r--sources/plugins/clipboard/lang/eo.js15
-rw-r--r--sources/plugins/clipboard/lang/es.js15
-rw-r--r--sources/plugins/clipboard/lang/et.js15
-rw-r--r--sources/plugins/clipboard/lang/eu.js15
-rw-r--r--sources/plugins/clipboard/lang/fa.js15
-rw-r--r--sources/plugins/clipboard/lang/fi.js15
-rw-r--r--sources/plugins/clipboard/lang/fo.js15
-rw-r--r--sources/plugins/clipboard/lang/fr-ca.js15
-rw-r--r--sources/plugins/clipboard/lang/fr.js15
-rw-r--r--sources/plugins/clipboard/lang/gl.js15
-rw-r--r--sources/plugins/clipboard/lang/gu.js15
-rw-r--r--sources/plugins/clipboard/lang/he.js15
-rw-r--r--sources/plugins/clipboard/lang/hi.js15
-rw-r--r--sources/plugins/clipboard/lang/hr.js15
-rw-r--r--sources/plugins/clipboard/lang/hu.js15
-rw-r--r--sources/plugins/clipboard/lang/id.js15
-rw-r--r--sources/plugins/clipboard/lang/is.js15
-rw-r--r--sources/plugins/clipboard/lang/it.js15
-rw-r--r--sources/plugins/clipboard/lang/ja.js15
-rw-r--r--sources/plugins/clipboard/lang/ka.js15
-rw-r--r--sources/plugins/clipboard/lang/km.js15
-rw-r--r--sources/plugins/clipboard/lang/ko.js15
-rw-r--r--sources/plugins/clipboard/lang/ku.js15
-rw-r--r--sources/plugins/clipboard/lang/lt.js15
-rw-r--r--sources/plugins/clipboard/lang/lv.js15
-rw-r--r--sources/plugins/clipboard/lang/mk.js15
-rw-r--r--sources/plugins/clipboard/lang/mn.js15
-rw-r--r--sources/plugins/clipboard/lang/ms.js15
-rw-r--r--sources/plugins/clipboard/lang/nb.js15
-rw-r--r--sources/plugins/clipboard/lang/nl.js15
-rw-r--r--sources/plugins/clipboard/lang/no.js15
-rw-r--r--sources/plugins/clipboard/lang/oc.js15
-rw-r--r--sources/plugins/clipboard/lang/pl.js15
-rw-r--r--sources/plugins/clipboard/lang/pt-br.js15
-rw-r--r--sources/plugins/clipboard/lang/pt.js15
-rw-r--r--sources/plugins/clipboard/lang/ro.js15
-rw-r--r--sources/plugins/clipboard/lang/ru.js15
-rw-r--r--sources/plugins/clipboard/lang/si.js15
-rw-r--r--sources/plugins/clipboard/lang/sk.js15
-rw-r--r--sources/plugins/clipboard/lang/sl.js15
-rw-r--r--sources/plugins/clipboard/lang/sq.js15
-rw-r--r--sources/plugins/clipboard/lang/sr-latn.js15
-rw-r--r--sources/plugins/clipboard/lang/sr.js15
-rw-r--r--sources/plugins/clipboard/lang/sv.js15
-rw-r--r--sources/plugins/clipboard/lang/th.js15
-rw-r--r--sources/plugins/clipboard/lang/tr.js15
-rw-r--r--sources/plugins/clipboard/lang/tt.js15
-rw-r--r--sources/plugins/clipboard/lang/ug.js15
-rw-r--r--sources/plugins/clipboard/lang/uk.js15
-rw-r--r--sources/plugins/clipboard/lang/vi.js15
-rw-r--r--sources/plugins/clipboard/lang/zh-cn.js15
-rw-r--r--sources/plugins/clipboard/lang/zh.js15
-rw-r--r--sources/plugins/clipboard/plugin.js2772
-rw-r--r--sources/plugins/contextmenu/lang/af.js7
-rw-r--r--sources/plugins/contextmenu/lang/ar.js7
-rw-r--r--sources/plugins/contextmenu/lang/az.js7
-rw-r--r--sources/plugins/contextmenu/lang/bg.js7
-rw-r--r--sources/plugins/contextmenu/lang/bn.js7
-rw-r--r--sources/plugins/contextmenu/lang/bs.js7
-rw-r--r--sources/plugins/contextmenu/lang/ca.js7
-rw-r--r--sources/plugins/contextmenu/lang/cs.js7
-rw-r--r--sources/plugins/contextmenu/lang/cy.js7
-rw-r--r--sources/plugins/contextmenu/lang/da.js7
-rw-r--r--sources/plugins/contextmenu/lang/de-ch.js7
-rw-r--r--sources/plugins/contextmenu/lang/de.js7
-rw-r--r--sources/plugins/contextmenu/lang/el.js7
-rw-r--r--sources/plugins/contextmenu/lang/en-au.js7
-rw-r--r--sources/plugins/contextmenu/lang/en-ca.js7
-rw-r--r--sources/plugins/contextmenu/lang/en-gb.js7
-rw-r--r--sources/plugins/contextmenu/lang/en.js7
-rw-r--r--sources/plugins/contextmenu/lang/eo.js7
-rw-r--r--sources/plugins/contextmenu/lang/es.js7
-rw-r--r--sources/plugins/contextmenu/lang/et.js7
-rw-r--r--sources/plugins/contextmenu/lang/eu.js7
-rw-r--r--sources/plugins/contextmenu/lang/fa.js7
-rw-r--r--sources/plugins/contextmenu/lang/fi.js7
-rw-r--r--sources/plugins/contextmenu/lang/fo.js7
-rw-r--r--sources/plugins/contextmenu/lang/fr-ca.js7
-rw-r--r--sources/plugins/contextmenu/lang/fr.js7
-rw-r--r--sources/plugins/contextmenu/lang/gl.js7
-rw-r--r--sources/plugins/contextmenu/lang/gu.js7
-rw-r--r--sources/plugins/contextmenu/lang/he.js7
-rw-r--r--sources/plugins/contextmenu/lang/hi.js7
-rw-r--r--sources/plugins/contextmenu/lang/hr.js7
-rw-r--r--sources/plugins/contextmenu/lang/hu.js7
-rw-r--r--sources/plugins/contextmenu/lang/id.js7
-rw-r--r--sources/plugins/contextmenu/lang/is.js7
-rw-r--r--sources/plugins/contextmenu/lang/it.js7
-rw-r--r--sources/plugins/contextmenu/lang/ja.js7
-rw-r--r--sources/plugins/contextmenu/lang/ka.js7
-rw-r--r--sources/plugins/contextmenu/lang/km.js7
-rw-r--r--sources/plugins/contextmenu/lang/ko.js7
-rw-r--r--sources/plugins/contextmenu/lang/ku.js7
-rw-r--r--sources/plugins/contextmenu/lang/lt.js7
-rw-r--r--sources/plugins/contextmenu/lang/lv.js7
-rw-r--r--sources/plugins/contextmenu/lang/mk.js7
-rw-r--r--sources/plugins/contextmenu/lang/mn.js7
-rw-r--r--sources/plugins/contextmenu/lang/ms.js7
-rw-r--r--sources/plugins/contextmenu/lang/nb.js7
-rw-r--r--sources/plugins/contextmenu/lang/nl.js7
-rw-r--r--sources/plugins/contextmenu/lang/no.js7
-rw-r--r--sources/plugins/contextmenu/lang/oc.js7
-rw-r--r--sources/plugins/contextmenu/lang/pl.js7
-rw-r--r--sources/plugins/contextmenu/lang/pt-br.js7
-rw-r--r--sources/plugins/contextmenu/lang/pt.js7
-rw-r--r--sources/plugins/contextmenu/lang/ro.js7
-rw-r--r--sources/plugins/contextmenu/lang/ru.js7
-rw-r--r--sources/plugins/contextmenu/lang/si.js7
-rw-r--r--sources/plugins/contextmenu/lang/sk.js7
-rw-r--r--sources/plugins/contextmenu/lang/sl.js7
-rw-r--r--sources/plugins/contextmenu/lang/sq.js7
-rw-r--r--sources/plugins/contextmenu/lang/sr-latn.js7
-rw-r--r--sources/plugins/contextmenu/lang/sr.js7
-rw-r--r--sources/plugins/contextmenu/lang/sv.js7
-rw-r--r--sources/plugins/contextmenu/lang/th.js7
-rw-r--r--sources/plugins/contextmenu/lang/tr.js7
-rw-r--r--sources/plugins/contextmenu/lang/tt.js7
-rw-r--r--sources/plugins/contextmenu/lang/ug.js7
-rw-r--r--sources/plugins/contextmenu/lang/uk.js7
-rw-r--r--sources/plugins/contextmenu/lang/vi.js7
-rw-r--r--sources/plugins/contextmenu/lang/zh-cn.js7
-rw-r--r--sources/plugins/contextmenu/lang/zh.js7
-rw-r--r--sources/plugins/contextmenu/plugin.js159
-rw-r--r--sources/plugins/dialog/dialogDefinition.js1032
-rw-r--r--sources/plugins/dialog/plugin.js3399
-rw-r--r--sources/plugins/dialog/samples/assets/my_dialog.js49
-rw-r--r--sources/plugins/dialog/samples/dialog.html190
-rw-r--r--sources/plugins/dialogadvtab/plugin.js196
-rw-r--r--sources/plugins/dialogui/plugin.js1530
-rw-r--r--sources/plugins/elementspath/lang/af.js8
-rw-r--r--sources/plugins/elementspath/lang/ar.js8
-rw-r--r--sources/plugins/elementspath/lang/az.js8
-rw-r--r--sources/plugins/elementspath/lang/bg.js8
-rw-r--r--sources/plugins/elementspath/lang/bn.js8
-rw-r--r--sources/plugins/elementspath/lang/bs.js8
-rw-r--r--sources/plugins/elementspath/lang/ca.js8
-rw-r--r--sources/plugins/elementspath/lang/cs.js8
-rw-r--r--sources/plugins/elementspath/lang/cy.js8
-rw-r--r--sources/plugins/elementspath/lang/da.js8
-rw-r--r--sources/plugins/elementspath/lang/de-ch.js8
-rw-r--r--sources/plugins/elementspath/lang/de.js8
-rw-r--r--sources/plugins/elementspath/lang/el.js8
-rw-r--r--sources/plugins/elementspath/lang/en-au.js8
-rw-r--r--sources/plugins/elementspath/lang/en-ca.js8
-rw-r--r--sources/plugins/elementspath/lang/en-gb.js8
-rw-r--r--sources/plugins/elementspath/lang/en.js8
-rw-r--r--sources/plugins/elementspath/lang/eo.js8
-rw-r--r--sources/plugins/elementspath/lang/es.js8
-rw-r--r--sources/plugins/elementspath/lang/et.js8
-rw-r--r--sources/plugins/elementspath/lang/eu.js8
-rw-r--r--sources/plugins/elementspath/lang/fa.js8
-rw-r--r--sources/plugins/elementspath/lang/fi.js8
-rw-r--r--sources/plugins/elementspath/lang/fo.js8
-rw-r--r--sources/plugins/elementspath/lang/fr-ca.js8
-rw-r--r--sources/plugins/elementspath/lang/fr.js8
-rw-r--r--sources/plugins/elementspath/lang/gl.js8
-rw-r--r--sources/plugins/elementspath/lang/gu.js8
-rw-r--r--sources/plugins/elementspath/lang/he.js8
-rw-r--r--sources/plugins/elementspath/lang/hi.js8
-rw-r--r--sources/plugins/elementspath/lang/hr.js8
-rw-r--r--sources/plugins/elementspath/lang/hu.js8
-rw-r--r--sources/plugins/elementspath/lang/is.js8
-rw-r--r--sources/plugins/elementspath/lang/it.js8
-rw-r--r--sources/plugins/elementspath/lang/ja.js8
-rw-r--r--sources/plugins/elementspath/lang/ka.js8
-rw-r--r--sources/plugins/elementspath/lang/km.js8
-rw-r--r--sources/plugins/elementspath/lang/ko.js8
-rw-r--r--sources/plugins/elementspath/lang/ku.js8
-rw-r--r--sources/plugins/elementspath/lang/lt.js8
-rw-r--r--sources/plugins/elementspath/lang/lv.js8
-rw-r--r--sources/plugins/elementspath/lang/mk.js8
-rw-r--r--sources/plugins/elementspath/lang/mn.js8
-rw-r--r--sources/plugins/elementspath/lang/ms.js8
-rw-r--r--sources/plugins/elementspath/lang/nb.js8
-rw-r--r--sources/plugins/elementspath/lang/nl.js8
-rw-r--r--sources/plugins/elementspath/lang/no.js8
-rw-r--r--sources/plugins/elementspath/lang/oc.js8
-rw-r--r--sources/plugins/elementspath/lang/pl.js8
-rw-r--r--sources/plugins/elementspath/lang/pt-br.js8
-rw-r--r--sources/plugins/elementspath/lang/pt.js8
-rw-r--r--sources/plugins/elementspath/lang/ro.js8
-rw-r--r--sources/plugins/elementspath/lang/ru.js8
-rw-r--r--sources/plugins/elementspath/lang/si.js8
-rw-r--r--sources/plugins/elementspath/lang/sk.js8
-rw-r--r--sources/plugins/elementspath/lang/sl.js8
-rw-r--r--sources/plugins/elementspath/lang/sq.js8
-rw-r--r--sources/plugins/elementspath/lang/sr-latn.js8
-rw-r--r--sources/plugins/elementspath/lang/sr.js8
-rw-r--r--sources/plugins/elementspath/lang/sv.js8
-rw-r--r--sources/plugins/elementspath/lang/th.js8
-rw-r--r--sources/plugins/elementspath/lang/tr.js8
-rw-r--r--sources/plugins/elementspath/lang/tt.js8
-rw-r--r--sources/plugins/elementspath/lang/ug.js8
-rw-r--r--sources/plugins/elementspath/lang/uk.js8
-rw-r--r--sources/plugins/elementspath/lang/vi.js8
-rw-r--r--sources/plugins/elementspath/lang/zh-cn.js8
-rw-r--r--sources/plugins/elementspath/lang/zh.js8
-rw-r--r--sources/plugins/elementspath/plugin.js244
-rw-r--r--sources/plugins/enterkey/plugin.js566
-rw-r--r--sources/plugins/enterkey/samples/enterkey.html106
-rw-r--r--sources/plugins/entities/plugin.js239
-rw-r--r--sources/plugins/fakeobjects/lang/af.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ar.js11
-rw-r--r--sources/plugins/fakeobjects/lang/az.js11
-rw-r--r--sources/plugins/fakeobjects/lang/bg.js11
-rw-r--r--sources/plugins/fakeobjects/lang/bn.js11
-rw-r--r--sources/plugins/fakeobjects/lang/bs.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ca.js11
-rw-r--r--sources/plugins/fakeobjects/lang/cs.js11
-rw-r--r--sources/plugins/fakeobjects/lang/cy.js11
-rw-r--r--sources/plugins/fakeobjects/lang/da.js11
-rw-r--r--sources/plugins/fakeobjects/lang/de-ch.js11
-rw-r--r--sources/plugins/fakeobjects/lang/de.js11
-rw-r--r--sources/plugins/fakeobjects/lang/el.js11
-rw-r--r--sources/plugins/fakeobjects/lang/en-au.js11
-rw-r--r--sources/plugins/fakeobjects/lang/en-ca.js11
-rw-r--r--sources/plugins/fakeobjects/lang/en-gb.js11
-rw-r--r--sources/plugins/fakeobjects/lang/en.js11
-rw-r--r--sources/plugins/fakeobjects/lang/eo.js11
-rw-r--r--sources/plugins/fakeobjects/lang/es.js11
-rw-r--r--sources/plugins/fakeobjects/lang/et.js11
-rw-r--r--sources/plugins/fakeobjects/lang/eu.js11
-rw-r--r--sources/plugins/fakeobjects/lang/fa.js11
-rw-r--r--sources/plugins/fakeobjects/lang/fi.js11
-rw-r--r--sources/plugins/fakeobjects/lang/fo.js11
-rw-r--r--sources/plugins/fakeobjects/lang/fr-ca.js11
-rw-r--r--sources/plugins/fakeobjects/lang/fr.js11
-rw-r--r--sources/plugins/fakeobjects/lang/gl.js11
-rw-r--r--sources/plugins/fakeobjects/lang/gu.js11
-rw-r--r--sources/plugins/fakeobjects/lang/he.js11
-rw-r--r--sources/plugins/fakeobjects/lang/hi.js11
-rw-r--r--sources/plugins/fakeobjects/lang/hr.js11
-rw-r--r--sources/plugins/fakeobjects/lang/hu.js11
-rw-r--r--sources/plugins/fakeobjects/lang/id.js11
-rw-r--r--sources/plugins/fakeobjects/lang/is.js11
-rw-r--r--sources/plugins/fakeobjects/lang/it.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ja.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ka.js11
-rw-r--r--sources/plugins/fakeobjects/lang/km.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ko.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ku.js11
-rw-r--r--sources/plugins/fakeobjects/lang/lt.js11
-rw-r--r--sources/plugins/fakeobjects/lang/lv.js11
-rw-r--r--sources/plugins/fakeobjects/lang/mk.js11
-rw-r--r--sources/plugins/fakeobjects/lang/mn.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ms.js11
-rw-r--r--sources/plugins/fakeobjects/lang/nb.js11
-rw-r--r--sources/plugins/fakeobjects/lang/nl.js11
-rw-r--r--sources/plugins/fakeobjects/lang/no.js11
-rw-r--r--sources/plugins/fakeobjects/lang/oc.js11
-rw-r--r--sources/plugins/fakeobjects/lang/pl.js11
-rw-r--r--sources/plugins/fakeobjects/lang/pt-br.js11
-rw-r--r--sources/plugins/fakeobjects/lang/pt.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ro.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ru.js11
-rw-r--r--sources/plugins/fakeobjects/lang/si.js11
-rw-r--r--sources/plugins/fakeobjects/lang/sk.js11
-rw-r--r--sources/plugins/fakeobjects/lang/sl.js11
-rw-r--r--sources/plugins/fakeobjects/lang/sq.js11
-rw-r--r--sources/plugins/fakeobjects/lang/sr-latn.js11
-rw-r--r--sources/plugins/fakeobjects/lang/sr.js11
-rw-r--r--sources/plugins/fakeobjects/lang/sv.js11
-rw-r--r--sources/plugins/fakeobjects/lang/th.js11
-rw-r--r--sources/plugins/fakeobjects/lang/tr.js11
-rw-r--r--sources/plugins/fakeobjects/lang/tt.js11
-rw-r--r--sources/plugins/fakeobjects/lang/ug.js11
-rw-r--r--sources/plugins/fakeobjects/lang/uk.js11
-rw-r--r--sources/plugins/fakeobjects/lang/vi.js11
-rw-r--r--sources/plugins/fakeobjects/lang/zh-cn.js11
-rw-r--r--sources/plugins/fakeobjects/lang/zh.js11
-rw-r--r--sources/plugins/fakeobjects/plugin.js183
-rw-r--r--sources/plugins/filebrowser/plugin.js573
-rw-r--r--sources/plugins/floatingspace/plugin.js406
-rw-r--r--sources/plugins/floatpanel/plugin.js598
-rw-r--r--sources/plugins/format/lang/af.js18
-rw-r--r--sources/plugins/format/lang/ar.js18
-rw-r--r--sources/plugins/format/lang/az.js18
-rw-r--r--sources/plugins/format/lang/bg.js18
-rw-r--r--sources/plugins/format/lang/bn.js18
-rw-r--r--sources/plugins/format/lang/bs.js18
-rw-r--r--sources/plugins/format/lang/ca.js18
-rw-r--r--sources/plugins/format/lang/cs.js18
-rw-r--r--sources/plugins/format/lang/cy.js18
-rw-r--r--sources/plugins/format/lang/da.js18
-rw-r--r--sources/plugins/format/lang/de-ch.js18
-rw-r--r--sources/plugins/format/lang/de.js18
-rw-r--r--sources/plugins/format/lang/el.js18
-rw-r--r--sources/plugins/format/lang/en-au.js18
-rw-r--r--sources/plugins/format/lang/en-ca.js18
-rw-r--r--sources/plugins/format/lang/en-gb.js18
-rw-r--r--sources/plugins/format/lang/en.js18
-rw-r--r--sources/plugins/format/lang/eo.js18
-rw-r--r--sources/plugins/format/lang/es.js18
-rw-r--r--sources/plugins/format/lang/et.js18
-rw-r--r--sources/plugins/format/lang/eu.js18
-rw-r--r--sources/plugins/format/lang/fa.js18
-rw-r--r--sources/plugins/format/lang/fi.js18
-rw-r--r--sources/plugins/format/lang/fo.js18
-rw-r--r--sources/plugins/format/lang/fr-ca.js18
-rw-r--r--sources/plugins/format/lang/fr.js18
-rw-r--r--sources/plugins/format/lang/gl.js18
-rw-r--r--sources/plugins/format/lang/gu.js18
-rw-r--r--sources/plugins/format/lang/he.js18
-rw-r--r--sources/plugins/format/lang/hi.js18
-rw-r--r--sources/plugins/format/lang/hr.js18
-rw-r--r--sources/plugins/format/lang/hu.js18
-rw-r--r--sources/plugins/format/lang/id.js18
-rw-r--r--sources/plugins/format/lang/is.js18
-rw-r--r--sources/plugins/format/lang/it.js18
-rw-r--r--sources/plugins/format/lang/ja.js18
-rw-r--r--sources/plugins/format/lang/ka.js18
-rw-r--r--sources/plugins/format/lang/km.js18
-rw-r--r--sources/plugins/format/lang/ko.js18
-rw-r--r--sources/plugins/format/lang/ku.js18
-rw-r--r--sources/plugins/format/lang/lt.js18
-rw-r--r--sources/plugins/format/lang/lv.js18
-rw-r--r--sources/plugins/format/lang/mk.js18
-rw-r--r--sources/plugins/format/lang/mn.js18
-rw-r--r--sources/plugins/format/lang/ms.js18
-rw-r--r--sources/plugins/format/lang/nb.js18
-rw-r--r--sources/plugins/format/lang/nl.js18
-rw-r--r--sources/plugins/format/lang/no.js18
-rw-r--r--sources/plugins/format/lang/oc.js18
-rw-r--r--sources/plugins/format/lang/pl.js18
-rw-r--r--sources/plugins/format/lang/pt-br.js18
-rw-r--r--sources/plugins/format/lang/pt.js18
-rw-r--r--sources/plugins/format/lang/ro.js18
-rw-r--r--sources/plugins/format/lang/ru.js18
-rw-r--r--sources/plugins/format/lang/si.js18
-rw-r--r--sources/plugins/format/lang/sk.js18
-rw-r--r--sources/plugins/format/lang/sl.js18
-rw-r--r--sources/plugins/format/lang/sq.js18
-rw-r--r--sources/plugins/format/lang/sr-latn.js18
-rw-r--r--sources/plugins/format/lang/sr.js18
-rw-r--r--sources/plugins/format/lang/sv.js18
-rw-r--r--sources/plugins/format/lang/th.js18
-rw-r--r--sources/plugins/format/lang/tr.js18
-rw-r--r--sources/plugins/format/lang/tt.js18
-rw-r--r--sources/plugins/format/lang/ug.js18
-rw-r--r--sources/plugins/format/lang/uk.js18
-rw-r--r--sources/plugins/format/lang/vi.js18
-rw-r--r--sources/plugins/format/lang/zh-cn.js18
-rw-r--r--sources/plugins/format/lang/zh.js18
-rw-r--r--sources/plugins/format/plugin.js279
-rw-r--r--sources/plugins/horizontalrule/icons/hidpi/horizontalrule.pngbin0 -> 530 bytes
-rw-r--r--sources/plugins/horizontalrule/icons/horizontalrule.pngbin0 -> 432 bytes
-rw-r--r--sources/plugins/horizontalrule/lang/af.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ar.js7
-rw-r--r--sources/plugins/horizontalrule/lang/az.js7
-rw-r--r--sources/plugins/horizontalrule/lang/bg.js7
-rw-r--r--sources/plugins/horizontalrule/lang/bn.js7
-rw-r--r--sources/plugins/horizontalrule/lang/bs.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ca.js7
-rw-r--r--sources/plugins/horizontalrule/lang/cs.js7
-rw-r--r--sources/plugins/horizontalrule/lang/cy.js7
-rw-r--r--sources/plugins/horizontalrule/lang/da.js7
-rw-r--r--sources/plugins/horizontalrule/lang/de-ch.js7
-rw-r--r--sources/plugins/horizontalrule/lang/de.js7
-rw-r--r--sources/plugins/horizontalrule/lang/el.js7
-rw-r--r--sources/plugins/horizontalrule/lang/en-au.js7
-rw-r--r--sources/plugins/horizontalrule/lang/en-ca.js7
-rw-r--r--sources/plugins/horizontalrule/lang/en-gb.js7
-rw-r--r--sources/plugins/horizontalrule/lang/en.js7
-rw-r--r--sources/plugins/horizontalrule/lang/eo.js7
-rw-r--r--sources/plugins/horizontalrule/lang/es.js7
-rw-r--r--sources/plugins/horizontalrule/lang/et.js7
-rw-r--r--sources/plugins/horizontalrule/lang/eu.js7
-rw-r--r--sources/plugins/horizontalrule/lang/fa.js7
-rw-r--r--sources/plugins/horizontalrule/lang/fi.js7
-rw-r--r--sources/plugins/horizontalrule/lang/fo.js7
-rw-r--r--sources/plugins/horizontalrule/lang/fr-ca.js7
-rw-r--r--sources/plugins/horizontalrule/lang/fr.js7
-rw-r--r--sources/plugins/horizontalrule/lang/gl.js7
-rw-r--r--sources/plugins/horizontalrule/lang/gu.js7
-rw-r--r--sources/plugins/horizontalrule/lang/he.js7
-rw-r--r--sources/plugins/horizontalrule/lang/hi.js7
-rw-r--r--sources/plugins/horizontalrule/lang/hr.js7
-rw-r--r--sources/plugins/horizontalrule/lang/hu.js7
-rw-r--r--sources/plugins/horizontalrule/lang/id.js7
-rw-r--r--sources/plugins/horizontalrule/lang/is.js7
-rw-r--r--sources/plugins/horizontalrule/lang/it.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ja.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ka.js7
-rw-r--r--sources/plugins/horizontalrule/lang/km.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ko.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ku.js7
-rw-r--r--sources/plugins/horizontalrule/lang/lt.js7
-rw-r--r--sources/plugins/horizontalrule/lang/lv.js7
-rw-r--r--sources/plugins/horizontalrule/lang/mk.js7
-rw-r--r--sources/plugins/horizontalrule/lang/mn.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ms.js7
-rw-r--r--sources/plugins/horizontalrule/lang/nb.js7
-rw-r--r--sources/plugins/horizontalrule/lang/nl.js7
-rw-r--r--sources/plugins/horizontalrule/lang/no.js7
-rw-r--r--sources/plugins/horizontalrule/lang/oc.js7
-rw-r--r--sources/plugins/horizontalrule/lang/pl.js7
-rw-r--r--sources/plugins/horizontalrule/lang/pt-br.js7
-rw-r--r--sources/plugins/horizontalrule/lang/pt.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ro.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ru.js7
-rw-r--r--sources/plugins/horizontalrule/lang/si.js7
-rw-r--r--sources/plugins/horizontalrule/lang/sk.js7
-rw-r--r--sources/plugins/horizontalrule/lang/sl.js7
-rw-r--r--sources/plugins/horizontalrule/lang/sq.js7
-rw-r--r--sources/plugins/horizontalrule/lang/sr-latn.js7
-rw-r--r--sources/plugins/horizontalrule/lang/sr.js7
-rw-r--r--sources/plugins/horizontalrule/lang/sv.js7
-rw-r--r--sources/plugins/horizontalrule/lang/th.js7
-rw-r--r--sources/plugins/horizontalrule/lang/tr.js7
-rw-r--r--sources/plugins/horizontalrule/lang/tt.js7
-rw-r--r--sources/plugins/horizontalrule/lang/ug.js7
-rw-r--r--sources/plugins/horizontalrule/lang/uk.js7
-rw-r--r--sources/plugins/horizontalrule/lang/vi.js7
-rw-r--r--sources/plugins/horizontalrule/lang/zh-cn.js7
-rw-r--r--sources/plugins/horizontalrule/lang/zh.js7
-rw-r--r--sources/plugins/horizontalrule/plugin.js43
-rw-r--r--sources/plugins/htmlwriter/plugin.js360
-rw-r--r--sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.flabin0 -> 85504 bytes
-rw-r--r--sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.swfbin0 -> 15571 bytes
-rw-r--r--sources/plugins/htmlwriter/samples/assets/outputforflash/swfobject.js5
-rw-r--r--sources/plugins/htmlwriter/samples/outputforflash.html283
-rw-r--r--sources/plugins/htmlwriter/samples/outputhtml.html224
-rw-r--r--sources/plugins/iframe/dialogs/iframe.js207
-rw-r--r--sources/plugins/iframe/icons/hidpi/iframe.pngbin0 -> 1837 bytes
-rw-r--r--sources/plugins/iframe/icons/iframe.pngbin0 -> 816 bytes
-rw-r--r--sources/plugins/iframe/images/placeholder.pngbin0 -> 265 bytes
-rw-r--r--sources/plugins/iframe/lang/af.js11
-rw-r--r--sources/plugins/iframe/lang/ar.js11
-rw-r--r--sources/plugins/iframe/lang/az.js11
-rw-r--r--sources/plugins/iframe/lang/bg.js11
-rw-r--r--sources/plugins/iframe/lang/bn.js11
-rw-r--r--sources/plugins/iframe/lang/bs.js11
-rw-r--r--sources/plugins/iframe/lang/ca.js11
-rw-r--r--sources/plugins/iframe/lang/cs.js11
-rw-r--r--sources/plugins/iframe/lang/cy.js11
-rw-r--r--sources/plugins/iframe/lang/da.js11
-rw-r--r--sources/plugins/iframe/lang/de-ch.js11
-rw-r--r--sources/plugins/iframe/lang/de.js11
-rw-r--r--sources/plugins/iframe/lang/el.js11
-rw-r--r--sources/plugins/iframe/lang/en-au.js11
-rw-r--r--sources/plugins/iframe/lang/en-ca.js11
-rw-r--r--sources/plugins/iframe/lang/en-gb.js11
-rw-r--r--sources/plugins/iframe/lang/en.js11
-rw-r--r--sources/plugins/iframe/lang/eo.js11
-rw-r--r--sources/plugins/iframe/lang/es.js11
-rw-r--r--sources/plugins/iframe/lang/et.js11
-rw-r--r--sources/plugins/iframe/lang/eu.js11
-rw-r--r--sources/plugins/iframe/lang/fa.js11
-rw-r--r--sources/plugins/iframe/lang/fi.js11
-rw-r--r--sources/plugins/iframe/lang/fo.js11
-rw-r--r--sources/plugins/iframe/lang/fr-ca.js11
-rw-r--r--sources/plugins/iframe/lang/fr.js11
-rw-r--r--sources/plugins/iframe/lang/gl.js11
-rw-r--r--sources/plugins/iframe/lang/gu.js11
-rw-r--r--sources/plugins/iframe/lang/he.js11
-rw-r--r--sources/plugins/iframe/lang/hi.js11
-rw-r--r--sources/plugins/iframe/lang/hr.js11
-rw-r--r--sources/plugins/iframe/lang/hu.js11
-rw-r--r--sources/plugins/iframe/lang/id.js11
-rw-r--r--sources/plugins/iframe/lang/is.js11
-rw-r--r--sources/plugins/iframe/lang/it.js11
-rw-r--r--sources/plugins/iframe/lang/ja.js11
-rw-r--r--sources/plugins/iframe/lang/ka.js11
-rw-r--r--sources/plugins/iframe/lang/km.js11
-rw-r--r--sources/plugins/iframe/lang/ko.js11
-rw-r--r--sources/plugins/iframe/lang/ku.js11
-rw-r--r--sources/plugins/iframe/lang/lt.js11
-rw-r--r--sources/plugins/iframe/lang/lv.js11
-rw-r--r--sources/plugins/iframe/lang/mk.js11
-rw-r--r--sources/plugins/iframe/lang/mn.js11
-rw-r--r--sources/plugins/iframe/lang/ms.js11
-rw-r--r--sources/plugins/iframe/lang/nb.js11
-rw-r--r--sources/plugins/iframe/lang/nl.js11
-rw-r--r--sources/plugins/iframe/lang/no.js11
-rw-r--r--sources/plugins/iframe/lang/oc.js11
-rw-r--r--sources/plugins/iframe/lang/pl.js11
-rw-r--r--sources/plugins/iframe/lang/pt-br.js11
-rw-r--r--sources/plugins/iframe/lang/pt.js11
-rw-r--r--sources/plugins/iframe/lang/ro.js11
-rw-r--r--sources/plugins/iframe/lang/ru.js11
-rw-r--r--sources/plugins/iframe/lang/si.js11
-rw-r--r--sources/plugins/iframe/lang/sk.js11
-rw-r--r--sources/plugins/iframe/lang/sl.js11
-rw-r--r--sources/plugins/iframe/lang/sq.js11
-rw-r--r--sources/plugins/iframe/lang/sr-latn.js11
-rw-r--r--sources/plugins/iframe/lang/sr.js11
-rw-r--r--sources/plugins/iframe/lang/sv.js11
-rw-r--r--sources/plugins/iframe/lang/th.js11
-rw-r--r--sources/plugins/iframe/lang/tr.js11
-rw-r--r--sources/plugins/iframe/lang/tt.js11
-rw-r--r--sources/plugins/iframe/lang/ug.js11
-rw-r--r--sources/plugins/iframe/lang/uk.js11
-rw-r--r--sources/plugins/iframe/lang/vi.js11
-rw-r--r--sources/plugins/iframe/lang/zh-cn.js11
-rw-r--r--sources/plugins/iframe/lang/zh.js11
-rw-r--r--sources/plugins/iframe/plugin.js85
-rw-r--r--sources/plugins/image/dialogs/image.js1254
-rw-r--r--sources/plugins/image/icons/hidpi/image.pngbin0 -> 905 bytes
-rw-r--r--sources/plugins/image/icons/image.pngbin0 -> 498 bytes
-rw-r--r--sources/plugins/image/images/noimage.pngbin0 -> 1610 bytes
-rw-r--r--sources/plugins/image/lang/af.js25
-rw-r--r--sources/plugins/image/lang/ar.js25
-rw-r--r--sources/plugins/image/lang/az.js25
-rw-r--r--sources/plugins/image/lang/bg.js25
-rw-r--r--sources/plugins/image/lang/bn.js25
-rw-r--r--sources/plugins/image/lang/bs.js25
-rw-r--r--sources/plugins/image/lang/ca.js25
-rw-r--r--sources/plugins/image/lang/cs.js25
-rw-r--r--sources/plugins/image/lang/cy.js25
-rw-r--r--sources/plugins/image/lang/da.js25
-rw-r--r--sources/plugins/image/lang/de-ch.js25
-rw-r--r--sources/plugins/image/lang/de.js25
-rw-r--r--sources/plugins/image/lang/el.js25
-rw-r--r--sources/plugins/image/lang/en-au.js25
-rw-r--r--sources/plugins/image/lang/en-ca.js25
-rw-r--r--sources/plugins/image/lang/en-gb.js25
-rw-r--r--sources/plugins/image/lang/en.js25
-rw-r--r--sources/plugins/image/lang/eo.js25
-rw-r--r--sources/plugins/image/lang/es.js25
-rw-r--r--sources/plugins/image/lang/et.js25
-rw-r--r--sources/plugins/image/lang/eu.js25
-rw-r--r--sources/plugins/image/lang/fa.js25
-rw-r--r--sources/plugins/image/lang/fi.js25
-rw-r--r--sources/plugins/image/lang/fo.js25
-rw-r--r--sources/plugins/image/lang/fr-ca.js25
-rw-r--r--sources/plugins/image/lang/fr.js25
-rw-r--r--sources/plugins/image/lang/gl.js25
-rw-r--r--sources/plugins/image/lang/gu.js25
-rw-r--r--sources/plugins/image/lang/he.js25
-rw-r--r--sources/plugins/image/lang/hi.js25
-rw-r--r--sources/plugins/image/lang/hr.js25
-rw-r--r--sources/plugins/image/lang/hu.js25
-rw-r--r--sources/plugins/image/lang/id.js25
-rw-r--r--sources/plugins/image/lang/is.js25
-rw-r--r--sources/plugins/image/lang/it.js25
-rw-r--r--sources/plugins/image/lang/ja.js25
-rw-r--r--sources/plugins/image/lang/ka.js25
-rw-r--r--sources/plugins/image/lang/km.js25
-rw-r--r--sources/plugins/image/lang/ko.js25
-rw-r--r--sources/plugins/image/lang/ku.js25
-rw-r--r--sources/plugins/image/lang/lt.js25
-rw-r--r--sources/plugins/image/lang/lv.js25
-rw-r--r--sources/plugins/image/lang/mk.js25
-rw-r--r--sources/plugins/image/lang/mn.js25
-rw-r--r--sources/plugins/image/lang/ms.js25
-rw-r--r--sources/plugins/image/lang/nb.js25
-rw-r--r--sources/plugins/image/lang/nl.js25
-rw-r--r--sources/plugins/image/lang/no.js25
-rw-r--r--sources/plugins/image/lang/oc.js25
-rw-r--r--sources/plugins/image/lang/pl.js25
-rw-r--r--sources/plugins/image/lang/pt-br.js25
-rw-r--r--sources/plugins/image/lang/pt.js25
-rw-r--r--sources/plugins/image/lang/ro.js25
-rw-r--r--sources/plugins/image/lang/ru.js25
-rw-r--r--sources/plugins/image/lang/si.js25
-rw-r--r--sources/plugins/image/lang/sk.js25
-rw-r--r--sources/plugins/image/lang/sl.js25
-rw-r--r--sources/plugins/image/lang/sq.js25
-rw-r--r--sources/plugins/image/lang/sr-latn.js25
-rw-r--r--sources/plugins/image/lang/sr.js25
-rw-r--r--sources/plugins/image/lang/sv.js25
-rw-r--r--sources/plugins/image/lang/th.js25
-rw-r--r--sources/plugins/image/lang/tr.js25
-rw-r--r--sources/plugins/image/lang/tt.js25
-rw-r--r--sources/plugins/image/lang/ug.js25
-rw-r--r--sources/plugins/image/lang/uk.js25
-rw-r--r--sources/plugins/image/lang/vi.js25
-rw-r--r--sources/plugins/image/lang/zh-cn.js25
-rw-r--r--sources/plugins/image/lang/zh.js25
-rw-r--r--sources/plugins/image/plugin.js183
-rw-r--r--sources/plugins/indent/dev/indent.html284
-rw-r--r--sources/plugins/indent/icons/hidpi/indent-rtl.pngbin0 -> 757 bytes
-rw-r--r--sources/plugins/indent/icons/hidpi/indent.pngbin0 -> 1001 bytes
-rw-r--r--sources/plugins/indent/icons/hidpi/outdent-rtl.pngbin0 -> 738 bytes
-rw-r--r--sources/plugins/indent/icons/hidpi/outdent.pngbin0 -> 754 bytes
-rw-r--r--sources/plugins/indent/icons/indent-rtl.pngbin0 -> 438 bytes
-rw-r--r--sources/plugins/indent/icons/indent.pngbin0 -> 489 bytes
-rw-r--r--sources/plugins/indent/icons/outdent-rtl.pngbin0 -> 450 bytes
-rw-r--r--sources/plugins/indent/icons/outdent.pngbin0 -> 413 bytes
-rw-r--r--sources/plugins/indent/lang/af.js8
-rw-r--r--sources/plugins/indent/lang/ar.js8
-rw-r--r--sources/plugins/indent/lang/az.js8
-rw-r--r--sources/plugins/indent/lang/bg.js8
-rw-r--r--sources/plugins/indent/lang/bn.js8
-rw-r--r--sources/plugins/indent/lang/bs.js8
-rw-r--r--sources/plugins/indent/lang/ca.js8
-rw-r--r--sources/plugins/indent/lang/cs.js8
-rw-r--r--sources/plugins/indent/lang/cy.js8
-rw-r--r--sources/plugins/indent/lang/da.js8
-rw-r--r--sources/plugins/indent/lang/de-ch.js8
-rw-r--r--sources/plugins/indent/lang/de.js8
-rw-r--r--sources/plugins/indent/lang/el.js8
-rw-r--r--sources/plugins/indent/lang/en-au.js8
-rw-r--r--sources/plugins/indent/lang/en-ca.js8
-rw-r--r--sources/plugins/indent/lang/en-gb.js8
-rw-r--r--sources/plugins/indent/lang/en.js8
-rw-r--r--sources/plugins/indent/lang/eo.js8
-rw-r--r--sources/plugins/indent/lang/es.js8
-rw-r--r--sources/plugins/indent/lang/et.js8
-rw-r--r--sources/plugins/indent/lang/eu.js8
-rw-r--r--sources/plugins/indent/lang/fa.js8
-rw-r--r--sources/plugins/indent/lang/fi.js8
-rw-r--r--sources/plugins/indent/lang/fo.js8
-rw-r--r--sources/plugins/indent/lang/fr-ca.js8
-rw-r--r--sources/plugins/indent/lang/fr.js8
-rw-r--r--sources/plugins/indent/lang/gl.js8
-rw-r--r--sources/plugins/indent/lang/gu.js8
-rw-r--r--sources/plugins/indent/lang/he.js8
-rw-r--r--sources/plugins/indent/lang/hi.js8
-rw-r--r--sources/plugins/indent/lang/hr.js8
-rw-r--r--sources/plugins/indent/lang/hu.js8
-rw-r--r--sources/plugins/indent/lang/id.js8
-rw-r--r--sources/plugins/indent/lang/is.js8
-rw-r--r--sources/plugins/indent/lang/it.js8
-rw-r--r--sources/plugins/indent/lang/ja.js8
-rw-r--r--sources/plugins/indent/lang/ka.js8
-rw-r--r--sources/plugins/indent/lang/km.js8
-rw-r--r--sources/plugins/indent/lang/ko.js8
-rw-r--r--sources/plugins/indent/lang/ku.js8
-rw-r--r--sources/plugins/indent/lang/lt.js8
-rw-r--r--sources/plugins/indent/lang/lv.js8
-rw-r--r--sources/plugins/indent/lang/mk.js8
-rw-r--r--sources/plugins/indent/lang/mn.js8
-rw-r--r--sources/plugins/indent/lang/ms.js8
-rw-r--r--sources/plugins/indent/lang/nb.js8
-rw-r--r--sources/plugins/indent/lang/nl.js8
-rw-r--r--sources/plugins/indent/lang/no.js8
-rw-r--r--sources/plugins/indent/lang/oc.js8
-rw-r--r--sources/plugins/indent/lang/pl.js8
-rw-r--r--sources/plugins/indent/lang/pt-br.js8
-rw-r--r--sources/plugins/indent/lang/pt.js8
-rw-r--r--sources/plugins/indent/lang/ro.js8
-rw-r--r--sources/plugins/indent/lang/ru.js8
-rw-r--r--sources/plugins/indent/lang/si.js8
-rw-r--r--sources/plugins/indent/lang/sk.js8
-rw-r--r--sources/plugins/indent/lang/sl.js8
-rw-r--r--sources/plugins/indent/lang/sq.js8
-rw-r--r--sources/plugins/indent/lang/sr-latn.js8
-rw-r--r--sources/plugins/indent/lang/sr.js8
-rw-r--r--sources/plugins/indent/lang/sv.js8
-rw-r--r--sources/plugins/indent/lang/th.js8
-rw-r--r--sources/plugins/indent/lang/tr.js8
-rw-r--r--sources/plugins/indent/lang/tt.js8
-rw-r--r--sources/plugins/indent/lang/ug.js8
-rw-r--r--sources/plugins/indent/lang/uk.js8
-rw-r--r--sources/plugins/indent/lang/vi.js8
-rw-r--r--sources/plugins/indent/lang/zh-cn.js8
-rw-r--r--sources/plugins/indent/lang/zh.js8
-rw-r--r--sources/plugins/indent/plugin.js461
-rw-r--r--sources/plugins/indentblock/plugin.js312
-rw-r--r--sources/plugins/indentlist/plugin.js318
-rw-r--r--sources/plugins/justify/icons/hidpi/justifyblock.pngbin0 -> 533 bytes
-rw-r--r--sources/plugins/justify/icons/hidpi/justifycenter.pngbin0 -> 576 bytes
-rw-r--r--sources/plugins/justify/icons/hidpi/justifyleft.pngbin0 -> 569 bytes
-rw-r--r--sources/plugins/justify/icons/hidpi/justifyright.pngbin0 -> 549 bytes
-rw-r--r--sources/plugins/justify/icons/justifyblock.pngbin0 -> 315 bytes
-rw-r--r--sources/plugins/justify/icons/justifycenter.pngbin0 -> 564 bytes
-rw-r--r--sources/plugins/justify/icons/justifyleft.pngbin0 -> 342 bytes
-rw-r--r--sources/plugins/justify/icons/justifyright.pngbin0 -> 348 bytes
-rw-r--r--sources/plugins/justify/lang/af.js10
-rw-r--r--sources/plugins/justify/lang/ar.js10
-rw-r--r--sources/plugins/justify/lang/az.js10
-rw-r--r--sources/plugins/justify/lang/bg.js10
-rw-r--r--sources/plugins/justify/lang/bn.js10
-rw-r--r--sources/plugins/justify/lang/bs.js10
-rw-r--r--sources/plugins/justify/lang/ca.js10
-rw-r--r--sources/plugins/justify/lang/cs.js10
-rw-r--r--sources/plugins/justify/lang/cy.js10
-rw-r--r--sources/plugins/justify/lang/da.js10
-rw-r--r--sources/plugins/justify/lang/de-ch.js10
-rw-r--r--sources/plugins/justify/lang/de.js10
-rw-r--r--sources/plugins/justify/lang/el.js10
-rw-r--r--sources/plugins/justify/lang/en-au.js10
-rw-r--r--sources/plugins/justify/lang/en-ca.js10
-rw-r--r--sources/plugins/justify/lang/en-gb.js10
-rw-r--r--sources/plugins/justify/lang/en.js10
-rw-r--r--sources/plugins/justify/lang/eo.js10
-rw-r--r--sources/plugins/justify/lang/es.js10
-rw-r--r--sources/plugins/justify/lang/et.js10
-rw-r--r--sources/plugins/justify/lang/eu.js10
-rw-r--r--sources/plugins/justify/lang/fa.js10
-rw-r--r--sources/plugins/justify/lang/fi.js10
-rw-r--r--sources/plugins/justify/lang/fo.js10
-rw-r--r--sources/plugins/justify/lang/fr-ca.js10
-rw-r--r--sources/plugins/justify/lang/fr.js10
-rw-r--r--sources/plugins/justify/lang/gl.js10
-rw-r--r--sources/plugins/justify/lang/gu.js10
-rw-r--r--sources/plugins/justify/lang/he.js10
-rw-r--r--sources/plugins/justify/lang/hi.js10
-rw-r--r--sources/plugins/justify/lang/hr.js10
-rw-r--r--sources/plugins/justify/lang/hu.js10
-rw-r--r--sources/plugins/justify/lang/id.js10
-rw-r--r--sources/plugins/justify/lang/is.js10
-rw-r--r--sources/plugins/justify/lang/it.js10
-rw-r--r--sources/plugins/justify/lang/ja.js10
-rw-r--r--sources/plugins/justify/lang/ka.js10
-rw-r--r--sources/plugins/justify/lang/km.js10
-rw-r--r--sources/plugins/justify/lang/ko.js10
-rw-r--r--sources/plugins/justify/lang/ku.js10
-rw-r--r--sources/plugins/justify/lang/lt.js10
-rw-r--r--sources/plugins/justify/lang/lv.js10
-rw-r--r--sources/plugins/justify/lang/mk.js10
-rw-r--r--sources/plugins/justify/lang/mn.js10
-rw-r--r--sources/plugins/justify/lang/ms.js10
-rw-r--r--sources/plugins/justify/lang/nb.js10
-rw-r--r--sources/plugins/justify/lang/nl.js10
-rw-r--r--sources/plugins/justify/lang/no.js10
-rw-r--r--sources/plugins/justify/lang/oc.js10
-rw-r--r--sources/plugins/justify/lang/pl.js10
-rw-r--r--sources/plugins/justify/lang/pt-br.js10
-rw-r--r--sources/plugins/justify/lang/pt.js10
-rw-r--r--sources/plugins/justify/lang/ro.js10
-rw-r--r--sources/plugins/justify/lang/ru.js10
-rw-r--r--sources/plugins/justify/lang/si.js10
-rw-r--r--sources/plugins/justify/lang/sk.js10
-rw-r--r--sources/plugins/justify/lang/sl.js10
-rw-r--r--sources/plugins/justify/lang/sq.js10
-rw-r--r--sources/plugins/justify/lang/sr-latn.js10
-rw-r--r--sources/plugins/justify/lang/sr.js10
-rw-r--r--sources/plugins/justify/lang/sv.js10
-rw-r--r--sources/plugins/justify/lang/th.js10
-rw-r--r--sources/plugins/justify/lang/tr.js10
-rw-r--r--sources/plugins/justify/lang/tt.js10
-rw-r--r--sources/plugins/justify/lang/ug.js10
-rw-r--r--sources/plugins/justify/lang/uk.js10
-rw-r--r--sources/plugins/justify/lang/vi.js10
-rw-r--r--sources/plugins/justify/lang/zh-cn.js10
-rw-r--r--sources/plugins/justify/lang/zh.js10
-rw-r--r--sources/plugins/justify/plugin.js245
-rw-r--r--sources/plugins/lineutils/dev/dnd.html172
-rw-r--r--sources/plugins/lineutils/dev/magicfinger.html285
-rw-r--r--sources/plugins/lineutils/plugin.js1018
-rw-r--r--sources/plugins/link/dialogs/anchor.js105
-rw-r--r--sources/plugins/link/dialogs/link.js979
-rw-r--r--sources/plugins/link/icons/anchor-rtl.pngbin0 -> 523 bytes
-rw-r--r--sources/plugins/link/icons/anchor.pngbin0 -> 517 bytes
-rw-r--r--sources/plugins/link/icons/hidpi/anchor-rtl.pngbin0 -> 957 bytes
-rw-r--r--sources/plugins/link/icons/hidpi/anchor.pngbin0 -> 917 bytes
-rw-r--r--sources/plugins/link/icons/hidpi/link.pngbin0 -> 935 bytes
-rw-r--r--sources/plugins/link/icons/hidpi/unlink.pngbin0 -> 1317 bytes
-rw-r--r--sources/plugins/link/icons/link.pngbin0 -> 533 bytes
-rw-r--r--sources/plugins/link/icons/unlink.pngbin0 -> 692 bytes
-rw-r--r--sources/plugins/link/images/anchor.pngbin0 -> 752 bytes
-rw-r--r--sources/plugins/link/images/hidpi/anchor.pngbin0 -> 1109 bytes
-rw-r--r--sources/plugins/link/lang/af.js67
-rw-r--r--sources/plugins/link/lang/ar.js67
-rw-r--r--sources/plugins/link/lang/az.js67
-rw-r--r--sources/plugins/link/lang/bg.js67
-rw-r--r--sources/plugins/link/lang/bn.js67
-rw-r--r--sources/plugins/link/lang/bs.js67
-rw-r--r--sources/plugins/link/lang/ca.js67
-rw-r--r--sources/plugins/link/lang/cs.js67
-rw-r--r--sources/plugins/link/lang/cy.js67
-rw-r--r--sources/plugins/link/lang/da.js67
-rw-r--r--sources/plugins/link/lang/de-ch.js67
-rw-r--r--sources/plugins/link/lang/de.js67
-rw-r--r--sources/plugins/link/lang/el.js67
-rw-r--r--sources/plugins/link/lang/en-au.js67
-rw-r--r--sources/plugins/link/lang/en-ca.js67
-rw-r--r--sources/plugins/link/lang/en-gb.js67
-rw-r--r--sources/plugins/link/lang/en.js67
-rw-r--r--sources/plugins/link/lang/eo.js67
-rw-r--r--sources/plugins/link/lang/es.js67
-rw-r--r--sources/plugins/link/lang/et.js67
-rw-r--r--sources/plugins/link/lang/eu.js67
-rw-r--r--sources/plugins/link/lang/fa.js67
-rw-r--r--sources/plugins/link/lang/fi.js67
-rw-r--r--sources/plugins/link/lang/fo.js67
-rw-r--r--sources/plugins/link/lang/fr-ca.js67
-rw-r--r--sources/plugins/link/lang/fr.js67
-rw-r--r--sources/plugins/link/lang/gl.js67
-rw-r--r--sources/plugins/link/lang/gu.js67
-rw-r--r--sources/plugins/link/lang/he.js67
-rw-r--r--sources/plugins/link/lang/hi.js67
-rw-r--r--sources/plugins/link/lang/hr.js67
-rw-r--r--sources/plugins/link/lang/hu.js67
-rw-r--r--sources/plugins/link/lang/id.js67
-rw-r--r--sources/plugins/link/lang/is.js67
-rw-r--r--sources/plugins/link/lang/it.js67
-rw-r--r--sources/plugins/link/lang/ja.js67
-rw-r--r--sources/plugins/link/lang/ka.js67
-rw-r--r--sources/plugins/link/lang/km.js67
-rw-r--r--sources/plugins/link/lang/ko.js67
-rw-r--r--sources/plugins/link/lang/ku.js67
-rw-r--r--sources/plugins/link/lang/lt.js67
-rw-r--r--sources/plugins/link/lang/lv.js67
-rw-r--r--sources/plugins/link/lang/mk.js67
-rw-r--r--sources/plugins/link/lang/mn.js67
-rw-r--r--sources/plugins/link/lang/ms.js67
-rw-r--r--sources/plugins/link/lang/nb.js67
-rw-r--r--sources/plugins/link/lang/nl.js67
-rw-r--r--sources/plugins/link/lang/no.js67
-rw-r--r--sources/plugins/link/lang/oc.js67
-rw-r--r--sources/plugins/link/lang/pl.js67
-rw-r--r--sources/plugins/link/lang/pt-br.js67
-rw-r--r--sources/plugins/link/lang/pt.js67
-rw-r--r--sources/plugins/link/lang/ro.js67
-rw-r--r--sources/plugins/link/lang/ru.js67
-rw-r--r--sources/plugins/link/lang/si.js67
-rw-r--r--sources/plugins/link/lang/sk.js67
-rw-r--r--sources/plugins/link/lang/sl.js67
-rw-r--r--sources/plugins/link/lang/sq.js67
-rw-r--r--sources/plugins/link/lang/sr-latn.js67
-rw-r--r--sources/plugins/link/lang/sr.js67
-rw-r--r--sources/plugins/link/lang/sv.js67
-rw-r--r--sources/plugins/link/lang/th.js67
-rw-r--r--sources/plugins/link/lang/tr.js67
-rw-r--r--sources/plugins/link/lang/tt.js67
-rw-r--r--sources/plugins/link/lang/ug.js67
-rw-r--r--sources/plugins/link/lang/uk.js67
-rw-r--r--sources/plugins/link/lang/vi.js67
-rw-r--r--sources/plugins/link/lang/zh-cn.js67
-rw-r--r--sources/plugins/link/lang/zh.js67
-rw-r--r--sources/plugins/link/plugin.js828
-rw-r--r--sources/plugins/list/icons/bulletedlist-rtl.pngbin0 -> 367 bytes
-rw-r--r--sources/plugins/list/icons/bulletedlist.pngbin0 -> 370 bytes
-rw-r--r--sources/plugins/list/icons/hidpi/bulletedlist-rtl.pngbin0 -> 820 bytes
-rw-r--r--sources/plugins/list/icons/hidpi/bulletedlist.pngbin0 -> 828 bytes
-rw-r--r--sources/plugins/list/icons/hidpi/numberedlist-rtl.pngbin0 -> 628 bytes
-rw-r--r--sources/plugins/list/icons/hidpi/numberedlist.pngbin0 -> 655 bytes
-rw-r--r--sources/plugins/list/icons/numberedlist-rtl.pngbin0 -> 390 bytes
-rw-r--r--sources/plugins/list/icons/numberedlist.pngbin0 -> 390 bytes
-rw-r--r--sources/plugins/list/lang/af.js8
-rw-r--r--sources/plugins/list/lang/ar.js8
-rw-r--r--sources/plugins/list/lang/az.js8
-rw-r--r--sources/plugins/list/lang/bg.js8
-rw-r--r--sources/plugins/list/lang/bn.js8
-rw-r--r--sources/plugins/list/lang/bs.js8
-rw-r--r--sources/plugins/list/lang/ca.js8
-rw-r--r--sources/plugins/list/lang/cs.js8
-rw-r--r--sources/plugins/list/lang/cy.js8
-rw-r--r--sources/plugins/list/lang/da.js8
-rw-r--r--sources/plugins/list/lang/de-ch.js8
-rw-r--r--sources/plugins/list/lang/de.js8
-rw-r--r--sources/plugins/list/lang/el.js8
-rw-r--r--sources/plugins/list/lang/en-au.js8
-rw-r--r--sources/plugins/list/lang/en-ca.js8
-rw-r--r--sources/plugins/list/lang/en-gb.js8
-rw-r--r--sources/plugins/list/lang/en.js8
-rw-r--r--sources/plugins/list/lang/eo.js8
-rw-r--r--sources/plugins/list/lang/es.js8
-rw-r--r--sources/plugins/list/lang/et.js8
-rw-r--r--sources/plugins/list/lang/eu.js8
-rw-r--r--sources/plugins/list/lang/fa.js8
-rw-r--r--sources/plugins/list/lang/fi.js8
-rw-r--r--sources/plugins/list/lang/fo.js8
-rw-r--r--sources/plugins/list/lang/fr-ca.js8
-rw-r--r--sources/plugins/list/lang/fr.js8
-rw-r--r--sources/plugins/list/lang/gl.js8
-rw-r--r--sources/plugins/list/lang/gu.js8
-rw-r--r--sources/plugins/list/lang/he.js8
-rw-r--r--sources/plugins/list/lang/hi.js8
-rw-r--r--sources/plugins/list/lang/hr.js8
-rw-r--r--sources/plugins/list/lang/hu.js8
-rw-r--r--sources/plugins/list/lang/id.js8
-rw-r--r--sources/plugins/list/lang/is.js8
-rw-r--r--sources/plugins/list/lang/it.js8
-rw-r--r--sources/plugins/list/lang/ja.js8
-rw-r--r--sources/plugins/list/lang/ka.js8
-rw-r--r--sources/plugins/list/lang/km.js8
-rw-r--r--sources/plugins/list/lang/ko.js8
-rw-r--r--sources/plugins/list/lang/ku.js8
-rw-r--r--sources/plugins/list/lang/lt.js8
-rw-r--r--sources/plugins/list/lang/lv.js8
-rw-r--r--sources/plugins/list/lang/mk.js8
-rw-r--r--sources/plugins/list/lang/mn.js8
-rw-r--r--sources/plugins/list/lang/ms.js8
-rw-r--r--sources/plugins/list/lang/nb.js8
-rw-r--r--sources/plugins/list/lang/nl.js8
-rw-r--r--sources/plugins/list/lang/no.js8
-rw-r--r--sources/plugins/list/lang/oc.js8
-rw-r--r--sources/plugins/list/lang/pl.js8
-rw-r--r--sources/plugins/list/lang/pt-br.js8
-rw-r--r--sources/plugins/list/lang/pt.js8
-rw-r--r--sources/plugins/list/lang/ro.js8
-rw-r--r--sources/plugins/list/lang/ru.js8
-rw-r--r--sources/plugins/list/lang/si.js8
-rw-r--r--sources/plugins/list/lang/sk.js8
-rw-r--r--sources/plugins/list/lang/sl.js8
-rw-r--r--sources/plugins/list/lang/sq.js8
-rw-r--r--sources/plugins/list/lang/sr-latn.js8
-rw-r--r--sources/plugins/list/lang/sr.js8
-rw-r--r--sources/plugins/list/lang/sv.js8
-rw-r--r--sources/plugins/list/lang/th.js8
-rw-r--r--sources/plugins/list/lang/tr.js8
-rw-r--r--sources/plugins/list/lang/tt.js8
-rw-r--r--sources/plugins/list/lang/ug.js8
-rw-r--r--sources/plugins/list/lang/uk.js8
-rw-r--r--sources/plugins/list/lang/vi.js8
-rw-r--r--sources/plugins/list/lang/zh-cn.js8
-rw-r--r--sources/plugins/list/lang/zh.js8
-rw-r--r--sources/plugins/list/plugin.js1111
-rw-r--r--sources/plugins/listblock/plugin.js241
-rw-r--r--sources/plugins/liststyle/dialogs/liststyle.js189
-rw-r--r--sources/plugins/liststyle/lang/af.js25
-rw-r--r--sources/plugins/liststyle/lang/ar.js25
-rw-r--r--sources/plugins/liststyle/lang/az.js25
-rw-r--r--sources/plugins/liststyle/lang/bg.js25
-rw-r--r--sources/plugins/liststyle/lang/bn.js25
-rw-r--r--sources/plugins/liststyle/lang/bs.js25
-rw-r--r--sources/plugins/liststyle/lang/ca.js25
-rw-r--r--sources/plugins/liststyle/lang/cs.js25
-rw-r--r--sources/plugins/liststyle/lang/cy.js25
-rw-r--r--sources/plugins/liststyle/lang/da.js25
-rw-r--r--sources/plugins/liststyle/lang/de-ch.js25
-rw-r--r--sources/plugins/liststyle/lang/de.js25
-rw-r--r--sources/plugins/liststyle/lang/el.js25
-rw-r--r--sources/plugins/liststyle/lang/en-au.js25
-rw-r--r--sources/plugins/liststyle/lang/en-ca.js25
-rw-r--r--sources/plugins/liststyle/lang/en-gb.js25
-rw-r--r--sources/plugins/liststyle/lang/en.js25
-rw-r--r--sources/plugins/liststyle/lang/eo.js25
-rw-r--r--sources/plugins/liststyle/lang/es.js25
-rw-r--r--sources/plugins/liststyle/lang/et.js25
-rw-r--r--sources/plugins/liststyle/lang/eu.js25
-rw-r--r--sources/plugins/liststyle/lang/fa.js25
-rw-r--r--sources/plugins/liststyle/lang/fi.js25
-rw-r--r--sources/plugins/liststyle/lang/fo.js25
-rw-r--r--sources/plugins/liststyle/lang/fr-ca.js25
-rw-r--r--sources/plugins/liststyle/lang/fr.js25
-rw-r--r--sources/plugins/liststyle/lang/gl.js25
-rw-r--r--sources/plugins/liststyle/lang/gu.js25
-rw-r--r--sources/plugins/liststyle/lang/he.js25
-rw-r--r--sources/plugins/liststyle/lang/hi.js25
-rw-r--r--sources/plugins/liststyle/lang/hr.js25
-rw-r--r--sources/plugins/liststyle/lang/hu.js25
-rw-r--r--sources/plugins/liststyle/lang/id.js25
-rw-r--r--sources/plugins/liststyle/lang/is.js25
-rw-r--r--sources/plugins/liststyle/lang/it.js25
-rw-r--r--sources/plugins/liststyle/lang/ja.js25
-rw-r--r--sources/plugins/liststyle/lang/ka.js25
-rw-r--r--sources/plugins/liststyle/lang/km.js25
-rw-r--r--sources/plugins/liststyle/lang/ko.js25
-rw-r--r--sources/plugins/liststyle/lang/ku.js25
-rw-r--r--sources/plugins/liststyle/lang/lt.js25
-rw-r--r--sources/plugins/liststyle/lang/lv.js25
-rw-r--r--sources/plugins/liststyle/lang/mk.js25
-rw-r--r--sources/plugins/liststyle/lang/mn.js25
-rw-r--r--sources/plugins/liststyle/lang/ms.js25
-rw-r--r--sources/plugins/liststyle/lang/nb.js25
-rw-r--r--sources/plugins/liststyle/lang/nl.js25
-rw-r--r--sources/plugins/liststyle/lang/no.js25
-rw-r--r--sources/plugins/liststyle/lang/oc.js25
-rw-r--r--sources/plugins/liststyle/lang/pl.js25
-rw-r--r--sources/plugins/liststyle/lang/pt-br.js25
-rw-r--r--sources/plugins/liststyle/lang/pt.js25
-rw-r--r--sources/plugins/liststyle/lang/ro.js25
-rw-r--r--sources/plugins/liststyle/lang/ru.js25
-rw-r--r--sources/plugins/liststyle/lang/si.js25
-rw-r--r--sources/plugins/liststyle/lang/sk.js25
-rw-r--r--sources/plugins/liststyle/lang/sl.js25
-rw-r--r--sources/plugins/liststyle/lang/sq.js25
-rw-r--r--sources/plugins/liststyle/lang/sr-latn.js25
-rw-r--r--sources/plugins/liststyle/lang/sr.js25
-rw-r--r--sources/plugins/liststyle/lang/sv.js25
-rw-r--r--sources/plugins/liststyle/lang/th.js25
-rw-r--r--sources/plugins/liststyle/lang/tr.js25
-rw-r--r--sources/plugins/liststyle/lang/tt.js25
-rw-r--r--sources/plugins/liststyle/lang/ug.js25
-rw-r--r--sources/plugins/liststyle/lang/uk.js25
-rw-r--r--sources/plugins/liststyle/lang/vi.js25
-rw-r--r--sources/plugins/liststyle/lang/zh-cn.js25
-rw-r--r--sources/plugins/liststyle/lang/zh.js25
-rw-r--r--sources/plugins/liststyle/plugin.js75
-rw-r--r--sources/plugins/magicline/dev/magicline.html594
-rw-r--r--sources/plugins/magicline/images/hidpi/icon-rtl.pngbin0 -> 176 bytes
-rw-r--r--sources/plugins/magicline/images/hidpi/icon.pngbin0 -> 199 bytes
-rw-r--r--sources/plugins/magicline/images/icon-rtl.pngbin0 -> 138 bytes
-rw-r--r--sources/plugins/magicline/images/icon.pngbin0 -> 133 bytes
-rw-r--r--sources/plugins/magicline/lang/af.js8
-rw-r--r--sources/plugins/magicline/lang/ar.js8
-rw-r--r--sources/plugins/magicline/lang/az.js8
-rw-r--r--sources/plugins/magicline/lang/bg.js8
-rw-r--r--sources/plugins/magicline/lang/ca.js8
-rw-r--r--sources/plugins/magicline/lang/cs.js8
-rw-r--r--sources/plugins/magicline/lang/cy.js8
-rw-r--r--sources/plugins/magicline/lang/da.js8
-rw-r--r--sources/plugins/magicline/lang/de-ch.js8
-rw-r--r--sources/plugins/magicline/lang/de.js8
-rw-r--r--sources/plugins/magicline/lang/el.js8
-rw-r--r--sources/plugins/magicline/lang/en-gb.js8
-rw-r--r--sources/plugins/magicline/lang/en.js8
-rw-r--r--sources/plugins/magicline/lang/eo.js8
-rw-r--r--sources/plugins/magicline/lang/es.js8
-rw-r--r--sources/plugins/magicline/lang/et.js8
-rw-r--r--sources/plugins/magicline/lang/eu.js8
-rw-r--r--sources/plugins/magicline/lang/fa.js8
-rw-r--r--sources/plugins/magicline/lang/fi.js8
-rw-r--r--sources/plugins/magicline/lang/fr-ca.js8
-rw-r--r--sources/plugins/magicline/lang/fr.js8
-rw-r--r--sources/plugins/magicline/lang/gl.js8
-rw-r--r--sources/plugins/magicline/lang/he.js8
-rw-r--r--sources/plugins/magicline/lang/hr.js8
-rw-r--r--sources/plugins/magicline/lang/hu.js8
-rw-r--r--sources/plugins/magicline/lang/id.js8
-rw-r--r--sources/plugins/magicline/lang/it.js8
-rw-r--r--sources/plugins/magicline/lang/ja.js8
-rw-r--r--sources/plugins/magicline/lang/km.js8
-rw-r--r--sources/plugins/magicline/lang/ko.js8
-rw-r--r--sources/plugins/magicline/lang/ku.js8
-rw-r--r--sources/plugins/magicline/lang/lv.js8
-rw-r--r--sources/plugins/magicline/lang/nb.js8
-rw-r--r--sources/plugins/magicline/lang/nl.js8
-rw-r--r--sources/plugins/magicline/lang/no.js8
-rw-r--r--sources/plugins/magicline/lang/oc.js8
-rw-r--r--sources/plugins/magicline/lang/pl.js8
-rw-r--r--sources/plugins/magicline/lang/pt-br.js8
-rw-r--r--sources/plugins/magicline/lang/pt.js8
-rw-r--r--sources/plugins/magicline/lang/ru.js8
-rw-r--r--sources/plugins/magicline/lang/si.js8
-rw-r--r--sources/plugins/magicline/lang/sk.js8
-rw-r--r--sources/plugins/magicline/lang/sl.js8
-rw-r--r--sources/plugins/magicline/lang/sq.js8
-rw-r--r--sources/plugins/magicline/lang/sv.js8
-rw-r--r--sources/plugins/magicline/lang/tr.js8
-rw-r--r--sources/plugins/magicline/lang/tt.js8
-rw-r--r--sources/plugins/magicline/lang/ug.js8
-rw-r--r--sources/plugins/magicline/lang/uk.js8
-rw-r--r--sources/plugins/magicline/lang/vi.js8
-rw-r--r--sources/plugins/magicline/lang/zh-cn.js8
-rw-r--r--sources/plugins/magicline/lang/zh.js8
-rw-r--r--sources/plugins/magicline/plugin.js1874
-rw-r--r--sources/plugins/magicline/samples/magicline.html209
-rw-r--r--sources/plugins/maximize/icons/hidpi/maximize.pngbin0 -> 1112 bytes
-rw-r--r--sources/plugins/maximize/icons/maximize.pngbin0 -> 461 bytes
-rw-r--r--sources/plugins/maximize/lang/af.js8
-rw-r--r--sources/plugins/maximize/lang/ar.js8
-rw-r--r--sources/plugins/maximize/lang/az.js8
-rw-r--r--sources/plugins/maximize/lang/bg.js8
-rw-r--r--sources/plugins/maximize/lang/bn.js8
-rw-r--r--sources/plugins/maximize/lang/bs.js8
-rw-r--r--sources/plugins/maximize/lang/ca.js8
-rw-r--r--sources/plugins/maximize/lang/cs.js8
-rw-r--r--sources/plugins/maximize/lang/cy.js8
-rw-r--r--sources/plugins/maximize/lang/da.js8
-rw-r--r--sources/plugins/maximize/lang/de-ch.js8
-rw-r--r--sources/plugins/maximize/lang/de.js8
-rw-r--r--sources/plugins/maximize/lang/el.js8
-rw-r--r--sources/plugins/maximize/lang/en-au.js8
-rw-r--r--sources/plugins/maximize/lang/en-ca.js8
-rw-r--r--sources/plugins/maximize/lang/en-gb.js8
-rw-r--r--sources/plugins/maximize/lang/en.js8
-rw-r--r--sources/plugins/maximize/lang/eo.js8
-rw-r--r--sources/plugins/maximize/lang/es.js8
-rw-r--r--sources/plugins/maximize/lang/et.js8
-rw-r--r--sources/plugins/maximize/lang/eu.js8
-rw-r--r--sources/plugins/maximize/lang/fa.js8
-rw-r--r--sources/plugins/maximize/lang/fi.js8
-rw-r--r--sources/plugins/maximize/lang/fo.js8
-rw-r--r--sources/plugins/maximize/lang/fr-ca.js8
-rw-r--r--sources/plugins/maximize/lang/fr.js8
-rw-r--r--sources/plugins/maximize/lang/gl.js8
-rw-r--r--sources/plugins/maximize/lang/gu.js8
-rw-r--r--sources/plugins/maximize/lang/he.js8
-rw-r--r--sources/plugins/maximize/lang/hi.js8
-rw-r--r--sources/plugins/maximize/lang/hr.js8
-rw-r--r--sources/plugins/maximize/lang/hu.js8
-rw-r--r--sources/plugins/maximize/lang/id.js8
-rw-r--r--sources/plugins/maximize/lang/is.js8
-rw-r--r--sources/plugins/maximize/lang/it.js8
-rw-r--r--sources/plugins/maximize/lang/ja.js8
-rw-r--r--sources/plugins/maximize/lang/ka.js8
-rw-r--r--sources/plugins/maximize/lang/km.js8
-rw-r--r--sources/plugins/maximize/lang/ko.js8
-rw-r--r--sources/plugins/maximize/lang/ku.js8
-rw-r--r--sources/plugins/maximize/lang/lt.js8
-rw-r--r--sources/plugins/maximize/lang/lv.js8
-rw-r--r--sources/plugins/maximize/lang/mk.js8
-rw-r--r--sources/plugins/maximize/lang/mn.js8
-rw-r--r--sources/plugins/maximize/lang/ms.js8
-rw-r--r--sources/plugins/maximize/lang/nb.js8
-rw-r--r--sources/plugins/maximize/lang/nl.js8
-rw-r--r--sources/plugins/maximize/lang/no.js8
-rw-r--r--sources/plugins/maximize/lang/oc.js8
-rw-r--r--sources/plugins/maximize/lang/pl.js8
-rw-r--r--sources/plugins/maximize/lang/pt-br.js8
-rw-r--r--sources/plugins/maximize/lang/pt.js8
-rw-r--r--sources/plugins/maximize/lang/ro.js8
-rw-r--r--sources/plugins/maximize/lang/ru.js8
-rw-r--r--sources/plugins/maximize/lang/si.js8
-rw-r--r--sources/plugins/maximize/lang/sk.js8
-rw-r--r--sources/plugins/maximize/lang/sl.js8
-rw-r--r--sources/plugins/maximize/lang/sq.js8
-rw-r--r--sources/plugins/maximize/lang/sr-latn.js8
-rw-r--r--sources/plugins/maximize/lang/sr.js8
-rw-r--r--sources/plugins/maximize/lang/sv.js8
-rw-r--r--sources/plugins/maximize/lang/th.js8
-rw-r--r--sources/plugins/maximize/lang/tr.js8
-rw-r--r--sources/plugins/maximize/lang/tt.js8
-rw-r--r--sources/plugins/maximize/lang/ug.js8
-rw-r--r--sources/plugins/maximize/lang/uk.js8
-rw-r--r--sources/plugins/maximize/lang/vi.js8
-rw-r--r--sources/plugins/maximize/lang/zh-cn.js8
-rw-r--r--sources/plugins/maximize/lang/zh.js8
-rw-r--r--sources/plugins/maximize/plugin.js314
-rw-r--r--sources/plugins/menu/plugin.js572
-rw-r--r--sources/plugins/oembed/LICENSE.md21
-rw-r--r--sources/plugins/oembed/README.md201
-rw-r--r--sources/plugins/oembed/icons/hidpi/oembed.pngbin0 -> 1849 bytes
-rw-r--r--sources/plugins/oembed/icons/oembed.pngbin0 -> 3143 bytes
-rw-r--r--sources/plugins/oembed/lang/de.js23
-rw-r--r--sources/plugins/oembed/lang/en.js23
-rw-r--r--sources/plugins/oembed/lang/fr.js25
-rw-r--r--sources/plugins/oembed/lang/nl.js23
-rw-r--r--sources/plugins/oembed/lang/pl.js23
-rw-r--r--sources/plugins/oembed/lang/pt-br.js23
-rw-r--r--sources/plugins/oembed/lang/ru.js23
-rw-r--r--sources/plugins/oembed/lang/tr.js23
-rw-r--r--sources/plugins/oembed/libs/jquery.oembed.min.js1
-rw-r--r--sources/plugins/oembed/plugin.js446
-rw-r--r--sources/plugins/panel/plugin.js403
-rw-r--r--sources/plugins/popup/plugin.js65
-rw-r--r--sources/plugins/removeformat/icons/hidpi/removeformat.pngbin0 -> 1219 bytes
-rw-r--r--sources/plugins/removeformat/icons/removeformat.pngbin0 -> 637 bytes
-rw-r--r--sources/plugins/removeformat/lang/af.js7
-rw-r--r--sources/plugins/removeformat/lang/ar.js7
-rw-r--r--sources/plugins/removeformat/lang/az.js7
-rw-r--r--sources/plugins/removeformat/lang/bg.js7
-rw-r--r--sources/plugins/removeformat/lang/bn.js7
-rw-r--r--sources/plugins/removeformat/lang/bs.js7
-rw-r--r--sources/plugins/removeformat/lang/ca.js7
-rw-r--r--sources/plugins/removeformat/lang/cs.js7
-rw-r--r--sources/plugins/removeformat/lang/cy.js7
-rw-r--r--sources/plugins/removeformat/lang/da.js7
-rw-r--r--sources/plugins/removeformat/lang/de-ch.js7
-rw-r--r--sources/plugins/removeformat/lang/de.js7
-rw-r--r--sources/plugins/removeformat/lang/el.js7
-rw-r--r--sources/plugins/removeformat/lang/en-au.js7
-rw-r--r--sources/plugins/removeformat/lang/en-ca.js7
-rw-r--r--sources/plugins/removeformat/lang/en-gb.js7
-rw-r--r--sources/plugins/removeformat/lang/en.js7
-rw-r--r--sources/plugins/removeformat/lang/eo.js7
-rw-r--r--sources/plugins/removeformat/lang/es.js7
-rw-r--r--sources/plugins/removeformat/lang/et.js7
-rw-r--r--sources/plugins/removeformat/lang/eu.js7
-rw-r--r--sources/plugins/removeformat/lang/fa.js7
-rw-r--r--sources/plugins/removeformat/lang/fi.js7
-rw-r--r--sources/plugins/removeformat/lang/fo.js7
-rw-r--r--sources/plugins/removeformat/lang/fr-ca.js7
-rw-r--r--sources/plugins/removeformat/lang/fr.js7
-rw-r--r--sources/plugins/removeformat/lang/gl.js7
-rw-r--r--sources/plugins/removeformat/lang/gu.js7
-rw-r--r--sources/plugins/removeformat/lang/he.js7
-rw-r--r--sources/plugins/removeformat/lang/hi.js7
-rw-r--r--sources/plugins/removeformat/lang/hr.js7
-rw-r--r--sources/plugins/removeformat/lang/hu.js7
-rw-r--r--sources/plugins/removeformat/lang/id.js7
-rw-r--r--sources/plugins/removeformat/lang/is.js7
-rw-r--r--sources/plugins/removeformat/lang/it.js7
-rw-r--r--sources/plugins/removeformat/lang/ja.js7
-rw-r--r--sources/plugins/removeformat/lang/ka.js7
-rw-r--r--sources/plugins/removeformat/lang/km.js7
-rw-r--r--sources/plugins/removeformat/lang/ko.js7
-rw-r--r--sources/plugins/removeformat/lang/ku.js7
-rw-r--r--sources/plugins/removeformat/lang/lt.js7
-rw-r--r--sources/plugins/removeformat/lang/lv.js7
-rw-r--r--sources/plugins/removeformat/lang/mk.js7
-rw-r--r--sources/plugins/removeformat/lang/mn.js7
-rw-r--r--sources/plugins/removeformat/lang/ms.js7
-rw-r--r--sources/plugins/removeformat/lang/nb.js7
-rw-r--r--sources/plugins/removeformat/lang/nl.js7
-rw-r--r--sources/plugins/removeformat/lang/no.js7
-rw-r--r--sources/plugins/removeformat/lang/oc.js7
-rw-r--r--sources/plugins/removeformat/lang/pl.js7
-rw-r--r--sources/plugins/removeformat/lang/pt-br.js7
-rw-r--r--sources/plugins/removeformat/lang/pt.js7
-rw-r--r--sources/plugins/removeformat/lang/ro.js7
-rw-r--r--sources/plugins/removeformat/lang/ru.js7
-rw-r--r--sources/plugins/removeformat/lang/si.js7
-rw-r--r--sources/plugins/removeformat/lang/sk.js7
-rw-r--r--sources/plugins/removeformat/lang/sl.js7
-rw-r--r--sources/plugins/removeformat/lang/sq.js7
-rw-r--r--sources/plugins/removeformat/lang/sr-latn.js7
-rw-r--r--sources/plugins/removeformat/lang/sr.js7
-rw-r--r--sources/plugins/removeformat/lang/sv.js7
-rw-r--r--sources/plugins/removeformat/lang/th.js7
-rw-r--r--sources/plugins/removeformat/lang/tr.js7
-rw-r--r--sources/plugins/removeformat/lang/tt.js7
-rw-r--r--sources/plugins/removeformat/lang/ug.js7
-rw-r--r--sources/plugins/removeformat/lang/uk.js7
-rw-r--r--sources/plugins/removeformat/lang/vi.js7
-rw-r--r--sources/plugins/removeformat/lang/zh-cn.js7
-rw-r--r--sources/plugins/removeformat/lang/zh.js7
-rw-r--r--sources/plugins/removeformat/plugin.js193
-rw-r--r--sources/plugins/resize/plugin.js187
-rw-r--r--sources/plugins/richcombo/plugin.js434
-rw-r--r--sources/plugins/showborders/plugin.js174
-rw-r--r--sources/plugins/sourcearea/icons/hidpi/source-rtl.pngbin0 -> 1018 bytes
-rw-r--r--sources/plugins/sourcearea/icons/hidpi/source.pngbin0 -> 1041 bytes
-rw-r--r--sources/plugins/sourcearea/icons/source-rtl.pngbin0 -> 565 bytes
-rw-r--r--sources/plugins/sourcearea/icons/source.pngbin0 -> 571 bytes
-rw-r--r--sources/plugins/sourcearea/lang/af.js7
-rw-r--r--sources/plugins/sourcearea/lang/ar.js7
-rw-r--r--sources/plugins/sourcearea/lang/az.js7
-rw-r--r--sources/plugins/sourcearea/lang/bg.js7
-rw-r--r--sources/plugins/sourcearea/lang/bn.js7
-rw-r--r--sources/plugins/sourcearea/lang/bs.js7
-rw-r--r--sources/plugins/sourcearea/lang/ca.js7
-rw-r--r--sources/plugins/sourcearea/lang/cs.js7
-rw-r--r--sources/plugins/sourcearea/lang/cy.js7
-rw-r--r--sources/plugins/sourcearea/lang/da.js7
-rw-r--r--sources/plugins/sourcearea/lang/de-ch.js7
-rw-r--r--sources/plugins/sourcearea/lang/de.js7
-rw-r--r--sources/plugins/sourcearea/lang/el.js7
-rw-r--r--sources/plugins/sourcearea/lang/en-au.js7
-rw-r--r--sources/plugins/sourcearea/lang/en-ca.js7
-rw-r--r--sources/plugins/sourcearea/lang/en-gb.js7
-rw-r--r--sources/plugins/sourcearea/lang/en.js7
-rw-r--r--sources/plugins/sourcearea/lang/eo.js7
-rw-r--r--sources/plugins/sourcearea/lang/es.js7
-rw-r--r--sources/plugins/sourcearea/lang/et.js7
-rw-r--r--sources/plugins/sourcearea/lang/eu.js7
-rw-r--r--sources/plugins/sourcearea/lang/fa.js7
-rw-r--r--sources/plugins/sourcearea/lang/fi.js7
-rw-r--r--sources/plugins/sourcearea/lang/fo.js7
-rw-r--r--sources/plugins/sourcearea/lang/fr-ca.js7
-rw-r--r--sources/plugins/sourcearea/lang/fr.js7
-rw-r--r--sources/plugins/sourcearea/lang/gl.js7
-rw-r--r--sources/plugins/sourcearea/lang/gu.js7
-rw-r--r--sources/plugins/sourcearea/lang/he.js7
-rw-r--r--sources/plugins/sourcearea/lang/hi.js7
-rw-r--r--sources/plugins/sourcearea/lang/hr.js7
-rw-r--r--sources/plugins/sourcearea/lang/hu.js7
-rw-r--r--sources/plugins/sourcearea/lang/id.js7
-rw-r--r--sources/plugins/sourcearea/lang/is.js7
-rw-r--r--sources/plugins/sourcearea/lang/it.js7
-rw-r--r--sources/plugins/sourcearea/lang/ja.js7
-rw-r--r--sources/plugins/sourcearea/lang/ka.js7
-rw-r--r--sources/plugins/sourcearea/lang/km.js7
-rw-r--r--sources/plugins/sourcearea/lang/ko.js7
-rw-r--r--sources/plugins/sourcearea/lang/ku.js7
-rw-r--r--sources/plugins/sourcearea/lang/lt.js7
-rw-r--r--sources/plugins/sourcearea/lang/lv.js7
-rw-r--r--sources/plugins/sourcearea/lang/mk.js7
-rw-r--r--sources/plugins/sourcearea/lang/mn.js7
-rw-r--r--sources/plugins/sourcearea/lang/ms.js7
-rw-r--r--sources/plugins/sourcearea/lang/nb.js7
-rw-r--r--sources/plugins/sourcearea/lang/nl.js7
-rw-r--r--sources/plugins/sourcearea/lang/no.js7
-rw-r--r--sources/plugins/sourcearea/lang/oc.js7
-rw-r--r--sources/plugins/sourcearea/lang/pl.js7
-rw-r--r--sources/plugins/sourcearea/lang/pt-br.js7
-rw-r--r--sources/plugins/sourcearea/lang/pt.js7
-rw-r--r--sources/plugins/sourcearea/lang/ro.js7
-rw-r--r--sources/plugins/sourcearea/lang/ru.js7
-rw-r--r--sources/plugins/sourcearea/lang/si.js7
-rw-r--r--sources/plugins/sourcearea/lang/sk.js7
-rw-r--r--sources/plugins/sourcearea/lang/sl.js7
-rw-r--r--sources/plugins/sourcearea/lang/sq.js7
-rw-r--r--sources/plugins/sourcearea/lang/sr-latn.js7
-rw-r--r--sources/plugins/sourcearea/lang/sr.js7
-rw-r--r--sources/plugins/sourcearea/lang/sv.js7
-rw-r--r--sources/plugins/sourcearea/lang/th.js7
-rw-r--r--sources/plugins/sourcearea/lang/tr.js7
-rw-r--r--sources/plugins/sourcearea/lang/tt.js7
-rw-r--r--sources/plugins/sourcearea/lang/ug.js7
-rw-r--r--sources/plugins/sourcearea/lang/uk.js7
-rw-r--r--sources/plugins/sourcearea/lang/vi.js7
-rw-r--r--sources/plugins/sourcearea/lang/zh-cn.js7
-rw-r--r--sources/plugins/sourcearea/lang/zh.js7
-rw-r--r--sources/plugins/sourcearea/plugin.js168
-rw-r--r--sources/plugins/tab/plugin.js302
-rw-r--r--sources/plugins/toolbar/lang/af.js22
-rw-r--r--sources/plugins/toolbar/lang/ar.js22
-rw-r--r--sources/plugins/toolbar/lang/az.js22
-rw-r--r--sources/plugins/toolbar/lang/bg.js22
-rw-r--r--sources/plugins/toolbar/lang/bn.js22
-rw-r--r--sources/plugins/toolbar/lang/bs.js22
-rw-r--r--sources/plugins/toolbar/lang/ca.js22
-rw-r--r--sources/plugins/toolbar/lang/cs.js22
-rw-r--r--sources/plugins/toolbar/lang/cy.js22
-rw-r--r--sources/plugins/toolbar/lang/da.js22
-rw-r--r--sources/plugins/toolbar/lang/de-ch.js22
-rw-r--r--sources/plugins/toolbar/lang/de.js22
-rw-r--r--sources/plugins/toolbar/lang/el.js22
-rw-r--r--sources/plugins/toolbar/lang/en-au.js22
-rw-r--r--sources/plugins/toolbar/lang/en-ca.js22
-rw-r--r--sources/plugins/toolbar/lang/en-gb.js22
-rw-r--r--sources/plugins/toolbar/lang/en.js22
-rw-r--r--sources/plugins/toolbar/lang/eo.js22
-rw-r--r--sources/plugins/toolbar/lang/es.js22
-rw-r--r--sources/plugins/toolbar/lang/et.js22
-rw-r--r--sources/plugins/toolbar/lang/eu.js22
-rw-r--r--sources/plugins/toolbar/lang/fa.js22
-rw-r--r--sources/plugins/toolbar/lang/fi.js22
-rw-r--r--sources/plugins/toolbar/lang/fo.js22
-rw-r--r--sources/plugins/toolbar/lang/fr-ca.js22
-rw-r--r--sources/plugins/toolbar/lang/fr.js22
-rw-r--r--sources/plugins/toolbar/lang/gl.js22
-rw-r--r--sources/plugins/toolbar/lang/gu.js22
-rw-r--r--sources/plugins/toolbar/lang/he.js22
-rw-r--r--sources/plugins/toolbar/lang/hi.js22
-rw-r--r--sources/plugins/toolbar/lang/hr.js22
-rw-r--r--sources/plugins/toolbar/lang/hu.js22
-rw-r--r--sources/plugins/toolbar/lang/id.js22
-rw-r--r--sources/plugins/toolbar/lang/is.js22
-rw-r--r--sources/plugins/toolbar/lang/it.js22
-rw-r--r--sources/plugins/toolbar/lang/ja.js22
-rw-r--r--sources/plugins/toolbar/lang/ka.js22
-rw-r--r--sources/plugins/toolbar/lang/km.js22
-rw-r--r--sources/plugins/toolbar/lang/ko.js22
-rw-r--r--sources/plugins/toolbar/lang/ku.js22
-rw-r--r--sources/plugins/toolbar/lang/lt.js22
-rw-r--r--sources/plugins/toolbar/lang/lv.js22
-rw-r--r--sources/plugins/toolbar/lang/mk.js22
-rw-r--r--sources/plugins/toolbar/lang/mn.js22
-rw-r--r--sources/plugins/toolbar/lang/ms.js22
-rw-r--r--sources/plugins/toolbar/lang/nb.js22
-rw-r--r--sources/plugins/toolbar/lang/nl.js22
-rw-r--r--sources/plugins/toolbar/lang/no.js22
-rw-r--r--sources/plugins/toolbar/lang/oc.js22
-rw-r--r--sources/plugins/toolbar/lang/pl.js22
-rw-r--r--sources/plugins/toolbar/lang/pt-br.js22
-rw-r--r--sources/plugins/toolbar/lang/pt.js22
-rw-r--r--sources/plugins/toolbar/lang/ro.js22
-rw-r--r--sources/plugins/toolbar/lang/ru.js22
-rw-r--r--sources/plugins/toolbar/lang/si.js22
-rw-r--r--sources/plugins/toolbar/lang/sk.js22
-rw-r--r--sources/plugins/toolbar/lang/sl.js22
-rw-r--r--sources/plugins/toolbar/lang/sq.js22
-rw-r--r--sources/plugins/toolbar/lang/sr-latn.js22
-rw-r--r--sources/plugins/toolbar/lang/sr.js22
-rw-r--r--sources/plugins/toolbar/lang/sv.js22
-rw-r--r--sources/plugins/toolbar/lang/th.js22
-rw-r--r--sources/plugins/toolbar/lang/tr.js22
-rw-r--r--sources/plugins/toolbar/lang/tt.js22
-rw-r--r--sources/plugins/toolbar/lang/ug.js22
-rw-r--r--sources/plugins/toolbar/lang/uk.js22
-rw-r--r--sources/plugins/toolbar/lang/vi.js22
-rw-r--r--sources/plugins/toolbar/lang/zh-cn.js22
-rw-r--r--sources/plugins/toolbar/lang/zh.js22
-rw-r--r--sources/plugins/toolbar/plugin.js806
-rw-r--r--sources/plugins/toolbar/samples/toolbar.html235
-rw-r--r--sources/plugins/widget/dev/assets/contents.css23
-rw-r--r--sources/plugins/widget/dev/assets/sample.jpgbin0 -> 17932 bytes
-rw-r--r--sources/plugins/widget/dev/assets/simplebox/contents.css36
-rw-r--r--sources/plugins/widget/dev/assets/simplebox/dialogs/simplebox.js51
-rw-r--r--sources/plugins/widget/dev/assets/simplebox/icons/simplebox.pngbin0 -> 286 bytes
-rw-r--r--sources/plugins/widget/dev/assets/simplebox/plugin.js114
-rw-r--r--sources/plugins/widget/dev/console.js131
-rw-r--r--sources/plugins/widget/dev/nestedwidgets.html134
-rw-r--r--sources/plugins/widget/dev/widgetstyles.html144
-rw-r--r--sources/plugins/widget/images/handle.pngbin0 -> 220 bytes
-rw-r--r--sources/plugins/widget/lang/af.js8
-rw-r--r--sources/plugins/widget/lang/ar.js8
-rw-r--r--sources/plugins/widget/lang/az.js8
-rw-r--r--sources/plugins/widget/lang/bg.js8
-rw-r--r--sources/plugins/widget/lang/ca.js8
-rw-r--r--sources/plugins/widget/lang/cs.js8
-rw-r--r--sources/plugins/widget/lang/cy.js8
-rw-r--r--sources/plugins/widget/lang/da.js8
-rw-r--r--sources/plugins/widget/lang/de-ch.js8
-rw-r--r--sources/plugins/widget/lang/de.js8
-rw-r--r--sources/plugins/widget/lang/el.js8
-rw-r--r--sources/plugins/widget/lang/en-gb.js8
-rw-r--r--sources/plugins/widget/lang/en.js8
-rw-r--r--sources/plugins/widget/lang/eo.js8
-rw-r--r--sources/plugins/widget/lang/es.js8
-rw-r--r--sources/plugins/widget/lang/eu.js8
-rw-r--r--sources/plugins/widget/lang/fa.js8
-rw-r--r--sources/plugins/widget/lang/fi.js8
-rw-r--r--sources/plugins/widget/lang/fr.js8
-rw-r--r--sources/plugins/widget/lang/gl.js8
-rw-r--r--sources/plugins/widget/lang/he.js8
-rw-r--r--sources/plugins/widget/lang/hr.js8
-rw-r--r--sources/plugins/widget/lang/hu.js8
-rw-r--r--sources/plugins/widget/lang/id.js8
-rw-r--r--sources/plugins/widget/lang/it.js8
-rw-r--r--sources/plugins/widget/lang/ja.js8
-rw-r--r--sources/plugins/widget/lang/km.js8
-rw-r--r--sources/plugins/widget/lang/ko.js8
-rw-r--r--sources/plugins/widget/lang/ku.js8
-rw-r--r--sources/plugins/widget/lang/lv.js8
-rw-r--r--sources/plugins/widget/lang/nb.js8
-rw-r--r--sources/plugins/widget/lang/nl.js8
-rw-r--r--sources/plugins/widget/lang/no.js8
-rw-r--r--sources/plugins/widget/lang/oc.js8
-rw-r--r--sources/plugins/widget/lang/pl.js8
-rw-r--r--sources/plugins/widget/lang/pt-br.js8
-rw-r--r--sources/plugins/widget/lang/pt.js8
-rw-r--r--sources/plugins/widget/lang/ru.js8
-rw-r--r--sources/plugins/widget/lang/sk.js8
-rw-r--r--sources/plugins/widget/lang/sl.js8
-rw-r--r--sources/plugins/widget/lang/sq.js8
-rw-r--r--sources/plugins/widget/lang/sv.js8
-rw-r--r--sources/plugins/widget/lang/tr.js8
-rw-r--r--sources/plugins/widget/lang/tt.js8
-rw-r--r--sources/plugins/widget/lang/ug.js8
-rw-r--r--sources/plugins/widget/lang/uk.js8
-rw-r--r--sources/plugins/widget/lang/vi.js8
-rw-r--r--sources/plugins/widget/lang/zh-cn.js8
-rw-r--r--sources/plugins/widget/lang/zh.js8
-rw-r--r--sources/plugins/widget/plugin.js4126
-rw-r--r--sources/plugins/widgetselection/plugin.js366
-rw-r--r--sources/plugins/wysiwygarea/plugin.js713
-rw-r--r--sources/plugins/wysiwygarea/samples/fullpage.html80
1625 files changed, 65587 insertions, 0 deletions
diff --git a/sources/plugins/a11yhelp/dialogs/a11yhelp.js b/sources/plugins/a11yhelp/dialogs/a11yhelp.js
new file mode 100644
index 0000000..73b930c
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/a11yhelp.js
@@ -0,0 +1,217 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.dialog.add( 'a11yHelp', function( editor ) {
7 var lang = editor.lang.a11yhelp,
8 coreLang = editor.lang.common.keyboard,
9 id = CKEDITOR.tools.getNextId();
10
11 // CharCode <-> KeyChar.
12 var keyMap = {
13 8: coreLang[ 8 ],
14 9: lang.tab,
15 13: coreLang[ 13 ],
16 16: coreLang[ 16 ],
17 17: coreLang[ 17 ],
18 18: coreLang[ 18 ],
19 19: lang.pause,
20 20: lang.capslock,
21 27: lang.escape,
22 33: lang.pageUp,
23 34: lang.pageDown,
24 35: coreLang[ 35 ],
25 36: coreLang[ 36 ],
26 37: lang.leftArrow,
27 38: lang.upArrow,
28 39: lang.rightArrow,
29 40: lang.downArrow,
30 45: lang.insert,
31 46: coreLang[ 46 ],
32 91: lang.leftWindowKey,
33 92: lang.rightWindowKey,
34 93: lang.selectKey,
35 96: lang.numpad0,
36 97: lang.numpad1,
37 98: lang.numpad2,
38 99: lang.numpad3,
39 100: lang.numpad4,
40 101: lang.numpad5,
41 102: lang.numpad6,
42 103: lang.numpad7,
43 104: lang.numpad8,
44 105: lang.numpad9,
45 106: lang.multiply,
46 107: lang.add,
47 109: lang.subtract,
48 110: lang.decimalPoint,
49 111: lang.divide,
50 112: lang.f1,
51 113: lang.f2,
52 114: lang.f3,
53 115: lang.f4,
54 116: lang.f5,
55 117: lang.f6,
56 118: lang.f7,
57 119: lang.f8,
58 120: lang.f9,
59 121: lang.f10,
60 122: lang.f11,
61 123: lang.f12,
62 144: lang.numLock,
63 145: lang.scrollLock,
64 186: lang.semiColon,
65 187: lang.equalSign,
66 188: lang.comma,
67 189: lang.dash,
68 190: lang.period,
69 191: lang.forwardSlash,
70 192: lang.graveAccent,
71 219: lang.openBracket,
72 220: lang.backSlash,
73 221: lang.closeBracket,
74 222: lang.singleQuote
75 };
76
77 // Modifier keys override.
78 keyMap[ CKEDITOR.ALT ] = coreLang[ 18 ];
79 keyMap[ CKEDITOR.SHIFT ] = coreLang[ 16 ];
80 keyMap[ CKEDITOR.CTRL ] = coreLang[ 17 ];
81
82 // Sort in desc.
83 var modifiers = [ CKEDITOR.ALT, CKEDITOR.SHIFT, CKEDITOR.CTRL ];
84
85 function representKeyStroke( keystroke ) {
86 var quotient, modifier,
87 presentation = [];
88
89 for ( var i = 0; i < modifiers.length; i++ ) {
90 modifier = modifiers[ i ];
91 quotient = keystroke / modifiers[ i ];
92 if ( quotient > 1 && quotient <= 2 ) {
93 keystroke -= modifier;
94 presentation.push( keyMap[ modifier ] );
95 }
96 }
97
98 presentation.push( keyMap[ keystroke ] || String.fromCharCode( keystroke ) );
99
100 return presentation.join( '+' );
101 }
102
103 var variablesPattern = /\$\{(.*?)\}/g;
104
105 var replaceVariables = ( function() {
106 // Swaps keystrokes with their commands in object literal.
107 // This makes searching keystrokes by command much easier.
108 var keystrokesByCode = editor.keystrokeHandler.keystrokes,
109 keystrokesByName = {};
110
111 for ( var i in keystrokesByCode )
112 keystrokesByName[ keystrokesByCode[ i ] ] = i;
113
114 return function( match, name ) {
115 // Return the keystroke representation or leave match untouched
116 // if there's no keystroke for such command.
117 return keystrokesByName[ name ] ? representKeyStroke( keystrokesByName[ name ] ) : match;
118 };
119 } )();
120
121 // Create the help list directly from lang file entries.
122 function buildHelpContents() {
123 var pageTpl = '<div class="cke_accessibility_legend" role="document" aria-labelledby="' + id + '_arialbl" tabIndex="-1">%1</div>' +
124 '<span id="' + id + '_arialbl" class="cke_voice_label">' + lang.contents + ' </span>',
125 sectionTpl = '<h1>%1</h1><dl>%2</dl>',
126 itemTpl = '<dt>%1</dt><dd>%2</dd>';
127
128 var pageHtml = [],
129 sections = lang.legend,
130 sectionLength = sections.length;
131
132 for ( var i = 0; i < sectionLength; i++ ) {
133 var section = sections[ i ],
134 sectionHtml = [],
135 items = section.items,
136 itemsLength = items.length;
137
138 for ( var j = 0; j < itemsLength; j++ ) {
139 var item = items[ j ],
140 itemLegend = item.legend.replace( variablesPattern, replaceVariables );
141
142 // (#9765) If some commands haven't been replaced in the legend,
143 // most likely their keystrokes are unavailable and we shouldn't include
144 // them in our help list.
145 if ( itemLegend.match( variablesPattern ) )
146 continue;
147
148 sectionHtml.push( itemTpl.replace( '%1', item.name ).replace( '%2', itemLegend ) );
149 }
150
151 pageHtml.push( sectionTpl.replace( '%1', section.name ).replace( '%2', sectionHtml.join( '' ) ) );
152 }
153
154 return pageTpl.replace( '%1', pageHtml.join( '' ) );
155 }
156
157 return {
158 title: lang.title,
159 minWidth: 600,
160 minHeight: 400,
161 contents: [ {
162 id: 'info',
163 label: editor.lang.common.generalTab,
164 expand: true,
165 elements: [
166 {
167 type: 'html',
168 id: 'legends',
169 style: 'white-space:normal;',
170 focus: function() {
171 this.getElement().focus();
172 },
173 html: buildHelpContents() + '<style type="text/css">' +
174 '.cke_accessibility_legend' +
175 '{' +
176 'width:600px;' +
177 'height:400px;' +
178 'padding-right:5px;' +
179 'overflow-y:auto;' +
180 'overflow-x:hidden;' +
181 '}' +
182 // Some adjustments are to be done for Quirks to work "properly" (#5757)
183 '.cke_browser_quirks .cke_accessibility_legend,' +
184 '{' +
185 'height:390px' +
186 '}' +
187 // Override non-wrapping white-space rule in reset css.
188 '.cke_accessibility_legend *' +
189 '{' +
190 'white-space:normal;' +
191 '}' +
192 '.cke_accessibility_legend h1' +
193 '{' +
194 'font-size: 20px;' +
195 'border-bottom: 1px solid #AAA;' +
196 'margin: 5px 0px 15px;' +
197 '}' +
198 '.cke_accessibility_legend dl' +
199 '{' +
200 'margin-left: 5px;' +
201 '}' +
202 '.cke_accessibility_legend dt' +
203 '{' +
204 'font-size: 13px;' +
205 'font-weight: bold;' +
206 '}' +
207 '.cke_accessibility_legend dd' +
208 '{' +
209 'margin:10px' +
210 '}' +
211 '</style>'
212 }
213 ]
214 } ],
215 buttons: [ CKEDITOR.dialog.cancelButton ]
216 };
217} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/_translationstatus.txt b/sources/plugins/a11yhelp/dialogs/lang/_translationstatus.txt
new file mode 100644
index 0000000..28e8dae
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/_translationstatus.txt
@@ -0,0 +1,25 @@
1Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
2For licensing, see LICENSE.md or http://ckeditor.com/license
3
4cs.js Found: 30 Missing: 0
5cy.js Found: 30 Missing: 0
6da.js Found: 12 Missing: 18
7de.js Found: 30 Missing: 0
8el.js Found: 25 Missing: 5
9eo.js Found: 30 Missing: 0
10fa.js Found: 30 Missing: 0
11fi.js Found: 30 Missing: 0
12fr.js Found: 30 Missing: 0
13gu.js Found: 12 Missing: 18
14he.js Found: 30 Missing: 0
15it.js Found: 30 Missing: 0
16mk.js Found: 5 Missing: 25
17nb.js Found: 30 Missing: 0
18nl.js Found: 30 Missing: 0
19no.js Found: 30 Missing: 0
20pt-br.js Found: 30 Missing: 0
21ro.js Found: 6 Missing: 24
22tr.js Found: 30 Missing: 0
23ug.js Found: 27 Missing: 3
24vi.js Found: 6 Missing: 24
25zh-cn.js Found: 30 Missing: 0
diff --git a/sources/plugins/a11yhelp/dialogs/lang/af.js b/sources/plugins/a11yhelp/dialogs/lang/af.js
new file mode 100644
index 0000000..7469bc1
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/af.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'af', {
7 title: 'Toeganglikheid instruksies',
8 contents: 'Hulp inhoud. Druk ESC om toe te maak.',
9 legend: [
10 {
11 name: 'Algemeen',
12 items: [
13 {
14 name: 'Bewerker balk',
15 legend: 'Druk ${toolbarFocus} om op die werkbalk te land. Beweeg na die volgende en voorige wekrbalkgroep met TAB and SHIFT+TAB. Beweeg na die volgende en voorige werkbalkknop met die regter of linker pyl. Druk SPASIE of ENTER om die knop te bevestig.'
16 },
17
18 {
19 name: 'Bewerker dialoog',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Bewerkerinhoudmenu',
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pouse',
88 capslock: 'Hoofletterslot',
89 escape: 'Ontsnap',
90 pageUp: 'Blaaiop',
91 pageDown: 'Blaaiaf',
92 leftArrow: 'Linkspyl',
93 upArrow: 'Oppyl',
94 rightArrow: 'Regterpyl',
95 downArrow: 'Afpyl',
96 insert: 'Toevoeg',
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Nommerblok 0',
101 numpad1: 'Nommerblok 1',
102 numpad2: 'Nommerblok 2',
103 numpad3: 'Nommerblok 3',
104 numpad4: 'Nommerblok 4',
105 numpad5: 'Nommerblok 5',
106 numpad6: 'Nommerblok 6',
107 numpad7: 'Nommerblok 7',
108 numpad8: 'Nommerblok 8',
109 numpad9: 'Nommerblok 9',
110 multiply: 'Maal',
111 add: 'Plus',
112 subtract: 'Minus',
113 decimalPoint: 'Desimaalepunt',
114 divide: 'Gedeeldeur',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Nommervergrendel',
128 scrollLock: 'Rolvergrendel',
129 semiColon: 'Kommapunt',
130 equalSign: 'Isgelykaan',
131 comma: 'Komma',
132 dash: 'Koppelteken',
133 period: 'Punt',
134 forwardSlash: 'Skuinsstreep',
135 graveAccent: 'Aksentteken',
136 openBracket: 'Oopblokhakkie',
137 backSlash: 'Trustreep',
138 closeBracket: 'Toeblokhakkie',
139 singleQuote: 'Enkelaanhaalingsteken'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ar.js b/sources/plugins/a11yhelp/dialogs/lang/ar.js
new file mode 100644
index 0000000..5c316c7
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ar.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ar', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'عام',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'إضافة',
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'تقسيم',
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'فاصلة',
132 dash: 'Dash', // MISSING
133 period: 'نقطة',
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/az.js b/sources/plugins/a11yhelp/dialogs/lang/az.js
new file mode 100644
index 0000000..9c04b65
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/az.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'az', {
7 title: 'Əlillərə dəstək üzrə təlimat',
8 contents: 'Kömək. Pəncərəni bağlamaq üçün ESC basın.',
9 legend: [
10 {
11 name: 'Əsas',
12 items: [
13 {
14 name: 'Düzəliş edənin alətlər çubuğu',
15 legend: 'Panelə keçmək üçün ${toolbarFocus} basın. Növbəti panelə TAB, əvvəlki panelə isə SHIFT+TAB düyməsi vasitəsi ilə keçə bilərsiz. Paneldəki düymələr arasında sol və sağ ox düyməsi ilə keçid edə bilərsiz. Seçilmiş düyməsi SPACE və ya ENTER ilə işlədə bilərsiniz.'
16 },
17
18 {
19 name: 'Redaktorun pəncərəsi',
20 legend:
21 'Pəncərə içində növbəti element seçmək üçün TAB düyməni basın, əvvəlki isə - SHIFT+TAB. Təsdiq edilməsi üçün ENTER, imtina edilməsi isə ESC diymələri istifadə edin. Pəncərədə bir neçə vərəq olanda olnarın siyahı ALT+F10 ilə aça bilərsiz. Vərəqlərin siyahı fokus altında olanda ox düymələr vasitəsi ilə onların arasında keçid edə bilərsiz.'
22 },
23
24 {
25 name: 'Redaktorun seçimlərin menyusu',
26 legend: 'Seçimləri redaktə etmək üçün ${contextMenu} ya da APPLICATION KEY basın. Növbəti seçimə keçmək üçün TAB ya AŞAĞI OX düyməsini basın, əvvəlki isə - SHIFT+TAB ya YUXARI OX. Seçimi arımaq SPACE ya ENTER düymələri istifadə edin. Alt menyunu açmaq üçün SPACE, ENTER ya SAĞA OX basın. ESC ya SOLA OX ilə geriyə qayıda bilərsiz. Bütün menyunu ESC ilə bağlıyın.'
27 },
28
29 {
30 name: 'Düzəliş edənin siyahı qutusu',
31 legend: 'Siyahı qutusu içində növbəti bənd seçmək üçün TAB ya AŞAĞI OX, əvvəlki isə SHIFT+TAB ya YUXARI OX basın. Seçimi arımaq SPACE ya ENTER düymələri istifadə edin. Siyahı qutusu ESC ilə bağlıyın.'
32 },
33
34 {
35 name: 'Redaktor elementin cığır paneli',
36 legend: 'Elementin cığır paneli seçmək üçün ${elementsPathFocus} basın. Növbəti element seçmək üçün TAB ya SAĞA OX, əvvəlki isə SHIFT+TAB ya SOLA OX istifadə edin. Elementi arımaq SPACE ya ENTER düymələri mövcuddur.'
37 }
38 ]
39 },
40 {
41 name: 'Əmrlər',
42 items: [
43 {
44 name: 'Əmri geri qaytar',
45 legend: '${undo} basın'
46 },
47 {
48 name: 'Geri əmri',
49 legend: '${redo} basın'
50 },
51 {
52 name: 'Qalın əmri',
53 legend: '${bold} basın'
54 },
55 {
56 name: 'Kursiv əmri',
57 legend: '${italic} basın'
58 },
59 {
60 name: 'Altdan xətt əmri',
61 legend: '${underline} basın'
62 },
63 {
64 name: 'Link əmri',
65 legend: '${link} basın'
66 },
67 {
68 name: 'Paneli gizlət əmri',
69 legend: '${toolbarCollapse} basın'
70 },
71 {
72 name: 'Əvvəlki fokus sahəsi seç əmrı',
73 legend: 'Kursordan əvvəl ən yaxın əlçatmaz yerə dəymək üçün ${accessPreviousSpace} basın, misal üçün: iki dal-badal HR teg. Uzaq yerlərə dəymək üçün bir neçə dəfə basın.'
74 },
75 {
76 name: 'Növbəti fokus sahəsi seç əmrı',
77 legend: 'Kursordan sonra ən yaxın əlçatmaz yerə dəymək üçün ${accessNextSpace} basın, misal üçün: iki dal-badal HR teg. Uzaq yerlərə dəymək üçün bir neçə dəfə basın.'
78 },
79 {
80 name: 'Hərtərəfli Kömək',
81 legend: '${a11yHelp} basın'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Sola ox işarəsi',
93 upArrow: 'Yuxarı ox işarəsi',
94 rightArrow: 'Sağa ox işarəsi',
95 downArrow: 'Aşağı ox işarəsi',
96 insert: 'Insert',
97 leftWindowKey: 'Soldaki Windows düyməsi',
98 rightWindowKey: 'Sağdaki Windows düyməsi',
99 selectKey: 'Düyməni seçin',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Vurma',
111 add: 'Əlavə et',
112 subtract: 'Çıxma',
113 decimalPoint: 'Onluq kəsri tam ədəddən ayıran nöqtə',
114 divide: 'Bölüşdürmə',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Nöqtəli verqül',
130 equalSign: 'Barəbərlik işarəsi',
131 comma: 'Vergül',
132 dash: 'Defis',
133 period: 'Nöqtə',
134 forwardSlash: 'Çəp xətt',
135 graveAccent: 'Vurğu işarəsi',
136 openBracket: 'Açılan mötərizə',
137 backSlash: 'Tərs çəpəki xətt',
138 closeBracket: 'Bağlanan mötərizə',
139 singleQuote: 'Tək dırnaq'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/bg.js b/sources/plugins/a11yhelp/dialogs/lang/bg.js
new file mode 100644
index 0000000..ce9cdd8
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/bg.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'bg', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'Общо',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ca.js b/sources/plugins/a11yhelp/dialogs/lang/ca.js
new file mode 100644
index 0000000..f415b90
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ca.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ca', {
7 title: 'Instruccions d\'Accessibilitat',
8 contents: 'Continguts de l\'Ajuda. Per tancar aquest quadre de diàleg premi ESC.',
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Editor de barra d\'eines',
15 legend: 'Premi ${toolbarFocus} per desplaçar-se per la barra d\'eines. Vagi en el següent i anterior grup de barra d\'eines amb TAB i SHIFT+TAB. Vagi en el següent i anterior botó de la barra d\'eines amb RIGHT ARROW i LEFT ARROW. Premi SPACE o ENTER per activar el botó de la barra d\'eines.'
16 },
17
18 {
19 name: 'Editor de quadre de diàleg',
20 legend:
21 'Dins d\'un quadre de diàleg, premi la tecla TAB per desplaçar-se fins al següent element del quadre de diàleg, premi la tecla Shift + TAB per desplaçar-se a l\'anterior element del quadre de diàleg, premi la tecla ENTER per confirmar el quadre de diàleg, premi la tecla ESC per cancel·lar el quadre de diàleg. Quan un quadre de diàleg té diverses pestanyes, la llista de pestanyes pot ser assolit ja sigui amb ALT + F10 o TAB, com a part de l\'ordre de tabulació del quadre de diàleg. Amb la llista de pestanyes seleccionada, pot anar a la fitxa següent i anterior amb la tecla FLETXA DRETA i ESQUERRA, respectivament.'
22 },
23
24 {
25 name: 'Editor de menú contextual',
26 legend: 'Premi ${contextMenu} o APPLICATION KEY per obrir el menú contextual. Després desplacis a la següent opció del menú amb TAB o DOWN ARROW. Desplacis a l\'anterior opció amb SHIFT+TAB o UP ARROW. Premi SPACE o ENTER per seleccionar l\'opció del menú. Obri el submenú de l\'actual opció utilitzant SPACE o ENTER o RIGHT ARROW. Pot tornar a l\'opció del menú pare amb ESC o LEFT ARROW. Tanqui el menú contextual amb ESC.'
27 },
28
29 {
30 name: 'Editor de caixa de llista',
31 legend: 'Dins d\'un quadre de llista, desplacis al següent element de la llista amb TAB o DOWN ARROW. Desplacis a l\'anterior element de la llista amb SHIFT+TAB o UP ARROW. Premi SPACE o ENTER per seleccionar l\'opció de la llista. Premi ESC per tancar el quadre de llista.'
32 },
33
34 {
35 name: 'Editor de barra de ruta de l\'element',
36 legend: 'Premi ${elementsPathFocus} per anar als elements de la barra de ruta. Desplacis al botó de l\'element següent amb TAB o RIGHT ARROW. Desplacis a l\'anterior botó amb SHIFT+TAB o LEFT ARROW. Premi SPACE o ENTER per seleccionar l\'element a l\'editor.'
37 }
38 ]
39 },
40 {
41 name: 'Ordres',
42 items: [
43 {
44 name: 'Desfer ordre',
45 legend: 'Premi ${undo}'
46 },
47 {
48 name: 'Refer ordre',
49 legend: 'Premi ${redo}'
50 },
51 {
52 name: 'Ordre negreta',
53 legend: 'Premi ${bold}'
54 },
55 {
56 name: 'Ordre cursiva',
57 legend: 'Premi ${italic}'
58 },
59 {
60 name: 'Ordre subratllat',
61 legend: 'Premi ${underline}'
62 },
63 {
64 name: 'Ordre enllaç',
65 legend: 'Premi ${link}'
66 },
67 {
68 name: 'Ordre amagar barra d\'eines',
69 legend: 'Premi ${toolbarCollapse}'
70 },
71 {
72 name: 'Ordre per accedir a l\'anterior espai enfocat',
73 legend: 'Premi ${accessPreviousSpace} per accedir a l\'enfocament d\'espai més proper inabastable abans del símbol d\'intercalació, per exemple: dos elements HR adjacents. Repetiu la combinació de tecles per arribar a enfocaments d\'espais distants.'
74 },
75 {
76 name: 'Ordre per accedir al següent espai enfocat',
77 legend: 'Premi ${accessNextSpace} per accedir a l\'enfocament d\'espai més proper inabastable després del símbol d\'intercalació, per exemple: dos elements HR adjacents. Repetiu la combinació de tecles per arribar a enfocaments d\'espais distants.'
78 },
79 {
80 name: 'Ajuda d\'accessibilitat',
81 legend: 'Premi ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulació',
87 pause: 'Pausa',
88 capslock: 'Bloqueig de majúscules',
89 escape: 'Escape',
90 pageUp: 'Pàgina Amunt',
91 pageDown: 'Pàgina Avall',
92 leftArrow: 'Fletxa Esquerra',
93 upArrow: 'Fletxa Amunt',
94 rightArrow: 'Fletxa Dreta',
95 downArrow: 'Fletxa Avall',
96 insert: 'Inserir',
97 leftWindowKey: 'Tecla Windows Esquerra',
98 rightWindowKey: 'Tecla Windows Dreta',
99 selectKey: 'Tecla Seleccionar',
100 numpad0: 'Teclat Numèric 0',
101 numpad1: 'Teclat Numèric 1',
102 numpad2: 'Teclat Numèric 2',
103 numpad3: 'Teclat Numèric 3',
104 numpad4: 'Teclat Numèric 4',
105 numpad5: 'Teclat Numèric 5',
106 numpad6: 'Teclat Numèric 6',
107 numpad7: 'Teclat Numèric 7',
108 numpad8: 'Teclat Numèric 8',
109 numpad9: 'Teclat Numèric 9',
110 multiply: 'Multiplicació',
111 add: 'Suma',
112 subtract: 'Resta',
113 decimalPoint: 'Punt Decimal',
114 divide: 'Divisió',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Bloqueig Teclat Numèric',
128 scrollLock: 'Bloqueig de Desplaçament',
129 semiColon: 'Punt i Coma',
130 equalSign: 'Símbol Igual',
131 comma: 'Coma',
132 dash: 'Guió',
133 period: 'Punt',
134 forwardSlash: 'Barra Diagonal',
135 graveAccent: 'Accent Obert',
136 openBracket: 'Claudàtor Obert',
137 backSlash: 'Barra Invertida',
138 closeBracket: 'Claudàtor Tancat',
139 singleQuote: 'Cometa Simple'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/cs.js b/sources/plugins/a11yhelp/dialogs/lang/cs.js
new file mode 100644
index 0000000..39e4d64
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/cs.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'cs', {
7 title: 'Instrukce pro přístupnost',
8 contents: 'Obsah nápovědy. Pro uzavření tohoto dialogu stiskněte klávesu ESC.',
9 legend: [
10 {
11 name: 'Obecné',
12 items: [
13 {
14 name: 'Panel nástrojů editoru',
15 legend: 'Stiskněte${toolbarFocus} k procházení panelu nástrojů. Přejděte na další a předchozí skupiny pomocí TAB a SHIFT+TAB. Přechod na další a předchozí tlačítko panelu nástrojů je pomocí ŠIPKA VPRAVO nebo ŠIPKA VLEVO. Stisknutím mezerníku nebo klávesy ENTER tlačítko aktivujete.'
16 },
17
18 {
19 name: 'Dialogové okno editoru',
20 legend:
21 'Uvnitř dialogového okna stiskněte TAB pro přesunutí na další prvek okna, stiskněte SHIFT+TAB pro přesun na předchozí prvek okna, stiskněte ENTER pro odeslání dialogu, stiskněte ESC pro jeho zrušení. Pro dialogová okna, která mají mnoho karet stiskněte ALT+F10 pro zaměření seznamu karet, nebo TAB, pro posun podle pořadí karet.Při zaměření seznamu karet se můžete jimi posouvat pomocí ŠIPKY VPRAVO a VLEVO.'
22 },
23
24 {
25 name: 'Kontextové menu editoru',
26 legend: 'Stiskněte ${contextMenu} nebo klávesu APPLICATION k otevření kontextového menu. Pak se přesuňte na další možnost menu pomocí TAB nebo ŠIPKY DOLŮ. Přesuňte se na předchozí možnost pomocí SHIFT+TAB nebo ŠIPKY NAHORU. Stiskněte MEZERNÍK nebo ENTER pro zvolení možnosti menu. Podmenu současné možnosti otevřete pomocí MEZERNÍKU nebo ENTER či ŠIPKY DOLEVA. Kontextové menu uzavřete stiskem ESC.'
27 },
28
29 {
30 name: 'Rámeček seznamu editoru',
31 legend: 'Uvnitř rámečku seznamu se přesunete na další položku menu pomocí TAB nebo ŠIPKA DOLŮ. Na předchozí položku se přesunete SHIFT+TAB nebo ŠIPKA NAHORU. Stiskněte MEZERNÍK nebo ENTER pro zvolení možnosti seznamu. Stiskněte ESC pro uzavření seznamu.'
32 },
33
34 {
35 name: 'Lišta cesty prvku v editoru',
36 legend: 'Stiskněte ${elementsPathFocus} pro procházení lišty cesty prvku. Na další tlačítko prvku se přesunete pomocí TAB nebo ŠIPKA VPRAVO. Na předchozí tlačítko se přesunete pomocí SHIFT+TAB nebo ŠIPKA VLEVO. Stiskněte MEZERNÍK nebo ENTER pro vybrání prvku v editoru.'
37 }
38 ]
39 },
40 {
41 name: 'Příkazy',
42 items: [
43 {
44 name: ' Příkaz Zpět',
45 legend: 'Stiskněte ${undo}'
46 },
47 {
48 name: ' Příkaz Znovu',
49 legend: 'Stiskněte ${redo}'
50 },
51 {
52 name: ' Příkaz Tučné',
53 legend: 'Stiskněte ${bold}'
54 },
55 {
56 name: ' Příkaz Kurzíva',
57 legend: 'Stiskněte ${italic}'
58 },
59 {
60 name: ' Příkaz Podtržení',
61 legend: 'Stiskněte ${underline}'
62 },
63 {
64 name: ' Příkaz Odkaz',
65 legend: 'Stiskněte ${link}'
66 },
67 {
68 name: ' Příkaz Skrýt panel nástrojů',
69 legend: 'Stiskněte ${toolbarCollapse}'
70 },
71 {
72 name: 'Příkaz pro přístup k předchozímu prostoru zaměření',
73 legend: 'Stiskněte ${accessPreviousSpace} pro přístup k nejbližšímu nedosažitelnému prostoru zaměření před stříškou, například: dva přilehlé prvky HR. Pro dosažení vzdálených prostorů zaměření tuto kombinaci kláves opakujte.'
74 },
75 {
76 name: 'Příkaz pro přístup k dalšímu prostoru zaměření',
77 legend: 'Stiskněte ${accessNextSpace} pro přístup k nejbližšímu nedosažitelnému prostoru zaměření po stříšce, například: dva přilehlé prvky HR. Pro dosažení vzdálených prostorů zaměření tuto kombinaci kláves opakujte.'
78 },
79 {
80 name: ' Nápověda přístupnosti',
81 legend: 'Stiskněte ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulátor',
87 pause: 'Pauza',
88 capslock: 'Caps lock',
89 escape: 'Escape',
90 pageUp: 'Stránka nahoru',
91 pageDown: 'Stránka dolů',
92 leftArrow: 'Šipka vlevo',
93 upArrow: 'Šipka nahoru',
94 rightArrow: 'Šipka vpravo',
95 downArrow: 'Šipka dolů',
96 insert: 'Vložit',
97 leftWindowKey: 'Levá klávesa Windows',
98 rightWindowKey: 'Pravá klávesa Windows',
99 selectKey: 'Vyberte klávesu',
100 numpad0: 'Numerická klávesa 0',
101 numpad1: 'Numerická klávesa 1',
102 numpad2: 'Numerická klávesa 2',
103 numpad3: 'Numerická klávesa 3',
104 numpad4: 'Numerická klávesa 4',
105 numpad5: 'Numerická klávesa 5',
106 numpad6: 'Numerická klávesa 6',
107 numpad7: 'Numerická klávesa 7',
108 numpad8: 'Numerická klávesa 8',
109 numpad9: 'Numerická klávesa 9',
110 multiply: 'Numerická klávesa násobení',
111 add: 'Přidat',
112 subtract: 'Numerická klávesa odečítání',
113 decimalPoint: 'Desetinná tečka',
114 divide: 'Numerická klávesa dělení',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num lock',
128 scrollLock: 'Scroll lock',
129 semiColon: 'Středník',
130 equalSign: 'Rovnítko',
131 comma: 'Čárka',
132 dash: 'Pomlčka',
133 period: 'Tečka',
134 forwardSlash: 'Lomítko',
135 graveAccent: 'Přízvuk',
136 openBracket: 'Otevřená hranatá závorka',
137 backSlash: 'Obrácené lomítko',
138 closeBracket: 'Uzavřená hranatá závorka',
139 singleQuote: 'Jednoduchá uvozovka'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/cy.js b/sources/plugins/a11yhelp/dialogs/lang/cy.js
new file mode 100644
index 0000000..3ac77cf
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/cy.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'cy', {
7 title: 'Canllawiau Hygyrchedd',
8 contents: 'Cynnwys Cymorth. I gau y deialog hwn, pwyswch ESC.',
9 legend: [
10 {
11 name: 'Cyffredinol',
12 items: [
13 {
14 name: 'Bar Offer y Golygydd',
15 legend: 'Pwyswch $ {toolbarFocus} i fynd at y bar offer. Symudwch i\'r grŵp bar offer nesaf a blaenorol gyda TAB a SHIFT+TAB. Symudwch i\'r botwm bar offer nesaf a blaenorol gyda SAETH DDE neu SAETH CHWITH. Pwyswch SPACE neu ENTER i wneud botwm y bar offer yn weithredol.'
16 },
17
18 {
19 name: 'Deialog y Golygydd',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Dewislen Cyd-destun y Golygydd',
26 legend: 'Pwyswch $ {contextMenu} neu\'r ALLWEDD \'APPLICATION\' i agor y ddewislen cyd-destun. Yna symudwch i\'r opsiwn ddewislen nesaf gyda\'r TAB neu\'r SAETH I LAWR. Symudwch i\'r opsiwn blaenorol gyda SHIFT+TAB neu\'r SAETH I FYNY. Pwyswch SPACE neu ENTER i ddewis yr opsiwn ddewislen. Agorwch is-dewislen yr opsiwn cyfredol gyda SPACE neu ENTER neu SAETH DDE. Ewch yn ôl i\'r eitem ar y ddewislen uwch gydag ESC neu SAETH CHWITH. Ceuwch y ddewislen cyd-destun gydag ESC.'
27 },
28
29 {
30 name: 'Blwch Rhestr y Golygydd',
31 legend: 'Tu mewn y blwch rhestr, ewch i\'r eitem rhestr nesaf gyda TAB neu\'r SAETH I LAWR. Symudwch i restr eitem flaenorol gyda SHIFT+TAB neu SAETH I FYNY. Pwyswch SPACE neu ENTER i ddewis yr opsiwn o\'r rhestr. Pwyswch ESC i gau\'r rhestr.'
32 },
33
34 {
35 name: 'Bar Llwybr Elfen y Golygydd',
36 legend: 'Pwyswch ${elementsPathFocus} i fynd i\'r bar llwybr elfennau. Symudwch i fotwm yr elfen nesaf gyda TAB neu SAETH DDE. Symudwch i fotwm blaenorol gyda SHIFT+TAB neu SAETH CHWITH. Pwyswch SPACE neu ENTER i ddewis yr elfen yn y golygydd.'
37 }
38 ]
39 },
40 {
41 name: 'Gorchmynion',
42 items: [
43 {
44 name: 'Gorchymyn dadwneud',
45 legend: 'Pwyswch ${undo}'
46 },
47 {
48 name: 'Gorchymyn ailadrodd',
49 legend: 'Pwyswch ${redo}'
50 },
51 {
52 name: 'Gorchymyn Bras',
53 legend: 'Pwyswch ${bold}'
54 },
55 {
56 name: 'Gorchymyn italig',
57 legend: 'Pwyswch ${italig}'
58 },
59 {
60 name: 'Gorchymyn tanlinellu',
61 legend: 'Pwyso ${underline}'
62 },
63 {
64 name: 'Gorchymyn dolen',
65 legend: 'Pwyswch ${link}'
66 },
67 {
68 name: 'Gorchymyn Cwympo\'r Dewislen',
69 legend: 'Pwyswch ${toolbarCollapse}'
70 },
71 {
72 name: 'Myned i orchymyn bwlch ffocws blaenorol',
73 legend: 'Pwyswch ${accessPreviousSpace} i fyned i\'r "blwch ffocws sydd methu ei gyrraedd" cyn y caret, er enghraifft: dwy elfen HR drws nesaf i\'w gilydd. AIladroddwch y cyfuniad allwedd i gyrraedd bylchau ffocws pell.'
74 },
75 {
76 name: 'Ewch i\'r gorchymyn blwch ffocws nesaf',
77 legend: 'Pwyswch ${accessNextSpace} i fyned i\'r blwch ffocws agosaf nad oes modd ei gyrraedd ar ôl y caret, er enghraifft: dwy elfen HR drws nesaf i\'w gilydd. Ailadroddwch y cyfuniad allwedd i gyrraedd blychau ffocws pell.'
78 },
79 {
80 name: 'Cymorth Hygyrchedd',
81 legend: 'Pwyswch ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape',
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/da.js b/sources/plugins/a11yhelp/dialogs/lang/da.js
new file mode 100644
index 0000000..f507bf0
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/da.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'da', {
7 title: 'Tilgængelighedsinstrukser',
8 contents: 'Onlinehjælp. For at lukke dette vindue klik ESC',
9 legend: [
10 {
11 name: 'Generelt',
12 items: [
13 {
14 name: 'Editor værktøjslinje',
15 legend: 'Tryk ${toolbarFocus} for at navigere til værktøjslinjen. Flyt til næste eller forrige værktøjsline gruppe ved hjælp af TAB eller SHIFT+TAB. Flyt til næste eller forrige værktøjslinje knap med venstre- eller højre piltast. Tryk på SPACE eller ENTER for at aktivere værktøjslinje knappen.'
16 },
17
18 {
19 name: 'Editor dialogboks',
20 legend:
21 'Inde i en dialogboks kan du, trykke på TAB for at navigere til næste element, trykke på SHIFT+TAB for at navigere til forrige element, trykke på ENTER for at afsende eller trykke på ESC for at lukke dialogboksen.\r\nNår en dialogboks har flere faner, fanelisten kan tilgås med ALT+F10 eller med TAB. Hvis fanelisten er i fokus kan du skifte til næste eller forrige tab, med højre- og venstre piltast.'
22 },
23
24 {
25 name: 'Redaktør kontekstmenu',
26 legend: 'Tryk ${contextMenu} eller APPLICATION KEY for at åbne kontekstmenuen. Flyt derefter til næste menuvalg med TAB eller PIL NED. Flyt til forrige valg med SHIFT+TAB eller PIL OP. Tryk MELLEMRUM eller RETUR for at vælge menu-muligheder. Åben under-menu af aktuelle valg med MELLEMRUM eller RETUR eller HØJRE PIL. Gå tilbage til overliggende menu-emne med ESC eller VENSTRE PIL. Luk kontekstmenu med ESC.'
27 },
28
29 {
30 name: 'Redaktør listeboks',
31 legend: 'Flyt til næste emne med TAB eller PIL NED inde i en listeboks. Flyt til forrige listeemne med SHIFT+TAB eller PIL OP. Tryk MELLEMRUM eller RETUR for at vælge liste-muligheder. Tryk ESC for at lukke liste-boksen.'
32 },
33
34 {
35 name: 'Redaktør elementsti-bar',
36 legend: 'Tryk ${elementsPathFocus} for at navigere til elementernes sti-bar. Flyt til næste element-knap med TAB eller HØJRE PIL. Flyt til forrige knap med SHIFT+TAB eller VENSTRE PIL. Klik MELLEMRUM eller RETUR for at vælge element i editoren.'
37 }
38 ]
39 },
40 {
41 name: 'Kommandoer',
42 items: [
43 {
44 name: 'Fortryd kommando',
45 legend: 'Klik på ${undo}'
46 },
47 {
48 name: 'Gentag kommando',
49 legend: 'Klik ${redo}'
50 },
51 {
52 name: 'Fed kommando',
53 legend: 'Klik ${bold}'
54 },
55 {
56 name: 'Kursiv kommando',
57 legend: 'Klik ${italic}'
58 },
59 {
60 name: 'Understregnings kommando',
61 legend: 'Klik ${underline}'
62 },
63 {
64 name: 'Link kommando',
65 legend: 'Klik ${link}'
66 },
67 {
68 name: 'Klap værktøjslinje sammen kommando ',
69 legend: 'Klik ${toolbarCollapse}'
70 },
71 {
72 name: 'Adgang til forrige fokusområde kommando',
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: 'Tilgængelighedshjælp',
81 legend: 'Kilk ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Venstre pil',
93 upArrow: 'Pil op',
94 rightArrow: 'Højre pil',
95 downArrow: 'Pil ned',
96 insert: 'Insert',
97 leftWindowKey: 'Venstre Windows tast',
98 rightWindowKey: 'Højre Windows tast',
99 selectKey: 'Select-knap',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Gange',
111 add: 'Plus',
112 subtract: 'Minus',
113 decimalPoint: 'Komma',
114 divide: 'Divider',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semikolon',
130 equalSign: 'Lighedstegn',
131 comma: 'Komma',
132 dash: 'Bindestreg',
133 period: 'Punktum',
134 forwardSlash: 'Skråstreg',
135 graveAccent: 'Accent grave',
136 openBracket: 'Start klamme',
137 backSlash: 'Omvendt skråstreg',
138 closeBracket: 'Slut klamme',
139 singleQuote: 'Enkelt citationstegn'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/de-ch.js b/sources/plugins/a11yhelp/dialogs/lang/de-ch.js
new file mode 100644
index 0000000..8d26d73
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/de-ch.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'de-ch', {
7 title: 'Barrierefreiheitinformationen',
8 contents: 'Hilfeinhalt. Um den Dialog zu schliessen die Taste ESC drücken.',
9 legend: [
10 {
11 name: 'Allgemein',
12 items: [
13 {
14 name: 'Editorwerkzeugleiste',
15 legend: 'Drücken Sie ${toolbarFocus} auf der Symbolleiste. Gehen Sie zur nächsten oder vorherigen Symbolleistengruppe mit TAB und SHIFT+TAB. Gehen Sie zur nächsten oder vorherigen Symbolleiste auf die Schaltfläche mit dem RECHTS- oder LINKS-Pfeil. Drücken Sie die Leertaste oder Eingabetaste, um die Schaltfläche in der Symbolleiste aktivieren.'
16 },
17
18 {
19 name: 'Editordialog',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor-Kontextmenü',
26 legend: 'Dürcken Sie ${contextMenu} oder die Anwendungstaste um das Kontextmenü zu öffnen. Man kann die Pfeiltasten zum Wechsel benutzen. Mit der Leertaste oder der Enter-Taste kann man den Menüpunkt aufrufen. Schliessen Sie das Kontextmenü mit der ESC-Taste.'
27 },
28
29 {
30 name: 'Editor-Listenbox',
31 legend: 'Innerhalb einer Listenbox kann man mit der TAB-Taste oder den Pfeilrunter-Taste den nächsten Menüeintrag wählen. Mit der SHIFT+TAB Tastenkombination oder der Pfeilhoch-Taste gelangt man zum vorherigen Menüpunkt. Mit der Leertaste oder Enter kann man den Menüpunkt auswählen. Drücken Sie ESC zum Verlassen des Menüs.'
32 },
33
34 {
35 name: 'Editor-Elementpfadleiste',
36 legend: 'Drücken Sie ${elementsPathFocus} um sich durch die Pfadleiste zu bewegen. Um zum nächsten Element zu gelangen drücken Sie TAB oder die Pfeilrechts-Taste. Zum vorherigen Element gelangen Sie mit der SHIFT+TAB oder der Pfeillinks-Taste. Drücken Sie die Leertaste oder Enter um das Element auszuwählen.'
37 }
38 ]
39 },
40 {
41 name: 'Befehle',
42 items: [
43 {
44 name: 'Rückgängig-Befehl',
45 legend: 'Drücken Sie ${undo}'
46 },
47 {
48 name: 'Wiederherstellen-Befehl',
49 legend: 'Drücken Sie ${redo}'
50 },
51 {
52 name: 'Fettschrift-Befehl',
53 legend: 'Drücken Sie ${bold}'
54 },
55 {
56 name: 'Kursiv-Befehl',
57 legend: 'Drücken Sie ${italic}'
58 },
59 {
60 name: 'Unterstreichen-Befehl',
61 legend: 'Drücken Sie ${underline}'
62 },
63 {
64 name: 'Link-Befehl',
65 legend: 'Drücken Sie ${link}'
66 },
67 {
68 name: 'Werkzeugleiste einklappen-Befehl',
69 legend: 'Drücken Sie ${toolbarCollapse}'
70 },
71 {
72 name: 'Zugang bisheriger Fokussierung Raumbefehl ',
73 legend: 'Drücken Sie ${accessPreviousSpace} auf den am nächsten nicht erreichbar Fokus-Abstand vor die Einfügemarke zugreifen: zwei benachbarte HR-Elemente. Wiederholen Sie die Tastenkombination um entfernte Fokusräume zu erreichen. '
74 },
75 {
76 name: 'Zugang nächster Schwerpunkt Raumbefehl ',
77 legend: 'Drücken Sie $ { accessNextSpace }, um den nächsten unerreichbar Fokus Leerzeichen nach dem Cursor zum Beispiel auf: zwei benachbarten HR Elemente. Wiederholen Sie die Tastenkombination zum fernen Fokus Bereiche zu erreichen. '
78 },
79 {
80 name: 'Eingabehilfen',
81 legend: 'Drücken Sie ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Feststell',
89 escape: 'Escape',
90 pageUp: 'Bild auf',
91 pageDown: 'Bild ab',
92 leftArrow: 'Linke Pfeiltaste',
93 upArrow: 'Obere Pfeiltaste',
94 rightArrow: 'Rechte Pfeiltaste',
95 downArrow: 'Untere Pfeiltaste',
96 insert: 'Einfügen',
97 leftWindowKey: 'Linke Windowstaste',
98 rightWindowKey: 'Rechte Windowstaste',
99 selectKey: 'Taste auswählen',
100 numpad0: 'Ziffernblock 0',
101 numpad1: 'Ziffernblock 1',
102 numpad2: 'Ziffernblock 2',
103 numpad3: 'Ziffernblock 3',
104 numpad4: 'Ziffernblock 4',
105 numpad5: 'Ziffernblock 5',
106 numpad6: 'Ziffernblock 6',
107 numpad7: 'Ziffernblock 7',
108 numpad8: 'Ziffernblock 8',
109 numpad9: 'Ziffernblock 9',
110 multiply: 'Multiplizieren',
111 add: 'Addieren',
112 subtract: 'Subtrahieren',
113 decimalPoint: 'Punkt',
114 divide: 'Dividieren',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Ziffernblock feststellen',
128 scrollLock: 'Rollen',
129 semiColon: 'Semikolon',
130 equalSign: 'Gleichheitszeichen',
131 comma: 'Komma',
132 dash: 'Bindestrich',
133 period: 'Punkt',
134 forwardSlash: 'Schrägstrich',
135 graveAccent: 'Gravis',
136 openBracket: 'Öffnende eckige Klammer',
137 backSlash: 'Rückwärtsgewandter Schrägstrich',
138 closeBracket: 'Schliessende eckige Klammer',
139 singleQuote: 'Einfaches Anführungszeichen'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/de.js b/sources/plugins/a11yhelp/dialogs/lang/de.js
new file mode 100644
index 0000000..c74be37
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/de.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'de', {
7 title: 'Barrierefreiheitinformationen',
8 contents: 'Hilfeinhalt. Um den Dialog zu schliessen die Taste ESC drücken.',
9 legend: [
10 {
11 name: 'Allgemein',
12 items: [
13 {
14 name: 'Editorwerkzeugleiste',
15 legend: 'Drücken Sie ${toolbarFocus} auf der Symbolleiste. Gehen Sie zur nächsten oder vorherigen Symbolleistengruppe mit TAB und SHIFT+TAB. Gehen Sie zur nächsten oder vorherigen Symbolleiste auf die Schaltfläche mit dem RECHTS- oder LINKS-Pfeil. Drücken Sie die Leertaste oder Eingabetaste, um die Schaltfläche in der Symbolleiste aktivieren.'
16 },
17
18 {
19 name: 'Editordialog',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor-Kontextmenü',
26 legend: 'Dürcken Sie ${contextMenu} oder die Anwendungstaste um das Kontextmenü zu öffnen. Man kann die Pfeiltasten zum Wechsel benutzen. Mit der Leertaste oder der Enter-Taste kann man den Menüpunkt aufrufen. Schliessen Sie das Kontextmenü mit der ESC-Taste.'
27 },
28
29 {
30 name: 'Editor-Listenbox',
31 legend: 'Innerhalb einer Listenbox kann man mit der TAB-Taste oder den Pfeilrunter-Taste den nächsten Menüeintrag wählen. Mit der SHIFT+TAB Tastenkombination oder der Pfeilhoch-Taste gelangt man zum vorherigen Menüpunkt. Mit der Leertaste oder Enter kann man den Menüpunkt auswählen. Drücken Sie ESC zum Verlassen des Menüs.'
32 },
33
34 {
35 name: 'Editor-Elementpfadleiste',
36 legend: 'Drücken Sie ${elementsPathFocus} um sich durch die Pfadleiste zu bewegen. Um zum nächsten Element zu gelangen drücken Sie TAB oder die Pfeilrechts-Taste. Zum vorherigen Element gelangen Sie mit der SHIFT+TAB oder der Pfeillinks-Taste. Drücken Sie die Leertaste oder Enter um das Element auszuwählen.'
37 }
38 ]
39 },
40 {
41 name: 'Befehle',
42 items: [
43 {
44 name: 'Rückgängig-Befehl',
45 legend: 'Drücken Sie ${undo}'
46 },
47 {
48 name: 'Wiederherstellen-Befehl',
49 legend: 'Drücken Sie ${redo}'
50 },
51 {
52 name: 'Fettschrift-Befehl',
53 legend: 'Drücken Sie ${bold}'
54 },
55 {
56 name: 'Kursiv-Befehl',
57 legend: 'Drücken Sie ${italic}'
58 },
59 {
60 name: 'Unterstreichen-Befehl',
61 legend: 'Drücken Sie ${underline}'
62 },
63 {
64 name: 'Link-Befehl',
65 legend: 'Drücken Sie ${link}'
66 },
67 {
68 name: 'Werkzeugleiste einklappen-Befehl',
69 legend: 'Drücken Sie ${toolbarCollapse}'
70 },
71 {
72 name: 'Zugang bisheriger Fokussierung Raumbefehl ',
73 legend: 'Drücken Sie ${accessPreviousSpace} auf den am nächsten nicht erreichbar Fokus-Abstand vor die Einfügemarke zugreifen: zwei benachbarte HR-Elemente. Wiederholen Sie die Tastenkombination um entfernte Fokusräume zu erreichen. '
74 },
75 {
76 name: 'Zugang nächster Schwerpunkt Raumbefehl ',
77 legend: 'Drücken Sie $ { accessNextSpace }, um den nächsten unerreichbar Fokus Leerzeichen nach dem Cursor zum Beispiel auf: zwei benachbarten HR Elemente. Wiederholen Sie die Tastenkombination zum fernen Fokus Bereiche zu erreichen. '
78 },
79 {
80 name: 'Eingabehilfen',
81 legend: 'Drücken Sie ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Feststell',
89 escape: 'Escape',
90 pageUp: 'Bild auf',
91 pageDown: 'Bild ab',
92 leftArrow: 'Linke Pfeiltaste',
93 upArrow: 'Obere Pfeiltaste',
94 rightArrow: 'Rechte Pfeiltaste',
95 downArrow: 'Untere Pfeiltaste',
96 insert: 'Einfügen',
97 leftWindowKey: 'Linke Windowstaste',
98 rightWindowKey: 'Rechte Windowstaste',
99 selectKey: 'Taste auswählen',
100 numpad0: 'Ziffernblock 0',
101 numpad1: 'Ziffernblock 1',
102 numpad2: 'Ziffernblock 2',
103 numpad3: 'Ziffernblock 3',
104 numpad4: 'Ziffernblock 4',
105 numpad5: 'Ziffernblock 5',
106 numpad6: 'Ziffernblock 6',
107 numpad7: 'Ziffernblock 7',
108 numpad8: 'Ziffernblock 8',
109 numpad9: 'Ziffernblock 9',
110 multiply: 'Multiplizieren',
111 add: 'Addieren',
112 subtract: 'Subtrahieren',
113 decimalPoint: 'Punkt',
114 divide: 'Dividieren',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Ziffernblock feststellen',
128 scrollLock: 'Rollen',
129 semiColon: 'Semikolon',
130 equalSign: 'Gleichheitszeichen',
131 comma: 'Komma',
132 dash: 'Bindestrich',
133 period: 'Punkt',
134 forwardSlash: 'Schrägstrich',
135 graveAccent: 'Gravis',
136 openBracket: 'Öffnende eckige Klammer',
137 backSlash: 'Rückwärtsgewandter Schrägstrich',
138 closeBracket: 'Schließende eckige Klammer',
139 singleQuote: 'Einfaches Anführungszeichen'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/el.js b/sources/plugins/a11yhelp/dialogs/lang/el.js
new file mode 100644
index 0000000..11febeb
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/el.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'el', {
7 title: 'Οδηγίες Προσβασιμότητας',
8 contents: 'Περιεχόμενα Βοήθειας. Πατήστε ESC για κλείσιμο.',
9 legend: [
10 {
11 name: 'Γενικά',
12 items: [
13 {
14 name: 'Εργαλειοθήκη Επεξεργαστή',
15 legend: 'Πατήστε ${toolbarFocus} για να περιηγηθείτε στην γραμμή εργαλείων. Μετακινηθείτε ανάμεσα στις ομάδες της γραμμής εργαλείων με TAB και SHIFT+TAB. Μετακινηθείτε ανάμεσα στα κουμπιά εργαλείων με το ΔΕΞΙ ή ΑΡΙΣΤΕΡΟ ΒΕΛΑΚΙ. Πατήστε ΔΙΑΣΤΗΜΑ ή ENTER για να ενεργοποιήσετε το ενεργό κουμπί εργαλείου.'
16 },
17
18 {
19 name: 'Παράθυρο Διαλόγου Επεξεργαστή',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Αναδυόμενο Μενού Επεξεργαστή',
26 legend: 'Πατήστε ${contextMenu} ή APPLICATION KEY για να ανοίξετε το αναδυόμενο μενού. Μετά μετακινηθείτε στην επόμενη επιλογή του μενού με TAB ή ΚΑΤΩ ΒΕΛΑΚΙ. Μετακινηθείτε στην προηγούμενη επιλογή με SHIFT+TAB ή το ΠΑΝΩ ΒΕΛΑΚΙ. Πατήστε ΔΙΑΣΤΗΜΑ ή ENTER για να επιλέξτε το τρέχων στοιχείο. Ανοίξτε το αναδυόμενο μενού της τρέχουσας επιλογής με ΔΙΑΣΤΗΜΑ ή ENTER ή το ΔΕΞΙ ΒΕΛΑΚΙ. Μεταβείτε πίσω στο αρχικό στοιχείο μενού με το ESC ή το ΑΡΙΣΤΕΡΟ ΒΕΛΑΚΙ. Κλείστε το αναδυόμενο μενού με ESC.'
27 },
28
29 {
30 name: 'Κουτί Λίστας Επεξεργαστών',
31 legend: 'Μέσα σε ένα κουτί λίστας, μετακινηθείτε στο επόμενο στοιχείο με TAB ή ΚΑΤΩ ΒΕΛΑΚΙ. Μετακινηθείτε στο προηγούμενο στοιχείο με SHIFT+TAB ή το ΠΑΝΩ ΒΕΛΑΚΙ. Πατήστε ΔΙΑΣΤΗΜΑ ή ENTER για να επιλέξετε ένα στοιχείο. Πατήστε ESC για να κλείσετε το κουτί της λίστας.'
32 },
33
34 {
35 name: 'Μπάρα Διαδρομών Στοιχείων Επεξεργαστή',
36 legend: 'Πατήστε ${elementsPathFocus} για να περιηγηθείτε στην μπάρα διαδρομών στοιχείων του επεξεργαστή. Μετακινηθείτε στο κουμπί του επόμενου στοιχείου με το TAB ή το ΔΕΞΙ ΒΕΛΑΚΙ. Μετακινηθείτε στο κουμπί του προηγούμενου στοιχείου με το SHIFT+TAB ή το ΑΡΙΣΤΕΡΟ ΒΕΛΑΚΙ. Πατήστε ΔΙΑΣΤΗΜΑ ή ENTER για να επιλέξετε το στοιχείο στον επεξεργαστή.'
37 }
38 ]
39 },
40 {
41 name: 'Εντολές',
42 items: [
43 {
44 name: 'Εντολή αναίρεσης',
45 legend: 'Πατήστε ${undo}'
46 },
47 {
48 name: 'Εντολή επανάληψης',
49 legend: 'Πατήστε ${redo}'
50 },
51 {
52 name: 'Εντολή έντονης γραφής',
53 legend: 'Πατήστε ${bold}'
54 },
55 {
56 name: 'Εντολή πλάγιας γραφής',
57 legend: 'Πατήστε ${italic}'
58 },
59 {
60 name: 'Εντολή υπογράμμισης',
61 legend: 'Πατήστε ${underline}'
62 },
63 {
64 name: 'Εντολή συνδέσμου',
65 legend: 'Πατήστε ${link}'
66 },
67 {
68 name: 'Εντολή Σύμπτηξης Εργαλειοθήκης',
69 legend: 'Πατήστε ${toolbarCollapse}'
70 },
71 {
72 name: 'Πρόσβαση στην προηγούμενη εντολή του χώρου εστίασης ',
73 legend: 'Πατήστε ${accessPreviousSpace} για να έχετε πρόσβαση στον πιο κοντινό χώρο εστίασης πριν το δρομέα, για παράδειγμα: δύο παρακείμενα στοιχεία ΥΕ. Επαναλάβετε το συνδυασμό πλήκτρων για να φθάσετε στους χώρους μακρινής εστίασης. '
74 },
75 {
76 name: 'Πρόσβαση στην επόμενη εντολή του χώρου εστίασης',
77 legend: 'Πατήστε ${accessNextSpace} για να έχετε πρόσβαση στον πιο κοντινό χώρο εστίασης μετά το δρομέα, για παράδειγμα: δύο παρακείμενα στοιχεία ΥΕ. Επαναλάβετε το συνδυασμό πλήκτρων για τους χώρους μακρινής εστίασης. '
78 },
79 {
80 name: 'Βοήθεια Προσβασιμότητας',
81 legend: 'Πατήστε ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Αριστερό Βέλος',
93 upArrow: 'Πάνω Βέλος',
94 rightArrow: 'Δεξί Βέλος',
95 downArrow: 'Κάτω Βέλος',
96 insert: 'Insert ',
97 leftWindowKey: 'Αριστερό Πλήκτρο Windows',
98 rightWindowKey: 'Δεξί Πλήκτρο Windows',
99 selectKey: 'Πλήκτρο Select',
100 numpad0: 'Αριθμητικό πληκτρολόγιο 0',
101 numpad1: 'Αριθμητικό Πληκτρολόγιο 1',
102 numpad2: 'Αριθμητικό πληκτρολόγιο 2',
103 numpad3: 'Αριθμητικό πληκτρολόγιο 3',
104 numpad4: 'Αριθμητικό πληκτρολόγιο 4',
105 numpad5: 'Αριθμητικό πληκτρολόγιο 5',
106 numpad6: 'Αριθμητικό πληκτρολόγιο 6',
107 numpad7: 'Αριθμητικό πληκτρολόγιο 7',
108 numpad8: 'Αριθμητικό πληκτρολόγιο 8',
109 numpad9: 'Αριθμητικό πληκτρολόγιο 9',
110 multiply: 'Πολλαπλασιασμός',
111 add: 'Πρόσθεση',
112 subtract: 'Αφαίρεση',
113 decimalPoint: 'Υποδιαστολή',
114 divide: 'Διαίρεση',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: '6',
121 f7: '7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Ερωτηματικό',
130 equalSign: 'Σύμβολο Ισότητας',
131 comma: 'Κόμμα',
132 dash: 'Παύλα',
133 period: 'Τελεία',
134 forwardSlash: 'Κάθετος',
135 graveAccent: 'Βαρεία',
136 openBracket: 'Άνοιγμα Παρένθεσης',
137 backSlash: 'Ανάστροφη Κάθετος',
138 closeBracket: 'Κλείσιμο Παρένθεσης',
139 singleQuote: 'Απόστροφος'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/en-gb.js b/sources/plugins/a11yhelp/dialogs/lang/en-gb.js
new file mode 100644
index 0000000..98bf636
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/en-gb.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'en-gb', {
7 title: 'Accessibility Instructions',
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Editor Toolbar',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu',
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box',
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar',
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands',
42 items: [
43 {
44 name: ' Undo command',
45 legend: 'Press ${undo}'
46 },
47 {
48 name: ' Redo command',
49 legend: 'Press ${redo}'
50 },
51 {
52 name: ' Bold command',
53 legend: 'Press ${bold}'
54 },
55 {
56 name: ' Italic command',
57 legend: 'Press ${italic}'
58 },
59 {
60 name: ' Underline command',
61 legend: 'Press ${underline}'
62 },
63 {
64 name: ' Link command',
65 legend: 'Press ${link}'
66 },
67 {
68 name: ' Toolbar Collapse command',
69 legend: 'Press ${toolbarCollapse}'
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help',
81 legend: 'Press ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Left Arrow',
93 upArrow: 'Up Arrow',
94 rightArrow: 'Right Arrow',
95 downArrow: 'Down Arrow',
96 insert: 'Insert',
97 leftWindowKey: 'Left Windows key',
98 rightWindowKey: 'Right Windows key',
99 selectKey: 'Select key',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Multiply',
111 add: 'Add',
112 subtract: 'Subtract',
113 decimalPoint: 'Decimal Point',
114 divide: 'Divide',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semicolon',
130 equalSign: 'Equal Sign',
131 comma: 'Comma',
132 dash: 'Dash',
133 period: 'Period',
134 forwardSlash: 'Forward Slash',
135 graveAccent: 'Grave Accent',
136 openBracket: 'Open Bracket',
137 backSlash: 'Backslash',
138 closeBracket: 'Close Bracket',
139 singleQuote: 'Single Quote'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/en.js b/sources/plugins/a11yhelp/dialogs/lang/en.js
new file mode 100644
index 0000000..fee0b4e
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/en.js
@@ -0,0 +1,159 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'en', {
7 title: 'Accessibility Instructions',
8 contents: 'Help Contents. To close this dialog press ESC.',
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Editor Toolbar',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. ' +
16 'Move to the next and previous toolbar group with TAB and SHIFT+TAB. ' +
17 'Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. ' +
18 'Press SPACE or ENTER to activate the toolbar button.'
19 },
20
21 {
22 name: 'Editor Dialog',
23 legend:
24 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. ' +
25 'When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. ' +
26 'With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.'
27 },
28
29 {
30 name: 'Editor Context Menu',
31 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. ' +
32 'Then move to next menu option with TAB or DOWN ARROW. ' +
33 'Move to previous option with SHIFT+TAB or UP ARROW. ' +
34 'Press SPACE or ENTER to select the menu option. ' +
35 'Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. ' +
36 'Go back to parent menu item with ESC or LEFT ARROW. ' +
37 'Close context menu with ESC.'
38 },
39
40 {
41 name: 'Editor List Box',
42 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. ' +
43 'Move to previous list item with SHIFT+TAB or UP ARROW. ' +
44 'Press SPACE or ENTER to select the list option. ' +
45 'Press ESC to close the list-box.'
46 },
47
48 {
49 name: 'Editor Element Path Bar',
50 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. ' +
51 'Move to next element button with TAB or RIGHT ARROW. ' +
52 'Move to previous button with SHIFT+TAB or LEFT ARROW. ' +
53 'Press SPACE or ENTER to select the element in editor.'
54 }
55 ]
56 },
57 {
58 name: 'Commands',
59 items: [
60 {
61 name: ' Undo command',
62 legend: 'Press ${undo}'
63 },
64 {
65 name: ' Redo command',
66 legend: 'Press ${redo}'
67 },
68 {
69 name: ' Bold command',
70 legend: 'Press ${bold}'
71 },
72 {
73 name: ' Italic command',
74 legend: 'Press ${italic}'
75 },
76 {
77 name: ' Underline command',
78 legend: 'Press ${underline}'
79 },
80 {
81 name: ' Link command',
82 legend: 'Press ${link}'
83 },
84 {
85 name: ' Toolbar Collapse command',
86 legend: 'Press ${toolbarCollapse}'
87 },
88 {
89 name: ' Access previous focus space command',
90 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, ' +
91 'for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.'
92 },
93 {
94 name: ' Access next focus space command',
95 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, ' +
96 'for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.'
97 },
98 {
99 name: ' Accessibility Help',
100 legend: 'Press ${a11yHelp}'
101 }
102 ]
103 }
104 ],
105 tab: 'Tab',
106 pause: 'Pause',
107 capslock: 'Caps Lock',
108 escape: 'Escape',
109 pageUp: 'Page Up',
110 pageDown: 'Page Down',
111 leftArrow: 'Left Arrow',
112 upArrow: 'Up Arrow',
113 rightArrow: 'Right Arrow',
114 downArrow: 'Down Arrow',
115 insert: 'Insert',
116 leftWindowKey: 'Left Windows key',
117 rightWindowKey: 'Right Windows key',
118 selectKey: 'Select key',
119 numpad0: 'Numpad 0',
120 numpad1: 'Numpad 1',
121 numpad2: 'Numpad 2',
122 numpad3: 'Numpad 3',
123 numpad4: 'Numpad 4',
124 numpad5: 'Numpad 5',
125 numpad6: 'Numpad 6',
126 numpad7: 'Numpad 7',
127 numpad8: 'Numpad 8',
128 numpad9: 'Numpad 9',
129 multiply: 'Multiply',
130 add: 'Add',
131 subtract: 'Subtract',
132 decimalPoint: 'Decimal Point',
133 divide: 'Divide',
134 f1: 'F1',
135 f2: 'F2',
136 f3: 'F3',
137 f4: 'F4',
138 f5: 'F5',
139 f6: 'F6',
140 f7: 'F7',
141 f8: 'F8',
142 f9: 'F9',
143 f10: 'F10',
144 f11: 'F11',
145 f12: 'F12',
146 numLock: 'Num Lock',
147 scrollLock: 'Scroll Lock',
148 semiColon: 'Semicolon',
149 equalSign: 'Equal Sign',
150 comma: 'Comma',
151 dash: 'Dash',
152 period: 'Period',
153 forwardSlash: 'Forward Slash',
154 graveAccent: 'Grave Accent',
155 openBracket: 'Open Bracket',
156 backSlash: 'Backslash',
157 closeBracket: 'Close Bracket',
158 singleQuote: 'Single Quote'
159} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/eo.js b/sources/plugins/a11yhelp/dialogs/lang/eo.js
new file mode 100644
index 0000000..c2bc106
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/eo.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'eo', {
7 title: 'Uzindikoj pri atingeblo',
8 contents: 'Helpilenhavo. Por fermi tiun dialogon, premu la ESKAPAN klavon.',
9 legend: [
10 {
11 name: 'Ĝeneralaĵoj',
12 items: [
13 {
14 name: 'Ilbreto de la redaktilo',
15 legend: 'Premu ${toolbarFocus} por atingi la ilbreton. Moviĝu al la sekva aŭ antaŭa grupoj de la ilbreto per la klavoj TABA kaj MAJUSKLIGA+TABA. Moviĝu al la sekva aŭ antaŭa butonoj de la ilbreto per la klavoj SAGO DEKSTREN kaj SAGO MALDEKSTREN. Premu la SPACETklavon aŭ la ENENklavon por aktivigi la ilbretbutonon.'
16 },
17
18 {
19 name: 'Redaktildialogo',
20 legend:
21 'En dialogo, premu la TABAN klavon por navigi al la sekva dialogelemento, premu la MAJUSKLIGAN+TABAN klavon por iri al la antaŭa dialogelemento, premu la ENEN klavon por sendi la dialogon, premu la ESKAPAN klavon por nuligi la dialogon. Kiam dialogo havas multajn langetojn, eblas atingi la langetliston aŭ per ALT+F10 aŭ per la TABA klavo kiel parton de la dialoga taba ordo. En langetlisto, moviĝu al la sekva kaj antaŭa langeto per la klavoj SAGO DEKSTREN KAJ MALDEKSTREN respektive.'
22 },
23
24 {
25 name: 'Kunteksta menuo de la redaktilo',
26 legend: 'Premu ${contextMenu} aŭ entajpu la KLAVKOMBINAĴON por malfermi la kuntekstan menuon. Poste moviĝu al la sekva opcio de la menuo per la klavoj TABA aŭ SAGO SUBEN. Moviĝu al la antaŭa opcio per la klavoj MAJUSKLGA + TABA aŭ SAGO SUPREN. Premu la SPACETklavon aŭ ENENklavon por selekti la menuopcion. Malfermu la submenuon de la kuranta opcio per la SPACETklavo aŭ la ENENklavo aŭ la SAGO DEKSTREN. Revenu al la elemento de la patra menuo per la klavoj ESKAPA aŭ SAGO MALDEKSTREN. Fermu la kuntekstan menuon per la ESKAPA klavo.'
27 },
28
29 {
30 name: 'Fallisto de la redaktilo',
31 legend: 'En fallisto, moviĝu al la sekva listelemento per la klavoj TABA aŭ SAGO SUBEN. Moviĝu al la antaŭa listelemento per la klavoj MAJUSKLIGA+TABA aŭ SAGO SUPREN. Premu la SPACETklavon aŭ ENENklavon por selekti la opcion en la listo. Premu la ESKAPAN klavon por fermi la falmenuon.'
32 },
33
34 {
35 name: 'Breto indikanta la vojon al la redaktilelementoj',
36 legend: 'Premu ${elementsPathFocus} por navigi al la breto indikanta la vojon al la redaktilelementoj. Moviĝu al la butono de la sekva elemento per la klavoj TABA aŭ SAGO DEKSTREN. Moviĝu al la butono de la antaŭa elemento per la klavoj MAJUSKLIGA+TABA aŭ SAGO MALDEKSTREN. Premu la SPACETklavon aŭ ENENklavon por selekti la elementon en la redaktilo.'
37 }
38 ]
39 },
40 {
41 name: 'Komandoj',
42 items: [
43 {
44 name: 'Komando malfari',
45 legend: 'Premu ${undo}'
46 },
47 {
48 name: 'Komando refari',
49 legend: 'Premu ${redo}'
50 },
51 {
52 name: 'Komando grasa',
53 legend: 'Premu ${bold}'
54 },
55 {
56 name: 'Komando kursiva',
57 legend: 'Premu ${italic}'
58 },
59 {
60 name: 'Komando substreki',
61 legend: 'Premu ${underline}'
62 },
63 {
64 name: 'Komando ligilo',
65 legend: 'Premu ${link}'
66 },
67 {
68 name: 'Komando faldi la ilbreton',
69 legend: 'Premu ${toolbarCollapse}'
70 },
71 {
72 name: 'Komando por atingi la antaŭan fokusan spacon',
73 legend: 'Press ${accessPreviousSpace} por atingi la plej proksiman neatingeblan fokusan spacon antaŭ la kursoro, ekzemple : du kuntuŝiĝajn HR elementojn. Ripetu la klavkombinaĵon por atingi malproksimajn fokusajn spacojn.'
74 },
75 {
76 name: 'Komando por atingi la sekvan fokusan spacon',
77 legend: 'Press ${accessNextSpace} por atingi la plej proksiman neatingeblan fokusan spacon post la kursoro, ekzemple : du kuntuŝiĝajn HR elementojn. Ripetu la klavkombinajôn por atingi malproksimajn fokusajn spacojn'
78 },
79 {
80 name: 'Helpilo pri atingeblo',
81 legend: 'Premu ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabo',
87 pause: 'Paŭzo',
88 capslock: 'Majuskla baskulo',
89 escape: 'Eskapa klavo',
90 pageUp: 'Antaŭa Paĝo',
91 pageDown: 'Sekva Paĝo',
92 leftArrow: 'Sago Maldekstren',
93 upArrow: 'Sago Supren',
94 rightArrow: 'Sago Dekstren',
95 downArrow: 'Sago Suben',
96 insert: 'Enmeti',
97 leftWindowKey: 'Maldekstra Windows-klavo',
98 rightWindowKey: 'Dekstra Windows-klavo',
99 selectKey: 'Selektklavo',
100 numpad0: 'Nombra Klavaro 0',
101 numpad1: 'Nombra Klavaro 1',
102 numpad2: 'Nombra Klavaro 2',
103 numpad3: 'Nombra Klavaro 3',
104 numpad4: 'Nombra Klavaro 4',
105 numpad5: 'Nombra Klavaro 5',
106 numpad6: 'Nombra Klavaro 6',
107 numpad7: 'Nombra Klavaro 7',
108 numpad8: 'Nombra Klavaro 8',
109 numpad9: 'Nombra Klavaro 9',
110 multiply: 'Obligi',
111 add: 'Almeti',
112 subtract: 'Subtrahi',
113 decimalPoint: 'Dekuma Punkto',
114 divide: 'Dividi',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Nombra Baskulo',
128 scrollLock: 'Ruluma Baskulo',
129 semiColon: 'Punktokomo',
130 equalSign: 'Egalsigno',
131 comma: 'Komo',
132 dash: 'Haltostreko',
133 period: 'Punkto',
134 forwardSlash: 'Oblikvo',
135 graveAccent: 'Malakuto',
136 openBracket: 'Malferma Krampo',
137 backSlash: 'Retroklino',
138 closeBracket: 'Ferma Krampo',
139 singleQuote: 'Citilo'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/es.js b/sources/plugins/a11yhelp/dialogs/lang/es.js
new file mode 100644
index 0000000..b1eaa20
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/es.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'es', {
7 title: 'Instrucciones de accesibilidad',
8 contents: 'Ayuda. Para cerrar presione ESC.',
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Barra de herramientas del editor',
15 legend: 'Presiona ${toolbarFocus} para navegar por la barra de herramientas. Para moverse por los distintos grupos de herramientas usa las teclas TAB y MAY+TAB. Para moverse por las distintas herramientas usa FLECHA DERECHA o FECHA IZQUIERDA. Presiona "espacio" o "intro" para activar la herramienta.'
16 },
17
18 {
19 name: 'Editor de diálogo',
20 legend:
21 'Dentro del diálogo, presione TAB para navegar a los siguientes elementos de diálogo, presione SHIFT+TAB para moverse a los anteriores elementos de diálogo, presione ENTER para enviar el diálogo, presiona ESC para cancelar el diálogo. Cuando el diálogo tiene multiples pestañas, la lista de pestañas puede ser abarcada con ALT + F10 or con TAB como parte del orden de pestañas del diálogo. ECon la pestaña enfocada, puede moverse a la siguiente o anterior pestaña con las FLECHAS IZQUIRDA y DERECHA respectivamente.'
22 },
23
24 {
25 name: 'Editor del menú contextual',
26 legend: 'Presiona ${contextMenu} o TECLA MENÚ para abrir el menú contextual. Entonces muévete a la siguiente opción del menú con TAB o FLECHA ABAJO. Muévete a la opción previa con SHIFT + TAB o FLECHA ARRIBA. Presiona ESPACIO o ENTER para seleccionar la opción del menú. Abre el submenú de la opción actual con ESPACIO o ENTER o FLECHA DERECHA. Regresa al elemento padre del menú con ESC o FLECHA IZQUIERDA. Cierra el menú contextual con ESC.'
27 },
28
29 {
30 name: 'Lista del Editor',
31 legend: 'Dentro de una lista, te mueves al siguiente elemento de la lista con TAB o FLECHA ABAJO. Te mueves al elemento previo de la lista con SHIFT+TAB o FLECHA ARRIBA. Presiona ESPACIO o ENTER para elegir la opción de la lista. Presiona ESC para cerrar la lista.'
32 },
33
34 {
35 name: 'Barra de Ruta del Elemento en el Editor',
36 legend: 'Presiona ${elementsPathFocus} para navegar a los elementos de la barra de ruta. Te mueves al siguiente elemento botón con TAB o FLECHA DERECHA. Te mueves al botón previo con SHIFT+TAB o FLECHA IZQUIERDA. Presiona ESPACIO o ENTER para seleccionar el elemento en el editor.'
37 }
38 ]
39 },
40 {
41 name: 'Comandos',
42 items: [
43 {
44 name: 'Comando deshacer',
45 legend: 'Presiona ${undo}'
46 },
47 {
48 name: 'Comando rehacer',
49 legend: 'Presiona ${redo}'
50 },
51 {
52 name: 'Comando negrita',
53 legend: 'Presiona ${bold}'
54 },
55 {
56 name: 'Comando itálica',
57 legend: 'Presiona ${italic}'
58 },
59 {
60 name: 'Comando subrayar',
61 legend: 'Presiona ${underline}'
62 },
63 {
64 name: 'Comando liga',
65 legend: 'Presiona ${liga}'
66 },
67 {
68 name: 'Comando colapsar barra de herramientas',
69 legend: 'Presiona ${toolbarCollapse}'
70 },
71 {
72 name: 'Comando accesar el anterior espacio de foco',
73 legend: 'Presiona ${accessPreviousSpace} para accesar el espacio de foco no disponible más cercano anterior al cursor, por ejemplo: dos elementos HR adyacentes. Repite la combinación de teclas para alcanzar espacios de foco distantes.'
74 },
75 {
76 name: 'Comando accesar el siguiente spacio de foco',
77 legend: 'Presiona ${accessNextSpace} para accesar el espacio de foco no disponible más cercano después del cursor, por ejemplo: dos elementos HR adyacentes. Repite la combinación de teclas para alcanzar espacios de foco distantes.'
78 },
79 {
80 name: 'Ayuda de Accesibilidad',
81 legend: 'Presiona ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulador',
87 pause: 'Pausa',
88 capslock: 'Bloq. Mayús.',
89 escape: 'Escape',
90 pageUp: 'Regresar Página',
91 pageDown: 'Avanzar Página',
92 leftArrow: 'Flecha Izquierda',
93 upArrow: 'Flecha Arriba',
94 rightArrow: 'Flecha Derecha',
95 downArrow: 'Flecha Abajo',
96 insert: 'Insertar',
97 leftWindowKey: 'Tecla Windows Izquierda',
98 rightWindowKey: 'Tecla Windows Derecha',
99 selectKey: 'Tecla de Selección',
100 numpad0: 'Tecla 0 del teclado numérico',
101 numpad1: 'Tecla 1 del teclado numérico',
102 numpad2: 'Tecla 2 del teclado numérico',
103 numpad3: 'Tecla 3 del teclado numérico',
104 numpad4: 'Tecla 4 del teclado numérico',
105 numpad5: 'Tecla 5 del teclado numérico',
106 numpad6: 'Tecla 6 del teclado numérico',
107 numpad7: 'Tecla 7 del teclado numérico',
108 numpad8: 'Tecla 8 del teclado numérico',
109 numpad9: 'Tecla 9 del teclado numérico',
110 multiply: 'Multiplicar',
111 add: 'Sumar',
112 subtract: 'Restar',
113 decimalPoint: 'Punto Decimal',
114 divide: 'Dividir',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Punto y coma',
130 equalSign: 'Signo de Igual',
131 comma: 'Coma',
132 dash: 'Guión',
133 period: 'Punto',
134 forwardSlash: 'Diagonal',
135 graveAccent: 'Acento Grave',
136 openBracket: 'Abrir llave',
137 backSlash: 'Diagonal Invertida',
138 closeBracket: 'Cerrar llave',
139 singleQuote: 'Comillas simples'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/et.js b/sources/plugins/a11yhelp/dialogs/lang/et.js
new file mode 100644
index 0000000..0146089
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/et.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'et', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Abi sisu. Selle dialoogi sulgemiseks vajuta ESC klahvi.',
9 legend: [
10 {
11 name: 'Üldine',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/eu.js b/sources/plugins/a11yhelp/dialogs/lang/eu.js
new file mode 100644
index 0000000..b53748f
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/eu.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'eu', {
7 title: 'Erabilerraztasunaren argibideak',
8 contents: 'Laguntzaren edukiak. Elkarrizketa-koadro hau ixteko sakatu ESC.',
9 legend: [
10 {
11 name: 'Orokorra',
12 items: [
13 {
14 name: 'Editorearen tresna-barra',
15 legend: 'Sakatu ${toolbarFocus} tresna-barrara nabigatzeko. Tresna-barrako aurreko eta hurrengo taldera joateko erabili TAB eta MAIUS+TAB. Tresna-barrako aurreko eta hurrengo botoira joateko erabili ESKUIN-GEZIA eta EZKER-GEZIA. Sakatu ZURIUNEA edo SARTU tresna-barrako botoia aktibatzeko.'
16 },
17
18 {
19 name: 'Editorearen elkarrizketa-koadroa',
20 legend:
21 'Elkarrizketa-koadro baten barruan sakatu TAB hurrengo elementura nabigatzeko, sakatu MAIUS+TAB aurreko elementura joateko, sakatu SARTU elkarrizketa-koadroa bidaltzeko eta sakatu ESC uzteko. Elkarrizketa-koadro batek hainbat fitxa dituenean, ALT+F10 erabiliz irits daiteke fitxen zerrendara, edo TAB erabiliz. Fokoa fitxen zerrendak duenean, aurreko eta hurrengo fitxetara joateko erabili EZKER-GEZIA eta ESKUIN-GEZIA.'
22 },
23
24 {
25 name: 'Editorearen testuinguru-menua',
26 legend: 'Sakatu ${contextMenu} edo APLIKAZIO TEKLA testuinguru-menua irekitzeko. Menuko hurrengo aukerara joateko erabili TAB edo BEHERA GEZIA. Aurreko aukerara nabigatzeko erabili MAIUS+TAB edo GORA GEZIA. Sakatu ZURIUNEA edo SARTU menuko aukera hautatzeko. Ireki uneko aukeraren azpi-menua ZURIUNEA edo SARTU edo ESKUIN-GEZIA erabiliz. Menuko aukera gurasora itzultzeko erabili ESC edo EZKER-GEZIA. Testuinguru-menua ixteko sakatu ESC.'
27 },
28
29 {
30 name: 'Editorearen zerrenda-koadroa',
31 legend: 'Zerrenda-koadro baten barruan, zerrendako hurrengo elementura joateko erabili TAB edo BEHERA GEZIA. Zerrendako aurreko elementura nabigatzeko MAIUS+TAB edo GORA GEZIA. Sakatu ZURIUNEA edo SARTU zerrendako aukera hautatzeko. Sakatu ESC zerrenda-koadroa ixteko.'
32 },
33
34 {
35 name: 'Editorearen elementuaren bide-barra',
36 legend: 'Sakatu ${elementsPathFocus} elementuaren bide-barrara nabigatzeko. Hurrengo elementuaren botoira joateko erabili TAB edo ESKUIN-GEZIA. Aurreko botoira joateko aldiz erabili MAIUS+TAB edo EZKER-GEZIA. Elementua editorean hautatzeko sakatu ZURIUNEA edo SARTU.'
37 }
38 ]
39 },
40 {
41 name: 'Komandoak',
42 items: [
43 {
44 name: 'Desegin komandoa',
45 legend: 'Sakatu ${undo}'
46 },
47 {
48 name: 'Berregin komandoa',
49 legend: 'Sakatu ${redo}'
50 },
51 {
52 name: 'Lodia komandoa',
53 legend: 'Sakatu ${bold}'
54 },
55 {
56 name: 'Etzana komandoa',
57 legend: 'Sakatu ${italic}'
58 },
59 {
60 name: 'Azpimarratu komandoa',
61 legend: 'Sakatu ${underline}'
62 },
63 {
64 name: 'Esteka komandoa',
65 legend: 'Sakatu ${link}'
66 },
67 {
68 name: 'Tolestu tresna-barra komandoa',
69 legend: 'Sakatu ${toolbarCollapse}'
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: 'Erabilerraztasunaren laguntza',
81 legend: 'Sakatu ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabuladorea',
87 pause: 'Pausatu',
88 capslock: 'Blok Maius',
89 escape: 'Ihes',
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Ezker-gezia',
93 upArrow: 'Gora gezia',
94 rightArrow: 'Eskuin-gezia',
95 downArrow: 'Behera gezia',
96 insert: 'Txertatu',
97 leftWindowKey: 'Ezkerreko Windows tekla',
98 rightWindowKey: 'Eskuineko Windows tekla',
99 selectKey: 'Hautatu tekla',
100 numpad0: 'Zenbakizko teklatua 0',
101 numpad1: 'Zenbakizko teklatua 1',
102 numpad2: 'Zenbakizko teklatua 2',
103 numpad3: 'Zenbakizko teklatua 3',
104 numpad4: 'Zenbakizko teklatua 4',
105 numpad5: 'Zenbakizko teklatua 5',
106 numpad6: 'Zenbakizko teklatua 6',
107 numpad7: 'Zenbakizko teklatua 7',
108 numpad8: 'Zenbakizko teklatua 8',
109 numpad9: 'Zenbakizko teklatua 9',
110 multiply: 'Biderkatu',
111 add: 'Gehitu',
112 subtract: 'Kendu',
113 decimalPoint: 'Koma hamartarra',
114 divide: 'Zatitu',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Blok Zenb',
128 scrollLock: 'Blok Korr',
129 semiColon: 'Puntu eta koma',
130 equalSign: 'Berdin zeinua',
131 comma: 'Koma',
132 dash: 'Marratxoa',
133 period: 'Puntua',
134 forwardSlash: 'Barra',
135 graveAccent: 'Azentu kamutsa',
136 openBracket: 'Parentesia ireki',
137 backSlash: 'Alderantzizko barra',
138 closeBracket: 'Itxi parentesia',
139 singleQuote: 'Komatxo bakuna'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fa.js b/sources/plugins/a11yhelp/dialogs/lang/fa.js
new file mode 100644
index 0000000..88072f0
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/fa.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'fa', {
7 title: 'دستورالعمل‌های دسترسی',
8 contents: 'راهنمای فهرست مطالب. برای بستن این کادر محاوره‌ای ESC را فشار دهید.',
9 legend: [
10 {
11 name: 'عمومی',
12 items: [
13 {
14 name: 'نوار ابزار ویرایشگر',
15 legend: '${toolbarFocus} را برای باز کردن نوار ابزار بفشارید. با کلید Tab و Shift+Tab در مجموعه نوار ابزار بعدی و قبلی حرکت کنید. برای حرکت در کلید نوار ابزار قبلی و بعدی با کلید جهت‌نمای راست و چپ جابجا شوید. کلید Space یا Enter را برای فعال کردن کلید نوار ابزار بفشارید.'
16 },
17
18 {
19 name: 'پنجره محاورهای ویرایشگر',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'منوی متنی ویرایشگر',
26 legend: '${contextMenu} یا کلید برنامههای کاربردی را برای باز کردن منوی متن را بفشارید. سپس میتوانید برای حرکت به گزینه بعدی منو با کلید Tab و یا کلید جهتنمای پایین جابجا شوید. حرکت به گزینه قبلی با Shift+Tab یا کلید جهتنمای بالا. فشردن Space یا Enter برای انتخاب یک گزینه از منو. باز کردن زیر شاخه گزینه منو جاری با کلید Space یا Enter و یا کلید جهتنمای راست و چپ. بازگشت به منوی والد با کلید Esc یا کلید جهتنمای چپ. بستن منوی متن با Esc.'
27 },
28
29 {
30 name: 'جعبه فهرست ویرایشگر',
31 legend: 'در داخل جعبه لیست، قلم دوم از اقلام لیست بعدی را با TAB و یا Arrow Down حرکت دهید. انتقال به قلم دوم از اقلام لیست قبلی را با SHIFT + TAB یا UP ARROW. کلید Space یا ENTER را برای انتخاب گزینه لیست بفشارید. کلید ESC را برای بستن جعبه لیست بفشارید.'
32 },
33
34 {
35 name: 'ویرایشگر عنصر نوار راه',
36 legend: 'برای رفتن به مسیر عناصر ${elementsPathFocus} را بفشارید. حرکت به کلید عنصر بعدی با کلید Tab یا کلید جهت‌نمای راست. برگشت به کلید قبلی با Shift+Tab یا کلید جهت‌نمای چپ. فشردن Space یا Enter برای انتخاب یک عنصر در ویرایشگر.'
37 }
38 ]
39 },
40 {
41 name: 'فرمان‌ها',
42 items: [
43 {
44 name: 'بازگشت به آخرین فرمان',
45 legend: 'فشردن ${undo}'
46 },
47 {
48 name: 'انجام مجدد فرمان',
49 legend: 'فشردن ${redo}'
50 },
51 {
52 name: 'فرمان درشت کردن متن',
53 legend: 'فشردن ${bold}'
54 },
55 {
56 name: 'فرمان کج کردن متن',
57 legend: 'فشردن ${italic}'
58 },
59 {
60 name: 'فرمان زیرخطدار کردن متن',
61 legend: 'فشردن ${underline}'
62 },
63 {
64 name: 'فرمان پیوند دادن',
65 legend: 'فشردن ${link}'
66 },
67 {
68 name: 'بستن نوار ابزار فرمان',
69 legend: 'فشردن ${toolbarCollapse}'
70 },
71 {
72 name: 'دسترسی به فرمان محل تمرکز قبلی',
73 legend: 'فشردن ${accessPreviousSpace} برای دسترسی به نزدیک‌ترین فضای قابل دسترسی تمرکز قبل از هشتک، برای مثال: دو عنصر مجاور HR -خط افقی-. تکرار کلید ترکیبی برای رسیدن به فضاهای تمرکز از راه دور.'
74 },
75 {
76 name: 'دسترسی به فضای دستور بعدی',
77 legend: 'برای دسترسی به نزدیک‌ترین فضای تمرکز غیر قابل دسترس، ${accessNextSpace} را پس از علامت هشتک بفشارید، برای مثال: دو عنصر مجاور HR -خط افقی-. کلید ترکیبی را برای رسیدن به فضای تمرکز تکرار کنید.'
78 },
79 {
80 name: 'راهنمای دسترسی',
81 legend: 'فشردن ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'برگه',
87 pause: 'توقف',
88 capslock: 'Caps Lock',
89 escape: 'گریز',
90 pageUp: 'صفحه به بالا',
91 pageDown: 'صفحه به پایین',
92 leftArrow: 'پیکان چپ',
93 upArrow: 'پیکان بالا',
94 rightArrow: 'پیکان راست',
95 downArrow: 'پیکان پایین',
96 insert: 'ورود',
97 leftWindowKey: 'کلید چپ ویندوز',
98 rightWindowKey: 'کلید راست ویندوز',
99 selectKey: 'انتخاب کلید',
100 numpad0: 'کلید شماره 0',
101 numpad1: 'کلید شماره 1',
102 numpad2: 'کلید شماره 2',
103 numpad3: 'کلید شماره 3',
104 numpad4: 'کلید شماره 4',
105 numpad5: 'کلید شماره 5',
106 numpad6: 'کلید شماره 6',
107 numpad7: 'کلید شماره 7',
108 numpad8: 'کلید شماره 8',
109 numpad9: 'کلید شماره 9',
110 multiply: 'ضرب',
111 add: 'افزودن',
112 subtract: 'تفریق',
113 decimalPoint: 'نقطه‌ی اعشار',
114 divide: 'جدا کردن',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semicolon',
130 equalSign: 'علامت تساوی',
131 comma: 'کاما',
132 dash: 'خط تیره',
133 period: 'دوره',
134 forwardSlash: 'Forward Slash',
135 graveAccent: 'Grave Accent',
136 openBracket: 'Open Bracket',
137 backSlash: 'Backslash',
138 closeBracket: 'Close Bracket',
139 singleQuote: 'Single Quote'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fi.js b/sources/plugins/a11yhelp/dialogs/lang/fi.js
new file mode 100644
index 0000000..093d409
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/fi.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'fi', {
7 title: 'Saavutettavuus ohjeet',
8 contents: 'Ohjeen sisällöt. Sulkeaksesi tämän dialogin paina ESC.',
9 legend: [
10 {
11 name: 'Yleinen',
12 items: [
13 {
14 name: 'Editorin työkalupalkki',
15 legend: 'Paina ${toolbarFocus} siirtyäksesi työkalupalkkiin. Siirry seuraavaan ja edelliseen työkalupalkin ryhmään TAB ja SHIFT+TAB näppäimillä. Siirry seuraavaan ja edelliseen työkalupainikkeeseen käyttämällä NUOLI OIKEALLE tai NUOLI VASEMMALLE näppäimillä. Paina VÄLILYÖNTI tai ENTER näppäintä aktivoidaksesi työkalupainikkeen.'
16 },
17
18 {
19 name: 'Editorin dialogi',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editorin oheisvalikko',
26 legend: 'Paina ${contextMenu} tai SOVELLUSPAINIKETTA avataksesi oheisvalikon. Liiku seuraavaan valikon vaihtoehtoon TAB tai NUOLI ALAS näppäimillä. Siirry edelliseen vaihtoehtoon SHIFT+TAB tai NUOLI YLÖS näppäimillä. Paina VÄLILYÖNTI tai ENTER valitaksesi valikon kohdan. Avataksesi nykyisen kohdan alivalikon paina VÄLILYÖNTI tai ENTER tai NUOLI OIKEALLE painiketta. Siirtyäksesi takaisin valikon ylemmälle tasolle paina ESC tai NUOLI vasemmalle. Oheisvalikko suljetaan ESC painikkeella.'
27 },
28
29 {
30 name: 'Editorin listalaatikko',
31 legend: 'Listalaatikon sisällä siirry seuraavaan listan kohtaan TAB tai NUOLI ALAS painikkeilla. Siirry edelliseen listan kohtaan SHIFT+TAB tai NUOLI YLÖS painikkeilla. Paina VÄLILYÖNTI tai ENTER valitaksesi listan vaihtoehdon. Paina ESC sulkeaksesi listalaatikon.'
32 },
33
34 {
35 name: 'Editorin elementtipolun palkki',
36 legend: 'Paina ${elementsPathFocus} siirtyäksesi elementtipolun palkkiin. Siirry seuraavaan elementtipainikkeeseen TAB tai NUOLI OIKEALLE painikkeilla. Siirry aiempaan painikkeeseen SHIFT+TAB tai NUOLI VASEMMALLE painikkeilla. Paina VÄLILYÖNTI tai ENTER valitaksesi elementin editorissa.'
37 }
38 ]
39 },
40 {
41 name: 'Komennot',
42 items: [
43 {
44 name: 'Peruuta komento',
45 legend: 'Paina ${undo}'
46 },
47 {
48 name: 'Tee uudelleen komento',
49 legend: 'Paina ${redo}'
50 },
51 {
52 name: 'Lihavoi komento',
53 legend: 'Paina ${bold}'
54 },
55 {
56 name: 'Kursivoi komento',
57 legend: 'Paina ${italic}'
58 },
59 {
60 name: 'Alleviivaa komento',
61 legend: 'Paina ${underline}'
62 },
63 {
64 name: 'Linkki komento',
65 legend: 'Paina ${link}'
66 },
67 {
68 name: 'Pienennä työkalupalkki komento',
69 legend: 'Paina ${toolbarCollapse}'
70 },
71 {
72 name: 'Siirry aiempaan fokustilaan komento',
73 legend: 'Paina ${accessPreviousSpace} siiryäksesi lähimpään kursorin edellä olevaan saavuttamattomaan fokustilaan, esimerkiksi: kaksi vierekkäistä HR elementtiä. Toista näppäinyhdistelmää päästäksesi kauempana oleviin fokustiloihin.'
74 },
75 {
76 name: 'Siirry seuraavaan fokustilaan komento',
77 legend: 'Paina ${accessPreviousSpace} siiryäksesi lähimpään kursorin jälkeen olevaan saavuttamattomaan fokustilaan, esimerkiksi: kaksi vierekkäistä HR elementtiä. Toista näppäinyhdistelmää päästäksesi kauempana oleviin fokustiloihin.'
78 },
79 {
80 name: 'Saavutettavuus ohjeet',
81 legend: 'Paina ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numeronäppäimistö 0',
101 numpad1: 'Numeronäppäimistö 1',
102 numpad2: 'Numeronäppäimistö 2',
103 numpad3: 'Numeronäppäimistö 3',
104 numpad4: 'Numeronäppäimistö 4',
105 numpad5: 'Numeronäppäimistö 5',
106 numpad6: 'Numeronäppäimistö 6',
107 numpad7: 'Numeronäppäimistö 7',
108 numpad8: 'Numeronäppäimistö 8',
109 numpad9: 'Numeronäppäimistö 9',
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Puolipiste',
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Pilkku',
132 dash: 'Dash', // MISSING
133 period: 'Piste',
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fo.js b/sources/plugins/a11yhelp/dialogs/lang/fo.js
new file mode 100644
index 0000000..efce724
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/fo.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'fo', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'General', // MISSING
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Falda',
111 add: 'Pluss',
112 subtract: 'Frádráttar',
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Býta',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semikolon',
130 equalSign: 'Javnatekn',
131 comma: 'Komma',
132 dash: 'Dash', // MISSING
133 period: 'Punktum',
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js b/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js
new file mode 100644
index 0000000..c87c586
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'fr-ca', {
7 title: 'Instructions d\'accessibilité',
8 contents: 'Contenu de l\'aide. Pour fermer cette fenêtre, appuyez sur ESC.',
9 legend: [
10 {
11 name: 'Général',
12 items: [
13 {
14 name: 'Barre d\'outil de l\'éditeur',
15 legend: 'Appuyer sur ${toolbarFocus} pour accéder à la barre d\'outils. Se déplacer vers les groupes suivant ou précédent de la barre d\'outil avec les touches TAB et SHIFT+TAB. Se déplacer vers les boutons suivant ou précédent de la barre d\'outils avec les touches FLECHE DROITE et FLECHE GAUCHE. Appuyer sur la barre d\'espace ou la touche ENTRER pour activer le bouton de barre d\'outils.'
16 },
17
18 {
19 name: 'Dialogue de l\'éditeur',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Menu contextuel de l\'éditeur',
26 legend: 'Appuyer sur ${contextMenu} ou entrer le RACCOURCI CLAVIER pour ouvrir le menu contextuel. Puis se déplacer vers l\'option suivante du menu avec les touches TAB ou FLECHE BAS. Se déplacer vers l\'option précédente avec les touches SHIFT+TAB ou FLECHE HAUT. appuyer sur la BARRE D\'ESPACE ou la touche ENTREE pour sélectionner l\'option du menu. Oovrir le sous-menu de l\'option courante avec la BARRE D\'ESPACE ou les touches ENTREE ou FLECHE DROITE. Revenir à l\'élément de menu parent avec les touches ESC ou FLECHE GAUCHE. Fermer le menu contextuel avec ESC.'
27 },
28
29 {
30 name: 'Menu déroulant de l\'éditeur',
31 legend: 'A l\'intérieur d\'une liste en menu déroulant, se déplacer vers l\'élément suivant de la liste avec les touches TAB ou FLECHE BAS. Se déplacer vers l\'élément précédent de la liste avec les touches SHIFT+TAB ou FLECHE HAUT. Appuyer sur la BARRE D\'ESPACE ou sur ENTREE pour sélectionner l\'option dans la liste. Appuyer sur ESC pour fermer le menu déroulant.'
32 },
33
34 {
35 name: 'Barre d\'emplacement des éléments de l\'éditeur',
36 legend: 'Appuyer sur ${elementsPathFocus} pour naviguer vers la barre d\'emplacement des éléments de léditeur. Se déplacer vers le bouton d\'élément suivant avec les touches TAB ou FLECHE DROITE. Se déplacer vers le bouton d\'élément précédent avec les touches SHIFT+TAB ou FLECHE GAUCHE. Appuyer sur la BARRE D\'ESPACE ou sur ENTREE pour sélectionner l\'élément dans l\'éditeur.'
37 }
38 ]
39 },
40 {
41 name: 'Commandes',
42 items: [
43 {
44 name: 'Annuler',
45 legend: 'Appuyer sur ${undo}'
46 },
47 {
48 name: 'Refaire',
49 legend: 'Appuyer sur ${redo}'
50 },
51 {
52 name: 'Gras',
53 legend: 'Appuyer sur ${bold}'
54 },
55 {
56 name: 'Italique',
57 legend: 'Appuyer sur ${italic}'
58 },
59 {
60 name: 'Souligné',
61 legend: 'Appuyer sur ${underline}'
62 },
63 {
64 name: 'Lien',
65 legend: 'Appuyer sur ${link}'
66 },
67 {
68 name: 'Enrouler la barre d\'outils',
69 legend: 'Appuyer sur ${toolbarCollapse}'
70 },
71 {
72 name: 'Accéder à l\'objet de focus précédent',
73 legend: 'Appuyer ${accessPreviousSpace} pour accéder au prochain espace disponible avant le curseur, par exemple: deux éléments HR adjacents. Répéter la combinaison pour joindre les éléments d\'espaces distantes.'
74 },
75 {
76 name: 'Accéder au prochain objet de focus',
77 legend: 'Appuyer ${accessNextSpace} pour accéder au prochain espace disponible après le curseur, par exemple: deux éléments HR adjacents. Répéter la combinaison pour joindre les éléments d\'espaces distantes.'
78 },
79 {
80 name: 'Aide d\'accessibilité',
81 legend: 'Appuyer sur ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fr.js b/sources/plugins/a11yhelp/dialogs/lang/fr.js
new file mode 100644
index 0000000..9727639
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/fr.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'fr', {
7 title: 'Instructions d\'accessibilité',
8 contents: 'Contenu de l\'aide. Pour fermer cette fenêtre, appuyez sur la touche Échap.',
9 legend: [
10 {
11 name: 'Général',
12 items: [
13 {
14 name: 'Barre d\'outils de l\'éditeur',
15 legend: 'Appuyer sur ${toolbarFocus} pour accéder à la barre d\'outils. Se déplacer vers le groupe suivant ou précédent de la barre d\'outils avec les touches Tab et Maj+Tab. Se déplacer vers le bouton suivant ou précédent de la barre d\'outils avec les touches Flèche droite et Flèche gauche. Appuyer sur la barre d\'espace ou la touche Entrée pour activer le bouton de barre d\'outils.'
16 },
17
18 {
19 name: 'Fenêtre de l\'éditeur',
20 legend:
21 'Dans une boîte de dialogue, appuyer sur Tab pour passer à l\'élément suivant, appuyer sur Maj+Tab pour passer à l\'élément précédent, appuyer sur Entrée pour valider, appuyer sur Échap pour annuler. Quand une boîte de dialogue possède des onglets, la liste peut être atteinte avec Alt+F10 ou avec Tab. Dans la liste des onglets, se déplacer vers le suivant et le précédent avec les touches Flèche droite et Flèche gauche respectivement.'
22 },
23
24 {
25 name: 'Menu contextuel de l\'éditeur',
26 legend: 'Appuyer sur ${contextMenu} ou sur la touche Menu pour ouvrir le menu contextuel. Se déplacer ensuite vers l\'option suivante du menu avec les touches Tab ou Flèche bas. Se déplacer vers l\'option précédente avec les touches Maj+Tab ou Flèche haut. Appuyer sur la barre d\'espace ou la touche Entrée pour sélectionner l\'option du menu. Appuyer sur la barre d\'espace, la touche Entrée ou Flèche droite pour ouvrir le sous-menu de l\'option sélectionnée. Revenir à l\'élément de menu parent avec la touche Échap ou Flèche gauche. Fermer le menu contextuel avec Échap.'
27 },
28
29 {
30 name: 'Zone de liste de l\'éditeur',
31 legend: 'Dans une liste en menu déroulant, se déplacer vers l\'élément suivant de la liste avec les touches Tab ou Flèche bas. Se déplacer vers l\'élément précédent de la liste avec les touches Maj+Tab ou Flèche haut. Appuyer sur la barre d\'espace ou sur Entrée pour sélectionner l\'option dans la liste. Appuyer sur Échap pour fermer le menu déroulant.'
32 },
33
34 {
35 name: 'Barre du chemin d\'éléments de l\'éditeur',
36 legend: 'Appuyer sur ${elementsPathFocus} pour naviguer vers la barre du fil d\'Ariane des éléments. Se déplacer vers le bouton de l\'élément suivant avec les touches Tab ou Flèche droite. Se déplacer vers le bouton précédent avec les touches Maj+Tab ou Flèche gauche. Appuyer sur la barre d\'espace ou sur Entrée pour sélectionner l\'élément dans l\'éditeur.'
37 }
38 ]
39 },
40 {
41 name: 'Commandes',
42 items: [
43 {
44 name: ' Annuler la commande',
45 legend: 'Appuyer sur ${undo}'
46 },
47 {
48 name: 'Commande restaurer',
49 legend: 'Appuyer sur ${redo}'
50 },
51 {
52 name: ' Commande gras',
53 legend: 'Appuyer sur ${bold}'
54 },
55 {
56 name: ' Commande italique',
57 legend: 'Appuyer sur ${italic}'
58 },
59 {
60 name: ' Commande souligné',
61 legend: 'Appuyer sur ${underline}'
62 },
63 {
64 name: ' Commande lien',
65 legend: 'Appuyer sur ${link}'
66 },
67 {
68 name: ' Commande enrouler la barre d\'outils',
69 legend: 'Appuyer sur ${toolbarCollapse}'
70 },
71 {
72 name: 'Commande d\'accès à l\'élément sélectionnable précédent',
73 legend: 'Appuyer sur ${accessNextSpace} pour accéder à l\'élément sélectionnable inatteignable le plus proche avant le curseur, par exemple : deux lignes horizontales adjacentes. Répéter la combinaison de touches pour atteindre les éléments sélectionnables précédents.'
74 },
75 {
76 name: 'Commande d\'accès à l\'élément sélectionnable suivant',
77 legend: 'Appuyer sur ${accessNextSpace} pour accéder à l\'élément sélectionnable inatteignable le plus proche après le curseur, par exemple : deux lignes horizontales adjacentes. Répéter la combinaison de touches pour atteindre les éléments sélectionnables suivants.'
78 },
79 {
80 name: ' Aide sur l\'accessibilité',
81 legend: 'Appuyer sur ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulation',
87 pause: 'Pause',
88 capslock: 'Verr. Maj.',
89 escape: 'Échap',
90 pageUp: 'Page supérieure',
91 pageDown: 'Page suivante',
92 leftArrow: 'Flèche gauche',
93 upArrow: 'Flèche haut',
94 rightArrow: 'Flèche droite',
95 downArrow: 'Flèche basse',
96 insert: 'Inser',
97 leftWindowKey: 'Touche Windows gauche',
98 rightWindowKey: 'Touche Windows droite',
99 selectKey: 'Touche Sélectionner',
100 numpad0: '0 du pavé numérique',
101 numpad1: '1 du pavé numérique',
102 numpad2: '2 du pavé numérique',
103 numpad3: '3 du pavé numérique',
104 numpad4: '4 du pavé numérique',
105 numpad5: '5 du pavé numérique',
106 numpad6: '6 du pavé numérique',
107 numpad7: '7 du pavé numérique',
108 numpad8: 'Pavé numérique 8',
109 numpad9: '9 du pavé numérique',
110 multiply: 'Multiplier',
111 add: 'Plus',
112 subtract: 'Moins',
113 decimalPoint: 'Point décimal',
114 divide: 'Diviser',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Verr. Num.',
128 scrollLock: 'Arrêt défil.',
129 semiColon: 'Point-virgule',
130 equalSign: 'Signe égal',
131 comma: 'Virgule',
132 dash: 'Tiret',
133 period: 'Point',
134 forwardSlash: 'Barre oblique',
135 graveAccent: 'Accent grave',
136 openBracket: 'Parenthèse ouvrante',
137 backSlash: 'Barre oblique inverse',
138 closeBracket: 'Parenthèse fermante',
139 singleQuote: 'Apostrophe'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/gl.js b/sources/plugins/a11yhelp/dialogs/lang/gl.js
new file mode 100644
index 0000000..4978330
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/gl.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'gl', {
7 title: 'Instrucións de accesibilidade',
8 contents: 'Axuda. Para pechar este diálogo prema ESC.',
9 legend: [
10 {
11 name: 'Xeral',
12 items: [
13 {
14 name: 'Barra de ferramentas do editor',
15 legend: 'Prema ${toolbarFocus} para navegar pola barra de ferramentas. Para moverse polos distintos grupos de ferramentas use as teclas TAB e MAIÚS+TAB. Para moverse polas distintas ferramentas use FRECHA DEREITA ou FRECHA ESQUERDA. Prema ESPAZO ou INTRO para activar o botón da barra de ferramentas.'
16 },
17
18 {
19 name: 'Editor de diálogo',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor do menú contextual',
26 legend: 'Prema ${contextMenu} ou a TECLA MENÚ para abrir o menú contextual. A seguir móvase á seguinte opción do menú con TAB ou FRECHA ABAIXO. Móvase á opción anterior con MAIÚS + TAB ou FRECHA ARRIBA. Prema ESPAZO ou INTRO para seleccionar a opción do menú. Abra o submenú da opción actual con ESPAZO ou INTRO ou FRECHA DEREITA. Regrese ao elemento principal do menú con ESC ou FRECHA ESQUERDA. Peche o menú contextual con ESC.'
27 },
28
29 {
30 name: 'Lista do editor',
31 legend: 'Dentro dunha lista, móvase ao seguinte elemento da lista con TAB ou FRECHA ABAIXO. Móvase ao elemento anterior da lista con MAIÚS+TAB ou FRECHA ARRIBA. Prema ESPAZO ou INTRO para escoller a opción da lista. Prema ESC para pechar a lista.'
32 },
33
34 {
35 name: 'Barra da ruta ao elemento no editor',
36 legend: 'Prema ${elementsPathFocus} para navegar ata os elementos da barra de ruta. Móvase ao seguinte elemento botón con TAB ou FRECHA DEREITA. Móvase ao botón anterior con MAIÚS+TAB ou FRECHA ESQUERDA. Prema ESPAZO ou INTRO para seleccionar o elemento no editor.'
37 }
38 ]
39 },
40 {
41 name: 'Ordes',
42 items: [
43 {
44 name: 'Orde «desfacer»',
45 legend: 'Prema ${undo}'
46 },
47 {
48 name: 'Orde «refacer»',
49 legend: 'Prema ${redo}'
50 },
51 {
52 name: 'Orde «negra»',
53 legend: 'Prema ${bold}'
54 },
55 {
56 name: 'Orde «cursiva»',
57 legend: 'Prema ${italic}'
58 },
59 {
60 name: 'Orde «subliñar»',
61 legend: 'Prema ${underline}'
62 },
63 {
64 name: 'Orde «ligazón»',
65 legend: 'Prema ${link}'
66 },
67 {
68 name: 'Orde «contraer a barra de ferramentas»',
69 legend: 'Prema ${toolbarCollapse}'
70 },
71 {
72 name: 'Orde «acceder ao anterior espazo en foco»',
73 legend: 'Prema ${accessPreviousSpace} para acceder ao espazo máis próximo de foco inalcanzábel anterior ao cursor, por exemplo: dous elementos HR adxacentes. Repita a combinación de teclas para chegar a espazos de foco distantes.'
74 },
75 {
76 name: 'Orde «acceder ao seguinte espazo en foco»',
77 legend: 'Prema ${accessNextSpace} para acceder ao espazo máis próximo de foco inalcanzábel posterior ao cursor, por exemplo: dous elementos HR adxacentes. Repita a combinación de teclas para chegar a espazos de foco distantes.'
78 },
79 {
80 name: 'Axuda da accesibilidade',
81 legend: 'Prema ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulador',
87 pause: 'Pausa',
88 capslock: 'Bloq. Maiús',
89 escape: 'Escape',
90 pageUp: 'Páxina arriba',
91 pageDown: 'Páxina abaixo',
92 leftArrow: 'Frecha esquerda',
93 upArrow: 'Frecha arriba',
94 rightArrow: 'Frecha dereita',
95 downArrow: 'Frecha abaixo',
96 insert: 'Inserir',
97 leftWindowKey: 'Tecla Windows esquerda',
98 rightWindowKey: 'Tecla Windows dereita',
99 selectKey: 'Escolla a tecla',
100 numpad0: 'Tec. numérico 0',
101 numpad1: 'Tec. numérico 1',
102 numpad2: 'Tec. numérico 2',
103 numpad3: 'Tec. numérico 3',
104 numpad4: 'Tec. numérico 4',
105 numpad5: 'Tec. numérico 5',
106 numpad6: 'Tec. numérico 6',
107 numpad7: 'Tec. numérico 7',
108 numpad8: 'Tec. numérico 8',
109 numpad9: 'Tec. numérico 9',
110 multiply: 'Multiplicar',
111 add: 'Sumar',
112 subtract: 'Restar',
113 decimalPoint: 'Punto decimal',
114 divide: 'Dividir',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Bloq. num.',
128 scrollLock: 'Bloq. despraz.',
129 semiColon: 'Punto e coma',
130 equalSign: 'Signo igual',
131 comma: 'Coma',
132 dash: 'Guión',
133 period: 'Punto',
134 forwardSlash: 'Barra inclinada',
135 graveAccent: 'Acento grave',
136 openBracket: 'Abrir corchete',
137 backSlash: 'Barra invertida',
138 closeBracket: 'Pechar corchete',
139 singleQuote: 'Comiña simple'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/gu.js b/sources/plugins/a11yhelp/dialogs/lang/gu.js
new file mode 100644
index 0000000..30eb2cd
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/gu.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'gu', {
7 title: 'એક્ક્ષેબિલિટી ની વિગતો',
8 contents: 'હેલ્પ. આ બંધ કરવા ESC દબાવો.',
9 legend: [
10 {
11 name: 'જનરલ',
12 items: [
13 {
14 name: 'એડિટર ટૂલબાર',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'એડિટર ડાયલોગ',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'કમાંડસ',
42 items: [
43 {
44 name: 'અન્ડું કમાંડ',
45 legend: '$ દબાવો {undo}'
46 },
47 {
48 name: 'ફરી કરો કમાંડ',
49 legend: '$ દબાવો {redo}'
50 },
51 {
52 name: 'બોલ્દનો કમાંડ',
53 legend: '$ દબાવો {bold}'
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/he.js b/sources/plugins/a11yhelp/dialogs/lang/he.js
new file mode 100644
index 0000000..24b8572
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/he.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'he', {
7 title: 'הוראות נגישות',
8 contents: 'הוראות נגישות. לסגירה לחץ אסקייפ (ESC).',
9 legend: [
10 {
11 name: 'כללי',
12 items: [
13 {
14 name: 'סרגל הכלים',
15 legend: 'לחץ על ${toolbarFocus} כדי לנווט לסרגל הכלים. עבור לכפתור הבא עם מקש הטאב (TAB) או חץ שמאלי. עבור לכפתור הקודם עם מקש השיפט (SHIFT) + טאב (TAB) או חץ ימני. לחץ רווח או אנטר (ENTER) כדי להפעיל את הכפתור הנבחר.'
16 },
17
18 {
19 name: 'דיאלוגים (חלונות תשאול)',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'תפריט ההקשר (Context Menu)',
26 legend: 'לחץ ${contextMenu} או APPLICATION KEYכדי לפתוח את תפריט ההקשר. עבור לאפשרות הבאה עם טאב (TAB) או חץ למטה. עבור לאפשרות הקודמת עם שיפט (SHIFT) + טאב (TAB) או חץ למעלה. לחץ רווח או אנטר (ENTER) כדי לבחור את האפשרות. פתח את תת התפריט (Sub-menu) של האפשרות הנוכחית עם רווח או אנטר (ENTER) או חץ שמאלי. חזור לתפריט האב עם אסקייפ (ESC) או חץ שמאלי. סגור את תפריט ההקשר עם אסקייפ (ESC).'
27 },
28
29 {
30 name: 'תפריטים צפים (List boxes)',
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'עץ אלמנטים (Elements Path)',
36 legend: 'לחץ ${elementsPathFocus} כדי לנווט לעץ האלמנטים. עבור לפריט הבא עם טאב (TAB) או חץ ימני. עבור לפריט הקודם עם שיפט (SHIFT) + טאב (TAB) או חץ שמאלי. לחץ רווח או אנטר (ENTER) כדי לבחור את האלמנט בעורך.'
37 }
38 ]
39 },
40 {
41 name: 'פקודות',
42 items: [
43 {
44 name: ' ביטול צעד אחרון',
45 legend: 'לחץ ${undo}'
46 },
47 {
48 name: ' חזרה על צעד אחרון',
49 legend: 'לחץ ${redo}'
50 },
51 {
52 name: ' הדגשה',
53 legend: 'לחץ ${bold}'
54 },
55 {
56 name: ' הטייה',
57 legend: 'לחץ ${italic}'
58 },
59 {
60 name: ' הוספת קו תחתון',
61 legend: 'לחץ ${underline}'
62 },
63 {
64 name: ' הוספת לינק',
65 legend: 'לחץ ${link}'
66 },
67 {
68 name: ' כיווץ סרגל הכלים',
69 legend: 'לחץ ${toolbarCollapse}'
70 },
71 {
72 name: 'גישה למיקום המיקוד הקודם',
73 legend: 'לחץ ${accessPreviousSpace} כדי לגשת למיקום המיקוד הלא-נגיש הקרוב לפני הסמן, למשל בין שני אלמנטים סמוכים מסוג HR. חזור על צירוף מקשים זה כדי להגיע למקומות מיקוד רחוקים יותר.'
74 },
75 {
76 name: 'גישה למיקום המיקוד הבא',
77 legend: 'לחץ ${accessNextSpace} כדי לגשת למיקום המיקוד הלא-נגיש הקרוב אחרי הסמן, למשל בין שני אלמנטים סמוכים מסוג HR. חזור על צירוף מקשים זה כדי להגיע למקומות מיקוד רחוקים יותר.'
78 },
79 {
80 name: ' הוראות נגישות',
81 legend: 'לחץ ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'חץ שמאלה',
93 upArrow: 'חץ למעלה',
94 rightArrow: 'חץ ימינה',
95 downArrow: 'חץ למטה',
96 insert: 'הכנס',
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'בחר מקש',
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'הוסף',
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'סלאש',
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'סלאש הפוך',
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'ציטוט יחיד'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/hi.js b/sources/plugins/a11yhelp/dialogs/lang/hi.js
new file mode 100644
index 0000000..308c5ef
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/hi.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'hi', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'सामान्य',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/hr.js b/sources/plugins/a11yhelp/dialogs/lang/hr.js
new file mode 100644
index 0000000..b05273e
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/hr.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'hr', {
7 title: 'Upute dostupnosti',
8 contents: 'Sadržaj pomoći. Za zatvaranje pritisnite ESC.',
9 legend: [
10 {
11 name: 'Općenito',
12 items: [
13 {
14 name: 'Alatna traka',
15 legend: 'Pritisni ${toolbarFocus} za navigaciju do alatne trake. Pomicanje do prethodne ili sljedeće alatne grupe vrši se pomoću SHIFT+TAB i TAB. Pomicanje do prethodnog ili sljedećeg gumba u alatnoj traci vrši se pomoću lijeve i desne strelice kursora. Pritisnite SPACE ili ENTER za aktivaciju alatne trake.'
16 },
17
18 {
19 name: 'Dijalog',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Kontekstni izbornik',
26 legend: 'Pritisnite ${contextMenu} ili APPLICATION tipku za otvaranje kontekstnog izbornika. Pomicanje se vrši TAB ili strelicom kursora prema dolje ili SHIFT+TAB ili strelica kursora prema gore. SPACE ili ENTER odabiru opciju izbornika. Otvorite podizbornik trenutne opcije sa SPACE, ENTER ili desna strelica kursora. Povratak na prethodni izbornik vrši se sa ESC ili lijevom strelicom kursora. Zatvaranje se vrši pritiskom na tipku ESC.'
27 },
28
29 {
30 name: 'Lista',
31 legend: 'Unutar list-boxa, pomicanje na sljedeću stavku vrši se sa TAB ili strelica kursora prema dolje. Na prethodnu sa SHIFT+TAB ili strelica prema gore. Pritiskom na SPACE ili ENTER odabire se stavka ili ESC za zatvaranje.'
32 },
33
34 {
35 name: 'Traka putanje elemenata',
36 legend: 'Pritisnite ${elementsPathFocus} za navigaciju po putanji elemenata. Pritisnite TAB ili desnu strelicu kursora za pomicanje na sljedeći element ili SHIFT+TAB ili lijeva strelica kursora za pomicanje na prethodni element. Pritiskom na SPACE ili ENTER vrši se odabir elementa.'
37 }
38 ]
39 },
40 {
41 name: 'Naredbe',
42 items: [
43 {
44 name: 'Vrati naredbu',
45 legend: 'Pritisni ${undo}'
46 },
47 {
48 name: 'Ponovi naredbu',
49 legend: 'Pritisni ${redo}'
50 },
51 {
52 name: 'Bold naredba',
53 legend: 'Pritisni ${bold}'
54 },
55 {
56 name: 'Italic naredba',
57 legend: 'Pritisni ${italic}'
58 },
59 {
60 name: 'Underline naredba',
61 legend: 'Pritisni ${underline}'
62 },
63 {
64 name: 'Link naredba',
65 legend: 'Pritisni ${link}'
66 },
67 {
68 name: 'Smanji alatnu traku naredba',
69 legend: 'Pritisni ${toolbarCollapse}'
70 },
71 {
72 name: 'Access previous focus space naredba',
73 legend: 'Pritisni ${accessPreviousSpace} za pristup najbližem nedostupnom razmaku prije kursora, npr.: dva spojena HR elementa. Ponovnim pritiskom dohvatiti će se sljedeći nedostupni razmak.'
74 },
75 {
76 name: 'Access next focus space naredba',
77 legend: 'Pritisni ${accessNextSpace} za pristup najbližem nedostupnom razmaku nakon kursora, npr.: dva spojena HR elementa. Ponovnim pritiskom dohvatiti će se sljedeći nedostupni razmak.'
78 },
79 {
80 name: 'Pomoć za dostupnost',
81 legend: 'Pritisni ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/hu.js b/sources/plugins/a11yhelp/dialogs/lang/hu.js
new file mode 100644
index 0000000..f14f17d
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/hu.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'hu', {
7 title: 'Kisegítő utasítások',
8 contents: 'Súgó tartalmak. A párbeszédablak bezárásához nyomjon ESC-et.',
9 legend: [
10 {
11 name: 'Általános',
12 items: [
13 {
14 name: 'Szerkesztő Eszköztár',
15 legend: 'Nyomjon ${toolbarFocus} hogy kijelölje az eszköztárat. A következő és előző eszköztár csoporthoz a TAB és SHIFT+TAB-al juthat el. A következő és előző eszköztár gombhoz a BAL NYÍL vagy JOBB NYÍL gombbal juthat el. Nyomjon SPACE-t vagy ENTER-t hogy aktiválja az eszköztár gombot.'
16 },
17
18 {
19 name: 'Szerkesző párbeszéd ablak',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Szerkesztő helyi menü',
26 legend: 'Nyomjon ${contextMenu}-t vagy ALKALMAZÁS BILLENTYŰT a helyi menü megnyitásához. Ezután a következő menüpontra léphet a TAB vagy LEFELÉ NYÍLLAL. Az előző opciót a SHIFT+TAB vagy FELFELÉ NYÍLLAL érheti el. Nyomjon SPACE-t vagy ENTER-t a menüpont kiválasztásához. A jelenlegi menüpont almenüjének megnyitásához nyomjon SPACE-t vagy ENTER-t, vagy JOBB NYILAT. A főmenühöz való visszatéréshez nyomjon ESC-et vagy BAL NYILAT. A helyi menü bezárása az ESC billentyűvel lehetséges.'
27 },
28
29 {
30 name: 'Szerkesztő lista',
31 legend: 'A listán belül a következő elemre a TAB vagy LEFELÉ NYÍLLAL mozoghat. Az előző elem kiválasztásához nyomjon SHIFT+TAB-ot vagy FELFELÉ NYILAT. Nyomjon SPACE-t vagy ENTER-t az elem kiválasztásához. Az ESC billentyű megnyomásával bezárhatja a listát.'
32 },
33
34 {
35 name: 'Szerkesztő elem utak sáv',
36 legend: 'Nyomj ${elementsPathFocus} hogy kijelöld a elemek út sávját. A következő elem gombhoz a TAB-al vagy a JOBB NYÍLLAL juthatsz el. Az előző gombhoz a SHIFT+TAB vagy BAL NYÍLLAL mehetsz. A SPACE vagy ENTER billentyűvel kiválaszthatod az elemet a szerkesztőben.'
37 }
38 ]
39 },
40 {
41 name: 'Parancsok',
42 items: [
43 {
44 name: 'Parancs visszavonása',
45 legend: 'Nyomj ${undo}'
46 },
47 {
48 name: 'Parancs megismétlése',
49 legend: 'Nyomjon ${redo}'
50 },
51 {
52 name: 'Félkövér parancs',
53 legend: 'Nyomjon ${bold}'
54 },
55 {
56 name: 'Dőlt parancs',
57 legend: 'Nyomjon ${italic}'
58 },
59 {
60 name: 'Aláhúzott parancs',
61 legend: 'Nyomjon ${underline}'
62 },
63 {
64 name: 'Link parancs',
65 legend: 'Nyomjon ${link}'
66 },
67 {
68 name: 'Szerkesztősáv összecsukása parancs',
69 legend: 'Nyomjon ${toolbarCollapse}'
70 },
71 {
72 name: 'Hozzáférés az előző fókusz helyhez parancs',
73 legend: 'Nyomj ${accessNextSpace} hogy hozzáférj a legközelebbi elérhetetlen fókusz helyhez a hiányjel előtt, például: két szomszédos HR elemhez. Ismételd meg a billentyűkombinációt hogy megtaláld a távolabbi fókusz helyeket.'
74 },
75 {
76 name: 'Hozzáférés a következő fókusz helyhez parancs',
77 legend: 'Nyomj ${accessNextSpace} hogy hozzáférj a legközelebbi elérhetetlen fókusz helyhez a hiányjel után, például: két szomszédos HR elemhez. Ismételd meg a billentyűkombinációt hogy megtaláld a távolabbi fókusz helyeket.'
78 },
79 {
80 name: 'Kisegítő súgó',
81 legend: 'Nyomjon ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'balra nyíl',
93 upArrow: 'felfelé nyíl',
94 rightArrow: 'jobbra nyíl',
95 downArrow: 'lefelé nyíl',
96 insert: 'Insert',
97 leftWindowKey: 'bal Windows-billentyű',
98 rightWindowKey: 'jobb Windows-billentyű',
99 selectKey: 'Billentyű választása',
100 numpad0: 'Számbillentyűk 0',
101 numpad1: 'Számbillentyűk 1',
102 numpad2: 'Számbillentyűk 2',
103 numpad3: 'Számbillentyűk 3',
104 numpad4: 'Számbillentyűk 4',
105 numpad5: 'Számbillentyűk 5',
106 numpad6: 'Számbillentyűk 6',
107 numpad7: 'Számbillentyűk 7',
108 numpad8: 'Számbillentyűk 8',
109 numpad9: 'Számbillentyűk 9',
110 multiply: 'Szorzás',
111 add: 'Hozzáadás',
112 subtract: 'Kivonás',
113 decimalPoint: 'Tizedespont',
114 divide: 'Osztás',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Pontosvessző',
130 equalSign: 'Egyenlőségjel',
131 comma: 'Vessző',
132 dash: 'Kötőjel',
133 period: 'Pont',
134 forwardSlash: 'Perjel',
135 graveAccent: 'Visszafelé dőlő ékezet',
136 openBracket: 'Nyitó szögletes zárójel',
137 backSlash: 'fordított perjel',
138 closeBracket: 'Záró szögletes zárójel',
139 singleQuote: 'szimpla idézőjel'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/id.js b/sources/plugins/a11yhelp/dialogs/lang/id.js
new file mode 100644
index 0000000..7799b38
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/id.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'id', {
7 title: 'Instruksi Accessibility',
8 contents: 'Bantuan. Tekan ESC untuk menutup dialog ini.',
9 legend: [
10 {
11 name: 'Umum',
12 items: [
13 {
14 name: 'Toolbar Editor',
15 legend: 'Tekan ${toolbarFocus} untuk berpindah ke toolbar. Untuk berpindah ke group toolbar selanjutnya dan sebelumnya gunakan TAB dan SHIFT+TAB. Untuk berpindah ke tombol toolbar selanjutnya dan sebelumnya gunakan RIGHT ARROW atau LEFT ARROW. Tekan SPASI atau ENTER untuk mengaktifkan tombol toolbar.'
16 },
17
18 {
19 name: 'Dialog Editor',
20 legend:
21 'Pada jendela dialog, tekan TAB untuk berpindah pada elemen dialog selanjutnya, tekan SHIFT+TAB untuk berpindah pada elemen dialog sebelumnya, tekan ENTER untuk submit dialog, tekan ESC untuk membatalkan dialog. Pada dialog dengan multi tab, daftar tab dapat diakses dengan ALT+F10 ataupun dengan tombol TAB sesuai urutan tab pada dialog. Jika daftar tab aktif terpilih, untuk berpindah tab dapat menggunakan RIGHT dan LEFT ARROW.'
22 },
23
24 {
25 name: 'Context Menu Editor',
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'List Box Editor',
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/it.js b/sources/plugins/a11yhelp/dialogs/lang/it.js
new file mode 100644
index 0000000..55ecadc
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/it.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'it', {
7 title: 'Istruzioni di Accessibilità',
8 contents: 'Contenuti di Aiuto. Per chiudere questa finestra premi ESC.',
9 legend: [
10 {
11 name: 'Generale',
12 items: [
13 {
14 name: 'Barra degli strumenti Editor',
15 legend: 'Premere ${toolbarFocus} per passare alla barra degli strumenti. Usare TAB per spostarsi al gruppo successivo, MAIUSC+TAB per spostarsi a quello precedente. Usare FRECCIA DESTRA per spostarsi al pulsante successivo, FRECCIA SINISTRA per spostarsi a quello precedente. Premere SPAZIO o INVIO per attivare il pulsante della barra degli strumenti.'
16 },
17
18 {
19 name: 'Finestra Editor',
20 legend:
21 'All\'interno di una finestra di dialogo è possibile premere TAB per passare all\'elemento successivo della finestra, MAIUSC+TAB per passare a quello precedente; premere INVIO per inviare i dati della finestra, oppure ESC per annullare l\'operazione. Quando una finestra di dialogo ha più schede, è possibile passare all\'elenco delle schede sia con ALT+F10 che con TAB, in base all\'ordine delle tabulazioni della finestra. Quando l\'elenco delle schede è attivo, premere la FRECCIA DESTRA o la FRECCIA SINISTRA per passare rispettivamente alla scheda successiva o a quella precedente.'
22 },
23
24 {
25 name: 'Menù contestuale Editor',
26 legend: 'Premi ${contextMenu} o TASTO APPLICAZIONE per aprire il menu contestuale. Dunque muoviti all\'opzione successiva del menu con il tasto TAB o con la Freccia Sotto. Muoviti all\'opzione precedente con MAIUSC+TAB o con Freccia Sopra. Premi SPAZIO o INVIO per scegliere l\'opzione di menu. Apri il sottomenu dell\'opzione corrente con SPAZIO o INVIO oppure con la Freccia Destra. Torna indietro al menu superiore con ESC oppure Freccia Sinistra. Chiudi il menu contestuale con ESC.'
27 },
28
29 {
30 name: 'Box Lista Editor',
31 legend: 'All\'interno di un elenco di opzioni, per spostarsi all\'elemento successivo premere TAB oppure FRECCIA GIÙ. Per spostarsi all\'elemento precedente usare SHIFT+TAB oppure FRECCIA SU. Premere SPAZIO o INVIO per selezionare l\'elemento della lista. Premere ESC per chiudere l\'elenco di opzioni.'
32 },
33
34 {
35 name: 'Barra percorso elementi editor',
36 legend: 'Premere ${elementsPathFocus} per passare agli elementi della barra del percorso. Usare TAB o FRECCIA DESTRA per passare al pulsante successivo. Per passare al pulsante precedente premere MAIUSC+TAB o FRECCIA SINISTRA. Premere SPAZIO o INVIO per selezionare l\'elemento nell\'editor.'
37 }
38 ]
39 },
40 {
41 name: 'Comandi',
42 items: [
43 {
44 name: ' Annulla comando',
45 legend: 'Premi ${undo}'
46 },
47 {
48 name: ' Ripeti comando',
49 legend: 'Premi ${redo}'
50 },
51 {
52 name: ' Comando Grassetto',
53 legend: 'Premi ${bold}'
54 },
55 {
56 name: ' Comando Corsivo',
57 legend: 'Premi ${italic}'
58 },
59 {
60 name: ' Comando Sottolineato',
61 legend: 'Premi ${underline}'
62 },
63 {
64 name: ' Comando Link',
65 legend: 'Premi ${link}'
66 },
67 {
68 name: ' Comando riduci barra degli strumenti',
69 legend: 'Premi ${toolbarCollapse}'
70 },
71 {
72 name: 'Comando di accesso al precedente spazio di focus',
73 legend: 'Premi ${accessPreviousSpace} per accedere il più vicino spazio di focus non raggiungibile prima del simbolo caret, per esempio due elementi HR adiacenti. Ripeti la combinazione di tasti per raggiungere spazi di focus distanti.'
74 },
75 {
76 name: 'Comando di accesso al prossimo spazio di focus',
77 legend: 'Premi ${accessNextSpace} per accedere il più vicino spazio di focus non raggiungibile dopo il simbolo caret, per esempio due elementi HR adiacenti. Ripeti la combinazione di tasti per raggiungere spazi di focus distanti.'
78 },
79 {
80 name: ' Aiuto Accessibilità',
81 legend: 'Premi ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pausa',
88 capslock: 'Bloc Maiusc',
89 escape: 'Esc',
90 pageUp: 'Pagina sù',
91 pageDown: 'Pagina giù',
92 leftArrow: 'Freccia sinistra',
93 upArrow: 'Freccia su',
94 rightArrow: 'Freccia destra',
95 downArrow: 'Freccia giù',
96 insert: 'Ins',
97 leftWindowKey: 'Tasto di Windows sinistro',
98 rightWindowKey: 'Tasto di Windows destro',
99 selectKey: 'Tasto di selezione',
100 numpad0: '0 sul tastierino numerico',
101 numpad1: '1 sul tastierino numerico',
102 numpad2: '2 sul tastierino numerico',
103 numpad3: '3 sul tastierino numerico',
104 numpad4: '4 sul tastierino numerico',
105 numpad5: '5 sul tastierino numerico',
106 numpad6: '6 sul tastierino numerico',
107 numpad7: '7 sul tastierino numerico',
108 numpad8: '8 sul tastierino numerico',
109 numpad9: '9 sul tastierino numerico',
110 multiply: 'Moltiplicazione',
111 add: 'Più',
112 subtract: 'Sottrazione',
113 decimalPoint: 'Punto decimale',
114 divide: 'Divisione',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Bloc Num',
128 scrollLock: 'Bloc Scorr',
129 semiColon: 'Punto-e-virgola',
130 equalSign: 'Segno di uguale',
131 comma: 'Virgola',
132 dash: 'Trattino',
133 period: 'Punto',
134 forwardSlash: 'Barra',
135 graveAccent: 'Accento grave',
136 openBracket: 'Parentesi quadra aperta',
137 backSlash: 'Barra rovesciata',
138 closeBracket: 'Parentesi quadra chiusa',
139 singleQuote: 'Apostrofo'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ja.js b/sources/plugins/a11yhelp/dialogs/lang/ja.js
new file mode 100644
index 0000000..9053e37
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ja.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ja', {
7 title: 'ユーザー補助の説明',
8 contents: 'ヘルプ このダイアログを閉じるには ESCを押してください。',
9 legend: [
10 {
11 name: '全般',
12 items: [
13 {
14 name: 'エディターツールバー',
15 legend: '${toolbarFocus} を押すとツールバーのオン/オフ操作ができます。カーソルをツールバーのグループで移動させるにはTabかSHIFT+Tabを押します。グループ内でカーソルを移動させるには、右カーソルか左カーソルを押します。スペースキーやエンターを押すとボタンを有効/無効にすることができます。'
16 },
17
18 {
19 name: '編集ダイアログ',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'エディターのメニュー',
26 legend: '${contextMenu} キーかAPPLICATION KEYを押すとコンテキストメニューが開きます。Tabか下カーソルでメニューのオプション選択が下に移動します。戻るには、SHIFT+Tabか上カーソルです。スペースもしくはENTERキーでメニューオプションを決定できます。現在選んでいるオプションのサブメニューを開くには、スペース、もしくは右カーソルを押します。サブメニューから親メニューに戻るには、ESCか左カーソルを押してください。ESCでコンテキストメニュー自体をキャンセルできます。'
27 },
28
29 {
30 name: 'エディターリストボックス',
31 legend: 'リストボックス内で移動するには、Tabか下カーソルで次のアイテムへ移動します。SHIFT+Tabで前のアイテムに戻ります。リストのオプションを選択するには、スペースもしくは、ENTERを押してください。リストボックスを閉じるには、ESCを押してください。'
32 },
33
34 {
35 name: 'エディター要素パスバー',
36 legend: '${elementsPathFocus} を押すとエレメントパスバーを操作出来ます。Tabか右カーソルで次のエレメントを選択できます。前のエレメントを選択するには、SHIFT+Tabか左カーソルです。スペースもしくは、ENTERでエディタ内の対象エレメントを選択出来ます。'
37 }
38 ]
39 },
40 {
41 name: 'コマンド',
42 items: [
43 {
44 name: '元に戻す',
45 legend: '${undo} をクリック'
46 },
47 {
48 name: 'やり直し',
49 legend: '${redo} をクリック'
50 },
51 {
52 name: '太字',
53 legend: '${bold} をクリック'
54 },
55 {
56 name: '斜体 ',
57 legend: '${italic} をクリック'
58 },
59 {
60 name: '下線',
61 legend: '${underline} をクリック'
62 },
63 {
64 name: 'リンク',
65 legend: '${link} をクリック'
66 },
67 {
68 name: 'ツールバーを縮める',
69 legend: '${toolbarCollapse} をクリック'
70 },
71 {
72 name: '前のカーソル移動のできないポイントへ',
73 legend: '${accessPreviousSpace} を押すとカーソルより前にあるカーソルキーで入り込めないスペースへ移動できます。例えば、HRエレメントが2つ接している場合などです。離れた場所へは、複数回キーを押します。'
74 },
75 {
76 name: '次のカーソル移動のできないポイントへ',
77 legend: '${accessNextSpace} を押すとカーソルより後ろにあるカーソルキーで入り込めないスペースへ移動できます。例えば、HRエレメントが2つ接している場合などです。離れた場所へは、複数回キーを押します。'
78 },
79 {
80 name: 'ユーザー補助ヘルプ',
81 legend: '${a11yHelp} をクリック'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: '左矢印',
93 upArrow: '上矢印',
94 rightArrow: '右矢印',
95 downArrow: '下矢印',
96 insert: 'Insert',
97 leftWindowKey: '左Windowキー',
98 rightWindowKey: '右のWindowキー',
99 selectKey: 'Select',
100 numpad0: 'Num 0',
101 numpad1: 'Num 1',
102 numpad2: 'Num 2',
103 numpad3: 'Num 3',
104 numpad4: 'Num 4',
105 numpad5: 'Num 5',
106 numpad6: 'Num 6',
107 numpad7: 'Num 7',
108 numpad8: 'Num 8',
109 numpad9: 'Num 9',
110 multiply: '掛ける',
111 add: '足す',
112 subtract: '引く',
113 decimalPoint: '小数点',
114 divide: '割る',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'セミコロン',
130 equalSign: 'イコール記号',
131 comma: 'カンマ',
132 dash: 'ダッシュ',
133 period: 'ピリオド',
134 forwardSlash: 'フォワードスラッシュ',
135 graveAccent: 'グレイヴアクセント',
136 openBracket: '開きカッコ',
137 backSlash: 'バックスラッシュ',
138 closeBracket: '閉じカッコ',
139 singleQuote: 'シングルクォート'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/km.js b/sources/plugins/a11yhelp/dialogs/lang/km.js
new file mode 100644
index 0000000..4cdd048
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/km.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'km', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'មាតិកា​ជំនួយ។ ដើម្បី​បិទ​ផ្ទាំង​នេះ សូម​ចុច ESC ។',
9 legend: [
10 {
11 name: 'ទូទៅ',
12 items: [
13 {
14 name: 'របារ​ឧបករណ៍​កម្មវិធី​និពន្ធ',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'ផ្ទាំង​កម្មវិធីនិពន្ធ',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'ម៉ីនុយបរិបទអ្នកកែសម្រួល',
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'ប្រអប់បញ្ជីអ្នកកែសម្រួល',
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'ពាក្យបញ្ជា',
42 items: [
43 {
44 name: 'ការ​បញ្ជា​មិនធ្វើវិញ',
45 legend: 'ចុច ${undo}'
46 },
47 {
48 name: 'ការបញ្ជា​ធ្វើវិញ',
49 legend: 'ចុច ${redo}'
50 },
51 {
52 name: 'ការបញ្ជា​អក្សរ​ដិត',
53 legend: 'ចុច ${bold}'
54 },
55 {
56 name: 'ការបញ្ជា​អក្សរ​ទ្រេត',
57 legend: 'ចុច ${italic}'
58 },
59 {
60 name: 'ពាក្យបញ្ជា​បន្ទាត់​ពីក្រោម',
61 legend: 'ចុច ${underline}'
62 },
63 {
64 name: 'ពាក្យបញ្ជា​តំណ',
65 legend: 'ចុច ${link}'
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: 'ជំនួយ​ពី​ភាព​ងាយស្រួល',
81 legend: 'ជួយ ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'ផ្អាក',
88 capslock: 'Caps Lock', // MISSING
89 escape: 'ចាកចេញ',
90 pageUp: 'ទំព័រ​លើ',
91 pageDown: 'ទំព័រ​ក្រោម',
92 leftArrow: 'ព្រួញ​ឆ្វេង',
93 upArrow: 'ព្រួញ​លើ',
94 rightArrow: 'ព្រួញ​ស្ដាំ',
95 downArrow: 'ព្រួញ​ក្រោម',
96 insert: 'បញ្ចូល',
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'ជ្រើស​គ្រាប់​ចុច',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'គុណ',
111 add: 'បន្ថែម',
112 subtract: 'ដក',
113 decimalPoint: 'ចំណុចទសភាគ',
114 divide: 'ចែក',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'បិទ​រំកិល',
129 semiColon: 'ចុច​ក្បៀស',
130 equalSign: 'សញ្ញា​អឺរ៉ូ',
131 comma: 'ក្បៀស',
132 dash: 'Dash', // MISSING
133 period: 'ចុច',
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'តង្កៀប​បើក',
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'តង្កៀប​បិទ',
139 singleQuote: 'បន្តក់​មួយ'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ko.js b/sources/plugins/a11yhelp/dialogs/lang/ko.js
new file mode 100644
index 0000000..e5ed192
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ko.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ko', {
7 title: '접근성 설명',
8 contents: '도움말. 이 창을 닫으시려면 ESC 를 누르세요.',
9 legend: [
10 {
11 name: '일반',
12 items: [
13 {
14 name: '편집기 툴바',
15 legend: '툴바를 탐색하시려면 ${toolbarFocus} 를 투르세요. 이전/다음 툴바 그룹으로 이동하시려면 TAB 키 또는 SHIFT+TAB 키를 누르세요. 이전/다음 툴바 버튼으로 이동하시려면 오른쪽 화살표 키 또는 왼쪽 화살표 키를 누르세요. 툴바 버튼을 활성화 하려면 SPACE 키 또는 ENTER 키를 누르세요.'
16 },
17
18 {
19 name: '편집기 다이얼로그',
20 legend:
21 'TAB 키를 누르면 다음 대화상자로 이동하고, SHIFT+TAB 키를 누르면 이전 대화상자로 이동합니다. 대화상자를 제출하려면 ENTER 키를 누르고, ESC 키를 누르면 대화상자를 취소합니다. 대화상자에 탭이 여러개 있을 때, ALT+F10 키 또는 TAB 키를 누르면 순서에 따라 탭 목록에 도달할 수 있습니다. 탭 목록에 초점이 맞을 때, 오른쪽과 왼쪽 화살표 키를 이용하면 각각 다음과 이전 탭으로 이동할 수 있습니다.'
22 },
23
24 {
25 name: '편집기 환경 메뉴',
26 legend: '${contextMenu} 또는 어플리케이션 키를 누르면 환경-메뉴를 열 수 있습니다. 환경-메뉴에서 TAB 키 또는 아래 화살표 키를 누르면 다음 메뉴 옵션으로 이동할 수 있습니다. 이전 옵션으로 이동은 SHIFT+TAB 키 또는 위 화살표 키를 눌러서 할 수 있습니다. 스페이스 키 또는 ENTER 키를 눌러서 메뉴 옵션을 선택할 수 있습니다. 스페이스 키 또는 ENTER 키 또는 오른쪽 화살표 키를 눌러서 하위 메뉴를 열 수 있습니다. 부모 메뉴 항목으로 돌아가려면 ESC 키 또는 왼쪽 화살표 키를 누릅니다. ESC 키를 눌러서 환경-메뉴를 닫습니다.'
27 },
28
29 {
30 name: '편집기 목록 박스',
31 legend: '리스트-박스 내에서, 목록의 다음 항목으로 이동하려면 TAB 키 또는 아래쪽 화살표 키를 누릅니다. 목록의 이전 항목으로 이동하려면 SHIFT+TAB 키 또는 위쪽 화살표 키를 누릅니다. 스페이스 키 또는 ENTER 키를 누르면 목록의 해당 옵션을 선택합니다. ESC 키를 눌러서 리스트-박스를 닫을 수 있습니다.'
32 },
33
34 {
35 name: '편집기 요소 경로 막대',
36 legend: '${elementsPathFocus}를 눌러서 요소 경로 막대를 탐색할 수 있습니다. 다음 요소로 이동하려면 TAB 키 또는 오른쪽 화살표 키를 누릅니다. SHIFT+TAB 키 또는 왼쪽 화살표 키를 누르면 이전 버튼으로 이동할 수 있습니다. 스페이스 키나 ENTER 키를 누르면 편집기의 해당 항목을 선택합니다.'
37 }
38 ]
39 },
40 {
41 name: '명령',
42 items: [
43 {
44 name: ' 명령 실행 취소',
45 legend: '${undo} 누르시오'
46 },
47 {
48 name: ' 명령 다시 실행',
49 legend: '${redo} 누르시오'
50 },
51 {
52 name: ' 굵게 명령',
53 legend: '${bold} 누르시오'
54 },
55 {
56 name: ' 기울임 꼴 명령',
57 legend: '${italic} 누르시오'
58 },
59 {
60 name: ' 밑줄 명령',
61 legend: '${underline} 누르시오'
62 },
63 {
64 name: ' 링크 명령',
65 legend: '${link} 누르시오'
66 },
67 {
68 name: ' 툴바 줄이기 명령',
69 legend: '${toolbarCollapse} 누르시오'
70 },
71 {
72 name: ' 이전 포커스 공간 접근 명령',
73 legend: '탈자 기호(^) 이전에 ${accessPreviousSpace} 를 누르면, 접근 불가능하면서 가장 가까운 포커스 영역에 접근합니다. 예를 들면, 두 인접한 HR 요소가 있습니다. 키 조합을 반복해서 멀리있는 포커스 영역들에 도달할 수 있습니다.'
74 },
75 {
76 name: '다음 포커스 공간 접근 명령',
77 legend: '탈자 기호(^) 다음에 ${accessNextSpace} 를 누르면, 접근 불가능하면서 가장 가까운 포커스 영역에 접근합니다. 예를 들면, 두 인접한 HR 요소가 있습니다. 키 조합을 반복해서 멀리있는 포커스 영역들에 도달할 수 있습니다. '
78 },
79 {
80 name: ' 접근성 도움말',
81 legend: '${a11yHelp} 누르시오'
82 }
83 ]
84 }
85 ],
86 tab: '탭 키',
87 pause: '일시정지 키',
88 capslock: '캡스 록 키',
89 escape: '이스케이프 키',
90 pageUp: '페이지 업 키',
91 pageDown: '페이지 다운 키',
92 leftArrow: '왼쪽 화살표 키',
93 upArrow: '위쪽 화살표 키',
94 rightArrow: '오른쪽 화살표 키',
95 downArrow: '아래쪽 화살표 키',
96 insert: '인서트 키',
97 leftWindowKey: '왼쪽 윈도우 키',
98 rightWindowKey: '오른쪽 윈도우 키',
99 selectKey: '셀렉트 키',
100 numpad0: '숫자 패드 0 키',
101 numpad1: '숫자 패드 1 키',
102 numpad2: '숫자 패드 2 키',
103 numpad3: '숫자 패드 3 키',
104 numpad4: '숫자 패드 4 키',
105 numpad5: '숫자 패드 5 키',
106 numpad6: '숫자 패드 6 키',
107 numpad7: '숫자 패드 7 키',
108 numpad8: '숫자 패드 8 키',
109 numpad9: '숫자 패드 9 키',
110 multiply: '곱셈(*) 키',
111 add: '덧셈(+) 키',
112 subtract: '뺄셈(-) 키',
113 decimalPoint: '온점(.) 키',
114 divide: '나눗셈(/) 키',
115 f1: 'F1 키',
116 f2: 'F2 키',
117 f3: 'F3 키',
118 f4: 'F4 키',
119 f5: 'F5 키',
120 f6: 'F6 키',
121 f7: 'F7 키',
122 f8: 'F8 키',
123 f9: 'F9 키',
124 f10: 'F10 키',
125 f11: 'F11 키',
126 f12: 'F12 키',
127 numLock: 'Num Lock 키',
128 scrollLock: 'Scroll Lock 키',
129 semiColon: '세미콜론(;) 키',
130 equalSign: '등호(=) 키',
131 comma: '쉼표(,) 키',
132 dash: '대시(-) 키',
133 period: '온점(.) 키',
134 forwardSlash: '슬래시(/) 키',
135 graveAccent: '억음 악센트(`) 키',
136 openBracket: '브라켓 열기([) 키',
137 backSlash: '역슬래시(\\\\) 키',
138 closeBracket: '브라켓 닫기(]) 키',
139 singleQuote: '외 따옴표(\') 키'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ku.js b/sources/plugins/a11yhelp/dialogs/lang/ku.js
new file mode 100644
index 0000000..3f044a2
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ku.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ku', {
7 title: 'ڕێنمای لەبەردەستدابوون',
8 contents: 'پێکهاتەی یارمەتی. کلیك ESC بۆ داخستنی ئەم دیالۆگه.',
9 legend: [
10 {
11 name: 'گشتی',
12 items: [
13 {
14 name: 'تووڵامرازی دەستكاریكەر',
15 legend: 'کلیك ${toolbarFocus} بۆ ڕابەری تووڵامراز. بۆ گواستنەوەی پێشوو داهاتووی گرووپی تووڵامرازی داگرتنی کلیلی TAB لەگەڵ‌ SHIFT+TAB. بۆ گواستنەوەی پێشوو داهاتووی دووگمەی تووڵامرازی لەڕێی کلیلی تیری دەستی ڕاست یان کلیلی تیری دەستی چەپ. کلیکی کلیلی SPACE یان ENTER بۆ چالاککردنی دووگمەی تووڵامراز.'
16 },
17
18 {
19 name: 'دیالۆگی دەستكاریكەر',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.'
22 },
23
24 {
25 name: 'پێڕستی سەرنووسەر',
26 legend: 'کلیك ${contextMenu} یان دوگمەی لیسته‌(Menu) بۆ کردنەوەی لیستەی دەق. بۆ چوونە هەڵبژاردەیەکی تر له‌ لیسته‌ کلیکی کلیلی TAB یان کلیلی تیری ڕوو لەخوارەوه‌ بۆ چوون بۆ هەڵبژاردەی پێشوو کلیکی کلیلی SHIFT+TAB یان کلیلی تیری ڕوو له‌ سەرەوە. داگرتنی کلیلی SPACE یان ENTER بۆ هەڵبژاردنی هەڵبژاردەی لیسته‌. بۆ کردنەوەی لقی ژێر لیسته‌ لەهەڵبژاردەی لیستە کلیکی کلیلی SPACE یان ENTER یان کلیلی تیری دەستی ڕاست. بۆ گەڕانەوه بۆ سەرەوەی لیسته‌ کلیکی کلیلی ESC یان کلیلی تیری دەستی چەپ. بۆ داخستنی لیستە کلیكی کلیلی ESC بکە.'
27 },
28
29 {
30 name: 'لیستی سنووقی سەرنووسەر',
31 legend: 'لەناو سنوقی لیست, چۆن بۆ هەڵنبژاردەی لیستێکی تر کلیکی کلیلی TAB یان کلیلی تیری ڕوو لەخوار. چوون بۆ هەڵبژاردەی لیستی پێشوو کلیکی کلیلی SHIFT+TAB یان کلیلی تیری ڕوو لەسەرەوه‌. کلیکی کلیلی SPACE یان ENTER بۆ دیاریکردنی ‌هەڵبژاردەی لیست. کلیکی کلیلی ESC بۆ داخستنی سنوقی لیست.'
32 },
33
34 {
35 name: 'تووڵامرازی توخم',
36 legend: 'کلیك ${elementsPathFocus} بۆ ڕابەری تووڵامرازی توخمەکان. چوون بۆ دوگمەی توخمێکی تر کلیکی کلیلی TAB یان کلیلی تیری دەستی ڕاست. چوون بۆ دوگمەی توخمی پێشوو کلیلی SHIFT+TAB یان کلیکی کلیلی تیری دەستی چەپ. داگرتنی کلیلی SPACE یان ENTER بۆ دیاریکردنی توخمەکه‌ لەسەرنووسه.'
37 }
38 ]
39 },
40 {
41 name: 'فەرمانەکان',
42 items: [
43 {
44 name: 'پووچکردنەوەی فەرمان',
45 legend: 'کلیك ${undo}'
46 },
47 {
48 name: 'هەڵگەڕانەوەی فەرمان',
49 legend: 'کلیك ${redo}'
50 },
51 {
52 name: 'فەرمانی دەقی قەڵەو',
53 legend: 'کلیك ${bold}'
54 },
55 {
56 name: 'فەرمانی دەقی لار',
57 legend: 'کلیك ${italic}'
58 },
59 {
60 name: 'فەرمانی ژێرهێڵ',
61 legend: 'کلیك ${underline}'
62 },
63 {
64 name: 'فەرمانی به‌ستەر',
65 legend: 'کلیك ${link}'
66 },
67 {
68 name: 'شاردەنەوەی تووڵامراز',
69 legend: 'کلیك ${toolbarCollapse}'
70 },
71 {
72 name: 'چوونەناو سەرنجدانی پێشوی فەرمانی بۆشایی',
73 legend: 'کلیک ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.'
74 },
75 {
76 name: 'چوونەناو سەرنجدانی داهاتووی فەرمانی بۆشایی',
77 legend: 'کلیک ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.'
78 },
79 {
80 name: 'دەستپێگەیشتنی یارمەتی',
81 legend: 'کلیك ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Left Arrow',
93 upArrow: 'Up Arrow',
94 rightArrow: 'Right Arrow',
95 downArrow: 'Down Arrow',
96 insert: 'Insert',
97 leftWindowKey: 'پەنجەرەی چەپ',
98 rightWindowKey: 'پەنجەرەی ڕاست',
99 selectKey: 'Select',
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: '1',
102 numpad2: '2',
103 numpad3: '3',
104 numpad4: '4',
105 numpad5: '5',
106 numpad6: '6',
107 numpad7: '7',
108 numpad8: '8',
109 numpad9: '9',
110 multiply: '*',
111 add: '+',
112 subtract: '-',
113 decimalPoint: '.',
114 divide: '/',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: ';',
130 equalSign: '=',
131 comma: ',',
132 dash: '-',
133 period: '.',
134 forwardSlash: '/',
135 graveAccent: '`',
136 openBracket: '[',
137 backSlash: '\\\\',
138 closeBracket: '}',
139 singleQuote: '\''
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/lt.js b/sources/plugins/a11yhelp/dialogs/lang/lt.js
new file mode 100644
index 0000000..c27e3ba
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/lt.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'lt', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'Bendros savybės',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/lv.js b/sources/plugins/a11yhelp/dialogs/lang/lv.js
new file mode 100644
index 0000000..aac4129
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/lv.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'lv', {
7 title: 'Pieejamības instrukcija',
8 contents: 'Palīdzības saturs. Lai aizvērtu ciet šo dialogu nospiediet ESC.',
9 legend: [
10 {
11 name: 'Galvenais',
12 items: [
13 {
14 name: 'Redaktora rīkjosla',
15 legend: 'Nospiediet ${toolbarFocus} lai pārvietotos uz rīkjoslu. Lai pārvietotos uz nākošo vai iepriekšējo rīkjoslas grupu izmantojiet pogu TAB un SHIFT+TAB. Lai pārvietotos uz nākošo vai iepriekšējo rīkjoslas pogu izmantojiet Kreiso vai Labo bultiņu. Nospiediet Atstarpi vai ENTER lai aktivizētu rīkjosla pogu.'
16 },
17
18 {
19 name: 'Redaktora dialoga logs',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Redaktora satura izvēle',
26 legend: 'Nospiediet ${contextMenu} vai APPLICATION KEY lai atvērtu satura izvēlni. Lai pārvietotos uz nākošo izvēlnes opciju izmantojiet pogu TAB vai pogu Bultiņu uz leju. Lai pārvietotos uz iepriekšējo opciju izmantojiet SHIFT+TAB vai pogu Bultiņa uz augšu. Nospiediet SPACE vai ENTER lai izvelētos izvēlnes opciju. Atveriet tekošajā opcija apakšizvēlni ar SAPCE vai ENTER ka ari to var izdarīt ar Labo bultiņu. Lai atgrieztos atpakaļ uz sakuma izvēlni nospiediet ESC vai Kreiso bultiņu. Lai aizvērtu ciet izvēlnes saturu nospiediet ESC.'
27 },
28
29 {
30 name: 'Redaktora saraksta lauks',
31 legend: 'Saraksta laukā, lai pārvietotos uz nākošo saraksta elementu nospiediet TAB vai pogu Bultiņa uz leju. Lai pārvietotos uz iepriekšējo saraksta elementu nospiediet SHIFT+TAB vai pogu Bultiņa uz augšu. Nospiediet SPACE vai ENTER lai izvēlētos saraksta opcijas. Nospiediet ESC lai aizvērtu saraksta lauku.'
32 },
33
34 {
35 name: 'Redaktora elementa ceļa josla',
36 legend: 'Nospiediet ${elementsPathFocus} lai pārvietotos uz elementa ceļa joslu. Lai pārvietotos uz nākošo elementa pogu izmantojiet TAB vai Labo bultiņu. Lai pārvietotos uz iepriekšējo elementa pogu izmantojiet SHIFT+TAB vai Kreiso bultiņu. Nospiediet SPACE vai ENTER lai izvēlētos elementu redaktorā.'
37 }
38 ]
39 },
40 {
41 name: 'Komandas',
42 items: [
43 {
44 name: 'Komanda atcelt darbību',
45 legend: 'Nospiediet ${undo}'
46 },
47 {
48 name: 'Komanda atkārtot darbību',
49 legend: 'Nospiediet ${redo}'
50 },
51 {
52 name: 'Treknraksta komanda',
53 legend: 'Nospiediet ${bold}'
54 },
55 {
56 name: 'Kursīva komanda',
57 legend: 'Nospiediet ${italic}'
58 },
59 {
60 name: 'Apakšsvītras komanda ',
61 legend: 'Nospiediet ${underline}'
62 },
63 {
64 name: 'Hipersaites komanda',
65 legend: 'Nospiediet ${link}'
66 },
67 {
68 name: 'Rīkjoslas aizvēršanas komanda',
69 legend: 'Nospiediet ${toolbarCollapse}'
70 },
71 {
72 name: 'Piekļūt iepriekšējai fokusa vietas komandai',
73 legend: 'Nospiediet ${accessPreviousSpace} lai piekļūtu tuvākajai nepieejamajai fokusa vietai pirms kursora. Piemēram: diviem blakus esošiem līnijas HR elementiem. Atkārtojiet taustiņu kombināciju lai piekļūtu pie tālākām vietām.'
74 },
75 {
76 name: 'Piekļūt nākošā fokusa apgabala komandai',
77 legend: 'Nospiediet ${accessNextSpace} lai piekļūtu tuvākajai nepieejamajai fokusa vietai pēc kursora. Piemēram: diviem blakus esošiem līnijas HR elementiem. Atkārtojiet taustiņu kombināciju lai piekļūtu pie tālākām vietām.'
78 },
79 {
80 name: 'Pieejamības palīdzība',
81 legend: 'Nospiediet ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/mk.js b/sources/plugins/a11yhelp/dialogs/lang/mk.js
new file mode 100644
index 0000000..8316358
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/mk.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'mk', {
7 title: 'Инструкции за пристапност',
8 contents: 'Содржина на делот за помош. За да го затворите овој дијалог притиснете ESC.',
9 legend: [
10 {
11 name: 'Општо',
12 items: [
13 {
14 name: 'Мени за уредувачот',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Дијалот за едиторот',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Контекст-мени на уредувачот',
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Наредби',
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Пауза',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Up',
92 leftArrow: 'Стрелка лево',
93 upArrow: 'Стрелка горе',
94 rightArrow: 'Стрелка десно',
95 downArrow: 'Стрелка доле',
96 insert: 'Insert',
97 leftWindowKey: 'Лево Windows копче',
98 rightWindowKey: 'Десно Windows копче',
99 selectKey: 'Select копче',
100 numpad0: 'Нум. таст. 0',
101 numpad1: 'Нум. таст. 1',
102 numpad2: 'Нум. таст. 2',
103 numpad3: 'Нум. таст. 3',
104 numpad4: 'Нум. таст. 4',
105 numpad5: 'Нум. таст. 5',
106 numpad6: 'Нум. таст. 6',
107 numpad7: 'Нум. таст. 7',
108 numpad8: 'Нум. таст. 8',
109 numpad9: 'Нум. таст. 9',
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/mn.js b/sources/plugins/a11yhelp/dialogs/lang/mn.js
new file mode 100644
index 0000000..eb11634
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/mn.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'mn', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'Ерөнхий',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/nb.js b/sources/plugins/a11yhelp/dialogs/lang/nb.js
new file mode 100644
index 0000000..ccfeb66
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/nb.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'nb', {
7 title: 'Instruksjoner for tilgjengelighet',
8 contents: 'Innhold for hjelp. Trykk ESC for å lukke denne dialogen.',
9 legend: [
10 {
11 name: 'Generelt',
12 items: [
13 {
14 name: 'Verktøylinje for editor',
15 legend: 'Trykk ${toolbarFocus} for å navigere til verktøylinjen. Flytt til neste og forrige verktøylinjegruppe med TAB og SHIFT+TAB. Flytt til neste og forrige verktøylinjeknapp med HØYRE PILTAST og VENSTRE PILTAST. Trykk MELLOMROM eller ENTER for å aktivere verktøylinjeknappen.'
16 },
17
18 {
19 name: 'Dialog for editor',
20 legend:
21 'Mens du er i en dialog, trykk TAB for å navigere til neste dialogelement, trykk SHIFT+TAB for å flytte til forrige dialogelement, trykk ENTER for å akseptere dialogen, trykk ESC for å avbryte dialogen. Når en dialog har flere faner, kan fanelisten nås med enten ALT+F10 eller med TAB. Når fanelisten er fokusert, går man til neste og forrige fane med henholdsvis HØYRE og VENSTRE PILTAST.'
22 },
23
24 {
25 name: 'Kontekstmeny for editor',
26 legend: 'Trykk ${contextMenu} eller MENYKNAPP for å åpne kontekstmeny. Gå til neste alternativ i menyen med TAB eller PILTAST NED. Gå til forrige alternativ med SHIFT+TAB eller PILTAST OPP. Trykk MELLOMROM eller ENTER for å velge menyalternativet. Åpne undermenyen på valgt alternativ med MELLOMROM eller ENTER eller HØYRE PILTAST. Gå tilbake til overordnet menyelement med ESC eller VENSTRE PILTAST. Lukk kontekstmenyen med ESC.'
27 },
28
29 {
30 name: 'Listeboks for editor',
31 legend: 'I en listeboks, gå til neste alternativ i listen med TAB eller PILTAST NED. Gå til forrige alternativ i listen med SHIFT+TAB eller PILTAST OPP. Trykk MELLOMROM eller ENTER for å velge alternativet i listen. Trykk ESC for å lukke listeboksen.'
32 },
33
34 {
35 name: 'Verktøylinje for elementsti',
36 legend: 'Trykk ${elementsPathFocus} for å navigere til verktøylinjen som viser elementsti. Gå til neste elementknapp med TAB eller HØYRE PILTAST. Gå til forrige elementknapp med SHIFT+TAB eller VENSTRE PILTAST. Trykk MELLOMROM eller ENTER for å velge elementet i editoren.'
37 }
38 ]
39 },
40 {
41 name: 'Hurtigtaster',
42 items: [
43 {
44 name: 'Angre',
45 legend: 'Trykk ${undo}'
46 },
47 {
48 name: 'Gjør om',
49 legend: 'Trykk ${redo}'
50 },
51 {
52 name: 'Fet tekst',
53 legend: 'Trykk ${bold}'
54 },
55 {
56 name: 'Kursiv tekst',
57 legend: 'Trykk ${italic}'
58 },
59 {
60 name: 'Understreking',
61 legend: 'Trykk ${underline}'
62 },
63 {
64 name: 'Lenke',
65 legend: 'Trykk ${link}'
66 },
67 {
68 name: 'Skjul verktøylinje',
69 legend: 'Trykk ${toolbarCollapse}'
70 },
71 {
72 name: 'Gå til forrige fokusområde',
73 legend: 'Trykk ${accessPreviousSpace} for å komme til nærmeste fokusområde før skrivemarkøren som ikke kan nås på vanlig måte, for eksempel to tilstøtende HR-elementer. Gjenta tastekombinasjonen for å komme til fokusområder lenger unna i dokumentet.'
74 },
75 {
76 name: 'Gå til neste fokusområde',
77 legend: 'Trykk ${accessNextSpace} for å komme til nærmeste fokusområde etter skrivemarkøren som ikke kan nås på vanlig måte, for eksempel to tilstøtende HR-elementer. Gjenta tastekombinasjonen for å komme til fokusområder lenger unna i dokumentet.'
78 },
79 {
80 name: 'Hjelp for tilgjengelighet',
81 legend: 'Trykk ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulator',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Venstre piltast',
93 upArrow: 'Opp-piltast',
94 rightArrow: 'Høyre piltast',
95 downArrow: 'Ned-piltast',
96 insert: 'Insert',
97 leftWindowKey: 'Venstre Windows-tast',
98 rightWindowKey: 'Høyre Windows-tast',
99 selectKey: 'Velg nøkkel',
100 numpad0: 'Numerisk tastatur 0',
101 numpad1: 'Numerisk tastatur 1',
102 numpad2: 'Numerisk tastatur 2',
103 numpad3: 'Numerisk tastatur 3',
104 numpad4: 'Numerisk tastatur 4',
105 numpad5: 'Numerisk tastatur 5',
106 numpad6: 'Numerisk tastatur 6',
107 numpad7: 'Numerisk tastatur 7',
108 numpad8: 'Numerisk tastatur 8',
109 numpad9: 'Numerisk tastatur 9',
110 multiply: 'Multipliser',
111 add: 'Legg til',
112 subtract: 'Trekk fra',
113 decimalPoint: 'Desimaltegn',
114 divide: 'Divider',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semikolon',
130 equalSign: 'Likhetstegn',
131 comma: 'Komma',
132 dash: 'Bindestrek',
133 period: 'Punktum',
134 forwardSlash: 'Forover skråstrek',
135 graveAccent: 'Grav aksent',
136 openBracket: 'Åpne parentes',
137 backSlash: 'Bakover skråstrek',
138 closeBracket: 'Lukk parentes',
139 singleQuote: 'Enkelt sitattegn'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/nl.js b/sources/plugins/a11yhelp/dialogs/lang/nl.js
new file mode 100644
index 0000000..00d53ea
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/nl.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'nl', {
7 title: 'Toegankelijkheidsinstructies',
8 contents: 'Help-inhoud. Druk op ESC om dit dialoog te sluiten.',
9 legend: [
10 {
11 name: 'Algemeen',
12 items: [
13 {
14 name: 'Werkbalk tekstverwerker',
15 legend: 'Druk op ${toolbarFocus} om naar de werkbalk te navigeren. Om te schakelen naar de volgende en vorige werkbalkgroep, gebruik TAB en SHIFT+TAB. Om te schakelen naar de volgende en vorige werkbalkknop, gebruik de PIJL RECHTS en PIJL LINKS. Druk op SPATIE of ENTER om een werkbalkknop te activeren.'
16 },
17
18 {
19 name: 'Dialoog tekstverwerker',
20 legend:
21 'In een dialoogvenster, druk op TAB om te navigeren naar het volgende veld. Druk op SHIFT+TAB om naar het vorige veld te navigeren. Druk op ENTER om het dialoogvenster te verzenden. Druk op ESC om het dialoogvenster te sluiten. Bij dialoogvensters met meerdere tabbladen kan de tabset bereikt worden met ALT+F10 of met TAB als onderdeel van de tabvolgorde in het dialoogvenster. Als de tabset focus heeft, kun je schakalen naar het volgende en vorige tabblad met respectievelijk PIJL RECHTS en PIJL LINKS.'
22 },
23
24 {
25 name: 'Contextmenu tekstverwerker',
26 legend: 'Druk op ${contextMenu} of APPLICATION KEY om het contextmenu te openen. Schakel naar de volgende menuoptie met TAB of PIJL OMLAAG. Schakel naar de vorige menuoptie met SHIFT+TAB of PIJL OMHOOG. Druk op SPATIE of ENTER om een menuoptie te selecteren. Op een submenu van de huidige optie met SPATIE, ENTER of PIJL RECHTS. Ga terug naar de bovenliggende menuoptie met ESC of PIJL LINKS. Sluit het contextmenu met ESC.'
27 },
28
29 {
30 name: 'Keuzelijst tekstverwerker',
31 legend: 'In een keuzelijst, schakel naar het volgende item met TAB of PIJL OMLAAG. Schakel naar het vorige item met SHIFT+TAB of PIJL OMHOOG. Druk op SPATIE of ENTER om het item te selecteren. Druk op ESC om de keuzelijst te sluiten.'
32 },
33
34 {
35 name: 'Elementenpad werkbalk tekstverwerker',
36 legend: 'Druk op ${elementsPathFocus} om naar het elementenpad te navigeren. Om te schakelen naar het volgende element, gebruik TAB of PIJL RECHTS. Om te schakelen naar het vorige element, gebruik SHIFT+TAB or PIJL LINKS. Druk op SPATIE of ENTER om een element te selecteren in de tekstverwerker.'
37 }
38 ]
39 },
40 {
41 name: 'Opdrachten',
42 items: [
43 {
44 name: 'Ongedaan maken opdracht',
45 legend: 'Druk op ${undo}'
46 },
47 {
48 name: 'Opnieuw uitvoeren opdracht',
49 legend: 'Druk op ${redo}'
50 },
51 {
52 name: 'Vetgedrukt opdracht',
53 legend: 'Druk op ${bold}'
54 },
55 {
56 name: 'Cursief opdracht',
57 legend: 'Druk op ${italic}'
58 },
59 {
60 name: 'Onderstrepen opdracht',
61 legend: 'Druk op ${underline}'
62 },
63 {
64 name: 'Link opdracht',
65 legend: 'Druk op ${link}'
66 },
67 {
68 name: 'Werkbalk inklappen opdracht',
69 legend: 'Druk op ${toolbarCollapse}'
70 },
71 {
72 name: 'Ga naar vorige focus spatie commando',
73 legend: 'Druk ${accessPreviousSpace} om toegang te verkrijgen tot de dichtstbijzijnde onbereikbare focus spatie voor de caret, bijvoorbeeld: twee aangrenzende HR elementen. Herhaal de toetscombinatie om de verste focus spatie te bereiken.'
74 },
75 {
76 name: 'Ga naar volgende focus spatie commando',
77 legend: 'Druk ${accessNextSpace} om toegang te verkrijgen tot de dichtstbijzijnde onbereikbare focus spatie na de caret, bijvoorbeeld: twee aangrenzende HR elementen. Herhaal de toetscombinatie om de verste focus spatie te bereiken.'
78 },
79 {
80 name: 'Toegankelijkheidshulp',
81 legend: 'Druk op ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Pijl naar links',
93 upArrow: 'Pijl omhoog',
94 rightArrow: 'Pijl naar rechts',
95 downArrow: 'Pijl naar beneden',
96 insert: 'Invoegen',
97 leftWindowKey: 'Linker Windows-toets',
98 rightWindowKey: 'Rechter Windows-toets',
99 selectKey: 'Selecteer toets',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Vermenigvuldigen',
111 add: 'Toevoegen',
112 subtract: 'Aftrekken',
113 decimalPoint: 'Decimaalteken',
114 divide: 'Delen',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Puntkomma',
130 equalSign: 'Is gelijk-teken',
131 comma: 'Komma',
132 dash: 'Koppelteken',
133 period: 'Punt',
134 forwardSlash: 'Slash',
135 graveAccent: 'Accent grave',
136 openBracket: 'Vierkant haakje openen',
137 backSlash: 'Backslash',
138 closeBracket: 'Vierkant haakje sluiten',
139 singleQuote: 'Apostrof'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/no.js b/sources/plugins/a11yhelp/dialogs/lang/no.js
new file mode 100644
index 0000000..4402ddf
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/no.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'no', {
7 title: 'Instruksjoner for tilgjengelighet',
8 contents: 'Innhold for hjelp. Trykk ESC for å lukke denne dialogen.',
9 legend: [
10 {
11 name: 'Generelt',
12 items: [
13 {
14 name: 'Verktøylinje for editor',
15 legend: 'Trykk ${toolbarFocus} for å navigere til verktøylinjen. Flytt til neste og forrige verktøylinjegruppe med TAB og SHIFT+TAB. Flytt til neste og forrige verktøylinjeknapp med HØYRE PILTAST og VENSTRE PILTAST. Trykk MELLOMROM eller ENTER for å aktivere verktøylinjeknappen.'
16 },
17
18 {
19 name: 'Dialog for editor',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Kontekstmeny for editor',
26 legend: 'Trykk ${contextMenu} eller MENYKNAPP for å åpne kontekstmeny. Gå til neste alternativ i menyen med TAB eller PILTAST NED. Gå til forrige alternativ med SHIFT+TAB eller PILTAST OPP. Trykk MELLOMROM eller ENTER for å velge menyalternativet. Åpne undermenyen på valgt alternativ med MELLOMROM eller ENTER eller HØYRE PILTAST. Gå tilbake til overordnet menyelement med ESC eller VENSTRE PILTAST. Lukk kontekstmenyen med ESC.'
27 },
28
29 {
30 name: 'Listeboks for editor',
31 legend: 'I en listeboks, gå til neste alternativ i listen med TAB eller PILTAST NED. Gå til forrige alternativ i listen med SHIFT+TAB eller PILTAST OPP. Trykk MELLOMROM eller ENTER for å velge alternativet i listen. Trykk ESC for å lukke listeboksen.'
32 },
33
34 {
35 name: 'Verktøylinje for elementsti',
36 legend: 'Trykk ${elementsPathFocus} for å navigere til verktøylinjen som viser elementsti. Gå til neste elementknapp med TAB eller HØYRE PILTAST. Gå til forrige elementknapp med SHIFT+TAB eller VENSTRE PILTAST. Trykk MELLOMROM eller ENTER for å velge elementet i editoren.'
37 }
38 ]
39 },
40 {
41 name: 'Kommandoer',
42 items: [
43 {
44 name: 'Angre',
45 legend: 'Trykk ${undo}'
46 },
47 {
48 name: 'Gjør om',
49 legend: 'Trykk ${redo}'
50 },
51 {
52 name: 'Fet tekst',
53 legend: 'Trykk ${bold}'
54 },
55 {
56 name: 'Kursiv tekst',
57 legend: 'Trykk ${italic}'
58 },
59 {
60 name: 'Understreking',
61 legend: 'Trykk ${underline}'
62 },
63 {
64 name: 'Link',
65 legend: 'Trykk ${link}'
66 },
67 {
68 name: 'Skjul verktøylinje',
69 legend: 'Trykk ${toolbarCollapse}'
70 },
71 {
72 name: 'Gå til forrige fokusområde',
73 legend: 'Trykk ${accessPreviousSpace} for å komme til nærmeste fokusområde før skrivemarkøren som ikke kan nås på vanlig måte, for eksempel to tilstøtende HR-elementer. Gjenta tastekombinasjonen for å komme til fokusområder lenger unna i dokumentet.'
74 },
75 {
76 name: 'Gå til neste fokusområde',
77 legend: 'Trykk ${accessNextSpace} for å komme til nærmeste fokusområde etter skrivemarkøren som ikke kan nås på vanlig måte, for eksempel to tilstøtende HR-elementer. Gjenta tastekombinasjonen for å komme til fokusområder lenger unna i dokumentet.'
78 },
79 {
80 name: 'Hjelp for tilgjengelighet',
81 legend: 'Trykk ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/oc.js b/sources/plugins/a11yhelp/dialogs/lang/oc.js
new file mode 100644
index 0000000..8df209d
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/oc.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'oc', {
7 title: 'Instruccions d\'accessibilitat',
8 contents: 'Contengut de l\'ajuda. Per tampar aquesta fenèstra, quichatz sus la tòca Escap.',
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Barra d\'aisinas de l\'editor',
15 legend: 'Quichar sus ${toolbarFocus} per accedir a la barra d\'aisinas. Se desplaçar cap al groupe seguent o precedent de la barra d\'aisinas amb las tòcas Tab e Maj+Tab. Se desplaçar cap al boton seguent o precedent de la barra d\'aisinas amb las tòcas Sageta dreita e Sageta esquèrra. Quichar sus la barra d\'espaci o la tòca Entrada per activer lo boton de barra d\'aisinas.'
16 },
17
18 {
19 name: 'Fenèstra de l\'editor',
20 legend:
21 'Dins una bóstia de dialòg, quichar sus Tab per passar a l\'element seguent, quichar sus Maj+Tab per passar a l\'element precedent, quichar sus Entrada per validar, quichar sus Escap per anullar. Quand una bóstia de dialòg possedís des onglets, la lista pòt èsser atenta amb Alt+F10 o amb Tab. Dins la lista dels onglets, se desplaçar cap al seguent e lo precedent amb las tòcas Sageta dreita e Sageta esquèrra respectivament.'
22 },
23
24 {
25 name: 'Menú contextual de l\'editor',
26 legend: 'Quichar sus ${contextMenu} o sus la tòca Menú per dobrir lo menú contextual. Se desplaçar ensuite cap a l\'opcion seguenta del menú amb las tòcas Tab o Sageta bas. Se desplaçar cap a l\'opcion precedenta amb las tòcas Maj+Tab o Sageta naut. Quichar sus la barra d\'espaci o la tòca Entrada per seleccionar l\'opcion del menu. Quichar sus la barra d\'espaci, la tòca Entrada o Sageta dreita per dobrir lo sosmenú de l\'opcion seleccionada. Tornar a l\'element de menú parent amb la tòca Escap o Sageta esquèrra. Tampar lo menú contextual amb Escap.'
27 },
28
29 {
30 name: 'Zòna de lista de l\'editor',
31 legend: 'Dins una lista en menú desenrotlant, se desplaçar cap a l\'element seguent de la lista amb las tòcas Tab o Sageta bas. Se desplaçar cap a l\'element precedent de la lista amb las tòcas Maj+Tab o Sageta naut. Quichar sus la barra d\'espaci o sus Entrada per seleccionar l\'opcion dins la lista. Quichar sus Escap per tampar lo menú desenrotlant.'
32 },
33
34 {
35 name: 'Barra del camin d\'elements de l\'editor',
36 legend: 'Quichar sus ${elementsPathFocus} per naviguer cap a la barra del fial d\'Ariana dels elements. Se desplaçar cap al boton de l\'element seguent amb las tòcas Tab o Sageta dreita. Se desplaçar cap al boton precedent amb las tòcas Maj+Tab o Sageta esquèrra. Quichar sus la barra d\'espaci o sus Entrada per seleccionar l\'element dins l\'editor.'
37 }
38 ]
39 },
40 {
41 name: 'Comandas',
42 items: [
43 {
44 name: 'Anullar la comanda',
45 legend: 'Quichar sus ${undo}'
46 },
47 {
48 name: 'Comanda restablir',
49 legend: 'Quichar sus ${redo}'
50 },
51 {
52 name: ' Comanda gras',
53 legend: 'Quichar sus ${bold}'
54 },
55 {
56 name: ' Comanda italica',
57 legend: 'Quichar sus ${italic}'
58 },
59 {
60 name: ' Comanda solinhat',
61 legend: 'Quichar sus ${underline}'
62 },
63 {
64 name: ' Comanda ligam',
65 legend: 'Quichar sus ${link}'
66 },
67 {
68 name: 'Comanda enrotlar la barra d\'aisinas',
69 legend: 'Quichar sus ${toolbarCollapse}'
70 },
71 {
72 name: 'Comanda d\'accès a l\'element seleccionable precedent',
73 legend: 'Quichar sus ${accessNextSpace} per accedir a l\'element seleccionable inategnible lo mai pròche abans lo cursor, per exemple : doas linhas orizontalas adjacentas. Repetir la combinason de tòcas per aténher los elements seleccionables precedents.'
74 },
75 {
76 name: 'Comanda d\'accès a l\'element seleccionable seguent',
77 legend: 'Quichar sus ${accessNextSpace} per accedir a l\'element seleccionable inatenhible lo mai pròche aprèp lo cursor, per exemple : doas linhas orizontalas adjacentas. Repetir la combinason de tòcas per aténher los elements seleccionables seguents.'
78 },
79 {
80 name: ' Ajuda sus l\'accessibilitat',
81 legend: 'Quichar sus ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tabulacion',
87 pause: 'Pausa',
88 capslock: 'Verr. Maj.',
89 escape: 'Escap',
90 pageUp: 'Pagina superiora',
91 pageDown: 'Pagina seguenta',
92 leftArrow: 'Sageta esquèrra',
93 upArrow: 'Sageta naut',
94 rightArrow: 'Sageta dreita',
95 downArrow: 'Sageta bassa',
96 insert: 'Inser',
97 leftWindowKey: 'Tòca Windows esquèrra',
98 rightWindowKey: 'Tòca Windows dreita',
99 selectKey: 'Tòca Seleccionar',
100 numpad0: '0 del pavat numeric',
101 numpad1: '1 del pavat numeric',
102 numpad2: '2 del pavat numeric',
103 numpad3: '3 del pavat numeric',
104 numpad4: '4 del pavat numeric',
105 numpad5: '5 del pavat numeric',
106 numpad6: '6 del pavat numeric',
107 numpad7: '7 del pavat numeric',
108 numpad8: 'Pavat numeric 8',
109 numpad9: '9 del pavat numeric',
110 multiply: 'Multiplicar',
111 add: 'Plus',
112 subtract: 'Mens',
113 decimalPoint: 'Punt decimal',
114 divide: 'Devesir',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Verr. Num.',
128 scrollLock: 'Arrèst desfil.',
129 semiColon: 'Punt-virgula',
130 equalSign: 'Signe egal',
131 comma: 'Virgula',
132 dash: 'Jonhent',
133 period: 'Punt',
134 forwardSlash: 'Barra oblica',
135 graveAccent: 'Accent grèu',
136 openBracket: 'Parentèsi dobèrta',
137 backSlash: 'Barra oblica invèrsa',
138 closeBracket: 'Parentèsi tampanta',
139 singleQuote: 'Apostròfa'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/pl.js b/sources/plugins/a11yhelp/dialogs/lang/pl.js
new file mode 100644
index 0000000..825ea08
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/pl.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'pl', {
7 title: 'Instrukcje dotyczące dostępności',
8 contents: 'Zawartość pomocy. Wciśnij ESC, aby zamknąć to okno.',
9 legend: [
10 {
11 name: 'Informacje ogólne',
12 items: [
13 {
14 name: 'Pasek narzędzi edytora',
15 legend: 'Naciśnij ${toolbarFocus}, by przejść do paska narzędzi. Przejdź do następnej i poprzedniej grupy narzędzi używając TAB oraz SHIFT+TAB. Przejdź do następnego i poprzedniego przycisku paska narzędzi za pomocą STRZAŁKI W PRAWO lub STRZAŁKI W LEWO. Naciśnij SPACJĘ lub ENTER by aktywować przycisk paska narzędzi.'
16 },
17
18 {
19 name: 'Okno dialogowe edytora',
20 legend:
21 'Wewnątrz okna dialogowego naciśnij TAB, by przejść do kolejnego elementu tego okna lub SHIFT+TAB, by przejść do poprzedniego elementu okna. Naciśnij ENTER w celu zatwierdzenia opcji okna dialogowego lub ESC w celu anulowania zmian. Jeśli okno dialogowe ma kilka zakładek, do listy zakładek można przejść za pomocą ALT+F10 lub TAB. Gdy lista zakładek jest aktywna, możesz przejść do kolejnej i poprzedniej zakładki za pomocą STRZAŁKI W PRAWO i STRZAŁKI W LEWO.'
22 },
23
24 {
25 name: 'Menu kontekstowe edytora',
26 legend: 'Wciśnij ${contextMenu} lub PRZYCISK APLIKACJI aby otworzyć menu kontekstowe. Przejdź do następnej pozycji menu wciskając TAB lub STRZAŁKĘ W DÓŁ. Przejdź do poprzedniej pozycji menu wciskając SHIFT + TAB lub STRZAŁKĘ W GÓRĘ. Wciśnij SPACJĘ lub ENTER aby wygrać pozycję menu. Otwórz pod-menu obecnej pozycji wciskając SPACJĘ lub ENTER lub STRZAŁKĘ W PRAWO. Wróć do pozycji nadrzędnego menu wciskając ESC lub STRZAŁKĘ W LEWO. Zamknij menu wciskając ESC.'
27 },
28
29 {
30 name: 'Lista w edytorze',
31 legend: 'Wewnątrz listy przejdź do kolejnego elementu listy za pomocą przycisku TAB lub STRZAŁKI W DÓŁ. Przejdź do poprzedniego elementu listy za pomocą SHIFT+TAB lub STRZAŁKI W GÓRĘ. Naciśnij SPACJĘ lub ENTER w celu wybrania opcji z listy. Naciśnij ESC, by zamknąć listę.'
32 },
33
34 {
35 name: 'Pasek ścieżki elementów edytora',
36 legend: 'Naciśnij ${elementsPathFocus} w celu przejścia do paska ścieżki elementów edytora. W celu przejścia do kolejnego elementu naciśnij klawisz TAB lub STRZAŁKI W PRAWO. W celu przejścia do poprzedniego elementu naciśnij klawisze SHIFT+TAB lub STRZAŁKI W LEWO. By wybrać element w edytorze, użyj klawisza SPACJI lub ENTER.'
37 }
38 ]
39 },
40 {
41 name: 'Polecenia',
42 items: [
43 {
44 name: 'Polecenie Cofnij',
45 legend: 'Naciśnij ${undo}'
46 },
47 {
48 name: 'Polecenie Ponów',
49 legend: 'Naciśnij ${redo}'
50 },
51 {
52 name: 'Polecenie Pogrubienie',
53 legend: 'Naciśnij ${bold}'
54 },
55 {
56 name: 'Polecenie Kursywa',
57 legend: 'Naciśnij ${italic}'
58 },
59 {
60 name: 'Polecenie Podkreślenie',
61 legend: 'Naciśnij ${underline}'
62 },
63 {
64 name: 'Polecenie Wstaw/ edytuj odnośnik',
65 legend: 'Naciśnij ${link}'
66 },
67 {
68 name: 'Polecenie schowaj pasek narzędzi',
69 legend: 'Naciśnij ${toolbarCollapse}'
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: 'Pomoc dotycząca dostępności',
81 legend: 'Naciśnij ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Strzałka w lewo',
93 upArrow: 'Strzałka w górę',
94 rightArrow: 'Strzałka w prawo',
95 downArrow: 'Strzałka w dół',
96 insert: 'Insert',
97 leftWindowKey: 'Lewy klawisz Windows',
98 rightWindowKey: 'Prawy klawisz Windows',
99 selectKey: 'Klawisz wyboru',
100 numpad0: 'Klawisz 0 na klawiaturze numerycznej',
101 numpad1: 'Klawisz 1 na klawiaturze numerycznej',
102 numpad2: 'Klawisz 2 na klawiaturze numerycznej',
103 numpad3: 'Klawisz 3 na klawiaturze numerycznej',
104 numpad4: 'Klawisz 4 na klawiaturze numerycznej',
105 numpad5: 'Klawisz 5 na klawiaturze numerycznej',
106 numpad6: 'Klawisz 6 na klawiaturze numerycznej',
107 numpad7: 'Klawisz 7 na klawiaturze numerycznej',
108 numpad8: 'Klawisz 8 na klawiaturze numerycznej',
109 numpad9: 'Klawisz 9 na klawiaturze numerycznej',
110 multiply: 'Przemnóż',
111 add: 'Plus',
112 subtract: 'Minus',
113 decimalPoint: 'Separator dziesiętny',
114 divide: 'Podziel',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Średnik',
130 equalSign: 'Znak równości',
131 comma: 'Przecinek',
132 dash: 'Pauza',
133 period: 'Kropka',
134 forwardSlash: 'Ukośnik prawy',
135 graveAccent: 'Akcent słaby',
136 openBracket: 'Nawias kwadratowy otwierający',
137 backSlash: 'Ukośnik lewy',
138 closeBracket: 'Nawias kwadratowy zamykający',
139 singleQuote: 'Apostrof'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/pt-br.js b/sources/plugins/a11yhelp/dialogs/lang/pt-br.js
new file mode 100644
index 0000000..030df98
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/pt-br.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'pt-br', {
7 title: 'Instruções de Acessibilidade',
8 contents: 'Conteúdo da Ajuda. Para fechar este diálogo pressione ESC.',
9 legend: [
10 {
11 name: 'Geral',
12 items: [
13 {
14 name: 'Barra de Ferramentas do Editor',
15 legend: 'Pressione ${toolbarFocus} para navegar para a barra de ferramentas. Mova para o anterior ou próximo grupo de ferramentas com TAB e SHIFT+TAB. Mova para o anterior ou próximo botão com SETA PARA DIREITA or SETA PARA ESQUERDA. Pressione ESPAÇO ou ENTER para ativar o botão da barra de ferramentas.'
16 },
17
18 {
19 name: 'Diálogo do Editor',
20 legend:
21 'Dentro de um diálogo, pressione TAB para navegar para o próximo elemento. Pressione SHIFT+TAB para mover para o elemento anterior. Pressione ENTER ara enviar o diálogo. pressione ESC para cancelar o diálogo. Quando um diálogo tem múltiplas abas, a lista de abas pode ser acessada com ALT+F10 ou TAB, como parte da ordem de tabulação do diálogo. Com a lista de abas em foco, mova para a próxima aba e para a aba anterior com a SETA DIREITA ou SETA ESQUERDA, respectivamente.'
22 },
23
24 {
25 name: 'Menu de Contexto do Editor',
26 legend: 'Pressione ${contextMenu} ou TECLA DE MENU para abrir o menu de contexto, então mova para a próxima opção com TAB ou SETA PARA BAIXO. Mova para a anterior com SHIFT+TAB ou SETA PARA CIMA. Pressione ESPAÇO ou ENTER para selecionar a opção do menu. Abra o submenu da opção atual com ESPAÇO ou ENTER ou SETA PARA DIREITA. Volte para o menu pai com ESC ou SETA PARA ESQUERDA. Feche o menu de contexto com ESC.'
27 },
28
29 {
30 name: 'Caixa de Lista do Editor',
31 legend: 'Dentro de uma caixa de lista, mova para o próximo item com TAB ou SETA PARA BAIXO. Mova para o item anterior com SHIFT+TAB ou SETA PARA CIMA. Pressione ESPAÇO ou ENTER para selecionar uma opção na lista. Pressione ESC para fechar a caixa de lista.'
32 },
33
34 {
35 name: 'Barra de Caminho do Elementos do Editor',
36 legend: 'Pressione ${elementsPathFocus} para a barra de caminho dos elementos. Mova para o próximo botão de elemento com TAB ou SETA PARA DIREITA. Mova para o botão anterior com SHIFT+TAB ou SETA PARA ESQUERDA. Pressione ESPAÇO ou ENTER para selecionar o elemento no editor.'
37 }
38 ]
39 },
40 {
41 name: 'Comandos',
42 items: [
43 {
44 name: ' Comando Desfazer',
45 legend: 'Pressione ${undo}'
46 },
47 {
48 name: ' Comando Refazer',
49 legend: 'Pressione ${redo}'
50 },
51 {
52 name: ' Comando Negrito',
53 legend: 'Pressione ${bold}'
54 },
55 {
56 name: ' Comando Itálico',
57 legend: 'Pressione ${italic}'
58 },
59 {
60 name: ' Comando Sublinhado',
61 legend: 'Pressione ${underline}'
62 },
63 {
64 name: ' Comando Link',
65 legend: 'Pressione ${link}'
66 },
67 {
68 name: ' Comando Fechar Barra de Ferramentas',
69 legend: 'Pressione ${toolbarCollapse}'
70 },
71 {
72 name: 'Acessar o comando anterior de spaço de foco',
73 legend: 'Pressione ${accessNextSpace} para acessar o espaço de foco não alcançável mais próximo antes do cursor, por exemplo: dois elementos HR adjacentes. Repita a combinação de teclas para alcançar espaços de foco distantes.'
74 },
75 {
76 name: 'Acessar próximo fomando de spaço de foco',
77 legend: 'Pressione ${accessNextSpace} para acessar o espaço de foco não alcançável mais próximo após o cursor, por exemplo: dois elementos HR adjacentes. Repita a combinação de teclas para alcançar espaços de foco distantes.'
78 },
79 {
80 name: ' Ajuda de Acessibilidade',
81 legend: 'Pressione ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tecla Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Seta à Esquerda',
93 upArrow: 'Seta à Cima',
94 rightArrow: 'Seta à Direita',
95 downArrow: 'Seta à Baixo',
96 insert: 'Insert',
97 leftWindowKey: 'Tecla do Windows Esquerda',
98 rightWindowKey: 'Tecla do Windows Direita',
99 selectKey: 'Tecla Selecionar',
100 numpad0: '0 do Teclado Numérico',
101 numpad1: '1 do Teclado Numérico',
102 numpad2: '2 do Teclado Numérico',
103 numpad3: '3 do Teclado Numérico',
104 numpad4: '4 do Teclado Numérico',
105 numpad5: '5 do Teclado Numérico',
106 numpad6: '6 do Teclado Numérico',
107 numpad7: '7 do Teclado Numérico',
108 numpad8: '8 do Teclado Numérico',
109 numpad9: '9 do Teclado Numérico',
110 multiply: 'Multiplicar',
111 add: 'Mais',
112 subtract: 'Subtrair',
113 decimalPoint: 'Ponto',
114 divide: 'Dividir',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Ponto-e-vírgula',
130 equalSign: 'Igual',
131 comma: 'Vírgula',
132 dash: 'Hífen',
133 period: 'Ponto',
134 forwardSlash: 'Barra',
135 graveAccent: 'Acento Grave',
136 openBracket: 'Abrir Conchetes',
137 backSlash: 'Contra-barra',
138 closeBracket: 'Fechar Colchetes',
139 singleQuote: 'Aspas Simples'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/pt.js b/sources/plugins/a11yhelp/dialogs/lang/pt.js
new file mode 100644
index 0000000..986a377
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/pt.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'pt', {
7 title: 'Instruções de acessibilidade',
8 contents: 'Conteúdo de ajuda. Use a tecla ESC para fechar esta janela.',
9 legend: [
10 {
11 name: 'Geral',
12 items: [
13 {
14 name: 'Barra de ferramentas do editor',
15 legend: 'Clique em ${toolbarFocus} para navegar na barra de ferramentas. Para navegar entre o grupo da barra de ferramentas anterior e seguinte use TAB e SHIFT+TAB. Para navegar entre o botão da barra de ferramentas seguinte e anterior use a SETA DIREITA ou SETA ESQUERDA. Carregue em ESPAÇO ou ENTER para ativar o botão da barra de ferramentas.'
16 },
17
18 {
19 name: 'Janela do editor',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Menu de contexto do editor',
26 legend: 'Clique em ${contextMenu} ou TECLA APLICAÇÃO para abrir o menu de contexto. Depois vá para a opção do menu seguinte com TAB ou SETA PARA BAIXO. Vá para a opção anterior com SHIFT+TAB ou SETA PARA CIMA. Pressione ESPAÇO ou ENTER para selecionar a opção do menu. Abra o submenu da opção atual com ESPAÇO, ENTER ou SETA DIREITA. GVá para o item do menu parente com ESC ou SETA ESQUERDA. Feche o menu de contexto com ESC.'
27 },
28
29 {
30 name: 'Editor de caixa em lista',
31 legend: 'Dentro de uma lista, para navegar para o item seguinte da lista use TAB ou SETA PARA BAIXO. Para o item anterior da lista use SHIFT+TAB ou SETA PARA BAIXO. Carregue em ESPAÇO ou ENTER para selecionar a opção lista. Carregue em ESC para fechar a caixa da lista.'
32 },
33
34 {
35 name: 'Editor da barra de caminho dos elementos',
36 legend: 'Clique em ${elementsPathFocus} para navegar na barra de caminho dos elementos. Para o botão do elemento seguinte use TAB ou SETA DIREITA. para o botão anterior use SHIFT+TAB ou SETA ESQUERDA. Carregue em ESPAÇO ou ENTER para selecionar o elemento no editor.'
37 }
38 ]
39 },
40 {
41 name: 'Comandos',
42 items: [
43 {
44 name: 'Comando de anular',
45 legend: 'Carregar ${undo}'
46 },
47 {
48 name: 'Comando de refazer',
49 legend: 'Clique ${redo}'
50 },
51 {
52 name: 'Comando de negrito',
53 legend: 'Pressione ${bold}'
54 },
55 {
56 name: 'Comando de itálico',
57 legend: 'Pressione ${italic}'
58 },
59 {
60 name: 'Comando de sublinhado',
61 legend: 'Pressione ${underline}'
62 },
63 {
64 name: 'Comando de hiperligação',
65 legend: 'Pressione ${link}'
66 },
67 {
68 name: 'Comando de ocultar barra de ferramentas',
69 legend: 'Pressione ${toolbarCollapse}'
70 },
71 {
72 name: 'Aceder ao comando espaço de foco anterior',
73 legend: 'Clique em ${accessPreviousSpace} para aceder ao espaço do focos inalcançável mais perto antes do sinal de omissão, por exemplo: dois elementos HR adjacentes. Repetir a combinação da chave para alcançar os espaços dos focos distantes.'
74 },
75 {
76 name: 'Acesso comando do espaço focus seguinte',
77 legend: 'Pressione ${accessNextSpace} para aceder ao espaço do focos inalcançável mais perto depois do sinal de omissão, por exemplo: dois elementos HR adjacentes. Repetir a combinação da chave para alcançar os espaços dos focos distantes.'
78 },
79 {
80 name: 'Ajuda a acessibilidade',
81 legend: 'Pressione ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pausa',
88 capslock: 'Maiúsculas',
89 escape: 'Esc',
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Seta esquerda',
93 upArrow: 'Seta para cima',
94 rightArrow: 'Seta direita',
95 downArrow: 'Seta para baixo',
96 insert: 'Inserir',
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiplicar',
111 add: 'Adicionar',
112 subtract: 'Subtrair',
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Separar',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Vírgula',
132 dash: 'Cardinal',
133 period: 'Ponto',
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Acento grave',
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Plica'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ro.js b/sources/plugins/a11yhelp/dialogs/lang/ro.js
new file mode 100644
index 0000000..a182bbd
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ro.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ro', {
7 title: 'Instrucțiuni de accesibilitate',
8 contents: 'Cuprins. Pentru a închide acest dialog, apăsați tasta ESC.',
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Editează bara instrumente.',
15 legend: 'Apasă ${toolbarFocus} pentru a naviga prin bara de instrumente. Pentru a te mișca prin grupurile de instrumente folosește tastele TAB și SHIFT+TAB. Pentru a te mișca intre diverse instrumente folosește tastele SĂGEATĂ DREAPTA sau SĂGEATĂ STÂNGA. Apasă butonul SPAȚIU sau ENTER pentru activarea instrumentului.'
16 },
17
18 {
19 name: 'Dialog editor',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor meniu contextual',
26 legend: 'Apasă ${contextMenu} sau TASTA MENIU pentru a deschide meniul contextual. Treci la următoarea opțiune din meniu cu TAB sau SĂGEATĂ JOS. Treci la opțiunea anterioară cu SHIFT+TAB sau SĂGEATĂ SUS. Apasă SPAȚIU sau ENTER pentru a selecta opțiunea din meniu. Deschide sub-meniul opțiunii curente cu SPAȚIU sau ENTER sau SĂGEATĂ DREAPTA. Revino la elementul din meniul părinte cu ESC sau SĂGEATĂ STÂNGA. Închide meniul de context cu ESC.'
27 },
28
29 {
30 name: 'Editor Casetă Listă',
31 legend: 'În interiorul unei liste, treci la următorull element cu TAB sau SĂGEATĂ JOS. Treci la elementul anterior din listă cu SHIFT+TAB sau SĂGEATĂ SUS. Apasă SPAȚIU sau ENTER pentru a selecta opțiunea din listă. Apasă ESC pentru a închide lista.'
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Comenzi',
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Apasă ${undo}'
46 },
47 {
48 name: 'Comanda precedentă',
49 legend: 'Apasă ${redo}'
50 },
51 {
52 name: 'Comanda Îngroșat',
53 legend: 'Apasă ${bold}'
54 },
55 {
56 name: 'Comanda Inclinat',
57 legend: 'Apasă ${italic}'
58 },
59 {
60 name: 'Comanda Subliniere',
61 legend: 'Apasă ${underline}'
62 },
63 {
64 name: 'Comanda Legatură',
65 legend: 'Apasă ${link}'
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ru.js b/sources/plugins/a11yhelp/dialogs/lang/ru.js
new file mode 100644
index 0000000..19d502a
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ru.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ru', {
7 title: 'Горячие клавиши',
8 contents: 'Помощь. Для закрытия этого окна нажмите ESC.',
9 legend: [
10 {
11 name: 'Основное',
12 items: [
13 {
14 name: 'Панель инструментов',
15 legend: 'Нажмите ${toolbarFocus} для перехода к панели инструментов. Для перемещения между группами панели инструментов используйте TAB и SHIFT+TAB. Для перемещения между кнопками панели иструментов используйте кнопки ВПРАВО или ВЛЕВО. Нажмите ПРОБЕЛ или ENTER для запуска кнопки панели инструментов.'
16 },
17
18 {
19 name: 'Диалоги',
20 legend:
21 'Внутри диалога, нажмите TAB чтобы перейти к следующему элементу диалога, нажмите SHIFT+TAB чтобы перейти к предыдущему элементу диалога, нажмите ENTER чтобы отправить диалог, нажмите ESC чтобы отменить диалог. Когда диалоговое окно имеет несколько вкладок, получить доступ к панели вкладок как части диалога можно нажатием или сочетания ALT+F10 или TAB, при этом активные элементы диалога будут перебираться с учетом порядка табуляции. При активной панели вкладок, переход к следующей или предыдущей вкладке осуществляется нажатием стрелки "ВПРАВО" или стрелки "ВЛЕВО" соответственно.'
22 },
23
24 {
25 name: 'Контекстное меню',
26 legend: 'Нажмите ${contextMenu} или клавишу APPLICATION, чтобы открыть контекстное меню. Затем перейдите к следующему пункту меню с помощью TAB или стрелкой "ВНИЗ". Переход к предыдущей опции - SHIFT+TAB или стрелкой "ВВЕРХ". Нажмите SPACE, или ENTER, чтобы задействовать опцию меню. Открыть подменю текущей опции - SPACE или ENTER или стрелкой "ВПРАВО". Возврат к родительскому пункту меню - ESC или стрелкой "ВЛЕВО". Закрытие контекстного меню - ESC.'
27 },
28
29 {
30 name: 'Редактор списка',
31 legend: 'Внутри окна списка, переход к следующему пункту списка - TAB или стрелкой "ВНИЗ". Переход к предыдущему пункту списка - SHIFT+TAB или стрелкой "ВВЕРХ". Нажмите SPACE, или ENTER, чтобы задействовать опцию списка. Нажмите ESC, чтобы закрыть окно списка.'
32 },
33
34 {
35 name: 'Путь к элементу',
36 legend: 'Нажмите ${elementsPathFocus}, чтобы перейти к панели пути элементов. Переход к следующей кнопке элемента - TAB или стрелкой "ВПРАВО". Переход к предыдущей кнопку - SHIFT+TAB или стрелкой "ВЛЕВО". Нажмите SPACE, или ENTER, чтобы выбрать элемент в редакторе.'
37 }
38 ]
39 },
40 {
41 name: 'Команды',
42 items: [
43 {
44 name: 'Отменить',
45 legend: 'Нажмите ${undo}'
46 },
47 {
48 name: 'Повторить',
49 legend: 'Нажмите ${redo}'
50 },
51 {
52 name: 'Полужирный',
53 legend: 'Нажмите ${bold}'
54 },
55 {
56 name: 'Курсив',
57 legend: 'Нажмите ${italic}'
58 },
59 {
60 name: 'Подчеркнутый',
61 legend: 'Нажмите ${underline}'
62 },
63 {
64 name: 'Гиперссылка',
65 legend: 'Нажмите ${link}'
66 },
67 {
68 name: 'Свернуть панель инструментов',
69 legend: 'Нажмите ${toolbarCollapse}'
70 },
71 {
72 name: 'Команды доступа к предыдущему фокусному пространству',
73 legend: 'Нажмите ${accessPreviousSpace}, чтобы обратиться к ближайшему недостижимому фокусному пространству перед символом "^", например: два смежных HR элемента. Повторите комбинацию клавиш, чтобы достичь отдаленных фокусных пространств.'
74 },
75 {
76 name: 'Команды доступа к следующему фокусному пространству',
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.'
78 },
79 {
80 name: 'Справка по горячим клавишам',
81 legend: 'Нажмите ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Esc',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Стрелка влево',
93 upArrow: 'Стрелка вверх',
94 rightArrow: 'Стрелка вправо',
95 downArrow: 'Стрелка вниз',
96 insert: 'Insert',
97 leftWindowKey: 'Левая клавиша Windows',
98 rightWindowKey: 'Правая клавиша Windows',
99 selectKey: 'Выбрать',
100 numpad0: 'Цифра 0',
101 numpad1: 'Цифра 1',
102 numpad2: 'Цифра 2',
103 numpad3: 'Цифра 3',
104 numpad4: 'Цифра 4',
105 numpad5: 'Цифра 5',
106 numpad6: 'Цифра 6',
107 numpad7: 'Цифра 7',
108 numpad8: 'Цифра 8',
109 numpad9: 'Цифра 9',
110 multiply: 'Умножить',
111 add: 'Плюс',
112 subtract: 'Вычесть',
113 decimalPoint: 'Десятичная точка',
114 divide: 'Делить',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Точка с запятой',
130 equalSign: 'Равно',
131 comma: 'Запятая',
132 dash: 'Тире',
133 period: 'Точка',
134 forwardSlash: 'Наклонная черта',
135 graveAccent: 'Апостроф',
136 openBracket: 'Открыть скобку',
137 backSlash: 'Обратная наклонная черта',
138 closeBracket: 'Закрыть скобку',
139 singleQuote: 'Одинарная кавычка'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/si.js b/sources/plugins/a11yhelp/dialogs/lang/si.js
new file mode 100644
index 0000000..14d94ad
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/si.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'si', {
7 title: 'ළඟා වියහැකි ',
8 contents: 'උදව් සඳහා අන්තර්ගතය.නික්මයෙමට ESC බොත්තම ඔබන්න',
9 legend: [
10 {
11 name: 'පොදු කරුණු',
12 items: [
13 {
14 name: 'සංස්කරණ මෙවලම් ',
15 legend: 'ඔබන්න ${මෙවලම් තීරු අවධානය} මෙවලම් තීරුවේ එහා මෙහා යෑමට.ඉදිරියට යෑමට හා ආපසු යෑමට මෙවලම් තීරුකාණ්ඩය හා TAB හා SHIFT+TAB .ඉදිරියට යෑමට හා ආපසු යෑමට මෙවලම් තීරු බොත්තම සමග RIGHT ARROW හෝ LEFT ARROW.මෙවලම් තීරු බොත්තම සක්‍රිය කර ගැනීමට SPACE හෝ ENTER බොත්තම ඔබන්න.'
16 },
17
18 {
19 name: 'සංස්කරණ ',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'සංස්කරණ අඩංගුවට ',
26 legend: 'ඔබන්න ${අන්තර්ගත මෙනුව} හෝ APPLICATION KEY අන්තර්ගත-මෙනුව විවුරතකිරීමට. ඊළඟ මෙනුව-ව්කල්පයන්ට යෑමට TAB හෝ DOWN ARROW බොත්තම ද, පෙර විකල්පයන්ටයෑමට SHIFT+TAB හෝ UP ARROW බොත්තම ද, මෙනුව-ව්කල්පයන් තේරීමට SPACE හෝ ENTER බොත්තම ද, දැනට විවුර්තව ඇති උප-මෙනුවක වීකල්ප තේරීමට SPACE හෝ ENTER හෝ RIGHT ARROW ද, නැවත පෙර ප්‍රධාන මෙනුවට යෑමට ESC හෝ LEFT ARROW බොත්තම ද. අන්තර්ගත-මෙනුව වැසීමට ESC බොත්තම ද ඔබන්න.'
27 },
28
29 {
30 name: 'සංස්කරණ තේරුම් ',
31 legend: 'තේරුම් කොටුව තුළ , ඊළඟ අයිතමයට යෑමට TAB හෝ DOWN ARROW , පෙර අයිතමයට යෑමට SHIFT+TAB හෝ UP ARROW . අයිතම විකල්පයන් තේරීමට SPACE හෝ ENTER ,තේරුම් කොටුව වැසීමට ESC බොත්තම් ද ඔබන්න.'
32 },
33
34 {
35 name: 'සංස්කරණ අංග සහිත ',
36 legend: 'ඔබන්න ${මෙවලම් තීරු අවධානය} මෙවලම් තීරුවේ එහා මෙහා යෑමට.ඉදිරියට යෑමට හා ආපසු යෑමට මෙවලම් තීරුකාණ්ඩය හා TAB හා SHIFT+TAB .ඉදිරියට යෑමට හා ආපසු යෑමට මෙවලම් තීරු බොත්තම සමග RIGHT ARROW හෝ LEFT ARROW.මෙවලම් තීරු බොත්තම සක්‍රිය කර ගැනීමට SPACE හෝ ENTER බොත්තම ඔබන්න.'
37 }
38 ]
39 },
40 {
41 name: 'විධාන',
42 items: [
43 {
44 name: 'විධානය වෙනස් ',
45 legend: 'ඔබන්න ${වෙනස් කිරීම}'
46 },
47 {
48 name: 'විධාන නැවත් පෙර පරිදිම වෙනස්කර ගැනීම.',
49 legend: 'ඔබන්න ${නැවත් පෙර පරිදිම වෙනස්කර ගැනීම}'
50 },
51 {
52 name: 'තද අකුරින් විධාන',
53 legend: 'ඔබන්න ${තද }'
54 },
55 {
56 name: 'බැධී අකුරු විධාන',
57 legend: 'ඔබන්න ${බැධී අකුරු }'
58 },
59 {
60 name: 'යටින් ඉරි ඇද ඇති විධාන.',
61 legend: 'ඔබන්න ${යටින් ඉරි ඇද ඇති}'
62 },
63 {
64 name: 'සම්බන්ධිත විධාන',
65 legend: 'ඔබන්න ${සම්බන්ධ }'
66 },
67 {
68 name: 'මෙවලම් තීරු හැකුලුම් විධාන',
69 legend: 'ඔබන්න ${මෙවලම් තීරු හැකුලුම් }'
70 },
71 {
72 name: 'යොමුවීමට පෙර වැදගත් විධාන',
73 legend: 'ඔබන්න ${යොමුවීමට ඊළඟ }'
74 },
75 {
76 name: 'යොමුවීමට ඊළග වැදගත් විධාන',
77 legend: 'ඔබන්න ${යොමුවීමට ඊළඟ }'
78 },
79 {
80 name: 'ප්‍රවේශ ',
81 legend: 'ඔබන්න ${a11y }'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sk.js b/sources/plugins/a11yhelp/dialogs/lang/sk.js
new file mode 100644
index 0000000..2d74c3b
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/sk.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'sk', {
7 title: 'Inštrukcie prístupnosti',
8 contents: 'Pomocný obsah. Pre zatvorenie tohto okna, stlačte ESC.',
9 legend: [
10 {
11 name: 'Všeobecne',
12 items: [
13 {
14 name: 'Lišta nástrojov editora',
15 legend: 'Stlačte ${toolbarFocus} pre navigáciu na lištu nástrojov. Medzi ďalšou a predchádzajúcou lištou nástrojov sa pohybujete s TAB a SHIFT+TAB. Medzi ďalším a predchádzajúcim tlačidlom na lište nástrojov sa pohybujete s pravou šípkou a ľavou šípkou. Stlačte medzerník alebo ENTER pre aktiváciu tlačidla lišty nástrojov.'
16 },
17
18 {
19 name: 'Editorový dialóg',
20 legend:
21 'V dialógovom okne stlačte TAB pre presun na ďalší prvok, SHIFT+TAB pre presun na predchádzajúci prvok, ENTER pre odoslanie, ESC pre zrušenie. Keď má dialógové okno viacero kariet, zoznam kariet dosiahnete buď stlačením ALT+F10 alebo s TAB v príslušnom poradí kariet. So zameraným zoznamom kariet sa pohybujte k ďalšej alebo predchádzajúcej karte cez PRAVÚ a ĽAVÚ ŠÍPKU.'
22 },
23
24 {
25 name: 'Editorové kontextové menu',
26 legend: 'Stlačte ${contextMenu} alebo APPLICATION KEY pre otvorenie kontextového menu. Potom sa presúvajte na ďalšie možnosti menu s TAB alebo dolnou šípkou. Presunte sa k predchádzajúcej možnosti s SHIFT+TAB alebo hornou šípkou. Stlačte medzerník alebo ENTER pre výber možnosti menu. Otvorte pod-menu danej možnosti s medzerníkom, alebo ENTER, alebo pravou šípkou. Vráťte sa späť do položky rodičovského menu s ESC alebo ľavou šípkou. Zatvorte kontextové menu s ESC.'
27 },
28
29 {
30 name: 'Editorov box zoznamu',
31 legend: 'V boxe zoznamu, presuňte sa na ďalšiu položku v zozname s TAB alebo dolnou šípkou. Presuňte sa k predchádzajúcej položke v zozname so SHIFT+TAB alebo hornou šípkou. Stlačte medzerník alebo ENTER pre výber možnosti zoznamu. Stlačte ESC pre zatvorenie boxu zoznamu.'
32 },
33
34 {
35 name: 'Editorove pásmo cesty prvku',
36 legend: 'Stlačte ${elementsPathFocus} pre navigovanie na pásmo cesty elementu. Presuňte sa na tlačidlo ďalšieho prvku s TAB alebo pravou šípkou. Presuňte sa k predchádzajúcemu tlačidlu s SHIFT+TAB alebo ľavou šípkou. Stlačte medzerník alebo ENTER pre výber prvku v editore.'
37 }
38 ]
39 },
40 {
41 name: 'Príkazy',
42 items: [
43 {
44 name: 'Vrátiť príkazy',
45 legend: 'Stlačte ${undo}'
46 },
47 {
48 name: 'Nanovo vrátiť príkaz',
49 legend: 'Stlačte ${redo}'
50 },
51 {
52 name: 'Príkaz na stučnenie',
53 legend: 'Stlačte ${bold}'
54 },
55 {
56 name: 'Príkaz na kurzívu',
57 legend: 'Stlačte ${italic}'
58 },
59 {
60 name: 'Príkaz na podčiarknutie',
61 legend: 'Stlačte ${underline}'
62 },
63 {
64 name: 'Príkaz na odkaz',
65 legend: 'Stlačte ${link}'
66 },
67 {
68 name: 'Príkaz na zbalenie lišty nástrojov',
69 legend: 'Stlačte ${toolbarCollapse}'
70 },
71 {
72 name: 'Prejsť na predchádzajúcu zamerateľnú medzeru príkazu',
73 legend: 'Stlačte ${accessPreviousSpace} pre prístup na najbližšie nedosiahnuteľné zamerateľné medzery pred vsuvkuo. Napríklad: dve za sebou idúce horizontálne čiary. Opakujte kombináciu klávesov pre dosiahnutie vzdialených zamerateľných medzier.'
74 },
75 {
76 name: 'Prejsť na ďalší ',
77 legend: 'Stlačte ${accessNextSpace} pre prístup na najbližšie nedosiahnuteľné zamerateľné medzery po vsuvke. Napríklad: dve za sebou idúce horizontálne čiary. Opakujte kombináciu klávesov pre dosiahnutie vzdialených zamerateľných medzier.'
78 },
79 {
80 name: 'Pomoc prístupnosti',
81 legend: 'Stlačte ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Stránka hore',
91 pageDown: 'Stránka dole',
92 leftArrow: 'Šípka naľavo',
93 upArrow: 'Šípka hore',
94 rightArrow: 'Šípka napravo',
95 downArrow: 'Šípka dole',
96 insert: 'Insert',
97 leftWindowKey: 'Ľavé Windows tlačidlo',
98 rightWindowKey: 'Pravé Windows tlačidlo',
99 selectKey: 'Tlačidlo Select',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Násobenie',
111 add: 'Sčítanie',
112 subtract: 'Odčítanie',
113 decimalPoint: 'Desatinná čiarka',
114 divide: 'Delenie',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Bodkočiarka',
130 equalSign: 'Rovná sa',
131 comma: 'Čiarka',
132 dash: 'Pomĺčka',
133 period: 'Bodka',
134 forwardSlash: 'Lomítko',
135 graveAccent: 'Zdôrazňovanie prízvuku',
136 openBracket: 'Hranatá zátvorka otváracia',
137 backSlash: 'Backslash',
138 closeBracket: 'Hranatá zátvorka zatváracia',
139 singleQuote: 'Jednoduché úvodzovky'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sl.js b/sources/plugins/a11yhelp/dialogs/lang/sl.js
new file mode 100644
index 0000000..bb38713
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/sl.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'sl', {
7 title: 'Navodila za dostopnost',
8 contents: 'Vsebina pomoči. Če želite zapreti pogovorno okno, pritisnite ESC.',
9 legend: [
10 {
11 name: 'Splošno',
12 items: [
13 {
14 name: 'Orodna vrstica urejevalnika',
15 legend: 'Pritisnite ${toolbarFocus} za pomik v orodno vrstico. Z TAB in SHIFT+TAB se pomikate na naslednjo in prejšnjo skupino orodne vrstice. Z DESNO PUŠČICO ali LEVO PUŠČICO se pomikate na naslednji in prejšnji gumb orodne vrstice. Pritisnite SPACE ali ENTER, da aktivirate gumb orodne vrstice.'
16 },
17
18 {
19 name: 'Urejevalno Pogovorno Okno',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Kontekstni meni urejevalnika',
26 legend: 'Pritisnite ${contextMenu} ali APPLICATION KEY, da odprete kontekstni meni. Nato se premaknite na naslednjo možnost menija s tipko TAB ali PUŠČICA DOL. Premakniti se na prejšnjo možnost z SHIFT + TAB ali PUŠČICA GOR. Pritisnite SPACE ali ENTER za izbiro možnosti menija. Odprite podmeni trenutne možnosti menija s tipko SPACE ali ENTER ali DESNA PUŠČICA. Vrnite se na matični element menija s tipko ESC ali LEVA PUŠČICA. Zaprite kontekstni meni z ESC.'
27 },
28
29 {
30 name: 'Urejevalno Seznamsko Polje',
31 legend: 'Znotraj seznama, se premaknete na naslednji element seznama s tipko TAB ali PUŠČICO DOL. Z SHIFT+TAB ali PUŠČICO GOR se premaknete na prejšnji element seznama. Pritisnite tipko SPACE ali ENTER za izbiro elementa. Pritisnite tipko ESC, da zaprete seznam.'
32 },
33
34 {
35 name: 'Urejevalna vrstica poti elementa',
36 legend: 'Pritisnite ${elementsPathFocus} za pomikanje po vrstici elementnih poti. S TAB ali DESNA PUŠČICA se premaknete na naslednji gumb elementa. Z SHIFT+TAB ali LEVO PUŠČICO se premaknete na prejšnji gumb elementa. Pritisnite SPACE ali ENTER za izbiro elementa v urejevalniku.'
37 }
38 ]
39 },
40 {
41 name: 'Ukazi',
42 items: [
43 {
44 name: 'Razveljavi ukaz',
45 legend: 'Pritisnite ${undo}'
46 },
47 {
48 name: 'Ponovi ukaz',
49 legend: 'Pritisnite ${redo}'
50 },
51 {
52 name: 'Krepki ukaz',
53 legend: 'Pritisnite ${bold}'
54 },
55 {
56 name: 'Ležeči ukaz',
57 legend: 'Pritisnite ${italic}'
58 },
59 {
60 name: 'Poudarni ukaz',
61 legend: 'Pritisnite ${underline}'
62 },
63 {
64 name: 'Ukaz povezave',
65 legend: 'Pritisnite ${link}'
66 },
67 {
68 name: 'Skrči Orodno Vrstico Ukaz',
69 legend: 'Pritisnite ${toolbarCollapse}'
70 },
71 {
72 name: 'Dostop do prejšnjega ukaza ostrenja',
73 legend: 'Pritisnite ${accessPreviousSpace} za dostop do najbližjega nedosegljivega osredotočenega prostora pred strešico, npr.: dva sosednja HR elementa. Ponovite kombinacijo tipk, da dosežete oddaljene osredotočene prostore.'
74 },
75 {
76 name: 'Dostop do naslednjega ukaza ostrenja',
77 legend: 'Pritisnite ${accessNextSpace} za dostop do najbližjega nedosegljivega osredotočenega prostora po strešici, npr.: dva sosednja HR elementa. Ponovite kombinacijo tipk, da dosežete oddaljene osredotočene prostore.'
78 },
79 {
80 name: 'Pomoč dostopnosti',
81 legend: 'Pritisnite ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Puščica levo',
93 upArrow: 'Puščica gor',
94 rightArrow: 'Puščica desno',
95 downArrow: 'Puščica dol',
96 insert: 'Insert',
97 leftWindowKey: 'Leva tipka Windows',
98 rightWindowKey: 'Desna tipka Windows',
99 selectKey: 'Select tipka',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Zmnoži',
111 add: 'Dodaj',
112 subtract: 'Odštej',
113 decimalPoint: 'Decimalna vejica',
114 divide: 'Deli',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Podpičje',
130 equalSign: 'Enačaj',
131 comma: 'Vejica',
132 dash: 'Vezaj',
133 period: 'Pika',
134 forwardSlash: 'Desna poševnica',
135 graveAccent: 'Krativec',
136 openBracket: 'Oklepaj',
137 backSlash: 'Leva poševnica',
138 closeBracket: 'Zaklepaj',
139 singleQuote: 'Opuščaj'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sq.js b/sources/plugins/a11yhelp/dialogs/lang/sq.js
new file mode 100644
index 0000000..c5947cc
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/sq.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'sq', {
7 title: 'Udhëzimet e Qasjes',
8 contents: 'Përmbajtja ndihmëse. Për ta mbyllur dialogun shtyp ESC.',
9 legend: [
10 {
11 name: 'Të përgjithshme',
12 items: [
13 {
14 name: 'Shiriti i Redaktuesit',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Dialogu i Redaktuesit',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Komandat',
42 items: [
43 {
44 name: 'Rikthe komandën',
45 legend: 'Shtyp ${undo}'
46 },
47 {
48 name: 'Ribëj komandën',
49 legend: 'Shtyp ${redo}'
50 },
51 {
52 name: 'Komanda e trashjes së tekstit',
53 legend: 'Shtyp ${bold}'
54 },
55 {
56 name: 'Komanda kursive',
57 legend: 'Shtyp ${italic}'
58 },
59 {
60 name: 'Komanda e nënvijëzimit',
61 legend: 'Shtyp ${underline}'
62 },
63 {
64 name: 'Komanda e Nyjes',
65 legend: 'Shtyp ${link}'
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Shtyp ${toolbarCollapse}'
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: 'Ndihmë Qasjeje',
81 legend: 'Shtyp ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Fletë',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Shenja majtas',
93 upArrow: 'Shenja sipër',
94 rightArrow: 'Shenja djathtas',
95 downArrow: 'Shenja poshtë',
96 insert: 'Shto',
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Shto',
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semicolon',
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Presje',
132 dash: 'vizë',
133 period: 'Pikë',
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Hape kllapën',
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Mbylle kllapën',
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js b/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js
new file mode 100644
index 0000000..5b743ac
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'sr-latn', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'Opšte',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sr.js b/sources/plugins/a11yhelp/dialogs/lang/sr.js
new file mode 100644
index 0000000..0e3e979
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/sr.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'sr', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'Опште',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Commands', // MISSING
42 items: [
43 {
44 name: ' Undo command', // MISSING
45 legend: 'Press ${undo}' // MISSING
46 },
47 {
48 name: ' Redo command', // MISSING
49 legend: 'Press ${redo}' // MISSING
50 },
51 {
52 name: ' Bold command', // MISSING
53 legend: 'Press ${bold}' // MISSING
54 },
55 {
56 name: ' Italic command', // MISSING
57 legend: 'Press ${italic}' // MISSING
58 },
59 {
60 name: ' Underline command', // MISSING
61 legend: 'Press ${underline}' // MISSING
62 },
63 {
64 name: ' Link command', // MISSING
65 legend: 'Press ${link}' // MISSING
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sv.js b/sources/plugins/a11yhelp/dialogs/lang/sv.js
new file mode 100644
index 0000000..4962b95
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/sv.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'sv', {
7 title: 'Hjälpmedelsinstruktioner',
8 contents: 'Hjälpinnehåll. För att stänga denna dialogruta trycker du på ESC.',
9 legend: [
10 {
11 name: 'Allmänt',
12 items: [
13 {
14 name: 'Editor verktygsfält',
15 legend: 'Tryck på ${toolbarFocus} för att navigera till verktygsfältet. Flytta till nästa och föregående verktygsfältsgrupp med TAB och SHIFT+TAB. Flytta till nästa och föregående knapp i verktygsfältet med HÖGERPIL eller VÄNSTERPIL. Tryck SPACE eller ENTER för att aktivera knappen i verktygsfältet.'
16 },
17
18 {
19 name: 'Dialogeditor',
20 legend:
21 'Inuti en dialogruta, tryck TAB för att navigera till nästa fält i dialogrutan, tryck SKIFT+TAB för att flytta till föregående fält, tryck ENTER för att skicka. Du avbryter och stänger dialogen med ESC. För dialogrutor som har flera flikar, tryck ALT+F10 eller TAB för att navigera till fliklistan. med fliklistan vald flytta till nästa och föregående flik med HÖGER- eller VÄNSTERPIL.'
22 },
23
24 {
25 name: 'Editor för innehållsmeny',
26 legend: 'Tryck på $ {contextMenu} eller PROGRAMTANGENTEN för att öppna snabbmenyn. Flytta sedan till nästa menyalternativ med TAB eller NEDPIL. Flytta till föregående alternativ med SHIFT + TABB eller UPPIL. Tryck Space eller ENTER för att välja menyalternativ. Öppna undermeny av nuvarande alternativ med SPACE eller ENTER eller HÖGERPIL. Gå tillbaka till överordnade menyalternativ med ESC eller VÄNSTERPIL. Stäng snabbmenyn med ESC.'
27 },
28
29 {
30 name: 'Editor för list-box',
31 legend: 'Inuti en list-box, gå till nästa listobjekt med TAB eller NEDPIL. Flytta till föregående listobjekt med SHIFT+TAB eller UPPIL. Tryck SPACE eller ENTER för att välja listan alternativet. Tryck ESC för att stänga list-boxen.'
32 },
33
34 {
35 name: 'Editor för elementens sökväg',
36 legend: 'Tryck på ${elementsPathFocus} för att navigera till verktygsfältet för elementens sökvägar. Flytta till nästa elementknapp med TAB eller HÖGERPIL. Flytta till föregående knapp med SKIFT+TAB eller VÄNSTERPIL. Tryck SPACE eller ENTER för att välja element i redigeraren.'
37 }
38 ]
39 },
40 {
41 name: 'Kommandon',
42 items: [
43 {
44 name: 'Ångra kommando',
45 legend: 'Tryck på ${undo}'
46 },
47 {
48 name: 'Gör om kommando',
49 legend: 'Tryck på ${redo}'
50 },
51 {
52 name: 'Kommandot fet stil',
53 legend: 'Tryck på ${bold}'
54 },
55 {
56 name: 'Kommandot kursiv',
57 legend: 'Tryck på ${italic}'
58 },
59 {
60 name: 'Kommandot understruken',
61 legend: 'Tryck på ${underline}'
62 },
63 {
64 name: 'Kommandot länk',
65 legend: 'Tryck på ${link}'
66 },
67 {
68 name: 'Verktygsfält Dölj kommandot',
69 legend: 'Tryck på ${toolbarCollapse}'
70 },
71 {
72 name: 'Gå till föregående fokus plats',
73 legend: 'Tryck på ${accessPreviousSpace} för att gå till närmast onåbara utrymme före markören, exempel: två intilliggande HR element. Repetera tangentkombinationen för att gå till nästa.'
74 },
75 {
76 name: 'Tillgå nästa fokuskommandots utrymme',
77 legend: 'Tryck ${accessNextSpace} på för att komma åt den närmaste onåbar fokus utrymme efter cirkumflex, till exempel: två intilliggande HR element. Upprepa tangentkombinationen för att nå avlägsna fokus utrymmen.'
78 },
79 {
80 name: 'Hjälp om tillgänglighet',
81 legend: 'Tryck ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Paus',
88 capslock: 'Caps lock',
89 escape: 'Escape',
90 pageUp: 'Sida Up',
91 pageDown: 'Sida Ned',
92 leftArrow: 'Vänsterpil',
93 upArrow: 'Uppil',
94 rightArrow: 'Högerpil',
95 downArrow: 'Nedåtpil',
96 insert: 'Infoga',
97 leftWindowKey: 'Vänster Windowstangent',
98 rightWindowKey: 'Höger Windowstangent',
99 selectKey: 'Välj tangent',
100 numpad0: 'Nummer 0',
101 numpad1: 'Nummer 1',
102 numpad2: 'Nummer 2',
103 numpad3: 'Nummer 3',
104 numpad4: 'Nummer 4',
105 numpad5: 'Nummer 5',
106 numpad6: 'Nummer 6',
107 numpad7: 'Nummer 7',
108 numpad8: 'Nummer 8',
109 numpad9: 'Nummer 9',
110 multiply: 'Multiplicera',
111 add: 'Addera',
112 subtract: 'Minus',
113 decimalPoint: 'Decimalpunkt',
114 divide: 'Dividera',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Semikolon',
130 equalSign: 'Lika med tecken',
131 comma: 'Komma',
132 dash: 'Minus',
133 period: 'Punkt',
134 forwardSlash: 'Snedstreck framåt',
135 graveAccent: 'Accent',
136 openBracket: 'Öppningsparentes',
137 backSlash: 'Snedstreck bakåt',
138 closeBracket: 'Slutparentes',
139 singleQuote: 'Enkelt Citattecken'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/th.js b/sources/plugins/a11yhelp/dialogs/lang/th.js
new file mode 100644
index 0000000..1382894
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/th.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'th', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'ทั่วไป',
12 items: [
13 {
14 name: 'แถบเครื่องมือสำหรับเครื่องมือช่วยพิมพ์',
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'คำสั่ง',
42 items: [
43 {
44 name: 'เลิกทำคำสั่ง',
45 legend: 'วาง ${undo}'
46 },
47 {
48 name: 'คำสั่งสำหรับทำซ้ำ',
49 legend: 'วาง ${redo}'
50 },
51 {
52 name: 'คำสั่งสำหรับตัวหนา',
53 legend: 'วาง ${bold}'
54 },
55 {
56 name: 'คำสั่งสำหรับตัวเอียง',
57 legend: 'วาง ${italic}'
58 },
59 {
60 name: 'คำสั่งสำหรับขีดเส้นใต้',
61 legend: 'วาง ${underline}'
62 },
63 {
64 name: 'คำสั่งสำหรับลิงก์',
65 legend: 'วาง ${link}'
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: 'Press ${toolbarCollapse}' // MISSING
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING
82 }
83 ]
84 }
85 ],
86 tab: 'Tab', // MISSING
87 pause: 'Pause', // MISSING
88 capslock: 'Caps Lock', // MISSING
89 escape: 'Escape', // MISSING
90 pageUp: 'Page Up', // MISSING
91 pageDown: 'Page Down', // MISSING
92 leftArrow: 'Left Arrow', // MISSING
93 upArrow: 'Up Arrow', // MISSING
94 rightArrow: 'Right Arrow', // MISSING
95 downArrow: 'Down Arrow', // MISSING
96 insert: 'Insert', // MISSING
97 leftWindowKey: 'Left Windows key', // MISSING
98 rightWindowKey: 'Right Windows key', // MISSING
99 selectKey: 'Select key', // MISSING
100 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING
103 numpad3: 'Numpad 3', // MISSING
104 numpad4: 'Numpad 4', // MISSING
105 numpad5: 'Numpad 5', // MISSING
106 numpad6: 'Numpad 6', // MISSING
107 numpad7: 'Numpad 7', // MISSING
108 numpad8: 'Numpad 8', // MISSING
109 numpad9: 'Numpad 9', // MISSING
110 multiply: 'Multiply', // MISSING
111 add: 'Add', // MISSING
112 subtract: 'Subtract', // MISSING
113 decimalPoint: 'Decimal Point', // MISSING
114 divide: 'Divide', // MISSING
115 f1: 'F1', // MISSING
116 f2: 'F2', // MISSING
117 f3: 'F3', // MISSING
118 f4: 'F4', // MISSING
119 f5: 'F5', // MISSING
120 f6: 'F6', // MISSING
121 f7: 'F7', // MISSING
122 f8: 'F8', // MISSING
123 f9: 'F9', // MISSING
124 f10: 'F10', // MISSING
125 f11: 'F11', // MISSING
126 f12: 'F12', // MISSING
127 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING
130 equalSign: 'Equal Sign', // MISSING
131 comma: 'Comma', // MISSING
132 dash: 'Dash', // MISSING
133 period: 'Period', // MISSING
134 forwardSlash: 'Forward Slash', // MISSING
135 graveAccent: 'Grave Accent', // MISSING
136 openBracket: 'Open Bracket', // MISSING
137 backSlash: 'Backslash', // MISSING
138 closeBracket: 'Close Bracket', // MISSING
139 singleQuote: 'Single Quote' // MISSING
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/tr.js b/sources/plugins/a11yhelp/dialogs/lang/tr.js
new file mode 100644
index 0000000..15306a5
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/tr.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'tr', {
7 title: 'Erişilebilirlik Talimatları',
8 contents: 'Yardım içeriği. Bu pencereyi kapatmak için ESC tuşuna basın.',
9 legend: [
10 {
11 name: 'Genel',
12 items: [
13 {
14 name: 'Düzenleyici Araç Çubuğu',
15 legend: 'Araç çubuğunda gezinmek için ${toolbarFocus} basın. TAB ve SHIFT+TAB ile önceki ve sonraki araç çubuğu grubuna taşıyın. SAĞ OK veya SOL OK ile önceki ve sonraki bir araç çubuğu düğmesini hareket ettirin. SPACE tuşuna basın veya araç çubuğu düğmesini etkinleştirmek için ENTER tuşna basın.'
16 },
17
18 {
19 name: 'Diyalog Düzenleyici',
20 legend:
21 'Dialog penceresi içinde, sonraki iletişim alanına gitmek için SEKME tuşuna basın, önceki alana geçmek için SHIFT + TAB tuşuna basın, pencereyi göndermek için ENTER tuşuna basın, dialog penceresini iptal etmek için ESC tuşuna basın. Birden çok sekme sayfaları olan diyalogların, sekme listesine gitmek için ALT + F10 tuşlarına basın. Sonra TAB veya SAĞ OK sonraki sekmeye taşıyın. SHIFT + TAB veya SOL OK ile önceki sekmeye geçin. Sekme sayfayı seçmek için SPACE veya ENTER tuşuna basın.'
22 },
23
24 {
25 name: 'İçerik Menü Editörü',
26 legend: 'İçerik menüsünü açmak için ${contextMenu} veya UYGULAMA TUŞU\'na basın. Daha sonra SEKME veya AŞAĞI OK ile bir sonraki menü seçeneği taşıyın. SHIFT + TAB veya YUKARI OK ile önceki seçeneğe gider. Menü seçeneğini seçmek için SPACE veya ENTER tuşuna basın. Seçili seçeneğin alt menüsünü SPACE ya da ENTER veya SAĞ OK açın. Üst menü öğesini geçmek için ESC veya SOL OK ile geri dönün. ESC ile bağlam menüsünü kapatın.'
27 },
28
29 {
30 name: 'Liste Kutusu Editörü',
31 legend: 'Liste kutusu içinde, bir sonraki liste öğesine SEKME VEYA AŞAĞI OK ile taşıyın. SHIFT+TAB veya YUKARI önceki liste öğesi taşıyın. Liste seçeneği seçmek için SPACE veya ENTER tuşuna basın. Liste kutusunu kapatmak için ESC tuşuna basın.'
32 },
33
34 {
35 name: 'Element Yol Çubuğu Editörü',
36 legend: 'Elementlerin yol çubuğunda gezinmek için ${ElementsPathFocus} basın. SEKME veya SAĞ OK ile sonraki element düğmesine taşıyın. SHIFT+TAB veya SOL OK önceki düğmeye hareket ettirin. Editör içindeki elementi seçmek için ENTER veya SPACE tuşuna basın.'
37 }
38 ]
39 },
40 {
41 name: 'Komutlar',
42 items: [
43 {
44 name: 'Komutu geri al',
45 legend: '$(undo)\'ya basın'
46 },
47 {
48 name: 'Komutu geri al',
49 legend: '${redo} basın'
50 },
51 {
52 name: ' Kalın komut',
53 legend: '${bold} basın'
54 },
55 {
56 name: ' İtalik komutu',
57 legend: '${italic} basın'
58 },
59 {
60 name: ' Alttan çizgi komutu',
61 legend: '${underline} basın'
62 },
63 {
64 name: ' Bağlantı komutu',
65 legend: '${link} basın'
66 },
67 {
68 name: ' Araç çubuğu Toplama komutu',
69 legend: '${toolbarCollapse} basın'
70 },
71 {
72 name: 'Önceki komut alanına odaklan',
73 legend: 'Düzeltme imleçinden önce, en yakın uzaktaki alana erişmek için ${accessPreviousSpace} basın, örneğin: iki birleşik HR elementleri. Aynı tuş kombinasyonu tekrarıyla diğer alanlarada ulaşın.'
74 },
75 {
76 name: 'Sonraki komut alanına odaklan',
77 legend: 'Düzeltme imleçinden sonra, en yakın uzaktaki alana erişmek için ${accessNextSpace} basın, örneğin: iki birleşik HR elementleri. Aynı tuş kombinasyonu tekrarıyla diğer alanlarada ulaşın.'
78 },
79 {
80 name: 'Erişilebilirlik Yardımı',
81 legend: '${a11yHelp}\'e basın'
82 }
83 ]
84 }
85 ],
86 tab: 'Sekme tuşu',
87 pause: 'Durdurma tuşu',
88 capslock: 'Büyük harf tuşu',
89 escape: 'Vazgeç tuşu',
90 pageUp: 'Sayfa Yukarı',
91 pageDown: 'Sayfa Aşağı',
92 leftArrow: 'Sol ok',
93 upArrow: 'Yukarı ok',
94 rightArrow: 'Sağ ok',
95 downArrow: 'Aşağı ok',
96 insert: 'Araya gir',
97 leftWindowKey: 'Sol windows tuşu',
98 rightWindowKey: 'Sağ windows tuşu',
99 selectKey: 'Seçme tuşu',
100 numpad0: 'Nümerik 0',
101 numpad1: 'Nümerik 1',
102 numpad2: 'Nümerik 2',
103 numpad3: 'Nümerik 3',
104 numpad4: 'Nümerik 4',
105 numpad5: 'Nümerik 5',
106 numpad6: 'Nümerik 6',
107 numpad7: 'Nümerik 7',
108 numpad8: 'Nümerik 8',
109 numpad9: 'Nümerik 9',
110 multiply: 'Çarpma',
111 add: 'Toplama',
112 subtract: 'Çıkarma',
113 decimalPoint: 'Ondalık işareti',
114 divide: 'Bölme',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lk',
128 scrollLock: 'Scr Lk',
129 semiColon: 'Noktalı virgül',
130 equalSign: 'Eşittir',
131 comma: 'Virgül',
132 dash: 'Eksi',
133 period: 'Nokta',
134 forwardSlash: 'İleri eğik çizgi',
135 graveAccent: 'Üst tırnak',
136 openBracket: 'Parantez aç',
137 backSlash: 'Ters eğik çizgi',
138 closeBracket: 'Parantez kapa',
139 singleQuote: 'Tek tırnak'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/tt.js b/sources/plugins/a11yhelp/dialogs/lang/tt.js
new file mode 100644
index 0000000..bdd9847
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/tt.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'tt', {
7 title: 'Accessibility Instructions', // MISSING
8 contents: 'Help Contents. To close this dialog press ESC.', // MISSING
9 legend: [
10 {
11 name: 'Гомуми',
12 items: [
13 {
14 name: 'Editor Toolbar', // MISSING
15 legend: 'Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.' // MISSING
16 },
17
18 {
19 name: 'Editor Dialog', // MISSING
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Editor Context Menu', // MISSING
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.' // MISSING
27 },
28
29 {
30 name: 'Editor List Box', // MISSING
31 legend: 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.' // MISSING
32 },
33
34 {
35 name: 'Editor Element Path Bar', // MISSING
36 legend: 'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.' // MISSING
37 }
38 ]
39 },
40 {
41 name: 'Командалар',
42 items: [
43 {
44 name: 'Кайтару',
45 legend: '${undo} басыгыз'
46 },
47 {
48 name: 'Кабатлау',
49 legend: '${redo} басыгыз'
50 },
51 {
52 name: 'Калын',
53 legend: '${bold} басыгыз'
54 },
55 {
56 name: 'Курсив',
57 legend: '${italic} басыгыз'
58 },
59 {
60 name: 'Астына сызылган',
61 legend: '${underline} басыгыз'
62 },
63 {
64 name: 'Сылталама',
65 legend: '${link} басыгыз'
66 },
67 {
68 name: ' Toolbar Collapse command', // MISSING
69 legend: '${toolbarCollapse} басыгыз'
70 },
71 {
72 name: ' Access previous focus space command', // MISSING
73 legend: 'Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
74 },
75 {
76 name: ' Access next focus space command', // MISSING
77 legend: 'Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces.' // MISSING
78 },
79 {
80 name: ' Accessibility Help', // MISSING
81 legend: '${a11yHelp} басыгыз'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Тыныш',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Сул якка ук',
93 upArrow: 'Өскә таба ук',
94 rightArrow: 'Уң якка ук',
95 downArrow: 'Аска таба ук',
96 insert: 'Өстәү',
97 leftWindowKey: 'Сул Windows төймəсе',
98 rightWindowKey: 'Уң Windows төймəсе',
99 selectKey: 'Select төймəсе',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Тапкырлау',
111 add: 'Кушу',
112 subtract: 'Алу',
113 decimalPoint: 'Унарлы нокта',
114 divide: 'Бүлү',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Нокталы өтер',
130 equalSign: 'Тигезлек билгесе',
131 comma: 'Өтер',
132 dash: 'Сызык',
133 period: 'Дәрәҗә',
134 forwardSlash: 'Кыек сызык',
135 graveAccent: 'Гравис',
136 openBracket: 'Җәя ачу',
137 backSlash: 'Кире кыек сызык',
138 closeBracket: 'Җәя ябу',
139 singleQuote: 'Бер иңле куштырнаклар'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ug.js b/sources/plugins/a11yhelp/dialogs/lang/ug.js
new file mode 100644
index 0000000..1771562
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/ug.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'ug', {
7 title: 'قوشۇمچە چۈشەندۈرۈش',
8 contents: 'ياردەم مەزمۇنى. بۇ سۆزلەشكۈنى ياپماقچى بولسىڭىز ESC نى بېسىڭ.',
9 legend: [
10 {
11 name: 'ئادەتتىكى',
12 items: [
13 {
14 name: 'قورال بالداق تەھرىر',
15 legend: '${toolbarFocus} بېسىلسا قورال بالداققا يېتەكلەيدۇ، TAB ياكى SHIFT+TAB ئارقىلىق قورال بالداق گۇرۇپپىسى تاللىنىدۇ، ئوڭ سول يا ئوقتا توپچا تاللىنىدۇ، بوشلۇق ياكى Enter كۇنۇپكىسىدا تاللانغان توپچىنى قوللىنىدۇ.'
16 },
17
18 {
19 name: 'تەھرىرلىگۈچ سۆزلەشكۈسى',
20 legend:
21 'سۆزلەشكۈدە TAB كۇنۇپكىسىدا كېيىنكى سۆز بۆلىكىگە يۆتكىلىدۇ، SHIFT+TAB بىرىكمە كۇنۇپكىسىدا ئالدىنقى سۆز بۆلىكىگە يۆتكىلىدۇ، ENTER كۇنۇپكىسىدا سۆزلەشكۈنى تاپشۇرىدۇ، ESC كۇنۇپكىسى سۆزلەشكۈدىن ۋاز كېچىدۇ. كۆپ بەتكۈچلۈك سۆزلەشكۈگە نىسبەتەن، ALT+F10 دا بەتكۈچ تىزىمىغا يۆتكەيدۇ. ئاندىن TAB كۇنۇپكىسى ياكى ئوڭ يا ئوق كۇنۇپكىسى كېيىنكى بەتكۈچكە يۆتكەيدۇ؛SHIFT+ TAB كۇنۇپكىسى ياكى سول يا ئوق كۇنۇپكىسى ئالدىنقى بەتكۈچكە يۆتكەيدۇ. بوشلۇق كۇنۇپكىسى ياكى ENTER كۇنۇپكىسى بەتكۈچنى تاللايدۇ.'
22 },
23
24 {
25 name: 'تەھرىرلىگۈچ تىل مۇھىت تىزىملىكى',
26 legend: '${contextMenu} ياكى ئەپ كۇنۇپكىسىدا تىل مۇھىت تىزىملىكىنى ئاچىدۇ. ئاندىن TAB ياكى ئاستى يا ئوق كۇنۇپكىسىدا كېيىنكى تىزىملىك تۈرىگە يۆتكەيدۇ؛ SHIFT+TAB ياكى ئۈستى يا ئوق كۇنۇپكىسىدا ئالدىنقى تىزىملىك تۈرىگە يۆتكەيدۇ. بوشلۇق ياكى ENTER كۇنۇپكىسىدا تىزىملىك تۈرىنى تاللايدۇ. بوشلۇق، ENTER ياكى ئوڭ يا ئوق كۇنۇپكىسىدا تارماق تىزىملىكنى ئاچىدۇ. قايتىش تىزىملىكىگە ESC ياكى سول يا ئوق كۇنۇپكىسى ئىشلىتىلىدۇ. ESC كۇنۇپكىسىدا تىل مۇھىت تىزىملىكى تاقىلىدۇ.'
27 },
28
29 {
30 name: 'تەھرىرلىگۈچ تىزىمى',
31 legend: 'تىزىم قۇتىسىدا، كېيىنكى تىزىم تۈرىگە يۆتكەشتە TAB ياكى ئاستى يا ئوق كۇنۇپكىسى ئىشلىتىلىدۇ. ئالدىنقى تىزىم تۈرىگە يۆتكەشتە SHIFT+TAB ياكى ئۈستى يا ئوق كۇنۇپكىسى ئىشلىتىلىدۇ. بوشلۇق ياكى ENTER كۇنۇپكىسىدا تىزىم تۈرىنى تاللايدۇ.ESC كۇنۇپكىسىدا تىزىم قۇتىسىنى يىغىدۇ.'
32 },
33
34 {
35 name: 'تەھرىرلىگۈچ ئېلېمېنت يول بالداق',
36 legend: '${elementsPathFocus} بېسىلسا ئېلېمېنت يول بالداققا يېتەكلەيدۇ، TAB ياكى ئوڭ يا ئوقتا كېيىنكى ئېلېمېنت تاللىنىدۇ، SHIFT+TAB ياكى سول يا ئوقتا ئالدىنقى ئېلېمېنت تاللىنىدۇ، بوشلۇق ياكى Enter كۇنۇپكىسىدا تەھرىرلىگۈچتىكى ئېلېمېنت تاللىنىدۇ.'
37 }
38 ]
39 },
40 {
41 name: 'بۇيرۇق',
42 items: [
43 {
44 name: 'بۇيرۇقتىن يېنىۋال',
45 legend: '${undo} نى بېسىڭ'
46 },
47 {
48 name: 'قايتىلاش بۇيرۇقى',
49 legend: '${redo} نى بېسىڭ'
50 },
51 {
52 name: 'توملىتىش بۇيرۇقى',
53 legend: '${bold} نى بېسىڭ'
54 },
55 {
56 name: 'يانتۇ بۇيرۇقى',
57 legend: '${italic} نى بېسىڭ'
58 },
59 {
60 name: 'ئاستى سىزىق بۇيرۇقى',
61 legend: '${underline} نى بېسىڭ'
62 },
63 {
64 name: 'ئۇلانما بۇيرۇقى',
65 legend: '${link} نى بېسىڭ'
66 },
67 {
68 name: 'قورال بالداق قاتلاش بۇيرۇقى',
69 legend: '${toolbarCollapse} نى بېسىڭ'
70 },
71 {
72 name: 'ئالدىنقى فوكۇس نۇقتىسىنى زىيارەت قىلىدىغان بۇيرۇق',
73 legend: '${accessPreviousSpace} بېسىپ ^ بەلگىسىگە ئەڭ يېقىن زىيارەت قىلغىلى بولمايدىغان فوكۇس نۇقتا رايونىنىڭ ئالدىنى زىيارەت قىلىدۇ، مەسىلەن: ئۆز ئارا قوشنا ئىككى HR ئېلېمېنت. بۇ بىرىكمە كۇنۇپكا تەكرارلانسا يىراقتىكى فوكۇس نۇقتا رايونىغا يەتكىلى بولىدۇ.'
74 },
75 {
76 name: 'كېيىنكى فوكۇس نۇقتىسىنى زىيارەت قىلىدىغان بۇيرۇق',
77 legend: '${accessNextSpace} بېسىپ ^ بەلگىسىگە ئەڭ يېقىن زىيارەت قىلغىلى بولمايدىغان فوكۇس نۇقتا رايونىنىڭ كەينىنى زىيارەت قىلىدۇ، مەسىلەن: ئۆز ئارا قوشنا ئىككى HR ئېلېمېنت. بۇ بىرىكمە كۇنۇپكا تەكرارلانسا يىراقتىكى فوكۇس نۇقتا رايونىغا يەتكىلى بولىدۇ.'
78 },
79 {
80 name: 'توسالغۇسىز لايىھە چۈشەندۈرۈشى',
81 legend: '${a11yHelp} نى بېسىڭ'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Escape',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'سول يا ئوق',
93 upArrow: 'ئۈستى يا ئوق',
94 rightArrow: 'ئوڭ يا ئوق',
95 downArrow: 'ئاستى يا ئوق',
96 insert: 'قىستۇر',
97 leftWindowKey: 'سول Windows كۇنۇپكىسى',
98 rightWindowKey: 'ئوڭ Windows كۇنۇپكىسى',
99 selectKey: 'تاللاش كۇنۇپكىسى',
100 numpad0: 'سان تاختا 0',
101 numpad1: 'سان تاختا 1',
102 numpad2: 'سان تاختا 2',
103 numpad3: 'سان تاختا 3',
104 numpad4: 'سان تاختا 4',
105 numpad5: 'سان تاختا 5',
106 numpad6: 'سان تاختا 6',
107 numpad7: 'سان تاختا 7',
108 numpad8: 'سان تاختا 8',
109 numpad9: 'سان تاختا 9',
110 multiply: 'يۇلتۇز كۇنۇپكىسى',
111 add: 'قوشۇش',
112 subtract: 'ئېلىش',
113 decimalPoint: 'كەسىر چېكىت',
114 divide: 'بۆلۈش',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'سان قۇلۇپ كۇنۇپكىسى',
128 scrollLock: 'سۈرگۈچ قۇلۇپ كۇنۇپكىسى',
129 semiColon: 'چېكىتلىك پەش',
130 equalSign: 'تەڭلىك بەلگىسى',
131 comma: 'پەش',
132 dash: 'سىزىقچە',
133 period: 'چېكىت',
134 forwardSlash: 'سولغا يانتۇ سىزىق',
135 graveAccent: 'ئۇرغۇ بەلگىسى',
136 openBracket: 'ئېچىلغان تىرناق',
137 backSlash: 'ئوڭغا يانتۇ سىزىق',
138 closeBracket: 'يېپىلغان تىرناق',
139 singleQuote: 'يالاڭ پەش'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/uk.js b/sources/plugins/a11yhelp/dialogs/lang/uk.js
new file mode 100644
index 0000000..d1e8589
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/uk.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'uk', {
7 title: 'Спеціальні Інструкції',
8 contents: 'Довідка. Натисніть ESC і вона зникне.',
9 legend: [
10 {
11 name: 'Основне',
12 items: [
13 {
14 name: 'Панель Редактора',
15 legend: 'Натисніть ${toolbarFocus} для переходу до панелі інструментів. Для переміщення між групами панелі інструментів використовуйте TAB і SHIFT+TAB. Для переміщення між кнопками панелі іструментів використовуйте кнопки СТРІЛКА ВПРАВО або ВЛІВО. Натисніть ПРОПУСК або ENTER для запуску кнопки панелі інструментів.'
16 },
17
18 {
19 name: 'Діалог Редактора',
20 legend:
21 'Усередині діалогу, натисніть TAB щоб перейти до наступного елементу діалогу, натисніть SHIFT+TAB щоб перейти до попереднього елемента діалогу, натисніть ENTER щоб відправити діалог, натисніть ESC щоб скасувати діалог. Коли діалогове вікно має декілька вкладок, отримати доступ до панелі вкладок як частині діалогу можна натисканням або поєднання ALT+F10 або TAB, при цьому активні елементи діалогу будуть перебиратися з урахуванням порядку табуляції. При активній панелі вкладок, перехід до наступної або попередньої вкладці здійснюється натисканням стрілки "ВПРАВО" або стрілки "ВЛЕВО" відповідно.'
22 },
23
24 {
25 name: 'Контекстне Меню Редактора',
26 legend: 'Press ${contextMenu} or APPLICATION KEY to open context-menu. Потім перейдіть до наступного пункту меню за допомогою TAB або СТРІЛКИ ВНИЗ. Натисніть ПРОПУСК або ENTER для вибору параметру меню. Відкрийте підменю поточного параметру, натиснувши ПРОПУСК або ENTER або СТРІЛКУ ВПРАВО. Перейдіть до батьківського елемента меню, натиснувши ESC або СТРІЛКУ ВЛІВО. Закрийте контекстне меню, натиснувши ESC.'
27 },
28
29 {
30 name: 'Скринька Списків Редактора',
31 legend: 'Усередині списку, перехід до наступного пункту списку виконується клавішею TAB або СТРІЛКА ВНИЗ. Перехід до попереднього елемента списку клавішею SHIFT+TAB або СТРІЛКА ВГОРУ. Натисніть ПРОПУСК або ENTER, щоб вибрати параметр списку. Натисніть клавішу ESC, щоб закрити список.'
32 },
33
34 {
35 name: 'Шлях до елемента редактора',
36 legend: 'Натисніть ${elementsPathFocus} для навігації між елементами панелі. Перейдіть до наступного елемента кнопкою TAB або СТРІЛКА ВПРАВО. Перейдіть до попереднього елемента кнопкою SHIFT+TAB або СТРІЛКА ВЛІВО. Натисніть ПРОПУСК або ENTER для вибору елемента в редакторі.'
37 }
38 ]
39 },
40 {
41 name: 'Команди',
42 items: [
43 {
44 name: 'Відмінити команду',
45 legend: 'Натисніть ${undo}'
46 },
47 {
48 name: 'Повторити',
49 legend: 'Натисніть ${redo}'
50 },
51 {
52 name: 'Жирний',
53 legend: 'Натисніть ${bold}'
54 },
55 {
56 name: 'Курсив',
57 legend: 'Натисніть ${italic}'
58 },
59 {
60 name: 'Підкреслений',
61 legend: 'Натисніть ${underline}'
62 },
63 {
64 name: 'Посилання',
65 legend: 'Натисніть ${link}'
66 },
67 {
68 name: 'Згорнути панель інструментів',
69 legend: 'Натисніть ${toolbarCollapse}'
70 },
71 {
72 name: 'Доступ до попереднього місця фокусування',
73 legend: 'Натисніть ${accessNextSpace} для доступу до найближчої недосяжної області фокусування перед кареткою, наприклад: два сусідні елементи HR. Повторіть комбінацію клавіш для досягнення віддалених областей фокусування.'
74 },
75 {
76 name: 'Доступ до наступного місця фокусування',
77 legend: 'Натисніть ${accessNextSpace} для доступу до найближчої недосяжної області фокусування після каретки, наприклад: два сусідні елементи HR. Повторіть комбінацію клавіш для досягнення віддалених областей фокусування.'
78 },
79 {
80 name: 'Допомога з доступності',
81 legend: 'Натисніть ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Esc',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: 'Ліва стрілка',
93 upArrow: 'Стрілка вгору',
94 rightArrow: 'Права стрілка',
95 downArrow: 'Стрілка вниз',
96 insert: 'Вставити',
97 leftWindowKey: 'Ліва клавіша Windows',
98 rightWindowKey: 'Права клавіша Windows',
99 selectKey: 'Виберіть клавішу',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: 'Множення',
111 add: 'Додати',
112 subtract: 'Віднімання',
113 decimalPoint: 'Десяткова кома',
114 divide: 'Ділення',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Крапка з комою',
130 equalSign: 'Знак рівності',
131 comma: 'Кома',
132 dash: 'Тире',
133 period: 'Період',
134 forwardSlash: 'Коса риска',
135 graveAccent: 'Гравіс',
136 openBracket: 'Відкрити дужку',
137 backSlash: 'Зворотна коса риска',
138 closeBracket: 'Закрити дужку',
139 singleQuote: 'Одинарні лапки'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/vi.js b/sources/plugins/a11yhelp/dialogs/lang/vi.js
new file mode 100644
index 0000000..497deb2
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/vi.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'vi', {
7 title: 'Hướng dẫn trợ năng',
8 contents: 'Nội dung Hỗ trợ. Nhấn ESC để đóng hộp thoại.',
9 legend: [
10 {
11 name: 'Chung',
12 items: [
13 {
14 name: 'Thanh công cụ soạn thảo',
15 legend: 'Nhấn ${toolbarFocus} để điều hướng đến thanh công cụ. Nhấn TAB và SHIFT+TAB để chuyển đến nhóm thanh công cụ khác. Nhấn MŨI TÊN PHẢI hoặc MŨI TÊN TRÁI để chuyển sang nút khác trên thanh công cụ. Nhấn PHÍM CÁCH hoặc ENTER để kích hoạt nút trên thanh công cụ.'
16 },
17
18 {
19 name: 'Hộp thoại Biên t',
20 legend:
21 'Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively.' // MISSING
22 },
23
24 {
25 name: 'Trình đơn Ngữ cảnh cBộ soạn thảo',
26 legend: 'Nhấn ${contextMenu} hoặc PHÍM ỨNG DỤNG để mở thực đơn ngữ cảnh. Sau đó nhấn TAB hoặc MŨI TÊN XUỐNG để di chuyển đến tuỳ chọn tiếp theo của thực đơn. Nhấn SHIFT+TAB hoặc MŨI TÊN LÊN để quay lại tuỳ chọn trước. Nhấn DẤU CÁCH hoặc ENTER để chọn tuỳ chọn của thực đơn. Nhấn DẤU CÁCH hoặc ENTER hoặc MŨI TÊN SANG PHẢI để mở thực đơn con của tuỳ chọn hiện tại. Nhấn ESC hoặc MŨI TÊN SANG TRÁI để quay trở lại thực đơn gốc. Nhấn ESC để đóng thực đơn ngữ cảnh.'
27 },
28
29 {
30 name: 'Hộp danh sách trình biên tập',
31 legend: 'Trong một danh sách chọn, di chuyển đối tượng tiếp theo với phím TAB hoặc phím mũi tên hướng xuống. Di chuyển đến đối tượng trước đó bằng cách nhấn tổ hợp phím SHIFT+TAB hoặc mũi tên hướng lên. Phím khoảng cách hoặc phím ENTER để chọn các tùy chọn trong danh sách. Nhấn phím ESC để đóng lại danh sách chọn.'
32 },
33
34 {
35 name: 'Thanh đường dẫn các đối tượng',
36 legend: 'Nhấn ${elementsPathFocus} để điều hướng các đối tượng trong thanh đường dẫn. Di chuyển đến đối tượng tiếp theo bằng phím TAB hoặc phím mũi tên bên phải. Di chuyển đến đối tượng trước đó bằng tổ hợp phím SHIFT+TAB hoặc phím mũi tên bên trái. Nhấn phím khoảng cách hoặc ENTER để chọn đối tượng trong trình soạn thảo.'
37 }
38 ]
39 },
40 {
41 name: 'Lệnh',
42 items: [
43 {
44 name: 'Làm lại lện',
45 legend: 'Ấn ${undo}'
46 },
47 {
48 name: 'Làm lại lệnh',
49 legend: 'Ấn ${redo}'
50 },
51 {
52 name: 'Lệnh in đậm',
53 legend: 'Ấn ${bold}'
54 },
55 {
56 name: 'Lệnh in nghiêng',
57 legend: 'Ấn ${italic}'
58 },
59 {
60 name: 'Lệnh gạch dưới',
61 legend: 'Ấn ${underline}'
62 },
63 {
64 name: 'Lệnh liên kết',
65 legend: 'Nhấn ${link}'
66 },
67 {
68 name: 'Lệnh hiển thị thanh công cụ',
69 legend: 'Nhấn${toolbarCollapse}'
70 },
71 {
72 name: 'Truy cập đến lệnh tập trung vào khoảng cách trước đó',
73 legend: 'Ấn ${accessPreviousSpace} để truy cập đến phần tập trung khoảng cách sau phần còn sót lại của khoảng cách gần nhất vốn không tác động đến được , thí dụ: hai yếu tố điều chỉnh HR. Lặp lại các phím kết họep này để vươn đến phần khoảng cách.'
74 },
75 {
76 name: 'Truy cập phần đối tượng lệnh khoảng trống',
77 legend: 'Ấn ${accessNextSpace} để truy cập đến phần tập trung khoảng cách sau phần còn sót lại của khoảng cách gần nhất vốn không tác động đến được , thí dụ: hai yếu tố điều chỉnh HR. Lặp lại các phím kết họep này để vươn đến phần khoảng cách.'
78 },
79 {
80 name: 'Trợ giúp liên quan',
81 legend: 'Nhấn ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Phím Tab',
87 pause: 'Phím Pause',
88 capslock: 'Phím Caps Lock',
89 escape: 'Phím Escape',
90 pageUp: 'Phím Page Up',
91 pageDown: 'Phím Page Down',
92 leftArrow: 'Phím Left Arrow',
93 upArrow: 'Phím Up Arrow',
94 rightArrow: 'Phím Right Arrow',
95 downArrow: 'Phím Down Arrow',
96 insert: 'Chèn',
97 leftWindowKey: 'Phím Left Windows',
98 rightWindowKey: 'Phím Right Windows ',
99 selectKey: 'Chọn phím',
100 numpad0: 'Phím 0',
101 numpad1: 'Phím 1',
102 numpad2: 'Phím 2',
103 numpad3: 'Phím 3',
104 numpad4: 'Phím 4',
105 numpad5: 'Phím 5',
106 numpad6: 'Phím 6',
107 numpad7: 'Phím 7',
108 numpad8: 'Phím 8',
109 numpad9: 'Phím 9',
110 multiply: 'Nhân',
111 add: 'Thêm',
112 subtract: 'Trừ',
113 decimalPoint: 'Điểm số thập phân',
114 divide: 'Chia',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: 'Dấu chấm phẩy',
130 equalSign: 'Đăng nhập bằng',
131 comma: 'Dấu phẩy',
132 dash: 'Dấu gạch ngang',
133 period: 'Phím .',
134 forwardSlash: 'Phím /',
135 graveAccent: 'Phím `',
136 openBracket: 'Open Bracket',
137 backSlash: 'Dấu gạch chéo ngược',
138 closeBracket: 'Gần giá đỡ',
139 singleQuote: 'Trích dẫn'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js b/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js
new file mode 100644
index 0000000..d2d0f2b
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'zh-cn', {
7 title: '辅助功能说明',
8 contents: '帮助内容。要关闭此对话框请按 ESC 键。',
9 legend: [
10 {
11 name: '常规',
12 items: [
13 {
14 name: '编辑器工具栏',
15 legend: '按 ${toolbarFocus} 切换到工具栏,使用 TAB 键和 SHIFT+TAB 组合键移动到上一个和下一个工具栏组。使用左右箭头键移动到上一个或下一个工具栏按钮。按空格键或回车键以选中工具栏按钮。'
16 },
17
18 {
19 name: '编辑器对话框',
20 legend:
21 '在对话框内,按 TAB 键移动到下一个字段,按 SHIFT + TAB 组合键移动到上一个字段,按 ENTER 键提交对话框,按 ESC 键取消对话框。对于有多选项卡的对话框,可以按 ALT + F10 直接切换到或者按 TAB 键逐步移到选项卡列表,当焦点移到选项卡列表时可以用左右箭头键来移动到前后的选项卡。'
22 },
23
24 {
25 name: '编辑器上下文菜单',
26 legend: '用 ${contextMenu} 或者“应用程序键”打开上下文菜单。然后用 TAB 键或者下箭头键来移动到下一个菜单项;SHIFT + TAB 组合键或者上箭头键移动到上一个菜单项。用 SPACE 键或者 ENTER 键选择菜单项。用 SPACE 键,ENTER 键或者右箭头键打开子菜单。返回菜单用 ESC 键或者左箭头键。用 ESC 键关闭上下文菜单。'
27 },
28
29 {
30 name: '编辑器列表框',
31 legend: '在列表框中,移到下一列表项用 TAB 键或者下箭头键。移到上一列表项用SHIFT+TAB 组合键或者上箭头键,用 SPACE 键或者 ENTER 键选择列表项。用 ESC 键收起列表框。'
32 },
33
34 {
35 name: '编辑器元素路径栏',
36 legend: '按 ${elementsPathFocus} 以导航到元素路径栏,使用 TAB 键或右箭头键选择下一个元素,使用 SHIFT+TAB 组合键或左箭头键选择上一个元素,按空格键或回车键以选定编辑器里的元素。'
37 }
38 ]
39 },
40 {
41 name: '命令',
42 items: [
43 {
44 name: ' 撤消命令',
45 legend: '按 ${undo}'
46 },
47 {
48 name: ' 重做命令',
49 legend: '按 ${redo}'
50 },
51 {
52 name: ' 加粗命令',
53 legend: '按 ${bold}'
54 },
55 {
56 name: ' 倾斜命令',
57 legend: '按 ${italic}'
58 },
59 {
60 name: ' 下划线命令',
61 legend: '按 ${underline}'
62 },
63 {
64 name: ' 链接命令',
65 legend: '按 ${link}'
66 },
67 {
68 name: ' 工具栏折叠命令',
69 legend: '按 ${toolbarCollapse}'
70 },
71 {
72 name: '访问前一个焦点区域的命令',
73 legend: '按 ${accessPreviousSpace} 访问^符号前最近的不可访问的焦点区域,例如:两个相邻的 HR 元素。重复此组合按键可以到达远处的焦点区域。'
74 },
75 {
76 name: '访问下一个焦点区域命令',
77 legend: '按 ${accessNextSpace} 以访问^符号后最近的不可访问的焦点区域。例如:两个相邻的 HR 元素。重复此组合按键可以到达远处的焦点区域。'
78 },
79 {
80 name: '辅助功能帮助',
81 legend: '按 ${a11yHelp}'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab 键',
87 pause: '暂停键',
88 capslock: '大写锁定键',
89 escape: 'Esc 键',
90 pageUp: '上翻页键',
91 pageDown: '下翻页键',
92 leftArrow: '向左箭头键',
93 upArrow: '向上箭头键',
94 rightArrow: '向右箭头键',
95 downArrow: '向下箭头键',
96 insert: '插入键',
97 leftWindowKey: '左 WIN 键',
98 rightWindowKey: '右 WIN 键',
99 selectKey: '选择键',
100 numpad0: '小键盘 0 键',
101 numpad1: '小键盘 1 键',
102 numpad2: '小键盘 2 键',
103 numpad3: '小键盘 3 键',
104 numpad4: '小键盘 4 键',
105 numpad5: '小键盘 5 键',
106 numpad6: '小键盘 6 键',
107 numpad7: '小键盘 7 键',
108 numpad8: '小键盘 8 键',
109 numpad9: '小键盘 9 键',
110 multiply: '星号键',
111 add: '加号键',
112 subtract: '减号键',
113 decimalPoint: '小数点键',
114 divide: '除号键',
115 f1: 'F1 键',
116 f2: 'F2 键',
117 f3: 'F3 键',
118 f4: 'F4 键',
119 f5: 'F5 键',
120 f6: 'F6 键',
121 f7: 'F7 键',
122 f8: 'F8 键',
123 f9: 'F9 键',
124 f10: 'F10 键',
125 f11: 'F11 键',
126 f12: 'F12 键',
127 numLock: '数字锁定键',
128 scrollLock: '滚动锁定键',
129 semiColon: '分号键',
130 equalSign: '等号键',
131 comma: '逗号键',
132 dash: '短划线键',
133 period: '句号键',
134 forwardSlash: '斜杠键',
135 graveAccent: '重音符键',
136 openBracket: '左中括号键',
137 backSlash: '反斜杠键',
138 closeBracket: '右中括号键',
139 singleQuote: '单引号键'
140} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/zh.js b/sources/plugins/a11yhelp/dialogs/lang/zh.js
new file mode 100644
index 0000000..0fe1310
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/zh.js
@@ -0,0 +1,140 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'a11yhelp', 'zh', {
7 title: '輔助工具指南',
8 contents: '說明內容。若要關閉此對話框請按「ESC」。',
9 legend: [
10 {
11 name: '一般',
12 items: [
13 {
14 name: '編輯器工具列',
15 legend: '請按 ${toolbarFocus} 以導覽到工具列。利用 TAB 或 SHIFT+TAB 以便移動到下一個及前一個工具列群組。利用右方向鍵或左方向鍵以便移動到下一個及上一個工具列按鈕。按下空白鍵或 ENTER 鍵啟用工具列按鈕。'
16 },
17
18 {
19 name: '編輯器對話方塊',
20 legend:
21 '在對話框中,按下 TAB 鍵以導覽到下一個對話框元素,按下 SHIFT+TAB 以移動到上一個對話框元素,按下 ENTER 以遞交對話框,按下 ESC 以取消對話框。當對話框有多個分頁時,可以使用 ALT+F10 或是在對話框分頁順序中的一部份按下 TAB 以使用分頁列表。焦點在分頁列表上時,分別使用右方向鍵及左方向鍵移動到下一個及上一個分頁。'
22 },
23
24 {
25 name: '編輯器內容功能表',
26 legend: '請按下「${contextMenu}」或是「應用程式鍵」以開啟內容選單。以「TAB」或是「↓」鍵移動到下一個選單選項。以「SHIFT + TAB」或是「↑」鍵移動到上一個選單選項。按下「空白鍵」或是「ENTER」鍵以選取選單選項。以「空白鍵」或「ENTER」或「→」開啟目前選項之子選單。以「ESC」或「←」回到父選單。以「ESC」鍵關閉內容選單」。'
27 },
28
29 {
30 name: '編輯器清單方塊',
31 legend: '在清單方塊中,使用 TAB 或下方向鍵移動到下一個列表項目。使用 SHIFT+TAB 或上方向鍵移動到上一個列表項目。按下空白鍵或 ENTER 以選取列表選項。按下 ESC 以關閉清單方塊。'
32 },
33
34 {
35 name: '編輯器元件路徑工具列',
36 legend: '請按 ${elementsPathFocus} 以瀏覽元素路徑列。利用 TAB 或右方向鍵以便移動到下一個元素按鈕。利用 SHIFT 或左方向鍵以便移動到上一個按鈕。按下空白鍵或 ENTER 鍵來選取在編輯器中的元素。'
37 }
38 ]
39 },
40 {
41 name: '命令',
42 items: [
43 {
44 name: '復原命令',
45 legend: '請按下「${undo}」'
46 },
47 {
48 name: '重複命令',
49 legend: '請按下「 ${redo}」'
50 },
51 {
52 name: '粗體命令',
53 legend: '請按下「${bold}」'
54 },
55 {
56 name: '斜體',
57 legend: '請按下「${italic}」'
58 },
59 {
60 name: '底線命令',
61 legend: '請按下「${underline}」'
62 },
63 {
64 name: '連結',
65 legend: '請按下「${link}」'
66 },
67 {
68 name: '隱藏工具列',
69 legend: '請按下「${toolbarCollapse}」'
70 },
71 {
72 name: '存取前一個焦點空間命令',
73 legend: '請按下 ${accessPreviousSpace} 以存取最近但無法靠近之插字符號前的焦點空間。舉例:二個相鄰的 HR 元素。\r\n重複按鍵以存取較遠的焦點空間。'
74 },
75 {
76 name: '存取下一個焦點空間命令',
77 legend: '請按下 ${accessNextSpace} 以存取最近但無法靠近之插字符號後的焦點空間。舉例:二個相鄰的 HR 元素。\r\n重複按鍵以存取較遠的焦點空間。'
78 },
79 {
80 name: '協助工具說明',
81 legend: '請按下「${a11yHelp}」'
82 }
83 ]
84 }
85 ],
86 tab: 'Tab',
87 pause: 'Pause',
88 capslock: 'Caps Lock',
89 escape: 'Esc',
90 pageUp: 'Page Up',
91 pageDown: 'Page Down',
92 leftArrow: '向左箭號',
93 upArrow: '向上鍵號',
94 rightArrow: '向右鍵號',
95 downArrow: '向下鍵號',
96 insert: '插入',
97 leftWindowKey: '左方 Windows 鍵',
98 rightWindowKey: '右方 Windows 鍵',
99 selectKey: '選擇鍵',
100 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8',
109 numpad9: 'Numpad 9',
110 multiply: '乘號',
111 add: '新增',
112 subtract: '減號',
113 decimalPoint: '小數點',
114 divide: '除號',
115 f1: 'F1',
116 f2: 'F2',
117 f3: 'F3',
118 f4: 'F4',
119 f5: 'F5',
120 f6: 'F6',
121 f7: 'F7',
122 f8: 'F8',
123 f9: 'F9',
124 f10: 'F10',
125 f11: 'F11',
126 f12: 'F12',
127 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock',
129 semiColon: '分號',
130 equalSign: '等號',
131 comma: '逗號',
132 dash: '虛線',
133 period: '句點',
134 forwardSlash: '斜線',
135 graveAccent: '抑音符號',
136 openBracket: '左方括號',
137 backSlash: '反斜線',
138 closeBracket: '右方括號',
139 singleQuote: '單引號'
140} );
diff --git a/sources/plugins/a11yhelp/plugin.js b/sources/plugins/a11yhelp/plugin.js
new file mode 100644
index 0000000..9e2925a
--- /dev/null
+++ b/sources/plugins/a11yhelp/plugin.js
@@ -0,0 +1,51 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Plugin definition for the a11yhelp, which provides a dialog
8 * with accessibility related help.
9 */
10
11( function() {
12 var pluginName = 'a11yhelp',
13 commandName = 'a11yHelp';
14
15 CKEDITOR.plugins.add( pluginName, {
16 requires: 'dialog',
17
18 // List of available localizations.
19 // jscs:disable
20 availableLangs: { af:1,ar:1,az:1,bg:1,ca:1,cs:1,cy:1,da:1,de:1,'de-ch':1,el:1,en:1,'en-gb':1,eo:1,es:1,et:1,eu:1,fa:1,fi:1,fo:1,fr:1,'fr-ca':1,gl:1,gu:1,he:1,hi:1,hr:1,hu:1,id:1,it:1,ja:1,km:1,ko:1,ku:1,lt:1,lv:1,mk:1,mn:1,nb:1,nl:1,no:1,oc:1,pl:1,pt:1,'pt-br':1,ro:1,ru:1,si:1,sk:1,sl:1,sq:1,sr:1,'sr-latn':1,sv:1,th:1,tr:1,tt:1,ug:1,uk:1,vi:1,zh:1,'zh-cn':1 },
21 // jscs:enable
22
23 init: function( editor ) {
24 var plugin = this;
25 editor.addCommand( commandName, {
26 exec: function() {
27 var langCode = editor.langCode;
28 langCode =
29 plugin.availableLangs[ langCode ] ? langCode :
30 plugin.availableLangs[ langCode.replace( /-.*/, '' ) ] ? langCode.replace( /-.*/, '' ) :
31 'en';
32
33 CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( plugin.path + 'dialogs/lang/' + langCode + '.js' ), function() {
34 editor.lang.a11yhelp = plugin.langEntries[ langCode ];
35 editor.openDialog( commandName );
36 } );
37 },
38 modes: { wysiwyg: 1, source: 1 },
39 readOnly: 1,
40 canUndo: false
41 } );
42
43 editor.setKeystroke( CKEDITOR.ALT + 48 /*0*/, 'a11yHelp' );
44 CKEDITOR.dialog.add( commandName, this.path + 'dialogs/a11yhelp.js' );
45
46 editor.on( 'ariaEditorHelpLabel', function( evt ) {
47 evt.data.label = editor.lang.common.editorHelp;
48 } );
49 }
50 } );
51} )();
diff --git a/sources/plugins/basicstyles/icons/bold.png b/sources/plugins/basicstyles/icons/bold.png
new file mode 100644
index 0000000..d714916
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/bold.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/hidpi/bold.png b/sources/plugins/basicstyles/icons/hidpi/bold.png
new file mode 100644
index 0000000..2de207d
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/hidpi/bold.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/hidpi/italic.png b/sources/plugins/basicstyles/icons/hidpi/italic.png
new file mode 100644
index 0000000..2c2dae4
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/hidpi/italic.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/hidpi/strike.png b/sources/plugins/basicstyles/icons/hidpi/strike.png
new file mode 100644
index 0000000..19c5e22
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/hidpi/strike.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/hidpi/subscript.png b/sources/plugins/basicstyles/icons/hidpi/subscript.png
new file mode 100644
index 0000000..585d59b
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/hidpi/subscript.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/hidpi/superscript.png b/sources/plugins/basicstyles/icons/hidpi/superscript.png
new file mode 100644
index 0000000..9daa12a
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/hidpi/superscript.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/hidpi/underline.png b/sources/plugins/basicstyles/icons/hidpi/underline.png
new file mode 100644
index 0000000..6653814
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/hidpi/underline.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/italic.png b/sources/plugins/basicstyles/icons/italic.png
new file mode 100644
index 0000000..5f8aaae
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/italic.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/strike.png b/sources/plugins/basicstyles/icons/strike.png
new file mode 100644
index 0000000..5842b7a
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/strike.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/subscript.png b/sources/plugins/basicstyles/icons/subscript.png
new file mode 100644
index 0000000..db11f78
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/subscript.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/superscript.png b/sources/plugins/basicstyles/icons/superscript.png
new file mode 100644
index 0000000..3df28d2
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/superscript.png
Binary files differ
diff --git a/sources/plugins/basicstyles/icons/underline.png b/sources/plugins/basicstyles/icons/underline.png
new file mode 100644
index 0000000..160be92
--- /dev/null
+++ b/sources/plugins/basicstyles/icons/underline.png
Binary files differ
diff --git a/sources/plugins/basicstyles/lang/af.js b/sources/plugins/basicstyles/lang/af.js
new file mode 100644
index 0000000..bcceb14
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/af.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'af', {
6 bold: 'Vet',
7 italic: 'Skuins',
8 strike: 'Deurgestreep',
9 subscript: 'Onderskrif',
10 superscript: 'Bo-skrif',
11 underline: 'Onderstreep'
12} );
diff --git a/sources/plugins/basicstyles/lang/ar.js b/sources/plugins/basicstyles/lang/ar.js
new file mode 100644
index 0000000..fb4adc6
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ar.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ar', {
6 bold: 'عريض',
7 italic: 'مائل',
8 strike: 'يتوسطه خط',
9 subscript: 'منخفض',
10 superscript: 'مرتفع',
11 underline: 'تسطير'
12} );
diff --git a/sources/plugins/basicstyles/lang/az.js b/sources/plugins/basicstyles/lang/az.js
new file mode 100644
index 0000000..097a1ec
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/az.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'az', {
6 bold: 'Qalın',
7 italic: 'Kursiv',
8 strike: 'Üstüxətli',
9 subscript: 'Aşağı indeks',
10 superscript: 'Yuxarı indeks',
11 underline: 'Altdan xətt'
12} );
diff --git a/sources/plugins/basicstyles/lang/bg.js b/sources/plugins/basicstyles/lang/bg.js
new file mode 100644
index 0000000..56f6f7d
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/bg.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'bg', {
6 bold: 'Удебелен',
7 italic: 'Наклонен',
8 strike: 'Зачертан текст',
9 subscript: 'Индексиран текст',
10 superscript: 'Суперскрипт',
11 underline: 'Подчертан'
12} );
diff --git a/sources/plugins/basicstyles/lang/bn.js b/sources/plugins/basicstyles/lang/bn.js
new file mode 100644
index 0000000..fd790a4
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/bn.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'bn', {
6 bold: 'বোল্ড',
7 italic: 'বাঁকা',
8 strike: 'স্ট্রাইক থ্রু',
9 subscript: 'অধোলেখ',
10 superscript: 'অভিলেখ',
11 underline: 'আন্ডারলাইন'
12} );
diff --git a/sources/plugins/basicstyles/lang/bs.js b/sources/plugins/basicstyles/lang/bs.js
new file mode 100644
index 0000000..9188f98
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/bs.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'bs', {
6 bold: 'Boldiraj',
7 italic: 'Ukosi',
8 strike: 'Precrtaj',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Podvuci'
12} );
diff --git a/sources/plugins/basicstyles/lang/ca.js b/sources/plugins/basicstyles/lang/ca.js
new file mode 100644
index 0000000..2924d1e
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ca.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ca', {
6 bold: 'Negreta',
7 italic: 'Cursiva',
8 strike: 'Ratllat',
9 subscript: 'Subíndex',
10 superscript: 'Superíndex',
11 underline: 'Subratllat'
12} );
diff --git a/sources/plugins/basicstyles/lang/cs.js b/sources/plugins/basicstyles/lang/cs.js
new file mode 100644
index 0000000..737c648
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/cs.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'cs', {
6 bold: 'Tučné',
7 italic: 'Kurzíva',
8 strike: 'Přeškrtnuté',
9 subscript: 'Dolní index',
10 superscript: 'Horní index',
11 underline: 'Podtržené'
12} );
diff --git a/sources/plugins/basicstyles/lang/cy.js b/sources/plugins/basicstyles/lang/cy.js
new file mode 100644
index 0000000..3acb736
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/cy.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'cy', {
6 bold: 'Bras',
7 italic: 'Italig',
8 strike: 'Llinell Trwyddo',
9 subscript: 'Is-sgript',
10 superscript: 'Uwchsgript',
11 underline: 'Tanlinellu'
12} );
diff --git a/sources/plugins/basicstyles/lang/da.js b/sources/plugins/basicstyles/lang/da.js
new file mode 100644
index 0000000..0b1f3e8
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/da.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'da', {
6 bold: 'Fed',
7 italic: 'Kursiv',
8 strike: 'Gennemstreget',
9 subscript: 'Sænket skrift',
10 superscript: 'Hævet skrift',
11 underline: 'Understreget'
12} );
diff --git a/sources/plugins/basicstyles/lang/de-ch.js b/sources/plugins/basicstyles/lang/de-ch.js
new file mode 100644
index 0000000..2370c04
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/de-ch.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'de-ch', {
6 bold: 'Fett',
7 italic: 'Kursiv',
8 strike: 'Durchgestrichen',
9 subscript: 'Tiefgestellt',
10 superscript: 'Hochgestellt',
11 underline: 'Unterstrichen'
12} );
diff --git a/sources/plugins/basicstyles/lang/de.js b/sources/plugins/basicstyles/lang/de.js
new file mode 100644
index 0000000..fbc92e4
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/de.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'de', {
6 bold: 'Fett',
7 italic: 'Kursiv',
8 strike: 'Durchgestrichen',
9 subscript: 'Tiefgestellt',
10 superscript: 'Hochgestellt',
11 underline: 'Unterstrichen'
12} );
diff --git a/sources/plugins/basicstyles/lang/el.js b/sources/plugins/basicstyles/lang/el.js
new file mode 100644
index 0000000..2c72cda
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/el.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'el', {
6 bold: 'Έντονη',
7 italic: 'Πλάγια',
8 strike: 'Διακριτή Διαγραφή',
9 subscript: 'Δείκτης',
10 superscript: 'Εκθέτης',
11 underline: 'Υπογράμμιση'
12} );
diff --git a/sources/plugins/basicstyles/lang/en-au.js b/sources/plugins/basicstyles/lang/en-au.js
new file mode 100644
index 0000000..6b9dc7e
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/en-au.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'en-au', {
6 bold: 'Bold',
7 italic: 'Italic',
8 strike: 'Strike Through',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Underline'
12} );
diff --git a/sources/plugins/basicstyles/lang/en-ca.js b/sources/plugins/basicstyles/lang/en-ca.js
new file mode 100644
index 0000000..612b2b8
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/en-ca.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'en-ca', {
6 bold: 'Bold',
7 italic: 'Italic',
8 strike: 'Strike Through',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Underline'
12} );
diff --git a/sources/plugins/basicstyles/lang/en-gb.js b/sources/plugins/basicstyles/lang/en-gb.js
new file mode 100644
index 0000000..418058e
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/en-gb.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'en-gb', {
6 bold: 'Bold',
7 italic: 'Italic',
8 strike: 'Strike Through',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Underline'
12} );
diff --git a/sources/plugins/basicstyles/lang/en.js b/sources/plugins/basicstyles/lang/en.js
new file mode 100644
index 0000000..3c9bc32
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/en.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'en', {
6 bold: 'Bold',
7 italic: 'Italic',
8 strike: 'Strikethrough',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Underline'
12} );
diff --git a/sources/plugins/basicstyles/lang/eo.js b/sources/plugins/basicstyles/lang/eo.js
new file mode 100644
index 0000000..995f0c3
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/eo.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'eo', {
6 bold: 'Grasa',
7 italic: 'Kursiva',
8 strike: 'Trastreko',
9 subscript: 'Suba indico',
10 superscript: 'Supra indico',
11 underline: 'Substreko'
12} );
diff --git a/sources/plugins/basicstyles/lang/es.js b/sources/plugins/basicstyles/lang/es.js
new file mode 100644
index 0000000..baaf99f
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/es.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'es', {
6 bold: 'Negrita',
7 italic: 'Cursiva',
8 strike: 'Tachado',
9 subscript: 'Subíndice',
10 superscript: 'Superíndice',
11 underline: 'Subrayado'
12} );
diff --git a/sources/plugins/basicstyles/lang/et.js b/sources/plugins/basicstyles/lang/et.js
new file mode 100644
index 0000000..8dee05e
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/et.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'et', {
6 bold: 'Paks',
7 italic: 'Kursiiv',
8 strike: 'Läbijoonitud',
9 subscript: 'Allindeks',
10 superscript: 'Ülaindeks',
11 underline: 'Allajoonitud'
12} );
diff --git a/sources/plugins/basicstyles/lang/eu.js b/sources/plugins/basicstyles/lang/eu.js
new file mode 100644
index 0000000..7017540
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/eu.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'eu', {
6 bold: 'Lodia',
7 italic: 'Etzana',
8 strike: 'Marratua',
9 subscript: 'Azpi-indizea',
10 superscript: 'Goi-indizea',
11 underline: 'Azpimarratu'
12} );
diff --git a/sources/plugins/basicstyles/lang/fa.js b/sources/plugins/basicstyles/lang/fa.js
new file mode 100644
index 0000000..49343fb
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/fa.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'fa', {
6 bold: 'درشت',
7 italic: 'خمیده',
8 strike: 'خط‌خورده',
9 subscript: 'زیرنویس',
10 superscript: 'بالانویس',
11 underline: 'زیرخط‌دار'
12} );
diff --git a/sources/plugins/basicstyles/lang/fi.js b/sources/plugins/basicstyles/lang/fi.js
new file mode 100644
index 0000000..5e1fbce
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/fi.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'fi', {
6 bold: 'Lihavoitu',
7 italic: 'Kursivoitu',
8 strike: 'Yliviivattu',
9 subscript: 'Alaindeksi',
10 superscript: 'Yläindeksi',
11 underline: 'Alleviivattu'
12} );
diff --git a/sources/plugins/basicstyles/lang/fo.js b/sources/plugins/basicstyles/lang/fo.js
new file mode 100644
index 0000000..f48b73a
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/fo.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'fo', {
6 bold: 'Feit skrift',
7 italic: 'Skráskrift',
8 strike: 'Yvirstrikað',
9 subscript: 'Lækkað skrift',
10 superscript: 'Hækkað skrift',
11 underline: 'Undirstrikað'
12} );
diff --git a/sources/plugins/basicstyles/lang/fr-ca.js b/sources/plugins/basicstyles/lang/fr-ca.js
new file mode 100644
index 0000000..6b8ffbf
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/fr-ca.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'fr-ca', {
6 bold: 'Gras',
7 italic: 'Italique',
8 strike: 'Barré',
9 subscript: 'Indice',
10 superscript: 'Exposant',
11 underline: 'Souligné'
12} );
diff --git a/sources/plugins/basicstyles/lang/fr.js b/sources/plugins/basicstyles/lang/fr.js
new file mode 100644
index 0000000..022e438
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/fr.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'fr', {
6 bold: 'Gras',
7 italic: 'Italique',
8 strike: 'Barré',
9 subscript: 'Indice',
10 superscript: 'Exposant',
11 underline: 'Souligné'
12} );
diff --git a/sources/plugins/basicstyles/lang/gl.js b/sources/plugins/basicstyles/lang/gl.js
new file mode 100644
index 0000000..ebd5aa4
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/gl.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'gl', {
6 bold: 'Negra',
7 italic: 'Cursiva',
8 strike: 'Riscado',
9 subscript: 'Subíndice',
10 superscript: 'Superíndice',
11 underline: 'Subliñado'
12} );
diff --git a/sources/plugins/basicstyles/lang/gu.js b/sources/plugins/basicstyles/lang/gu.js
new file mode 100644
index 0000000..fc043b4
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/gu.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'gu', {
6 bold: 'બોલ્ડ/સ્પષ્ટ',
7 italic: 'ઇટેલિક, ત્રાંસા',
8 strike: 'છેકી નાખવું',
9 subscript: 'એક ચિહ્નની નીચે કરેલું બીજું ચિહ્ન',
10 superscript: 'એક ચિહ્ન ઉપર કરેલું બીજું ચિહ્ન.',
11 underline: 'અન્ડર્લાઇન, નીચે લીટી'
12} );
diff --git a/sources/plugins/basicstyles/lang/he.js b/sources/plugins/basicstyles/lang/he.js
new file mode 100644
index 0000000..16b16a4
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/he.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'he', {
6 bold: 'מודגש',
7 italic: 'נטוי',
8 strike: 'כתיב מחוק',
9 subscript: 'כתיב תחתון',
10 superscript: 'כתיב עליון',
11 underline: 'קו תחתון'
12} );
diff --git a/sources/plugins/basicstyles/lang/hi.js b/sources/plugins/basicstyles/lang/hi.js
new file mode 100644
index 0000000..2b2fcb5
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/hi.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'hi', {
6 bold: 'बोल्ड',
7 italic: 'इटैलिक',
8 strike: 'स्ट्राइक थ्रू',
9 subscript: 'अधोलेख',
10 superscript: 'अभिलेख',
11 underline: 'रेखांकण'
12} );
diff --git a/sources/plugins/basicstyles/lang/hr.js b/sources/plugins/basicstyles/lang/hr.js
new file mode 100644
index 0000000..6ddfb31
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/hr.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'hr', {
6 bold: 'Podebljaj',
7 italic: 'Ukosi',
8 strike: 'Precrtano',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Potcrtano'
12} );
diff --git a/sources/plugins/basicstyles/lang/hu.js b/sources/plugins/basicstyles/lang/hu.js
new file mode 100644
index 0000000..41d3a32
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/hu.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'hu', {
6 bold: 'Félkövér',
7 italic: 'Dőlt',
8 strike: 'Áthúzott',
9 subscript: 'Alsó index',
10 superscript: 'Felső index',
11 underline: 'Aláhúzott'
12} );
diff --git a/sources/plugins/basicstyles/lang/id.js b/sources/plugins/basicstyles/lang/id.js
new file mode 100644
index 0000000..39e916d
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/id.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'id', {
6 bold: 'Huruf Tebal',
7 italic: 'Huruf Miring',
8 strike: 'Strikethrough', // MISSING
9 subscript: 'Subscript', // MISSING
10 superscript: 'Superscript', // MISSING
11 underline: 'Garis Bawah'
12} );
diff --git a/sources/plugins/basicstyles/lang/is.js b/sources/plugins/basicstyles/lang/is.js
new file mode 100644
index 0000000..d22f80a
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/is.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'is', {
6 bold: 'Feitletrað',
7 italic: 'Skáletrað',
8 strike: 'Yfirstrikað',
9 subscript: 'Niðurskrifað',
10 superscript: 'Uppskrifað',
11 underline: 'Undirstrikað'
12} );
diff --git a/sources/plugins/basicstyles/lang/it.js b/sources/plugins/basicstyles/lang/it.js
new file mode 100644
index 0000000..12d5594
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/it.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'it', {
6 bold: 'Grassetto',
7 italic: 'Corsivo',
8 strike: 'Barrato',
9 subscript: 'Pedice',
10 superscript: 'Apice',
11 underline: 'Sottolineato'
12} );
diff --git a/sources/plugins/basicstyles/lang/ja.js b/sources/plugins/basicstyles/lang/ja.js
new file mode 100644
index 0000000..1d7ba09
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ja.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ja', {
6 bold: '太字',
7 italic: '斜体',
8 strike: '打ち消し線',
9 subscript: '下付き',
10 superscript: '上付き',
11 underline: '下線'
12} );
diff --git a/sources/plugins/basicstyles/lang/ka.js b/sources/plugins/basicstyles/lang/ka.js
new file mode 100644
index 0000000..e1ea391
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ka.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ka', {
6 bold: 'მსხვილი',
7 italic: 'დახრილი',
8 strike: 'გადახაზული',
9 subscript: 'ინდექსი',
10 superscript: 'ხარისხი',
11 underline: 'გახაზული'
12} );
diff --git a/sources/plugins/basicstyles/lang/km.js b/sources/plugins/basicstyles/lang/km.js
new file mode 100644
index 0000000..a55d004
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/km.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'km', {
6 bold: 'ដិត',
7 italic: 'ទ្រេត',
8 strike: 'គូស​បន្ទាត់​ចំ​កណ្ដាល',
9 subscript: 'អក្សរតូចក្រោម',
10 superscript: 'អក្សរតូចលើ',
11 underline: 'គូស​បន្ទាត់​ក្រោម'
12} );
diff --git a/sources/plugins/basicstyles/lang/ko.js b/sources/plugins/basicstyles/lang/ko.js
new file mode 100644
index 0000000..7a61f11
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ko.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ko', {
6 bold: '굵게',
7 italic: '기울임꼴',
8 strike: '취소선',
9 subscript: '아래 첨자',
10 superscript: '위 첨자',
11 underline: '밑줄'
12} );
diff --git a/sources/plugins/basicstyles/lang/ku.js b/sources/plugins/basicstyles/lang/ku.js
new file mode 100644
index 0000000..fa3c16d
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ku.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ku', {
6 bold: 'قەڵەو',
7 italic: 'لار',
8 strike: 'لێدان',
9 subscript: 'ژێرنووس',
10 superscript: 'سەرنووس',
11 underline: 'ژێرهێڵ'
12} );
diff --git a/sources/plugins/basicstyles/lang/lt.js b/sources/plugins/basicstyles/lang/lt.js
new file mode 100644
index 0000000..edb6949
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/lt.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'lt', {
6 bold: 'Pusjuodis',
7 italic: 'Kursyvas',
8 strike: 'Perbrauktas',
9 subscript: 'Apatinis indeksas',
10 superscript: 'Viršutinis indeksas',
11 underline: 'Pabrauktas'
12} );
diff --git a/sources/plugins/basicstyles/lang/lv.js b/sources/plugins/basicstyles/lang/lv.js
new file mode 100644
index 0000000..4efd61f
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/lv.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'lv', {
6 bold: 'Treknināts',
7 italic: 'Kursīvs',
8 strike: 'Pārsvītrots',
9 subscript: 'Apakšrakstā',
10 superscript: 'Augšrakstā',
11 underline: 'Pasvītrots'
12} );
diff --git a/sources/plugins/basicstyles/lang/mk.js b/sources/plugins/basicstyles/lang/mk.js
new file mode 100644
index 0000000..7d56475
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/mk.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'mk', {
6 bold: 'Здебелено',
7 italic: 'Накривено',
8 strike: 'Прецртано',
9 subscript: 'Долен индекс',
10 superscript: 'Горен индекс',
11 underline: 'Подвлечено'
12} );
diff --git a/sources/plugins/basicstyles/lang/mn.js b/sources/plugins/basicstyles/lang/mn.js
new file mode 100644
index 0000000..71fa4da
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/mn.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'mn', {
6 bold: 'Тод бүдүүн',
7 italic: 'Налуу',
8 strike: 'Дундуур нь зураастай болгох',
9 subscript: 'Суурь болгох',
10 superscript: 'Зэрэг болгох',
11 underline: 'Доогуур нь зураастай болгох'
12} );
diff --git a/sources/plugins/basicstyles/lang/ms.js b/sources/plugins/basicstyles/lang/ms.js
new file mode 100644
index 0000000..0fd97ee
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ms.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ms', {
6 bold: 'Bold',
7 italic: 'Italic',
8 strike: 'Strike Through',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Underline'
12} );
diff --git a/sources/plugins/basicstyles/lang/nb.js b/sources/plugins/basicstyles/lang/nb.js
new file mode 100644
index 0000000..6ab2325
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/nb.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'nb', {
6 bold: 'Fet',
7 italic: 'Kursiv',
8 strike: 'Gjennomstreking',
9 subscript: 'Senket skrift',
10 superscript: 'Hevet skrift',
11 underline: 'Understreking'
12} );
diff --git a/sources/plugins/basicstyles/lang/nl.js b/sources/plugins/basicstyles/lang/nl.js
new file mode 100644
index 0000000..b2ddb86
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/nl.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'nl', {
6 bold: 'Vet',
7 italic: 'Cursief',
8 strike: 'Doorhalen',
9 subscript: 'Subscript',
10 superscript: 'Superscript',
11 underline: 'Onderstrepen'
12} );
diff --git a/sources/plugins/basicstyles/lang/no.js b/sources/plugins/basicstyles/lang/no.js
new file mode 100644
index 0000000..9fdcf1b
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/no.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'no', {
6 bold: 'Fet',
7 italic: 'Kursiv',
8 strike: 'Gjennomstreking',
9 subscript: 'Senket skrift',
10 superscript: 'Hevet skrift',
11 underline: 'Understreking'
12} );
diff --git a/sources/plugins/basicstyles/lang/oc.js b/sources/plugins/basicstyles/lang/oc.js
new file mode 100644
index 0000000..56d7df0
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/oc.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'oc', {
6 bold: 'Gras',
7 italic: 'Italica',
8 strike: 'Raiat',
9 subscript: 'Indici',
10 superscript: 'Exponent',
11 underline: 'Solinhat'
12} );
diff --git a/sources/plugins/basicstyles/lang/pl.js b/sources/plugins/basicstyles/lang/pl.js
new file mode 100644
index 0000000..5739141
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/pl.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'pl', {
6 bold: 'Pogrubienie',
7 italic: 'Kursywa',
8 strike: 'Przekreślenie',
9 subscript: 'Indeks dolny',
10 superscript: 'Indeks górny',
11 underline: 'Podkreślenie'
12} );
diff --git a/sources/plugins/basicstyles/lang/pt-br.js b/sources/plugins/basicstyles/lang/pt-br.js
new file mode 100644
index 0000000..b1bbd20
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/pt-br.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'pt-br', {
6 bold: 'Negrito',
7 italic: 'Itálico',
8 strike: 'Tachado',
9 subscript: 'Subscrito',
10 superscript: 'Sobrescrito',
11 underline: 'Sublinhado'
12} );
diff --git a/sources/plugins/basicstyles/lang/pt.js b/sources/plugins/basicstyles/lang/pt.js
new file mode 100644
index 0000000..7421106
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/pt.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'pt', {
6 bold: 'Negrito',
7 italic: 'Itálico',
8 strike: 'Rasurado',
9 subscript: 'Superior à linha',
10 superscript: 'Superior à linha',
11 underline: 'Sublinhado'
12} );
diff --git a/sources/plugins/basicstyles/lang/ro.js b/sources/plugins/basicstyles/lang/ro.js
new file mode 100644
index 0000000..e760a45
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ro.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ro', {
6 bold: 'Îngroşat (bold)',
7 italic: 'Înclinat (italic)',
8 strike: 'Tăiat (strike through)',
9 subscript: 'Indice (subscript)',
10 superscript: 'Putere (superscript)',
11 underline: 'Subliniat (underline)'
12} );
diff --git a/sources/plugins/basicstyles/lang/ru.js b/sources/plugins/basicstyles/lang/ru.js
new file mode 100644
index 0000000..0a38898
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ru.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ru', {
6 bold: 'Полужирный',
7 italic: 'Курсив',
8 strike: 'Зачеркнутый',
9 subscript: 'Подстрочный индекс',
10 superscript: 'Надстрочный индекс',
11 underline: 'Подчеркнутый'
12} );
diff --git a/sources/plugins/basicstyles/lang/si.js b/sources/plugins/basicstyles/lang/si.js
new file mode 100644
index 0000000..58b5a45
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/si.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'si', {
6 bold: 'තද අකුරින් ලියනලද',
7 italic: 'බැධීඅකුරින් ලියන ලද',
8 strike: 'Strikethrough', // MISSING
9 subscript: 'Subscript', // MISSING
10 superscript: 'Superscript', // MISSING
11 underline: 'යටින් ඉරි අදින ලද'
12} );
diff --git a/sources/plugins/basicstyles/lang/sk.js b/sources/plugins/basicstyles/lang/sk.js
new file mode 100644
index 0000000..42e351d
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/sk.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'sk', {
6 bold: 'Tučné',
7 italic: 'Kurzíva',
8 strike: 'Prečiarknuté',
9 subscript: 'Dolný index',
10 superscript: 'Horný index',
11 underline: 'Podčiarknuté'
12} );
diff --git a/sources/plugins/basicstyles/lang/sl.js b/sources/plugins/basicstyles/lang/sl.js
new file mode 100644
index 0000000..3ccb5ba
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/sl.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'sl', {
6 bold: 'Krepko',
7 italic: 'Ležeče',
8 strike: 'Prečrtano',
9 subscript: 'Podpisano',
10 superscript: 'Nadpisano',
11 underline: 'Podčrtano'
12} );
diff --git a/sources/plugins/basicstyles/lang/sq.js b/sources/plugins/basicstyles/lang/sq.js
new file mode 100644
index 0000000..5c6d704
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/sq.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'sq', {
6 bold: 'Trash',
7 italic: 'Pjerrët',
8 strike: 'Nëpërmes',
9 subscript: 'Nën-skriptë',
10 superscript: 'Super-skriptë',
11 underline: 'Nënvijëzuar'
12} );
diff --git a/sources/plugins/basicstyles/lang/sr-latn.js b/sources/plugins/basicstyles/lang/sr-latn.js
new file mode 100644
index 0000000..535dd50
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/sr-latn.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'sr-latn', {
6 bold: 'Podebljano',
7 italic: 'Kurziv',
8 strike: 'Precrtano',
9 subscript: 'Indeks',
10 superscript: 'Stepen',
11 underline: 'Podvučeno'
12} );
diff --git a/sources/plugins/basicstyles/lang/sr.js b/sources/plugins/basicstyles/lang/sr.js
new file mode 100644
index 0000000..2e7564e
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/sr.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'sr', {
6 bold: 'Подебљано',
7 italic: 'Курзив',
8 strike: 'Прецртано',
9 subscript: 'Индекс',
10 superscript: 'Степен',
11 underline: 'Подвучено'
12} );
diff --git a/sources/plugins/basicstyles/lang/sv.js b/sources/plugins/basicstyles/lang/sv.js
new file mode 100644
index 0000000..efa20a8
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/sv.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'sv', {
6 bold: 'Fet',
7 italic: 'Kursiv',
8 strike: 'Genomstruken',
9 subscript: 'Nedsänkta tecken',
10 superscript: 'Upphöjda tecken',
11 underline: 'Understruken'
12} );
diff --git a/sources/plugins/basicstyles/lang/th.js b/sources/plugins/basicstyles/lang/th.js
new file mode 100644
index 0000000..82cab00
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/th.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'th', {
6 bold: 'ตัวหนา',
7 italic: 'ตัวเอียง',
8 strike: 'ตัวขีดเส้นทับ',
9 subscript: 'ตัวห้อย',
10 superscript: 'ตัวยก',
11 underline: 'ตัวขีดเส้นใต้'
12} );
diff --git a/sources/plugins/basicstyles/lang/tr.js b/sources/plugins/basicstyles/lang/tr.js
new file mode 100644
index 0000000..0e36c82
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/tr.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'tr', {
6 bold: 'Kalın',
7 italic: 'İtalik',
8 strike: 'Üstü Çizgili',
9 subscript: 'Alt Simge',
10 superscript: 'Üst Simge',
11 underline: 'Altı Çizgili'
12} );
diff --git a/sources/plugins/basicstyles/lang/tt.js b/sources/plugins/basicstyles/lang/tt.js
new file mode 100644
index 0000000..c8da547
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/tt.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'tt', {
6 bold: 'Калын',
7 italic: 'Курсив',
8 strike: 'Сызылган',
9 subscript: 'Аскы индекс',
10 superscript: 'Өске индекс',
11 underline: 'Астына сызылган'
12} );
diff --git a/sources/plugins/basicstyles/lang/ug.js b/sources/plugins/basicstyles/lang/ug.js
new file mode 100644
index 0000000..aa28429
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/ug.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'ug', {
6 bold: 'توم',
7 italic: 'يانتۇ',
8 strike: 'ئۆچۈرۈش سىزىقى',
9 subscript: 'تۆۋەن ئىندېكس',
10 superscript: 'يۇقىرى ئىندېكس',
11 underline: 'ئاستى سىزىق'
12} );
diff --git a/sources/plugins/basicstyles/lang/uk.js b/sources/plugins/basicstyles/lang/uk.js
new file mode 100644
index 0000000..3ec1acc
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/uk.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'uk', {
6 bold: 'Жирний',
7 italic: 'Курсив',
8 strike: 'Закреслений',
9 subscript: 'Нижній індекс',
10 superscript: 'Верхній індекс',
11 underline: 'Підкреслений'
12} );
diff --git a/sources/plugins/basicstyles/lang/vi.js b/sources/plugins/basicstyles/lang/vi.js
new file mode 100644
index 0000000..c0aaa69
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/vi.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'vi', {
6 bold: 'Đậm',
7 italic: 'Nghiêng',
8 strike: 'Gạch xuyên ngang',
9 subscript: 'Chỉ số dưới',
10 superscript: 'Chỉ số trên',
11 underline: 'Gạch chân'
12} );
diff --git a/sources/plugins/basicstyles/lang/zh-cn.js b/sources/plugins/basicstyles/lang/zh-cn.js
new file mode 100644
index 0000000..f43d23d
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/zh-cn.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'zh-cn', {
6 bold: '加粗',
7 italic: '倾斜',
8 strike: '删除线',
9 subscript: '下标',
10 superscript: '上标',
11 underline: '下划线'
12} );
diff --git a/sources/plugins/basicstyles/lang/zh.js b/sources/plugins/basicstyles/lang/zh.js
new file mode 100644
index 0000000..d74943c
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/zh.js
@@ -0,0 +1,12 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'zh', {
6 bold: '粗體',
7 italic: '斜體',
8 strike: '刪除線',
9 subscript: '下標',
10 superscript: '上標',
11 underline: '底線'
12} );
diff --git a/sources/plugins/basicstyles/plugin.js b/sources/plugins/basicstyles/plugin.js
new file mode 100644
index 0000000..4a6325a
--- /dev/null
+++ b/sources/plugins/basicstyles/plugin.js
@@ -0,0 +1,209 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'basicstyles', {
7 // jscs:disable maximumLineLength
8 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
9 // jscs:enable maximumLineLength
10 icons: 'bold,italic,underline,strike,subscript,superscript', // %REMOVE_LINE_CORE%
11 hidpi: true, // %REMOVE_LINE_CORE%
12 init: function( editor ) {
13 var order = 0;
14 // All buttons use the same code to register. So, to avoid
15 // duplications, let's use this tool function.
16 var addButtonCommand = function( buttonName, buttonLabel, commandName, styleDefiniton ) {
17 // Disable the command if no definition is configured.
18 if ( !styleDefiniton )
19 return;
20
21 var style = new CKEDITOR.style( styleDefiniton ),
22 forms = contentForms[ commandName ];
23
24 // Put the style as the most important form.
25 forms.unshift( style );
26
27 // Listen to contextual style activation.
28 editor.attachStyleStateChange( style, function( state ) {
29 !editor.readOnly && editor.getCommand( commandName ).setState( state );
30 } );
31
32 // Create the command that can be used to apply the style.
33 editor.addCommand( commandName, new CKEDITOR.styleCommand( style, {
34 contentForms: forms
35 } ) );
36
37 // Register the button, if the button plugin is loaded.
38 if ( editor.ui.addButton ) {
39 editor.ui.addButton( buttonName, {
40 label: buttonLabel,
41 command: commandName,
42 toolbar: 'basicstyles,' + ( order += 10 )
43 } );
44 }
45 };
46
47 var contentForms = {
48 bold: [
49 'strong',
50 'b',
51 [ 'span', function( el ) {
52 var fw = el.styles[ 'font-weight' ];
53 return fw == 'bold' || +fw >= 700;
54 } ]
55 ],
56
57 italic: [
58 'em',
59 'i',
60 [ 'span', function( el ) {
61 return el.styles[ 'font-style' ] == 'italic';
62 } ]
63 ],
64
65 underline: [
66 'u',
67 [ 'span', function( el ) {
68 return el.styles[ 'text-decoration' ] == 'underline';
69 } ]
70 ],
71
72 strike: [
73 's',
74 'strike',
75 [ 'span', function( el ) {
76 return el.styles[ 'text-decoration' ] == 'line-through';
77 } ]
78 ],
79
80 subscript: [
81 'sub'
82 ],
83
84 superscript: [
85 'sup'
86 ]
87 },
88 config = editor.config,
89 lang = editor.lang.basicstyles;
90
91 addButtonCommand( 'Bold', lang.bold, 'bold', config.coreStyles_bold );
92 addButtonCommand( 'Italic', lang.italic, 'italic', config.coreStyles_italic );
93 addButtonCommand( 'Underline', lang.underline, 'underline', config.coreStyles_underline );
94 addButtonCommand( 'Strike', lang.strike, 'strike', config.coreStyles_strike );
95 addButtonCommand( 'Subscript', lang.subscript, 'subscript', config.coreStyles_subscript );
96 addButtonCommand( 'Superscript', lang.superscript, 'superscript', config.coreStyles_superscript );
97
98 editor.setKeystroke( [
99 [ CKEDITOR.CTRL + 66 /*B*/, 'bold' ],
100 [ CKEDITOR.CTRL + 73 /*I*/, 'italic' ],
101 [ CKEDITOR.CTRL + 85 /*U*/, 'underline' ]
102 ] );
103 }
104} );
105
106// Basic Inline Styles.
107
108/**
109 * The style definition that applies the **bold** style to the text.
110 *
111 * Read more in the [documentation](#!/guide/dev_basicstyles)
112 * and see the [SDK sample](http://sdk.ckeditor.com/samples/basicstyles.html).
113 *
114 * config.coreStyles_bold = { element: 'b', overrides: 'strong' };
115 *
116 * config.coreStyles_bold = {
117 * element: 'span',
118 * attributes: { 'class': 'Bold' }
119 * };
120 *
121 * @cfg
122 * @member CKEDITOR.config
123 */
124CKEDITOR.config.coreStyles_bold = { element: 'strong', overrides: 'b' };
125
126/**
127 * The style definition that applies the *italics* style to the text.
128 *
129 * Read more in the [documentation](#!/guide/dev_basicstyles)
130 * and see the [SDK sample](http://sdk.ckeditor.com/samples/basicstyles.html).
131 *
132 * config.coreStyles_italic = { element: 'i', overrides: 'em' };
133 *
134 * CKEDITOR.config.coreStyles_italic = {
135 * element: 'span',
136 * attributes: { 'class': 'Italic' }
137 * };
138 *
139 * @cfg
140 * @member CKEDITOR.config
141 */
142CKEDITOR.config.coreStyles_italic = { element: 'em', overrides: 'i' };
143
144/**
145 * The style definition that applies the <u>underline</u> style to the text.
146 *
147 * Read more in the [documentation](#!/guide/dev_basicstyles)
148 * and see the [SDK sample](http://sdk.ckeditor.com/samples/basicstyles.html).
149 *
150 * CKEDITOR.config.coreStyles_underline = {
151 * element: 'span',
152 * attributes: { 'class': 'Underline' }
153 * };
154 *
155 * @cfg
156 * @member CKEDITOR.config
157 */
158CKEDITOR.config.coreStyles_underline = { element: 'u' };
159
160/**
161 * The style definition that applies the <strike>strikethrough</strike> style to the text.
162 *
163 * Read more in the [documentation](#!/guide/dev_basicstyles)
164 * and see the [SDK sample](http://sdk.ckeditor.com/samples/basicstyles.html).
165 *
166 * CKEDITOR.config.coreStyles_strike = {
167 * element: 'span',
168 * attributes: { 'class': 'Strikethrough' },
169 * overrides: 'strike'
170 * };
171 *
172 * @cfg
173 * @member CKEDITOR.config
174 */
175CKEDITOR.config.coreStyles_strike = { element: 's', overrides: 'strike' };
176
177/**
178 * The style definition that applies the subscript style to the text.
179 *
180 * Read more in the [documentation](#!/guide/dev_basicstyles)
181 * and see the [SDK sample](http://sdk.ckeditor.com/samples/basicstyles.html).
182 *
183 * CKEDITOR.config.coreStyles_subscript = {
184 * element: 'span',
185 * attributes: { 'class': 'Subscript' },
186 * overrides: 'sub'
187 * };
188 *
189 * @cfg
190 * @member CKEDITOR.config
191 */
192CKEDITOR.config.coreStyles_subscript = { element: 'sub' };
193
194/**
195 * The style definition that applies the superscript style to the text.
196 *
197 * Read more in the [documentation](#!/guide/dev_basicstyles)
198 * and see the [SDK sample](http://sdk.ckeditor.com/samples/basicstyles.html).
199 *
200 * CKEDITOR.config.coreStyles_superscript = {
201 * element: 'span',
202 * attributes: { 'class': 'Superscript' },
203 * overrides: 'sup'
204 * };
205 *
206 * @cfg
207 * @member CKEDITOR.config
208 */
209CKEDITOR.config.coreStyles_superscript = { element: 'sup' };
diff --git a/sources/plugins/button/lang/af.js b/sources/plugins/button/lang/af.js
new file mode 100644
index 0000000..6ccebfa
--- /dev/null
+++ b/sources/plugins/button/lang/af.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'af', {
7 selectedLabel: '%1 uitgekies'
8} );
diff --git a/sources/plugins/button/lang/ar.js b/sources/plugins/button/lang/ar.js
new file mode 100644
index 0000000..025068d
--- /dev/null
+++ b/sources/plugins/button/lang/ar.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ar', {
7 selectedLabel: '%1 (محدد)'
8} );
diff --git a/sources/plugins/button/lang/az.js b/sources/plugins/button/lang/az.js
new file mode 100644
index 0000000..30ac85e
--- /dev/null
+++ b/sources/plugins/button/lang/az.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'az', {
7 selectedLabel: '%1 (seçilib)'
8} );
diff --git a/sources/plugins/button/lang/bg.js b/sources/plugins/button/lang/bg.js
new file mode 100644
index 0000000..0b146bb
--- /dev/null
+++ b/sources/plugins/button/lang/bg.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'bg', {
7 selectedLabel: '%1 (Избрано)'
8} );
diff --git a/sources/plugins/button/lang/ca.js b/sources/plugins/button/lang/ca.js
new file mode 100644
index 0000000..0891d49
--- /dev/null
+++ b/sources/plugins/button/lang/ca.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ca', {
7 selectedLabel: '%1 (Seleccionat)'
8} );
diff --git a/sources/plugins/button/lang/cs.js b/sources/plugins/button/lang/cs.js
new file mode 100644
index 0000000..552a05c
--- /dev/null
+++ b/sources/plugins/button/lang/cs.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'cs', {
7 selectedLabel: '%1 (Vybráno)'
8} );
diff --git a/sources/plugins/button/lang/da.js b/sources/plugins/button/lang/da.js
new file mode 100644
index 0000000..255dcc5
--- /dev/null
+++ b/sources/plugins/button/lang/da.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'da', {
7 selectedLabel: '%1 (Valgt)'
8} );
diff --git a/sources/plugins/button/lang/de-ch.js b/sources/plugins/button/lang/de-ch.js
new file mode 100644
index 0000000..63430d7
--- /dev/null
+++ b/sources/plugins/button/lang/de-ch.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'de-ch', {
7 selectedLabel: '%1 (Ausgewählt)'
8} );
diff --git a/sources/plugins/button/lang/de.js b/sources/plugins/button/lang/de.js
new file mode 100644
index 0000000..dca3daa
--- /dev/null
+++ b/sources/plugins/button/lang/de.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'de', {
7 selectedLabel: '%1 (Ausgewählt)'
8} );
diff --git a/sources/plugins/button/lang/el.js b/sources/plugins/button/lang/el.js
new file mode 100644
index 0000000..1718816
--- /dev/null
+++ b/sources/plugins/button/lang/el.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'el', {
7 selectedLabel: '%1 (Επιλεγμένο)'
8} );
diff --git a/sources/plugins/button/lang/en-gb.js b/sources/plugins/button/lang/en-gb.js
new file mode 100644
index 0000000..d7daefc
--- /dev/null
+++ b/sources/plugins/button/lang/en-gb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'en-gb', {
7 selectedLabel: '%1 (Selected)'
8} );
diff --git a/sources/plugins/button/lang/en.js b/sources/plugins/button/lang/en.js
new file mode 100644
index 0000000..d5c4088
--- /dev/null
+++ b/sources/plugins/button/lang/en.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'en', {
7 selectedLabel: '%1 (Selected)'
8} );
diff --git a/sources/plugins/button/lang/eo.js b/sources/plugins/button/lang/eo.js
new file mode 100644
index 0000000..acf0c13
--- /dev/null
+++ b/sources/plugins/button/lang/eo.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'eo', {
7 selectedLabel: '%1 (Selektita)'
8} );
diff --git a/sources/plugins/button/lang/es.js b/sources/plugins/button/lang/es.js
new file mode 100644
index 0000000..cb46c6f
--- /dev/null
+++ b/sources/plugins/button/lang/es.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'es', {
7 selectedLabel: '%1 (Seleccionado)'
8} );
diff --git a/sources/plugins/button/lang/eu.js b/sources/plugins/button/lang/eu.js
new file mode 100644
index 0000000..c49d92a
--- /dev/null
+++ b/sources/plugins/button/lang/eu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'eu', {
7 selectedLabel: '%1 (hautatuta)'
8} );
diff --git a/sources/plugins/button/lang/fa.js b/sources/plugins/button/lang/fa.js
new file mode 100644
index 0000000..358c88a
--- /dev/null
+++ b/sources/plugins/button/lang/fa.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'fa', {
7 selectedLabel: '%1 (انتخاب شده)'
8} );
diff --git a/sources/plugins/button/lang/fi.js b/sources/plugins/button/lang/fi.js
new file mode 100644
index 0000000..4822e74
--- /dev/null
+++ b/sources/plugins/button/lang/fi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'fi', {
7 selectedLabel: '%1 (Valittu)'
8} );
diff --git a/sources/plugins/button/lang/fr.js b/sources/plugins/button/lang/fr.js
new file mode 100644
index 0000000..1b1c6d3
--- /dev/null
+++ b/sources/plugins/button/lang/fr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'fr', {
7 selectedLabel: '%1 (Sélectionné)'
8} );
diff --git a/sources/plugins/button/lang/gl.js b/sources/plugins/button/lang/gl.js
new file mode 100644
index 0000000..3e4e0b7
--- /dev/null
+++ b/sources/plugins/button/lang/gl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'gl', {
7 selectedLabel: '%1 (seleccionado)'
8} );
diff --git a/sources/plugins/button/lang/he.js b/sources/plugins/button/lang/he.js
new file mode 100644
index 0000000..c67afb6
--- /dev/null
+++ b/sources/plugins/button/lang/he.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'he', {
7 selectedLabel: '1% (סומן)'
8} );
diff --git a/sources/plugins/button/lang/hu.js b/sources/plugins/button/lang/hu.js
new file mode 100644
index 0000000..0dffac1
--- /dev/null
+++ b/sources/plugins/button/lang/hu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'hu', {
7 selectedLabel: '%1 (Kiválasztva)'
8} );
diff --git a/sources/plugins/button/lang/id.js b/sources/plugins/button/lang/id.js
new file mode 100644
index 0000000..f973ffc
--- /dev/null
+++ b/sources/plugins/button/lang/id.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'id', {
7 selectedLabel: '%1(Dipilih)'
8} );
diff --git a/sources/plugins/button/lang/it.js b/sources/plugins/button/lang/it.js
new file mode 100644
index 0000000..359dc9a
--- /dev/null
+++ b/sources/plugins/button/lang/it.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'it', {
7 selectedLabel: '%1 (selezionato)'
8} );
diff --git a/sources/plugins/button/lang/ja.js b/sources/plugins/button/lang/ja.js
new file mode 100644
index 0000000..e2b064f
--- /dev/null
+++ b/sources/plugins/button/lang/ja.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ja', {
7 selectedLabel: '%1 (選択中)'
8} );
diff --git a/sources/plugins/button/lang/km.js b/sources/plugins/button/lang/km.js
new file mode 100644
index 0000000..9437a2f
--- /dev/null
+++ b/sources/plugins/button/lang/km.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'km', {
7 selectedLabel: '%1 (បាន​ជ្រើស​រើស)'
8} );
diff --git a/sources/plugins/button/lang/ko.js b/sources/plugins/button/lang/ko.js
new file mode 100644
index 0000000..64ad966
--- /dev/null
+++ b/sources/plugins/button/lang/ko.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ko', {
7 selectedLabel: '%1 (선택됨)'
8} );
diff --git a/sources/plugins/button/lang/ku.js b/sources/plugins/button/lang/ku.js
new file mode 100644
index 0000000..d342dd0
--- /dev/null
+++ b/sources/plugins/button/lang/ku.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ku', {
7 selectedLabel: '%1 (هەڵبژێردراو)'
8} );
diff --git a/sources/plugins/button/lang/lt.js b/sources/plugins/button/lang/lt.js
new file mode 100644
index 0000000..b492bd5
--- /dev/null
+++ b/sources/plugins/button/lang/lt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'lt', {
7 selectedLabel: '%1 (Pasirinkta)'
8} );
diff --git a/sources/plugins/button/lang/nb.js b/sources/plugins/button/lang/nb.js
new file mode 100644
index 0000000..8d38121
--- /dev/null
+++ b/sources/plugins/button/lang/nb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'nb', {
7 selectedLabel: '%1 (Valgt)'
8} );
diff --git a/sources/plugins/button/lang/nl.js b/sources/plugins/button/lang/nl.js
new file mode 100644
index 0000000..3e00f80
--- /dev/null
+++ b/sources/plugins/button/lang/nl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'nl', {
7 selectedLabel: '%1 (Geselecteerd)'
8} );
diff --git a/sources/plugins/button/lang/no.js b/sources/plugins/button/lang/no.js
new file mode 100644
index 0000000..e6252b1
--- /dev/null
+++ b/sources/plugins/button/lang/no.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'no', {
7 selectedLabel: '%1 (Valgt)'
8} );
diff --git a/sources/plugins/button/lang/oc.js b/sources/plugins/button/lang/oc.js
new file mode 100644
index 0000000..cb91761
--- /dev/null
+++ b/sources/plugins/button/lang/oc.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'oc', {
7 selectedLabel: '%1 (Seleccionat)'
8} );
diff --git a/sources/plugins/button/lang/pl.js b/sources/plugins/button/lang/pl.js
new file mode 100644
index 0000000..304d07a
--- /dev/null
+++ b/sources/plugins/button/lang/pl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'pl', {
7 selectedLabel: '%1 (Wybrany)'
8} );
diff --git a/sources/plugins/button/lang/pt-br.js b/sources/plugins/button/lang/pt-br.js
new file mode 100644
index 0000000..e3fdf84
--- /dev/null
+++ b/sources/plugins/button/lang/pt-br.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'pt-br', {
7 selectedLabel: '%1 (Selecionado)'
8} );
diff --git a/sources/plugins/button/lang/pt.js b/sources/plugins/button/lang/pt.js
new file mode 100644
index 0000000..e02c45a
--- /dev/null
+++ b/sources/plugins/button/lang/pt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'pt', {
7 selectedLabel: '%1 (Selecionado)'
8} );
diff --git a/sources/plugins/button/lang/ro.js b/sources/plugins/button/lang/ro.js
new file mode 100644
index 0000000..0669dd5
--- /dev/null
+++ b/sources/plugins/button/lang/ro.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ro', {
7 selectedLabel: '%1 (Selectat)'
8} );
diff --git a/sources/plugins/button/lang/ru.js b/sources/plugins/button/lang/ru.js
new file mode 100644
index 0000000..085f6ee
--- /dev/null
+++ b/sources/plugins/button/lang/ru.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ru', {
7 selectedLabel: '%1 (Выбрано)'
8} );
diff --git a/sources/plugins/button/lang/sk.js b/sources/plugins/button/lang/sk.js
new file mode 100644
index 0000000..12bec80
--- /dev/null
+++ b/sources/plugins/button/lang/sk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'sk', {
7 selectedLabel: '%1 (Vybrané)'
8} );
diff --git a/sources/plugins/button/lang/sl.js b/sources/plugins/button/lang/sl.js
new file mode 100644
index 0000000..c6633ae
--- /dev/null
+++ b/sources/plugins/button/lang/sl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'sl', {
7 selectedLabel: '%1 (Izbrano)'
8} );
diff --git a/sources/plugins/button/lang/sq.js b/sources/plugins/button/lang/sq.js
new file mode 100644
index 0000000..2e53e4c
--- /dev/null
+++ b/sources/plugins/button/lang/sq.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'sq', {
7 selectedLabel: '%1 (Përzgjedhur)'
8} );
diff --git a/sources/plugins/button/lang/sv.js b/sources/plugins/button/lang/sv.js
new file mode 100644
index 0000000..b89e475
--- /dev/null
+++ b/sources/plugins/button/lang/sv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'sv', {
7 selectedLabel: '%1 (Vald)'
8} );
diff --git a/sources/plugins/button/lang/tr.js b/sources/plugins/button/lang/tr.js
new file mode 100644
index 0000000..30d3670
--- /dev/null
+++ b/sources/plugins/button/lang/tr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'tr', {
7 selectedLabel: '%1 (Seçilmiş)'
8} );
diff --git a/sources/plugins/button/lang/tt.js b/sources/plugins/button/lang/tt.js
new file mode 100644
index 0000000..6324922
--- /dev/null
+++ b/sources/plugins/button/lang/tt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'tt', {
7 selectedLabel: '%1 (Сайланган)'
8} );
diff --git a/sources/plugins/button/lang/ug.js b/sources/plugins/button/lang/ug.js
new file mode 100644
index 0000000..fa3a90c
--- /dev/null
+++ b/sources/plugins/button/lang/ug.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'ug', {
7 selectedLabel: '%1 (تاللاندى)'
8} );
diff --git a/sources/plugins/button/lang/uk.js b/sources/plugins/button/lang/uk.js
new file mode 100644
index 0000000..7b49fe2
--- /dev/null
+++ b/sources/plugins/button/lang/uk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'uk', {
7 selectedLabel: '%1 (Вибрано)'
8} );
diff --git a/sources/plugins/button/lang/vi.js b/sources/plugins/button/lang/vi.js
new file mode 100644
index 0000000..b6a5911
--- /dev/null
+++ b/sources/plugins/button/lang/vi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'vi', {
7 selectedLabel: '%1 (Đã chọn)'
8} );
diff --git a/sources/plugins/button/lang/zh-cn.js b/sources/plugins/button/lang/zh-cn.js
new file mode 100644
index 0000000..fade7d7
--- /dev/null
+++ b/sources/plugins/button/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'zh-cn', {
7 selectedLabel: '已选中 %1 项'
8} );
diff --git a/sources/plugins/button/lang/zh.js b/sources/plugins/button/lang/zh.js
new file mode 100644
index 0000000..7479462
--- /dev/null
+++ b/sources/plugins/button/lang/zh.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'button', 'zh', {
7 selectedLabel: '%1 (已選取)'
8} );
diff --git a/sources/plugins/button/plugin.js b/sources/plugins/button/plugin.js
new file mode 100644
index 0000000..6d2db33
--- /dev/null
+++ b/sources/plugins/button/plugin.js
@@ -0,0 +1,389 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 var template = '<a id="{id}"' +
8 ' class="cke_button cke_button__{name} cke_button_{state} {cls}"' +
9 ( CKEDITOR.env.gecko && !CKEDITOR.env.hc ? '' : ' href="javascript:void(\'{titleJs}\')"' ) +
10 ' title="{title}"' +
11 ' tabindex="-1"' +
12 ' hidefocus="true"' +
13 ' role="button"' +
14 ' aria-labelledby="{id}_label"' +
15 ' aria-describedby="{id}_description"' +
16 ' aria-haspopup="{hasArrow}"' +
17 ' aria-disabled="{ariaDisabled}"';
18
19 // Some browsers don't cancel key events in the keydown but in the
20 // keypress.
21 // TODO: Check if really needed.
22 if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )
23 template += ' onkeypress="return false;"';
24
25 // With Firefox, we need to force the button to redraw, otherwise it
26 // will remain in the focus state.
27 if ( CKEDITOR.env.gecko )
28 template += ' onblur="this.style.cssText = this.style.cssText;"';
29
30 template += ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event);"' +
31 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' +
32 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188
33 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' +
34 '<span class="cke_button_icon cke_button__{iconName}_icon" style="{style}"';
35
36
37 template += '>&nbsp;</span>' +
38 '<span id="{id}_label" class="cke_button_label cke_button__{name}_label" aria-hidden="false">{label}</span>' +
39 '<span id="{id}_description" class="cke_button_label" aria-hidden="false">{ariaShortcut}</span>' +
40 '{arrowHtml}' +
41 '</a>';
42
43 var templateArrow = '<span class="cke_button_arrow">' +
44 // BLACK DOWN-POINTING TRIANGLE
45 ( CKEDITOR.env.hc ? '&#9660;' : '' ) +
46 '</span>';
47
48 var btnArrowTpl = CKEDITOR.addTemplate( 'buttonArrow', templateArrow ),
49 btnTpl = CKEDITOR.addTemplate( 'button', template );
50
51 CKEDITOR.plugins.add( 'button', {
52 lang: 'af,ar,az,bg,ca,cs,da,de,de-ch,el,en,en-gb,eo,es,eu,fa,fi,fr,gl,he,hu,id,it,ja,km,ko,ku,lt,nb,nl,no,oc,pl,pt,pt-br,ro,ru,sk,sl,sq,sv,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
53 beforeInit: function( editor ) {
54 editor.ui.addHandler( CKEDITOR.UI_BUTTON, CKEDITOR.ui.button.handler );
55 }
56 } );
57
58 /**
59 * Button UI element.
60 *
61 * @readonly
62 * @property {String} [='button']
63 * @member CKEDITOR
64 */
65 CKEDITOR.UI_BUTTON = 'button';
66
67 /**
68 * Represents a button UI element. This class should not be called directly. To
69 * create new buttons use {@link CKEDITOR.ui#addButton} instead.
70 *
71 * @class
72 * @constructor Creates a button class instance.
73 * @param {Object} definition The button definition.
74 */
75 CKEDITOR.ui.button = function( definition ) {
76 CKEDITOR.tools.extend( this, definition,
77 // Set defaults.
78 {
79 title: definition.label,
80 click: definition.click ||
81 function( editor ) {
82 editor.execCommand( definition.command );
83 }
84 } );
85
86 this._ = {};
87 };
88
89 /**
90 * Represents the button handler object.
91 *
92 * @class
93 * @singleton
94 * @extends CKEDITOR.ui.handlerDefinition
95 */
96 CKEDITOR.ui.button.handler = {
97 /**
98 * Transforms a button definition in a {@link CKEDITOR.ui.button} instance.
99 *
100 * @member CKEDITOR.ui.button.handler
101 * @param {Object} definition
102 * @returns {CKEDITOR.ui.button}
103 */
104 create: function( definition ) {
105 return new CKEDITOR.ui.button( definition );
106 }
107 };
108
109 /** @class CKEDITOR.ui.button */
110 CKEDITOR.ui.button.prototype = {
111 /**
112 * Renders the button.
113 *
114 * @param {CKEDITOR.editor} editor The editor instance which this button is
115 * to be used by.
116 * @param {Array} output The output array to which the HTML code related to
117 * this button should be appended.
118 */
119 render: function( editor, output ) {
120 function updateState() {
121 // "this" is a CKEDITOR.ui.button instance.
122 var mode = editor.mode;
123
124 if ( mode ) {
125 // Restore saved button state.
126 var state = this.modes[ mode ] ? modeStates[ mode ] !== undefined ? modeStates[ mode ] : CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
127
128 state = editor.readOnly && !this.readOnly ? CKEDITOR.TRISTATE_DISABLED : state;
129
130 this.setState( state );
131
132 // Let plugin to disable button.
133 if ( this.refresh )
134 this.refresh();
135 }
136 }
137
138 var env = CKEDITOR.env,
139 id = this._.id = CKEDITOR.tools.getNextId(),
140 stateName = '',
141 command = this.command,
142 // Get the command name.
143 clickFn,
144 keystroke,
145 shortcut;
146
147 this._.editor = editor;
148
149 var instance = {
150 id: id,
151 button: this,
152 editor: editor,
153 focus: function() {
154 var element = CKEDITOR.document.getById( id );
155 element.focus();
156 },
157 execute: function() {
158 this.button.click( editor );
159 },
160 attach: function( editor ) {
161 this.button.attach( editor );
162 }
163 };
164
165 var keydownFn = CKEDITOR.tools.addFunction( function( ev ) {
166 if ( instance.onkey ) {
167 ev = new CKEDITOR.dom.event( ev );
168 return ( instance.onkey( instance, ev.getKeystroke() ) !== false );
169 }
170 } );
171
172 var focusFn = CKEDITOR.tools.addFunction( function( ev ) {
173 var retVal;
174
175 if ( instance.onfocus )
176 retVal = ( instance.onfocus( instance, new CKEDITOR.dom.event( ev ) ) !== false );
177
178 return retVal;
179 } );
180
181 var selLocked = 0;
182
183 instance.clickFn = clickFn = CKEDITOR.tools.addFunction( function() {
184
185 // Restore locked selection in Opera.
186 if ( selLocked ) {
187 editor.unlockSelection( 1 );
188 selLocked = 0;
189 }
190 instance.execute();
191
192 // Fixed iOS focus issue when your press disabled button (#12381).
193 if ( env.iOS ) {
194 editor.focus();
195 }
196 } );
197
198
199 // Indicate a mode sensitive button.
200 if ( this.modes ) {
201 var modeStates = {};
202
203 editor.on( 'beforeModeUnload', function() {
204 if ( editor.mode && this._.state != CKEDITOR.TRISTATE_DISABLED )
205 modeStates[ editor.mode ] = this._.state;
206 }, this );
207
208 // Update status when activeFilter, mode or readOnly changes.
209 editor.on( 'activeFilterChange', updateState, this );
210 editor.on( 'mode', updateState, this );
211 // If this button is sensitive to readOnly state, update it accordingly.
212 !this.readOnly && editor.on( 'readOnly', updateState, this );
213
214 } else if ( command ) {
215 // Get the command instance.
216 command = editor.getCommand( command );
217
218 if ( command ) {
219 command.on( 'state', function() {
220 this.setState( command.state );
221 }, this );
222
223 stateName += ( command.state == CKEDITOR.TRISTATE_ON ? 'on' : command.state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 'off' );
224 }
225 }
226
227 // For button that has text-direction awareness on selection path.
228 if ( this.directional ) {
229 editor.on( 'contentDirChanged', function( evt ) {
230 var el = CKEDITOR.document.getById( this._.id ),
231 icon = el.getFirst();
232
233 var pathDir = evt.data;
234
235 // Make a minor direction change to become style-able for the skin icon.
236 if ( pathDir != editor.lang.dir )
237 el.addClass( 'cke_' + pathDir );
238 else
239 el.removeClass( 'cke_ltr' ).removeClass( 'cke_rtl' );
240
241 // Inline style update for the plugin icon.
242 icon.setAttribute( 'style', CKEDITOR.skin.getIconStyle( iconName, pathDir == 'rtl', this.icon, this.iconOffset ) );
243 }, this );
244 }
245
246 if ( !command ) {
247 stateName += 'off';
248 } else {
249 keystroke = editor.getCommandKeystroke( command );
250
251 if ( keystroke ) {
252 shortcut = CKEDITOR.tools.keystrokeToString( editor.lang.common.keyboard, keystroke );
253 }
254 }
255
256 var name = this.name || this.command,
257 iconName = name;
258
259 // Check if we're pointing to an icon defined by another command. (#9555)
260 if ( this.icon && !( /\./ ).test( this.icon ) ) {
261 iconName = this.icon;
262 this.icon = null;
263 }
264
265 var params = {
266 id: id,
267 name: name,
268 iconName: iconName,
269 label: this.label,
270 cls: this.className || '',
271 state: stateName,
272 ariaDisabled: stateName == 'disabled' ? 'true' : 'false',
273 title: this.title + ( shortcut ? ' (' + shortcut.display + ')' : '' ),
274 ariaShortcut: shortcut ? editor.lang.common.keyboardShortcut + ' ' + shortcut.aria : '',
275 titleJs: env.gecko && !env.hc ? '' : ( this.title || '' ).replace( "'", '' ),
276 hasArrow: this.hasArrow ? 'true' : 'false',
277 keydownFn: keydownFn,
278 focusFn: focusFn,
279 clickFn: clickFn,
280 style: CKEDITOR.skin.getIconStyle( iconName, ( editor.lang.dir == 'rtl' ), this.icon, this.iconOffset ),
281 arrowHtml: this.hasArrow ? btnArrowTpl.output() : ''
282 };
283
284 btnTpl.output( params, output );
285
286 if ( this.onRender )
287 this.onRender();
288
289 return instance;
290 },
291
292 /**
293 * Sets the button state.
294 *
295 * @param {Number} state Indicates the button state. One of {@link CKEDITOR#TRISTATE_ON},
296 * {@link CKEDITOR#TRISTATE_OFF}, or {@link CKEDITOR#TRISTATE_DISABLED}.
297 */
298 setState: function( state ) {
299 if ( this._.state == state )
300 return false;
301
302 this._.state = state;
303
304 var element = CKEDITOR.document.getById( this._.id );
305
306 if ( element ) {
307 element.setState( state, 'cke_button' );
308
309 state == CKEDITOR.TRISTATE_DISABLED ?
310 element.setAttribute( 'aria-disabled', true ) :
311 element.removeAttribute( 'aria-disabled' );
312
313 if ( !this.hasArrow ) {
314 // Note: aria-pressed attribute should not be added to menuButton instances. (#11331)
315 state == CKEDITOR.TRISTATE_ON ?
316 element.setAttribute( 'aria-pressed', true ) :
317 element.removeAttribute( 'aria-pressed' );
318 } else {
319 var newLabel = state == CKEDITOR.TRISTATE_ON ?
320 this._.editor.lang.button.selectedLabel.replace( /%1/g, this.label ) : this.label;
321 CKEDITOR.document.getById( this._.id + '_label' ).setText( newLabel );
322 }
323
324 return true;
325 } else {
326 return false;
327 }
328 },
329
330 /**
331 * Gets the button state.
332 *
333 * @returns {Number} The button state. One of {@link CKEDITOR#TRISTATE_ON},
334 * {@link CKEDITOR#TRISTATE_OFF}, or {@link CKEDITOR#TRISTATE_DISABLED}.
335 */
336 getState: function() {
337 return this._.state;
338 },
339
340 /**
341 * Returns this button's {@link CKEDITOR.feature} instance.
342 *
343 * It may be this button instance if it has at least one of
344 * `allowedContent` and `requiredContent` properties. Otherwise,
345 * if a command is bound to this button by the `command` property, then
346 * that command will be returned.
347 *
348 * This method implements the {@link CKEDITOR.feature#toFeature} interface method.
349 *
350 * @since 4.1
351 * @param {CKEDITOR.editor} Editor instance.
352 * @returns {CKEDITOR.feature} The feature.
353 */
354 toFeature: function( editor ) {
355 if ( this._.feature )
356 return this._.feature;
357
358 var feature = this;
359
360 // If button isn't a feature, return command if is bound.
361 if ( !this.allowedContent && !this.requiredContent && this.command )
362 feature = editor.getCommand( this.command ) || feature;
363
364 return this._.feature = feature;
365 }
366 };
367
368 /**
369 * Adds a button definition to the UI elements list.
370 *
371 * editorInstance.ui.addButton( 'MyBold', {
372 * label: 'My Bold',
373 * command: 'bold',
374 * toolbar: 'basicstyles,1'
375 * } );
376 *
377 * @member CKEDITOR.ui
378 * @param {String} name The button name.
379 * @param {Object} definition The button definition.
380 * @param {String} definition.label The textual part of the button (if visible) and its tooltip.
381 * @param {String} definition.command The command to be executed once the button is activated.
382 * @param {String} definition.toolbar The {@link CKEDITOR.config#toolbarGroups toolbar group} into which
383 * the button will be added. An optional index value (separated by a comma) determines the button position within the group.
384 */
385 CKEDITOR.ui.prototype.addButton = function( name, definition ) {
386 this.add( name, CKEDITOR.UI_BUTTON, definition );
387 };
388
389} )();
diff --git a/sources/plugins/clipboard/dev/clipboard.html b/sources/plugins/clipboard/dev/clipboard.html
new file mode 100644
index 0000000..735d00e
--- /dev/null
+++ b/sources/plugins/clipboard/dev/clipboard.html
@@ -0,0 +1,190 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Clipboard playground &ndash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link href="../../../samples/old/sample.css" rel="stylesheet">
12 <style>
13body {
14 margin: 0;
15}
16
17#editables, #console
18{
19 width: 48%;
20}
21#editable {
22 padding: 5px 10px;
23}
24
25#console {
26 position: fixed;
27 top: 10px;
28 right: 30px;
29 height: 500px;
30 border: solid 3px #555;
31 overflow: auto;
32}
33#console > p {
34 border-bottom: solid 1px #555;
35 margin: 0;
36 padding: 0 5px;
37 background: rgba(0, 0, 0, 0.25);
38 transition: background-color 1s;
39}
40#console > p.old {
41 background: rgba(0, 0, 0, 0);
42}
43#console time, #console .prompt {
44 padding: 0 5px;
45 display: inline-block;
46}
47#console time {
48 background: #999;
49 background: rgba(0, 0, 0, 0.5 );
50 color: #FFF;
51 margin-left: -5px;
52}
53#console .prompt {
54 background: #DDD;
55 background: rgba(0, 0, 0, 0.1 );
56 min-width: 200px;
57}
58.someClass {
59 color: blue;
60}
61.specChar {
62 color: #777;
63 background-color: #EEE;
64 background-color: rgba(0, 0, 0, 0.1);
65 font-size: 0.8em;
66 border-radius: 2px;
67 padding: 1px;
68}
69 </style>
70</head>
71<body>
72 <h1 class="samples">
73 CKEditor Sample &mdash; clipboard plugin playground
74 </h1>
75 <div id="editables">
76 <p>
77 <label for="editor1">
78 Editor 1:</label>
79 <textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
80 </p>
81 <p>
82 <label for="editor2">
83 Editor 2:</label>
84 <textarea cols="80" id="editor2" name="editor2" rows="10">&lt;p&gt;This is more &lt;strong class="MsoNormal"&gt;sample text&lt;/strong&gt;.&lt;/p&gt;</textarea>
85 </p>
86 <p>
87 <label for="editor3">
88 Editor 3:</label>
89 <textarea cols="80" id="editor3" name="editor3" rows="10">&lt;p&gt;This editor &lt;strong&gt;forces pasting in text mode&lt;/strong&gt; by listening for "beforePaste" event.&lt;/p&gt;</textarea>
90 </p>
91 <p>
92 <label for="editor4">
93 Editor 4:</label>
94 <textarea cols="80" id="editor4" name="editor4" rows="10">&lt;p&gt;This editor &lt;strong&gt;forces pasting in text mode&lt;/strong&gt; by "forcePasteAsPlainText" config option.&lt;/p&gt;</textarea>
95 </p>
96 <p>
97 <label for="editor5">
98 Editor 5:</label>
99 <textarea cols="80" id="editor5" name="editor5" rows="10">Editor with autoParagraphing set to off.</textarea>
100 </p>
101 <div id="editor6" contenteditable="true" style="font-family: Georgia; font-size: 14px">
102 <h1>Editor 6</h1>
103 <p>Content content content.</p>
104 <p class="someClass">Styled by <code>.someClass</code>.</p>
105 </div>
106 </div>
107 <div id="console">
108 </div>
109 <script>
110( function()
111{
112 'use strict';
113
114 var log = window.__log = function( title, msg ) {
115 var msgEl = new CKEDITOR.dom.element( 'p' ),
116 consoleEl = CKEDITOR.document.getById( 'console' ),
117 time = new Date().toString().match( /\d\d:\d\d:\d\d/ )[ 0 ],
118 format = function( tpl ) {
119 return tpl.replace( /{time}/g, time ).replace( '{title}', title ).replace( '{msg}', msg || '' );
120 };
121
122 window.console && console.log && console.log( format( '[{time}] {title}: {msg}' ) );
123
124 msg = ( msg || '' ).replace( /\r/g, '{\\r}' ).replace( /\n/g, '{\\n}' ).replace( /\t/g, '{\\t}' );
125 msg = CKEDITOR.tools.htmlEncode( msg );
126 msg = msg.replace( /\{(\\\w)\}/g, '<code class="specChar">$1</code>' );
127
128 msgEl.setHtml( format( '<time datetime="{time}">{time}</time><span class="prompt">{title}</span> {msg}' ) );
129 consoleEl.append( msgEl );
130 consoleEl.$.scrollTop = consoleEl.$.scrollHeight;
131 setTimeout( function() { msgEl.addClass( 'old' ); }, 250 );
132 };
133
134 var observe = function( editor, num ) {
135 var p = 'EDITOR ' + num + ' > ';
136
137 editor.on( 'paste', function( event ) {
138 log( p + 'paste(prior:-1)', event.data.type + ' - "' + event.data.dataValue + '"' );
139 }, null, null, -1 );
140 editor.on( 'paste', function( event ) {
141 log( p + 'paste(prior:10)', event.data.type + ' - "' + event.data.dataValue + '"' );
142 } );
143 editor.on( 'paste', function( event ) {
144 log( p + 'paste(prior:999)', event.data.type + ' - "' + event.data.dataValue + '"' );
145 }, null, null, 999 );
146 editor.on( 'beforePaste', function( event ) {
147 log( p + 'beforePaste', event.data.type );
148 } );
149 editor.on( 'beforePaste', function( event ) {
150 log( p + 'beforePaste(prior:999)', event.data.type );
151 }, null, null, 999 );
152 editor.on( 'afterPaste', function( event ) {
153 log( p + 'afterPaste' );
154 } );
155 editor.on( 'copy', function( event ) {
156 log( p + 'copy' );
157 } );
158 editor.on( 'cut', function( event ) {
159 log( p + 'cut' );
160 } );
161 };
162
163 CKEDITOR.disableAutoInline = true;
164 var config = {
165 height: 120,
166 toolbar: [ [ 'Source' ] ],
167 allowedContent: true
168 },
169 editor1 = CKEDITOR.replace( 'editor1', config ),
170 editor2 = CKEDITOR.replace( 'editor2', config ),
171 editor3 = CKEDITOR.replace( 'editor3', config ),
172 editor4 = CKEDITOR.replace( 'editor4', CKEDITOR.tools.extend( { forcePasteAsPlainText: true }, config ) ),
173 editor5 = CKEDITOR.replace( 'editor5', CKEDITOR.tools.extend( { autoParagraph: false }, config ) ),
174 editor6 = CKEDITOR.inline( document.getElementById( 'editor6' ), config );
175
176 editor3.on( 'beforePaste', function( evt ) {
177 evt.data.type = 'text';
178 } );
179
180 observe( editor1, 1 );
181 observe( editor2, 2 );
182 observe( editor3, 3 );
183 observe( editor4, 4 );
184 observe( editor5, 5 );
185 observe( editor6, 6 );
186
187})();
188 </script>
189</body>
190</html>
diff --git a/sources/plugins/clipboard/dev/console.js b/sources/plugins/clipboard/dev/console.js
new file mode 100644
index 0000000..96ccd81
--- /dev/null
+++ b/sources/plugins/clipboard/dev/console.js
@@ -0,0 +1,49 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/* global CKCONSOLE */
7
8'use strict';
9
10( function() {
11 var pasteType, pasteValue;
12
13 CKCONSOLE.add( 'paste', {
14 panels: [
15 {
16 type: 'box',
17 content:
18 '<ul class="ckconsole_list">' +
19 '<li>type: <span class="ckconsole_value" data-value="type"></span></li>' +
20 '<li>value: <span class="ckconsole_value" data-value="value"></span></li>' +
21 '</ul>',
22
23 refresh: function() {
24 return {
25 header: 'Paste',
26 type: pasteType,
27 value: pasteValue
28 };
29 },
30
31 refreshOn: function( editor, refresh ) {
32 editor.on( 'paste', function( evt ) {
33 pasteType = evt.data.type;
34 pasteValue = CKEDITOR.tools.htmlEncode( evt.data.dataValue );
35 refresh();
36 } );
37 }
38 },
39 {
40 type: 'log',
41 on: function( editor, log, logFn ) {
42 editor.on( 'paste', function( evt ) {
43 logFn( 'paste; type:' + evt.data.type )();
44 } );
45 }
46 }
47 ]
48 } );
49} )();
diff --git a/sources/plugins/clipboard/dev/dnd.html b/sources/plugins/clipboard/dev/dnd.html
new file mode 100644
index 0000000..2dfb2be
--- /dev/null
+++ b/sources/plugins/clipboard/dev/dnd.html
@@ -0,0 +1,185 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Manual test for #11460</title>
10 <script src="../../../ckeditor.js"></script>
11 <script src="../../../dev/console/console.js"></script>
12 <script src="../../../plugins/clipboard/dev/console.js"></script>
13 <link rel="stylesheet" href="../../../samples/old/sample.css">
14 <style type="text/css">
15 h2 {
16 margin: 10px 0px 4px 0px;
17 padding: 0;
18 font-size: 14px;
19 }
20 h3 {
21 margin: 5px 0px 2px 0px;
22 padding: 0;
23 font-size: 12px;
24 }
25 </style>
26</head>
27<body>
28 <h1 class="samples">
29 Manual test for #11460
30 </h1>
31 <h2>Description (<a href="javascript:hideshow('description');">hide/show</a>)</h2>
32 <div id="description" class="description">
33 <p>Test internal D&amp;D in the editor, dropping content from an external source (helpers, MS Word) and D&amp;D between editors. Keep in mind that internal D&amp;D is the most complex operation because editor have to handle two ranges at the same time.</p>
34 <h3>Expected behavior:</h3>
35 <ul>
36 <li>proper drop position,</li>
37 <li>in the internal and cross editor D&amp;D: dragged content should be removed,</li>
38 <li>dropped content should be (more less) the same as dragged content,</li>
39 <li>paste event should be fired,</li>
40 <li>undo should work properly (one undo operation for one D&amp;D),</li>
41 <li>no crashes, nor errors,</li>
42 </ul>
43 <h3>Drag scenarios:</h3>
44 <ul>
45 <li>drag simple text,</li>
46 <li>drag table cell/cells,</li>
47 <li>drag link,</li>
48 <li>drag helpers textarea content,</li>
49 <li>drag helpers html content,</li>
50 <li>drag content from MS Word.</li>
51 </ul>
52 <h3>Drop scenarios:</h3>
53 <ul>
54 <li>drop in the different paragraph (before and after),</li>
55 <li>drop in the same paragraph (before and after),</li>
56 <li>drop in the same text node (before and after),</li>
57 <li>drop between text lines,</li>
58 <li>drop on the whitespace next to the header,</li>
59 <li>drop on the whitespace on the left side from the quote,</li>
60 <li>drop into a cell.</li>
61 </ul>
62 <h3>Known issues (not part of this ticket):</h3>
63 <ul>
64 <li>because of <a href="http://dev.ckeditor.com/ticket/11636">#11636</a> dragged content is not correct in some cases (e.g. when you drag part of the link),</li>
65 <li>drag position needs clean up after D&amp;D (e.g. remove empty paragraphs, fix table),</li>
66 <li>drop position needs clean up after D&amp;D (e.g. add spaces before/after dropped content, apply parents styles, break paragraph when one paragraph is dropped at the end to the other paragraph),</li>
67 <li>in the external D&amp;D: Chrome add plenty of addition tags.</li>
68 </ul>
69 </div>
70 <div>
71 <h2>Helpers (<a href="javascript:hideshow('helpers');">hide/show</a>)</h2>
72 <div id="helpers">
73 <textarea style="width:49%; height:50px; float: left;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In commodo vulputate tempor. Sed <b>at</b> elit.</textarea>
74 <div style="width:49%; height:50px; float: right;">
75 Lorem ipsum <b>dolor</b> sit <i>amet</i>, consectetur adipiscing elit. In commodo vulputate tempor. Sed &lt;b&gt;at elit&lt;/b&gt; vel ligula mollis aliquet a ac odio.
76 <pre>
77Aenean cursus egestas ipsum.
78 </pre>
79 </div>
80 <div style="clear:both;"></div>
81 </div>
82 </div>
83 <div>
84 <h2>Classic editor (<a href="javascript:hideshow('classic-editor');">hide/show</a>)</h2>
85 <div id="classic-editor">
86 <textarea cols="80" id="classic" name="classic" rows="10">
87 &lt;h1&gt;&lt;img alt=&quot;Saturn V carrying Apollo 11&quot; class=&quot;right&quot; src=&quot;../../../samples/assets/sample.jpg&quot;/&gt; Apollo 11&lt;/h1&gt; &lt;p&gt;&lt;b&gt;Apollo 11&lt;/b&gt; was the spaceflight that landed the first humans, Americans &lt;a href=&quot;http://en.wikipedia.org/wiki/Neil_Armstrong&quot; title=&quot;Neil Armstrong&quot;&gt;Neil Armstrong&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Buzz_Aldrin&quot; title=&quot;Buzz Aldrin&quot;&gt;Buzz Aldrin&lt;/a&gt;, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.&lt;/p&gt; &lt;p&gt;Armstrong spent about &lt;s&gt;three and a half&lt;/s&gt; two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5&amp;nbsp;kg) of lunar material for return to Earth. A third member of the mission, &lt;a href=&quot;http://en.wikipedia.org/wiki/Michael_Collins_(astronaut)&quot; title=&quot;Michael Collins (astronaut)&quot;&gt;Michael Collins&lt;/a&gt;, piloted the &lt;a href=&quot;http://en.wikipedia.org/wiki/Apollo_Command/Service_Module&quot; title=&quot;Apollo Command/Service Module&quot;&gt;command&lt;/a&gt; spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.&lt;/p&gt; &lt;h2&gt;Broadcasting and &lt;em&gt;quotes&lt;/em&gt; &lt;a id=&quot;quotes&quot; name=&quot;quotes&quot;&gt;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;One small step for [a] man, one giant leap for mankind.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Apollo 11 effectively ended the &lt;a href=&quot;http://en.wikipedia.org/wiki/Space_Race&quot; title=&quot;Space Race&quot;&gt;Space Race&lt;/a&gt; and fulfilled a national goal proposed in 1961 by the late U.S. President &lt;a href=&quot;http://en.wikipedia.org/wiki/John_F._Kennedy&quot; title=&quot;John F. Kennedy&quot;&gt;John F. Kennedy&lt;/a&gt; in a speech before the United States Congress:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.&lt;/p&gt;&lt;/blockquote&gt; &lt;h2&gt;Technical details &lt;a id=&quot;tech-details&quot; name=&quot;tech-details&quot;&gt;&lt;/a&gt;&lt;/h2&gt; &lt;table align=&quot;right&quot; border=&quot;1&quot; bordercolor=&quot;#ccc&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; style=&quot;border-collapse:collapse;margin:10px 0 10px 15px;&quot;&gt; &lt;caption&gt;&lt;strong&gt;Mission crew&lt;/strong&gt;&lt;/caption&gt; &lt;thead&gt; &lt;tr&gt; &lt;th scope=&quot;col&quot;&gt;Position&lt;/th&gt; &lt;th scope=&quot;col&quot;&gt;Astronaut&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;Commander&lt;/td&gt; &lt;td&gt;Neil A. Armstrong&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Command Module Pilot&lt;/td&gt; &lt;td&gt;Michael Collins&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Lunar Module Pilot&lt;/td&gt; &lt;td&gt;Edwin &amp;quot;Buzz&amp;quot; E. Aldrin, Jr.&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;Launched by a &lt;strong&gt;Saturn V&lt;/strong&gt; rocket from &lt;a href=&quot;http://en.wikipedia.org/wiki/Kennedy_Space_Center&quot; title=&quot;Kennedy Space Center&quot;&gt;Kennedy Space Center&lt;/a&gt; in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of &lt;a href=&quot;http://en.wikipedia.org/wiki/NASA&quot; title=&quot;NASA&quot;&gt;NASA&lt;/a&gt;&amp;#39;s Apollo program. The Apollo spacecraft had three parts:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;Command Module&lt;/strong&gt; with a cabin for the three astronauts which was the only part which landed back on Earth&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Service Module&lt;/strong&gt; which supported the Command Module with propulsion, electrical power, oxygen and water&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Lunar Module&lt;/strong&gt; for landing on the Moon.&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;After being sent to the Moon by the Saturn V&amp;#39;s upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Mare_Tranquillitatis&quot; title=&quot;Mare Tranquillitatis&quot;&gt;Sea of Tranquility&lt;/a&gt;. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Pacific_Ocean&quot; title=&quot;Pacific Ocean&quot;&gt;Pacific Ocean&lt;/a&gt; on July 24.&lt;/p&gt; &lt;hr/&gt; &lt;p style=&quot;text-align: right;&quot;&gt;&lt;small&gt;Source: &lt;a href=&quot;http://en.wikipedia.org/wiki/Apollo_11&quot;&gt;Wikipedia.org&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
88 </textarea>
89 </div>
90 </div>
91 <div>
92 <h2>Inline editor (<a href="javascript:hideshow('inline');">hide/show</a>)</h2>
93 <div id="inline" contenteditable="true">
94 <h1><img alt="Saturn V carrying Apollo 11" class="right" src="../../../samples/assets/sample.jpg" /> Apollo 11</h1>
95
96 <p><b>Apollo 11</b> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.</p>
97
98 <p>Armstrong spent about <s>three and a half</s> two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5&nbsp;kg) of lunar material for return to Earth. A third member of the mission, <a href="http://en.wikipedia.org/wiki/Michael_Collins_(astronaut)" title="Michael Collins (astronaut)">Michael Collins</a>, piloted the <a href="http://en.wikipedia.org/wiki/Apollo_Command/Service_Module" title="Apollo Command/Service Module">command</a> spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.</p>
99
100 <h2>Broadcasting and <em>quotes</em> <a id="quotes" name="quotes"></a></h2>
101
102 <p>Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:</p>
103
104 <blockquote>
105 <p>One small step for [a] man, one giant leap for mankind.</p>
106 </blockquote>
107
108 <p>Apollo 11 effectively ended the <a href="http://en.wikipedia.org/wiki/Space_Race" title="Space Race">Space Race</a> and fulfilled a national goal proposed in 1961 by the late U.S. President <a href="http://en.wikipedia.org/wiki/John_F._Kennedy" title="John F. Kennedy">John F. Kennedy</a> in a speech before the United States Congress:</p>
109
110 <blockquote>
111 <p>[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.</p>
112 </blockquote>
113
114 <h2>Technical details <a id="tech-details" name="tech-details"></a></h2>
115
116 <table align="right" border="1" bordercolor="#ccc" cellpadding="5" cellspacing="0" style="border-collapse:collapse;margin:10px 0 10px 15px;">
117 <caption><strong>Mission crew</strong></caption>
118 <thead>
119 <tr>
120 <th scope="col">Position</th>
121 <th scope="col">Astronaut</th>
122 </tr>
123 </thead>
124 <tbody>
125 <tr>
126 <td>Commander</td>
127 <td>Neil A. Armstrong</td>
128 </tr>
129 <tr>
130 <td>Command Module Pilot</td>
131 <td>Michael Collins</td>
132 </tr>
133 <tr>
134 <td>Lunar Module Pilot</td>
135 <td>Edwin &quot;Buzz&quot; E. Aldrin, Jr.</td>
136 </tr>
137 </tbody>
138 </table>
139
140 <p>Launched by a <strong>Saturn V</strong> rocket from <a href="http://en.wikipedia.org/wiki/Kennedy_Space_Center" title="Kennedy Space Center">Kennedy Space Center</a> in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of <a href="http://en.wikipedia.org/wiki/NASA" title="NASA">NASA</a>&#39;s Apollo program. The Apollo spacecraft had three parts:</p>
141
142 <ol>
143 <li><strong>Command Module</strong> with a cabin for the three astronauts which was the only part which landed back on Earth</li>
144 <li><strong>Service Module</strong> which supported the Command Module with propulsion, electrical power, oxygen and water</li>
145 <li><strong>Lunar Module</strong> for landing on the Moon.</li>
146 </ol>
147
148 <p>After being sent to the Moon by the Saturn V&#39;s upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the <a href="http://en.wikipedia.org/wiki/Mare_Tranquillitatis" title="Mare Tranquillitatis">Sea of Tranquility</a>. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the <a href="http://en.wikipedia.org/wiki/Pacific_Ocean" title="Pacific Ocean">Pacific Ocean</a> on July 24.</p>
149
150 <hr />
151 <p style="text-align: right;"><small>Source: <a href="http://en.wikipedia.org/wiki/Apollo_11">Wikipedia.org</a></small></p>
152 </div>
153 </div>
154 <script type="text/javascript">
155 CKEDITOR.disableAutoInline = true;
156
157 function hideshow( id ) {
158 var element = CKEDITOR.document.getById( id );
159
160 if( element.getStyle( 'display' ) == 'none' )
161 element.show();
162 else
163 element.hide();
164 }
165
166 CKEDITOR.replace( 'classic' );
167 CKEDITOR.inline( 'inline' );
168
169 CKCONSOLE.addEventPanel( 'dragstart', [ '$', 'target', 'dataTransfer' ] );
170 CKCONSOLE.addEventPanel( 'dragend', [ '$', 'target', 'dataTransfer' ] );
171 CKCONSOLE.addEventPanel( 'drop',
172 [ '$', 'target', 'dataTransfer', 'dragRange', 'dropRange' ] );
173
174 CKCONSOLE.create( 'dragstart', { editor: 'classic' } );
175 CKCONSOLE.create( 'drop', { editor: 'classic' } );
176 CKCONSOLE.create( 'paste', { editor: 'classic' } );
177 CKCONSOLE.create( 'dragend', { editor: 'classic' } );
178
179 CKCONSOLE.create( 'dragstart', { editor: 'inline' } );
180 CKCONSOLE.create( 'drop', { editor: 'inline' } );
181 CKCONSOLE.create( 'paste', { editor: 'inline' } );
182 CKCONSOLE.create( 'dragend', { editor: 'inline' } );
183 </script>
184</body>
185</html>
diff --git a/sources/plugins/clipboard/dialogs/paste.js b/sources/plugins/clipboard/dialogs/paste.js
new file mode 100644
index 0000000..80ce29f
--- /dev/null
+++ b/sources/plugins/clipboard/dialogs/paste.js
@@ -0,0 +1,254 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.dialog.add( 'paste', function( editor ) {
7 var lang = editor.lang.clipboard,
8 clipboard = CKEDITOR.plugins.clipboard,
9 lastDataTransfer;
10
11 function onPasteFrameLoad( win ) {
12 var doc = new CKEDITOR.dom.document( win.document ),
13 body = doc.getBody(),
14 script = doc.getById( 'cke_actscrpt' );
15
16 script && script.remove();
17
18 body.setAttribute( 'contenteditable', true );
19
20 // Forward dataTransfer (#13883).
21 body.on( clipboard.mainPasteEvent, function( evt ) {
22 var dataTransfer = clipboard.initPasteDataTransfer( evt );
23
24 if ( !lastDataTransfer ) {
25 lastDataTransfer = dataTransfer;
26 } else
27 // For two paste with the same dataTransfer we can use that dataTransfer (two internal pastes are
28 // considered as an internal paste).
29 if ( dataTransfer != lastDataTransfer ) {
30 // If there were two paste with different DataTransfer objects create a new, empty, data transfer
31 // and use it (one internal and one external paste are considered as external paste).
32 lastDataTransfer = clipboard.initPasteDataTransfer();
33 }
34 } );
35
36 // IE before version 8 will leave cursor blinking inside the document after
37 // editor blurred unless we clean up the selection. (#4716)
38 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) {
39 doc.getWindow().on( 'blur', function() {
40 doc.$.selection.empty();
41 } );
42 }
43
44 doc.on( 'keydown', function( e ) {
45 var domEvent = e.data,
46 key = domEvent.getKeystroke(),
47 processed;
48
49 switch ( key ) {
50 case 27:
51 this.hide();
52 processed = 1;
53 break;
54
55 case 9:
56 case CKEDITOR.SHIFT + 9:
57 this.changeFocus( 1 );
58 processed = 1;
59 }
60
61 processed && domEvent.preventDefault();
62 }, this );
63
64 editor.fire( 'ariaWidget', new CKEDITOR.dom.element( win.frameElement ) );
65
66 // Handle pending focus.
67 if ( doc.getWindow().getFrame().removeCustomData( 'pendingFocus' ) )
68 body.focus();
69 }
70
71 // If pasteDialogCommit wasn't canceled by e.g. editor.getClipboardData
72 // then fire paste event.
73 // Do not use editor#paste, because it would start from beforePaste event.
74 editor.on( 'pasteDialogCommit', function( evt ) {
75 if ( evt.data )
76 editor.fire( 'paste', {
77 type: 'auto',
78 dataValue: evt.data.dataValue,
79 method: 'paste',
80 dataTransfer: evt.data.dataTransfer || clipboard.initPasteDataTransfer()
81 } );
82 }, null, null, 1000 );
83
84 return {
85 title: lang.title,
86
87 minWidth: CKEDITOR.env.ie && CKEDITOR.env.quirks ? 370 : 350,
88 minHeight: CKEDITOR.env.quirks ? 250 : 245,
89 onShow: function() {
90 // FIREFOX BUG: Force the browser to render the dialog to make the to-be-
91 // inserted iframe editable. (#3366)
92 this.parts.dialog.$.offsetHeight;
93
94 this.setupContent();
95
96 // Set dialog title to the custom value (set e.g. in editor.openDialog callback) and reset this value.
97 // If custom title not set, use default one.
98 this.parts.title.setHtml( this.customTitle || lang.title );
99 this.customTitle = null;
100 },
101
102 onLoad: function() {
103 if ( ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) && editor.lang.dir == 'rtl' )
104 this.parts.contents.setStyle( 'overflow', 'hidden' );
105 },
106
107 onOk: function() {
108 this.commitContent();
109 },
110
111 contents: [ {
112 id: 'general',
113 label: editor.lang.common.generalTab,
114 elements: [
115 {
116 type: 'html',
117 id: 'securityMsg',
118 html: '<div style="white-space:normal;width:340px">' + lang.securityMsg + '</div>'
119 },
120 {
121 type: 'html',
122 id: 'pasteMsg',
123 html: '<div style="white-space:normal;width:340px">' + lang.pasteMsg + '</div>'
124 },
125 {
126 type: 'html',
127 id: 'editing_area',
128 style: 'width:100%;height:100%',
129 html: '',
130 focus: function() {
131 var iframe = this.getInputElement(),
132 doc = iframe.getFrameDocument(),
133 body = doc.getBody();
134
135 // Frame content may not loaded at the moment.
136 if ( !body || body.isReadOnly() )
137 iframe.setCustomData( 'pendingFocus', 1 );
138 else
139 body.focus();
140 },
141 setup: function() {
142 var dialog = this.getDialog();
143 var htmlToLoad = '<html dir="' + editor.config.contentsLangDirection + '"' +
144 ' lang="' + ( editor.config.contentsLanguage || editor.langCode ) + '">' +
145 '<head><style>body{margin:3px;height:95%;word-break:break-all;}</style></head><body>' +
146 '<script id="cke_actscrpt" type="text/javascript">' +
147 'window.parent.CKEDITOR.tools.callFunction(' + CKEDITOR.tools.addFunction( onPasteFrameLoad, dialog ) + ',this);' +
148 '</script></body>' +
149 '</html>';
150
151 var src =
152 CKEDITOR.env.air ?
153 'javascript:void(0)' : // jshint ignore:line
154 ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ?
155 'javascript:void((function(){' + encodeURIComponent( // jshint ignore:line
156 'document.open();' +
157 '(' + CKEDITOR.tools.fixDomain + ')();' +
158 'document.close();'
159 ) + '})())"'
160 : '';
161
162 var iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' +
163 ' class="cke_pasteframe"' +
164 ' frameborder="0" ' +
165 ' allowTransparency="true"' +
166 ' src="' + src + '"' +
167 ' aria-label="' + lang.pasteArea + '"' +
168 ' aria-describedby="' + dialog.getContentElement( 'general', 'pasteMsg' ).domId + '"' +
169 '></iframe>' );
170
171 // Reset last data transfer.
172 lastDataTransfer = null;
173
174 iframe.on( 'load', function( e ) {
175 e.removeListener();
176
177 var doc = iframe.getFrameDocument();
178 doc.write( htmlToLoad );
179
180 editor.focusManager.add( doc.getBody() );
181
182 if ( CKEDITOR.env.air )
183 onPasteFrameLoad.call( this, doc.getWindow().$ );
184 }, dialog );
185
186 iframe.setCustomData( 'dialog', dialog );
187
188 var container = this.getElement();
189 container.setHtml( '' );
190 container.append( iframe );
191
192 // IE need a redirect on focus to make
193 // the cursor blinking inside iframe. (#5461)
194 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) {
195 var focusGrabber = CKEDITOR.dom.element.createFromHtml( '<span tabindex="-1" style="position:absolute" role="presentation"></span>' );
196 focusGrabber.on( 'focus', function() {
197 // Since fixDomain is called in src attribute,
198 // IE needs some slight delay to correctly move focus.
199 setTimeout( function() {
200 iframe.$.contentWindow.focus();
201 } );
202 } );
203 container.append( focusGrabber );
204
205 // Override focus handler on field.
206 this.focus = function() {
207 focusGrabber.focus();
208 this.fire( 'focus' );
209 };
210 }
211
212 this.getInputElement = function() {
213 return iframe;
214 };
215
216 // Force container to scale in IE.
217 if ( CKEDITOR.env.ie ) {
218 container.setStyle( 'display', 'block' );
219 container.setStyle( 'height', ( iframe.$.offsetHeight + 2 ) + 'px' );
220 }
221 },
222 commit: function() {
223 var editor = this.getDialog().getParentEditor(),
224 body = this.getInputElement().getFrameDocument().getBody(),
225 bogus = body.getBogus(),
226 html;
227 bogus && bogus.remove();
228
229 // Saving the contents so changes until paste is complete will not take place (#7500)
230 html = body.getHtml();
231
232 // Opera needs some time to think about what has happened and what it should do now.
233 setTimeout( function() {
234 editor.fire( 'pasteDialogCommit', {
235 dataValue: html,
236 // Avoid error if there was no paste so lastDataTransfer is null.
237 dataTransfer: lastDataTransfer || clipboard.initPasteDataTransfer()
238 } );
239 }, 0 );
240 }
241 }
242 ]
243 } ]
244 };
245} );
246
247/**
248 * Internal event to pass paste dialog's data to the listeners.
249 *
250 * @private
251 * @event pasteDialogCommit
252 * @member CKEDITOR.editor
253 * @param {CKEDITOR.editor} editor This editor instance.
254 */
diff --git a/sources/plugins/clipboard/icons/copy-rtl.png b/sources/plugins/clipboard/icons/copy-rtl.png
new file mode 100644
index 0000000..ce94fc0
--- /dev/null
+++ b/sources/plugins/clipboard/icons/copy-rtl.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/copy.png b/sources/plugins/clipboard/icons/copy.png
new file mode 100644
index 0000000..ce94fc0
--- /dev/null
+++ b/sources/plugins/clipboard/icons/copy.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/cut-rtl.png b/sources/plugins/clipboard/icons/cut-rtl.png
new file mode 100644
index 0000000..8ae48d9
--- /dev/null
+++ b/sources/plugins/clipboard/icons/cut-rtl.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/cut.png b/sources/plugins/clipboard/icons/cut.png
new file mode 100644
index 0000000..8ae48d9
--- /dev/null
+++ b/sources/plugins/clipboard/icons/cut.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/hidpi/copy-rtl.png b/sources/plugins/clipboard/icons/hidpi/copy-rtl.png
new file mode 100644
index 0000000..74c6765
--- /dev/null
+++ b/sources/plugins/clipboard/icons/hidpi/copy-rtl.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/hidpi/copy.png b/sources/plugins/clipboard/icons/hidpi/copy.png
new file mode 100644
index 0000000..74c6765
--- /dev/null
+++ b/sources/plugins/clipboard/icons/hidpi/copy.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/hidpi/cut-rtl.png b/sources/plugins/clipboard/icons/hidpi/cut-rtl.png
new file mode 100644
index 0000000..f5a9b0d
--- /dev/null
+++ b/sources/plugins/clipboard/icons/hidpi/cut-rtl.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/hidpi/cut.png b/sources/plugins/clipboard/icons/hidpi/cut.png
new file mode 100644
index 0000000..f5a9b0d
--- /dev/null
+++ b/sources/plugins/clipboard/icons/hidpi/cut.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/hidpi/paste-rtl.png b/sources/plugins/clipboard/icons/hidpi/paste-rtl.png
new file mode 100644
index 0000000..12cac92
--- /dev/null
+++ b/sources/plugins/clipboard/icons/hidpi/paste-rtl.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/hidpi/paste.png b/sources/plugins/clipboard/icons/hidpi/paste.png
new file mode 100644
index 0000000..12cac92
--- /dev/null
+++ b/sources/plugins/clipboard/icons/hidpi/paste.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/paste-rtl.png b/sources/plugins/clipboard/icons/paste-rtl.png
new file mode 100644
index 0000000..7039251
--- /dev/null
+++ b/sources/plugins/clipboard/icons/paste-rtl.png
Binary files differ
diff --git a/sources/plugins/clipboard/icons/paste.png b/sources/plugins/clipboard/icons/paste.png
new file mode 100644
index 0000000..7039251
--- /dev/null
+++ b/sources/plugins/clipboard/icons/paste.png
Binary files differ
diff --git a/sources/plugins/clipboard/lang/af.js b/sources/plugins/clipboard/lang/af.js
new file mode 100644
index 0000000..f87522f
--- /dev/null
+++ b/sources/plugins/clipboard/lang/af.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'af', {
6 copy: 'Kopiëer',
7 copyError: 'U blaaier se sekuriteitsinstelling belet die kopiëringsaksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+C).',
8 cut: 'Knip',
9 cutError: 'U blaaier se sekuriteitsinstelling belet die outomatiese knip-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).',
10 paste: 'Plak',
11 pasteArea: 'Plak-area',
12 pasteMsg: 'Plak die teks in die volgende teks-area met die sleutelbordkombinasie (<STRONG>Ctrl/Cmd+V</STRONG>) en druk <STRONG>OK</STRONG>.',
13 securityMsg: 'Weens u blaaier se sekuriteitsinstelling is data op die knipbord nie toeganklik nie. U kan dit eers weer in hierdie venster plak.',
14 title: 'Byvoeg'
15} );
diff --git a/sources/plugins/clipboard/lang/ar.js b/sources/plugins/clipboard/lang/ar.js
new file mode 100644
index 0000000..aa96596
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ar.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ar', {
6 copy: 'نسخ',
7 copyError: 'الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع عمليات النسخ التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl/Cmd+C).',
8 cut: 'قص',
9 cutError: 'الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع القص التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl/Cmd+X).',
10 paste: 'لصق',
11 pasteArea: 'منطقة اللصق',
12 pasteMsg: 'الصق داخل الصندوق بإستخدام زرائر (<STRONG>Ctrl/Cmd+V</STRONG>) في لوحة المفاتيح، ثم اضغط زر <STRONG>موافق</STRONG>.',
13 securityMsg: 'نظراً لإعدادات الأمان الخاصة بمتصفحك، لن يتمكن هذا المحرر من الوصول لمحتوى حافظتك، لذلك يجب عليك لصق المحتوى مرة أخرى في هذه النافذة.',
14 title: 'لصق'
15} );
diff --git a/sources/plugins/clipboard/lang/az.js b/sources/plugins/clipboard/lang/az.js
new file mode 100644
index 0000000..1fc1a99
--- /dev/null
+++ b/sources/plugins/clipboard/lang/az.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'az', {
6 copy: 'Köçür',
7 copyError: 'Avtomatik köçürülməsi mümkün deyil. Ctrl+C basın.',
8 cut: 'Kəs',
9 cutError: 'Avtomatik kəsmə mümkün deyil. Ctrl+X basın.',
10 paste: 'Əlavə et',
11 pasteArea: 'Əlavəetmə sahəsi',
12 pasteMsg: 'Bu sahəyə əlavə edin (<strong>Ctrl+V</strong>)',
13 securityMsg: 'Mübadilə buferi açmaq mümkün deyil. Bu pəncərədə yenidən əlavə edin.',
14 title: 'Əlavə et'
15} );
diff --git a/sources/plugins/clipboard/lang/bg.js b/sources/plugins/clipboard/lang/bg.js
new file mode 100644
index 0000000..93a5a9c
--- /dev/null
+++ b/sources/plugins/clipboard/lang/bg.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'bg', {
6 copy: 'Копирай',
7 copyError: 'Настройките за сигурност на вашия бразуър не разрешават на редактора да изпълни запаметяването. За целта използвайте клавиатурата (Ctrl/Cmd+C).',
8 cut: 'Отрежи',
9 cutError: 'Настройките за сигурност на Вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. Моля ползвайте клавиатурните команди за целта (ctrl+x).',
10 paste: 'Вмъкни',
11 pasteArea: 'Зона за вмъкване',
12 pasteMsg: 'Вмъкнете тук съдъжанието с клавиатуарата (<STRONG>Ctrl/Cmd+V</STRONG>) и натиснете <STRONG>OK</STRONG>.',
13 securityMsg: 'Заради настройките за сигурност на Вашия браузър, редакторът не може да прочете данните от клипборда коректно.',
14 title: 'Вмъкни'
15} );
diff --git a/sources/plugins/clipboard/lang/bn.js b/sources/plugins/clipboard/lang/bn.js
new file mode 100644
index 0000000..f821fa0
--- /dev/null
+++ b/sources/plugins/clipboard/lang/bn.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'bn', {
6 copy: 'কপি',
7 copyError: 'আপনার ব্রাউজারের নিরাপত্তা সেটিংসমূহ এডিটরকে স্বয়ংক্রিয়ভাবে কপি করার প্রক্রিয়া চালনা করার অনুমতি দেয় না। অনুগ্রহপূর্বক এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl/Cmd+C)।',
8 cut: 'কাট',
9 cutError: 'আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কাট করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl/Cmd+X)।',
10 paste: 'পেস্ট',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'অনুগ্রহ করে নীচের বাক্সে কিবোর্ড ব্যবহার করে (<STRONG>Ctrl/Cmd+V</STRONG>) পেস্ট করুন এবং <STRONG>OK</STRONG> চাপ দিন',
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.', // MISSING
14 title: 'পেস্ট'
15} );
diff --git a/sources/plugins/clipboard/lang/bs.js b/sources/plugins/clipboard/lang/bs.js
new file mode 100644
index 0000000..1c23a61
--- /dev/null
+++ b/sources/plugins/clipboard/lang/bs.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'bs', {
6 copy: 'Kopiraj',
7 copyError: 'Sigurnosne postavke Vašeg pretraživaèa ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tastaturi (Ctrl/Cmd+C).',
8 cut: 'Izreži',
9 cutError: 'Sigurnosne postavke vašeg pretraživaèa ne dozvoljavaju operacije automatskog rezanja. Molimo koristite kraticu na tastaturi (Ctrl/Cmd+X).',
10 paste: 'Zalijepi',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK', // MISSING
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.', // MISSING
14 title: 'Zalijepi'
15} );
diff --git a/sources/plugins/clipboard/lang/ca.js b/sources/plugins/clipboard/lang/ca.js
new file mode 100644
index 0000000..52179c1
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ca.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ca', {
6 copy: 'Copiar',
7 copyError: 'La configuració de seguretat del vostre navegador no permet executar automàticament les operacions de copiar. Si us plau, utilitzeu el teclat (Ctrl/Cmd+C).',
8 cut: 'Retallar',
9 cutError: 'La configuració de seguretat del vostre navegador no permet executar automàticament les operacions de retallar. Si us plau, utilitzeu el teclat (Ctrl/Cmd+X).',
10 paste: 'Enganxar',
11 pasteArea: 'Àrea d\'enganxat',
12 pasteMsg: 'Si us plau, enganxi dins del següent camp utilitzant el teclat (<strong>Ctrl/Cmd+V</strong>) i premi OK.',
13 securityMsg: 'A causa de la configuració de seguretat del vostre navegador, l\'editor no pot accedir a les dades del porta-retalls directament. Enganxeu-ho un altre cop en aquesta finestra.',
14 title: 'Enganxar'
15} );
diff --git a/sources/plugins/clipboard/lang/cs.js b/sources/plugins/clipboard/lang/cs.js
new file mode 100644
index 0000000..7cf573e
--- /dev/null
+++ b/sources/plugins/clipboard/lang/cs.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'cs', {
6 copy: 'Kopírovat',
7 copyError: 'Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro kopírování zvoleného textu do schránky. Prosím zkopírujte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+C).',
8 cut: 'Vyjmout',
9 cutError: 'Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+X).',
10 paste: 'Vložit',
11 pasteArea: 'Oblast vkládání',
12 pasteMsg: 'Do následujícího pole vložte požadovaný obsah pomocí klávesnice (<STRONG>Ctrl/Cmd+V</STRONG>) a stiskněte <STRONG>OK</STRONG>.',
13 securityMsg: 'Z důvodů nastavení bezpečnosti vašeho prohlížeče nemůže editor přistupovat přímo do schránky. Obsah schránky prosím vložte znovu do tohoto okna.',
14 title: 'Vložit'
15} );
diff --git a/sources/plugins/clipboard/lang/cy.js b/sources/plugins/clipboard/lang/cy.js
new file mode 100644
index 0000000..00c5eeb
--- /dev/null
+++ b/sources/plugins/clipboard/lang/cy.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'cy', {
6 copy: 'Copïo',
7 copyError: '\'Dyw gosodiadau diogelwch eich porwr ddim yn caniatàu\'r golygydd i gynnal \'gweithredoedd copïo\' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl/Cmd+C).',
8 cut: 'Torri',
9 cutError: 'Nid yw gosodiadau diogelwch eich porwr yn caniatàu\'r golygydd i gynnal \'gweithredoedd torri\' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl/Cmd+X).',
10 paste: 'Gludo',
11 pasteArea: 'Ardal Gludo',
12 pasteMsg: 'Gludwch i mewn i\'r blwch canlynol gan ddefnyddio\'r bysellfwrdd (<strong>Ctrl/Cmd+V</strong>) a phwyso <strong>Iawn</strong>.',
13 securityMsg: 'Oherwydd gosodiadau diogelwch eich porwr, \'dyw\'r porwr ddim yn gallu ennill mynediad i\'r data ar y clipfwrdd yn uniongyrchol. Mae angen i chi ei ludo eto i\'r ffenestr hon.',
14 title: 'Gludo'
15} );
diff --git a/sources/plugins/clipboard/lang/da.js b/sources/plugins/clipboard/lang/da.js
new file mode 100644
index 0000000..c029016
--- /dev/null
+++ b/sources/plugins/clipboard/lang/da.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'da', {
6 copy: 'Kopiér',
7 copyError: 'Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.<br><br>Brug i stedet tastaturet til at kopiere teksten (Ctrl/Cmd+C).',
8 cut: 'Klip',
9 cutError: 'Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.<br><br>Brug i stedet tastaturet til at klippe teksten (Ctrl/Cmd+X).',
10 paste: 'Indsæt',
11 pasteArea: 'Indsæt område',
12 pasteMsg: 'Indsæt i feltet herunder (<STRONG>Ctrl/Cmd+V</STRONG>) og klik på <STRONG>OK</STRONG>.',
13 securityMsg: 'Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.<br><br>Du skal indsætte udklipsholderens indhold i dette vindue igen.',
14 title: 'Indsæt'
15} );
diff --git a/sources/plugins/clipboard/lang/de-ch.js b/sources/plugins/clipboard/lang/de-ch.js
new file mode 100644
index 0000000..325b100
--- /dev/null
+++ b/sources/plugins/clipboard/lang/de-ch.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'de-ch', {
6 copy: 'Kopieren',
7 copyError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).',
8 cut: 'Ausschneiden',
9 cutError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).',
10 paste: 'Einfügen',
11 pasteArea: 'Einfügebereich',
12 pasteMsg: 'Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit <STRONG>Strg+V</STRONG>) ein und bestätigen Sie mit <STRONG>OK</STRONG>.',
13 securityMsg: 'Aufgrund von Sicherheitsbeschränkungen Ihres Browsers kann der Editor nicht direkt auf die Zwischenablage zugreifen. Bitte fügen Sie den Inhalt erneut in diesem Fenster ein.',
14 title: 'Einfügen'
15} );
diff --git a/sources/plugins/clipboard/lang/de.js b/sources/plugins/clipboard/lang/de.js
new file mode 100644
index 0000000..2d6b30b
--- /dev/null
+++ b/sources/plugins/clipboard/lang/de.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'de', {
6 copy: 'Kopieren',
7 copyError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).',
8 cut: 'Ausschneiden',
9 cutError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).',
10 paste: 'Einfügen',
11 pasteArea: 'Einfügebereich',
12 pasteMsg: 'Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit <STRONG>Strg+V</STRONG>) ein und bestätigen Sie mit <STRONG>OK</STRONG>.',
13 securityMsg: 'Aufgrund von Sicherheitsbeschränkungen Ihres Browsers kann der Editor nicht direkt auf die Zwischenablage zugreifen. Bitte fügen Sie den Inhalt erneut in diesem Fenster ein.',
14 title: 'Einfügen'
15} );
diff --git a/sources/plugins/clipboard/lang/el.js b/sources/plugins/clipboard/lang/el.js
new file mode 100644
index 0000000..0528840
--- /dev/null
+++ b/sources/plugins/clipboard/lang/el.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'el', {
6 copy: 'Αντιγραφή',
7 copyError: 'Οι ρυθμίσεις ασφαλείας του περιηγητή σας δεν επιτρέπουν την επιλεγμένη εργασία αντιγραφής. Παρακαλώ χρησιμοποιείστε το πληκτρολόγιο (Ctrl/Cmd+C).',
8 cut: 'Αποκοπή',
9 cutError: 'Οι ρυθμίσεις ασφαλείας του περιηγητή σας δεν επιτρέπουν την επιλεγμένη εργασία αποκοπής. Παρακαλώ χρησιμοποιείστε το πληκτρολόγιο (Ctrl/Cmd+X).',
10 paste: 'Επικόλληση',
11 pasteArea: 'Περιοχή Επικόλλησης',
12 pasteMsg: 'Παρακαλώ επικολλήστε στο ακόλουθο κουτί χρησιμοποιώντας το πληκτρολόγιο (<strong>Ctrl/Cmd+V</strong>) και πατήστε OK.',
13 securityMsg: 'Λόγων των ρυθμίσεων ασφάλειας του περιηγητή σας, ο επεξεργαστής δεν μπορεί να έχει πρόσβαση στην μνήμη επικόλλησης. Χρειάζεται να επικολλήσετε ξανά σε αυτό το παράθυρο.',
14 title: 'Επικόλληση'
15} );
diff --git a/sources/plugins/clipboard/lang/en-au.js b/sources/plugins/clipboard/lang/en-au.js
new file mode 100644
index 0000000..5c497fb
--- /dev/null
+++ b/sources/plugins/clipboard/lang/en-au.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'en-au', {
6 copy: 'Copy',
7 copyError: 'Your browser security settings don\'t permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).',
8 cut: 'Cut',
9 cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).',
10 paste: 'Paste',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK',
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.',
14 title: 'Paste'
15} );
diff --git a/sources/plugins/clipboard/lang/en-ca.js b/sources/plugins/clipboard/lang/en-ca.js
new file mode 100644
index 0000000..036ebab
--- /dev/null
+++ b/sources/plugins/clipboard/lang/en-ca.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'en-ca', {
6 copy: 'Copy',
7 copyError: 'Your browser security settings don\'t permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).',
8 cut: 'Cut',
9 cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).',
10 paste: 'Paste',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK',
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.',
14 title: 'Paste'
15} );
diff --git a/sources/plugins/clipboard/lang/en-gb.js b/sources/plugins/clipboard/lang/en-gb.js
new file mode 100644
index 0000000..bb511ce
--- /dev/null
+++ b/sources/plugins/clipboard/lang/en-gb.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'en-gb', {
6 copy: 'Copy',
7 copyError: 'Your browser security settings don\'t permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).',
8 cut: 'Cut',
9 cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).',
10 paste: 'Paste',
11 pasteArea: 'Paste Area',
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK',
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.',
14 title: 'Paste'
15} );
diff --git a/sources/plugins/clipboard/lang/en.js b/sources/plugins/clipboard/lang/en.js
new file mode 100644
index 0000000..4db6960
--- /dev/null
+++ b/sources/plugins/clipboard/lang/en.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'en', {
6 copy: 'Copy',
7 copyError: 'Your browser security settings don\'t permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).',
8 cut: 'Cut',
9 cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).',
10 paste: 'Paste',
11 pasteArea: 'Paste Area',
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK',
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.',
14 title: 'Paste'
15} );
diff --git a/sources/plugins/clipboard/lang/eo.js b/sources/plugins/clipboard/lang/eo.js
new file mode 100644
index 0000000..2df4150
--- /dev/null
+++ b/sources/plugins/clipboard/lang/eo.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'eo', {
6 copy: 'Kopii',
7 copyError: 'La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras kopiajn operaciojn. Bonvolu uzi la klavaron por tio (Ctrl/Cmd-C).',
8 cut: 'Eltondi',
9 cutError: 'La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras eltondajn operaciojn. Bonvolu uzi la klavaron por tio (Ctrl/Cmd-X).',
10 paste: 'Interglui',
11 pasteArea: 'Intergluoareo',
12 pasteMsg: 'Bonvolu glui la tekston en la jenan areon per uzado de la klavaro (<strong>Ctrl/Cmd+V</strong>) kaj premu OK',
13 securityMsg: 'Pro la sekurecagordo de via TTT-legilo, la redaktilo ne povas rekte atingi viajn datenojn en la poŝo. Bonvolu denove interglui la datenojn en tiun fenestron.',
14 title: 'Interglui'
15} );
diff --git a/sources/plugins/clipboard/lang/es.js b/sources/plugins/clipboard/lang/es.js
new file mode 100644
index 0000000..c455992
--- /dev/null
+++ b/sources/plugins/clipboard/lang/es.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'es', {
6 copy: 'Copiar',
7 copyError: 'La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de copiado.\r\nPor favor use el teclado (Ctrl/Cmd+C).',
8 cut: 'Cortar',
9 cutError: 'La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado.\r\nPor favor use el teclado (Ctrl/Cmd+X).',
10 paste: 'Pegar',
11 pasteArea: 'Zona de pegado',
12 pasteMsg: 'Por favor pegue dentro del cuadro utilizando el teclado (<STRONG>Ctrl/Cmd+V</STRONG>);\r\nluego presione <STRONG>Aceptar</STRONG>.',
13 securityMsg: 'Debido a la configuración de seguridad de su navegador, el editor no tiene acceso al portapapeles.\r\nEs necesario que lo pegue de nuevo en esta ventana.',
14 title: 'Pegar'
15} );
diff --git a/sources/plugins/clipboard/lang/et.js b/sources/plugins/clipboard/lang/et.js
new file mode 100644
index 0000000..7d86b30
--- /dev/null
+++ b/sources/plugins/clipboard/lang/et.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'et', {
6 copy: 'Kopeeri',
7 copyError: 'Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt kopeerida. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+C).',
8 cut: 'Lõika',
9 cutError: 'Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).',
10 paste: 'Aseta',
11 pasteArea: 'Asetamise ala',
12 pasteMsg: 'Palun aseta tekst järgnevasse kasti kasutades klaviatuuri klahvikombinatsiooni (<STRONG>Ctrl/Cmd+V</STRONG>) ja vajuta seejärel <STRONG>OK</STRONG>.',
13 securityMsg: 'Sinu veebisirvija turvaseadete tõttu ei oma redaktor otsest ligipääsu lõikelaua andmetele. Sa pead asetama need uuesti siia aknasse.',
14 title: 'Asetamine'
15} );
diff --git a/sources/plugins/clipboard/lang/eu.js b/sources/plugins/clipboard/lang/eu.js
new file mode 100644
index 0000000..93240b5
--- /dev/null
+++ b/sources/plugins/clipboard/lang/eu.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'eu', {
6 copy: 'Kopiatu',
7 copyError: 'Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki kopiatzea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+C).',
8 cut: 'Ebaki',
9 cutError: 'Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki moztea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+X).',
10 paste: 'Itsatsi',
11 pasteArea: 'Itsasteko area',
12 pasteMsg: 'Mesedez teklatua erabiliz (<strong>Ctrl/Cmd+V</strong>) ondorengo eremuan testua itsatsi eta sakatu <strong>Ados</strong>.',
13 securityMsg: 'Nabigatzailearen segurtasun ezarpenak direla eta, editoreak ezin du arbela zuzenean erabili. Leiho honetan berriro itsatsi behar duzu.',
14 title: 'Itsatsi'
15} );
diff --git a/sources/plugins/clipboard/lang/fa.js b/sources/plugins/clipboard/lang/fa.js
new file mode 100644
index 0000000..8abee21
--- /dev/null
+++ b/sources/plugins/clipboard/lang/fa.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'fa', {
6 copy: 'رونوشت',
7 copyError: 'تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای کپی کردن را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+C).',
8 cut: 'برش',
9 cutError: 'تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).',
10 paste: 'چسباندن',
11 pasteArea: 'محل چسباندن',
12 pasteMsg: 'لطفا متن را با کلیدهای (<STRONG>Ctrl/Cmd+V</STRONG>) در این جعبهٴ متنی بچسبانید و <STRONG>پذیرش</STRONG> را بزنید.',
13 securityMsg: 'به خاطر تنظیمات امنیتی مرورگر شما، ویرایشگر نمیتواند دسترسی مستقیم به دادههای clipboard داشته باشد. شما باید دوباره آنرا در این پنجره بچسبانید.',
14 title: 'چسباندن'
15} );
diff --git a/sources/plugins/clipboard/lang/fi.js b/sources/plugins/clipboard/lang/fi.js
new file mode 100644
index 0000000..d165fb3
--- /dev/null
+++ b/sources/plugins/clipboard/lang/fi.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'fi', {
6 copy: 'Kopioi',
7 copyError: 'Selaimesi turva-asetukset eivät salli editorin toteuttaa kopioimista. Käytä näppäimistöä kopioimiseen (Ctrl+C).',
8 cut: 'Leikkaa',
9 cutError: 'Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).',
10 paste: 'Liitä',
11 pasteArea: 'Leikealue',
12 pasteMsg: 'Liitä painamalla (<STRONG>Ctrl+V</STRONG>) ja painamalla <STRONG>OK</STRONG>.',
13 securityMsg: 'Selaimesi turva-asetukset eivät salli editorin käyttää leikepöytää suoraan. Sinun pitää suorittaa liittäminen tässä ikkunassa.',
14 title: 'Liitä'
15} );
diff --git a/sources/plugins/clipboard/lang/fo.js b/sources/plugins/clipboard/lang/fo.js
new file mode 100644
index 0000000..5c1ec8a
--- /dev/null
+++ b/sources/plugins/clipboard/lang/fo.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'fo', {
6 copy: 'Avrita',
7 copyError: 'Trygdaruppseting alnótskagans forðar tekstviðgeranum í at avrita tekstin. Vinarliga nýt knappaborðið til at avrita tekstin (Ctrl/Cmd+C).',
8 cut: 'Kvett',
9 cutError: 'Trygdaruppseting alnótskagans forðar tekstviðgeranum í at kvetta tekstin. Vinarliga nýt knappaborðið til at kvetta tekstin (Ctrl/Cmd+X).',
10 paste: 'Innrita',
11 pasteArea: 'Avritingarumráði',
12 pasteMsg: 'Vinarliga koyr tekstin í hendan rútin við knappaborðinum (<strong>Ctrl/Cmd+V</strong>) og klikk á <strong>Góðtak</strong>.',
13 securityMsg: 'Trygdaruppseting alnótskagans forðar tekstviðgeranum í beinleiðis atgongd til avritingarminnið. Tygum mugu royna aftur í hesum rútinum.',
14 title: 'Innrita'
15} );
diff --git a/sources/plugins/clipboard/lang/fr-ca.js b/sources/plugins/clipboard/lang/fr-ca.js
new file mode 100644
index 0000000..3425f56
--- /dev/null
+++ b/sources/plugins/clipboard/lang/fr-ca.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'fr-ca', {
6 copy: 'Copier',
7 copyError: 'Les paramètres de sécurité de votre navigateur empêchent l\'éditeur de copier automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl/Cmd+C).',
8 cut: 'Couper',
9 cutError: 'Les paramètres de sécurité de votre navigateur empêchent l\'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl/Cmd+X).',
10 paste: 'Coller',
11 pasteArea: 'Coller la zone',
12 pasteMsg: 'Veuillez coller dans la zone ci-dessous en utilisant le clavier (<STRONG>Ctrl/Cmd+V</STRONG>) et appuyer sur <STRONG>OK</STRONG>.',
13 securityMsg: 'A cause des paramètres de sécurité de votre navigateur, l\'éditeur ne peut accéder au presse-papier directement. Vous devez coller à nouveau le contenu dans cette fenêtre.',
14 title: 'Coller'
15} );
diff --git a/sources/plugins/clipboard/lang/fr.js b/sources/plugins/clipboard/lang/fr.js
new file mode 100644
index 0000000..bb8349f
--- /dev/null
+++ b/sources/plugins/clipboard/lang/fr.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'fr', {
6 copy: 'Copier',
7 copyError: 'Les paramètres de sécurité de votre navigateur n\'autorisent pas l\'éditeur à exécuter automatiquement l\'opération « Copier ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+C).',
8 cut: 'Couper',
9 cutError: 'Les paramètres de sécurité de votre navigateur n\'autorisent pas l\'éditeur à exécuter automatiquement l\'opération « Couper ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+X).',
10 paste: 'Coller',
11 pasteArea: 'Coller la zone',
12 pasteMsg: 'Veuillez coller le texte dans la zone suivante en utilisant le raccourci clavier (<strong>Ctrl/Cmd+V</strong>) et cliquez sur OK.',
13 securityMsg: 'Les paramètres de sécurité de votre navigateur empêchent l\'éditeur d\'accéder directement aux données du presse-papier. Vous devez les coller à nouveau dans cette fenêtre.',
14 title: 'Coller'
15} );
diff --git a/sources/plugins/clipboard/lang/gl.js b/sources/plugins/clipboard/lang/gl.js
new file mode 100644
index 0000000..3c89dd0
--- /dev/null
+++ b/sources/plugins/clipboard/lang/gl.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'gl', {
6 copy: 'Copiar',
7 copyError: 'Os axustes de seguranza do seu navegador non permiten que o editor realice automaticamente as tarefas de copia. Use o teclado para iso (Ctrl/Cmd+C).',
8 cut: 'Cortar',
9 cutError: 'Os axustes de seguranza do seu navegador non permiten que o editor realice automaticamente as tarefas de corte. Use o teclado para iso (Ctrl/Cmd+X).',
10 paste: 'Pegar',
11 pasteArea: 'Zona de pegado',
12 pasteMsg: 'Pegue dentro do seguinte cadro usando o teclado (<STRONG>Ctrl/Cmd+V</STRONG>) e prema en Aceptar',
13 securityMsg: 'Por mor da configuración de seguranza do seu navegador, o editor non ten acceso ao portapapeis. É necesario pegalo novamente nesta xanela.',
14 title: 'Pegar'
15} );
diff --git a/sources/plugins/clipboard/lang/gu.js b/sources/plugins/clipboard/lang/gu.js
new file mode 100644
index 0000000..fcf039a
--- /dev/null
+++ b/sources/plugins/clipboard/lang/gu.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'gu', {
6 copy: 'નકલ',
7 copyError: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસ કોપી કરવાની પરવાનગી નથી આપતી. (Ctrl/Cmd+C) का प्रयोग करें।',
8 cut: 'કાપવું',
9 cutError: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસ કટ કરવાની પરવાનગી નથી આપતી. (Ctrl/Cmd+X) નો ઉપયોગ કરો.',
10 paste: 'પેસ્ટ',
11 pasteArea: 'પેસ્ટ કરવાની જગ્યા',
12 pasteMsg: 'Ctrl/Cmd+V નો પ્રયોગ કરી પેસ્ટ કરો',
13 securityMsg: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસના કારણે,એડિટર તમારા કિલ્પબોર્ડ ડેટા ને કોપી નથી કરી શકતો. તમારે આ વિન્ડોમાં ફરીથી પેસ્ટ કરવું પડશે.',
14 title: 'પેસ્ટ'
15} );
diff --git a/sources/plugins/clipboard/lang/he.js b/sources/plugins/clipboard/lang/he.js
new file mode 100644
index 0000000..a3726c3
--- /dev/null
+++ b/sources/plugins/clipboard/lang/he.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'he', {
6 copy: 'העתקה',
7 copyError: 'הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות העתקה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+C).',
8 cut: 'גזירה',
9 cutError: 'הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות גזירה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+X).',
10 paste: 'הדבקה',
11 pasteArea: 'איזור הדבקה',
12 pasteMsg: 'נא להדביק בתוך הקופסה באמצעות (<b>Ctrl/Cmd+V</b>) וללחוץ על <b>אישור</b>.',
13 securityMsg: 'עקב הגדרות אבטחה בדפדפן, לא ניתן לגשת אל לוח הגזירים (Clipboard) בצורה ישירה. נא להדביק שוב בחלון זה.',
14 title: 'הדבקה'
15} );
diff --git a/sources/plugins/clipboard/lang/hi.js b/sources/plugins/clipboard/lang/hi.js
new file mode 100644
index 0000000..738b0b9
--- /dev/null
+++ b/sources/plugins/clipboard/lang/hi.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'hi', {
6 copy: 'कॉपी',
7 copyError: 'आपके ब्राआउज़र की सुरक्षा सॅटिन्ग्स ने कॉपी करने की अनुमति नहीं प्रदान की है। (Ctrl/Cmd+C) का प्रयोग करें।',
8 cut: 'कट',
9 cutError: 'आपके ब्राउज़र की सुरक्षा सॅटिन्ग्स ने कट करने की अनुमति नहीं प्रदान की है। (Ctrl/Cmd+X) का प्रयोग करें।',
10 paste: 'पेस्ट',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'Ctrl/Cmd+V का प्रयोग करके पेस्ट करें और ठीक है करें.',
13 securityMsg: 'आपके ब्राउज़र की सुरक्षा आपके ब्राउज़र की सुरKश सैटिंग के कारण, एडिटर आपके क्लिपबोर्ड डेटा को नहीं पा सकता है. आपको उसे इस विन्डो में दोबारा पेस्ट करना होगा.',
14 title: 'पेस्ट'
15} );
diff --git a/sources/plugins/clipboard/lang/hr.js b/sources/plugins/clipboard/lang/hr.js
new file mode 100644
index 0000000..7366069
--- /dev/null
+++ b/sources/plugins/clipboard/lang/hr.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'hr', {
6 copy: 'Kopiraj',
7 copyError: 'Sigurnosne postavke Vašeg pretraživača ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tipkovnici (Ctrl/Cmd+C).',
8 cut: 'Izreži',
9 cutError: 'Sigurnosne postavke Vašeg pretraživača ne dozvoljavaju operacije automatskog izrezivanja. Molimo koristite kraticu na tipkovnici (Ctrl/Cmd+X).',
10 paste: 'Zalijepi',
11 pasteArea: 'Prostor za ljepljenje',
12 pasteMsg: 'Molimo zaljepite unutar doljnjeg okvira koristeći tipkovnicu (<STRONG>Ctrl/Cmd+V</STRONG>) i kliknite <STRONG>OK</STRONG>.',
13 securityMsg: 'Zbog sigurnosnih postavki Vašeg pretraživača, editor nema direktan pristup Vašem međuspremniku. Potrebno je ponovno zalijepiti tekst u ovaj prozor.',
14 title: 'Zalijepi'
15} );
diff --git a/sources/plugins/clipboard/lang/hu.js b/sources/plugins/clipboard/lang/hu.js
new file mode 100644
index 0000000..b124e35
--- /dev/null
+++ b/sources/plugins/clipboard/lang/hu.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'hu', {
6 copy: 'Másolás',
7 copyError: 'A böngésző biztonsági beállításai nem engedélyezik a szerkesztőnek, hogy végrehajtsa a másolás műveletet. Használja az alábbi billentyűkombinációt (Ctrl/Cmd+X).',
8 cut: 'Kivágás',
9 cutError: 'A böngésző biztonsági beállításai nem engedélyezik a szerkesztőnek, hogy végrehajtsa a kivágás műveletet. Használja az alábbi billentyűkombinációt (Ctrl/Cmd+X).',
10 paste: 'Beillesztés',
11 pasteArea: 'Beszúrás mező',
12 pasteMsg: 'Másolja be az alábbi mezőbe a <STRONG>Ctrl/Cmd+V</STRONG> billentyűk lenyomásával, majd nyomjon <STRONG>Rendben</STRONG>-t.',
13 securityMsg: 'A böngésző biztonsági beállításai miatt a szerkesztő nem képes hozzáférni a vágólap adataihoz. Illeszd be újra ebben az ablakban.',
14 title: 'Beillesztés'
15} );
diff --git a/sources/plugins/clipboard/lang/id.js b/sources/plugins/clipboard/lang/id.js
new file mode 100644
index 0000000..e7b40ad
--- /dev/null
+++ b/sources/plugins/clipboard/lang/id.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'id', {
6 copy: 'Salin',
7 copyError: 'Pengaturan keamanan peramban anda tidak mengizinkan editor untuk mengeksekusi operasi menyalin secara otomatis. Mohon gunakan papan tuts (Ctrl/Cmd+C)',
8 cut: 'Potong',
9 cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', // MISSING
10 paste: 'Tempel',
11 pasteArea: 'Area Tempel',
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK', // MISSING
13 securityMsg: 'Karena pengaturan keamanan peramban anda, editor tida dapat mengakses data clipboard anda secara langsung. Anda harus mem-paste kembali pada halaman ini',
14 title: 'Tempel'
15} );
diff --git a/sources/plugins/clipboard/lang/is.js b/sources/plugins/clipboard/lang/is.js
new file mode 100644
index 0000000..6b36cef
--- /dev/null
+++ b/sources/plugins/clipboard/lang/is.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'is', {
6 copy: 'Afrita',
7 copyError: 'Öryggisstillingar vafrans þíns leyfa ekki afritun texta með músaraðgerð. Notaðu lyklaborðið í afrita (Ctrl/Cmd+C).',
8 cut: 'Klippa',
9 cutError: 'Öryggisstillingar vafrans þíns leyfa ekki klippingu texta með músaraðgerð. Notaðu lyklaborðið í klippa (Ctrl/Cmd+X).',
10 paste: 'Líma',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'Límdu í svæðið hér að neðan og (<STRONG>Ctrl/Cmd+V</STRONG>) og smelltu á <STRONG>OK</STRONG>.',
13 securityMsg: 'Vegna öryggisstillinga í vafranum þínum fær ritillinn ekki beinan aðgang að klippuborðinu. Þú verður að líma innihaldið aftur inn í þennan glugga.',
14 title: 'Líma'
15} );
diff --git a/sources/plugins/clipboard/lang/it.js b/sources/plugins/clipboard/lang/it.js
new file mode 100644
index 0000000..21f8815
--- /dev/null
+++ b/sources/plugins/clipboard/lang/it.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'it', {
6 copy: 'Copia',
7 copyError: 'Le impostazioni di sicurezza del browser non permettono di copiare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+C).',
8 cut: 'Taglia',
9 cutError: 'Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+X).',
10 paste: 'Incolla',
11 pasteArea: 'Incolla',
12 pasteMsg: 'Incolla il testo all\'interno dell\'area sottostante usando la scorciatoia di tastiere (<STRONG>Ctrl/Cmd+V</STRONG>) e premi <STRONG>OK</STRONG>.',
13 securityMsg: 'A causa delle impostazioni di sicurezza del browser,l\'editor non è in grado di accedere direttamente agli appunti. E\' pertanto necessario incollarli di nuovo in questa finestra.',
14 title: 'Incolla'
15} );
diff --git a/sources/plugins/clipboard/lang/ja.js b/sources/plugins/clipboard/lang/ja.js
new file mode 100644
index 0000000..f099380
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ja.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ja', {
6 copy: 'コピー',
7 copyError: 'ブラウザーのセキュリティ設定によりエディタのコピー操作を自動で実行することができません。実行するには手動でキーボードの(Ctrl/Cmd+C)を使用してください。',
8 cut: '切り取り',
9 cutError: 'ブラウザーのセキュリティ設定によりエディタの切り取り操作を自動で実行することができません。実行するには手動でキーボードの(Ctrl/Cmd+X)を使用してください。',
10 paste: '貼り付け',
11 pasteArea: '貼り付け場所',
12 pasteMsg: 'キーボード(<STRONG>Ctrl/Cmd+V</STRONG>)を使用して、次の入力エリア内で貼り付けて、<STRONG>OK</STRONG>を押してください。',
13 securityMsg: 'ブラウザのセキュリティ設定により、エディタはクリップボードデータに直接アクセスすることができません。このウィンドウは貼り付け操作を行う度に表示されます。',
14 title: '貼り付け'
15} );
diff --git a/sources/plugins/clipboard/lang/ka.js b/sources/plugins/clipboard/lang/ka.js
new file mode 100644
index 0000000..e1af8cb
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ka.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ka', {
6 copy: 'ასლი',
7 copyError: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა ასლის ოპერაციის ავტომატურად განხორციელების საშუალებას. გამოიყენეთ კლავიატურა ამისთვის (Ctrl/Cmd+C).',
8 cut: 'ამოჭრა',
9 cutError: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა ამოჭრის ოპერაციის ავტომატურად განხორციელების საშუალებას. გამოიყენეთ კლავიატურა ამისთვის (Ctrl/Cmd+X).',
10 paste: 'ჩასმა',
11 pasteArea: 'ჩასმის არე',
12 pasteMsg: 'ჩასვით ამ არის შიგნით კლავიატურის გამოყენებით (<strong>Ctrl/Cmd+V</strong>) და დააჭირეთ OK-ს',
13 securityMsg: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა clipboard-ის მონაცემების წვდომის უფლებას. კიდევ უნდა ჩასვათ ტექსტი ამ ფანჯარაში.',
14 title: 'ჩასმა'
15} );
diff --git a/sources/plugins/clipboard/lang/km.js b/sources/plugins/clipboard/lang/km.js
new file mode 100644
index 0000000..32c30cb
--- /dev/null
+++ b/sources/plugins/clipboard/lang/km.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'km', {
6 copy: 'ចម្លង',
7 copyError: 'ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ ចំលងអត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl/Cmd+C)។',
8 cut: 'កាត់យក',
9 cutError: 'ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ កាត់អត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl/Cmd+X) ។',
10 paste: 'បិទ​ភ្ជាប់',
11 pasteArea: 'តំបន់​បិទ​ភ្ជាប់',
12 pasteMsg: 'សូមចំលងអត្ថបទទៅដាក់ក្នុងប្រអប់ដូចខាងក្រោមដោយប្រើប្រាស់ ឃី ​(<STRONG>Ctrl/Cmd+V</STRONG>) ហើយចុច <STRONG>OK</STRONG> ។',
13 securityMsg: 'ព្រោះតែ​ការកំណត់​សុវត្ថិភាព ប្រអប់សរសេរ​មិន​អាចចាប់​យកទិន្នន័យពីក្តារតម្បៀតខ្ទាស់​អ្នក​​ដោយផ្ទាល់​បានទេ។ អ្នក​ត្រូវចំលង​ដាក់វាម្តង​ទៀត ក្នុងផ្ទាំងនេះ។',
14 title: 'បិទ​ភ្ជាប់'
15} );
diff --git a/sources/plugins/clipboard/lang/ko.js b/sources/plugins/clipboard/lang/ko.js
new file mode 100644
index 0000000..0a0d1e9
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ko.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ko', {
6 copy: '복사',
7 copyError: '브라우저의 보안설정 때문에 복사할 수 없습니다. 키보드(Ctrl/Cmd+C)를 이용해서 복사하십시오.',
8 cut: '잘라내기',
9 cutError: '브라우저의 보안설정 때문에 잘라내기 기능을 실행할 수 없습니다. 키보드(Ctrl/Cmd+X)를 이용해서 잘라내기 하십시오',
10 paste: '붙여넣기',
11 pasteArea: '붙여넣기 범위',
12 pasteMsg: '키보드(<strong>Ctrl/Cmd+V</strong>)를 이용해서 상자안에 붙여넣고 <strong>확인</strong> 를 누르세요.',
13 securityMsg: '브라우저 보안 설정으로 인해, 클립보드에 직접 접근할 수 없습니다. 이 창에 다시 붙여넣기 하십시오.',
14 title: '붙여넣기'
15} );
diff --git a/sources/plugins/clipboard/lang/ku.js b/sources/plugins/clipboard/lang/ku.js
new file mode 100644
index 0000000..86e1778
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ku.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ku', {
6 copy: 'لەبەرگرتنەوە',
7 copyError: 'پارێزی وێبگەڕەکەت ڕێگەنادات بەسەرنووسەکە لە لکاندنی دەقی خۆکارارنە. تکایە لەبری ئەمە ئەم فەرمانە بەکاربهێنە بەداگرتنی کلیلی (Ctrl/Cmd+C).',
8 cut: 'بڕین',
9 cutError: 'پارێزی وێبگەڕەکەت ڕێگەنادات بە سەرنووسەکە لەبڕینی خۆکارانە. تکایە لەبری ئەمە ئەم فەرمانە بەکاربهێنە بەداگرتنی کلیلی (Ctrl/Cmd+X).',
10 paste: 'لکاندن',
11 pasteArea: 'ناوچەی لکاندن',
12 pasteMsg: 'تکایە بیلکێنە لەناوەوەی ئەم سنوقە لەڕێی تەختەکلیلەکەت بە بەکارهێنانی کلیلی (<STRONG>Ctrl/Cmd+V</STRONG>) دووای کلیکی باشە بکە.',
13 securityMsg: 'بەهۆی شێوەپێدانی پارێزی وێبگەڕەکەت، سەرنووسەکه ناتوانێت دەستبگەیەنێت بەهەڵگیراوەکە ڕاستەوخۆ. بۆیه پێویسته دووباره بیلکێنیت لەم پەنجەرەیه.',
14 title: 'لکاندن'
15} );
diff --git a/sources/plugins/clipboard/lang/lt.js b/sources/plugins/clipboard/lang/lt.js
new file mode 100644
index 0000000..86ecbbb
--- /dev/null
+++ b/sources/plugins/clipboard/lang/lt.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'lt', {
6 copy: 'Kopijuoti',
7 copyError: 'Jūsų naršyklės saugumo nustatymai neleidžia redaktoriui automatiškai įvykdyti kopijavimo operacijų. Tam prašome naudoti klaviatūrą (Ctrl/Cmd+C).',
8 cut: 'Iškirpti',
9 cutError: 'Jūsų naršyklės saugumo nustatymai neleidžia redaktoriui automatiškai įvykdyti iškirpimo operacijų. Tam prašome naudoti klaviatūrą (Ctrl/Cmd+X).',
10 paste: 'Įdėti',
11 pasteArea: 'Įkelti dalį',
12 pasteMsg: 'Žemiau esančiame įvedimo lauke įdėkite tekstą, naudodami klaviatūrą (<STRONG>Ctrl/Cmd+V</STRONG>) ir paspauskite mygtuką <STRONG>OK</STRONG>.',
13 securityMsg: 'Dėl jūsų naršyklės saugumo nustatymų, redaktorius negali tiesiogiai pasiekti laikinosios atminties. Jums reikia nukopijuoti dar kartą į šį langą.',
14 title: 'Įdėti'
15} );
diff --git a/sources/plugins/clipboard/lang/lv.js b/sources/plugins/clipboard/lang/lv.js
new file mode 100644
index 0000000..c762fc6
--- /dev/null
+++ b/sources/plugins/clipboard/lang/lv.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'lv', {
6 copy: 'Kopēt',
7 copyError: 'Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt kopēšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+C), lai veiktu šo darbību.',
8 cut: 'Izgriezt',
9 cutError: 'Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt izgriezšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+X), lai veiktu šo darbību.',
10 paste: 'Ielīmēt',
11 pasteArea: 'Ielīmēšanas zona',
12 pasteMsg: 'Lūdzu, ievietojiet tekstu šajā laukumā, izmantojot klaviatūru (<STRONG>Ctrl/Cmd+V</STRONG>) un apstipriniet ar <STRONG>Darīts!</STRONG>.',
13 securityMsg: 'Jūsu pārlūka drošības uzstādījumu dēļ, nav iespējams tieši piekļūt jūsu starpliktuvei. Jums jāielīmē atkārtoti šajā logā.',
14 title: 'Ievietot'
15} );
diff --git a/sources/plugins/clipboard/lang/mk.js b/sources/plugins/clipboard/lang/mk.js
new file mode 100644
index 0000000..eb16066
--- /dev/null
+++ b/sources/plugins/clipboard/lang/mk.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'mk', {
6 copy: 'Копирај (Copy)',
7 copyError: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот автоматски да изврши копирање. Ве молиме употребете ја тастатурата. (Ctrl/Cmd+C)',
8 cut: 'Исечи (Cut)',
9 cutError: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот автоматски да изврши сечење. Ве молиме употребете ја тастатурата. (Ctrl/Cmd+C)',
10 paste: 'Залепи (Paste)',
11 pasteArea: 'Простор за залепување',
12 pasteMsg: 'Ве молиме да залепите во следниот квадрат користејќи ја тастатурата (<string>Ctrl/Cmd+V</string>) и да притиснете OK',
13 securityMsg: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот директно да пристапи до копираните податоци. Потребно е повторно да се обидете во овој прозорец.',
14 title: 'Залепи (Paste)'
15} );
diff --git a/sources/plugins/clipboard/lang/mn.js b/sources/plugins/clipboard/lang/mn.js
new file mode 100644
index 0000000..5351941
--- /dev/null
+++ b/sources/plugins/clipboard/lang/mn.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'mn', {
6 copy: 'Хуулах',
7 copyError: 'Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хуулах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl/Cmd+C) товчны хослолыг ашиглана уу.',
8 cut: 'Хайчлах',
9 cutError: 'Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хайчлах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl/Cmd+X) товчны хослолыг ашиглана уу.',
10 paste: 'Буулгах',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: '(<strong>Ctrl/Cmd+V</strong>) товчийг ашиглан paste хийнэ үү. Мөн <strong>OK</strong> дар.',
13 securityMsg: 'Таны үзүүлэгч/browser/-н хамгаалалтын тохиргооноос болоод editor clipboard өгөгдөлрүү шууд хандах боломжгүй. Энэ цонход дахин paste хийхийг оролд.',
14 title: 'Буулгах'
15} );
diff --git a/sources/plugins/clipboard/lang/ms.js b/sources/plugins/clipboard/lang/ms.js
new file mode 100644
index 0000000..3a01be4
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ms.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ms', {
6 copy: 'Salin',
7 copyError: 'Keselamatan perisian browser anda tidak membenarkan operasi salinan text/imej. Sila gunakan papan kekunci (Ctrl/Cmd+C).',
8 cut: 'Potong',
9 cutError: 'Keselamatan perisian browser anda tidak membenarkan operasi suntingan text/imej. Sila gunakan papan kekunci (Ctrl/Cmd+X).',
10 paste: 'Tampal',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK', // MISSING
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.', // MISSING
14 title: 'Tampal'
15} );
diff --git a/sources/plugins/clipboard/lang/nb.js b/sources/plugins/clipboard/lang/nb.js
new file mode 100644
index 0000000..5355b8a
--- /dev/null
+++ b/sources/plugins/clipboard/lang/nb.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'nb', {
6 copy: 'Kopier',
7 copyError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk kopiering av tekst. Vennligst bruk tastatursnarveien (Ctrl/Cmd+C).',
8 cut: 'Klipp ut',
9 cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk tastatursnarveien (Ctrl/Cmd+X).',
10 paste: 'Lim inn',
11 pasteArea: 'Innlimingsområde',
12 pasteMsg: 'Vennligst lim inn i følgende boks med tastaturet (<strong>Ctrl/Cmd+V</strong>) og trykk <strong>OK</strong>.',
13 securityMsg: 'Din nettlesers sikkerhetsinstillinger gir ikke redigeringsverktøyet direkte tilgang til utklippstavlen. Du må derfor lime det inn på nytt i dette vinduet.',
14 title: 'Lim inn'
15} );
diff --git a/sources/plugins/clipboard/lang/nl.js b/sources/plugins/clipboard/lang/nl.js
new file mode 100644
index 0000000..bae806f
--- /dev/null
+++ b/sources/plugins/clipboard/lang/nl.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'nl', {
6 copy: 'Kopiëren',
7 copyError: 'De beveiligingsinstelling van de browser verhinderen het automatisch kopiëren. Gebruik de sneltoets Ctrl/Cmd+C van het toetsenbord.',
8 cut: 'Knippen',
9 cutError: 'De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl/Cmd+X van het toetsenbord.',
10 paste: 'Plakken',
11 pasteArea: 'Plakgebied',
12 pasteMsg: 'Plak de tekst in het volgende vak gebruikmakend van uw toetsenbord (<strong>Ctrl/Cmd+V</strong>) en klik op OK.',
13 securityMsg: 'Door de beveiligingsinstellingen van uw browser is het niet mogelijk om direct vanuit het klembord in de editor te plakken. Middels opnieuw plakken in dit venster kunt u de tekst alsnog plakken in de editor.',
14 title: 'Plakken'
15} );
diff --git a/sources/plugins/clipboard/lang/no.js b/sources/plugins/clipboard/lang/no.js
new file mode 100644
index 0000000..e8c48da
--- /dev/null
+++ b/sources/plugins/clipboard/lang/no.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'no', {
6 copy: 'Kopier',
7 copyError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk kopiering av tekst. Vennligst bruk snarveien (Ctrl/Cmd+C).',
8 cut: 'Klipp ut',
9 cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk snarveien (Ctrl/Cmd+X).',
10 paste: 'Lim inn',
11 pasteArea: 'Innlimingsområde',
12 pasteMsg: 'Vennligst lim inn i følgende boks med tastaturet (<STRONG>Ctrl/Cmd+V</STRONG>) og trykk <STRONG>OK</STRONG>.',
13 securityMsg: 'Din nettlesers sikkerhetsinstillinger gir ikke redigeringsverktøyet direkte tilgang til utklippstavlen. Du må derfor lime det inn på nytt i dette vinduet.',
14 title: 'Lim inn'
15} );
diff --git a/sources/plugins/clipboard/lang/oc.js b/sources/plugins/clipboard/lang/oc.js
new file mode 100644
index 0000000..e9e78cd
--- /dev/null
+++ b/sources/plugins/clipboard/lang/oc.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'oc', {
6 copy: 'Copiar',
7 copyError: 'Los paramètres de seguretat de vòstre navigador autorizan pas l\'editor a executar automaticament l\'operacion « Copiar ». Utilizatz l\'acorchi de clavièr a aqueste efièit (Ctrl/Cmd+C).',
8 cut: 'Talhar',
9 cutError: 'Los paramètres de seguretat de vòstre navigador autorizan pas l\'editor a executar automaticament l\'operacion « Talhar ». Utilizatz l\'acorchi de clavièr a aqueste efièit (Ctrl/Cmd+X).',
10 paste: 'Pegar',
11 pasteArea: 'Pegar la zòna',
12 pasteMsg: 'Pegatz lo tèxte dins la zòna seguenta en utilizant l\'acorchi de clavièr (<strong>Ctrl/Cmd+V</strong>) e clicatz sus D\'acòrdi.',
13 securityMsg: 'Los paramètres de seguretat de vòstre navigador empach l\'editor d\'accedir dirèctament a las donadas del quichapapièr. Las vos cal pegar tornamai dins aquesta fenèstra.',
14 title: 'Pegar'
15} );
diff --git a/sources/plugins/clipboard/lang/pl.js b/sources/plugins/clipboard/lang/pl.js
new file mode 100644
index 0000000..e2ccd16
--- /dev/null
+++ b/sources/plugins/clipboard/lang/pl.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'pl', {
6 copy: 'Kopiuj',
7 copyError: 'Ustawienia bezpieczeństwa Twojej przeglądarki nie pozwalają na automatyczne kopiowanie tekstu. Użyj skrótu klawiszowego Ctrl/Cmd+C.',
8 cut: 'Wytnij',
9 cutError: 'Ustawienia bezpieczeństwa Twojej przeglądarki nie pozwalają na automatyczne wycinanie tekstu. Użyj skrótu klawiszowego Ctrl/Cmd+X.',
10 paste: 'Wklej',
11 pasteArea: 'Obszar wklejania',
12 pasteMsg: 'Wklej tekst w poniższym polu, używając skrótu klawiaturowego (<STRONG>Ctrl/Cmd+V</STRONG>), i kliknij <STRONG>OK</STRONG>.',
13 securityMsg: 'Zabezpieczenia przeglądarki uniemożliwiają wklejenie danych bezpośrednio do edytora. Proszę ponownie wkleić dane w tym oknie.',
14 title: 'Wklej'
15} );
diff --git a/sources/plugins/clipboard/lang/pt-br.js b/sources/plugins/clipboard/lang/pt-br.js
new file mode 100644
index 0000000..74608ba
--- /dev/null
+++ b/sources/plugins/clipboard/lang/pt-br.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'pt-br', {
6 copy: 'Copiar',
7 copyError: 'As configurações de segurança do seu navegador não permitem que o editor execute operações de copiar automaticamente. Por favor, utilize o teclado para copiar (Ctrl/Cmd+C).',
8 cut: 'Recortar',
9 cutError: 'As configurações de segurança do seu navegador não permitem que o editor execute operações de recortar automaticamente. Por favor, utilize o teclado para recortar (Ctrl/Cmd+X).',
10 paste: 'Colar',
11 pasteArea: 'Área para Colar',
12 pasteMsg: 'Transfira o link usado na caixa usando o teclado com (<STRONG>Ctrl/Cmd+V</STRONG>) e <STRONG>OK</STRONG>.',
13 securityMsg: 'As configurações de segurança do seu navegador não permitem que o editor acesse os dados da área de transferência diretamente. Por favor cole o conteúdo manualmente nesta janela.',
14 title: 'Colar'
15} );
diff --git a/sources/plugins/clipboard/lang/pt.js b/sources/plugins/clipboard/lang/pt.js
new file mode 100644
index 0000000..623ce06
--- /dev/null
+++ b/sources/plugins/clipboard/lang/pt.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'pt', {
6 copy: 'Copiar',
7 copyError: 'A configuração de segurança do navegador não permite a execução automática de operações de copiar. Por favor use o teclado (Ctrl/Cmd+C).',
8 cut: 'Cortar',
9 cutError: 'A configuração de segurança do navegador não permite a execução automática de operações de cortar. Por favor use o teclado (Ctrl/Cmd+X).',
10 paste: 'Colar',
11 pasteArea: 'Colar área',
12 pasteMsg: 'Por favor, cole dentro da seguinte caixa usando o teclado (<STRONG>Ctrl/Cmd+V</STRONG>) e carregue em <STRONG>OK</STRONG>.',
13 securityMsg: 'Devido ás definições de segurança do teu browser, o editor não pode aceder ao clipboard diretamente. É necessário que voltes a colar as informações nesta janela.',
14 title: 'Colar'
15} );
diff --git a/sources/plugins/clipboard/lang/ro.js b/sources/plugins/clipboard/lang/ro.js
new file mode 100644
index 0000000..1e57798
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ro.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ro', {
6 copy: 'Copiază',
7 copyError: 'Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de copiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+C).',
8 cut: 'Taie',
9 cutError: 'Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de tăiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+X).',
10 paste: 'Adaugă',
11 pasteArea: 'Suprafața de adăugare',
12 pasteMsg: 'Vă rugăm adăugaţi în căsuţa următoare folosind tastatura (<strong>Ctrl/Cmd+V</strong>) şi apăsaţi OK',
13 securityMsg: 'Din cauza setărilor de securitate ale programului dvs. cu care navigaţi pe internet (browser), editorul nu poate accesa direct datele din clipboard. Va trebui să adăugaţi din nou datele în această fereastră.',
14 title: 'Adaugă'
15} );
diff --git a/sources/plugins/clipboard/lang/ru.js b/sources/plugins/clipboard/lang/ru.js
new file mode 100644
index 0000000..d9b4d58
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ru.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ru', {
6 copy: 'Копировать',
7 copyError: 'Настройки безопасности вашего браузера не разрешают редактору выполнять операции по копированию текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+C).',
8 cut: 'Вырезать',
9 cutError: 'Настройки безопасности вашего браузера не разрешают редактору выполнять операции по вырезке текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+X).',
10 paste: 'Вставить',
11 pasteArea: 'Зона для вставки',
12 pasteMsg: 'Пожалуйста, вставьте текст в зону ниже, используя клавиатуру (<strong>Ctrl/Cmd+V</strong>) и нажмите кнопку "OK".',
13 securityMsg: 'Настройки безопасности вашего браузера не разрешают редактору напрямую обращаться к буферу обмена. Вы должны вставить текст снова в это окно.',
14 title: 'Вставить'
15} );
diff --git a/sources/plugins/clipboard/lang/si.js b/sources/plugins/clipboard/lang/si.js
new file mode 100644
index 0000000..8430d01
--- /dev/null
+++ b/sources/plugins/clipboard/lang/si.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'si', {
6 copy: 'පිටපත් කරන්න',
7 copyError: 'Your browser security settings don\'t permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).', // MISSING
8 cut: 'කපාගන්න',
9 cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', // MISSING
10 paste: 'අලවන්න',
11 pasteArea: 'අලවන ප්‍රදේශ',
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK', // MISSING
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.', // MISSING
14 title: 'අලවන්න'
15} );
diff --git a/sources/plugins/clipboard/lang/sk.js b/sources/plugins/clipboard/lang/sk.js
new file mode 100644
index 0000000..6b2b4f4
--- /dev/null
+++ b/sources/plugins/clipboard/lang/sk.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sk', {
6 copy: 'Kopírovať',
7 copyError: 'Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu kopírovania. Použite na to klávesnicu (Ctrl/Cmd+C).',
8 cut: 'Vystrihnúť',
9 cutError: 'Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu vystrihnutia. Použite na to klávesnicu (Ctrl/Cmd+X).',
10 paste: 'Vložiť',
11 pasteArea: 'Miesto na vloženie',
12 pasteMsg: 'Použitím klávesnice (<STRONG>Ctrl/Cmd+V</STRONG>) vložte text do rámčeka a stlačte OK.',
13 securityMsg: 'Kvôli bezpečnostným nastaveniam vášho prehliadača editor nemôže pristupovať k schránke na kopírovanie priamo. Vložte to preto do tohto okna.',
14 title: 'Vložiť'
15} );
diff --git a/sources/plugins/clipboard/lang/sl.js b/sources/plugins/clipboard/lang/sl.js
new file mode 100644
index 0000000..3ddc89e
--- /dev/null
+++ b/sources/plugins/clipboard/lang/sl.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sl', {
6 copy: 'Kopiraj',
7 copyError: 'Varnostne nastavitve brskalnika ne dopuščajo samodejnega kopiranja. Uporabite kombinacijo tipk na tipkovnici (Ctrl/Cmd+C).',
8 cut: 'Izreži',
9 cutError: 'Varnostne nastavitve brskalnika ne dopuščajo samodejnega izrezovanja. Uporabite kombinacijo tipk na tipkovnici (Ctrl/Cmd+X).',
10 paste: 'Prilepi',
11 pasteArea: 'Prilepi območje',
12 pasteMsg: 'Prosimo, prilepite v sleči okvir s pomočjo tipkovnice (<strong>Ctrl/Cmd+V</strong>) in pritisnite V redu.',
13 securityMsg: 'Zaradi varnostnih nastavitev vašega brskalnika urejevalnik ne more neposredno dostopati do odložišča. Vsebino odložišča ponovno prilepite v to okno.',
14 title: 'Prilepi'
15} );
diff --git a/sources/plugins/clipboard/lang/sq.js b/sources/plugins/clipboard/lang/sq.js
new file mode 100644
index 0000000..eda22e7
--- /dev/null
+++ b/sources/plugins/clipboard/lang/sq.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sq', {
6 copy: 'Kopjo',
7 copyError: 'Të dhënat e sigurisë së shfletuesit tuaj nuk lejojnë që redaktuesi automatikisht të kryej veprimin e kopjimit. Ju lutemi shfrytëzoni tastierën për këtë veprim (Ctrl/Cmd+C).',
8 cut: 'Preje',
9 cutError: 'Të dhënat e sigurisë së shfletuesit tuaj nuk lejojnë që redaktuesi automatikisht të kryej veprimin e prerjes. Ju lutemi shfrytëzoni tastierën për këtë veprim (Ctrl/Cmd+X).',
10 paste: 'Hidhe',
11 pasteArea: 'Hapësira Hedhëse',
12 pasteMsg: 'Ju lutemi hidhni brenda kutizës në vijim duke shfrytëzuar tastierën (<strong>Ctrl/Cmd+V</strong>) dhe shtypni Mirë.',
13 securityMsg: 'Për shkak të dhënave të sigurisë së shfletuesit tuaj, redaktuesi nuk është në gjendje të i qaset drejtpërdrejtë të dhanve të tabelës suaj të punës. Ju duhet të hidhni atë përsëri në këtë dritare.',
14 title: 'Hidhe'
15} );
diff --git a/sources/plugins/clipboard/lang/sr-latn.js b/sources/plugins/clipboard/lang/sr-latn.js
new file mode 100644
index 0000000..52102f6
--- /dev/null
+++ b/sources/plugins/clipboard/lang/sr-latn.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sr-latn', {
6 copy: 'Kopiraj',
7 copyError: 'Sigurnosna podešavanja Vašeg pretraživača ne dozvoljavaju operacije automatskog kopiranja teksta. Molimo Vas da koristite prečicu sa tastature (Ctrl/Cmd+C).',
8 cut: 'Iseci',
9 cutError: 'Sigurnosna podešavanja Vašeg pretraživača ne dozvoljavaju operacije automatskog isecanja teksta. Molimo Vas da koristite prečicu sa tastature (Ctrl/Cmd+X).',
10 paste: 'Zalepi',
11 pasteArea: 'Prostor za lepljenje',
12 pasteMsg: 'Molimo Vas da zalepite unutar donje povrine koristeći tastaturnu prečicu (<STRONG>Ctrl/Cmd+V</STRONG>) i da pritisnete <STRONG>OK</STRONG>.',
13 securityMsg: 'Zbog sigurnosnih postavki vašeg pregledača, editor nije u mogućnosti da direktno pristupi podacima u klipbordu. Potrebno je da zalepite još jednom u ovom prozoru.',
14 title: 'Zalepi'
15} );
diff --git a/sources/plugins/clipboard/lang/sr.js b/sources/plugins/clipboard/lang/sr.js
new file mode 100644
index 0000000..c59ff1f
--- /dev/null
+++ b/sources/plugins/clipboard/lang/sr.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sr', {
6 copy: 'Копирај',
7 copyError: 'Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског копирања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl/Cmd+C).',
8 cut: 'Исеци',
9 cutError: 'Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског исецања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl/Cmd+X).',
10 paste: 'Залепи',
11 pasteArea: 'Залепи зону',
12 pasteMsg: 'Молимо Вас да залепите унутар доње површине користећи тастатурну пречицу (<STRONG>Ctrl/Cmd+V</STRONG>) и да притиснете <STRONG>OK</STRONG>.',
13 securityMsg: 'Због сигурносних подешавања претраживача, едитор не може да приступи оставу. Требате да га поново залепите у овом прозору.',
14 title: 'Залепи'
15} );
diff --git a/sources/plugins/clipboard/lang/sv.js b/sources/plugins/clipboard/lang/sv.js
new file mode 100644
index 0000000..9663daa
--- /dev/null
+++ b/sources/plugins/clipboard/lang/sv.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sv', {
6 copy: 'Kopiera',
7 copyError: 'Säkerhetsinställningar i Er webbläsare tillåter inte åtgärden kopiera. Använd (Ctrl/Cmd+C) istället.',
8 cut: 'Klipp ut',
9 cutError: 'Säkerhetsinställningar i Er webbläsare tillåter inte åtgärden klipp ut. Använd (Ctrl/Cmd+X) istället.',
10 paste: 'Klistra in',
11 pasteArea: 'Paste Area',
12 pasteMsg: 'Var god och klistra in Er text i rutan nedan genom att använda (<strong>Ctrl/Cmd+V</strong>) klicka sen på OK.',
13 securityMsg: 'På grund av din webbläsares säkerhetsinställningar kan verktyget inte få åtkomst till urklippsdatan. Var god och använd detta fönster istället.',
14 title: 'Klistra in'
15} );
diff --git a/sources/plugins/clipboard/lang/th.js b/sources/plugins/clipboard/lang/th.js
new file mode 100644
index 0000000..29664a6
--- /dev/null
+++ b/sources/plugins/clipboard/lang/th.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'th', {
6 copy: 'สำเนา',
7 copyError: 'ไม่สามารถสำเนาข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl/Cmd และตัว C พร้อมกัน).',
8 cut: 'ตัด',
9 cutError: 'ไม่สามารถตัดข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl/Cmd และตัว X พร้อมกัน).',
10 paste: 'วาง',
11 pasteArea: 'Paste Area', // MISSING
12 pasteMsg: 'กรุณาใช้คีย์บอร์ดเท่านั้น โดยกดปุ๋ม (<strong>Ctrl/Cmd และ V</strong>)พร้อมๆกัน และกด <strong>OK</strong>.',
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.', // MISSING
14 title: 'วาง'
15} );
diff --git a/sources/plugins/clipboard/lang/tr.js b/sources/plugins/clipboard/lang/tr.js
new file mode 100644
index 0000000..a60ddc7
--- /dev/null
+++ b/sources/plugins/clipboard/lang/tr.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'tr', {
6 copy: 'Kopyala',
7 copyError: 'Gezgin yazılımınızın güvenlik ayarları düzenleyicinin otomatik kopyalama işlemine izin vermiyor. İşlem için (Ctrl/Cmd+C) tuşlarını kullanın.',
8 cut: 'Kes',
9 cutError: 'Gezgin yazılımınızın güvenlik ayarları düzenleyicinin otomatik kesme işlemine izin vermiyor. İşlem için (Ctrl/Cmd+X) tuşlarını kullanın.',
10 paste: 'Yapıştır',
11 pasteArea: 'Yapıştırma Alanı',
12 pasteMsg: 'Lütfen aşağıdaki kutunun içine yapıştırın. (<STRONG>Ctrl/Cmd+V</STRONG>) ve <STRONG>Tamam</STRONG> butonunu tıklayın.',
13 securityMsg: 'Gezgin yazılımınızın güvenlik ayarları düzenleyicinin direkt olarak panoya erişimine izin vermiyor. Bu pencere içine tekrar yapıştırmalısınız..',
14 title: 'Yapıştır'
15} );
diff --git a/sources/plugins/clipboard/lang/tt.js b/sources/plugins/clipboard/lang/tt.js
new file mode 100644
index 0000000..e4b0537
--- /dev/null
+++ b/sources/plugins/clipboard/lang/tt.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'tt', {
6 copy: 'Күчермәләү',
7 copyError: 'Браузерыгызның иминлек үзлекләре автоматик рәвештә күчермәләү үтәүне тыя. Тиз төймәләрне (Ctrl/Cmd+C) кулланыгыз.',
8 cut: 'Кисеп алу',
9 cutError: 'Браузерыгызның иминлек үзлекләре автоматик рәвештә күчермәләү үтәүне тыя. Тиз төймәләрне (Ctrl/Cmd+C) кулланыгыз.',
10 paste: 'Өстәү',
11 pasteArea: 'Өстәү мәйданы',
12 pasteMsg: 'Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK', // MISSING
13 securityMsg: 'Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.', // MISSING
14 title: 'Өстәү'
15} );
diff --git a/sources/plugins/clipboard/lang/ug.js b/sources/plugins/clipboard/lang/ug.js
new file mode 100644
index 0000000..dcdf29c
--- /dev/null
+++ b/sources/plugins/clipboard/lang/ug.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'ug', {
6 copy: 'كۆچۈر',
7 copyError: 'تور كۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى تەھرىرلىگۈچنىڭ كۆچۈر مەشغۇلاتىنى ئۆزلۈكىدىن ئىجرا قىلىشىغا يول قويمايدۇ، ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+C) ئارقىلىق تاماملاڭ',
8 cut: 'كەس',
9 cutError: 'تور كۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى تەھرىرلىگۈچنىڭ كەس مەشغۇلاتىنى ئۆزلۈكىدىن ئىجرا قىلىشىغا يول قويمايدۇ، ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+X) ئارقىلىق تاماملاڭ',
10 paste: 'چاپلا',
11 pasteArea: 'چاپلاش دائىرىسى',
12 pasteMsg: 'ھەرپتاختا تېز كۇنۇپكا (<STRONG>Ctrl/Cmd+V</STRONG>) نى ئىشلىتىپ مەزمۇننى تۆۋەندىكى رامكىغا كۆچۈرۈڭ، ئاندىن <STRONG>جەزملە</STRONG>نى بېسىڭ',
13 securityMsg: 'توركۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى سەۋەبىدىن بۇ تەھرىرلىگۈچ چاپلاش تاختىسىدىكى مەزمۇننى بىۋاستە زىيارەت قىلالمايدۇ، بۇ كۆزنەكتە قايتا بىر قېتىم چاپلىشىڭىز كېرەك.',
14 title: 'چاپلا'
15} );
diff --git a/sources/plugins/clipboard/lang/uk.js b/sources/plugins/clipboard/lang/uk.js
new file mode 100644
index 0000000..242688f
--- /dev/null
+++ b/sources/plugins/clipboard/lang/uk.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'uk', {
6 copy: 'Копіювати',
7 copyError: 'Налаштування безпеки Вашого браузера не дозволяють редактору автоматично виконувати операції копіювання. Будь ласка, використовуйте клавіатуру для цього (Ctrl/Cmd+C).',
8 cut: 'Вирізати',
9 cutError: 'Налаштування безпеки Вашого браузера не дозволяють редактору автоматично виконувати операції вирізування. Будь ласка, використовуйте клавіатуру для цього (Ctrl/Cmd+X)',
10 paste: 'Вставити',
11 pasteArea: 'Область вставки',
12 pasteMsg: 'Будь ласка, вставте інформацію з буфера обміну в цю область, користуючись комбінацією клавіш (<STRONG>Ctrl/Cmd+V</STRONG>), та натисніть <STRONG>OK</STRONG>.',
13 securityMsg: 'Редактор не може отримати прямий доступ до буферу обміну у зв\'язку з налаштуваннями Вашого браузера. Вам потрібно вставити інформацію в це вікно.',
14 title: 'Вставити'
15} );
diff --git a/sources/plugins/clipboard/lang/vi.js b/sources/plugins/clipboard/lang/vi.js
new file mode 100644
index 0000000..fd36e1f
--- /dev/null
+++ b/sources/plugins/clipboard/lang/vi.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'vi', {
6 copy: 'Sao chép',
7 copyError: 'Các thiết lập bảo mật của trình duyệt không cho phép trình biên tập tự động thực thi lệnh sao chép. Hãy sử dụng bàn phím cho lệnh này (Ctrl/Cmd+C).',
8 cut: 'Cắt',
9 cutError: 'Các thiết lập bảo mật của trình duyệt không cho phép trình biên tập tự động thực thi lệnh cắt. Hãy sử dụng bàn phím cho lệnh này (Ctrl/Cmd+X).',
10 paste: 'Dán',
11 pasteArea: 'Khu vực dán',
12 pasteMsg: 'Hãy dán nội dung vào trong khung bên dưới, sử dụng tổ hợp phím (<STRONG>Ctrl/Cmd+V</STRONG>) và nhấn vào nút <STRONG>Đồng ý</STRONG>.',
13 securityMsg: 'Do thiết lập bảo mật của trình duyệt nên trình biên tập không thể truy cập trực tiếp vào nội dung đã sao chép. Bạn cần phải dán lại nội dung vào cửa sổ này.',
14 title: 'Dán'
15} );
diff --git a/sources/plugins/clipboard/lang/zh-cn.js b/sources/plugins/clipboard/lang/zh-cn.js
new file mode 100644
index 0000000..930f24e
--- /dev/null
+++ b/sources/plugins/clipboard/lang/zh-cn.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'zh-cn', {
6 copy: '复制',
7 copyError: '您的浏览器安全设置不允许编辑器自动执行复制操作,请使用键盘快捷键(Ctrl/Cmd+C)来完成。',
8 cut: '剪切',
9 cutError: '您的浏览器安全设置不允许编辑器自动执行剪切操作,请使用键盘快捷键(Ctrl/Cmd+X)来完成。',
10 paste: '粘贴',
11 pasteArea: '粘贴区域',
12 pasteMsg: '请使用键盘快捷键(<STRONG>Ctrl/Cmd+V</STRONG>)把内容粘贴到下面的方框里,再按 <STRONG>确定</STRONG>',
13 securityMsg: '因为您的浏览器的安全设置原因,本编辑器不能直接访问您的剪贴板内容,你需要在本窗口重新粘贴一次。',
14 title: '粘贴'
15} );
diff --git a/sources/plugins/clipboard/lang/zh.js b/sources/plugins/clipboard/lang/zh.js
new file mode 100644
index 0000000..33a4ef0
--- /dev/null
+++ b/sources/plugins/clipboard/lang/zh.js
@@ -0,0 +1,15 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'zh', {
6 copy: '複製',
7 copyError: '瀏覽器的安全性設定不允許編輯器自動執行複製動作。請使用鍵盤快捷鍵 (Ctrl/Cmd+C) 複製。',
8 cut: '剪下',
9 cutError: '瀏覽器的安全性設定不允許編輯器自動執行剪下動作。請使用鏐盤快捷鍵 (Ctrl/Cmd+X) 剪下。',
10 paste: '貼上',
11 pasteArea: '貼上區',
12 pasteMsg: '請使用鍵盤快捷鍵 (<strong>Ctrl/Cmd+V</strong>) 貼到下方區域中並按下「確定」。',
13 securityMsg: '因為瀏覽器的安全性設定,本編輯器無法直接存取您的剪貼簿資料,請您自行在本視窗進行貼上動作。',
14 title: '貼上'
15} );
diff --git a/sources/plugins/clipboard/plugin.js b/sources/plugins/clipboard/plugin.js
new file mode 100644
index 0000000..5c387b3
--- /dev/null
+++ b/sources/plugins/clipboard/plugin.js
@@ -0,0 +1,2772 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @ignore
8 * File overview: Clipboard support.
9 */
10
11//
12// COPY & PASTE EXECUTION FLOWS:
13// -- CTRL+C
14// * if ( isCustomCopyCutSupported )
15// * dataTransfer.setData( 'text/html', getSelectedHtml )
16// * else
17// * browser's default behavior
18// -- CTRL+X
19// * listen onKey (onkeydown)
20// * fire 'saveSnapshot' on editor
21// * if ( isCustomCopyCutSupported )
22// * dataTransfer.setData( 'text/html', getSelectedHtml )
23// * extractSelectedHtml // remove selected contents
24// * else
25// * browser's default behavior
26// * deferred second 'saveSnapshot' event
27// -- CTRL+V
28// * listen onKey (onkeydown)
29// * simulate 'beforepaste' for non-IEs on editable
30// * listen 'onpaste' on editable ('onbeforepaste' for IE)
31// * fire 'beforePaste' on editor
32// * if ( !canceled && ( htmlInDataTransfer || !external paste) && dataTransfer is not empty ) getClipboardDataByPastebin
33// * fire 'paste' on editor
34// * !canceled && fire 'afterPaste' on editor
35// -- Copy command
36// * tryToCutCopy
37// * execCommand
38// * !success && notification
39// -- Cut command
40// * fixCut
41// * tryToCutCopy
42// * execCommand
43// * !success && notification
44// -- Paste command
45// * fire 'paste' on editable ('beforepaste' for IE)
46// * !canceled && execCommand 'paste'
47// * !success && fire 'pasteDialog' on editor
48// -- Paste from native context menu & menubar
49// (Fx & Webkits are handled in 'paste' default listener.
50// Opera cannot be handled at all because it doesn't fire any events
51// Special treatment is needed for IE, for which is this part of doc)
52// * listen 'onpaste'
53// * cancel native event
54// * fire 'beforePaste' on editor
55// * if ( !canceled && ( htmlInDataTransfer || !external paste) && dataTransfer is not empty ) getClipboardDataByPastebin
56// * execIECommand( 'paste' ) -> this fires another 'paste' event, so cancel it
57// * fire 'paste' on editor
58// * !canceled && fire 'afterPaste' on editor
59//
60//
61// PASTE EVENT - PREPROCESSING:
62// -- Possible dataValue types: auto, text, html.
63// -- Possible dataValue contents:
64// * text (possible \n\r)
65// * htmlified text (text + br,div,p - no presentational markup & attrs - depends on browser)
66// * html
67// -- Possible flags:
68// * htmlified - if true then content is a HTML even if no markup inside. This flag is set
69// for content from editable pastebins, because they 'htmlify' pasted content.
70//
71// -- Type: auto:
72// * content: htmlified text -> filter, unify text markup (brs, ps, divs), set type: text
73// * content: html -> filter, set type: html
74// -- Type: text:
75// * content: htmlified text -> filter, unify text markup
76// * content: html -> filter, strip presentational markup, unify text markup
77// -- Type: html:
78// * content: htmlified text -> filter, unify text markup
79// * content: html -> filter
80//
81// -- Phases:
82// * if dataValue is empty copy data from dataTransfer to dataValue (priority 1)
83// * filtering (priorities 3-5) - e.g. pastefromword filters
84// * content type sniffing (priority 6)
85// * markup transformations for text (priority 6)
86//
87// DRAG & DROP EXECUTION FLOWS:
88// -- Drag
89// * save to the global object:
90// * drag timestamp (with 'cke-' prefix),
91// * selected html,
92// * drag range,
93// * editor instance.
94// * put drag timestamp into event.dataTransfer.text
95// -- Drop
96// * if events text == saved timestamp && editor == saved editor
97// internal drag & drop occurred
98// * getRangeAtDropPosition
99// * create bookmarks for drag and drop ranges starting from the end of the document
100// * dragRange.deleteContents()
101// * fire 'paste' with saved html and drop range
102// * if events text == saved timestamp && editor != saved editor
103// cross editor drag & drop occurred
104// * getRangeAtDropPosition
105// * fire 'paste' with saved html
106// * dragRange.deleteContents()
107// * FF: refreshCursor on afterPaste
108// * if events text != saved timestamp
109// drop form external source occurred
110// * getRangeAtDropPosition
111// * if event contains html data then fire 'paste' with html
112// * else if event contains text data then fire 'paste' with encoded text
113// * FF: refreshCursor on afterPaste
114
115'use strict';
116
117( function() {
118 // Register the plugin.
119 CKEDITOR.plugins.add( 'clipboard', {
120 requires: 'dialog',
121 // jscs:disable maximumLineLength
122 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
123 // jscs:enable maximumLineLength
124 icons: 'copy,copy-rtl,cut,cut-rtl,paste,paste-rtl', // %REMOVE_LINE_CORE%
125 hidpi: true, // %REMOVE_LINE_CORE%
126 init: function( editor ) {
127 var filterType,
128 filtersFactory = filtersFactoryFactory();
129
130 if ( editor.config.forcePasteAsPlainText ) {
131 filterType = 'plain-text';
132 } else if ( editor.config.pasteFilter ) {
133 filterType = editor.config.pasteFilter;
134 }
135 // On Webkit the pasteFilter defaults 'semantic-content' because pasted data is so terrible
136 // that it must be always filtered.
137 else if ( CKEDITOR.env.webkit && !( 'pasteFilter' in editor.config ) ) {
138 filterType = 'semantic-content';
139 }
140
141 editor.pasteFilter = filtersFactory.get( filterType );
142
143 initPasteClipboard( editor );
144 initDragDrop( editor );
145
146 CKEDITOR.dialog.add( 'paste', CKEDITOR.getUrl( this.path + 'dialogs/paste.js' ) );
147
148 // Convert image file (if present) to base64 string for Firefox. Do it as the first
149 // step as the conversion is asynchronous and should hold all further paste processing.
150 if ( CKEDITOR.env.gecko ) {
151 var supportedImageTypes = [ 'image/png', 'image/jpeg', 'image/gif' ],
152 latestId;
153
154 editor.on( 'paste', function( evt ) {
155 var dataObj = evt.data,
156 data = dataObj.dataValue,
157 dataTransfer = dataObj.dataTransfer;
158
159 // If data empty check for image content inside data transfer. #16705
160 if ( !data && dataObj.method == 'paste' && dataTransfer && dataTransfer.getFilesCount() == 1 && latestId != dataTransfer.id ) {
161 var file = dataTransfer.getFile( 0 );
162
163 if ( CKEDITOR.tools.indexOf( supportedImageTypes, file.type ) != -1 ) {
164 var fileReader = new FileReader();
165
166 // Convert image file to img tag with base64 image.
167 fileReader.addEventListener( 'load', function() {
168 evt.data.dataValue = '<img src="' + fileReader.result + '" />';
169 editor.fire( 'paste', evt.data );
170 }, false );
171
172 // Proceed with normal flow if reading file was aborted.
173 fileReader.addEventListener( 'abort', function() {
174 editor.fire( 'paste', evt.data );
175 }, false );
176
177 // Proceed with normal flow if reading file failed.
178 fileReader.addEventListener( 'error', function() {
179 editor.fire( 'paste', evt.data );
180 }, false );
181
182 fileReader.readAsDataURL( file );
183
184 latestId = dataObj.dataTransfer.id;
185
186 evt.stop();
187 }
188 }
189 }, null, null, 1 );
190 }
191
192 editor.on( 'paste', function( evt ) {
193 // Init `dataTransfer` if `paste` event was fired without it, so it will be always available.
194 if ( !evt.data.dataTransfer ) {
195 evt.data.dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer();
196 }
197
198 // If dataValue is already set (manually or by paste bin), so do not override it.
199 if ( evt.data.dataValue ) {
200 return;
201 }
202
203 var dataTransfer = evt.data.dataTransfer,
204 // IE support only text data and throws exception if we try to get html data.
205 // This html data object may also be empty if we drag content of the textarea.
206 value = dataTransfer.getData( 'text/html' );
207
208 if ( value ) {
209 evt.data.dataValue = value;
210 evt.data.type = 'html';
211 } else {
212 // Try to get text data otherwise.
213 value = dataTransfer.getData( 'text/plain' );
214
215 if ( value ) {
216 evt.data.dataValue = editor.editable().transformPlainTextToHtml( value );
217 evt.data.type = 'text';
218 }
219 }
220 }, null, null, 1 );
221
222 editor.on( 'paste', function( evt ) {
223 var data = evt.data.dataValue,
224 blockElements = CKEDITOR.dtd.$block;
225
226 // Filter webkit garbage.
227 if ( data.indexOf( 'Apple-' ) > -1 ) {
228 // Replace special webkit's &nbsp; with simple space, because webkit
229 // produces them even for normal spaces.
230 data = data.replace( /<span class="Apple-converted-space">&nbsp;<\/span>/gi, ' ' );
231
232 // Strip <span> around white-spaces when not in forced 'html' content type.
233 // This spans are created only when pasting plain text into Webkit,
234 // but for safety reasons remove them always.
235 if ( evt.data.type != 'html' ) {
236 data = data.replace( /<span class="Apple-tab-span"[^>]*>([^<]*)<\/span>/gi, function( all, spaces ) {
237 // Replace tabs with 4 spaces like Fx does.
238 return spaces.replace( /\t/g, '&nbsp;&nbsp; &nbsp;' );
239 } );
240 }
241
242 // This br is produced only when copying & pasting HTML content.
243 if ( data.indexOf( '<br class="Apple-interchange-newline">' ) > -1 ) {
244 evt.data.startsWithEOL = 1;
245 evt.data.preSniffing = 'html'; // Mark as not text.
246 data = data.replace( /<br class="Apple-interchange-newline">/, '' );
247 }
248
249 // Remove all other classes.
250 data = data.replace( /(<[^>]+) class="Apple-[^"]*"/gi, '$1' );
251 }
252
253 // Strip editable that was copied from inside. (#9534)
254 if ( data.match( /^<[^<]+cke_(editable|contents)/i ) ) {
255 var tmp,
256 editable_wrapper,
257 wrapper = new CKEDITOR.dom.element( 'div' );
258
259 wrapper.setHtml( data );
260 // Verify for sure and check for nested editor UI parts. (#9675)
261 while ( wrapper.getChildCount() == 1 &&
262 ( tmp = wrapper.getFirst() ) &&
263 tmp.type == CKEDITOR.NODE_ELEMENT && // Make sure first-child is element.
264 ( tmp.hasClass( 'cke_editable' ) || tmp.hasClass( 'cke_contents' ) ) ) {
265 wrapper = editable_wrapper = tmp;
266 }
267
268 // If editable wrapper was found strip it and bogus <br> (added on FF).
269 if ( editable_wrapper )
270 data = editable_wrapper.getHtml().replace( /<br>$/i, '' );
271 }
272
273 if ( CKEDITOR.env.ie ) {
274 // &nbsp; <p> -> <p> (br.cke-pasted-remove will be removed later)
275 data = data.replace( /^&nbsp;(?: |\r\n)?<(\w+)/g, function( match, elementName ) {
276 if ( elementName.toLowerCase() in blockElements ) {
277 evt.data.preSniffing = 'html'; // Mark as not a text.
278 return '<' + elementName;
279 }
280 return match;
281 } );
282 } else if ( CKEDITOR.env.webkit ) {
283 // </p><div><br></div> -> </p><br>
284 // We don't mark br, because this situation can happen for htmlified text too.
285 data = data.replace( /<\/(\w+)><div><br><\/div>$/, function( match, elementName ) {
286 if ( elementName in blockElements ) {
287 evt.data.endsWithEOL = 1;
288 return '</' + elementName + '>';
289 }
290 return match;
291 } );
292 } else if ( CKEDITOR.env.gecko ) {
293 // Firefox adds bogus <br> when user pasted text followed by space(s).
294 data = data.replace( /(\s)<br>$/, '$1' );
295 }
296
297 evt.data.dataValue = data;
298 }, null, null, 3 );
299
300 editor.on( 'paste', function( evt ) {
301 var dataObj = evt.data,
302 type = dataObj.type,
303 data = dataObj.dataValue,
304 trueType,
305 // Default is 'html'.
306 defaultType = editor.config.clipboard_defaultContentType || 'html',
307 transferType = dataObj.dataTransfer.getTransferType( editor );
308
309 // If forced type is 'html' we don't need to know true data type.
310 if ( type == 'html' || dataObj.preSniffing == 'html' ) {
311 trueType = 'html';
312 } else {
313 trueType = recogniseContentType( data );
314 }
315
316 // Unify text markup.
317 if ( trueType == 'htmlifiedtext' ) {
318 data = htmlifiedTextHtmlification( editor.config, data );
319 }
320
321 // Strip presentational markup & unify text markup.
322 // Forced plain text (dialog or forcePAPT).
323 // Note: we do not check dontFilter option in this case, because forcePAPT was implemented
324 // before pasteFilter and pasteFilter is automatically used on Webkit&Blink since 4.5, so
325 // forcePAPT should have priority as it had before 4.5.
326 if ( type == 'text' && trueType == 'html' ) {
327 data = filterContent( editor, data, filtersFactory.get( 'plain-text' ) );
328 }
329 // External paste and pasteFilter exists and filtering isn't disabled.
330 else if ( transferType == CKEDITOR.DATA_TRANSFER_EXTERNAL && editor.pasteFilter && !dataObj.dontFilter ) {
331 data = filterContent( editor, data, editor.pasteFilter );
332 }
333
334 if ( dataObj.startsWithEOL ) {
335 data = '<br data-cke-eol="1">' + data;
336 }
337 if ( dataObj.endsWithEOL ) {
338 data += '<br data-cke-eol="1">';
339 }
340
341 if ( type == 'auto' ) {
342 type = ( trueType == 'html' || defaultType == 'html' ) ? 'html' : 'text';
343 }
344
345 dataObj.type = type;
346 dataObj.dataValue = data;
347 delete dataObj.preSniffing;
348 delete dataObj.startsWithEOL;
349 delete dataObj.endsWithEOL;
350 }, null, null, 6 );
351
352 // Inserts processed data into the editor at the end of the
353 // events chain.
354 editor.on( 'paste', function( evt ) {
355 var data = evt.data;
356
357 if ( data.dataValue ) {
358 editor.insertHtml( data.dataValue, data.type, data.range );
359
360 // Defer 'afterPaste' so all other listeners for 'paste' will be fired first.
361 // Fire afterPaste only if paste inserted some HTML.
362 setTimeout( function() {
363 editor.fire( 'afterPaste' );
364 }, 0 );
365 }
366 }, null, null, 1000 );
367
368 editor.on( 'pasteDialog', function( evt ) {
369 // TODO it's possible that this setTimeout is not needed any more,
370 // because of changes introduced in the same commit as this comment.
371 // Editor.getClipboardData adds listener to the dialog's events which are
372 // fired after a while (not like 'showDialog').
373 setTimeout( function() {
374 // Open default paste dialog.
375 editor.openDialog( 'paste', evt.data );
376 }, 0 );
377 } );
378 }
379 } );
380
381 function firePasteEvents( editor, data, withBeforePaste ) {
382 if ( !data.type ) {
383 data.type = 'auto';
384 }
385
386 if ( withBeforePaste ) {
387 // Fire 'beforePaste' event so clipboard flavor get customized
388 // by other plugins.
389 if ( editor.fire( 'beforePaste', data ) === false )
390 return false; // Event canceled
391 }
392
393 // Do not fire paste if there is no data (dataValue and dataTranfser are empty).
394 // This check should be done after firing 'beforePaste' because for native paste
395 // 'beforePaste' is by default fired even for empty clipboard.
396 if ( !data.dataValue && data.dataTransfer.isEmpty() ) {
397 return false;
398 }
399
400 if ( !data.dataValue ) {
401 data.dataValue = '';
402 }
403
404 // Because of FF bug we need to use this hack, otherwise cursor is hidden
405 // or it is not possible to move it (#12420).
406 // Also, check that editor.toolbox exists, because the toolbar plugin might not be loaded (#13305).
407 if ( CKEDITOR.env.gecko && data.method == 'drop' && editor.toolbox ) {
408 editor.once( 'afterPaste', function() {
409 editor.toolbox.focus();
410 } );
411 }
412
413 return editor.fire( 'paste', data );
414 }
415
416 function initPasteClipboard( editor ) {
417 var clipboard = CKEDITOR.plugins.clipboard,
418 preventBeforePasteEvent = 0,
419 preventPasteEvent = 0,
420 inReadOnly = 0;
421
422 addListeners();
423 addButtonsCommands();
424
425 /**
426 * Gets clipboard data by directly accessing the clipboard (IE only) or opening the paste dialog window.
427 *
428 * editor.getClipboardData( { title: 'Get my data' }, function( data ) {
429 * if ( data )
430 * alert( data.type + ' ' + data.dataValue );
431 * } );
432 *
433 * @member CKEDITOR.editor
434 * @param {Object} options
435 * @param {String} [options.title] The title of the paste dialog window.
436 * @param {Function} callback A function that will be executed with `data.type` and `data.dataValue`
437 * or `null` if none of the capturing methods succeeded.
438 */
439 editor.getClipboardData = function( options, callback ) {
440 var beforePasteNotCanceled = false,
441 dataType = 'auto',
442 dialogCommited = false;
443
444 // Options are optional - args shift.
445 if ( !callback ) {
446 callback = options;
447 options = null;
448 }
449
450 // Listen with maximum priority to handle content before everyone else.
451 // This callback will handle paste event that will be fired if direct
452 // access to the clipboard succeed in IE.
453 editor.on( 'paste', onPaste, null, null, 0 );
454
455 // Listen at the end of listeners chain to see if event wasn't canceled
456 // and to retrieve modified data.type.
457 editor.on( 'beforePaste', onBeforePaste, null, null, 1000 );
458
459 // getClipboardDataDirectly() will fire 'beforePaste' synchronously, so we can
460 // check if it was canceled and if any listener modified data.type.
461
462 // If command didn't succeed (only IE allows to access clipboard and only if
463 // user agrees) open and handle paste dialog.
464 if ( getClipboardDataDirectly() === false ) {
465 // Direct access to the clipboard wasn't successful so remove listener.
466 editor.removeListener( 'paste', onPaste );
467
468 // If beforePaste was canceled do not open dialog.
469 // Add listeners only if dialog really opened. 'pasteDialog' can be canceled.
470 if ( beforePasteNotCanceled && editor.fire( 'pasteDialog', onDialogOpen ) ) {
471 editor.on( 'pasteDialogCommit', onDialogCommit );
472
473 // 'dialogHide' will be fired after 'pasteDialogCommit'.
474 editor.on( 'dialogHide', function( evt ) {
475 evt.removeListener();
476 evt.data.removeListener( 'pasteDialogCommit', onDialogCommit );
477
478 // Because Opera has to wait a while in pasteDialog we have to wait here.
479 setTimeout( function() {
480 // Notify even if user canceled dialog (clicked 'cancel', ESC, etc).
481 if ( !dialogCommited )
482 callback( null );
483 }, 10 );
484 } );
485 } else {
486 callback( null );
487 }
488 }
489
490 function onPaste( evt ) {
491 evt.removeListener();
492 evt.cancel();
493 callback( evt.data );
494 }
495
496 function onBeforePaste( evt ) {
497 evt.removeListener();
498 beforePasteNotCanceled = true;
499 dataType = evt.data.type;
500 }
501
502 function onDialogCommit( evt ) {
503 evt.removeListener();
504 // Cancel pasteDialogCommit so paste dialog won't automatically fire
505 // 'paste' evt by itself.
506 evt.cancel();
507 dialogCommited = true;
508 callback( {
509 type: dataType,
510 dataValue: evt.data.dataValue,
511 dataTransfer: evt.data.dataTransfer,
512 method: 'paste'
513 } );
514 }
515
516 function onDialogOpen() {
517 this.customTitle = ( options && options.title );
518 }
519 };
520
521 function addButtonsCommands() {
522 addButtonCommand( 'Cut', 'cut', createCutCopyCmd( 'cut' ), 10, 1 );
523 addButtonCommand( 'Copy', 'copy', createCutCopyCmd( 'copy' ), 20, 4 );
524 addButtonCommand( 'Paste', 'paste', createPasteCmd(), 30, 8 );
525
526 function addButtonCommand( buttonName, commandName, command, toolbarOrder, ctxMenuOrder ) {
527 var lang = editor.lang.clipboard[ commandName ];
528
529 editor.addCommand( commandName, command );
530 editor.ui.addButton && editor.ui.addButton( buttonName, {
531 label: lang,
532 command: commandName,
533 toolbar: 'clipboard,' + toolbarOrder
534 } );
535
536 // If the "menu" plugin is loaded, register the menu item.
537 if ( editor.addMenuItems ) {
538 editor.addMenuItem( commandName, {
539 label: lang,
540 command: commandName,
541 group: 'clipboard',
542 order: ctxMenuOrder
543 } );
544 }
545 }
546 }
547
548 function addListeners() {
549 editor.on( 'key', onKey );
550 editor.on( 'contentDom', addPasteListenersToEditable );
551
552 // For improved performance, we're checking the readOnly state on selectionChange instead of hooking a key event for that.
553 editor.on( 'selectionChange', function( evt ) {
554 inReadOnly = evt.data.selection.getRanges()[ 0 ].checkReadOnly();
555 setToolbarStates();
556 } );
557
558 // If the "contextmenu" plugin is loaded, register the listeners.
559 if ( editor.contextMenu ) {
560 editor.contextMenu.addListener( function( element, selection ) {
561 inReadOnly = selection.getRanges()[ 0 ].checkReadOnly();
562 return {
563 cut: stateFromNamedCommand( 'cut' ),
564 copy: stateFromNamedCommand( 'copy' ),
565 paste: stateFromNamedCommand( 'paste' )
566 };
567 } );
568 }
569 }
570
571 // Add events listeners to editable.
572 function addPasteListenersToEditable() {
573 var editable = editor.editable();
574
575 if ( CKEDITOR.plugins.clipboard.isCustomCopyCutSupported ) {
576 var initOnCopyCut = function( evt ) {
577 // If user tries to cut in read-only editor, we must prevent default action. (#13872)
578 if ( !editor.readOnly || evt.name != 'cut' ) {
579 clipboard.initPasteDataTransfer( evt, editor );
580 }
581 evt.data.preventDefault();
582 };
583
584 editable.on( 'copy', initOnCopyCut );
585 editable.on( 'cut', initOnCopyCut );
586
587 // Delete content with the low priority so one can overwrite cut data.
588 editable.on( 'cut', function() {
589 // If user tries to cut in read-only editor, we must prevent default action. (#13872)
590 if ( !editor.readOnly ) {
591 editor.extractSelectedHtml();
592 }
593 }, null, null, 999 );
594 }
595
596 // We'll be catching all pasted content in one line, regardless of whether
597 // it's introduced by a document command execution (e.g. toolbar buttons) or
598 // user paste behaviors (e.g. CTRL+V).
599 editable.on( clipboard.mainPasteEvent, function( evt ) {
600 if ( clipboard.mainPasteEvent == 'beforepaste' && preventBeforePasteEvent ) {
601 return;
602 }
603
604 // If you've just asked yourself why preventPasteEventNow() is not here, but
605 // in listener for CTRL+V and exec method of 'paste' command
606 // you've asked the same question we did.
607 //
608 // THE ANSWER:
609 //
610 // First thing to notice - this answer makes sense only for IE,
611 // because other browsers don't listen for 'paste' event.
612 //
613 // What would happen if we move preventPasteEventNow() here?
614 // For:
615 // * CTRL+V - IE fires 'beforepaste', so we prevent 'paste' and pasteDataFromClipboard(). OK.
616 // * editor.execCommand( 'paste' ) - we fire 'beforepaste', so we prevent
617 // 'paste' and pasteDataFromClipboard() and doc.execCommand( 'Paste' ). OK.
618 // * native context menu - IE fires 'beforepaste', so we prevent 'paste', but unfortunately
619 // on IE we fail with pasteDataFromClipboard() here, because of... we don't know why, but
620 // we just fail, so... we paste nothing. FAIL.
621 // * native menu bar - the same as for native context menu.
622 //
623 // But don't you know any way to distinguish first two cases from last two?
624 // Only one - special flag set in CTRL+V handler and exec method of 'paste'
625 // command. And that's what we did using preventPasteEventNow().
626
627 pasteDataFromClipboard( evt );
628 } );
629
630 // It's not possible to clearly handle all four paste methods (ctrl+v, native menu bar
631 // native context menu, editor's command) in one 'paste/beforepaste' event in IE.
632 //
633 // For ctrl+v & editor's command it's easy to handle pasting in 'beforepaste' listener,
634 // so we do this. For another two methods it's better to use 'paste' event.
635 //
636 // 'paste' is always being fired after 'beforepaste' (except of weird one on opening native
637 // context menu), so for two methods handled in 'beforepaste' we're canceling 'paste'
638 // using preventPasteEvent state.
639 //
640 // 'paste' event in IE is being fired before getClipboardDataByPastebin executes its callback.
641 //
642 // QUESTION: Why didn't you handle all 4 paste methods in handler for 'paste'?
643 // Wouldn't this just be simpler?
644 // ANSWER: Then we would have to evt.data.preventDefault() only for native
645 // context menu and menu bar pastes. The same with execIECommand().
646 // That would force us to mark CTRL+V and editor's paste command with
647 // special flag, other than preventPasteEvent. But we still would have to
648 // have preventPasteEvent for the second event fired by execIECommand.
649 // Code would be longer and not cleaner.
650 if ( clipboard.mainPasteEvent == 'beforepaste' ) {
651 editable.on( 'paste', function( evt ) {
652 if ( preventPasteEvent ) {
653 return;
654 }
655
656 // Cancel next 'paste' event fired by execIECommand( 'paste' )
657 // at the end of this callback.
658 preventPasteEventNow();
659
660 // Prevent native paste.
661 evt.data.preventDefault();
662
663 pasteDataFromClipboard( evt );
664
665 // Force IE to paste content into pastebin so pasteDataFromClipboard will work.
666 if ( !execIECommand( 'paste' ) ) {
667 editor.openDialog( 'paste' );
668 }
669 } );
670
671 // If mainPasteEvent is 'beforePaste' (IE before Edge),
672 // dismiss the (wrong) 'beforepaste' event fired on context/toolbar menu open. (#7953)
673 editable.on( 'contextmenu', preventBeforePasteEventNow, null, null, 0 );
674
675 editable.on( 'beforepaste', function( evt ) {
676 // Do not prevent event on CTRL+V and SHIFT+INS because it blocks paste (#11970).
677 if ( evt.data && !evt.data.$.ctrlKey && !evt.data.$.shiftKey )
678 preventBeforePasteEventNow();
679 }, null, null, 0 );
680 }
681
682 editable.on( 'beforecut', function() {
683 !preventBeforePasteEvent && fixCut( editor );
684 } );
685
686 var mouseupTimeout;
687
688 // Use editor.document instead of editable in non-IEs for observing mouseup
689 // since editable won't fire the event if selection process started within
690 // iframe and ended out of the editor (#9851).
691 editable.attachListener( CKEDITOR.env.ie ? editable : editor.document.getDocumentElement(), 'mouseup', function() {
692 mouseupTimeout = setTimeout( function() {
693 setToolbarStates();
694 }, 0 );
695 } );
696
697 // Make sure that deferred mouseup callback isn't executed after editor instance
698 // had been destroyed. This may happen when editor.destroy() is called in parallel
699 // with mouseup event (i.e. a button with onclick callback) (#10219).
700 editor.on( 'destroy', function() {
701 clearTimeout( mouseupTimeout );
702 } );
703
704 editable.on( 'keyup', setToolbarStates );
705 }
706
707 // Create object representing Cut or Copy commands.
708 function createCutCopyCmd( type ) {
709 return {
710 type: type,
711 canUndo: type == 'cut', // We can't undo copy to clipboard.
712 startDisabled: true,
713 fakeKeystroke: type == 'cut' ? CKEDITOR.CTRL + 88 /*X*/ : CKEDITOR.CTRL + 67 /*C*/,
714 exec: function() {
715 // Attempts to execute the Cut and Copy operations.
716 function tryToCutCopy( type ) {
717 if ( CKEDITOR.env.ie )
718 return execIECommand( type );
719
720 // non-IEs part
721 try {
722 // Other browsers throw an error if the command is disabled.
723 return editor.document.$.execCommand( type, false, null );
724 } catch ( e ) {
725 return false;
726 }
727 }
728
729 this.type == 'cut' && fixCut();
730
731 var success = tryToCutCopy( this.type );
732
733 if ( !success ) {
734 // Show cutError or copyError.
735 editor.showNotification( editor.lang.clipboard[ this.type + 'Error' ] ); // jshint ignore:line
736 }
737
738 return success;
739 }
740 };
741 }
742
743 function createPasteCmd() {
744 return {
745 // Snapshots are done manually by editable.insertXXX methods.
746 canUndo: false,
747 async: true,
748 fakeKeystroke: CKEDITOR.CTRL + 86 /*V*/,
749 exec: function( editor, data ) {
750 var cmd = this,
751 fire = function( data, withBeforePaste ) {
752 data && firePasteEvents( editor, data, !!withBeforePaste );
753
754 editor.fire( 'afterCommandExec', {
755 name: 'paste',
756 command: cmd,
757 returnValue: !!data
758 } );
759 };
760
761 // Check data precisely - don't open dialog on empty string.
762 if ( typeof data == 'string' )
763 fire( {
764 dataValue: data,
765 method: 'paste',
766 dataTransfer: clipboard.initPasteDataTransfer()
767 }, 1 );
768 else
769 editor.getClipboardData( fire );
770 }
771 };
772 }
773
774 function preventPasteEventNow() {
775 preventPasteEvent = 1;
776 // For safety reason we should wait longer than 0/1ms.
777 // We don't know how long execution of quite complex getClipboardData will take
778 // and in for example 'paste' listener execCommand() (which fires 'paste') is called
779 // after getClipboardData finishes.
780 // Luckily, it's impossible to immediately fire another 'paste' event we want to handle,
781 // because we only handle there native context menu and menu bar.
782 setTimeout( function() {
783 preventPasteEvent = 0;
784 }, 100 );
785 }
786
787 function preventBeforePasteEventNow() {
788 preventBeforePasteEvent = 1;
789 setTimeout( function() {
790 preventBeforePasteEvent = 0;
791 }, 10 );
792 }
793
794 // Tries to execute any of the paste, cut or copy commands in IE. Returns a
795 // boolean indicating that the operation succeeded.
796 // @param {String} command *LOWER CASED* name of command ('paste', 'cut', 'copy').
797 function execIECommand( command ) {
798 var doc = editor.document,
799 body = doc.getBody(),
800 enabled = false,
801 onExec = function() {
802 enabled = true;
803 };
804
805 // The following seems to be the only reliable way to detect that
806 // clipboard commands are enabled in IE. It will fire the
807 // onpaste/oncut/oncopy events only if the security settings allowed
808 // the command to execute.
809 body.on( command, onExec );
810
811 // IE7: document.execCommand has problem to paste into positioned element.
812 if ( CKEDITOR.env.version > 7 ) {
813 doc.$.execCommand( command );
814 } else {
815 doc.$.selection.createRange().execCommand( command );
816 }
817
818 body.removeListener( command, onExec );
819
820 return enabled;
821 }
822
823 // Cutting off control type element in IE standards breaks the selection entirely. (#4881)
824 function fixCut() {
825 if ( !CKEDITOR.env.ie || CKEDITOR.env.quirks )
826 return;
827
828 var sel = editor.getSelection(),
829 control, range, dummy;
830
831 if ( ( sel.getType() == CKEDITOR.SELECTION_ELEMENT ) && ( control = sel.getSelectedElement() ) ) {
832 range = sel.getRanges()[ 0 ];
833 dummy = editor.document.createText( '' );
834 dummy.insertBefore( control );
835 range.setStartBefore( dummy );
836 range.setEndAfter( control );
837 sel.selectRanges( [ range ] );
838
839 // Clear up the fix if the paste wasn't succeeded.
840 setTimeout( function() {
841 // Element still online?
842 if ( control.getParent() ) {
843 dummy.remove();
844 sel.selectElement( control );
845 }
846 }, 0 );
847 }
848 }
849
850 // Allow to peek clipboard content by redirecting the
851 // pasting content into a temporary bin and grab the content of it.
852 function getClipboardDataByPastebin( evt, callback ) {
853 var doc = editor.document,
854 editable = editor.editable(),
855 cancel = function( evt ) {
856 evt.cancel();
857 },
858 blurListener;
859
860 // Avoid recursions on 'paste' event or consequent paste too fast. (#5730)
861 if ( doc.getById( 'cke_pastebin' ) )
862 return;
863
864 var sel = editor.getSelection();
865 var bms = sel.createBookmarks();
866
867 // #11384. On IE9+ we use native selectionchange (i.e. editor#selectionCheck) to cache the most
868 // recent selection which we then lock on editable blur. See selection.js for more info.
869 // selectionchange fired before getClipboardDataByPastebin() cached selection
870 // before creating bookmark (cached selection will be invalid, because bookmarks modified the DOM),
871 // so we need to fire selectionchange one more time, to store current seleciton.
872 // Selection will be locked when we focus pastebin.
873 if ( CKEDITOR.env.ie )
874 sel.root.fire( 'selectionchange' );
875
876 // Create container to paste into.
877 // For rich content we prefer to use "body" since it holds
878 // the least possibility to be splitted by pasted content, while this may
879 // breaks the text selection on a frame-less editable, "div" would be
880 // the best one in that case.
881 // In another case on old IEs moving the selection into a "body" paste bin causes error panic.
882 // Body can't be also used for Opera which fills it with <br>
883 // what is indistinguishable from pasted <br> (copying <br> in Opera isn't possible,
884 // but it can be copied from other browser).
885 var pastebin = new CKEDITOR.dom.element(
886 ( CKEDITOR.env.webkit || editable.is( 'body' ) ) && !CKEDITOR.env.ie ? 'body' : 'div', doc );
887
888 pastebin.setAttributes( {
889 id: 'cke_pastebin',
890 'data-cke-temp': '1'
891 } );
892
893 var containerOffset = 0,
894 offsetParent,
895 win = doc.getWindow();
896
897 if ( CKEDITOR.env.webkit ) {
898 // It's better to paste close to the real paste destination, so inherited styles
899 // (which Webkits will try to compensate by styling span) differs less from the destination's one.
900 editable.append( pastebin );
901 // Style pastebin like .cke_editable, to minimize differences between origin and destination. (#9754)
902 pastebin.addClass( 'cke_editable' );
903
904 // Compensate position of offsetParent.
905 if ( !editable.is( 'body' ) ) {
906 // We're not able to get offsetParent from pastebin (body element), so check whether
907 // its parent (editable) is positioned.
908 if ( editable.getComputedStyle( 'position' ) != 'static' )
909 offsetParent = editable;
910 // And if not - safely get offsetParent from editable.
911 else
912 offsetParent = CKEDITOR.dom.element.get( editable.$.offsetParent );
913
914 containerOffset = offsetParent.getDocumentPosition().y;
915 }
916 } else {
917 // Opera and IE doesn't allow to append to html element.
918 editable.getAscendant( CKEDITOR.env.ie ? 'body' : 'html', 1 ).append( pastebin );
919 }
920
921 pastebin.setStyles( {
922 position: 'absolute',
923 // Position the bin at the top (+10 for safety) of viewport to avoid any subsequent document scroll.
924 top: ( win.getScrollPosition().y - containerOffset + 10 ) + 'px',
925 width: '1px',
926 // Caret has to fit in that height, otherwise browsers like Chrome & Opera will scroll window to show it.
927 // Set height equal to viewport's height - 20px (safety gaps), minimum 1px.
928 height: Math.max( 1, win.getViewPaneSize().height - 20 ) + 'px',
929 overflow: 'hidden',
930 // Reset styles that can mess up pastebin position.
931 margin: 0,
932 padding: 0
933 } );
934
935 // Paste fails in Safari when the body tag has 'user-select: none'. (#12506)
936 if ( CKEDITOR.env.safari )
937 pastebin.setStyles( CKEDITOR.tools.cssVendorPrefix( 'user-select', 'text' ) );
938
939 // Check if the paste bin now establishes new editing host.
940 var isEditingHost = pastebin.getParent().isReadOnly();
941
942 if ( isEditingHost ) {
943 // Hide the paste bin.
944 pastebin.setOpacity( 0 );
945 // And make it editable.
946 pastebin.setAttribute( 'contenteditable', true );
947 }
948 // Transparency is not enough since positioned non-editing host always shows
949 // resize handler, pull it off the screen instead.
950 else {
951 pastebin.setStyle( editor.config.contentsLangDirection == 'ltr' ? 'left' : 'right', '-10000px' );
952 }
953
954 editor.on( 'selectionChange', cancel, null, null, 0 );
955
956 // Webkit fill fire blur on editable when moving selection to
957 // pastebin (if body is used). Cancel it because it causes incorrect
958 // selection lock in case of inline editor (#10644).
959 // The same seems to apply to Firefox (#10787).
960 if ( CKEDITOR.env.webkit || CKEDITOR.env.gecko )
961 blurListener = editable.once( 'blur', cancel, null, null, -100 );
962
963 // Temporarily move selection to the pastebin.
964 isEditingHost && pastebin.focus();
965 var range = new CKEDITOR.dom.range( pastebin );
966 range.selectNodeContents( pastebin );
967 var selPastebin = range.select();
968
969 // If non-native paste is executed, IE will open security alert and blur editable.
970 // Editable will then lock selection inside itself and after accepting security alert
971 // this selection will be restored. We overwrite stored selection, so it's restored
972 // in pastebin. (#9552)
973 if ( CKEDITOR.env.ie ) {
974 blurListener = editable.once( 'blur', function() {
975 editor.lockSelection( selPastebin );
976 } );
977 }
978
979 var scrollTop = CKEDITOR.document.getWindow().getScrollPosition().y;
980
981 // Wait a while and grab the pasted contents.
982 setTimeout( function() {
983 // Restore main window's scroll position which could have been changed
984 // by browser in cases described in #9771.
985 if ( CKEDITOR.env.webkit )
986 CKEDITOR.document.getBody().$.scrollTop = scrollTop;
987
988 // Blur will be fired only on non-native paste. In other case manually remove listener.
989 blurListener && blurListener.removeListener();
990
991 // Restore properly the document focus. (#8849)
992 if ( CKEDITOR.env.ie )
993 editable.focus();
994
995 // IE7: selection must go before removing pastebin. (#8691)
996 sel.selectBookmarks( bms );
997 pastebin.remove();
998
999 // Grab the HTML contents.
1000 // We need to look for a apple style wrapper on webkit it also adds
1001 // a div wrapper if you copy/paste the body of the editor.
1002 // Remove hidden div and restore selection.
1003 var bogusSpan;
1004 if ( CKEDITOR.env.webkit && ( bogusSpan = pastebin.getFirst() ) && ( bogusSpan.is && bogusSpan.hasClass( 'Apple-style-span' ) ) )
1005 pastebin = bogusSpan;
1006
1007 editor.removeListener( 'selectionChange', cancel );
1008 callback( pastebin.getHtml() );
1009 }, 0 );
1010 }
1011
1012 // Try to get content directly on IE from clipboard, without native event
1013 // being fired before. In other words - synthetically get clipboard data, if it's possible.
1014 // mainPasteEvent will be fired, so if forced native paste:
1015 // * worked, getClipboardDataByPastebin will grab it,
1016 // * didn't work, dataValue and dataTransfer will be empty and editor#paste won't be fired.
1017 // Clipboard data can be accessed directly only on IEs older than Edge.
1018 // On other browsers we should fire beforePaste event and return false.
1019 function getClipboardDataDirectly() {
1020 if ( clipboard.mainPasteEvent == 'paste' ) {
1021 // beforePaste should be fired when dialog open so it can be canceled.
1022 editor.fire( 'beforePaste', { type: 'auto', method: 'paste' } );
1023 return false;
1024 }
1025
1026 // Prevent IE from pasting at the begining of the document.
1027 editor.focus();
1028
1029 // Command will be handled by 'beforepaste', but as
1030 // execIECommand( 'paste' ) will fire also 'paste' event
1031 // we're canceling it.
1032 preventPasteEventNow();
1033
1034 // #9247: Lock focus to prevent IE from hiding toolbar for inline editor.
1035 var focusManager = editor.focusManager;
1036 focusManager.lock();
1037
1038 if ( editor.editable().fire( clipboard.mainPasteEvent ) && !execIECommand( 'paste' ) ) {
1039 focusManager.unlock();
1040 return false;
1041 }
1042 focusManager.unlock();
1043
1044 return true;
1045 }
1046
1047 // Listens for some clipboard related keystrokes, so they get customized.
1048 // Needs to be bind to keydown event.
1049 function onKey( event ) {
1050 if ( editor.mode != 'wysiwyg' )
1051 return;
1052
1053 switch ( event.data.keyCode ) {
1054 // Paste
1055 case CKEDITOR.CTRL + 86: // CTRL+V
1056 case CKEDITOR.SHIFT + 45: // SHIFT+INS
1057 var editable = editor.editable();
1058
1059 // Cancel 'paste' event because ctrl+v is for IE handled
1060 // by 'beforepaste'.
1061 preventPasteEventNow();
1062
1063 // Simulate 'beforepaste' event for all browsers using 'paste' as main event.
1064 if ( clipboard.mainPasteEvent == 'paste' ) {
1065 editable.fire( 'beforepaste' );
1066 }
1067
1068 return;
1069
1070 // Cut
1071 case CKEDITOR.CTRL + 88: // CTRL+X
1072 case CKEDITOR.SHIFT + 46: // SHIFT+DEL
1073 // Save Undo snapshot.
1074 editor.fire( 'saveSnapshot' ); // Save before cut
1075 setTimeout( function() {
1076 editor.fire( 'saveSnapshot' ); // Save after cut
1077 }, 50 ); // OSX is slow (#11416).
1078 }
1079 }
1080
1081 function pasteDataFromClipboard( evt ) {
1082 // Default type is 'auto', but can be changed by beforePaste listeners.
1083 var eventData = {
1084 type: 'auto',
1085 method: 'paste',
1086 dataTransfer: clipboard.initPasteDataTransfer( evt )
1087 };
1088
1089 eventData.dataTransfer.cacheData();
1090
1091 // Fire 'beforePaste' event so clipboard flavor get customized by other plugins.
1092 // If 'beforePaste' is canceled continue executing getClipboardDataByPastebin and then do nothing
1093 // (do not fire 'paste', 'afterPaste' events). This way we can grab all - synthetically
1094 // and natively pasted content and prevent its insertion into editor
1095 // after canceling 'beforePaste' event.
1096 var beforePasteNotCanceled = editor.fire( 'beforePaste', eventData ) !== false;
1097
1098 // Do not use paste bin if the browser let us get HTML or files from dataTranfer.
1099 if ( beforePasteNotCanceled && clipboard.canClipboardApiBeTrusted( eventData.dataTransfer, editor ) ) {
1100 evt.data.preventDefault();
1101 setTimeout( function() {
1102 firePasteEvents( editor, eventData );
1103 }, 0 );
1104 } else {
1105 getClipboardDataByPastebin( evt, function( data ) {
1106 // Clean up.
1107 eventData.dataValue = data.replace( /<span[^>]+data-cke-bookmark[^<]*?<\/span>/ig, '' );
1108
1109 // Fire remaining events (without beforePaste)
1110 beforePasteNotCanceled && firePasteEvents( editor, eventData );
1111 } );
1112 }
1113 }
1114
1115 function setToolbarStates() {
1116 if ( editor.mode != 'wysiwyg' )
1117 return;
1118
1119 var pasteState = stateFromNamedCommand( 'paste' );
1120
1121 editor.getCommand( 'cut' ).setState( stateFromNamedCommand( 'cut' ) );
1122 editor.getCommand( 'copy' ).setState( stateFromNamedCommand( 'copy' ) );
1123 editor.getCommand( 'paste' ).setState( pasteState );
1124 editor.fire( 'pasteState', pasteState );
1125 }
1126
1127 function stateFromNamedCommand( command ) {
1128 if ( inReadOnly && command in { paste: 1, cut: 1 } )
1129 return CKEDITOR.TRISTATE_DISABLED;
1130
1131 if ( command == 'paste' )
1132 return CKEDITOR.TRISTATE_OFF;
1133
1134 // Cut, copy - check if the selection is not empty.
1135 var sel = editor.getSelection(),
1136 ranges = sel.getRanges(),
1137 selectionIsEmpty = sel.getType() == CKEDITOR.SELECTION_NONE || ( ranges.length == 1 && ranges[ 0 ].collapsed );
1138
1139 return selectionIsEmpty ? CKEDITOR.TRISTATE_DISABLED : CKEDITOR.TRISTATE_OFF;
1140 }
1141 }
1142
1143 // Returns:
1144 // * 'htmlifiedtext' if content looks like transformed by browser from plain text.
1145 // See clipboard/paste.html TCs for more info.
1146 // * 'html' if it is not 'htmlifiedtext'.
1147 function recogniseContentType( data ) {
1148 if ( CKEDITOR.env.webkit ) {
1149 // Plain text or ( <div><br></div> and text inside <div> ).
1150 if ( !data.match( /^[^<]*$/g ) && !data.match( /^(<div><br( ?\/)?><\/div>|<div>[^<]*<\/div>)*$/gi ) )
1151 return 'html';
1152 } else if ( CKEDITOR.env.ie ) {
1153 // Text and <br> or ( text and <br> in <p> - paragraphs can be separated by new \r\n ).
1154 if ( !data.match( /^([^<]|<br( ?\/)?>)*$/gi ) && !data.match( /^(<p>([^<]|<br( ?\/)?>)*<\/p>|(\r\n))*$/gi ) )
1155 return 'html';
1156 } else if ( CKEDITOR.env.gecko ) {
1157 // Text or <br>.
1158 if ( !data.match( /^([^<]|<br( ?\/)?>)*$/gi ) )
1159 return 'html';
1160 } else {
1161 return 'html';
1162 }
1163
1164 return 'htmlifiedtext';
1165 }
1166
1167 // This function transforms what browsers produce when
1168 // pasting plain text into editable element (see clipboard/paste.html TCs
1169 // for more info) into correct HTML (similar to that produced by text2Html).
1170 function htmlifiedTextHtmlification( config, data ) {
1171 function repeatParagraphs( repeats ) {
1172 // Repeat blocks floor((n+1)/2) times.
1173 // Even number of repeats - add <br> at the beginning of last <p>.
1174 return CKEDITOR.tools.repeat( '</p><p>', ~~( repeats / 2 ) ) + ( repeats % 2 == 1 ? '<br>' : '' );
1175 }
1176
1177 // Replace adjacent white-spaces (EOLs too - Fx sometimes keeps them) with one space.
1178 data = data.replace( /\s+/g, ' ' )
1179 // Remove spaces from between tags.
1180 .replace( /> +</g, '><' )
1181 // Normalize XHTML syntax and upper cased <br> tags.
1182 .replace( /<br ?\/>/gi, '<br>' );
1183
1184 // IE - lower cased tags.
1185 data = data.replace( /<\/?[A-Z]+>/g, function( match ) {
1186 return match.toLowerCase();
1187 } );
1188
1189 // Don't touch single lines (no <br|p|div>) - nothing to do here.
1190 if ( data.match( /^[^<]$/ ) )
1191 return data;
1192
1193 // Webkit.
1194 if ( CKEDITOR.env.webkit && data.indexOf( '<div>' ) > -1 ) {
1195 // One line break at the beginning - insert <br>
1196 data = data.replace( /^(<div>(<br>|)<\/div>)(?!$|(<div>(<br>|)<\/div>))/g, '<br>' )
1197 // Two or more - reduce number of new lines by one.
1198 .replace( /^(<div>(<br>|)<\/div>){2}(?!$)/g, '<div></div>' );
1199
1200 // Two line breaks create one paragraph in Webkit.
1201 if ( data.match( /<div>(<br>|)<\/div>/ ) ) {
1202 data = '<p>' + data.replace( /(<div>(<br>|)<\/div>)+/g, function( match ) {
1203 return repeatParagraphs( match.split( '</div><div>' ).length + 1 );
1204 } ) + '</p>';
1205 }
1206
1207 // One line break create br.
1208 data = data.replace( /<\/div><div>/g, '<br>' );
1209
1210 // Remove remaining divs.
1211 data = data.replace( /<\/?div>/g, '' );
1212 }
1213
1214 // Opera and Firefox and enterMode != BR.
1215 if ( CKEDITOR.env.gecko && config.enterMode != CKEDITOR.ENTER_BR ) {
1216 // Remove bogus <br> - Fx generates two <brs> for one line break.
1217 // For two line breaks it still produces two <brs>, but it's better to ignore this case than the first one.
1218 if ( CKEDITOR.env.gecko )
1219 data = data.replace( /^<br><br>$/, '<br>' );
1220
1221 // This line satisfy edge case when for Opera we have two line breaks
1222 //data = data.replace( /)
1223
1224 if ( data.indexOf( '<br><br>' ) > -1 ) {
1225 // Two line breaks create one paragraph, three - 2, four - 3, etc.
1226 data = '<p>' + data.replace( /(<br>){2,}/g, function( match ) {
1227 return repeatParagraphs( match.length / 4 );
1228 } ) + '</p>';
1229 }
1230 }
1231
1232 return switchEnterMode( config, data );
1233 }
1234
1235 function filtersFactoryFactory() {
1236 var filters = {};
1237
1238 function setUpTags() {
1239 var tags = {};
1240
1241 for ( var tag in CKEDITOR.dtd ) {
1242 if ( tag.charAt( 0 ) != '$' && tag != 'div' && tag != 'span' ) {
1243 tags[ tag ] = 1;
1244 }
1245 }
1246
1247 return tags;
1248 }
1249
1250 function createSemanticContentFilter() {
1251 var filter = new CKEDITOR.filter();
1252
1253 filter.allow( {
1254 $1: {
1255 elements: setUpTags(),
1256 attributes: true,
1257 styles: false,
1258 classes: false
1259 }
1260 } );
1261
1262 return filter;
1263 }
1264
1265 return {
1266 get: function( type ) {
1267 if ( type == 'plain-text' ) {
1268 // Does this look confusing to you? Did we forget about enter mode?
1269 // It is a trick that let's us creating one filter for edidtor, regardless of its
1270 // activeEnterMode (which as the name indicates can change during runtime).
1271 //
1272 // How does it work?
1273 // The active enter mode is passed to the filter.applyTo method.
1274 // The filter first marks all elements except <br> as disallowed and then tries to remove
1275 // them. However, it cannot remove e.g. a <p> element completely, because it's a basic structural element,
1276 // so it tries to replace it with an element created based on the active enter mode, eventually doing nothing.
1277 //
1278 // Now you can sleep well.
1279 return filters.plainText || ( filters.plainText = new CKEDITOR.filter( 'br' ) );
1280 } else if ( type == 'semantic-content' ) {
1281 return filters.semanticContent || ( filters.semanticContent = createSemanticContentFilter() );
1282 } else if ( type ) {
1283 // Create filter based on rules (string or object).
1284 return new CKEDITOR.filter( type );
1285 }
1286
1287 return null;
1288 }
1289 };
1290 }
1291
1292 function filterContent( editor, data, filter ) {
1293 var fragment = CKEDITOR.htmlParser.fragment.fromHtml( data ),
1294 writer = new CKEDITOR.htmlParser.basicWriter();
1295
1296 filter.applyTo( fragment, true, false, editor.activeEnterMode );
1297 fragment.writeHtml( writer );
1298
1299 return writer.getHtml();
1300 }
1301
1302 function switchEnterMode( config, data ) {
1303 if ( config.enterMode == CKEDITOR.ENTER_BR ) {
1304 data = data.replace( /(<\/p><p>)+/g, function( match ) {
1305 return CKEDITOR.tools.repeat( '<br>', match.length / 7 * 2 );
1306 } ).replace( /<\/?p>/g, '' );
1307 } else if ( config.enterMode == CKEDITOR.ENTER_DIV ) {
1308 data = data.replace( /<(\/)?p>/g, '<$1div>' );
1309 }
1310
1311 return data;
1312 }
1313
1314 function preventDefaultSetDropEffectToNone( evt ) {
1315 evt.data.preventDefault();
1316 evt.data.$.dataTransfer.dropEffect = 'none';
1317 }
1318
1319 function initDragDrop( editor ) {
1320 var clipboard = CKEDITOR.plugins.clipboard;
1321
1322 editor.on( 'contentDom', function() {
1323 var editable = editor.editable(),
1324 dropTarget = CKEDITOR.plugins.clipboard.getDropTarget( editor ),
1325 top = editor.ui.space( 'top' ),
1326 bottom = editor.ui.space( 'bottom' );
1327
1328 // -------------- DRAGOVER TOP & BOTTOM --------------
1329
1330 // Not allowing dragging on toolbar and bottom (#12613).
1331 clipboard.preventDefaultDropOnElement( top );
1332 clipboard.preventDefaultDropOnElement( bottom );
1333
1334 // -------------- DRAGSTART --------------
1335 // Listed on dragstart to mark internal and cross-editor drag & drop
1336 // and save range and selected HTML.
1337
1338 editable.attachListener( dropTarget, 'dragstart', fireDragEvent );
1339
1340 // Make sure to reset data transfer (in case dragend was not called or was canceled).
1341 editable.attachListener( editor, 'dragstart', clipboard.resetDragDataTransfer, clipboard, null, 1 );
1342
1343 // Create a dataTransfer object and save it globally.
1344 editable.attachListener( editor, 'dragstart', function( evt ) {
1345 clipboard.initDragDataTransfer( evt, editor );
1346 }, null, null, 2 );
1347
1348 editable.attachListener( editor, 'dragstart', function() {
1349 // Save drag range globally for cross editor D&D.
1350 var dragRange = clipboard.dragRange = editor.getSelection().getRanges()[ 0 ];
1351
1352 // Store number of children, so we can later tell if any text node was split on drop. (#13011, #13447)
1353 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) {
1354 clipboard.dragStartContainerChildCount = dragRange ? getContainerChildCount( dragRange.startContainer ) : null;
1355 clipboard.dragEndContainerChildCount = dragRange ? getContainerChildCount( dragRange.endContainer ) : null;
1356 }
1357 }, null, null, 100 );
1358
1359 // -------------- DRAGEND --------------
1360 // Clean up on dragend.
1361
1362 editable.attachListener( dropTarget, 'dragend', fireDragEvent );
1363
1364 // Init data transfer if someone wants to use it in dragend.
1365 editable.attachListener( editor, 'dragend', clipboard.initDragDataTransfer, clipboard, null, 1 );
1366
1367 // When drag & drop is done we need to reset dataTransfer so the future
1368 // external drop will be not recognize as internal.
1369 editable.attachListener( editor, 'dragend', clipboard.resetDragDataTransfer, clipboard, null, 100 );
1370
1371 // -------------- DRAGOVER --------------
1372 // We need to call preventDefault on dragover because otherwise if
1373 // we drop image it will overwrite document.
1374
1375 editable.attachListener( dropTarget, 'dragover', function( evt ) {
1376 var target = evt.data.getTarget();
1377
1378 // Prevent reloading page when dragging image on empty document (#12619).
1379 if ( target && target.is && target.is( 'html' ) ) {
1380 evt.data.preventDefault();
1381 return;
1382 }
1383
1384 // If we do not prevent default dragover on IE the file path
1385 // will be loaded and we will lose content. On the other hand
1386 // if we prevent it the cursor will not we shown, so we prevent
1387 // dragover only on IE, on versions which support file API and only
1388 // if the event contains files.
1389 if ( CKEDITOR.env.ie &&
1390 CKEDITOR.plugins.clipboard.isFileApiSupported &&
1391 evt.data.$.dataTransfer.types.contains( 'Files' ) ) {
1392 evt.data.preventDefault();
1393 }
1394 } );
1395
1396 // -------------- DROP --------------
1397
1398 editable.attachListener( dropTarget, 'drop', function( evt ) {
1399 // Do nothing if event was already prevented. (#13879)
1400 if ( evt.data.$.defaultPrevented ) {
1401 return;
1402 }
1403
1404 // Cancel native drop.
1405 evt.data.preventDefault();
1406
1407 var target = evt.data.getTarget(),
1408 readOnly = target.isReadOnly();
1409
1410 // Do nothing if drop on non editable element (#13015).
1411 // The <html> tag isn't editable (body is), but we want to allow drop on it
1412 // (so it is possible to drop below editor contents).
1413 if ( readOnly && !( target.type == CKEDITOR.NODE_ELEMENT && target.is( 'html' ) ) ) {
1414 return;
1415 }
1416
1417 // Getting drop position is one of the most complex parts.
1418 var dropRange = clipboard.getRangeAtDropPosition( evt, editor ),
1419 dragRange = clipboard.dragRange;
1420
1421 // Do nothing if it was not possible to get drop range.
1422 if ( !dropRange ) {
1423 return;
1424 }
1425
1426 // Fire drop.
1427 fireDragEvent( evt, dragRange, dropRange );
1428 }, null, null, 9999 );
1429
1430 // Create dataTransfer or get it, if it was created before.
1431 editable.attachListener( editor, 'drop', clipboard.initDragDataTransfer, clipboard, null, 1 );
1432
1433 // Execute drop action, fire paste.
1434 editable.attachListener( editor, 'drop', function( evt ) {
1435 var data = evt.data;
1436
1437 if ( !data ) {
1438 return;
1439 }
1440
1441 // Let user modify drag and drop range.
1442 var dropRange = data.dropRange,
1443 dragRange = data.dragRange,
1444 dataTransfer = data.dataTransfer;
1445
1446 if ( dataTransfer.getTransferType( editor ) == CKEDITOR.DATA_TRANSFER_INTERNAL ) {
1447 // Execute drop with a timeout because otherwise selection, after drop,
1448 // on IE is in the drag position, instead of drop position.
1449 setTimeout( function() {
1450 clipboard.internalDrop( dragRange, dropRange, dataTransfer, editor );
1451 }, 0 );
1452 } else if ( dataTransfer.getTransferType( editor ) == CKEDITOR.DATA_TRANSFER_CROSS_EDITORS ) {
1453 crossEditorDrop( dragRange, dropRange, dataTransfer );
1454 } else {
1455 externalDrop( dropRange, dataTransfer );
1456 }
1457 }, null, null, 9999 );
1458
1459 // Cross editor drag and drop (drag in one Editor and drop in the other).
1460 function crossEditorDrop( dragRange, dropRange, dataTransfer ) {
1461 // Paste event should be fired before delete contents because otherwise
1462 // Chrome have a problem with drop range (Chrome split the drop
1463 // range container so the offset is bigger then container length).
1464 dropRange.select();
1465 firePasteEvents( editor, { dataTransfer: dataTransfer, method: 'drop' }, 1 );
1466
1467 // Remove dragged content and make a snapshot.
1468 dataTransfer.sourceEditor.fire( 'saveSnapshot' );
1469
1470 dataTransfer.sourceEditor.editable().extractHtmlFromRange( dragRange );
1471
1472 // Make some selection before saving snapshot, otherwise error will be thrown, because
1473 // there will be no valid selection after content is removed.
1474 dataTransfer.sourceEditor.getSelection().selectRanges( [ dragRange ] );
1475 dataTransfer.sourceEditor.fire( 'saveSnapshot' );
1476 }
1477
1478 // Drop from external source.
1479 function externalDrop( dropRange, dataTransfer ) {
1480 // Paste content into the drop position.
1481 dropRange.select();
1482
1483 firePasteEvents( editor, { dataTransfer: dataTransfer, method: 'drop' }, 1 );
1484
1485 // Usually we reset DataTranfer on dragend,
1486 // but dragend is called on the same element as dragstart
1487 // so it will not be called on on external drop.
1488 clipboard.resetDragDataTransfer();
1489 }
1490
1491 // Fire drag/drop events (dragstart, dragend, drop).
1492 function fireDragEvent( evt, dragRange, dropRange ) {
1493 var eventData = {
1494 $: evt.data.$,
1495 target: evt.data.getTarget()
1496 };
1497
1498 if ( dragRange ) {
1499 eventData.dragRange = dragRange;
1500 }
1501 if ( dropRange ) {
1502 eventData.dropRange = dropRange;
1503 }
1504
1505 if ( editor.fire( evt.name, eventData ) === false ) {
1506 evt.data.preventDefault();
1507 }
1508 }
1509
1510 function getContainerChildCount( container ) {
1511 if ( container.type != CKEDITOR.NODE_ELEMENT ) {
1512 container = container.getParent();
1513 }
1514
1515 return container.getChildCount();
1516 }
1517 } );
1518 }
1519
1520 /**
1521 * @singleton
1522 * @class CKEDITOR.plugins.clipboard
1523 */
1524 CKEDITOR.plugins.clipboard = {
1525 /**
1526 * True if the environment allows to set data on copy or cut manually. This value is false in IE, because this browser
1527 * shows the security dialog window when the script tries to set clipboard data and on iOS, because custom data is
1528 * not saved to clipboard there.
1529 *
1530 * @since 4.5
1531 * @readonly
1532 * @property {Boolean}
1533 */
1534 isCustomCopyCutSupported: !CKEDITOR.env.ie && !CKEDITOR.env.iOS,
1535
1536 /**
1537 * True if the environment supports MIME types and custom data types in dataTransfer/cliboardData getData/setData methods.
1538 *
1539 * @since 4.5
1540 * @readonly
1541 * @property {Boolean}
1542 */
1543 isCustomDataTypesSupported: !CKEDITOR.env.ie,
1544
1545 /**
1546 * True if the environment supports File API.
1547 *
1548 * @since 4.5
1549 * @readonly
1550 * @property {Boolean}
1551 */
1552 isFileApiSupported: !CKEDITOR.env.ie || CKEDITOR.env.version > 9,
1553
1554 /**
1555 * Main native paste event editable should listen to.
1556 *
1557 * **Note:** Safari does not like the {@link CKEDITOR.editor#beforePaste} event &mdash; it sometimes does not
1558 * handle <kbd>Ctrl+C</kbd> properly. This is probably caused by some race condition between events.
1559 * Chrome, Firefox and Edge work well with both events, so it is better to use {@link CKEDITOR.editor#paste}
1560 * which will handle pasting from e.g. browsers' menu bars.
1561 * IE7/8 does not like the {@link CKEDITOR.editor#paste} event for which it is throwing random errors.
1562 *
1563 * @since 4.5
1564 * @readonly
1565 * @property {String}
1566 */
1567 mainPasteEvent: ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? 'beforepaste' : 'paste',
1568
1569 /**
1570 * Returns `true` if it is expected that a browser provides HTML data through the Clipboard API.
1571 * If not, this method returns `false` and as a result CKEditor will use the paste bin. Read more in
1572 * the [Clipboard Integration](http://docs.ckeditor.com/#!/guide/dev_clipboard-section-clipboard-api) guide.
1573 *
1574 * @since 4.5.2
1575 * @returns {Boolean}
1576 */
1577 canClipboardApiBeTrusted: function( dataTransfer, editor ) {
1578 // If it's an internal or cross-editor data transfer, then it means that custom cut/copy/paste support works
1579 // and that the data were put manually on the data transfer so we can be sure that it's available.
1580 if ( dataTransfer.getTransferType( editor ) != CKEDITOR.DATA_TRANSFER_EXTERNAL ) {
1581 return true;
1582 }
1583
1584 // In Chrome we can trust Clipboard API, with the exception of Chrome on Android (in both - mobile and desktop modes), where
1585 // clipboard API is not available so we need to check it (#13187).
1586 if ( CKEDITOR.env.chrome && !dataTransfer.isEmpty() ) {
1587 return true;
1588 }
1589
1590 // Because of a Firefox bug HTML data are not available in some cases (e.g. paste from Word), in such cases we
1591 // need to use the pastebin (#13528, https://bugzilla.mozilla.org/show_bug.cgi?id=1183686).
1592 if ( CKEDITOR.env.gecko && ( dataTransfer.getData( 'text/html' ) || dataTransfer.getFilesCount() ) ) {
1593 return true;
1594 }
1595
1596 // In Safari and IE HTML data is not available though the Clipboard API.
1597 // In Edge things are a bit messy at the moment -
1598 // https://connect.microsoft.com/IE/feedback/details/1572456/edge-clipboard-api-text-html-content-messed-up-in-event-clipboarddata
1599 // It is safer to use the paste bin in unknown cases.
1600 return false;
1601 },
1602
1603 /**
1604 * Returns the element that should be used as the target for the drop event.
1605 *
1606 * @since 4.5
1607 * @param {CKEDITOR.editor} editor The editor instance.
1608 * @returns {CKEDITOR.dom.domObject} the element that should be used as the target for the drop event.
1609 */
1610 getDropTarget: function( editor ) {
1611 var editable = editor.editable();
1612
1613 // #11123 Firefox needs to listen on document, because otherwise event won't be fired.
1614 // #11086 IE8 cannot listen on document.
1615 if ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) || editable.isInline() ) {
1616 return editable;
1617 } else {
1618 return editor.document;
1619 }
1620 },
1621
1622 /**
1623 * IE 8 & 9 split text node on drop so the first node contains the
1624 * text before the drop position and the second contains the rest. If you
1625 * drag the content from the same node you will be not be able to get
1626 * it (the range becomes invalid), so you need to join them back.
1627 *
1628 * Note that the first node in IE 8 & 9 is the original node object
1629 * but with shortened content.
1630 *
1631 * Before:
1632 * --- Text Node A ----------------------------------
1633 * /\
1634 * Drag position
1635 *
1636 * After (IE 8 & 9):
1637 * --- Text Node A ----- --- Text Node B -----------
1638 * /\ /\
1639 * Drop position Drag position
1640 * (invalid)
1641 *
1642 * After (other browsers):
1643 * --- Text Node A ----------------------------------
1644 * /\ /\
1645 * Drop position Drag position
1646 *
1647 * **Note:** This function is in the public scope for tests usage only.
1648 *
1649 * @since 4.5
1650 * @private
1651 * @param {CKEDITOR.dom.range} dragRange The drag range.
1652 * @param {CKEDITOR.dom.range} dropRange The drop range.
1653 * @param {Number} preDragStartContainerChildCount The number of children of the drag range start container before the drop.
1654 * @param {Number} preDragEndContainerChildCount The number of children of the drag range end container before the drop.
1655 */
1656 fixSplitNodesAfterDrop: function( dragRange, dropRange, preDragStartContainerChildCount, preDragEndContainerChildCount ) {
1657 var dropContainer = dropRange.startContainer;
1658
1659 if (
1660 typeof preDragEndContainerChildCount != 'number' ||
1661 typeof preDragStartContainerChildCount != 'number'
1662 ) {
1663 return;
1664 }
1665
1666 // We are only concerned about ranges anchored in elements.
1667 if ( dropContainer.type != CKEDITOR.NODE_ELEMENT ) {
1668 return;
1669 }
1670
1671 if ( handleContainer( dragRange.startContainer, dropContainer, preDragStartContainerChildCount ) ) {
1672 return;
1673 }
1674
1675 if ( handleContainer( dragRange.endContainer, dropContainer, preDragEndContainerChildCount ) ) {
1676 return;
1677 }
1678
1679 function handleContainer( dragContainer, dropContainer, preChildCount ) {
1680 var dragElement = dragContainer;
1681 if ( dragElement.type == CKEDITOR.NODE_TEXT ) {
1682 dragElement = dragContainer.getParent();
1683 }
1684
1685 if ( dragElement.equals( dropContainer ) && preChildCount != dropContainer.getChildCount() ) {
1686 applyFix( dropRange );
1687 return true;
1688 }
1689 }
1690
1691 function applyFix( dropRange ) {
1692 var nodeBefore = dropRange.startContainer.getChild( dropRange.startOffset - 1 ),
1693 nodeAfter = dropRange.startContainer.getChild( dropRange.startOffset );
1694
1695 if (
1696 nodeBefore && nodeBefore.type == CKEDITOR.NODE_TEXT &&
1697 nodeAfter && nodeAfter.type == CKEDITOR.NODE_TEXT
1698 ) {
1699 var offset = nodeBefore.getLength();
1700
1701 nodeBefore.setText( nodeBefore.getText() + nodeAfter.getText() );
1702 nodeAfter.remove();
1703
1704 dropRange.setStart( nodeBefore, offset );
1705 dropRange.collapse( true );
1706 }
1707 }
1708 },
1709
1710 /**
1711 * Checks whether turning the drag range into bookmarks will invalidate the drop range.
1712 * This usually happens when the drop range shares the container with the drag range and is
1713 * located after the drag range, but there are countless edge cases.
1714 *
1715 * This function is stricly related to {@link #internalDrop} which toggles
1716 * order in which it creates bookmarks for both ranges based on a value returned
1717 * by this method. In some cases this method returns a value which is not necessarily
1718 * true in terms of what it was meant to check, but it is convenient, because
1719 * we know how it is interpreted in {@link #internalDrop}, so the correct
1720 * behavior of the entire algorithm is assured.
1721 *
1722 * **Note:** This function is in the public scope for tests usage only.
1723 *
1724 * @since 4.5
1725 * @private
1726 * @param {CKEDITOR.dom.range} dragRange The first range to compare.
1727 * @param {CKEDITOR.dom.range} dropRange The second range to compare.
1728 * @returns {Boolean} `true` if the first range is before the second range.
1729 */
1730 isDropRangeAffectedByDragRange: function( dragRange, dropRange ) {
1731 var dropContainer = dropRange.startContainer,
1732 dropOffset = dropRange.endOffset;
1733
1734 // Both containers are the same and drop offset is at the same position or later.
1735 // " A L] A " " M A "
1736 // ^ ^
1737 if ( dragRange.endContainer.equals( dropContainer ) && dragRange.endOffset <= dropOffset ) {
1738 return true;
1739 }
1740
1741 // Bookmark for drag start container will mess up with offsets.
1742 // " O [L A " " M A "
1743 // ^ ^
1744 if (
1745 dragRange.startContainer.getParent().equals( dropContainer ) &&
1746 dragRange.startContainer.getIndex() < dropOffset
1747 ) {
1748 return true;
1749 }
1750
1751 // Bookmark for drag end container will mess up with offsets.
1752 // " O] L A " " M A "
1753 // ^ ^
1754 if (
1755 dragRange.endContainer.getParent().equals( dropContainer ) &&
1756 dragRange.endContainer.getIndex() < dropOffset
1757 ) {
1758 return true;
1759 }
1760
1761 return false;
1762 },
1763
1764 /**
1765 * Internal drag and drop (drag and drop in the same editor instance).
1766 *
1767 * **Note:** This function is in the public scope for tests usage only.
1768 *
1769 * @since 4.5
1770 * @private
1771 * @param {CKEDITOR.dom.range} dragRange The first range to compare.
1772 * @param {CKEDITOR.dom.range} dropRange The second range to compare.
1773 * @param {CKEDITOR.plugins.clipboard.dataTransfer} dataTransfer
1774 * @param {CKEDITOR.editor} editor
1775 */
1776 internalDrop: function( dragRange, dropRange, dataTransfer, editor ) {
1777 var clipboard = CKEDITOR.plugins.clipboard,
1778 editable = editor.editable(),
1779 dragBookmark, dropBookmark, isDropRangeAffected;
1780
1781 // Save and lock snapshot so there will be only
1782 // one snapshot for both remove and insert content.
1783 editor.fire( 'saveSnapshot' );
1784 editor.fire( 'lockSnapshot', { dontUpdate: 1 } );
1785
1786 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) {
1787 this.fixSplitNodesAfterDrop(
1788 dragRange,
1789 dropRange,
1790 clipboard.dragStartContainerChildCount,
1791 clipboard.dragEndContainerChildCount
1792 );
1793 }
1794
1795 // Because we manipulate multiple ranges we need to do it carefully,
1796 // changing one range (event creating a bookmark) may make other invalid.
1797 // We need to change ranges into bookmarks so we can manipulate them easily in the future.
1798 // We can change the range which is later in the text before we change the preceding range.
1799 // We call isDropRangeAffectedByDragRange to test the order of ranges.
1800 isDropRangeAffected = this.isDropRangeAffectedByDragRange( dragRange, dropRange );
1801 if ( !isDropRangeAffected ) {
1802 dragBookmark = dragRange.createBookmark( false );
1803 }
1804 dropBookmark = dropRange.clone().createBookmark( false );
1805 if ( isDropRangeAffected ) {
1806 dragBookmark = dragRange.createBookmark( false );
1807 }
1808
1809 // Check if drop range is inside range.
1810 // This is an edge case when we drop something on editable's margin/padding.
1811 // That space is not treated as a part of the range we drag, so it is possible to drop there.
1812 // When we drop, browser tries to find closest drop position and it finds it inside drag range. (#13453)
1813 var startNode = dragBookmark.startNode,
1814 endNode = dragBookmark.endNode,
1815 dropNode = dropBookmark.startNode,
1816 dropInsideDragRange =
1817 // Must check endNode because dragRange could be collapsed in some edge cases (simulated DnD).
1818 endNode &&
1819 ( startNode.getPosition( dropNode ) & CKEDITOR.POSITION_PRECEDING ) &&
1820 ( endNode.getPosition( dropNode ) & CKEDITOR.POSITION_FOLLOWING );
1821
1822 // If the drop range happens to be inside drag range change it's position to the beginning of the drag range.
1823 if ( dropInsideDragRange ) {
1824 // We only change position of bookmark span that is connected with dropBookmark.
1825 // dropRange will be overwritten and set to the dropBookmark later.
1826 dropNode.insertBefore( startNode );
1827 }
1828
1829 // No we can safely delete content for the drag range...
1830 dragRange = editor.createRange();
1831 dragRange.moveToBookmark( dragBookmark );
1832 editable.extractHtmlFromRange( dragRange, 1 );
1833
1834 // ...and paste content into the drop position.
1835 dropRange = editor.createRange();
1836 dropRange.moveToBookmark( dropBookmark );
1837
1838 // We do not select drop range, because of may be in the place we can not set the selection
1839 // (e.g. between blocks, in case of block widget D&D). We put range to the paste event instead.
1840 firePasteEvents( editor, { dataTransfer: dataTransfer, method: 'drop', range: dropRange }, 1 );
1841
1842 editor.fire( 'unlockSnapshot' );
1843 },
1844
1845 /**
1846 * Gets the range from the `drop` event.
1847 *
1848 * @since 4.5
1849 * @param {Object} domEvent A native DOM drop event object.
1850 * @param {CKEDITOR.editor} editor The source editor instance.
1851 * @returns {CKEDITOR.dom.range} range at drop position.
1852 */
1853 getRangeAtDropPosition: function( dropEvt, editor ) {
1854 var $evt = dropEvt.data.$,
1855 x = $evt.clientX,
1856 y = $evt.clientY,
1857 $range,
1858 defaultRange = editor.getSelection( true ).getRanges()[ 0 ],
1859 range = editor.createRange();
1860
1861 // Make testing possible.
1862 if ( dropEvt.data.testRange )
1863 return dropEvt.data.testRange;
1864
1865 // Webkits.
1866 if ( document.caretRangeFromPoint ) {
1867 $range = editor.document.$.caretRangeFromPoint( x, y );
1868 range.setStart( CKEDITOR.dom.node( $range.startContainer ), $range.startOffset );
1869 range.collapse( true );
1870 }
1871 // FF.
1872 else if ( $evt.rangeParent ) {
1873 range.setStart( CKEDITOR.dom.node( $evt.rangeParent ), $evt.rangeOffset );
1874 range.collapse( true );
1875 }
1876 // IEs 9+.
1877 // We check if editable is focused to make sure that it's an internal DnD. External DnD must use the second
1878 // mechanism because of http://dev.ckeditor.com/ticket/13472#comment:6.
1879 else if ( CKEDITOR.env.ie && CKEDITOR.env.version > 8 && defaultRange && editor.editable().hasFocus ) {
1880 // On IE 9+ range by default is where we expected it.
1881 // defaultRange may be undefined if dragover was canceled (file drop).
1882 return defaultRange;
1883 }
1884 // IE 8 and all IEs if !defaultRange or external DnD.
1885 else if ( document.body.createTextRange ) {
1886 // To use this method we need a focus (which may be somewhere else in case of external drop).
1887 editor.focus();
1888
1889 $range = editor.document.getBody().$.createTextRange();
1890 try {
1891 var sucess = false;
1892
1893 // If user drop between text line IEs moveToPoint throws exception:
1894 //
1895 // Lorem ipsum pulvinar purus et euismod
1896 //
1897 // dolor sit amet,| consectetur adipiscing
1898 // *
1899 // vestibulum tincidunt augue eget tempus.
1900 //
1901 // * - drop position
1902 // | - expected cursor position
1903 //
1904 // So we try to call moveToPoint with +-1px up to +-20px above or
1905 // below original drop position to find nearest good drop position.
1906 for ( var i = 0; i < 20 && !sucess; i++ ) {
1907 if ( !sucess ) {
1908 try {
1909 $range.moveToPoint( x, y - i );
1910 sucess = true;
1911 } catch ( err ) {
1912 }
1913 }
1914 if ( !sucess ) {
1915 try {
1916 $range.moveToPoint( x, y + i );
1917 sucess = true;
1918 } catch ( err ) {
1919 }
1920 }
1921 }
1922
1923 if ( sucess ) {
1924 var id = 'cke-temp-' + ( new Date() ).getTime();
1925 $range.pasteHTML( '<span id="' + id + '">\u200b</span>' );
1926
1927 var span = editor.document.getById( id );
1928 range.moveToPosition( span, CKEDITOR.POSITION_BEFORE_START );
1929 span.remove();
1930 } else {
1931 // If the fist method does not succeed we might be next to
1932 // the short element (like header):
1933 //
1934 // Lorem ipsum pulvinar purus et euismod.
1935 //
1936 //
1937 // SOME HEADER| *
1938 //
1939 //
1940 // vestibulum tincidunt augue eget tempus.
1941 //
1942 // * - drop position
1943 // | - expected cursor position
1944 //
1945 // In such situation elementFromPoint returns proper element. Using getClientRect
1946 // it is possible to check if the cursor should be at the beginning or at the end
1947 // of paragraph.
1948 var $element = editor.document.$.elementFromPoint( x, y ),
1949 element = new CKEDITOR.dom.element( $element ),
1950 rect;
1951
1952 if ( !element.equals( editor.editable() ) && element.getName() != 'html' ) {
1953 rect = element.getClientRect();
1954
1955 if ( x < rect.left ) {
1956 range.setStartAt( element, CKEDITOR.POSITION_AFTER_START );
1957 range.collapse( true );
1958 } else {
1959 range.setStartAt( element, CKEDITOR.POSITION_BEFORE_END );
1960 range.collapse( true );
1961 }
1962 }
1963 // If drop happens on no element elementFromPoint returns html or body.
1964 //
1965 // * |Lorem ipsum pulvinar purus et euismod.
1966 //
1967 // vestibulum tincidunt augue eget tempus.
1968 //
1969 // * - drop position
1970 // | - expected cursor position
1971 //
1972 // In such case we can try to use default selection. If startContainer is not
1973 // 'editable' element it is probably proper selection.
1974 else if ( defaultRange && defaultRange.startContainer &&
1975 !defaultRange.startContainer.equals( editor.editable() ) ) {
1976 return defaultRange;
1977
1978 // Otherwise we can not find any drop position and we have to return null
1979 // and cancel drop event.
1980 } else {
1981 return null;
1982 }
1983
1984 }
1985 } catch ( err ) {
1986 return null;
1987 }
1988 } else {
1989 return null;
1990 }
1991
1992 return range;
1993 },
1994
1995 /**
1996 * This function tries to link the `evt.data.dataTransfer` property of the {@link CKEDITOR.editor#dragstart},
1997 * {@link CKEDITOR.editor#dragend} and {@link CKEDITOR.editor#drop} events to a single
1998 * {@link CKEDITOR.plugins.clipboard.dataTransfer} object.
1999 *
2000 * This method is automatically used by the core of the drag and drop functionality and
2001 * usually does not have to be called manually when using the drag and drop events.
2002 *
2003 * This method behaves differently depending on whether the drag and drop events were fired
2004 * artificially (to represent a non-native drag and drop) or whether they were caused by the native drag and drop.
2005 *
2006 * If the native event is not available, then it will create a new {@link CKEDITOR.plugins.clipboard.dataTransfer}
2007 * instance (if it does not exist already) and will link it to this and all following event objects until
2008 * the {@link #resetDragDataTransfer} method is called. It means that all three drag and drop events must be fired
2009 * in order to ensure that the data transfer is bound correctly.
2010 *
2011 * If the native event is available, then the {@link CKEDITOR.plugins.clipboard.dataTransfer} is identified
2012 * by its ID and a new instance is assigned to the `evt.data.dataTransfer` only if the ID changed or
2013 * the {@link #resetDragDataTransfer} method was called.
2014 *
2015 * @since 4.5
2016 * @param {CKEDITOR.dom.event} [evt] A drop event object.
2017 * @param {CKEDITOR.editor} [sourceEditor] The source editor instance.
2018 */
2019 initDragDataTransfer: function( evt, sourceEditor ) {
2020 // Create a new dataTransfer object based on the drop event.
2021 // If this event was used on dragstart to create dataTransfer
2022 // both dataTransfer objects will have the same id.
2023 var nativeDataTransfer = evt.data.$ ? evt.data.$.dataTransfer : null,
2024 dataTransfer = new this.dataTransfer( nativeDataTransfer, sourceEditor );
2025
2026 if ( !nativeDataTransfer ) {
2027 // No native event.
2028 if ( this.dragData ) {
2029 dataTransfer = this.dragData;
2030 } else {
2031 this.dragData = dataTransfer;
2032 }
2033 } else {
2034 // Native event. If there is the same id we will replace dataTransfer with the one
2035 // created on drag, because it contains drag editor, drag content and so on.
2036 // Otherwise (in case of drag from external source) we save new object to
2037 // the global clipboard.dragData.
2038 if ( this.dragData && dataTransfer.id == this.dragData.id ) {
2039 dataTransfer = this.dragData;
2040 } else {
2041 this.dragData = dataTransfer;
2042 }
2043 }
2044
2045 evt.data.dataTransfer = dataTransfer;
2046 },
2047
2048 /**
2049 * Removes the global {@link #dragData} so the next call to {@link #initDragDataTransfer}
2050 * always creates a new instance of {@link CKEDITOR.plugins.clipboard.dataTransfer}.
2051 *
2052 * @since 4.5
2053 */
2054 resetDragDataTransfer: function() {
2055 this.dragData = null;
2056 },
2057
2058 /**
2059 * Global object storing the data transfer of the current drag and drop operation.
2060 * Do not use it directly, use {@link #initDragDataTransfer} and {@link #resetDragDataTransfer}.
2061 *
2062 * Note: This object is global (meaning that it is not related to a single editor instance)
2063 * in order to handle drag and drop from one editor into another.
2064 *
2065 * @since 4.5
2066 * @private
2067 * @property {CKEDITOR.plugins.clipboard.dataTransfer} dragData
2068 */
2069
2070 /**
2071 * Range object to save the drag range and remove its content after the drop.
2072 *
2073 * @since 4.5
2074 * @private
2075 * @property {CKEDITOR.dom.range} dragRange
2076 */
2077
2078 /**
2079 * Initializes and links data transfer objects based on the paste event. If the data
2080 * transfer object was already initialized on this event, the function will
2081 * return that object. In IE it is not possible to link copy/cut and paste events
2082 * so the method always returns a new object. The same happens if there is no paste event
2083 * passed to the method.
2084 *
2085 * @since 4.5
2086 * @param {CKEDITOR.dom.event} [evt] A paste event object.
2087 * @param {CKEDITOR.editor} [sourceEditor] The source editor instance.
2088 * @returns {CKEDITOR.plugins.clipboard.dataTransfer} The data transfer object.
2089 */
2090 initPasteDataTransfer: function( evt, sourceEditor ) {
2091 if ( !this.isCustomCopyCutSupported ) {
2092 // Edge does not support custom copy/cut, but it have some useful data in the clipboardData (#13755).
2093 return new this.dataTransfer( ( CKEDITOR.env.edge && evt && evt.data.$ && evt.data.$.clipboardData ) || null, sourceEditor );
2094 } else if ( evt && evt.data && evt.data.$ ) {
2095 var dataTransfer = new this.dataTransfer( evt.data.$.clipboardData, sourceEditor );
2096
2097 if ( this.copyCutData && dataTransfer.id == this.copyCutData.id ) {
2098 dataTransfer = this.copyCutData;
2099 dataTransfer.$ = evt.data.$.clipboardData;
2100 } else {
2101 this.copyCutData = dataTransfer;
2102 }
2103
2104 return dataTransfer;
2105 } else {
2106 return new this.dataTransfer( null, sourceEditor );
2107 }
2108 },
2109
2110 /**
2111 * Prevents dropping on the specified element.
2112 *
2113 * @since 4.5
2114 * @param {CKEDITOR.dom.element} element The element on which dropping should be disabled.
2115 */
2116 preventDefaultDropOnElement: function( element ) {
2117 element && element.on( 'dragover', preventDefaultSetDropEffectToNone );
2118 }
2119 };
2120
2121 // Data type used to link drag and drop events.
2122 //
2123 // In IE URL data type is buggie and there is no way to mark drag & drop without
2124 // modifying text data (which would be displayed if user drop content to the textarea)
2125 // so we just read dragged text.
2126 //
2127 // In Chrome and Firefox we can use custom data types.
2128 var clipboardIdDataType = CKEDITOR.plugins.clipboard.isCustomDataTypesSupported ? 'cke/id' : 'Text';
2129 /**
2130 * Facade for the native `dataTransfer`/`clipboadData` object to hide all differences
2131 * between browsers.
2132 *
2133 * @since 4.5
2134 * @class CKEDITOR.plugins.clipboard.dataTransfer
2135 * @constructor Creates a class instance.
2136 * @param {Object} [nativeDataTransfer] A native data transfer object.
2137 * @param {CKEDITOR.editor} [editor] The source editor instance. If the editor is defined, dataValue will
2138 * be created based on the editor content and the type will be 'html'.
2139 */
2140 CKEDITOR.plugins.clipboard.dataTransfer = function( nativeDataTransfer, editor ) {
2141 if ( nativeDataTransfer ) {
2142 this.$ = nativeDataTransfer;
2143 }
2144
2145 this._ = {
2146 metaRegExp: /^<meta.*?>/i,
2147 bodyRegExp: /<body(?:[\s\S]*?)>([\s\S]*)<\/body>/i,
2148 fragmentRegExp: /<!--(?:Start|End)Fragment-->/g,
2149
2150 data: {},
2151 files: [],
2152
2153 normalizeType: function( type ) {
2154 type = type.toLowerCase();
2155
2156 if ( type == 'text' || type == 'text/plain' ) {
2157 return 'Text'; // IE support only Text and URL;
2158 } else if ( type == 'url' ) {
2159 return 'URL'; // IE support only Text and URL;
2160 } else {
2161 return type;
2162 }
2163 }
2164 };
2165
2166 // Check if ID is already created.
2167 this.id = this.getData( clipboardIdDataType );
2168
2169 // If there is no ID we need to create it. Different browsers needs different ID.
2170 if ( !this.id ) {
2171 if ( clipboardIdDataType == 'Text' ) {
2172 // For IE10+ only Text data type is supported and we have to compare dragged
2173 // and dropped text. If the ID is not set it means that empty string was dragged
2174 // (ex. image with no alt). We change null to empty string.
2175 this.id = '';
2176 } else {
2177 // String for custom data type.
2178 this.id = 'cke-' + CKEDITOR.tools.getUniqueId();
2179 }
2180 }
2181
2182 // In IE10+ we can not use any data type besides text, so we do not call setData.
2183 if ( clipboardIdDataType != 'Text' ) {
2184 // Try to set ID so it will be passed from the drag to the drop event.
2185 // On some browsers with some event it is not possible to setData so we
2186 // need to catch exceptions.
2187 try {
2188 this.$.setData( clipboardIdDataType, this.id );
2189 } catch ( err ) {}
2190 }
2191
2192 if ( editor ) {
2193 this.sourceEditor = editor;
2194
2195 this.setData( 'text/html', editor.getSelectedHtml( 1 ) );
2196
2197 // Without setData( 'text', ... ) on dragstart there is no drop event in Safari.
2198 // Also 'text' data is empty as drop to the textarea does not work if we do not put there text.
2199 if ( clipboardIdDataType != 'Text' && !this.getData( 'text/plain' ) ) {
2200 this.setData( 'text/plain', editor.getSelection().getSelectedText() );
2201 }
2202 }
2203
2204 /**
2205 * Data transfer ID used to bind all dataTransfer
2206 * objects based on the same event (e.g. in drag and drop events).
2207 *
2208 * @readonly
2209 * @property {String} id
2210 */
2211
2212 /**
2213 * A native DOM event object.
2214 *
2215 * @readonly
2216 * @property {Object} $
2217 */
2218
2219 /**
2220 * Source editor &mdash; the editor where the drag starts.
2221 * Might be undefined if the drag starts outside the editor (e.g. when dropping files to the editor).
2222 *
2223 * @readonly
2224 * @property {CKEDITOR.editor} sourceEditor
2225 */
2226
2227 /**
2228 * Private properties and methods.
2229 *
2230 * @private
2231 * @property {Object} _
2232 */
2233 };
2234
2235 /**
2236 * Data transfer operation (drag and drop or copy and paste) started and ended in the same
2237 * editor instance.
2238 *
2239 * @since 4.5
2240 * @readonly
2241 * @property {Number} [=1]
2242 * @member CKEDITOR
2243 */
2244 CKEDITOR.DATA_TRANSFER_INTERNAL = 1;
2245
2246 /**
2247 * Data transfer operation (drag and drop or copy and paste) started in one editor
2248 * instance and ended in another.
2249 *
2250 * @since 4.5
2251 * @readonly
2252 * @property {Number} [=2]
2253 * @member CKEDITOR
2254 */
2255 CKEDITOR.DATA_TRANSFER_CROSS_EDITORS = 2;
2256
2257 /**
2258 * Data transfer operation (drag and drop or copy and paste) started outside of the editor.
2259 * The source of the data may be a textarea, HTML, another application, etc.
2260 *
2261 * @since 4.5
2262 * @readonly
2263 * @property {Number} [=3]
2264 * @member CKEDITOR
2265 */
2266 CKEDITOR.DATA_TRANSFER_EXTERNAL = 3;
2267
2268 CKEDITOR.plugins.clipboard.dataTransfer.prototype = {
2269 /**
2270 * Facade for the native `getData` method.
2271 *
2272 * @param {String} type The type of data to retrieve.
2273 * @returns {String} type Stored data for the given type or an empty string if the data for that type does not exist.
2274 */
2275 getData: function( type ) {
2276 function isEmpty( data ) {
2277 return data === undefined || data === null || data === '';
2278 }
2279
2280 type = this._.normalizeType( type );
2281
2282 var data = this._.data[ type ],
2283 result;
2284
2285 if ( isEmpty( data ) ) {
2286 try {
2287 data = this.$.getData( type );
2288 } catch ( e ) {}
2289 }
2290
2291 if ( isEmpty( data ) ) {
2292 data = '';
2293 }
2294
2295 // Some browsers add <meta http-equiv="content-type" content="text/html; charset=utf-8"> at the begging of the HTML data
2296 // or surround it with <html><head>...</head><body>(some content)<!--StartFragment--> and <!--EndFragment-->(some content)</body></html>
2297 // This code removes meta tags and returns only the contents of the <body> element if found. Note that
2298 // some significant content may be placed outside Start/EndFragment comments so it's kept.
2299 //
2300 // See #13583 for more details.
2301 if ( type == 'text/html' ) {
2302 data = data.replace( this._.metaRegExp, '' );
2303
2304 // Keep only contents of the <body> element
2305 result = this._.bodyRegExp.exec( data );
2306 if ( result && result.length ) {
2307 data = result[ 1 ];
2308
2309 // Remove also comments.
2310 data = data.replace( this._.fragmentRegExp, '' );
2311 }
2312 }
2313 // Firefox on Linux put files paths as a text/plain data if there are files
2314 // in the dataTransfer object. We need to hide it, because files should be
2315 // handled on paste only if dataValue is empty.
2316 else if ( type == 'Text' && CKEDITOR.env.gecko && this.getFilesCount() &&
2317 data.substring( 0, 7 ) == 'file://' ) {
2318 data = '';
2319 }
2320
2321 return data;
2322 },
2323
2324 /**
2325 * Facade for the native `setData` method.
2326 *
2327 * @param {String} type The type of data to retrieve.
2328 * @param {String} value The data to add.
2329 */
2330 setData: function( type, value ) {
2331 type = this._.normalizeType( type );
2332
2333 this._.data[ type ] = value;
2334
2335 // There is "Unexpected call to method or property access." error if you try
2336 // to set data of unsupported type on IE.
2337 if ( !CKEDITOR.plugins.clipboard.isCustomDataTypesSupported && type != 'URL' && type != 'Text' ) {
2338 return;
2339 }
2340
2341 // If we use the text type to bind the ID, then if someone tries to set the text, we must also
2342 // update ID accordingly. #13468.
2343 if ( clipboardIdDataType == 'Text' && type == 'Text' ) {
2344 this.id = value;
2345 }
2346
2347 try {
2348 this.$.setData( type, value );
2349 } catch ( e ) {}
2350 },
2351
2352 /**
2353 * Gets the data transfer type.
2354 *
2355 * @param {CKEDITOR.editor} targetEditor The drop/paste target editor instance.
2356 * @returns {Number} Possible values: {@link CKEDITOR#DATA_TRANSFER_INTERNAL},
2357 * {@link CKEDITOR#DATA_TRANSFER_CROSS_EDITORS}, {@link CKEDITOR#DATA_TRANSFER_EXTERNAL}.
2358 */
2359 getTransferType: function( targetEditor ) {
2360 if ( !this.sourceEditor ) {
2361 return CKEDITOR.DATA_TRANSFER_EXTERNAL;
2362 } else if ( this.sourceEditor == targetEditor ) {
2363 return CKEDITOR.DATA_TRANSFER_INTERNAL;
2364 } else {
2365 return CKEDITOR.DATA_TRANSFER_CROSS_EDITORS;
2366 }
2367 },
2368
2369 /**
2370 * Copies the data from the native data transfer to a private cache.
2371 * This function is needed because the data from the native data transfer
2372 * is available only synchronously to the event listener. It is not possible
2373 * to get the data asynchronously, after a timeout, and the {@link CKEDITOR.editor#paste}
2374 * event is fired asynchronously &mdash; hence the need for caching the data.
2375 */
2376 cacheData: function() {
2377 if ( !this.$ ) {
2378 return;
2379 }
2380
2381 var that = this,
2382 i, file;
2383
2384 function getAndSetData( type ) {
2385 type = that._.normalizeType( type );
2386
2387 var data = that.getData( type );
2388 if ( data ) {
2389 that._.data[ type ] = data;
2390 }
2391 }
2392
2393 // Copy data.
2394 if ( CKEDITOR.plugins.clipboard.isCustomDataTypesSupported ) {
2395 if ( this.$.types ) {
2396 for ( i = 0; i < this.$.types.length; i++ ) {
2397 getAndSetData( this.$.types[ i ] );
2398 }
2399 }
2400 } else {
2401 getAndSetData( 'Text' );
2402 getAndSetData( 'URL' );
2403 }
2404
2405 // Copy files references.
2406 file = this._getImageFromClipboard();
2407 if ( ( this.$ && this.$.files ) || file ) {
2408 this._.files = [];
2409
2410 // Edge have empty files property with no length (#13755).
2411 if ( this.$.files && this.$.files.length ) {
2412 for ( i = 0; i < this.$.files.length; i++ ) {
2413 this._.files.push( this.$.files[ i ] );
2414 }
2415 }
2416
2417 // Don't include $.items if both $.files and $.items contains files, because,
2418 // according to spec and browsers behavior, they contain the same files.
2419 if ( this._.files.length === 0 && file ) {
2420 this._.files.push( file );
2421 }
2422 }
2423 },
2424
2425 /**
2426 * Gets the number of files in the dataTransfer object.
2427 *
2428 * @returns {Number} The number of files.
2429 */
2430 getFilesCount: function() {
2431 if ( this._.files.length ) {
2432 return this._.files.length;
2433 }
2434
2435 if ( this.$ && this.$.files && this.$.files.length ) {
2436 return this.$.files.length;
2437 }
2438
2439 return this._getImageFromClipboard() ? 1 : 0;
2440 },
2441
2442 /**
2443 * Gets the file at the index given.
2444 *
2445 * @param {Number} i Index.
2446 * @returns {File} File instance.
2447 */
2448 getFile: function( i ) {
2449 if ( this._.files.length ) {
2450 return this._.files[ i ];
2451 }
2452
2453 if ( this.$ && this.$.files && this.$.files.length ) {
2454 return this.$.files[ i ];
2455 }
2456
2457 // File or null if the file was not found.
2458 return i === 0 ? this._getImageFromClipboard() : undefined;
2459 },
2460
2461 /**
2462 * Checks if the data transfer contains any data.
2463 *
2464 * @returns {Boolean} `true` if the object contains no data.
2465 */
2466 isEmpty: function() {
2467 var typesToCheck = {},
2468 type;
2469
2470 // If dataTransfer contains files it is not empty.
2471 if ( this.getFilesCount() ) {
2472 return false;
2473 }
2474
2475 // Add custom types.
2476 for ( type in this._.data ) {
2477 typesToCheck[ type ] = 1;
2478 }
2479
2480 // Add native types.
2481 if ( this.$ ) {
2482 if ( CKEDITOR.plugins.clipboard.isCustomDataTypesSupported ) {
2483 if ( this.$.types ) {
2484 for ( var i = 0; i < this.$.types.length; i++ ) {
2485 typesToCheck[ this.$.types[ i ] ] = 1;
2486 }
2487 }
2488 } else {
2489 typesToCheck.Text = 1;
2490 typesToCheck.URL = 1;
2491 }
2492 }
2493
2494 // Remove ID.
2495 if ( clipboardIdDataType != 'Text' ) {
2496 typesToCheck[ clipboardIdDataType ] = 0;
2497 }
2498
2499 for ( type in typesToCheck ) {
2500 if ( typesToCheck[ type ] && this.getData( type ) !== '' ) {
2501 return false;
2502 }
2503 }
2504
2505 return true;
2506 },
2507
2508 /**
2509 * When the content of the clipboard is pasted in Chrome, the clipboard data object has an empty `files` property,
2510 * but it is possible to get the file as `items[0].getAsFile();` (#12961).
2511 *
2512 * @private
2513 * @returns {File} File instance or `null` if not found.
2514 */
2515 _getImageFromClipboard: function() {
2516 var file;
2517
2518 if ( this.$ && this.$.items && this.$.items[ 0 ] ) {
2519 try {
2520 file = this.$.items[ 0 ].getAsFile();
2521 // Duck typing
2522 if ( file && file.type ) {
2523 return file;
2524 }
2525 } catch ( err ) {
2526 // noop
2527 }
2528 }
2529
2530 return undefined;
2531 }
2532 };
2533} )();
2534
2535/**
2536 * The default content type that is used when pasted data cannot be clearly recognized as HTML or text.
2537 *
2538 * For example: `'foo'` may come from a plain text editor or a website. It is not possible to recognize the content
2539 * type in this case, so the default type will be used. At the same time it is clear that `'<b>example</b> text'` is
2540 * HTML and its origin is a web page, email or another rich text editor.
2541 *
2542 * **Note:** If content type is text, then styles of the paste context are preserved.
2543 *
2544 * CKEDITOR.config.clipboard_defaultContentType = 'text';
2545 *
2546 * See also the {@link CKEDITOR.editor#paste} event and read more about the integration with clipboard
2547 * in the [Clipboard Deep Dive guide](#!/guide/dev_clipboard).
2548 *
2549 * @since 4.0
2550 * @cfg {'html'/'text'} [clipboard_defaultContentType='html']
2551 * @member CKEDITOR.config
2552 */
2553
2554/**
2555 * Fired after the user initiated a paste action, but before the data is inserted into the editor.
2556 * The listeners to this event are able to process the content before its insertion into the document.
2557 *
2558 * Read more about the integration with clipboard in the [Clipboard Deep Dive guide](#!/guide/dev_clipboard).
2559 *
2560 * See also:
2561 *
2562 * * the {@link CKEDITOR.config#pasteFilter} option,
2563 * * the {@link CKEDITOR.editor#drop} event,
2564 * * the {@link CKEDITOR.plugins.clipboard.dataTransfer} class.
2565 *
2566 * @since 3.1
2567 * @event paste
2568 * @member CKEDITOR.editor
2569 * @param {CKEDITOR.editor} editor This editor instance.
2570 * @param data
2571 * @param {String} data.type The type of data in `data.dataValue`. Usually `'html'` or `'text'`, but for listeners
2572 * with a priority smaller than `6` it may also be `'auto'` which means that the content type has not been recognised yet
2573 * (this will be done by the content type sniffer that listens with priority `6`).
2574 * @param {String} data.dataValue HTML to be pasted.
2575 * @param {String} data.method Indicates the data transfer method. It could be drag and drop or copy and paste.
2576 * Possible values: `'drop'`, `'paste'`. Introduced in CKEditor 4.5.
2577 * @param {CKEDITOR.plugins.clipboard.dataTransfer} data.dataTransfer Facade for the native dataTransfer object
2578 * which provides access to various data types and files, and passes some data between linked events
2579 * (like drag and drop). Introduced in CKEditor 4.5.
2580 * @param {Boolean} [data.dontFilter=false] Whether the {@link CKEDITOR.editor#pasteFilter paste filter} should not
2581 * be applied to data. This option has no effect when `data.type` equals `'text'` which means that for instance
2582 * {@link CKEDITOR.config#forcePasteAsPlainText} has a higher priority. Introduced in CKEditor 4.5.
2583 */
2584
2585/**
2586 * Fired before the {@link #paste} event. Allows to preset data type.
2587 *
2588 * **Note:** This event is deprecated. Add a `0` priority listener for the
2589 * {@link #paste} event instead.
2590 *
2591 * @deprecated
2592 * @event beforePaste
2593 * @member CKEDITOR.editor
2594 */
2595
2596 /**
2597 * Fired after the {@link #paste} event if content was modified. Note that if the paste
2598 * event does not insert any data, the `afterPaste` event will not be fired.
2599 *
2600 * @event afterPaste
2601 * @member CKEDITOR.editor
2602 */
2603
2604/**
2605 * Internal event to open the Paste dialog window.
2606 *
2607 * @private
2608 * @event pasteDialog
2609 * @member CKEDITOR.editor
2610 * @param {CKEDITOR.editor} editor This editor instance.
2611 * @param {Function} [data] Callback that will be passed to {@link CKEDITOR.editor#openDialog}.
2612 */
2613
2614/**
2615 * Facade for the native `drop` event. Fired when the native `drop` event occurs.
2616 *
2617 * **Note:** To manipulate dropped data, use the {@link CKEDITOR.editor#paste} event.
2618 * Use the `drop` event only to control drag and drop operations (e.g. to prevent the ability to drop some content).
2619 *
2620 * Read more about integration with drag and drop in the [Clipboard Deep Dive guide](#!/guide/dev_clipboard).
2621 *
2622 * See also:
2623 *
2624 * * The {@link CKEDITOR.editor#paste} event,
2625 * * The {@link CKEDITOR.editor#dragstart} and {@link CKEDITOR.editor#dragend} events,
2626 * * The {@link CKEDITOR.plugins.clipboard.dataTransfer} class.
2627 *
2628 * @since 4.5
2629 * @event drop
2630 * @member CKEDITOR.editor
2631 * @param {CKEDITOR.editor} editor This editor instance.
2632 * @param data
2633 * @param {Object} data.$ Native drop event.
2634 * @param {CKEDITOR.dom.node} data.target Drop target.
2635 * @param {CKEDITOR.plugins.clipboard.dataTransfer} data.dataTransfer DataTransfer facade.
2636 * @param {CKEDITOR.dom.range} data.dragRange Drag range, lets you manipulate the drag range.
2637 * Note that dragged HTML is saved as `text/html` data on `dragstart` so if you change the drag range
2638 * on drop, dropped HTML will not change. You need to change it manually using
2639 * {@link CKEDITOR.plugins.clipboard.dataTransfer#setData dataTransfer.setData}.
2640 * @param {CKEDITOR.dom.range} data.dropRange Drop range, lets you manipulate the drop range.
2641 */
2642
2643/**
2644 * Facade for the native `dragstart` event. Fired when the native `dragstart` event occurs.
2645 *
2646 * This event can be canceled in order to block the drag start operation. It can also be fired to mimic the start of the drag and drop
2647 * operation. For instance, the `widget` plugin uses this option to integrate its custom block widget drag and drop with
2648 * the entire system.
2649 *
2650 * Read more about integration with drag and drop in the [Clipboard Deep Dive guide](#!/guide/dev_clipboard).
2651 *
2652 * See also:
2653 *
2654 * * The {@link CKEDITOR.editor#paste} event,
2655 * * The {@link CKEDITOR.editor#drop} and {@link CKEDITOR.editor#dragend} events,
2656 * * The {@link CKEDITOR.plugins.clipboard.dataTransfer} class.
2657 *
2658 * @since 4.5
2659 * @event dragstart
2660 * @member CKEDITOR.editor
2661 * @param {CKEDITOR.editor} editor This editor instance.
2662 * @param data
2663 * @param {Object} data.$ Native dragstart event.
2664 * @param {CKEDITOR.dom.node} data.target Drag target.
2665 * @param {CKEDITOR.plugins.clipboard.dataTransfer} data.dataTransfer DataTransfer facade.
2666 */
2667
2668/**
2669 * Facade for the native `dragend` event. Fired when the native `dragend` event occurs.
2670 *
2671 * Read more about integration with drag and drop in the [Clipboard Deep Dive guide](#!/guide/dev_clipboard).
2672 *
2673 * See also:
2674 *
2675 * * The {@link CKEDITOR.editor#paste} event,
2676 * * The {@link CKEDITOR.editor#drop} and {@link CKEDITOR.editor#dragend} events,
2677 * * The {@link CKEDITOR.plugins.clipboard.dataTransfer} class.
2678 *
2679 * @since 4.5
2680 * @event dragend
2681 * @member CKEDITOR.editor
2682 * @param {CKEDITOR.editor} editor This editor instance.
2683 * @param data
2684 * @param {Object} data.$ Native dragend event.
2685 * @param {CKEDITOR.dom.node} data.target Drag target.
2686 * @param {CKEDITOR.plugins.clipboard.dataTransfer} data.dataTransfer DataTransfer facade.
2687 */
2688
2689/**
2690 * Defines a filter which is applied to external data pasted or dropped into the editor. Possible values are:
2691 *
2692 * * `'plain-text'` &ndash; Content will be pasted as a plain text.
2693 * * `'semantic-content'` &ndash; Known tags (except `div`, `span`) with all attributes (except
2694 * `style` and `class`) will be kept.
2695 * * `'h1 h2 p div'` &ndash; Custom rules compatible with {@link CKEDITOR.filter}.
2696 * * `null` &ndash; Content will not be filtered by the paste filter (but it still may be filtered
2697 * by [Advanced Content Filter](#!/guide/dev_advanced_content_filter)). This value can be used to
2698 * disable the paste filter in Chrome and Safari, where this option defaults to `'semantic-content'`.
2699 *
2700 * Example:
2701 *
2702 * config.pasteFilter = 'plain-text';
2703 *
2704 * Custom setting:
2705 *
2706 * config.pasteFilter = 'h1 h2 p ul ol li; img[!src, alt]; a[!href]';
2707 *
2708 * Based on this configuration option, a proper {@link CKEDITOR.filter} instance will be defined and assigned to the editor
2709 * as a {@link CKEDITOR.editor#pasteFilter}. You can tweak the paste filter settings on the fly on this object
2710 * as well as delete or replace it.
2711 *
2712 * var editor = CKEDITOR.replace( 'editor', {
2713 * pasteFilter: 'semantic-content'
2714 * } );
2715 *
2716 * editor.on( 'instanceReady', function() {
2717 * // The result of this will be that all semantic content will be preserved
2718 * // except tables.
2719 * editor.pasteFilter.disallow( 'table' );
2720 * } );
2721 *
2722 * Note that the paste filter is applied only to **external** data. There are three data sources:
2723 *
2724 * * copied and pasted in the same editor (internal),
2725 * * copied from one editor and pasted into another (cross-editor),
2726 * * coming from all other sources like websites, MS Word, etc. (external).
2727 *
2728 * If {@link CKEDITOR.config#allowedContent Advanced Content Filter} is not disabled, then
2729 * it will also be applied to pasted and dropped data. The paste filter job is to "normalize"
2730 * external data which often needs to be handled differently than content produced by the editor.
2731 *
2732 * This setting defaults to `'semantic-content'` in Chrome, Opera and Safari (all Blink and Webkit based browsers)
2733 * due to messy HTML which these browsers keep in the clipboard. In other browsers it defaults to `null`.
2734 *
2735 * @since 4.5
2736 * @cfg {String} [pasteFilter='semantic-content' in Chrome and Safari and `null` in other browsers]
2737 * @member CKEDITOR.config
2738 */
2739
2740/**
2741 * {@link CKEDITOR.filter Content filter} which is used when external data is pasted or dropped into the editor
2742 * or a forced paste as plain text occurs.
2743 *
2744 * This object might be used on the fly to define rules for pasted external content.
2745 * This object is available and used if the {@link CKEDITOR.plugins.clipboard clipboard} plugin is enabled and
2746 * {@link CKEDITOR.config#pasteFilter} or {@link CKEDITOR.config#forcePasteAsPlainText} was defined.
2747 *
2748 * To enable the filter:
2749 *
2750 * var editor = CKEDITOR.replace( 'editor', {
2751 * pasteFilter: 'plain-text'
2752 * } );
2753 *
2754 * You can also modify the filter on the fly later on:
2755 *
2756 * editor.pasteFilter = new CKEDITOR.filter( 'p h1 h2; a[!href]' );
2757 *
2758 * Note that the paste filter is only applied to **external** data. There are three data sources:
2759 *
2760 * * copied and pasted in the same editor (internal),
2761 * * copied from one editor and pasted into another (cross-editor),
2762 * * coming from all other sources like websites, MS Word, etc. (external).
2763 *
2764 * If {@link CKEDITOR.config#allowedContent Advanced Content Filter} is not disabled, then
2765 * it will also be applied to pasted and dropped data. The paste filter job is to "normalize"
2766 * external data which often needs to be handled differently than content produced by the editor.
2767 *
2768 * @since 4.5
2769 * @readonly
2770 * @property {CKEDITOR.filter} [pasteFilter]
2771 * @member CKEDITOR.editor
2772 */
diff --git a/sources/plugins/contextmenu/lang/af.js b/sources/plugins/contextmenu/lang/af.js
new file mode 100644
index 0000000..76b5b96
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/af.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'af', {
6 options: 'Konteks Spyskaart-opsies'
7} );
diff --git a/sources/plugins/contextmenu/lang/ar.js b/sources/plugins/contextmenu/lang/ar.js
new file mode 100644
index 0000000..c81b063
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ar.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ar', {
6 options: 'خصائص قائمة السياق'
7} );
diff --git a/sources/plugins/contextmenu/lang/az.js b/sources/plugins/contextmenu/lang/az.js
new file mode 100644
index 0000000..651f2f8
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/az.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'az', {
6 options: 'Əlavə əməliyyatlar'
7} );
diff --git a/sources/plugins/contextmenu/lang/bg.js b/sources/plugins/contextmenu/lang/bg.js
new file mode 100644
index 0000000..6bb7a40
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/bg.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'bg', {
6 options: 'Опции на контекстното меню'
7} );
diff --git a/sources/plugins/contextmenu/lang/bn.js b/sources/plugins/contextmenu/lang/bn.js
new file mode 100644
index 0000000..fe93ec8
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/bn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'bn', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/bs.js b/sources/plugins/contextmenu/lang/bs.js
new file mode 100644
index 0000000..9354351
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/bs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'bs', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/ca.js b/sources/plugins/contextmenu/lang/ca.js
new file mode 100644
index 0000000..91c7ec8
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ca', {
6 options: 'Opcions del menú contextual'
7} );
diff --git a/sources/plugins/contextmenu/lang/cs.js b/sources/plugins/contextmenu/lang/cs.js
new file mode 100644
index 0000000..e53a0f5
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/cs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'cs', {
6 options: 'Nastavení kontextové nabídky'
7} );
diff --git a/sources/plugins/contextmenu/lang/cy.js b/sources/plugins/contextmenu/lang/cy.js
new file mode 100644
index 0000000..1816b84
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/cy.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'cy', {
6 options: 'Opsiynau Dewislen Cyd-destun'
7} );
diff --git a/sources/plugins/contextmenu/lang/da.js b/sources/plugins/contextmenu/lang/da.js
new file mode 100644
index 0000000..10043a5
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/da.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'da', {
6 options: 'Muligheder for hjælpemenu'
7} );
diff --git a/sources/plugins/contextmenu/lang/de-ch.js b/sources/plugins/contextmenu/lang/de-ch.js
new file mode 100644
index 0000000..216cd18
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/de-ch.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'de-ch', {
6 options: 'Kontextmenüoptionen'
7} );
diff --git a/sources/plugins/contextmenu/lang/de.js b/sources/plugins/contextmenu/lang/de.js
new file mode 100644
index 0000000..aa0c098
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/de.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'de', {
6 options: 'Kontextmenüoptionen'
7} );
diff --git a/sources/plugins/contextmenu/lang/el.js b/sources/plugins/contextmenu/lang/el.js
new file mode 100644
index 0000000..bdad720
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/el.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'el', {
6 options: 'Επιλογές Αναδυόμενου Μενού'
7} );
diff --git a/sources/plugins/contextmenu/lang/en-au.js b/sources/plugins/contextmenu/lang/en-au.js
new file mode 100644
index 0000000..cd6b202
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/en-au.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'en-au', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/en-ca.js b/sources/plugins/contextmenu/lang/en-ca.js
new file mode 100644
index 0000000..25950c9
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/en-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'en-ca', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/en-gb.js b/sources/plugins/contextmenu/lang/en-gb.js
new file mode 100644
index 0000000..62f08d5
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/en-gb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'en-gb', {
6 options: 'Context Menu Options'
7} );
diff --git a/sources/plugins/contextmenu/lang/en.js b/sources/plugins/contextmenu/lang/en.js
new file mode 100644
index 0000000..10b5f47
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/en.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'en', {
6 options: 'Context Menu Options'
7} );
diff --git a/sources/plugins/contextmenu/lang/eo.js b/sources/plugins/contextmenu/lang/eo.js
new file mode 100644
index 0000000..6a9760c
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/eo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'eo', {
6 options: 'Opcioj de Kunteksta Menuo'
7} );
diff --git a/sources/plugins/contextmenu/lang/es.js b/sources/plugins/contextmenu/lang/es.js
new file mode 100644
index 0000000..1e8e06d
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/es.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'es', {
6 options: 'Opciones del menú contextual'
7} );
diff --git a/sources/plugins/contextmenu/lang/et.js b/sources/plugins/contextmenu/lang/et.js
new file mode 100644
index 0000000..d7ece9a
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/et.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'et', {
6 options: 'Kontekstimenüü valikud'
7} );
diff --git a/sources/plugins/contextmenu/lang/eu.js b/sources/plugins/contextmenu/lang/eu.js
new file mode 100644
index 0000000..32018e0
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/eu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'eu', {
6 options: 'Testuinguru-menuaren aukerak'
7} );
diff --git a/sources/plugins/contextmenu/lang/fa.js b/sources/plugins/contextmenu/lang/fa.js
new file mode 100644
index 0000000..233d30d
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/fa.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'fa', {
6 options: 'گزینه​های منوی زمینه'
7} );
diff --git a/sources/plugins/contextmenu/lang/fi.js b/sources/plugins/contextmenu/lang/fi.js
new file mode 100644
index 0000000..5c11832
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/fi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'fi', {
6 options: 'Pikavalikon ominaisuudet'
7} );
diff --git a/sources/plugins/contextmenu/lang/fo.js b/sources/plugins/contextmenu/lang/fo.js
new file mode 100644
index 0000000..6069a48
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/fo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'fo', {
6 options: 'Context Menu Options'
7} );
diff --git a/sources/plugins/contextmenu/lang/fr-ca.js b/sources/plugins/contextmenu/lang/fr-ca.js
new file mode 100644
index 0000000..d7aca5c
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/fr-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'fr-ca', {
6 options: 'Options du menu contextuel'
7} );
diff --git a/sources/plugins/contextmenu/lang/fr.js b/sources/plugins/contextmenu/lang/fr.js
new file mode 100644
index 0000000..7af3f33
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/fr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'fr', {
6 options: 'Options du menu contextuel'
7} );
diff --git a/sources/plugins/contextmenu/lang/gl.js b/sources/plugins/contextmenu/lang/gl.js
new file mode 100644
index 0000000..de69eae
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/gl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'gl', {
6 options: 'Opcións do menú contextual'
7} );
diff --git a/sources/plugins/contextmenu/lang/gu.js b/sources/plugins/contextmenu/lang/gu.js
new file mode 100644
index 0000000..d9a83da
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/gu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'gu', {
6 options: 'કોન્તેક્ષ્ત્ મેનુના વિકલ્પો'
7} );
diff --git a/sources/plugins/contextmenu/lang/he.js b/sources/plugins/contextmenu/lang/he.js
new file mode 100644
index 0000000..a276534
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/he.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'he', {
6 options: 'אפשרויות תפריט ההקשר'
7} );
diff --git a/sources/plugins/contextmenu/lang/hi.js b/sources/plugins/contextmenu/lang/hi.js
new file mode 100644
index 0000000..a3f501d
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/hi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'hi', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/hr.js b/sources/plugins/contextmenu/lang/hr.js
new file mode 100644
index 0000000..149c1eb
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/hr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'hr', {
6 options: 'Opcije izbornika'
7} );
diff --git a/sources/plugins/contextmenu/lang/hu.js b/sources/plugins/contextmenu/lang/hu.js
new file mode 100644
index 0000000..60bb66c
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/hu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'hu', {
6 options: 'Helyi menü opciók'
7} );
diff --git a/sources/plugins/contextmenu/lang/id.js b/sources/plugins/contextmenu/lang/id.js
new file mode 100644
index 0000000..8d19e50
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/id.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'id', {
6 options: 'Opsi Konteks Pilihan'
7} );
diff --git a/sources/plugins/contextmenu/lang/is.js b/sources/plugins/contextmenu/lang/is.js
new file mode 100644
index 0000000..4404c99
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/is.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'is', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/it.js b/sources/plugins/contextmenu/lang/it.js
new file mode 100644
index 0000000..0453e18
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/it.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'it', {
6 options: 'Opzioni del menù contestuale'
7} );
diff --git a/sources/plugins/contextmenu/lang/ja.js b/sources/plugins/contextmenu/lang/ja.js
new file mode 100644
index 0000000..5887847
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ja.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ja', {
6 options: 'コンテキストメニューオプション'
7} );
diff --git a/sources/plugins/contextmenu/lang/ka.js b/sources/plugins/contextmenu/lang/ka.js
new file mode 100644
index 0000000..f279b0a
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ka.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ka', {
6 options: 'კონტექსტური მენიუს პარამეტრები'
7} );
diff --git a/sources/plugins/contextmenu/lang/km.js b/sources/plugins/contextmenu/lang/km.js
new file mode 100644
index 0000000..9f5d965
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/km.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'km', {
6 options: 'ជម្រើស​ម៉ឺនុយ​បរិបទ'
7} );
diff --git a/sources/plugins/contextmenu/lang/ko.js b/sources/plugins/contextmenu/lang/ko.js
new file mode 100644
index 0000000..45273b5
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ko.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ko', {
6 options: '컨텍스트 메뉴 옵션'
7} );
diff --git a/sources/plugins/contextmenu/lang/ku.js b/sources/plugins/contextmenu/lang/ku.js
new file mode 100644
index 0000000..c183cb2
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ku.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ku', {
6 options: 'هەڵبژاردەی لیستەی کلیکی دەستی ڕاست'
7} );
diff --git a/sources/plugins/contextmenu/lang/lt.js b/sources/plugins/contextmenu/lang/lt.js
new file mode 100644
index 0000000..e16597a
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/lt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'lt', {
6 options: 'Kontekstinio meniu parametrai'
7} );
diff --git a/sources/plugins/contextmenu/lang/lv.js b/sources/plugins/contextmenu/lang/lv.js
new file mode 100644
index 0000000..b14f0eb
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/lv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'lv', {
6 options: 'Uznirstošās izvēlnes uzstādījumi'
7} );
diff --git a/sources/plugins/contextmenu/lang/mk.js b/sources/plugins/contextmenu/lang/mk.js
new file mode 100644
index 0000000..1d7c4c7
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/mk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'mk', {
6 options: 'Контекст-мени опции'
7} );
diff --git a/sources/plugins/contextmenu/lang/mn.js b/sources/plugins/contextmenu/lang/mn.js
new file mode 100644
index 0000000..5076f18
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/mn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'mn', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/ms.js b/sources/plugins/contextmenu/lang/ms.js
new file mode 100644
index 0000000..019ba76
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ms.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ms', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/nb.js b/sources/plugins/contextmenu/lang/nb.js
new file mode 100644
index 0000000..c7c41b0
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/nb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'nb', {
6 options: 'Alternativer for høyreklikkmeny'
7} );
diff --git a/sources/plugins/contextmenu/lang/nl.js b/sources/plugins/contextmenu/lang/nl.js
new file mode 100644
index 0000000..0ceb7cb
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/nl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'nl', {
6 options: 'Contextmenu opties'
7} );
diff --git a/sources/plugins/contextmenu/lang/no.js b/sources/plugins/contextmenu/lang/no.js
new file mode 100644
index 0000000..ee283cf
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/no.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'no', {
6 options: 'Alternativer for høyreklikkmeny'
7} );
diff --git a/sources/plugins/contextmenu/lang/oc.js b/sources/plugins/contextmenu/lang/oc.js
new file mode 100644
index 0000000..8fab98f
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/oc.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'oc', {
6 options: 'Opcions del menú contextual'
7} );
diff --git a/sources/plugins/contextmenu/lang/pl.js b/sources/plugins/contextmenu/lang/pl.js
new file mode 100644
index 0000000..99ef5d9
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/pl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'pl', {
6 options: 'Opcje menu kontekstowego'
7} );
diff --git a/sources/plugins/contextmenu/lang/pt-br.js b/sources/plugins/contextmenu/lang/pt-br.js
new file mode 100644
index 0000000..ec91513
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/pt-br.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'pt-br', {
6 options: 'Opções Menu de Contexto'
7} );
diff --git a/sources/plugins/contextmenu/lang/pt.js b/sources/plugins/contextmenu/lang/pt.js
new file mode 100644
index 0000000..c2c969d
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/pt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'pt', {
6 options: 'Menu de opções de contexto'
7} );
diff --git a/sources/plugins/contextmenu/lang/ro.js b/sources/plugins/contextmenu/lang/ro.js
new file mode 100644
index 0000000..928c4b3
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ro.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ro', {
6 options: 'Opțiuni Meniu Contextual'
7} );
diff --git a/sources/plugins/contextmenu/lang/ru.js b/sources/plugins/contextmenu/lang/ru.js
new file mode 100644
index 0000000..f671b6a
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ru.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ru', {
6 options: 'Параметры контекстного меню'
7} );
diff --git a/sources/plugins/contextmenu/lang/si.js b/sources/plugins/contextmenu/lang/si.js
new file mode 100644
index 0000000..ec603a3
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/si.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'si', {
6 options: 'අනතර්ග ලේඛණ විකල්ප'
7} );
diff --git a/sources/plugins/contextmenu/lang/sk.js b/sources/plugins/contextmenu/lang/sk.js
new file mode 100644
index 0000000..fda2b3d
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/sk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'sk', {
6 options: 'Možnosti kontextového menu'
7} );
diff --git a/sources/plugins/contextmenu/lang/sl.js b/sources/plugins/contextmenu/lang/sl.js
new file mode 100644
index 0000000..9c7fc29
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/sl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'sl', {
6 options: 'Možnosti kontekstnega menija'
7} );
diff --git a/sources/plugins/contextmenu/lang/sq.js b/sources/plugins/contextmenu/lang/sq.js
new file mode 100644
index 0000000..698ca2d
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/sq.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'sq', {
6 options: 'Mundësitë e Menysë së Kontekstit'
7} );
diff --git a/sources/plugins/contextmenu/lang/sr-latn.js b/sources/plugins/contextmenu/lang/sr-latn.js
new file mode 100644
index 0000000..d550e84
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/sr-latn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'sr-latn', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/sr.js b/sources/plugins/contextmenu/lang/sr.js
new file mode 100644
index 0000000..2f7ba14
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/sr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'sr', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/sv.js b/sources/plugins/contextmenu/lang/sv.js
new file mode 100644
index 0000000..a3b043f
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/sv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'sv', {
6 options: 'Context Menu Options'
7} );
diff --git a/sources/plugins/contextmenu/lang/th.js b/sources/plugins/contextmenu/lang/th.js
new file mode 100644
index 0000000..ce77065
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/th.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'th', {
6 options: 'Context Menu Options' // MISSING
7} );
diff --git a/sources/plugins/contextmenu/lang/tr.js b/sources/plugins/contextmenu/lang/tr.js
new file mode 100644
index 0000000..4d5a550
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/tr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'tr', {
6 options: 'İçerik Menüsü Seçenekleri'
7} );
diff --git a/sources/plugins/contextmenu/lang/tt.js b/sources/plugins/contextmenu/lang/tt.js
new file mode 100644
index 0000000..0531370
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/tt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'tt', {
6 options: 'Контекст меню үзлекләре'
7} );
diff --git a/sources/plugins/contextmenu/lang/ug.js b/sources/plugins/contextmenu/lang/ug.js
new file mode 100644
index 0000000..95a9d0a
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/ug.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'ug', {
6 options: 'قىسقا يول تىزىملىك تاللانمىسى'
7} );
diff --git a/sources/plugins/contextmenu/lang/uk.js b/sources/plugins/contextmenu/lang/uk.js
new file mode 100644
index 0000000..0a4ffb9
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/uk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'uk', {
6 options: 'Опції контекстного меню'
7} );
diff --git a/sources/plugins/contextmenu/lang/vi.js b/sources/plugins/contextmenu/lang/vi.js
new file mode 100644
index 0000000..42c39b0
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/vi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'vi', {
6 options: 'Tùy chọn menu bổ xung'
7} );
diff --git a/sources/plugins/contextmenu/lang/zh-cn.js b/sources/plugins/contextmenu/lang/zh-cn.js
new file mode 100644
index 0000000..56879ee
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/zh-cn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'zh-cn', {
6 options: '快捷菜单选项'
7} );
diff --git a/sources/plugins/contextmenu/lang/zh.js b/sources/plugins/contextmenu/lang/zh.js
new file mode 100644
index 0000000..c8d8b93
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/zh.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'contextmenu', 'zh', {
6 options: '內容功能表選項'
7} );
diff --git a/sources/plugins/contextmenu/plugin.js b/sources/plugins/contextmenu/plugin.js
new file mode 100644
index 0000000..6cd3935
--- /dev/null
+++ b/sources/plugins/contextmenu/plugin.js
@@ -0,0 +1,159 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'contextmenu', {
7 requires: 'menu',
8
9 // jscs:disable maximumLineLength
10 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
11 // jscs:enable maximumLineLength
12
13 // Make sure the base class (CKEDITOR.menu) is loaded before it (#3318).
14 onLoad: function() {
15 /**
16 * Class replacing the non-configurable native context menu with a configurable CKEditor's equivalent.
17 *
18 * @class
19 * @extends CKEDITOR.menu
20 */
21 CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass( {
22 base: CKEDITOR.menu,
23
24 /**
25 * Creates the CKEDITOR.plugins.contextMenu class instance.
26 *
27 * @constructor
28 * @param {CKEDITOR.editor} editor
29 */
30 $: function( editor ) {
31 this.base.call( this, editor, {
32 panel: {
33 className: 'cke_menu_panel',
34 attributes: {
35 'aria-label': editor.lang.contextmenu.options
36 }
37 }
38 } );
39 },
40
41 proto: {
42 /**
43 * Starts watching on native context menu triggers (<kbd>Option</kbd> key, right click) on the given element.
44 *
45 * @param {CKEDITOR.dom.element} element
46 * @param {Boolean} [nativeContextMenuOnCtrl] Whether to open native context menu if the
47 * <kbd>Ctrl</kbd> key is held on opening the context menu. See {@link CKEDITOR.config#browserContextMenuOnCtrl}.
48 */
49 addTarget: function( element, nativeContextMenuOnCtrl ) {
50 element.on( 'contextmenu', function( event ) {
51 var domEvent = event.data,
52 isCtrlKeyDown =
53 // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event,
54 // which make this property unreliable. (#4826)
55 ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) );
56
57 if ( nativeContextMenuOnCtrl && isCtrlKeyDown )
58 return;
59
60 // Cancel the browser context menu.
61 domEvent.preventDefault();
62
63 // Fix selection when non-editable element in Webkit/Blink (Mac) (#11306).
64 if ( CKEDITOR.env.mac && CKEDITOR.env.webkit ) {
65 var editor = this.editor,
66 contentEditableParent = new CKEDITOR.dom.elementPath( domEvent.getTarget(), editor.editable() ).contains( function( el ) {
67 // Return when non-editable or nested editable element is found.
68 return el.hasAttribute( 'contenteditable' );
69 }, true ); // Exclude editor's editable.
70
71 // Fake selection for non-editables only (to exclude nested editables).
72 if ( contentEditableParent && contentEditableParent.getAttribute( 'contenteditable' ) == 'false' )
73 editor.getSelection().fake( contentEditableParent );
74 }
75
76 var doc = domEvent.getTarget().getDocument(),
77 offsetParent = domEvent.getTarget().getDocument().getDocumentElement(),
78 fromFrame = !doc.equals( CKEDITOR.document ),
79 scroll = doc.getWindow().getScrollPosition(),
80 offsetX = fromFrame ? domEvent.$.clientX : domEvent.$.pageX || scroll.x + domEvent.$.clientX,
81 offsetY = fromFrame ? domEvent.$.clientY : domEvent.$.pageY || scroll.y + domEvent.$.clientY;
82
83 CKEDITOR.tools.setTimeout( function() {
84 this.open( offsetParent, null, offsetX, offsetY );
85
86 // IE needs a short while to allow selection change before opening menu. (#7908)
87 }, CKEDITOR.env.ie ? 200 : 0, this );
88 }, this );
89
90 if ( CKEDITOR.env.webkit ) {
91 var holdCtrlKey,
92 onKeyDown = function( event ) {
93 holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey;
94 },
95 resetOnKeyUp = function() {
96 holdCtrlKey = 0;
97 };
98
99 element.on( 'keydown', onKeyDown );
100 element.on( 'keyup', resetOnKeyUp );
101 element.on( 'contextmenu', resetOnKeyUp );
102 }
103 },
104
105 /**
106 * Opens the context menu in the given location. See the {@link CKEDITOR.menu#show} method.
107 *
108 * @param {CKEDITOR.dom.element} offsetParent
109 * @param {Number} [corner]
110 * @param {Number} [offsetX]
111 * @param {Number} [offsetY]
112 */
113 open: function( offsetParent, corner, offsetX, offsetY ) {
114 this.editor.focus();
115 offsetParent = offsetParent || CKEDITOR.document.getDocumentElement();
116
117 // #9362: Force selection check to update commands' states in the new context.
118 this.editor.selectionChange( 1 );
119
120 this.show( offsetParent, corner, offsetX, offsetY );
121 }
122 }
123 } );
124 },
125
126 beforeInit: function( editor ) {
127 /**
128 * @readonly
129 * @property {CKEDITOR.plugins.contextMenu} contextMenu
130 * @member CKEDITOR.editor
131 */
132 var contextMenu = editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor );
133
134 editor.on( 'contentDom', function() {
135 contextMenu.addTarget( editor.editable(), editor.config.browserContextMenuOnCtrl !== false );
136 } );
137
138 editor.addCommand( 'contextMenu', {
139 exec: function() {
140 editor.contextMenu.open( editor.document.getBody() );
141 }
142 } );
143
144 editor.setKeystroke( CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' );
145 editor.setKeystroke( CKEDITOR.CTRL + CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' );
146 }
147} );
148
149/**
150 * Whether to show the browser native context menu when the <kbd>Ctrl</kbd> or
151 * <kbd>Meta</kbd> (Mac) key is pressed on opening the context menu with the
152 * right mouse button click or the <kbd>Menu</kbd> key.
153 *
154 * config.browserContextMenuOnCtrl = false;
155 *
156 * @since 3.0.2
157 * @cfg {Boolean} [browserContextMenuOnCtrl=true]
158 * @member CKEDITOR.config
159 */
diff --git a/sources/plugins/dialog/dialogDefinition.js b/sources/plugins/dialog/dialogDefinition.js
new file mode 100644
index 0000000..6ecb491
--- /dev/null
+++ b/sources/plugins/dialog/dialogDefinition.js
@@ -0,0 +1,1032 @@
1// jscs:disable disallowMixedSpacesAndTabs
2/**
3 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4 * For licensing, see LICENSE.md or http://ckeditor.com/license
5 */
6
7/**
8 * @fileOverview Defines the "virtual" dialog, dialog content and dialog button
9 * definition classes.
10 */
11
12/**
13 * The definition of a dialog window.
14 *
15 * This class is not really part of the API. It just illustrates the properties
16 * that developers can use to define and create dialogs.
17 *
18 * // There is no constructor for this class, the user just has to define an
19 * // object with the appropriate properties.
20 *
21 * CKEDITOR.dialog.add( 'testOnly', function( editor ) {
22 * return {
23 * title: 'Test Dialog',
24 * resizable: CKEDITOR.DIALOG_RESIZE_BOTH,
25 * minWidth: 500,
26 * minHeight: 400,
27 * contents: [
28 * {
29 * id: 'tab1',
30 * label: 'First Tab',
31 * title: 'First Tab Title',
32 * accessKey: 'Q',
33 * elements: [
34 * {
35 * type: 'text',
36 * label: 'Test Text 1',
37 * id: 'testText1',
38 * 'default': 'hello world!'
39 * }
40 * ]
41 * }
42 * ]
43 * };
44 * } );
45 *
46 * @class CKEDITOR.dialog.definition
47 */
48
49/**
50 * The dialog title, displayed in the dialog's header. Required.
51 *
52 * @property {String} title
53 */
54
55/**
56 * How the dialog can be resized, must be one of the four contents defined below.
57 *
58 * * {@link CKEDITOR#DIALOG_RESIZE_NONE}
59 * * {@link CKEDITOR#DIALOG_RESIZE_WIDTH}
60 * * {@link CKEDITOR#DIALOG_RESIZE_HEIGHT}
61 * * {@link CKEDITOR#DIALOG_RESIZE_BOTH}
62 *
63 * @property {Number} [resizable=CKEDITOR.DIALOG_RESIZE_NONE]
64 */
65
66/**
67 * The minimum width of the dialog, in pixels.
68 *
69 * @property {Number} [minWidth=600]
70 */
71
72/**
73 * The minimum height of the dialog, in pixels.
74 *
75 * @property {Number} [minHeight=400]
76 */
77
78
79/**
80 * The initial width of the dialog, in pixels.
81 *
82 * @since 3.5.3
83 * @property {Number} [width=CKEDITOR.dialog.definition#minWidth]
84 */
85
86/**
87 * The initial height of the dialog, in pixels.
88 *
89 * @since 3.5.3
90 * @property {Number} [height=CKEDITOR.dialog.definition.minHeight]
91 */
92
93/**
94 * The buttons in the dialog, defined as an array of
95 * {@link CKEDITOR.dialog.definition.button} objects.
96 *
97 * @property {Array} [buttons=[ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ]]
98 */
99
100/**
101 * The contents in the dialog, defined as an array of
102 * {@link CKEDITOR.dialog.definition.content} objects. Required.
103 *
104 * @property {Array} contents
105 */
106
107/**
108 * The function to execute when OK is pressed.
109 *
110 * @property {Function} onOk
111 */
112
113/**
114 * The function to execute when Cancel is pressed.
115 *
116 * @property {Function} onCancel
117 */
118
119/**
120 * The function to execute when the dialog is displayed for the first time.
121 *
122 * @property {Function} onLoad
123 */
124
125/**
126 * The function to execute when the dialog is loaded (executed every time the dialog is opened).
127 *
128 * @property {Function} onShow
129 */
130
131/**
132 * This class is not really part of the API. It just illustrates the properties
133 * that developers can use to define and create dialog content pages.
134 *
135 * @class CKEDITOR.dialog.definition.content.
136 */
137
138/**
139 * The id of the content page.
140 *
141 * @property {String} id
142 */
143
144/**
145 * The tab label of the content page.
146 *
147 * @property {String} label
148 */
149
150/**
151 * The popup message of the tab label.
152 *
153 * @property {String} title
154 */
155
156/**
157 * The CTRL hotkey for switching to the tab.
158 *
159 * contentDefinition.accessKey = 'Q'; // Switch to this page when CTRL-Q is pressed.
160 *
161 * @property {String} accessKey
162 */
163
164/**
165 * The UI elements contained in this content page, defined as an array of
166 * {@link CKEDITOR.dialog.definition.uiElement} objects.
167 *
168 * @property {Array} elements
169 */
170
171/**
172 * The definition of user interface element (textarea, radio etc).
173 *
174 * This class is not really part of the API. It just illustrates the properties
175 * that developers can use to define and create dialog UI elements.
176 *
177 * @class CKEDITOR.dialog.definition.uiElement
178 * @see CKEDITOR.ui.dialog.uiElement
179 */
180
181/**
182 * The id of the UI element.
183 *
184 * @property {String} id
185 */
186
187/**
188 * The type of the UI element. Required.
189 *
190 * @property {String} type
191 */
192
193/**
194 * The popup label of the UI element.
195 *
196 * @property {String} title
197 */
198
199/**
200 * The content that needs to be allowed to enable this UI element.
201 * All formats accepted by {@link CKEDITOR.filter#check} may be used.
202 *
203 * When all UI elements in a tab are disabled, this tab will be disabled automatically.
204 *
205 * @property {String/Object/CKEDITOR.style} requiredContent
206 */
207
208/**
209 * CSS class names to append to the UI element.
210 *
211 * @property {String} className
212 */
213
214/**
215 * Inline CSS classes to append to the UI element.
216 *
217 * @property {String} style
218 */
219
220/**
221 * Horizontal alignment (in container) of the UI element.
222 *
223 * @property {String} align
224 */
225
226/**
227 * Function to execute the first time the UI element is displayed.
228 *
229 * @property {Function} onLoad
230 */
231
232/**
233 * Function to execute whenever the UI element's parent dialog is displayed.
234 *
235 * @property {Function} onShow
236 */
237
238/**
239 * Function to execute whenever the UI element's parent dialog is closed.
240 *
241 * @property {Function} onHide
242 */
243
244/**
245 * Function to execute whenever the UI element's parent
246 * dialog's {@link CKEDITOR.dialog#setupContent} method is executed.
247 * It usually takes care of the respective UI element as a standalone element.
248 *
249 * @property {Function} setup
250 */
251
252/**
253 * Function to execute whenever the UI element's parent
254 * dialog's {@link CKEDITOR.dialog#commitContent} method is executed.
255 * It usually takes care of the respective UI element as a standalone element.
256 *
257 * @property {Function} commit
258 */
259
260// ----- hbox -----------------------------------------------------------------
261
262/**
263 * Horizontal layout box for dialog UI elements, auto-expends to available width of container.
264 *
265 * This class is not really part of the API. It just illustrates the properties
266 * that developers can use to define and create horizontal layouts.
267 *
268 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.hbox} object and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
269 *
270 * // There is no constructor for this class, the user just has to define an
271 * // object with the appropriate properties.
272 *
273 * // Example:
274 * {
275 * type: 'hbox',
276 * widths: [ '25%', '25%', '50%' ],
277 * children: [
278 * {
279 * type: 'text',
280 * id: 'id1',
281 * width: '40px',
282 * },
283 * {
284 * type: 'text',
285 * id: 'id2',
286 * width: '40px',
287 * },
288 * {
289 * type: 'text',
290 * id: 'id3'
291 * }
292 * ]
293 * }
294 *
295 * @class CKEDITOR.dialog.definition.hbox
296 * @extends CKEDITOR.dialog.definition.uiElement
297 */
298
299/**
300 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container.
301 *
302 * @property {Array} children
303 */
304
305/**
306 * (Optional) The widths of child cells.
307 *
308 * @property {Array} widths
309 */
310
311/**
312 * (Optional) The height of the layout.
313 *
314 * @property {Number} height
315 */
316
317/**
318 * The CSS styles to apply to this element.
319 *
320 * @property {String} styles
321 */
322
323/**
324 * (Optional) The padding width inside child cells. Example: 0, 1.
325 *
326 * @property {Number} padding
327 */
328
329/**
330 * (Optional) The alignment of the whole layout. Example: center, top.
331 *
332 * @property {String} align
333 */
334
335// ----- vbox -----------------------------------------------------------------
336
337/**
338 * Vertical layout box for dialog UI elements.
339 *
340 * This class is not really part of the API. It just illustrates the properties
341 * that developers can use to define and create vertical layouts.
342 *
343 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.vbox} object and can
344 * be accessed with {@link CKEDITOR.dialog#getContentElement}.
345 *
346 * // There is no constructor for this class, the user just has to define an
347 * // object with the appropriate properties.
348 *
349 * // Example:
350 * {
351 * type: 'vbox',
352 * align: 'right',
353 * width: '200px',
354 * children: [
355 * {
356 * type: 'text',
357 * id: 'age',
358 * label: 'Age'
359 * },
360 * {
361 * type: 'text',
362 * id: 'sex',
363 * label: 'Sex'
364 * },
365 * {
366 * type: 'text',
367 * id: 'nationality',
368 * label: 'Nationality'
369 * }
370 * ]
371 * }
372 *
373 * @class CKEDITOR.dialog.definition.vbox
374 * @extends CKEDITOR.dialog.definition.uiElement
375 */
376
377/**
378 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container.
379 *
380 * @property {Array} children
381 */
382
383/**
384 * (Optional) The width of the layout.
385 *
386 * @property {Array} width
387 */
388
389/**
390 * (Optional) The heights of individual cells.
391 *
392 * @property {Number} heights
393 */
394
395/**
396 * The CSS styles to apply to this element.
397 *
398 * @property {String} styles
399 */
400
401/**
402 * (Optional) The padding width inside child cells. Example: 0, 1.
403 *
404 * @property {Number} padding
405 */
406
407/**
408 * (Optional) The alignment of the whole layout. Example: center, top.
409 *
410 * @property {String} align
411 */
412
413/**
414 * (Optional) Whether the layout should expand vertically to fill its container.
415 *
416 * @property {Boolean} expand
417 */
418
419// ----- labeled element ------------------------------------------------------
420
421/**
422 * The definition of labeled user interface element (textarea, textInput etc).
423 *
424 * This class is not really part of the API. It just illustrates the properties
425 * that developers can use to define and create dialog UI elements.
426 *
427 * @class CKEDITOR.dialog.definition.labeledElement
428 * @extends CKEDITOR.dialog.definition.uiElement
429 * @see CKEDITOR.ui.dialog.labeledElement
430 */
431
432/**
433 * The label of the UI element.
434 *
435 * {
436 * type: 'text',
437 * label: 'My Label'
438 * }
439 *
440 * @property {String} label
441 */
442
443/**
444 * (Optional) Specify the layout of the label. Set to `'horizontal'` for horizontal layout.
445 * The default layout is vertical.
446 *
447 * {
448 * type: 'text',
449 * label: 'My Label',
450 * labelLayout: 'horizontal'
451 * }
452 *
453 * @property {String} labelLayout
454 */
455
456/**
457 * (Optional) Applies only to horizontal layouts: a two elements array of lengths to specify the widths of the
458 * label and the content element. See also {@link CKEDITOR.dialog.definition.labeledElement#labelLayout}.
459 *
460 * {
461 * type: 'text',
462 * label: 'My Label',
463 * labelLayout: 'horizontal',
464 * widths: [100, 200]
465 * }
466 *
467 * @property {Array} widths
468 */
469
470/**
471 * Specify the inline style of the uiElement label.
472 *
473 * {
474 * type: 'text',
475 * label: 'My Label',
476 * labelStyle: 'color: red'
477 * }
478 *
479 * @property {String} labelStyle
480 */
481
482
483/**
484 * Specify the inline style of the input element.
485 *
486 * {
487 * type: 'text',
488 * label: 'My Label',
489 * inputStyle: 'text-align: center'
490 * }
491 *
492 * @since 3.6.1
493 * @property {String} inputStyle
494 */
495
496/**
497 * Specify the inline style of the input element container.
498 *
499 * {
500 * type: 'text',
501 * label: 'My Label',
502 * controlStyle: 'width: 3em'
503 * }
504 *
505 * @since 3.6.1
506 * @property {String} controlStyle
507 */
508
509// ----- button ---------------------------------------------------------------
510
511/**
512 * The definition of a button.
513 *
514 * This class is not really part of the API. It just illustrates the properties
515 * that developers can use to define and create buttons.
516 *
517 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.button} object
518 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
519 *
520 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
521 *
522 * // There is no constructor for this class, the user just has to define an
523 * // object with the appropriate properties.
524 *
525 * // Example:
526 * {
527 * type: 'button',
528 * id: 'buttonId',
529 * label: 'Click me',
530 * title: 'My title',
531 * onClick: function() {
532 * // this = CKEDITOR.ui.dialog.button
533 * alert( 'Clicked: ' + this.id );
534 * }
535 * }
536 *
537 * @class CKEDITOR.dialog.definition.button
538 * @extends CKEDITOR.dialog.definition.uiElement
539 */
540
541/**
542 * Whether the button is disabled.
543 *
544 * @property {Boolean} disabled
545 */
546
547/**
548 * The label of the UI element.
549 *
550 * @property {String} label
551 */
552
553// ----- checkbox ------
554/**
555 * The definition of a checkbox element.
556 *
557 * This class is not really part of the API. It just illustrates the properties
558 * that developers can use to define and create groups of checkbox buttons.
559 *
560 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.checkbox} object
561 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
562 *
563 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
564 *
565 * // There is no constructor for this class, the user just has to define an
566 * // object with the appropriate properties.
567 *
568 * // Example:
569 * {
570 * type: 'checkbox',
571 * id: 'agree',
572 * label: 'I agree',
573 * 'default': 'checked',
574 * onClick: function() {
575 * // this = CKEDITOR.ui.dialog.checkbox
576 * alert( 'Checked: ' + this.getValue() );
577 * }
578 * }
579 *
580 * @class CKEDITOR.dialog.definition.checkbox
581 * @extends CKEDITOR.dialog.definition.uiElement
582 */
583
584/**
585 * (Optional) The validation function.
586 *
587 * @property {Function} validate
588 */
589
590/**
591 * The label of the UI element.
592 *
593 * @property {String} label
594 */
595
596/**
597 * The default state.
598 *
599 * @property {String} [default='' (unchecked)]
600 */
601
602// ----- file -----------------------------------------------------------------
603
604/**
605 * The definition of a file upload input.
606 *
607 * This class is not really part of the API. It just illustrates the properties
608 * that developers can use to define and create file upload elements.
609 *
610 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.file} object
611 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
612 *
613 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
614 *
615 * // There is no constructor for this class, the user just has to define an
616 * // object with the appropriate properties.
617 *
618 * // Example:
619 * {
620 * type: 'file',
621 * id: 'upload',
622 * label: 'Select file from your computer',
623 * size: 38
624 * },
625 * {
626 * type: 'fileButton',
627 * id: 'fileId',
628 * label: 'Upload file',
629 * 'for': [ 'tab1', 'upload' ],
630 * filebrowser: {
631 * onSelect: function( fileUrl, data ) {
632 * alert( 'Successfully uploaded: ' + fileUrl );
633 * }
634 * }
635 * }
636 *
637 * @class CKEDITOR.dialog.definition.file
638 * @extends CKEDITOR.dialog.definition.labeledElement
639 */
640
641/**
642 * (Optional) The validation function.
643 *
644 * @property {Function} validate
645 */
646
647/**
648 * (Optional) The action attribute of the form element associated with this file upload input.
649 * If empty, CKEditor will use path to server connector for currently opened folder.
650 *
651 * @property {String} action
652 */
653
654/**
655 * The size of the UI element.
656 *
657 * @property {Number} size
658 */
659
660// ----- fileButton -----------------------------------------------------------
661
662/**
663 * The definition of a button for submitting the file in a file upload input.
664 *
665 * This class is not really part of the API. It just illustrates the properties
666 * that developers can use to define and create a button for submitting the file in a file upload input.
667 *
668 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.fileButton} object
669 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
670 *
671 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
672 *
673 * @class CKEDITOR.dialog.definition.fileButton
674 * @extends CKEDITOR.dialog.definition.uiElement
675 */
676
677/**
678 * (Optional) The validation function.
679 *
680 * @property {Function} validate
681 */
682
683/**
684 * The label of the UI element.
685 *
686 * @property {String} label
687 */
688
689/**
690 * The instruction for CKEditor how to deal with file upload.
691 * By default, the file and fileButton elements will not work "as expected" if this attribute is not set.
692 *
693 * // Update field with id 'txtUrl' in the 'tab1' tab when file is uploaded.
694 * filebrowser: 'tab1:txtUrl'
695 *
696 * // Call custom onSelect function when file is successfully uploaded.
697 * filebrowser: {
698 * onSelect: function( fileUrl, data ) {
699 * alert( 'Successfully uploaded: ' + fileUrl );
700 * }
701 * }
702 *
703 * @property {String} filebrowser/Object
704 */
705
706/**
707 * An array that contains pageId and elementId of the file upload input element for which this button is created.
708 *
709 * [ pageId, elementId ]
710 *
711 * @property {String} for
712 */
713
714// ----- html -----------------------------------------------------------------
715
716/**
717 * The definition of a raw HTML element.
718 *
719 * This class is not really part of the API. It just illustrates the properties
720 * that developers can use to define and create elements made from raw HTML code.
721 *
722 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.html} object
723 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
724 *
725 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
726 * To access HTML elements use {@link CKEDITOR.dom.document#getById}.
727 *
728 * // There is no constructor for this class, the user just has to define an
729 * // object with the appropriate properties.
730 *
731 * // Example 1:
732 * {
733 * type: 'html',
734 * html: '<h3>This is some sample HTML content.</h3>'
735 * }
736 *
737 * // Example 2:
738 * // Complete sample with document.getById() call when the "Ok" button is clicked.
739 * var dialogDefinition = {
740 * title: 'Sample dialog',
741 * minWidth: 300,
742 * minHeight: 200,
743 * onOk: function() {
744 * // "this" is now a CKEDITOR.dialog object.
745 * var document = this.getElement().getDocument();
746 * // document = CKEDITOR.dom.document
747 * var element = <b>document.getById( 'myDiv' );</b>
748 * if ( element )
749 * alert( element.getHtml() );
750 * },
751 * contents: [
752 * {
753 * id: 'tab1',
754 * label: '',
755 * title: '',
756 * elements: [
757 * {
758 * type: 'html',
759 * html: '<div id="myDiv">Sample <b>text</b>.</div><div id="otherId">Another div.</div>'
760 * }
761 * ]
762 * }
763 * ],
764 * buttons: [ CKEDITOR.dialog.cancelButton, CKEDITOR.dialog.okButton ]
765 * };
766 *
767 * @class CKEDITOR.dialog.definition.html
768 * @extends CKEDITOR.dialog.definition.uiElement
769 */
770
771/**
772 * (Required) HTML code of this element.
773 *
774 * @property {String} html
775 */
776
777// ----- radio ----------------------------------------------------------------
778
779/**
780 * The definition of a radio group.
781 *
782 * This class is not really part of the API. It just illustrates the properties
783 * that developers can use to define and create groups of radio buttons.
784 *
785 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.radio} object
786 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
787 *
788 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
789 *
790 * // There is no constructor for this class, the user just has to define an
791 * // object with the appropriate properties.
792 *
793 * // Example:
794 * {
795 * type: 'radio',
796 * id: 'country',
797 * label: 'Which country is bigger',
798 * items: [ [ 'France', 'FR' ], [ 'Germany', 'DE' ] ],
799 * style: 'color: green',
800 * 'default': 'DE',
801 * onClick: function() {
802 * // this = CKEDITOR.ui.dialog.radio
803 * alert( 'Current value: ' + this.getValue() );
804 * }
805 * }
806 *
807 * @class CKEDITOR.dialog.definition.radio
808 * @extends CKEDITOR.dialog.definition.labeledElement
809 */
810
811/**
812 * The default value.
813 *
814 * @property {String} default
815 */
816
817/**
818 * (Optional) The validation function.
819 *
820 * @property {Function} validate
821 */
822
823/**
824 * An array of options. Each option is a 1- or 2-item array of format `[ 'Description', 'Value' ]`.
825 * If `'Value'` is missing, then the value would be assumed to be the same as the description.
826 *
827 * @property {Array} items
828 */
829
830// ----- selectElement --------------------------------------------------------
831
832/**
833 * The definition of a select element.
834 *
835 * This class is not really part of the API. It just illustrates the properties
836 * that developers can use to define and create select elements.
837 *
838 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.select} object
839 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
840 *
841 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
842 *
843 * // There is no constructor for this class, the user just has to define an
844 * // object with the appropriate properties.
845 *
846 * // Example:
847 * {
848 * type: 'select',
849 * id: 'sport',
850 * label: 'Select your favourite sport',
851 * items: [ [ 'Basketball' ], [ 'Baseball' ], [ 'Hockey' ], [ 'Football' ] ],
852 * 'default': 'Football',
853 * onChange: function( api ) {
854 * // this = CKEDITOR.ui.dialog.select
855 * alert( 'Current value: ' + this.getValue() );
856 * }
857 * }
858 *
859 * @class CKEDITOR.dialog.definition.select
860 * @extends CKEDITOR.dialog.definition.labeledElement
861 */
862
863/**
864 * The default value.
865 *
866 * @property {String} default
867 */
868
869/**
870 * (Optional) The validation function.
871 *
872 * @property {Function} validate
873 */
874
875/**
876 * An array of options. Each option is a 1- or 2-item array of format `[ 'Description', 'Value' ]`.
877 * If `'Value'` is missing, then the value would be assumed to be the same as the description.
878 *
879 * @property {Array} items
880 */
881
882/**
883 * (Optional) Set this to true if you'd like to have a multiple-choice select box.
884 *
885 * @property {Boolean} [multiple=false]
886 */
887
888/**
889 * (Optional) The number of items to display in the select box.
890 *
891 * @property {Number} size
892 */
893
894// ----- textInput ------------------------------------------------------------
895
896/**
897 * The definition of a text field (single line).
898 *
899 * This class is not really part of the API. It just illustrates the properties
900 * that developers can use to define and create text fields.
901 *
902 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.textInput} object
903 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
904 *
905 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
906 *
907 * // There is no constructor for this class, the user just has to define an
908 * // object with the appropriate properties.
909 *
910 * {
911 * type: 'text',
912 * id: 'name',
913 * label: 'Your name',
914 * 'default': '',
915 * validate: function() {
916 * if ( !this.getValue() ) {
917 * api.openMsgDialog( '', 'Name cannot be empty.' );
918 * return false;
919 * }
920 * }
921 * }
922 *
923 * @class CKEDITOR.dialog.definition.textInput
924 * @extends CKEDITOR.dialog.definition.labeledElement
925 */
926
927/**
928 * The default value.
929 *
930 * @property {String} default
931 */
932
933/**
934 * (Optional) The maximum length.
935 *
936 * @property {Number} maxLength
937 */
938
939/**
940 * (Optional) The size of the input field.
941 *
942 * @property {Number} size
943 */
944
945/**
946 * (Optional) The validation function.
947 *
948 * @property {Function} validate
949 */
950
951/**
952 * @property bidi
953 * @inheritdoc CKEDITOR.dialog.definition.textarea#bidi
954 */
955
956// ----- textarea -------------------------------------------------------------
957
958/**
959 * The definition of a text field (multiple lines).
960 *
961 * This class is not really part of the API. It just illustrates the properties
962 * that developers can use to define and create textarea.
963 *
964 * Once the dialog is opened, the created element becomes a {@link CKEDITOR.ui.dialog.textarea} object
965 * and can be accessed with {@link CKEDITOR.dialog#getContentElement}.
966 *
967 * For a complete example of dialog definition, please check {@link CKEDITOR.dialog#add}.
968 *
969* // There is no constructor for this class, the user just has to define an
970* // object with the appropriate properties.
971*
972* // Example:
973* {
974* type: 'textarea',
975* id: 'message',
976* label: 'Your comment',
977* 'default': '',
978* validate: function() {
979* if ( this.getValue().length < 5 ) {
980* api.openMsgDialog( 'The comment is too short.' );
981* return false;
982* }
983* }
984* }
985 *
986 * @class CKEDITOR.dialog.definition.textarea
987 * @extends CKEDITOR.dialog.definition.labeledElement
988 */
989
990/**
991 * The number of rows.
992 *
993 * @property {Number} rows
994 */
995
996/**
997 * The number of columns.
998 *
999 * @property {Number} cols
1000 */
1001
1002/**
1003 * (Optional) The validation function.
1004 *
1005 * @property {Function} validate
1006 */
1007
1008/**
1009 * The default value.
1010 *
1011 * @property {String} default
1012 */
1013
1014/**
1015 * Whether the text direction of this input should be togglable using the following keystrokes:
1016 *
1017 * * *Shift+Alt+End* &ndash; switch to Right-To-Left,
1018 * * *Shift+Alt+Home* &ndash; switch to Left-To-Right.
1019 *
1020 * By default the input will be loaded without any text direction set, which means that
1021 * the direction will be inherited from the editor's text direction.
1022 *
1023 * If the direction was set, a marker will be prepended to every non-empty value of this input:
1024 *
1025 * * [`\u202A`](http://unicode.org/cldr/utility/character.jsp?a=202A) &ndash; for Right-To-Left,
1026 * * [`\u202B`](http://unicode.org/cldr/utility/character.jsp?a=202B) &ndash; for Left-To-Right.
1027 *
1028 * This marker allows for restoring the same text direction upon the next dialog opening.
1029 *
1030 * @since 4.5
1031 * @property {Boolean} bidi
1032 */
diff --git a/sources/plugins/dialog/plugin.js b/sources/plugins/dialog/plugin.js
new file mode 100644
index 0000000..d6af6a2
--- /dev/null
+++ b/sources/plugins/dialog/plugin.js
@@ -0,0 +1,3399 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The floating dialog plugin.
8 */
9
10/**
11 * No resize for this dialog.
12 *
13 * @readonly
14 * @property {Number} [=0]
15 * @member CKEDITOR
16 */
17CKEDITOR.DIALOG_RESIZE_NONE = 0;
18
19/**
20 * Only allow horizontal resizing for this dialog, disable vertical resizing.
21 *
22 * @readonly
23 * @property {Number} [=1]
24 * @member CKEDITOR
25 */
26CKEDITOR.DIALOG_RESIZE_WIDTH = 1;
27
28/**
29 * Only allow vertical resizing for this dialog, disable horizontal resizing.
30 *
31 * @readonly
32 * @property {Number} [=2]
33 * @member CKEDITOR
34 */
35CKEDITOR.DIALOG_RESIZE_HEIGHT = 2;
36
37/**
38 * Allow the dialog to be resized in both directions.
39 *
40 * @readonly
41 * @property {Number} [=3]
42 * @member CKEDITOR
43 */
44CKEDITOR.DIALOG_RESIZE_BOTH = 3;
45
46/**
47 * Dialog state when idle.
48 *
49 * @readonly
50 * @property {Number} [=1]
51 * @member CKEDITOR
52 */
53CKEDITOR.DIALOG_STATE_IDLE = 1;
54
55/**
56 * Dialog state when busy.
57 *
58 * @readonly
59 * @property {Number} [=2]
60 * @member CKEDITOR
61 */
62CKEDITOR.DIALOG_STATE_BUSY = 2;
63
64( function() {
65 var cssLength = CKEDITOR.tools.cssLength;
66
67 function isTabVisible( tabId ) {
68 return !!this._.tabs[ tabId ][ 0 ].$.offsetHeight;
69 }
70
71 function getPreviousVisibleTab() {
72 var tabId = this._.currentTabId,
73 length = this._.tabIdList.length,
74 tabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, tabId ) + length;
75
76 for ( var i = tabIndex - 1; i > tabIndex - length; i-- ) {
77 if ( isTabVisible.call( this, this._.tabIdList[ i % length ] ) )
78 return this._.tabIdList[ i % length ];
79 }
80
81 return null;
82 }
83
84 function getNextVisibleTab() {
85 var tabId = this._.currentTabId,
86 length = this._.tabIdList.length,
87 tabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, tabId );
88
89 for ( var i = tabIndex + 1; i < tabIndex + length; i++ ) {
90 if ( isTabVisible.call( this, this._.tabIdList[ i % length ] ) )
91 return this._.tabIdList[ i % length ];
92 }
93
94 return null;
95 }
96
97
98 function clearOrRecoverTextInputValue( container, isRecover ) {
99 var inputs = container.$.getElementsByTagName( 'input' );
100 for ( var i = 0, length = inputs.length; i < length; i++ ) {
101 var item = new CKEDITOR.dom.element( inputs[ i ] );
102
103 if ( item.getAttribute( 'type' ).toLowerCase() == 'text' ) {
104 if ( isRecover ) {
105 item.setAttribute( 'value', item.getCustomData( 'fake_value' ) || '' );
106 item.removeCustomData( 'fake_value' );
107 } else {
108 item.setCustomData( 'fake_value', item.getAttribute( 'value' ) );
109 item.setAttribute( 'value', '' );
110 }
111 }
112 }
113 }
114
115 // Handle dialog element validation state UI changes.
116 function handleFieldValidated( isValid, msg ) {
117 var input = this.getInputElement();
118 if ( input )
119 isValid ? input.removeAttribute( 'aria-invalid' ) : input.setAttribute( 'aria-invalid', true );
120
121 if ( !isValid ) {
122 if ( this.select )
123 this.select();
124 else
125 this.focus();
126 }
127
128 msg && alert( msg ); // jshint ignore:line
129
130 this.fire( 'validated', { valid: isValid, msg: msg } );
131 }
132
133 function resetField() {
134 var input = this.getInputElement();
135 input && input.removeAttribute( 'aria-invalid' );
136 }
137
138 var templateSource = '<div class="cke_reset_all {editorId} {editorDialogClass} {hidpi}' +
139 '" dir="{langDir}"' +
140 ' lang="{langCode}"' +
141 ' role="dialog"' +
142 ' aria-labelledby="cke_dialog_title_{id}"' +
143 '>' +
144 '<table class="cke_dialog ' + CKEDITOR.env.cssClass + ' cke_{langDir}"' +
145 ' style="position:absolute" role="presentation">' +
146 '<tr><td role="presentation">' +
147 '<div class="cke_dialog_body" role="presentation">' +
148 '<div id="cke_dialog_title_{id}" class="cke_dialog_title" role="presentation"></div>' +
149 '<a id="cke_dialog_close_button_{id}" class="cke_dialog_close_button" href="javascript:void(0)" title="{closeTitle}" role="button"><span class="cke_label">X</span></a>' +
150 '<div id="cke_dialog_tabs_{id}" class="cke_dialog_tabs" role="tablist"></div>' +
151 '<table class="cke_dialog_contents" role="presentation">' +
152 '<tr>' +
153 '<td id="cke_dialog_contents_{id}" class="cke_dialog_contents_body" role="presentation"></td>' +
154 '</tr>' +
155 '<tr>' +
156 '<td id="cke_dialog_footer_{id}" class="cke_dialog_footer" role="presentation"></td>' +
157 '</tr>' +
158 '</table>' +
159 '</div>' +
160 '</td></tr>' +
161 '</table>' +
162 '</div>';
163
164 function buildDialog( editor ) {
165 var element = CKEDITOR.dom.element.createFromHtml( CKEDITOR.addTemplate( 'dialog', templateSource ).output( {
166 id: CKEDITOR.tools.getNextNumber(),
167 editorId: editor.id,
168 langDir: editor.lang.dir,
169 langCode: editor.langCode,
170 editorDialogClass: 'cke_editor_' + editor.name.replace( /\./g, '\\.' ) + '_dialog',
171 closeTitle: editor.lang.common.close,
172 hidpi: CKEDITOR.env.hidpi ? 'cke_hidpi' : ''
173 } ) );
174
175 // TODO: Change this to getById(), so it'll support custom templates.
176 var body = element.getChild( [ 0, 0, 0, 0, 0 ] ),
177 title = body.getChild( 0 ),
178 close = body.getChild( 1 );
179
180 // Don't allow dragging on dialog (#13184).
181 editor.plugins.clipboard && CKEDITOR.plugins.clipboard.preventDefaultDropOnElement( body );
182
183 // IFrame shim for dialog that masks activeX in IE. (#7619)
184 if ( CKEDITOR.env.ie && !CKEDITOR.env.quirks && !CKEDITOR.env.edge ) {
185 var src = 'javascript:void(function(){' + encodeURIComponent( 'document.open();(' + CKEDITOR.tools.fixDomain + ')();document.close();' ) + '}())', // jshint ignore:line
186 iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' +
187 ' frameBorder="0"' +
188 ' class="cke_iframe_shim"' +
189 ' src="' + src + '"' +
190 ' tabIndex="-1"' +
191 '></iframe>' );
192 iframe.appendTo( body.getParent() );
193 }
194
195 // Make the Title and Close Button unselectable.
196 title.unselectable();
197 close.unselectable();
198
199 return {
200 element: element,
201 parts: {
202 dialog: element.getChild( 0 ),
203 title: title,
204 close: close,
205 tabs: body.getChild( 2 ),
206 contents: body.getChild( [ 3, 0, 0, 0 ] ),
207 footer: body.getChild( [ 3, 0, 1, 0 ] )
208 }
209 };
210 }
211
212 /**
213 * This is the base class for runtime dialog objects. An instance of this
214 * class represents a single named dialog for a single editor instance.
215 *
216 * var dialogObj = new CKEDITOR.dialog( editor, 'smiley' );
217 *
218 * @class
219 * @constructor Creates a dialog class instance.
220 * @param {Object} editor The editor which created the dialog.
221 * @param {String} dialogName The dialog's registered name.
222 */
223 CKEDITOR.dialog = function( editor, dialogName ) {
224 // Load the dialog definition.
225 var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ],
226 defaultDefinition = CKEDITOR.tools.clone( defaultDialogDefinition ),
227 buttonsOrder = editor.config.dialog_buttonsOrder || 'OS',
228 dir = editor.lang.dir,
229 tabsToRemove = {},
230 i, processed, stopPropagation;
231
232 if ( ( buttonsOrder == 'OS' && CKEDITOR.env.mac ) || // The buttons in MacOS Apps are in reverse order (#4750)
233 ( buttonsOrder == 'rtl' && dir == 'ltr' ) || ( buttonsOrder == 'ltr' && dir == 'rtl' ) )
234 defaultDefinition.buttons.reverse();
235
236
237 // Completes the definition with the default values.
238 definition = CKEDITOR.tools.extend( definition( editor ), defaultDefinition );
239
240 // Clone a functionally independent copy for this dialog.
241 definition = CKEDITOR.tools.clone( definition );
242
243 // Create a complex definition object, extending it with the API
244 // functions.
245 definition = new definitionObject( this, definition );
246
247 var themeBuilt = buildDialog( editor );
248
249 // Initialize some basic parameters.
250 this._ = {
251 editor: editor,
252 element: themeBuilt.element,
253 name: dialogName,
254 contentSize: { width: 0, height: 0 },
255 size: { width: 0, height: 0 },
256 contents: {},
257 buttons: {},
258 accessKeyMap: {},
259
260 // Initialize the tab and page map.
261 tabs: {},
262 tabIdList: [],
263 currentTabId: null,
264 currentTabIndex: null,
265 pageCount: 0,
266 lastTab: null,
267 tabBarMode: false,
268
269 // Initialize the tab order array for input widgets.
270 focusList: [],
271 currentFocusIndex: 0,
272 hasFocus: false
273 };
274
275 this.parts = themeBuilt.parts;
276
277 CKEDITOR.tools.setTimeout( function() {
278 editor.fire( 'ariaWidget', this.parts.contents );
279 }, 0, this );
280
281 // Set the startup styles for the dialog, avoiding it enlarging the
282 // page size on the dialog creation.
283 var startStyles = {
284 position: CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed',
285 top: 0,
286 visibility: 'hidden'
287 };
288
289 startStyles[ dir == 'rtl' ? 'right' : 'left' ] = 0;
290 this.parts.dialog.setStyles( startStyles );
291
292
293 // Call the CKEDITOR.event constructor to initialize this instance.
294 CKEDITOR.event.call( this );
295
296 // Fire the "dialogDefinition" event, making it possible to customize
297 // the dialog definition.
298 this.definition = definition = CKEDITOR.fire( 'dialogDefinition', {
299 name: dialogName,
300 definition: definition
301 }, editor ).definition;
302
303 // Cache tabs that should be removed.
304 if ( !( 'removeDialogTabs' in editor._ ) && editor.config.removeDialogTabs ) {
305 var removeContents = editor.config.removeDialogTabs.split( ';' );
306
307 for ( i = 0; i < removeContents.length; i++ ) {
308 var parts = removeContents[ i ].split( ':' );
309 if ( parts.length == 2 ) {
310 var removeDialogName = parts[ 0 ];
311 if ( !tabsToRemove[ removeDialogName ] )
312 tabsToRemove[ removeDialogName ] = [];
313 tabsToRemove[ removeDialogName ].push( parts[ 1 ] );
314 }
315 }
316 editor._.removeDialogTabs = tabsToRemove;
317 }
318
319 // Remove tabs of this dialog.
320 if ( editor._.removeDialogTabs && ( tabsToRemove = editor._.removeDialogTabs[ dialogName ] ) ) {
321 for ( i = 0; i < tabsToRemove.length; i++ )
322 definition.removeContents( tabsToRemove[ i ] );
323 }
324
325 // Initialize load, show, hide, ok and cancel events.
326 if ( definition.onLoad )
327 this.on( 'load', definition.onLoad );
328
329 if ( definition.onShow )
330 this.on( 'show', definition.onShow );
331
332 if ( definition.onHide )
333 this.on( 'hide', definition.onHide );
334
335 if ( definition.onOk ) {
336 this.on( 'ok', function( evt ) {
337 // Dialog confirm might probably introduce content changes (#5415).
338 editor.fire( 'saveSnapshot' );
339 setTimeout( function() {
340 editor.fire( 'saveSnapshot' );
341 }, 0 );
342 if ( definition.onOk.call( this, evt ) === false )
343 evt.data.hide = false;
344 } );
345 }
346
347 // Set default dialog state.
348 this.state = CKEDITOR.DIALOG_STATE_IDLE;
349
350 if ( definition.onCancel ) {
351 this.on( 'cancel', function( evt ) {
352 if ( definition.onCancel.call( this, evt ) === false )
353 evt.data.hide = false;
354 } );
355 }
356
357 var me = this;
358
359 // Iterates over all items inside all content in the dialog, calling a
360 // function for each of them.
361 var iterContents = function( func ) {
362 var contents = me._.contents,
363 stop = false;
364
365 for ( var i in contents ) {
366 for ( var j in contents[ i ] ) {
367 stop = func.call( this, contents[ i ][ j ] );
368 if ( stop )
369 return;
370 }
371 }
372 };
373
374 this.on( 'ok', function( evt ) {
375 iterContents( function( item ) {
376 if ( item.validate ) {
377 var retval = item.validate( this ),
378 invalid = ( typeof retval == 'string' ) || retval === false;
379
380 if ( invalid ) {
381 evt.data.hide = false;
382 evt.stop();
383 }
384
385 handleFieldValidated.call( item, !invalid, typeof retval == 'string' ? retval : undefined );
386 return invalid;
387 }
388 } );
389 }, this, null, 0 );
390
391 this.on( 'cancel', function( evt ) {
392 iterContents( function( item ) {
393 if ( item.isChanged() ) {
394 if ( !editor.config.dialog_noConfirmCancel && !confirm( editor.lang.common.confirmCancel ) ) // jshint ignore:line
395 evt.data.hide = false;
396 return true;
397 }
398 } );
399 }, this, null, 0 );
400
401 this.parts.close.on( 'click', function( evt ) {
402 if ( this.fire( 'cancel', { hide: true } ).hide !== false )
403 this.hide();
404 evt.data.preventDefault();
405 }, this );
406
407 // Sort focus list according to tab order definitions.
408 function setupFocus() {
409 var focusList = me._.focusList;
410 focusList.sort( function( a, b ) {
411 // Mimics browser tab order logics;
412 if ( a.tabIndex != b.tabIndex )
413 return b.tabIndex - a.tabIndex;
414 // Sort is not stable in some browsers,
415 // fall-back the comparator to 'focusIndex';
416 else
417 return a.focusIndex - b.focusIndex;
418 } );
419
420 var size = focusList.length;
421 for ( var i = 0; i < size; i++ )
422 focusList[ i ].focusIndex = i;
423 }
424
425 // Expects 1 or -1 as an offset, meaning direction of the offset change.
426 function changeFocus( offset ) {
427 var focusList = me._.focusList;
428 offset = offset || 0;
429
430 if ( focusList.length < 1 )
431 return;
432
433 var startIndex = me._.currentFocusIndex;
434
435 if ( me._.tabBarMode && offset < 0 ) {
436 // If we are in tab mode, we need to mimic that we started tabbing back from the first
437 // focusList (so it will go to the last one).
438 startIndex = 0;
439 }
440
441 // Trigger the 'blur' event of any input element before anything,
442 // since certain UI updates may depend on it.
443 try {
444 focusList[ startIndex ].getInputElement().$.blur();
445 } catch ( e ) {}
446
447 var currentIndex = startIndex,
448 hasTabs = me._.pageCount > 1;
449
450 do {
451 currentIndex = currentIndex + offset;
452
453 if ( hasTabs && !me._.tabBarMode && ( currentIndex == focusList.length || currentIndex == -1 ) ) {
454 // If the dialog was not in tab mode, then focus the first tab (#13027).
455 me._.tabBarMode = true;
456 me._.tabs[ me._.currentTabId ][ 0 ].focus();
457 me._.currentFocusIndex = -1;
458
459 // Early return, in order to avoid accessing focusList[ -1 ].
460 return;
461 }
462
463 currentIndex = ( currentIndex + focusList.length ) % focusList.length;
464
465 if ( currentIndex == startIndex ) {
466 break;
467 }
468 } while ( offset && !focusList[ currentIndex ].isFocusable() );
469
470 focusList[ currentIndex ].focus();
471
472 // Select whole field content.
473 if ( focusList[ currentIndex ].type == 'text' )
474 focusList[ currentIndex ].select();
475 }
476
477 this.changeFocus = changeFocus;
478
479
480 function keydownHandler( evt ) {
481 // If I'm not the top dialog, ignore.
482 if ( me != CKEDITOR.dialog._.currentTop )
483 return;
484
485 var keystroke = evt.data.getKeystroke(),
486 rtl = editor.lang.dir == 'rtl',
487 arrowKeys = [ 37, 38, 39, 40 ],
488 button;
489
490 processed = stopPropagation = 0;
491
492 if ( keystroke == 9 || keystroke == CKEDITOR.SHIFT + 9 ) {
493 var shiftPressed = ( keystroke == CKEDITOR.SHIFT + 9 );
494 changeFocus( shiftPressed ? -1 : 1 );
495 processed = 1;
496 } else if ( keystroke == CKEDITOR.ALT + 121 && !me._.tabBarMode && me.getPageCount() > 1 ) {
497 // Alt-F10 puts focus into the current tab item in the tab bar.
498 me._.tabBarMode = true;
499 me._.tabs[ me._.currentTabId ][ 0 ].focus();
500 me._.currentFocusIndex = -1;
501 processed = 1;
502 } else if ( CKEDITOR.tools.indexOf( arrowKeys, keystroke ) != -1 && me._.tabBarMode ) {
503 // Array with key codes that activate previous tab.
504 var prevKeyCodes = [
505 // Depending on the lang dir: right or left key
506 rtl ? 39 : 37,
507 // Top/bot arrow: actually for both cases it's the same.
508 38
509 ],
510 nextId = CKEDITOR.tools.indexOf( prevKeyCodes, keystroke ) != -1 ? getPreviousVisibleTab.call( me ) : getNextVisibleTab.call( me );
511
512 me.selectPage( nextId );
513 me._.tabs[ nextId ][ 0 ].focus();
514 processed = 1;
515 } else if ( ( keystroke == 13 || keystroke == 32 ) && me._.tabBarMode ) {
516 this.selectPage( this._.currentTabId );
517 this._.tabBarMode = false;
518 this._.currentFocusIndex = -1;
519 changeFocus( 1 );
520 processed = 1;
521 }
522 // If user presses enter key in a text box, it implies clicking OK for the dialog.
523 else if ( keystroke == 13 /*ENTER*/ ) {
524 // Don't do that for a target that handles ENTER.
525 var target = evt.data.getTarget();
526 if ( !target.is( 'a', 'button', 'select', 'textarea' ) && ( !target.is( 'input' ) || target.$.type != 'button' ) ) {
527 button = this.getButton( 'ok' );
528 button && CKEDITOR.tools.setTimeout( button.click, 0, button );
529 processed = 1;
530 }
531 stopPropagation = 1; // Always block the propagation (#4269)
532 } else if ( keystroke == 27 /*ESC*/ ) {
533 button = this.getButton( 'cancel' );
534
535 // If there's a Cancel button, click it, else just fire the cancel event and hide the dialog.
536 if ( button )
537 CKEDITOR.tools.setTimeout( button.click, 0, button );
538 else {
539 if ( this.fire( 'cancel', { hide: true } ).hide !== false )
540 this.hide();
541 }
542 stopPropagation = 1; // Always block the propagation (#4269)
543 } else {
544 return;
545 }
546
547 keypressHandler( evt );
548 }
549
550 function keypressHandler( evt ) {
551 if ( processed )
552 evt.data.preventDefault( 1 );
553 else if ( stopPropagation )
554 evt.data.stopPropagation();
555 }
556
557 var dialogElement = this._.element;
558
559 editor.focusManager.add( dialogElement, 1 );
560
561 // Add the dialog keyboard handlers.
562 this.on( 'show', function() {
563 dialogElement.on( 'keydown', keydownHandler, this );
564
565 // Some browsers instead, don't cancel key events in the keydown, but in the
566 // keypress. So we must do a longer trip in those cases. (#4531,#8985)
567 if ( CKEDITOR.env.gecko )
568 dialogElement.on( 'keypress', keypressHandler, this );
569
570 } );
571 this.on( 'hide', function() {
572 dialogElement.removeListener( 'keydown', keydownHandler );
573 if ( CKEDITOR.env.gecko )
574 dialogElement.removeListener( 'keypress', keypressHandler );
575
576 // Reset fields state when closing dialog.
577 iterContents( function( item ) {
578 resetField.apply( item );
579 } );
580 } );
581 this.on( 'iframeAdded', function( evt ) {
582 var doc = new CKEDITOR.dom.document( evt.data.iframe.$.contentWindow.document );
583 doc.on( 'keydown', keydownHandler, this, null, 0 );
584 } );
585
586 // Auto-focus logic in dialog.
587 this.on( 'show', function() {
588 // Setup tabIndex on showing the dialog instead of on loading
589 // to allow dynamic tab order happen in dialog definition.
590 setupFocus();
591
592 var hasTabs = me._.pageCount > 1;
593
594 if ( editor.config.dialog_startupFocusTab && hasTabs ) {
595 me._.tabBarMode = true;
596 me._.tabs[ me._.currentTabId ][ 0 ].focus();
597 me._.currentFocusIndex = -1;
598 } else if ( !this._.hasFocus ) {
599 // http://dev.ckeditor.com/ticket/13114#comment:4.
600 this._.currentFocusIndex = hasTabs ? -1 : this._.focusList.length - 1;
601
602 // Decide where to put the initial focus.
603 if ( definition.onFocus ) {
604 var initialFocus = definition.onFocus.call( this );
605 // Focus the field that the user specified.
606 initialFocus && initialFocus.focus();
607 }
608 // Focus the first field in layout order.
609 else {
610 changeFocus( 1 );
611 }
612 }
613 }, this, null, 0xffffffff );
614
615 // IE6 BUG: Text fields and text areas are only half-rendered the first time the dialog appears in IE6 (#2661).
616 // This is still needed after [2708] and [2709] because text fields in hidden TR tags are still broken.
617 if ( CKEDITOR.env.ie6Compat ) {
618 this.on( 'load', function() {
619 var outer = this.getElement(),
620 inner = outer.getFirst();
621 inner.remove();
622 inner.appendTo( outer );
623 }, this );
624 }
625
626 initDragAndDrop( this );
627 initResizeHandles( this );
628
629 // Insert the title.
630 ( new CKEDITOR.dom.text( definition.title, CKEDITOR.document ) ).appendTo( this.parts.title );
631
632 // Insert the tabs and contents.
633 for ( i = 0; i < definition.contents.length; i++ ) {
634 var page = definition.contents[ i ];
635 page && this.addPage( page );
636 }
637
638 this.parts.tabs.on( 'click', function( evt ) {
639 var target = evt.data.getTarget();
640 // If we aren't inside a tab, bail out.
641 if ( target.hasClass( 'cke_dialog_tab' ) ) {
642 // Get the ID of the tab, without the 'cke_' prefix and the unique number suffix.
643 var id = target.$.id;
644 this.selectPage( id.substring( 4, id.lastIndexOf( '_' ) ) );
645
646 if ( this._.tabBarMode ) {
647 this._.tabBarMode = false;
648 this._.currentFocusIndex = -1;
649 changeFocus( 1 );
650 }
651 evt.data.preventDefault();
652 }
653 }, this );
654
655 // Insert buttons.
656 var buttonsHtml = [],
657 buttons = CKEDITOR.dialog._.uiElementBuilders.hbox.build( this, {
658 type: 'hbox',
659 className: 'cke_dialog_footer_buttons',
660 widths: [],
661 children: definition.buttons
662 }, buttonsHtml ).getChild();
663 this.parts.footer.setHtml( buttonsHtml.join( '' ) );
664
665 for ( i = 0; i < buttons.length; i++ )
666 this._.buttons[ buttons[ i ].id ] = buttons[ i ];
667
668 /**
669 * Current state of the dialog. Use the {@link #setState} method to update it.
670 * See the {@link #event-state} event to know more.
671 *
672 * @readonly
673 * @property {Number} [state=CKEDITOR.DIALOG_STATE_IDLE]
674 */
675 };
676
677 // Focusable interface. Use it via dialog.addFocusable.
678 function Focusable( dialog, element, index ) {
679 this.element = element;
680 this.focusIndex = index;
681 // TODO: support tabIndex for focusables.
682 this.tabIndex = 0;
683 this.isFocusable = function() {
684 return !element.getAttribute( 'disabled' ) && element.isVisible();
685 };
686 this.focus = function() {
687 dialog._.currentFocusIndex = this.focusIndex;
688 this.element.focus();
689 };
690 // Bind events
691 element.on( 'keydown', function( e ) {
692 if ( e.data.getKeystroke() in { 32: 1, 13: 1 } )
693 this.fire( 'click' );
694 } );
695 element.on( 'focus', function() {
696 this.fire( 'mouseover' );
697 } );
698 element.on( 'blur', function() {
699 this.fire( 'mouseout' );
700 } );
701 }
702
703 // Re-layout the dialog on window resize.
704 function resizeWithWindow( dialog ) {
705 var win = CKEDITOR.document.getWindow();
706 function resizeHandler() {
707 dialog.layout();
708 }
709 win.on( 'resize', resizeHandler );
710 dialog.on( 'hide', function() {
711 win.removeListener( 'resize', resizeHandler );
712 } );
713 }
714
715 CKEDITOR.dialog.prototype = {
716 destroy: function() {
717 this.hide();
718 this._.element.remove();
719 },
720
721 /**
722 * Resizes the dialog.
723 *
724 * dialogObj.resize( 800, 640 );
725 *
726 * @method
727 * @param {Number} width The width of the dialog in pixels.
728 * @param {Number} height The height of the dialog in pixels.
729 */
730 resize: ( function() {
731 return function( width, height ) {
732 if ( this._.contentSize && this._.contentSize.width == width && this._.contentSize.height == height )
733 return;
734
735 CKEDITOR.dialog.fire( 'resize', {
736 dialog: this,
737 width: width,
738 height: height
739 }, this._.editor );
740
741 this.fire( 'resize', {
742 width: width,
743 height: height
744 }, this._.editor );
745
746 var contents = this.parts.contents;
747 contents.setStyles( {
748 width: width + 'px',
749 height: height + 'px'
750 } );
751
752 // Update dialog position when dimension get changed in RTL.
753 if ( this._.editor.lang.dir == 'rtl' && this._.position )
754 this._.position.x = CKEDITOR.document.getWindow().getViewPaneSize().width - this._.contentSize.width - parseInt( this._.element.getFirst().getStyle( 'right' ), 10 );
755
756 this._.contentSize = { width: width, height: height };
757 };
758 } )(),
759
760 /**
761 * Gets the current size of the dialog in pixels.
762 *
763 * var width = dialogObj.getSize().width;
764 *
765 * @returns {Object}
766 * @returns {Number} return.width
767 * @returns {Number} return.height
768 */
769 getSize: function() {
770 var element = this._.element.getFirst();
771 return { width: element.$.offsetWidth || 0, height: element.$.offsetHeight || 0 };
772 },
773
774 /**
775 * Moves the dialog to an `(x, y)` coordinate relative to the window.
776 *
777 * dialogObj.move( 10, 40 );
778 *
779 * @method
780 * @param {Number} x The target x-coordinate.
781 * @param {Number} y The target y-coordinate.
782 * @param {Boolean} save Flag indicate whether the dialog position should be remembered on next open up.
783 */
784 move: function( x, y, save ) {
785
786 // The dialog may be fixed positioned or absolute positioned. Ask the
787 // browser what is the current situation first.
788 var element = this._.element.getFirst(), rtl = this._.editor.lang.dir == 'rtl';
789 var isFixed = element.getComputedStyle( 'position' ) == 'fixed';
790
791 // (#8888) In some cases of a very small viewport, dialog is incorrectly
792 // positioned in IE7. It also happens that it remains sticky and user cannot
793 // scroll down/up to reveal dialog's content below/above the viewport; this is
794 // cumbersome.
795 // The only way to fix this is to move mouse out of the browser and
796 // go back to see that dialog position is automagically fixed. No events,
797 // no style change - pure magic. This is a IE7 rendering issue, which can be
798 // fixed with dummy style redraw on each move.
799 if ( CKEDITOR.env.ie )
800 element.setStyle( 'zoom', '100%' );
801
802 if ( isFixed && this._.position && this._.position.x == x && this._.position.y == y )
803 return;
804
805 // Save the current position.
806 this._.position = { x: x, y: y };
807
808 // If not fixed positioned, add scroll position to the coordinates.
809 if ( !isFixed ) {
810 var scrollPosition = CKEDITOR.document.getWindow().getScrollPosition();
811 x += scrollPosition.x;
812 y += scrollPosition.y;
813 }
814
815 // Translate coordinate for RTL.
816 if ( rtl ) {
817 var dialogSize = this.getSize(), viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize();
818 x = viewPaneSize.width - dialogSize.width - x;
819 }
820
821 var styles = { 'top': ( y > 0 ? y : 0 ) + 'px' };
822 styles[ rtl ? 'right' : 'left' ] = ( x > 0 ? x : 0 ) + 'px';
823
824 element.setStyles( styles );
825
826 save && ( this._.moved = 1 );
827 },
828
829 /**
830 * Gets the dialog's position in the window.
831 *
832 * var dialogX = dialogObj.getPosition().x;
833 *
834 * @returns {Object}
835 * @returns {Number} return.x
836 * @returns {Number} return.y
837 */
838 getPosition: function() {
839 return CKEDITOR.tools.extend( {}, this._.position );
840 },
841
842 /**
843 * Shows the dialog box.
844 *
845 * dialogObj.show();
846 */
847 show: function() {
848 // Insert the dialog's element to the root document.
849 var element = this._.element;
850 var definition = this.definition;
851 if ( !( element.getParent() && element.getParent().equals( CKEDITOR.document.getBody() ) ) )
852 element.appendTo( CKEDITOR.document.getBody() );
853 else
854 element.setStyle( 'display', 'block' );
855
856 // First, set the dialog to an appropriate size.
857 this.resize(
858 this._.contentSize && this._.contentSize.width || definition.width || definition.minWidth,
859 this._.contentSize && this._.contentSize.height || definition.height || definition.minHeight
860 );
861
862 // Reset all inputs back to their default value.
863 this.reset();
864
865 // Select the first tab by default.
866 this.selectPage( this.definition.contents[ 0 ].id );
867
868 // Set z-index.
869 if ( CKEDITOR.dialog._.currentZIndex === null )
870 CKEDITOR.dialog._.currentZIndex = this._.editor.config.baseFloatZIndex;
871 this._.element.getFirst().setStyle( 'z-index', CKEDITOR.dialog._.currentZIndex += 10 );
872
873 // Maintain the dialog ordering and dialog cover.
874 if ( CKEDITOR.dialog._.currentTop === null ) {
875 CKEDITOR.dialog._.currentTop = this;
876 this._.parentDialog = null;
877 showCover( this._.editor );
878
879 } else {
880 this._.parentDialog = CKEDITOR.dialog._.currentTop;
881 var parentElement = this._.parentDialog.getElement().getFirst();
882 parentElement.$.style.zIndex -= Math.floor( this._.editor.config.baseFloatZIndex / 2 );
883 CKEDITOR.dialog._.currentTop = this;
884 }
885
886 element.on( 'keydown', accessKeyDownHandler );
887 element.on( 'keyup', accessKeyUpHandler );
888
889 // Reset the hasFocus state.
890 this._.hasFocus = false;
891
892 for ( var i in definition.contents ) {
893 if ( !definition.contents[ i ] )
894 continue;
895
896 var content = definition.contents[ i ],
897 tab = this._.tabs[ content.id ],
898 requiredContent = content.requiredContent,
899 enableElements = 0;
900
901 if ( !tab )
902 continue;
903
904 for ( var j in this._.contents[ content.id ] ) {
905 var elem = this._.contents[ content.id ][ j ];
906
907 if ( elem.type == 'hbox' || elem.type == 'vbox' || !elem.getInputElement() )
908 continue;
909
910 if ( elem.requiredContent && !this._.editor.activeFilter.check( elem.requiredContent ) )
911 elem.disable();
912 else {
913 elem.enable();
914 enableElements++;
915 }
916 }
917
918 if ( !enableElements || ( requiredContent && !this._.editor.activeFilter.check( requiredContent ) ) )
919 tab[ 0 ].addClass( 'cke_dialog_tab_disabled' );
920 else
921 tab[ 0 ].removeClass( 'cke_dialog_tab_disabled' );
922 }
923
924 CKEDITOR.tools.setTimeout( function() {
925 this.layout();
926 resizeWithWindow( this );
927
928 this.parts.dialog.setStyle( 'visibility', '' );
929
930 // Execute onLoad for the first show.
931 this.fireOnce( 'load', {} );
932 CKEDITOR.ui.fire( 'ready', this );
933
934 this.fire( 'show', {} );
935 this._.editor.fire( 'dialogShow', this );
936
937 if ( !this._.parentDialog )
938 this._.editor.focusManager.lock();
939
940 // Save the initial values of the dialog.
941 this.foreach( function( contentObj ) {
942 contentObj.setInitValue && contentObj.setInitValue();
943 } );
944
945 }, 100, this );
946 },
947
948 /**
949 * Rearrange the dialog to its previous position or the middle of the window.
950 *
951 * @since 3.5
952 */
953 layout: function() {
954 var el = this.parts.dialog;
955 var dialogSize = this.getSize();
956 var win = CKEDITOR.document.getWindow(),
957 viewSize = win.getViewPaneSize();
958
959 var posX = ( viewSize.width - dialogSize.width ) / 2,
960 posY = ( viewSize.height - dialogSize.height ) / 2;
961
962 // Switch to absolute position when viewport is smaller than dialog size.
963 if ( !CKEDITOR.env.ie6Compat ) {
964 if ( dialogSize.height + ( posY > 0 ? posY : 0 ) > viewSize.height || dialogSize.width + ( posX > 0 ? posX : 0 ) > viewSize.width ) {
965 el.setStyle( 'position', 'absolute' );
966 } else {
967 el.setStyle( 'position', 'fixed' );
968 }
969 }
970
971 this.move( this._.moved ? this._.position.x : posX, this._.moved ? this._.position.y : posY );
972 },
973
974 /**
975 * Executes a function for each UI element.
976 *
977 * @param {Function} fn Function to execute for each UI element.
978 * @returns {CKEDITOR.dialog} The current dialog object.
979 */
980 foreach: function( fn ) {
981 for ( var i in this._.contents ) {
982 for ( var j in this._.contents[ i ] ) {
983 fn.call( this, this._.contents[i][j] );
984 }
985 }
986
987 return this;
988 },
989
990 /**
991 * Resets all input values in the dialog.
992 *
993 * dialogObj.reset();
994 *
995 * @method
996 * @chainable
997 */
998 reset: ( function() {
999 var fn = function( widget ) {
1000 if ( widget.reset )
1001 widget.reset( 1 );
1002 };
1003 return function() {
1004 this.foreach( fn );
1005 return this;
1006 };
1007 } )(),
1008
1009
1010 /**
1011 * Calls the {@link CKEDITOR.dialog.definition.uiElement#setup} method of each
1012 * of the UI elements, with the arguments passed through it.
1013 * It is usually being called when the dialog is opened, to put the initial value inside the field.
1014 *
1015 * dialogObj.setupContent();
1016 *
1017 * var timestamp = ( new Date() ).valueOf();
1018 * dialogObj.setupContent( timestamp );
1019 */
1020 setupContent: function() {
1021 var args = arguments;
1022 this.foreach( function( widget ) {
1023 if ( widget.setup )
1024 widget.setup.apply( widget, args );
1025 } );
1026 },
1027
1028 /**
1029 * Calls the {@link CKEDITOR.dialog.definition.uiElement#commit} method of each
1030 * of the UI elements, with the arguments passed through it.
1031 * It is usually being called when the user confirms the dialog, to process the values.
1032 *
1033 * dialogObj.commitContent();
1034 *
1035 * var timestamp = ( new Date() ).valueOf();
1036 * dialogObj.commitContent( timestamp );
1037 */
1038 commitContent: function() {
1039 var args = arguments;
1040 this.foreach( function( widget ) {
1041 // Make sure IE triggers "change" event on last focused input before closing the dialog. (#7915)
1042 if ( CKEDITOR.env.ie && this._.currentFocusIndex == widget.focusIndex )
1043 widget.getInputElement().$.blur();
1044
1045 if ( widget.commit )
1046 widget.commit.apply( widget, args );
1047 } );
1048 },
1049
1050 /**
1051 * Hides the dialog box.
1052 *
1053 * dialogObj.hide();
1054 */
1055 hide: function() {
1056 if ( !this.parts.dialog.isVisible() )
1057 return;
1058
1059 this.fire( 'hide', {} );
1060 this._.editor.fire( 'dialogHide', this );
1061 // Reset the tab page.
1062 this.selectPage( this._.tabIdList[ 0 ] );
1063 var element = this._.element;
1064 element.setStyle( 'display', 'none' );
1065 this.parts.dialog.setStyle( 'visibility', 'hidden' );
1066 // Unregister all access keys associated with this dialog.
1067 unregisterAccessKey( this );
1068
1069 // Close any child(top) dialogs first.
1070 while ( CKEDITOR.dialog._.currentTop != this )
1071 CKEDITOR.dialog._.currentTop.hide();
1072
1073 // Maintain dialog ordering and remove cover if needed.
1074 if ( !this._.parentDialog )
1075 hideCover( this._.editor );
1076 else {
1077 var parentElement = this._.parentDialog.getElement().getFirst();
1078 parentElement.setStyle( 'z-index', parseInt( parentElement.$.style.zIndex, 10 ) + Math.floor( this._.editor.config.baseFloatZIndex / 2 ) );
1079 }
1080 CKEDITOR.dialog._.currentTop = this._.parentDialog;
1081
1082 // Deduct or clear the z-index.
1083 if ( !this._.parentDialog ) {
1084 CKEDITOR.dialog._.currentZIndex = null;
1085
1086 // Remove access key handlers.
1087 element.removeListener( 'keydown', accessKeyDownHandler );
1088 element.removeListener( 'keyup', accessKeyUpHandler );
1089
1090 var editor = this._.editor;
1091 editor.focus();
1092
1093 // Give a while before unlock, waiting for focus to return to the editable. (#172)
1094 setTimeout( function() {
1095 editor.focusManager.unlock();
1096
1097 // Fixed iOS focus issue (#12381).
1098 // Keep in mind that editor.focus() does not work in this case.
1099 if ( CKEDITOR.env.iOS ) {
1100 editor.window.focus();
1101 }
1102 }, 0 );
1103
1104 } else {
1105 CKEDITOR.dialog._.currentZIndex -= 10;
1106 }
1107
1108 delete this._.parentDialog;
1109 // Reset the initial values of the dialog.
1110 this.foreach( function( contentObj ) {
1111 contentObj.resetInitValue && contentObj.resetInitValue();
1112 } );
1113
1114 // Reset dialog state back to IDLE, if busy (#13213).
1115 this.setState( CKEDITOR.DIALOG_STATE_IDLE );
1116 },
1117
1118 /**
1119 * Adds a tabbed page into the dialog.
1120 *
1121 * @param {Object} contents Content definition.
1122 */
1123 addPage: function( contents ) {
1124 if ( contents.requiredContent && !this._.editor.filter.check( contents.requiredContent ) )
1125 return;
1126
1127 var pageHtml = [],
1128 titleHtml = contents.label ? ' title="' + CKEDITOR.tools.htmlEncode( contents.label ) + '"' : '',
1129 vbox = CKEDITOR.dialog._.uiElementBuilders.vbox.build( this, {
1130 type: 'vbox',
1131 className: 'cke_dialog_page_contents',
1132 children: contents.elements,
1133 expand: !!contents.expand,
1134 padding: contents.padding,
1135 style: contents.style || 'width: 100%;'
1136 }, pageHtml );
1137
1138 var contentMap = this._.contents[ contents.id ] = {},
1139 cursor,
1140 children = vbox.getChild(),
1141 enabledFields = 0;
1142
1143 while ( ( cursor = children.shift() ) ) {
1144 // Count all allowed fields.
1145 if ( !cursor.notAllowed && cursor.type != 'hbox' && cursor.type != 'vbox' )
1146 enabledFields++;
1147
1148 contentMap[ cursor.id ] = cursor;
1149 if ( typeof cursor.getChild == 'function' )
1150 children.push.apply( children, cursor.getChild() );
1151 }
1152
1153 // If all fields are disabled (because they are not allowed) hide this tab.
1154 if ( !enabledFields )
1155 contents.hidden = true;
1156
1157 // Create the HTML for the tab and the content block.
1158 var page = CKEDITOR.dom.element.createFromHtml( pageHtml.join( '' ) );
1159 page.setAttribute( 'role', 'tabpanel' );
1160
1161 var env = CKEDITOR.env;
1162 var tabId = 'cke_' + contents.id + '_' + CKEDITOR.tools.getNextNumber(),
1163 tab = CKEDITOR.dom.element.createFromHtml( [
1164 '<a class="cke_dialog_tab"',
1165 ( this._.pageCount > 0 ? ' cke_last' : 'cke_first' ),
1166 titleHtml,
1167 ( !!contents.hidden ? ' style="display:none"' : '' ),
1168 ' id="', tabId, '"',
1169 env.gecko && !env.hc ? '' : ' href="javascript:void(0)"',
1170 ' tabIndex="-1"',
1171 ' hidefocus="true"',
1172 ' role="tab">',
1173 contents.label,
1174 '</a>'
1175 ].join( '' ) );
1176
1177 page.setAttribute( 'aria-labelledby', tabId );
1178
1179 // Take records for the tabs and elements created.
1180 this._.tabs[ contents.id ] = [ tab, page ];
1181 this._.tabIdList.push( contents.id );
1182 !contents.hidden && this._.pageCount++;
1183 this._.lastTab = tab;
1184 this.updateStyle();
1185
1186 // Attach the DOM nodes.
1187
1188 page.setAttribute( 'name', contents.id );
1189 page.appendTo( this.parts.contents );
1190
1191 tab.unselectable();
1192 this.parts.tabs.append( tab );
1193
1194 // Add access key handlers if access key is defined.
1195 if ( contents.accessKey ) {
1196 registerAccessKey( this, this, 'CTRL+' + contents.accessKey, tabAccessKeyDown, tabAccessKeyUp );
1197 this._.accessKeyMap[ 'CTRL+' + contents.accessKey ] = contents.id;
1198 }
1199 },
1200
1201 /**
1202 * Activates a tab page in the dialog by its id.
1203 *
1204 * dialogObj.selectPage( 'tab_1' );
1205 *
1206 * @param {String} id The id of the dialog tab to be activated.
1207 */
1208 selectPage: function( id ) {
1209 if ( this._.currentTabId == id )
1210 return;
1211
1212 if ( this._.tabs[ id ][ 0 ].hasClass( 'cke_dialog_tab_disabled' ) )
1213 return;
1214
1215 // If event was canceled - do nothing.
1216 if ( this.fire( 'selectPage', { page: id, currentPage: this._.currentTabId } ) === false )
1217 return;
1218
1219 // Hide the non-selected tabs and pages.
1220 for ( var i in this._.tabs ) {
1221 var tab = this._.tabs[ i ][ 0 ],
1222 page = this._.tabs[ i ][ 1 ];
1223 if ( i != id ) {
1224 tab.removeClass( 'cke_dialog_tab_selected' );
1225 page.hide();
1226 }
1227 page.setAttribute( 'aria-hidden', i != id );
1228 }
1229
1230 var selected = this._.tabs[ id ];
1231 selected[ 0 ].addClass( 'cke_dialog_tab_selected' );
1232
1233 // [IE] an invisible input[type='text'] will enlarge it's width
1234 // if it's value is long when it shows, so we clear it's value
1235 // before it shows and then recover it (#5649)
1236 if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat ) {
1237 clearOrRecoverTextInputValue( selected[ 1 ] );
1238 selected[ 1 ].show();
1239 setTimeout( function() {
1240 clearOrRecoverTextInputValue( selected[ 1 ], 1 );
1241 }, 0 );
1242 } else {
1243 selected[ 1 ].show();
1244 }
1245
1246 this._.currentTabId = id;
1247 this._.currentTabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, id );
1248 },
1249
1250 /**
1251 * Dialog state-specific style updates.
1252 */
1253 updateStyle: function() {
1254 // If only a single page shown, a different style is used in the central pane.
1255 this.parts.dialog[ ( this._.pageCount === 1 ? 'add' : 'remove' ) + 'Class' ]( 'cke_single_page' );
1256 },
1257
1258 /**
1259 * Hides a page's tab away from the dialog.
1260 *
1261 * dialog.hidePage( 'tab_3' );
1262 *
1263 * @param {String} id The page's Id.
1264 */
1265 hidePage: function( id ) {
1266 var tab = this._.tabs[ id ] && this._.tabs[ id ][ 0 ];
1267 if ( !tab || this._.pageCount == 1 || !tab.isVisible() )
1268 return;
1269 // Switch to other tab first when we're hiding the active tab.
1270 else if ( id == this._.currentTabId )
1271 this.selectPage( getPreviousVisibleTab.call( this ) );
1272
1273 tab.hide();
1274 this._.pageCount--;
1275 this.updateStyle();
1276 },
1277
1278 /**
1279 * Unhides a page's tab.
1280 *
1281 * dialog.showPage( 'tab_2' );
1282 *
1283 * @param {String} id The page's Id.
1284 */
1285 showPage: function( id ) {
1286 var tab = this._.tabs[ id ] && this._.tabs[ id ][ 0 ];
1287 if ( !tab )
1288 return;
1289 tab.show();
1290 this._.pageCount++;
1291 this.updateStyle();
1292 },
1293
1294 /**
1295 * Gets the root DOM element of the dialog.
1296 *
1297 * var dialogElement = dialogObj.getElement().getFirst();
1298 * dialogElement.setStyle( 'padding', '5px' );
1299 *
1300 * @returns {CKEDITOR.dom.element} The `<span>` element containing this dialog.
1301 */
1302 getElement: function() {
1303 return this._.element;
1304 },
1305
1306 /**
1307 * Gets the name of the dialog.
1308 *
1309 * var dialogName = dialogObj.getName();
1310 *
1311 * @returns {String} The name of this dialog.
1312 */
1313 getName: function() {
1314 return this._.name;
1315 },
1316
1317 /**
1318 * Gets a dialog UI element object from a dialog page.
1319 *
1320 * dialogObj.getContentElement( 'tabId', 'elementId' ).setValue( 'Example' );
1321 *
1322 * @param {String} pageId id of dialog page.
1323 * @param {String} elementId id of UI element.
1324 * @returns {CKEDITOR.ui.dialog.uiElement} The dialog UI element.
1325 */
1326 getContentElement: function( pageId, elementId ) {
1327 var page = this._.contents[ pageId ];
1328 return page && page[ elementId ];
1329 },
1330
1331 /**
1332 * Gets the value of a dialog UI element.
1333 *
1334 * alert( dialogObj.getValueOf( 'tabId', 'elementId' ) );
1335 *
1336 * @param {String} pageId id of dialog page.
1337 * @param {String} elementId id of UI element.
1338 * @returns {Object} The value of the UI element.
1339 */
1340 getValueOf: function( pageId, elementId ) {
1341 return this.getContentElement( pageId, elementId ).getValue();
1342 },
1343
1344 /**
1345 * Sets the value of a dialog UI element.
1346 *
1347 * dialogObj.setValueOf( 'tabId', 'elementId', 'Example' );
1348 *
1349 * @param {String} pageId id of the dialog page.
1350 * @param {String} elementId id of the UI element.
1351 * @param {Object} value The new value of the UI element.
1352 */
1353 setValueOf: function( pageId, elementId, value ) {
1354 return this.getContentElement( pageId, elementId ).setValue( value );
1355 },
1356
1357 /**
1358 * Gets the UI element of a button in the dialog's button row.
1359 *
1360 * @returns {CKEDITOR.ui.dialog.button} The button object.
1361 *
1362 * @param {String} id The id of the button.
1363 */
1364 getButton: function( id ) {
1365 return this._.buttons[ id ];
1366 },
1367
1368 /**
1369 * Simulates a click to a dialog button in the dialog's button row.
1370 *
1371 * @returns The return value of the dialog's `click` event.
1372 *
1373 * @param {String} id The id of the button.
1374 */
1375 click: function( id ) {
1376 return this._.buttons[ id ].click();
1377 },
1378
1379 /**
1380 * Disables a dialog button.
1381 *
1382 * @param {String} id The id of the button.
1383 */
1384 disableButton: function( id ) {
1385 return this._.buttons[ id ].disable();
1386 },
1387
1388 /**
1389 * Enables a dialog button.
1390 *
1391 * @param {String} id The id of the button.
1392 */
1393 enableButton: function( id ) {
1394 return this._.buttons[ id ].enable();
1395 },
1396
1397 /**
1398 * Gets the number of pages in the dialog.
1399 *
1400 * @returns {Number} Page count.
1401 */
1402 getPageCount: function() {
1403 return this._.pageCount;
1404 },
1405
1406 /**
1407 * Gets the editor instance which opened this dialog.
1408 *
1409 * @returns {CKEDITOR.editor} Parent editor instances.
1410 */
1411 getParentEditor: function() {
1412 return this._.editor;
1413 },
1414
1415 /**
1416 * Gets the element that was selected when opening the dialog, if any.
1417 *
1418 * @returns {CKEDITOR.dom.element} The element that was selected, or `null`.
1419 */
1420 getSelectedElement: function() {
1421 return this.getParentEditor().getSelection().getSelectedElement();
1422 },
1423
1424 /**
1425 * Adds element to dialog's focusable list.
1426 *
1427 * @param {CKEDITOR.dom.element} element
1428 * @param {Number} [index]
1429 */
1430 addFocusable: function( element, index ) {
1431 if ( typeof index == 'undefined' ) {
1432 index = this._.focusList.length;
1433 this._.focusList.push( new Focusable( this, element, index ) );
1434 } else {
1435 this._.focusList.splice( index, 0, new Focusable( this, element, index ) );
1436 for ( var i = index + 1; i < this._.focusList.length; i++ )
1437 this._.focusList[ i ].focusIndex++;
1438 }
1439 },
1440
1441 /**
1442 * Sets the dialog {@link #property-state}.
1443 *
1444 * @since 4.5
1445 * @param {Number} state Either {@link CKEDITOR#DIALOG_STATE_IDLE} or {@link CKEDITOR#DIALOG_STATE_BUSY}.
1446 */
1447 setState: function( state ) {
1448 var oldState = this.state;
1449
1450 if ( oldState == state ) {
1451 return;
1452 }
1453
1454 this.state = state;
1455
1456 if ( state == CKEDITOR.DIALOG_STATE_BUSY ) {
1457 // Insert the spinner on demand.
1458 if ( !this.parts.spinner ) {
1459 var dir = this.getParentEditor().lang.dir,
1460 spinnerDef = {
1461 attributes: {
1462 'class': 'cke_dialog_spinner'
1463 },
1464 styles: {
1465 'float': dir == 'rtl' ? 'right' : 'left'
1466 }
1467 };
1468
1469 spinnerDef.styles[ 'margin-' + ( dir == 'rtl' ? 'left' : 'right' ) ] = '8px';
1470
1471 this.parts.spinner = CKEDITOR.document.createElement( 'div', spinnerDef );
1472
1473 this.parts.spinner.setHtml( '&#8987;' );
1474 this.parts.spinner.appendTo( this.parts.title, 1 );
1475 }
1476
1477 // Finally, show the spinner.
1478 this.parts.spinner.show();
1479
1480 this.getButton( 'ok' ).disable();
1481 } else if ( state == CKEDITOR.DIALOG_STATE_IDLE ) {
1482 // Hide the spinner. But don't do anything if there is no spinner yet.
1483 this.parts.spinner && this.parts.spinner.hide();
1484
1485 this.getButton( 'ok' ).enable();
1486 }
1487
1488 this.fire( 'state', state );
1489 }
1490 };
1491
1492 CKEDITOR.tools.extend( CKEDITOR.dialog, {
1493 /**
1494 * Registers a dialog.
1495 *
1496 * // Full sample plugin, which does not only register a dialog window but also adds an item to the context menu.
1497 * // To open the dialog window, choose "Open dialog" in the context menu.
1498 * CKEDITOR.plugins.add( 'myplugin', {
1499 * init: function( editor ) {
1500 * editor.addCommand( 'mydialog',new CKEDITOR.dialogCommand( 'mydialog' ) );
1501 *
1502 * if ( editor.contextMenu ) {
1503 * editor.addMenuGroup( 'mygroup', 10 );
1504 * editor.addMenuItem( 'My Dialog', {
1505 * label: 'Open dialog',
1506 * command: 'mydialog',
1507 * group: 'mygroup'
1508 * } );
1509 * editor.contextMenu.addListener( function( element ) {
1510 * return { 'My Dialog': CKEDITOR.TRISTATE_OFF };
1511 * } );
1512 * }
1513 *
1514 * CKEDITOR.dialog.add( 'mydialog', function( api ) {
1515 * // CKEDITOR.dialog.definition
1516 * var dialogDefinition = {
1517 * title: 'Sample dialog',
1518 * minWidth: 390,
1519 * minHeight: 130,
1520 * contents: [
1521 * {
1522 * id: 'tab1',
1523 * label: 'Label',
1524 * title: 'Title',
1525 * expand: true,
1526 * padding: 0,
1527 * elements: [
1528 * {
1529 * type: 'html',
1530 * html: '<p>This is some sample HTML content.</p>'
1531 * },
1532 * {
1533 * type: 'textarea',
1534 * id: 'textareaId',
1535 * rows: 4,
1536 * cols: 40
1537 * }
1538 * ]
1539 * }
1540 * ],
1541 * buttons: [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ],
1542 * onOk: function() {
1543 * // "this" is now a CKEDITOR.dialog object.
1544 * // Accessing dialog elements:
1545 * var textareaObj = this.getContentElement( 'tab1', 'textareaId' );
1546 * alert( "You have entered: " + textareaObj.getValue() );
1547 * }
1548 * };
1549 *
1550 * return dialogDefinition;
1551 * } );
1552 * }
1553 * } );
1554 *
1555 * CKEDITOR.replace( 'editor1', { extraPlugins: 'myplugin' } );
1556 *
1557 * @static
1558 * @param {String} name The dialog's name.
1559 * @param {Function/String} dialogDefinition
1560 * A function returning the dialog's definition, or the URL to the `.js` file holding the function.
1561 * The function should accept an argument `editor` which is the current editor instance, and
1562 * return an object conforming to {@link CKEDITOR.dialog.definition}.
1563 * @see CKEDITOR.dialog.definition
1564 */
1565 add: function( name, dialogDefinition ) {
1566 // Avoid path registration from multiple instances override definition.
1567 if ( !this._.dialogDefinitions[ name ] || typeof dialogDefinition == 'function' )
1568 this._.dialogDefinitions[ name ] = dialogDefinition;
1569 },
1570
1571 /**
1572 * @static
1573 * @todo
1574 */
1575 exists: function( name ) {
1576 return !!this._.dialogDefinitions[ name ];
1577 },
1578
1579 /**
1580 * @static
1581 * @todo
1582 */
1583 getCurrent: function() {
1584 return CKEDITOR.dialog._.currentTop;
1585 },
1586
1587 /**
1588 * Check whether tab wasn't removed by {@link CKEDITOR.config#removeDialogTabs}.
1589 *
1590 * @since 4.1
1591 * @static
1592 * @param {CKEDITOR.editor} editor
1593 * @param {String} dialogName
1594 * @param {String} tabName
1595 * @returns {Boolean}
1596 */
1597 isTabEnabled: function( editor, dialogName, tabName ) {
1598 var cfg = editor.config.removeDialogTabs;
1599
1600 return !( cfg && cfg.match( new RegExp( '(?:^|;)' + dialogName + ':' + tabName + '(?:$|;)', 'i' ) ) );
1601 },
1602
1603 /**
1604 * The default OK button for dialogs. Fires the `ok` event and closes the dialog if the event succeeds.
1605 *
1606 * @static
1607 * @method
1608 */
1609 okButton: ( function() {
1610 var retval = function( editor, override ) {
1611 override = override || {};
1612 return CKEDITOR.tools.extend( {
1613 id: 'ok',
1614 type: 'button',
1615 label: editor.lang.common.ok,
1616 'class': 'cke_dialog_ui_button_ok',
1617 onClick: function( evt ) {
1618 var dialog = evt.data.dialog;
1619 if ( dialog.fire( 'ok', { hide: true } ).hide !== false )
1620 dialog.hide();
1621 }
1622 }, override, true );
1623 };
1624 retval.type = 'button';
1625 retval.override = function( override ) {
1626 return CKEDITOR.tools.extend( function( editor ) {
1627 return retval( editor, override );
1628 }, { type: 'button' }, true );
1629 };
1630 return retval;
1631 } )(),
1632
1633 /**
1634 * The default cancel button for dialogs. Fires the `cancel` event and
1635 * closes the dialog if no UI element value changed.
1636 *
1637 * @static
1638 * @method
1639 */
1640 cancelButton: ( function() {
1641 var retval = function( editor, override ) {
1642 override = override || {};
1643 return CKEDITOR.tools.extend( {
1644 id: 'cancel',
1645 type: 'button',
1646 label: editor.lang.common.cancel,
1647 'class': 'cke_dialog_ui_button_cancel',
1648 onClick: function( evt ) {
1649 var dialog = evt.data.dialog;
1650 if ( dialog.fire( 'cancel', { hide: true } ).hide !== false )
1651 dialog.hide();
1652 }
1653 }, override, true );
1654 };
1655 retval.type = 'button';
1656 retval.override = function( override ) {
1657 return CKEDITOR.tools.extend( function( editor ) {
1658 return retval( editor, override );
1659 }, { type: 'button' }, true );
1660 };
1661 return retval;
1662 } )(),
1663
1664 /**
1665 * Registers a dialog UI element.
1666 *
1667 * @static
1668 * @param {String} typeName The name of the UI element.
1669 * @param {Function} builder The function to build the UI element.
1670 */
1671 addUIElement: function( typeName, builder ) {
1672 this._.uiElementBuilders[ typeName ] = builder;
1673 }
1674 } );
1675
1676 CKEDITOR.dialog._ = {
1677 uiElementBuilders: {},
1678
1679 dialogDefinitions: {},
1680
1681 currentTop: null,
1682
1683 currentZIndex: null
1684 };
1685
1686 // "Inherit" (copy actually) from CKEDITOR.event.
1687 CKEDITOR.event.implementOn( CKEDITOR.dialog );
1688 CKEDITOR.event.implementOn( CKEDITOR.dialog.prototype );
1689
1690 var defaultDialogDefinition = {
1691 resizable: CKEDITOR.DIALOG_RESIZE_BOTH,
1692 minWidth: 600,
1693 minHeight: 400,
1694 buttons: [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ]
1695 };
1696
1697 // Tool function used to return an item from an array based on its id
1698 // property.
1699 var getById = function( array, id, recurse ) {
1700 for ( var i = 0, item;
1701 ( item = array[ i ] ); i++ ) {
1702 if ( item.id == id )
1703 return item;
1704 if ( recurse && item[ recurse ] ) {
1705 var retval = getById( item[ recurse ], id, recurse );
1706 if ( retval )
1707 return retval;
1708 }
1709 }
1710 return null;
1711 };
1712
1713 // Tool function used to add an item into an array.
1714 var addById = function( array, newItem, nextSiblingId, recurse, nullIfNotFound ) {
1715 if ( nextSiblingId ) {
1716 for ( var i = 0, item;
1717 ( item = array[ i ] ); i++ ) {
1718 if ( item.id == nextSiblingId ) {
1719 array.splice( i, 0, newItem );
1720 return newItem;
1721 }
1722
1723 if ( recurse && item[ recurse ] ) {
1724 var retval = addById( item[ recurse ], newItem, nextSiblingId, recurse, true );
1725 if ( retval )
1726 return retval;
1727 }
1728 }
1729
1730 if ( nullIfNotFound )
1731 return null;
1732 }
1733
1734 array.push( newItem );
1735 return newItem;
1736 };
1737
1738 // Tool function used to remove an item from an array based on its id.
1739 var removeById = function( array, id, recurse ) {
1740 for ( var i = 0, item;
1741 ( item = array[ i ] ); i++ ) {
1742 if ( item.id == id )
1743 return array.splice( i, 1 );
1744 if ( recurse && item[ recurse ] ) {
1745 var retval = removeById( item[ recurse ], id, recurse );
1746 if ( retval )
1747 return retval;
1748 }
1749 }
1750 return null;
1751 };
1752
1753 /**
1754 * This class is not really part of the API. It is the `definition` property value
1755 * passed to `dialogDefinition` event handlers.
1756 *
1757 * CKEDITOR.on( 'dialogDefinition', function( evt ) {
1758 * var definition = evt.data.definition;
1759 * var content = definition.getContents( 'page1' );
1760 * // ...
1761 * } );
1762 *
1763 * @private
1764 * @class CKEDITOR.dialog.definitionObject
1765 * @extends CKEDITOR.dialog.definition
1766 * @constructor Creates a definitionObject class instance.
1767 */
1768 var definitionObject = function( dialog, dialogDefinition ) {
1769 // TODO : Check if needed.
1770 this.dialog = dialog;
1771
1772 // Transform the contents entries in contentObjects.
1773 var contents = dialogDefinition.contents;
1774 for ( var i = 0, content;
1775 ( content = contents[ i ] ); i++ )
1776 contents[ i ] = content && new contentObject( dialog, content );
1777
1778 CKEDITOR.tools.extend( this, dialogDefinition );
1779 };
1780
1781 definitionObject.prototype = {
1782 /**
1783 * Gets a content definition.
1784 *
1785 * @param {String} id The id of the content definition.
1786 * @returns {CKEDITOR.dialog.definition.content} The content definition matching id.
1787 */
1788 getContents: function( id ) {
1789 return getById( this.contents, id );
1790 },
1791
1792 /**
1793 * Gets a button definition.
1794 *
1795 * @param {String} id The id of the button definition.
1796 * @returns {CKEDITOR.dialog.definition.button} The button definition matching id.
1797 */
1798 getButton: function( id ) {
1799 return getById( this.buttons, id );
1800 },
1801
1802 /**
1803 * Adds a content definition object under this dialog definition.
1804 *
1805 * @param {CKEDITOR.dialog.definition.content} contentDefinition The
1806 * content definition.
1807 * @param {String} [nextSiblingId] The id of an existing content
1808 * definition which the new content definition will be inserted
1809 * before. Omit if the new content definition is to be inserted as
1810 * the last item.
1811 * @returns {CKEDITOR.dialog.definition.content} The inserted content definition.
1812 */
1813 addContents: function( contentDefinition, nextSiblingId ) {
1814 return addById( this.contents, contentDefinition, nextSiblingId );
1815 },
1816
1817 /**
1818 * Adds a button definition object under this dialog definition.
1819 *
1820 * @param {CKEDITOR.dialog.definition.button} buttonDefinition The
1821 * button definition.
1822 * @param {String} [nextSiblingId] The id of an existing button
1823 * definition which the new button definition will be inserted
1824 * before. Omit if the new button definition is to be inserted as
1825 * the last item.
1826 * @returns {CKEDITOR.dialog.definition.button} The inserted button definition.
1827 */
1828 addButton: function( buttonDefinition, nextSiblingId ) {
1829 return addById( this.buttons, buttonDefinition, nextSiblingId );
1830 },
1831
1832 /**
1833 * Removes a content definition from this dialog definition.
1834 *
1835 * @param {String} id The id of the content definition to be removed.
1836 * @returns {CKEDITOR.dialog.definition.content} The removed content definition.
1837 */
1838 removeContents: function( id ) {
1839 removeById( this.contents, id );
1840 },
1841
1842 /**
1843 * Removes a button definition from the dialog definition.
1844 *
1845 * @param {String} id The id of the button definition to be removed.
1846 * @returns {CKEDITOR.dialog.definition.button} The removed button definition.
1847 */
1848 removeButton: function( id ) {
1849 removeById( this.buttons, id );
1850 }
1851 };
1852
1853 /**
1854 * This class is not really part of the API. It is the template of the
1855 * objects representing content pages inside the
1856 * CKEDITOR.dialog.definitionObject.
1857 *
1858 * CKEDITOR.on( 'dialogDefinition', function( evt ) {
1859 * var definition = evt.data.definition;
1860 * var content = definition.getContents( 'page1' );
1861 * content.remove( 'textInput1' );
1862 * // ...
1863 * } );
1864 *
1865 * @private
1866 * @class CKEDITOR.dialog.definition.contentObject
1867 * @constructor Creates a contentObject class instance.
1868 */
1869 function contentObject( dialog, contentDefinition ) {
1870 this._ = {
1871 dialog: dialog
1872 };
1873
1874 CKEDITOR.tools.extend( this, contentDefinition );
1875 }
1876
1877 contentObject.prototype = {
1878 /**
1879 * Gets a UI element definition under the content definition.
1880 *
1881 * @param {String} id The id of the UI element definition.
1882 * @returns {CKEDITOR.dialog.definition.uiElement}
1883 */
1884 get: function( id ) {
1885 return getById( this.elements, id, 'children' );
1886 },
1887
1888 /**
1889 * Adds a UI element definition to the content definition.
1890 *
1891 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition The
1892 * UI elemnet definition to be added.
1893 * @param {String} nextSiblingId The id of an existing UI element
1894 * definition which the new UI element definition will be inserted
1895 * before. Omit if the new button definition is to be inserted as
1896 * the last item.
1897 * @returns {CKEDITOR.dialog.definition.uiElement} The element definition inserted.
1898 */
1899 add: function( elementDefinition, nextSiblingId ) {
1900 return addById( this.elements, elementDefinition, nextSiblingId, 'children' );
1901 },
1902
1903 /**
1904 * Removes a UI element definition from the content definition.
1905 *
1906 * @param {String} id The id of the UI element definition to be removed.
1907 * @returns {CKEDITOR.dialog.definition.uiElement} The element definition removed.
1908 */
1909 remove: function( id ) {
1910 removeById( this.elements, id, 'children' );
1911 }
1912 };
1913
1914 function initDragAndDrop( dialog ) {
1915 var lastCoords = null,
1916 abstractDialogCoords = null,
1917 editor = dialog.getParentEditor(),
1918 magnetDistance = editor.config.dialog_magnetDistance,
1919 margins = CKEDITOR.skin.margins || [ 0, 0, 0, 0 ];
1920
1921 if ( typeof magnetDistance == 'undefined' )
1922 magnetDistance = 20;
1923
1924 function mouseMoveHandler( evt ) {
1925 var dialogSize = dialog.getSize(),
1926 viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(),
1927 x = evt.data.$.screenX,
1928 y = evt.data.$.screenY,
1929 dx = x - lastCoords.x,
1930 dy = y - lastCoords.y,
1931 realX, realY;
1932
1933 lastCoords = { x: x, y: y };
1934 abstractDialogCoords.x += dx;
1935 abstractDialogCoords.y += dy;
1936
1937 if ( abstractDialogCoords.x + margins[ 3 ] < magnetDistance )
1938 realX = -margins[ 3 ];
1939 else if ( abstractDialogCoords.x - margins[ 1 ] > viewPaneSize.width - dialogSize.width - magnetDistance )
1940 realX = viewPaneSize.width - dialogSize.width + ( editor.lang.dir == 'rtl' ? 0 : margins[ 1 ] );
1941 else
1942 realX = abstractDialogCoords.x;
1943
1944 if ( abstractDialogCoords.y + margins[ 0 ] < magnetDistance )
1945 realY = -margins[ 0 ];
1946 else if ( abstractDialogCoords.y - margins[ 2 ] > viewPaneSize.height - dialogSize.height - magnetDistance )
1947 realY = viewPaneSize.height - dialogSize.height + margins[ 2 ];
1948 else
1949 realY = abstractDialogCoords.y;
1950
1951 dialog.move( realX, realY, 1 );
1952
1953 evt.data.preventDefault();
1954 }
1955
1956 function mouseUpHandler() {
1957 CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler );
1958 CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler );
1959
1960 if ( CKEDITOR.env.ie6Compat ) {
1961 var coverDoc = currentCover.getChild( 0 ).getFrameDocument();
1962 coverDoc.removeListener( 'mousemove', mouseMoveHandler );
1963 coverDoc.removeListener( 'mouseup', mouseUpHandler );
1964 }
1965 }
1966
1967 dialog.parts.title.on( 'mousedown', function( evt ) {
1968 lastCoords = { x: evt.data.$.screenX, y: evt.data.$.screenY };
1969
1970 CKEDITOR.document.on( 'mousemove', mouseMoveHandler );
1971 CKEDITOR.document.on( 'mouseup', mouseUpHandler );
1972 abstractDialogCoords = dialog.getPosition();
1973
1974 if ( CKEDITOR.env.ie6Compat ) {
1975 var coverDoc = currentCover.getChild( 0 ).getFrameDocument();
1976 coverDoc.on( 'mousemove', mouseMoveHandler );
1977 coverDoc.on( 'mouseup', mouseUpHandler );
1978 }
1979
1980 evt.data.preventDefault();
1981 }, dialog );
1982 }
1983
1984 function initResizeHandles( dialog ) {
1985 var def = dialog.definition,
1986 resizable = def.resizable;
1987
1988 if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE )
1989 return;
1990
1991 var editor = dialog.getParentEditor();
1992 var wrapperWidth, wrapperHeight, viewSize, origin, startSize, dialogCover;
1993
1994 var mouseDownFn = CKEDITOR.tools.addFunction( function( $event ) {
1995 startSize = dialog.getSize();
1996
1997 var content = dialog.parts.contents,
1998 iframeDialog = content.$.getElementsByTagName( 'iframe' ).length;
1999
2000 // Shim to help capturing "mousemove" over iframe.
2001 if ( iframeDialog ) {
2002 dialogCover = CKEDITOR.dom.element.createFromHtml( '<div class="cke_dialog_resize_cover" style="height: 100%; position: absolute; width: 100%;"></div>' );
2003 content.append( dialogCover );
2004 }
2005
2006 // Calculate the offset between content and chrome size.
2007 wrapperHeight = startSize.height - dialog.parts.contents.getSize( 'height', !( CKEDITOR.env.gecko || CKEDITOR.env.ie && CKEDITOR.env.quirks ) );
2008 wrapperWidth = startSize.width - dialog.parts.contents.getSize( 'width', 1 );
2009
2010 origin = { x: $event.screenX, y: $event.screenY };
2011
2012 viewSize = CKEDITOR.document.getWindow().getViewPaneSize();
2013
2014 CKEDITOR.document.on( 'mousemove', mouseMoveHandler );
2015 CKEDITOR.document.on( 'mouseup', mouseUpHandler );
2016
2017 if ( CKEDITOR.env.ie6Compat ) {
2018 var coverDoc = currentCover.getChild( 0 ).getFrameDocument();
2019 coverDoc.on( 'mousemove', mouseMoveHandler );
2020 coverDoc.on( 'mouseup', mouseUpHandler );
2021 }
2022
2023 $event.preventDefault && $event.preventDefault();
2024 } );
2025
2026 // Prepend the grip to the dialog.
2027 dialog.on( 'load', function() {
2028 var direction = '';
2029 if ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH )
2030 direction = ' cke_resizer_horizontal';
2031 else if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT )
2032 direction = ' cke_resizer_vertical';
2033 var resizer = CKEDITOR.dom.element.createFromHtml(
2034 '<div' +
2035 ' class="cke_resizer' + direction + ' cke_resizer_' + editor.lang.dir + '"' +
2036 ' title="' + CKEDITOR.tools.htmlEncode( editor.lang.common.resize ) + '"' +
2037 ' onmousedown="CKEDITOR.tools.callFunction(' + mouseDownFn + ', event )">' +
2038 // BLACK LOWER RIGHT TRIANGLE (ltr)
2039 // BLACK LOWER LEFT TRIANGLE (rtl)
2040 ( editor.lang.dir == 'ltr' ? '\u25E2' : '\u25E3' ) +
2041 '</div>' );
2042 dialog.parts.footer.append( resizer, 1 );
2043 } );
2044 editor.on( 'destroy', function() {
2045 CKEDITOR.tools.removeFunction( mouseDownFn );
2046 } );
2047
2048 function mouseMoveHandler( evt ) {
2049 var rtl = editor.lang.dir == 'rtl',
2050 dx = ( evt.data.$.screenX - origin.x ) * ( rtl ? -1 : 1 ),
2051 dy = evt.data.$.screenY - origin.y,
2052 width = startSize.width,
2053 height = startSize.height,
2054 internalWidth = width + dx * ( dialog._.moved ? 1 : 2 ),
2055 internalHeight = height + dy * ( dialog._.moved ? 1 : 2 ),
2056 element = dialog._.element.getFirst(),
2057 right = rtl && element.getComputedStyle( 'right' ),
2058 position = dialog.getPosition();
2059
2060 if ( position.y + internalHeight > viewSize.height )
2061 internalHeight = viewSize.height - position.y;
2062
2063 if ( ( rtl ? right : position.x ) + internalWidth > viewSize.width )
2064 internalWidth = viewSize.width - ( rtl ? right : position.x );
2065
2066 // Make sure the dialog will not be resized to the wrong side when it's in the leftmost position for RTL.
2067 if ( ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH || resizable == CKEDITOR.DIALOG_RESIZE_BOTH ) )
2068 width = Math.max( def.minWidth || 0, internalWidth - wrapperWidth );
2069
2070 if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT || resizable == CKEDITOR.DIALOG_RESIZE_BOTH )
2071 height = Math.max( def.minHeight || 0, internalHeight - wrapperHeight );
2072
2073 dialog.resize( width, height );
2074
2075 if ( !dialog._.moved )
2076 dialog.layout();
2077
2078 evt.data.preventDefault();
2079 }
2080
2081 function mouseUpHandler() {
2082 CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler );
2083 CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler );
2084
2085 if ( dialogCover ) {
2086 dialogCover.remove();
2087 dialogCover = null;
2088 }
2089
2090 if ( CKEDITOR.env.ie6Compat ) {
2091 var coverDoc = currentCover.getChild( 0 ).getFrameDocument();
2092 coverDoc.removeListener( 'mouseup', mouseUpHandler );
2093 coverDoc.removeListener( 'mousemove', mouseMoveHandler );
2094 }
2095 }
2096 }
2097
2098 var resizeCover;
2099 // Caching resuable covers and allowing only one cover
2100 // on screen.
2101 var covers = {},
2102 currentCover;
2103
2104 function cancelEvent( ev ) {
2105 ev.data.preventDefault( 1 );
2106 }
2107
2108 function showCover( editor ) {
2109 var win = CKEDITOR.document.getWindow(),
2110 config = editor.config,
2111 skinName = ( CKEDITOR.skinName || editor.config.skin ),
2112 backgroundColorStyle = config.dialog_backgroundCoverColor || ( skinName == 'moono-lisa' ? 'black' : 'white' ),
2113 backgroundCoverOpacity = config.dialog_backgroundCoverOpacity,
2114 baseFloatZIndex = config.baseFloatZIndex,
2115 coverKey = CKEDITOR.tools.genKey( backgroundColorStyle, backgroundCoverOpacity, baseFloatZIndex ),
2116 coverElement = covers[ coverKey ];
2117
2118 if ( !coverElement ) {
2119 var html = [
2120 '<div tabIndex="-1" style="position: ', ( CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed' ),
2121 '; z-index: ', baseFloatZIndex,
2122 '; top: 0px; left: 0px; ',
2123 ( !CKEDITOR.env.ie6Compat ? 'background-color: ' + backgroundColorStyle : '' ),
2124 '" class="cke_dialog_background_cover">'
2125 ];
2126
2127 if ( CKEDITOR.env.ie6Compat ) {
2128 // Support for custom document.domain in IE.
2129 var iframeHtml = '<html><body style=\\\'background-color:' + backgroundColorStyle + ';\\\'></body></html>';
2130
2131 html.push( '<iframe' +
2132 ' hidefocus="true"' +
2133 ' frameborder="0"' +
2134 ' id="cke_dialog_background_iframe"' +
2135 ' src="javascript:' );
2136
2137 html.push( 'void((function(){' + encodeURIComponent(
2138 'document.open();' +
2139 // Support for custom document.domain in IE.
2140 '(' + CKEDITOR.tools.fixDomain + ')();' +
2141 'document.write( \'' + iframeHtml + '\' );' +
2142 'document.close();'
2143 ) + '})())' );
2144
2145 html.push( '"' +
2146 ' style="' +
2147 'position:absolute;' +
2148 'left:0;' +
2149 'top:0;' +
2150 'width:100%;' +
2151 'height: 100%;' +
2152 'filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0)">' +
2153 '</iframe>' );
2154 }
2155
2156 html.push( '</div>' );
2157
2158 coverElement = CKEDITOR.dom.element.createFromHtml( html.join( '' ) );
2159 coverElement.setOpacity( backgroundCoverOpacity !== undefined ? backgroundCoverOpacity : 0.5 );
2160
2161 coverElement.on( 'keydown', cancelEvent );
2162 coverElement.on( 'keypress', cancelEvent );
2163 coverElement.on( 'keyup', cancelEvent );
2164
2165 coverElement.appendTo( CKEDITOR.document.getBody() );
2166 covers[ coverKey ] = coverElement;
2167 } else {
2168 coverElement.show();
2169 }
2170
2171 // Makes the dialog cover a focus holder as well.
2172 editor.focusManager.add( coverElement );
2173
2174 currentCover = coverElement;
2175 var resizeFunc = function() {
2176 var size = win.getViewPaneSize();
2177 coverElement.setStyles( {
2178 width: size.width + 'px',
2179 height: size.height + 'px'
2180 } );
2181 };
2182
2183 var scrollFunc = function() {
2184 var pos = win.getScrollPosition(),
2185 cursor = CKEDITOR.dialog._.currentTop;
2186 coverElement.setStyles( {
2187 left: pos.x + 'px',
2188 top: pos.y + 'px'
2189 } );
2190
2191 if ( cursor ) {
2192 do {
2193 var dialogPos = cursor.getPosition();
2194 cursor.move( dialogPos.x, dialogPos.y );
2195 } while ( ( cursor = cursor._.parentDialog ) );
2196 }
2197 };
2198
2199 resizeCover = resizeFunc;
2200 win.on( 'resize', resizeFunc );
2201 resizeFunc();
2202 // Using Safari/Mac, focus must be kept where it is (#7027)
2203 if ( !( CKEDITOR.env.mac && CKEDITOR.env.webkit ) )
2204 coverElement.focus();
2205
2206 if ( CKEDITOR.env.ie6Compat ) {
2207 // IE BUG: win.$.onscroll assignment doesn't work.. it must be window.onscroll.
2208 // So we need to invent a really funny way to make it work.
2209 var myScrollHandler = function() {
2210 scrollFunc();
2211 arguments.callee.prevScrollHandler.apply( this, arguments );
2212 };
2213 win.$.setTimeout( function() {
2214 myScrollHandler.prevScrollHandler = window.onscroll ||
2215 function() {};
2216 window.onscroll = myScrollHandler;
2217 }, 0 );
2218 scrollFunc();
2219 }
2220 }
2221
2222 function hideCover( editor ) {
2223 if ( !currentCover )
2224 return;
2225
2226 editor.focusManager.remove( currentCover );
2227 var win = CKEDITOR.document.getWindow();
2228 currentCover.hide();
2229 win.removeListener( 'resize', resizeCover );
2230
2231 if ( CKEDITOR.env.ie6Compat ) {
2232 win.$.setTimeout( function() {
2233 var prevScrollHandler = window.onscroll && window.onscroll.prevScrollHandler;
2234 window.onscroll = prevScrollHandler || null;
2235 }, 0 );
2236 }
2237 resizeCover = null;
2238 }
2239
2240 function removeCovers() {
2241 for ( var coverId in covers )
2242 covers[ coverId ].remove();
2243 covers = {};
2244 }
2245
2246 var accessKeyProcessors = {};
2247
2248 var accessKeyDownHandler = function( evt ) {
2249 var ctrl = evt.data.$.ctrlKey || evt.data.$.metaKey,
2250 alt = evt.data.$.altKey,
2251 shift = evt.data.$.shiftKey,
2252 key = String.fromCharCode( evt.data.$.keyCode ),
2253 keyProcessor = accessKeyProcessors[ ( ctrl ? 'CTRL+' : '' ) + ( alt ? 'ALT+' : '' ) + ( shift ? 'SHIFT+' : '' ) + key ];
2254
2255 if ( !keyProcessor || !keyProcessor.length )
2256 return;
2257
2258 keyProcessor = keyProcessor[ keyProcessor.length - 1 ];
2259 keyProcessor.keydown && keyProcessor.keydown.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key );
2260 evt.data.preventDefault();
2261 };
2262
2263 var accessKeyUpHandler = function( evt ) {
2264 var ctrl = evt.data.$.ctrlKey || evt.data.$.metaKey,
2265 alt = evt.data.$.altKey,
2266 shift = evt.data.$.shiftKey,
2267 key = String.fromCharCode( evt.data.$.keyCode ),
2268 keyProcessor = accessKeyProcessors[ ( ctrl ? 'CTRL+' : '' ) + ( alt ? 'ALT+' : '' ) + ( shift ? 'SHIFT+' : '' ) + key ];
2269
2270 if ( !keyProcessor || !keyProcessor.length )
2271 return;
2272
2273 keyProcessor = keyProcessor[ keyProcessor.length - 1 ];
2274 if ( keyProcessor.keyup ) {
2275 keyProcessor.keyup.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key );
2276 evt.data.preventDefault();
2277 }
2278 };
2279
2280 var registerAccessKey = function( uiElement, dialog, key, downFunc, upFunc ) {
2281 var procList = accessKeyProcessors[ key ] || ( accessKeyProcessors[ key ] = [] );
2282 procList.push( {
2283 uiElement: uiElement,
2284 dialog: dialog,
2285 key: key,
2286 keyup: upFunc || uiElement.accessKeyUp,
2287 keydown: downFunc || uiElement.accessKeyDown
2288 } );
2289 };
2290
2291 var unregisterAccessKey = function( obj ) {
2292 for ( var i in accessKeyProcessors ) {
2293 var list = accessKeyProcessors[ i ];
2294 for ( var j = list.length - 1; j >= 0; j-- ) {
2295 if ( list[ j ].dialog == obj || list[ j ].uiElement == obj )
2296 list.splice( j, 1 );
2297 }
2298 if ( list.length === 0 )
2299 delete accessKeyProcessors[ i ];
2300 }
2301 };
2302
2303 var tabAccessKeyUp = function( dialog, key ) {
2304 if ( dialog._.accessKeyMap[ key ] )
2305 dialog.selectPage( dialog._.accessKeyMap[ key ] );
2306 };
2307
2308 var tabAccessKeyDown = function() {};
2309
2310 ( function() {
2311 CKEDITOR.ui.dialog = {
2312 /**
2313 * The base class of all dialog UI elements.
2314 *
2315 * @class CKEDITOR.ui.dialog.uiElement
2316 * @constructor Creates a uiElement class instance.
2317 * @param {CKEDITOR.dialog} dialog Parent dialog object.
2318 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition Element
2319 * definition.
2320 *
2321 * Accepted fields:
2322 *
2323 * * `id` (Required) The id of the UI element. See {@link CKEDITOR.dialog#getContentElement}.
2324 * * `type` (Required) The type of the UI element. The
2325 * value to this field specifies which UI element class will be used to
2326 * generate the final widget.
2327 * * `title` (Optional) The popup tooltip for the UI
2328 * element.
2329 * * `hidden` (Optional) A flag that tells if the element
2330 * should be initially visible.
2331 * * `className` (Optional) Additional CSS class names
2332 * to add to the UI element. Separated by space.
2333 * * `style` (Optional) Additional CSS inline styles
2334 * to add to the UI element. A semicolon (;) is required after the last
2335 * style declaration.
2336 * * `accessKey` (Optional) The alphanumeric access key
2337 * for this element. Access keys are automatically prefixed by CTRL.
2338 * * `on*` (Optional) Any UI element definition field that
2339 * starts with `on` followed immediately by a capital letter and
2340 * probably more letters is an event handler. Event handlers may be further
2341 * divided into registered event handlers and DOM event handlers. Please
2342 * refer to {@link CKEDITOR.ui.dialog.uiElement#registerEvents} and
2343 * {@link CKEDITOR.ui.dialog.uiElement#eventProcessors} for more information.
2344 *
2345 * @param {Array} htmlList
2346 * List of HTML code to be added to the dialog's content area.
2347 * @param {Function/String} [nodeNameArg='div']
2348 * A function returning a string, or a simple string for the node name for
2349 * the root DOM node.
2350 * @param {Function/Object} [stylesArg={}]
2351 * A function returning an object, or a simple object for CSS styles applied
2352 * to the DOM node.
2353 * @param {Function/Object} [attributesArg={}]
2354 * A fucntion returning an object, or a simple object for attributes applied
2355 * to the DOM node.
2356 * @param {Function/String} [contentsArg='']
2357 * A function returning a string, or a simple string for the HTML code inside
2358 * the root DOM node. Default is empty string.
2359 */
2360 uiElement: function( dialog, elementDefinition, htmlList, nodeNameArg, stylesArg, attributesArg, contentsArg ) {
2361 if ( arguments.length < 4 )
2362 return;
2363
2364 var nodeName = ( nodeNameArg.call ? nodeNameArg( elementDefinition ) : nodeNameArg ) || 'div',
2365 html = [ '<', nodeName, ' ' ],
2366 styles = ( stylesArg && stylesArg.call ? stylesArg( elementDefinition ) : stylesArg ) || {},
2367 attributes = ( attributesArg && attributesArg.call ? attributesArg( elementDefinition ) : attributesArg ) || {},
2368 innerHTML = ( contentsArg && contentsArg.call ? contentsArg.call( this, dialog, elementDefinition ) : contentsArg ) || '',
2369 domId = this.domId = attributes.id || CKEDITOR.tools.getNextId() + '_uiElement',
2370 i;
2371
2372 if ( elementDefinition.requiredContent && !dialog.getParentEditor().filter.check( elementDefinition.requiredContent ) ) {
2373 styles.display = 'none';
2374 this.notAllowed = true;
2375 }
2376
2377 // Set the id, a unique id is required for getElement() to work.
2378 attributes.id = domId;
2379
2380 // Set the type and definition CSS class names.
2381 var classes = {};
2382 if ( elementDefinition.type )
2383 classes[ 'cke_dialog_ui_' + elementDefinition.type ] = 1;
2384 if ( elementDefinition.className )
2385 classes[ elementDefinition.className ] = 1;
2386 if ( elementDefinition.disabled )
2387 classes.cke_disabled = 1;
2388
2389 var attributeClasses = ( attributes[ 'class' ] && attributes[ 'class' ].split ) ? attributes[ 'class' ].split( ' ' ) : [];
2390 for ( i = 0; i < attributeClasses.length; i++ ) {
2391 if ( attributeClasses[ i ] )
2392 classes[ attributeClasses[ i ] ] = 1;
2393 }
2394 var finalClasses = [];
2395 for ( i in classes )
2396 finalClasses.push( i );
2397 attributes[ 'class' ] = finalClasses.join( ' ' );
2398
2399 // Set the popup tooltop.
2400 if ( elementDefinition.title )
2401 attributes.title = elementDefinition.title;
2402
2403 // Write the inline CSS styles.
2404 var styleStr = ( elementDefinition.style || '' ).split( ';' );
2405
2406 // Element alignment support.
2407 if ( elementDefinition.align ) {
2408 var align = elementDefinition.align;
2409 styles[ 'margin-left' ] = align == 'left' ? 0 : 'auto';
2410 styles[ 'margin-right' ] = align == 'right' ? 0 : 'auto';
2411 }
2412
2413 for ( i in styles )
2414 styleStr.push( i + ':' + styles[ i ] );
2415 if ( elementDefinition.hidden )
2416 styleStr.push( 'display:none' );
2417 for ( i = styleStr.length - 1; i >= 0; i-- ) {
2418 if ( styleStr[ i ] === '' )
2419 styleStr.splice( i, 1 );
2420 }
2421 if ( styleStr.length > 0 )
2422 attributes.style = ( attributes.style ? ( attributes.style + '; ' ) : '' ) + styleStr.join( '; ' );
2423
2424 // Write the attributes.
2425 for ( i in attributes )
2426 html.push( i + '="' + CKEDITOR.tools.htmlEncode( attributes[ i ] ) + '" ' );
2427
2428 // Write the content HTML.
2429 html.push( '>', innerHTML, '</', nodeName, '>' );
2430
2431 // Add contents to the parent HTML array.
2432 htmlList.push( html.join( '' ) );
2433
2434 ( this._ || ( this._ = {} ) ).dialog = dialog;
2435
2436 // Override isChanged if it is defined in element definition.
2437 if ( typeof elementDefinition.isChanged == 'boolean' )
2438 this.isChanged = function() {
2439 return elementDefinition.isChanged;
2440 };
2441 if ( typeof elementDefinition.isChanged == 'function' )
2442 this.isChanged = elementDefinition.isChanged;
2443
2444 // Overload 'get(set)Value' on definition.
2445 if ( typeof elementDefinition.setValue == 'function' ) {
2446 this.setValue = CKEDITOR.tools.override( this.setValue, function( org ) {
2447 return function( val ) {
2448 org.call( this, elementDefinition.setValue.call( this, val ) );
2449 };
2450 } );
2451 }
2452
2453 if ( typeof elementDefinition.getValue == 'function' ) {
2454 this.getValue = CKEDITOR.tools.override( this.getValue, function( org ) {
2455 return function() {
2456 return elementDefinition.getValue.call( this, org.call( this ) );
2457 };
2458 } );
2459 }
2460
2461 // Add events.
2462 CKEDITOR.event.implementOn( this );
2463
2464 this.registerEvents( elementDefinition );
2465 if ( this.accessKeyUp && this.accessKeyDown && elementDefinition.accessKey )
2466 registerAccessKey( this, dialog, 'CTRL+' + elementDefinition.accessKey );
2467
2468 var me = this;
2469 dialog.on( 'load', function() {
2470 var input = me.getInputElement();
2471 if ( input ) {
2472 var focusClass = me.type in { 'checkbox': 1, 'ratio': 1 } && CKEDITOR.env.ie && CKEDITOR.env.version < 8 ? 'cke_dialog_ui_focused' : '';
2473 input.on( 'focus', function() {
2474 dialog._.tabBarMode = false;
2475 dialog._.hasFocus = true;
2476 me.fire( 'focus' );
2477 focusClass && this.addClass( focusClass );
2478
2479 } );
2480
2481 input.on( 'blur', function() {
2482 me.fire( 'blur' );
2483 focusClass && this.removeClass( focusClass );
2484 } );
2485 }
2486 } );
2487
2488 // Completes this object with everything we have in the
2489 // definition.
2490 CKEDITOR.tools.extend( this, elementDefinition );
2491
2492 // Register the object as a tab focus if it can be included.
2493 if ( this.keyboardFocusable ) {
2494 this.tabIndex = elementDefinition.tabIndex || 0;
2495
2496 this.focusIndex = dialog._.focusList.push( this ) - 1;
2497 this.on( 'focus', function() {
2498 dialog._.currentFocusIndex = me.focusIndex;
2499 } );
2500 }
2501 },
2502
2503 /**
2504 * Horizontal layout box for dialog UI elements, auto-expends to available width of container.
2505 *
2506 * @class CKEDITOR.ui.dialog.hbox
2507 * @extends CKEDITOR.ui.dialog.uiElement
2508 * @constructor Creates a hbox class instance.
2509 * @param {CKEDITOR.dialog} dialog Parent dialog object.
2510 * @param {Array} childObjList
2511 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container.
2512 * @param {Array} childHtmlList
2513 * Array of HTML code that correspond to the HTML output of all the
2514 * objects in childObjList.
2515 * @param {Array} htmlList
2516 * Array of HTML code that this element will output to.
2517 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
2518 * The element definition. Accepted fields:
2519 *
2520 * * `widths` (Optional) The widths of child cells.
2521 * * `height` (Optional) The height of the layout.
2522 * * `padding` (Optional) The padding width inside child cells.
2523 * * `align` (Optional) The alignment of the whole layout.
2524 */
2525 hbox: function( dialog, childObjList, childHtmlList, htmlList, elementDefinition ) {
2526 if ( arguments.length < 4 )
2527 return;
2528
2529 this._ || ( this._ = {} );
2530
2531 var children = this._.children = childObjList,
2532 widths = elementDefinition && elementDefinition.widths || null,
2533 height = elementDefinition && elementDefinition.height || null,
2534 styles = {},
2535 i;
2536 /** @ignore */
2537 var innerHTML = function() {
2538 var html = [ '<tbody><tr class="cke_dialog_ui_hbox">' ];
2539 for ( i = 0; i < childHtmlList.length; i++ ) {
2540 var className = 'cke_dialog_ui_hbox_child',
2541 styles = [];
2542 if ( i === 0 ) {
2543 className = 'cke_dialog_ui_hbox_first';
2544 }
2545 if ( i == childHtmlList.length - 1 ) {
2546 className = 'cke_dialog_ui_hbox_last';
2547 }
2548
2549 html.push( '<td class="', className, '" role="presentation" ' );
2550 if ( widths ) {
2551 if ( widths[ i ] ) {
2552 styles.push( 'width:' + cssLength( widths[i] ) );
2553 }
2554 } else {
2555 styles.push( 'width:' + Math.floor( 100 / childHtmlList.length ) + '%' );
2556 }
2557 if ( height ) {
2558 styles.push( 'height:' + cssLength( height ) );
2559 }
2560 if ( elementDefinition && elementDefinition.padding !== undefined ) {
2561 styles.push( 'padding:' + cssLength( elementDefinition.padding ) );
2562 }
2563 // In IE Quirks alignment has to be done on table cells. (#7324)
2564 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align ) {
2565 styles.push( 'text-align:' + children[ i ].align );
2566 }
2567 if ( styles.length > 0 ) {
2568 html.push( 'style="' + styles.join( '; ' ) + '" ' );
2569 }
2570 html.push( '>', childHtmlList[ i ], '</td>' );
2571 }
2572 html.push( '</tr></tbody>' );
2573 return html.join( '' );
2574 };
2575
2576 var attribs = { role: 'presentation' };
2577 elementDefinition && elementDefinition.align && ( attribs.align = elementDefinition.align );
2578
2579 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition || { type: 'hbox' }, htmlList, 'table', styles, attribs, innerHTML );
2580 },
2581
2582 /**
2583 * Vertical layout box for dialog UI elements.
2584 *
2585 * @class CKEDITOR.ui.dialog.vbox
2586 * @extends CKEDITOR.ui.dialog.hbox
2587 * @constructor Creates a vbox class instance.
2588 * @param {CKEDITOR.dialog} dialog Parent dialog object.
2589 * @param {Array} childObjList
2590 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container.
2591 * @param {Array} childHtmlList
2592 * Array of HTML code that correspond to the HTML output of all the
2593 * objects in childObjList.
2594 * @param {Array} htmlList Array of HTML code that this element will output to.
2595 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
2596 * The element definition. Accepted fields:
2597 *
2598 * * `width` (Optional) The width of the layout.
2599 * * `heights` (Optional) The heights of individual cells.
2600 * * `align` (Optional) The alignment of the layout.
2601 * * `padding` (Optional) The padding width inside child cells.
2602 * * `expand` (Optional) Whether the layout should expand
2603 * vertically to fill its container.
2604 */
2605 vbox: function( dialog, childObjList, childHtmlList, htmlList, elementDefinition ) {
2606 if ( arguments.length < 3 )
2607 return;
2608
2609 this._ || ( this._ = {} );
2610
2611 var children = this._.children = childObjList,
2612 width = elementDefinition && elementDefinition.width || null,
2613 heights = elementDefinition && elementDefinition.heights || null;
2614 /** @ignore */
2615 var innerHTML = function() {
2616 var html = [ '<table role="presentation" cellspacing="0" border="0" ' ];
2617 html.push( 'style="' );
2618 if ( elementDefinition && elementDefinition.expand )
2619 html.push( 'height:100%;' );
2620 html.push( 'width:' + cssLength( width || '100%' ), ';' );
2621
2622 // (#10123) Temp fix for dialog broken layout in latest webkit.
2623 if ( CKEDITOR.env.webkit )
2624 html.push( 'float:none;' );
2625
2626 html.push( '"' );
2627 html.push( 'align="', CKEDITOR.tools.htmlEncode(
2628 ( elementDefinition && elementDefinition.align ) || ( dialog.getParentEditor().lang.dir == 'ltr' ? 'left' : 'right' ) ), '" ' );
2629
2630 html.push( '><tbody>' );
2631 for ( var i = 0; i < childHtmlList.length; i++ ) {
2632 var styles = [];
2633 html.push( '<tr><td role="presentation" ' );
2634 if ( width )
2635 styles.push( 'width:' + cssLength( width || '100%' ) );
2636 if ( heights )
2637 styles.push( 'height:' + cssLength( heights[ i ] ) );
2638 else if ( elementDefinition && elementDefinition.expand )
2639 styles.push( 'height:' + Math.floor( 100 / childHtmlList.length ) + '%' );
2640 if ( elementDefinition && elementDefinition.padding !== undefined )
2641 styles.push( 'padding:' + cssLength( elementDefinition.padding ) );
2642 // In IE Quirks alignment has to be done on table cells. (#7324)
2643 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align )
2644 styles.push( 'text-align:' + children[ i ].align );
2645 if ( styles.length > 0 )
2646 html.push( 'style="', styles.join( '; ' ), '" ' );
2647 html.push( ' class="cke_dialog_ui_vbox_child">', childHtmlList[ i ], '</td></tr>' );
2648 }
2649 html.push( '</tbody></table>' );
2650 return html.join( '' );
2651 };
2652 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition || { type: 'vbox' }, htmlList, 'div', null, { role: 'presentation' }, innerHTML );
2653 }
2654 };
2655 } )();
2656
2657 /** @class CKEDITOR.ui.dialog.uiElement */
2658 CKEDITOR.ui.dialog.uiElement.prototype = {
2659 /**
2660 * Gets the root DOM element of this dialog UI object.
2661 *
2662 * uiElement.getElement().hide();
2663 *
2664 * @returns {CKEDITOR.dom.element} Root DOM element of UI object.
2665 */
2666 getElement: function() {
2667 return CKEDITOR.document.getById( this.domId );
2668 },
2669
2670 /**
2671 * Gets the DOM element that the user inputs values.
2672 *
2673 * This function is used by {@link #setValue}, {@link #getValue} and {@link #focus}. It should
2674 * be overrided in child classes where the input element isn't the root
2675 * element.
2676 *
2677 * var rawValue = textInput.getInputElement().$.value;
2678 *
2679 * @returns {CKEDITOR.dom.element} The element where the user input values.
2680 */
2681 getInputElement: function() {
2682 return this.getElement();
2683 },
2684
2685 /**
2686 * Gets the parent dialog object containing this UI element.
2687 *
2688 * var dialog = uiElement.getDialog();
2689 *
2690 * @returns {CKEDITOR.dialog} Parent dialog object.
2691 */
2692 getDialog: function() {
2693 return this._.dialog;
2694 },
2695
2696 /**
2697 * Sets the value of this dialog UI object.
2698 *
2699 * uiElement.setValue( 'Dingo' );
2700 *
2701 * @chainable
2702 * @param {Object} value The new value.
2703 * @param {Boolean} noChangeEvent Internal commit, to supress `change` event on this element.
2704 */
2705 setValue: function( value, noChangeEvent ) {
2706 this.getInputElement().setValue( value );
2707 !noChangeEvent && this.fire( 'change', { value: value } );
2708 return this;
2709 },
2710
2711 /**
2712 * Gets the current value of this dialog UI object.
2713 *
2714 * var myValue = uiElement.getValue();
2715 *
2716 * @returns {Object} The current value.
2717 */
2718 getValue: function() {
2719 return this.getInputElement().getValue();
2720 },
2721
2722 /**
2723 * Tells whether the UI object's value has changed.
2724 *
2725 * if ( uiElement.isChanged() )
2726 * confirm( 'Value changed! Continue?' );
2727 *
2728 * @returns {Boolean} `true` if changed, `false` if not changed.
2729 */
2730 isChanged: function() {
2731 // Override in input classes.
2732 return false;
2733 },
2734
2735 /**
2736 * Selects the parent tab of this element. Usually called by focus() or overridden focus() methods.
2737 *
2738 * focus : function() {
2739 * this.selectParentTab();
2740 * // do something else.
2741 * }
2742 *
2743 * @chainable
2744 */
2745 selectParentTab: function() {
2746 var element = this.getInputElement(),
2747 cursor = element,
2748 tabId;
2749 while ( ( cursor = cursor.getParent() ) && cursor.$.className.search( 'cke_dialog_page_contents' ) == -1 ) {
2750
2751 }
2752
2753 // Some widgets don't have parent tabs (e.g. OK and Cancel buttons).
2754 if ( !cursor )
2755 return this;
2756
2757 tabId = cursor.getAttribute( 'name' );
2758 // Avoid duplicate select.
2759 if ( this._.dialog._.currentTabId != tabId )
2760 this._.dialog.selectPage( tabId );
2761 return this;
2762 },
2763
2764 /**
2765 * Puts the focus to the UI object. Switches tabs if the UI object isn't in the active tab page.
2766 *
2767 * uiElement.focus();
2768 *
2769 * @chainable
2770 */
2771 focus: function() {
2772 this.selectParentTab().getInputElement().focus();
2773 return this;
2774 },
2775
2776 /**
2777 * Registers the `on*` event handlers defined in the element definition.
2778 *
2779 * The default behavior of this function is:
2780 *
2781 * 1. If the on* event is defined in the class's eventProcesors list,
2782 * then the registration is delegated to the corresponding function
2783 * in the eventProcessors list.
2784 * 2. If the on* event is not defined in the eventProcessors list, then
2785 * register the event handler under the corresponding DOM event of
2786 * the UI element's input DOM element (as defined by the return value
2787 * of {@link #getInputElement}).
2788 *
2789 * This function is only called at UI element instantiation, but can
2790 * be overridded in child classes if they require more flexibility.
2791 *
2792 * @chainable
2793 * @param {CKEDITOR.dialog.definition.uiElement} definition The UI element
2794 * definition.
2795 */
2796 registerEvents: function( definition ) {
2797 var regex = /^on([A-Z]\w+)/,
2798 match;
2799
2800 var registerDomEvent = function( uiElement, dialog, eventName, func ) {
2801 dialog.on( 'load', function() {
2802 uiElement.getInputElement().on( eventName, func, uiElement );
2803 } );
2804 };
2805
2806 for ( var i in definition ) {
2807 if ( !( match = i.match( regex ) ) )
2808 continue;
2809 if ( this.eventProcessors[ i ] )
2810 this.eventProcessors[ i ].call( this, this._.dialog, definition[ i ] );
2811 else
2812 registerDomEvent( this, this._.dialog, match[ 1 ].toLowerCase(), definition[ i ] );
2813 }
2814
2815 return this;
2816 },
2817
2818 /**
2819 * The event processor list used by
2820 * {@link CKEDITOR.ui.dialog.uiElement#getInputElement} at UI element
2821 * instantiation. The default list defines three `on*` events:
2822 *
2823 * 1. `onLoad` - Called when the element's parent dialog opens for the
2824 * first time.
2825 * 2. `onShow` - Called whenever the element's parent dialog opens.
2826 * 3. `onHide` - Called whenever the element's parent dialog closes.
2827 *
2828 * // This connects the 'click' event in CKEDITOR.ui.dialog.button to onClick
2829 * // handlers in the UI element's definitions.
2830 * CKEDITOR.ui.dialog.button.eventProcessors = CKEDITOR.tools.extend( {},
2831 * CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,
2832 * { onClick : function( dialog, func ) { this.on( 'click', func ); } },
2833 * true
2834 * );
2835 *
2836 * @property {Object}
2837 */
2838 eventProcessors: {
2839 onLoad: function( dialog, func ) {
2840 dialog.on( 'load', func, this );
2841 },
2842
2843 onShow: function( dialog, func ) {
2844 dialog.on( 'show', func, this );
2845 },
2846
2847 onHide: function( dialog, func ) {
2848 dialog.on( 'hide', func, this );
2849 }
2850 },
2851
2852 /**
2853 * The default handler for a UI element's access key down event, which
2854 * tries to put focus to the UI element.
2855 *
2856 * Can be overridded in child classes for more sophisticaed behavior.
2857 *
2858 * @param {CKEDITOR.dialog} dialog The parent dialog object.
2859 * @param {String} key The key combination pressed. Since access keys
2860 * are defined to always include the `CTRL` key, its value should always
2861 * include a `'CTRL+'` prefix.
2862 */
2863 accessKeyDown: function() {
2864 this.focus();
2865 },
2866
2867 /**
2868 * The default handler for a UI element's access key up event, which
2869 * does nothing.
2870 *
2871 * Can be overridded in child classes for more sophisticated behavior.
2872 *
2873 * @param {CKEDITOR.dialog} dialog The parent dialog object.
2874 * @param {String} key The key combination pressed. Since access keys
2875 * are defined to always include the `CTRL` key, its value should always
2876 * include a `'CTRL+'` prefix.
2877 */
2878 accessKeyUp: function() {},
2879
2880 /**
2881 * Disables a UI element.
2882 */
2883 disable: function() {
2884 var element = this.getElement(),
2885 input = this.getInputElement();
2886 input.setAttribute( 'disabled', 'true' );
2887 element.addClass( 'cke_disabled' );
2888 },
2889
2890 /**
2891 * Enables a UI element.
2892 */
2893 enable: function() {
2894 var element = this.getElement(),
2895 input = this.getInputElement();
2896 input.removeAttribute( 'disabled' );
2897 element.removeClass( 'cke_disabled' );
2898 },
2899
2900 /**
2901 * Determines whether an UI element is enabled or not.
2902 *
2903 * @returns {Boolean} Whether the UI element is enabled.
2904 */
2905 isEnabled: function() {
2906 return !this.getElement().hasClass( 'cke_disabled' );
2907 },
2908
2909 /**
2910 * Determines whether an UI element is visible or not.
2911 *
2912 * @returns {Boolean} Whether the UI element is visible.
2913 */
2914 isVisible: function() {
2915 return this.getInputElement().isVisible();
2916 },
2917
2918 /**
2919 * Determines whether an UI element is focus-able or not.
2920 * Focus-able is defined as being both visible and enabled.
2921 *
2922 * @returns {Boolean} Whether the UI element can be focused.
2923 */
2924 isFocusable: function() {
2925 if ( !this.isEnabled() || !this.isVisible() )
2926 return false;
2927 return true;
2928 }
2929 };
2930
2931 /** @class CKEDITOR.ui.dialog.hbox */
2932 CKEDITOR.ui.dialog.hbox.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement(), {
2933 /**
2934 * Gets a child UI element inside this container.
2935 *
2936 * var checkbox = hbox.getChild( [0,1] );
2937 * checkbox.setValue( true );
2938 *
2939 * @param {Array/Number} indices An array or a single number to indicate the child's
2940 * position in the container's descendant tree. Omit to get all the children in an array.
2941 * @returns {Array/CKEDITOR.ui.dialog.uiElement} Array of all UI elements in the container
2942 * if no argument given, or the specified UI element if indices is given.
2943 */
2944 getChild: function( indices ) {
2945 // If no arguments, return a clone of the children array.
2946 if ( arguments.length < 1 )
2947 return this._.children.concat();
2948
2949 // If indices isn't array, make it one.
2950 if ( !indices.splice )
2951 indices = [ indices ];
2952
2953 // Retrieve the child element according to tree position.
2954 if ( indices.length < 2 )
2955 return this._.children[ indices[ 0 ] ];
2956 else
2957 return ( this._.children[ indices[ 0 ] ] && this._.children[ indices[ 0 ] ].getChild ) ? this._.children[ indices[ 0 ] ].getChild( indices.slice( 1, indices.length ) ) : null;
2958 }
2959 }, true );
2960
2961 CKEDITOR.ui.dialog.vbox.prototype = new CKEDITOR.ui.dialog.hbox();
2962
2963 ( function() {
2964 var commonBuilder = {
2965 build: function( dialog, elementDefinition, output ) {
2966 var children = elementDefinition.children,
2967 child,
2968 childHtmlList = [],
2969 childObjList = [];
2970 for ( var i = 0;
2971 ( i < children.length && ( child = children[ i ] ) ); i++ ) {
2972 var childHtml = [];
2973 childHtmlList.push( childHtml );
2974 childObjList.push( CKEDITOR.dialog._.uiElementBuilders[ child.type ].build( dialog, child, childHtml ) );
2975 }
2976 return new CKEDITOR.ui.dialog[ elementDefinition.type ]( dialog, childObjList, childHtmlList, output, elementDefinition );
2977 }
2978 };
2979
2980 CKEDITOR.dialog.addUIElement( 'hbox', commonBuilder );
2981 CKEDITOR.dialog.addUIElement( 'vbox', commonBuilder );
2982 } )();
2983
2984 /**
2985 * Generic dialog command. It opens a specific dialog when executed.
2986 *
2987 * // Register the "link" command, which opens the "link" dialog.
2988 * editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) );
2989 *
2990 * @class
2991 * @constructor Creates a dialogCommand class instance.
2992 * @extends CKEDITOR.commandDefinition
2993 * @param {String} dialogName The name of the dialog to open when executing
2994 * this command.
2995 * @param {Object} [ext] Additional command definition's properties.
2996 */
2997 CKEDITOR.dialogCommand = function( dialogName, ext ) {
2998 this.dialogName = dialogName;
2999 CKEDITOR.tools.extend( this, ext, true );
3000 };
3001
3002 CKEDITOR.dialogCommand.prototype = {
3003 exec: function( editor ) {
3004 editor.openDialog( this.dialogName );
3005 },
3006
3007 // Dialog commands just open a dialog ui, thus require no undo logic,
3008 // undo support should dedicate to specific dialog implementation.
3009 canUndo: false,
3010
3011 editorFocus: 1
3012 };
3013
3014 ( function() {
3015 var notEmptyRegex = /^([a]|[^a])+$/,
3016 integerRegex = /^\d*$/,
3017 numberRegex = /^\d*(?:\.\d+)?$/,
3018 htmlLengthRegex = /^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/,
3019 cssLengthRegex = /^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i,
3020 inlineStyleRegex = /^(\s*[\w-]+\s*:\s*[^:;]+(?:;|$))*$/;
3021
3022 CKEDITOR.VALIDATE_OR = 1;
3023 CKEDITOR.VALIDATE_AND = 2;
3024
3025 CKEDITOR.dialog.validate = {
3026 functions: function() {
3027 var args = arguments;
3028 return function() {
3029 /**
3030 * It's important for validate functions to be able to accept the value
3031 * as argument in addition to this.getValue(), so that it is possible to
3032 * combine validate functions together to make more sophisticated
3033 * validators.
3034 */
3035 var value = this && this.getValue ? this.getValue() : args[ 0 ];
3036
3037 var msg,
3038 relation = CKEDITOR.VALIDATE_AND,
3039 functions = [],
3040 i;
3041
3042 for ( i = 0; i < args.length; i++ ) {
3043 if ( typeof args[ i ] == 'function' )
3044 functions.push( args[ i ] );
3045 else
3046 break;
3047 }
3048
3049 if ( i < args.length && typeof args[ i ] == 'string' ) {
3050 msg = args[ i ];
3051 i++;
3052 }
3053
3054 if ( i < args.length && typeof args[ i ] == 'number' )
3055 relation = args[ i ];
3056
3057 var passed = ( relation == CKEDITOR.VALIDATE_AND ? true : false );
3058 for ( i = 0; i < functions.length; i++ ) {
3059 if ( relation == CKEDITOR.VALIDATE_AND )
3060 passed = passed && functions[ i ]( value );
3061 else
3062 passed = passed || functions[ i ]( value );
3063 }
3064
3065 return !passed ? msg : true;
3066 };
3067 },
3068
3069 regex: function( regex, msg ) {
3070 /*
3071 * Can be greatly shortened by deriving from functions validator if code size
3072 * turns out to be more important than performance.
3073 */
3074 return function() {
3075 var value = this && this.getValue ? this.getValue() : arguments[ 0 ];
3076 return !regex.test( value ) ? msg : true;
3077 };
3078 },
3079
3080 notEmpty: function( msg ) {
3081 return this.regex( notEmptyRegex, msg );
3082 },
3083
3084 integer: function( msg ) {
3085 return this.regex( integerRegex, msg );
3086 },
3087
3088 'number': function( msg ) {
3089 return this.regex( numberRegex, msg );
3090 },
3091
3092 'cssLength': function( msg ) {
3093 return this.functions( function( val ) {
3094 return cssLengthRegex.test( CKEDITOR.tools.trim( val ) );
3095 }, msg );
3096 },
3097
3098 'htmlLength': function( msg ) {
3099 return this.functions( function( val ) {
3100 return htmlLengthRegex.test( CKEDITOR.tools.trim( val ) );
3101 }, msg );
3102 },
3103
3104 'inlineStyle': function( msg ) {
3105 return this.functions( function( val ) {
3106 return inlineStyleRegex.test( CKEDITOR.tools.trim( val ) );
3107 }, msg );
3108 },
3109
3110 equals: function( value, msg ) {
3111 return this.functions( function( val ) {
3112 return val == value;
3113 }, msg );
3114 },
3115
3116 notEqual: function( value, msg ) {
3117 return this.functions( function( val ) {
3118 return val != value;
3119 }, msg );
3120 }
3121 };
3122
3123 CKEDITOR.on( 'instanceDestroyed', function( evt ) {
3124 // Remove dialog cover on last instance destroy.
3125 if ( CKEDITOR.tools.isEmpty( CKEDITOR.instances ) ) {
3126 var currentTopDialog;
3127 while ( ( currentTopDialog = CKEDITOR.dialog._.currentTop ) )
3128 currentTopDialog.hide();
3129 removeCovers();
3130 }
3131
3132 var dialogs = evt.editor._.storedDialogs;
3133 for ( var name in dialogs )
3134 dialogs[ name ].destroy();
3135
3136 } );
3137
3138 } )();
3139
3140 // Extend the CKEDITOR.editor class with dialog specific functions.
3141 CKEDITOR.tools.extend( CKEDITOR.editor.prototype, {
3142 /**
3143 * Loads and opens a registered dialog.
3144 *
3145 * CKEDITOR.instances.editor1.openDialog( 'smiley' );
3146 *
3147 * @member CKEDITOR.editor
3148 * @param {String} dialogName The registered name of the dialog.
3149 * @param {Function} callback The function to be invoked after dialog instance created.
3150 * @returns {CKEDITOR.dialog} The dialog object corresponding to the dialog displayed.
3151 * `null` if the dialog name is not registered.
3152 * @see CKEDITOR.dialog#add
3153 */
3154 openDialog: function( dialogName, callback ) {
3155 var dialog = null, dialogDefinitions = CKEDITOR.dialog._.dialogDefinitions[ dialogName ];
3156
3157 if ( CKEDITOR.dialog._.currentTop === null )
3158 showCover( this );
3159
3160 // If the dialogDefinition is already loaded, open it immediately.
3161 if ( typeof dialogDefinitions == 'function' ) {
3162 var storedDialogs = this._.storedDialogs || ( this._.storedDialogs = {} );
3163
3164 dialog = storedDialogs[ dialogName ] || ( storedDialogs[ dialogName ] = new CKEDITOR.dialog( this, dialogName ) );
3165
3166 callback && callback.call( dialog, dialog );
3167 dialog.show();
3168
3169 } else if ( dialogDefinitions == 'failed' ) {
3170 hideCover( this );
3171 throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName + '" failed when loading definition.' );
3172 } else if ( typeof dialogDefinitions == 'string' ) {
3173
3174 CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( dialogDefinitions ),
3175 function() {
3176 var dialogDefinition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ];
3177 // In case of plugin error, mark it as loading failed.
3178 if ( typeof dialogDefinition != 'function' )
3179 CKEDITOR.dialog._.dialogDefinitions[ dialogName ] = 'failed';
3180
3181 this.openDialog( dialogName, callback );
3182 }, this, 0, 1 );
3183 }
3184
3185 CKEDITOR.skin.loadPart( 'dialog' );
3186
3187 return dialog;
3188 }
3189 } );
3190} )();
3191
3192CKEDITOR.plugins.add( 'dialog', {
3193 requires: 'dialogui',
3194 init: function( editor ) {
3195 editor.on( 'doubleclick', function( evt ) {
3196 if ( evt.data.dialog )
3197 editor.openDialog( evt.data.dialog );
3198 }, null, null, 999 );
3199 }
3200} );
3201
3202// Dialog related configurations.
3203
3204/**
3205 * The color of the dialog background cover. It should be a valid CSS color string.
3206 *
3207 * config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)';
3208 *
3209 * @cfg {String} [dialog_backgroundCoverColor='white']
3210 * @member CKEDITOR.config
3211 */
3212
3213/**
3214 * The opacity of the dialog background cover. It should be a number within the
3215 * range `[0.0, 1.0]`.
3216 *
3217 * config.dialog_backgroundCoverOpacity = 0.7;
3218 *
3219 * @cfg {Number} [dialog_backgroundCoverOpacity=0.5]
3220 * @member CKEDITOR.config
3221 */
3222
3223/**
3224 * If the dialog has more than one tab, put focus into the first tab as soon as dialog is opened.
3225 *
3226 * config.dialog_startupFocusTab = true;
3227 *
3228 * @cfg {Boolean} [dialog_startupFocusTab=false]
3229 * @member CKEDITOR.config
3230 */
3231
3232/**
3233 * The distance of magnetic borders used in moving and resizing dialogs,
3234 * measured in pixels.
3235 *
3236 * config.dialog_magnetDistance = 30;
3237 *
3238 * @cfg {Number} [dialog_magnetDistance=20]
3239 * @member CKEDITOR.config
3240 */
3241
3242/**
3243 * The guideline to follow when generating the dialog buttons. There are 3 possible options:
3244 *
3245 * * `'OS'` - the buttons will be displayed in the default order of the user's OS;
3246 * * `'ltr'` - for Left-To-Right order;
3247 * * `'rtl'` - for Right-To-Left order.
3248 *
3249 * Example:
3250 *
3251 * config.dialog_buttonsOrder = 'rtl';
3252 *
3253 * @since 3.5
3254 * @cfg {String} [dialog_buttonsOrder='OS']
3255 * @member CKEDITOR.config
3256 */
3257
3258/**
3259 * The dialog contents to removed. It's a string composed by dialog name and tab name with a colon between them.
3260 *
3261 * Separate each pair with semicolon (see example).
3262 *
3263 * **Note:** All names are case-sensitive.
3264 *
3265 * **Note:** Be cautious when specifying dialog tabs that are mandatory,
3266 * like `'info'`, dialog functionality might be broken because of this!
3267 *
3268 * config.removeDialogTabs = 'flash:advanced;image:Link';
3269 *
3270 * @since 3.5
3271 * @cfg {String} [removeDialogTabs='']
3272 * @member CKEDITOR.config
3273 */
3274
3275/**
3276 * Tells if user should not be asked to confirm close, if any dialog field was modified.
3277 * By default it is set to `false` meaning that the confirmation dialog will be shown.
3278 *
3279 * config.dialog_noConfirmCancel = true;
3280 *
3281 * @since 4.3
3282 * @cfg {Boolean} [dialog_noConfirmCancel=false]
3283 * @member CKEDITOR.config
3284 */
3285
3286/**
3287 * Event fired when a dialog definition is about to be used to create a dialog into
3288 * an editor instance. This event makes it possible to customize the definition
3289 * before creating it.
3290 *
3291 * Note that this event is called only the first time a specific dialog is
3292 * opened. Successive openings will use the cached dialog, and this event will
3293 * not get fired.
3294 *
3295 * @event dialogDefinition
3296 * @member CKEDITOR
3297 * @param {CKEDITOR.dialog.definition} data The dialog defination that
3298 * is being loaded.
3299 * @param {CKEDITOR.editor} editor The editor instance that will use the dialog.
3300 */
3301
3302/**
3303 * Event fired when a tab is going to be selected in a dialog.
3304 *
3305 * @event selectPage
3306 * @member CKEDITOR.dialog
3307 * @param data
3308 * @param {String} data.page The id of the page that it's gonna be selected.
3309 * @param {String} data.currentPage The id of the current page.
3310 */
3311
3312/**
3313 * Event fired when the user tries to dismiss a dialog.
3314 *
3315 * @event cancel
3316 * @member CKEDITOR.dialog
3317 * @param data
3318 * @param {Boolean} data.hide Whether the event should proceed or not.
3319 */
3320
3321/**
3322 * Event fired when the user tries to confirm a dialog.
3323 *
3324 * @event ok
3325 * @member CKEDITOR.dialog
3326 * @param data
3327 * @param {Boolean} data.hide Whether the event should proceed or not.
3328 */
3329
3330/**
3331 * Event fired when a dialog is shown.
3332 *
3333 * @event show
3334 * @member CKEDITOR.dialog
3335 */
3336
3337/**
3338 * Event fired when a dialog is shown.
3339 *
3340 * @event dialogShow
3341 * @member CKEDITOR.editor
3342 * @param {CKEDITOR.editor} editor This editor instance.
3343 * @param {CKEDITOR.dialog} data The opened dialog instance.
3344 */
3345
3346/**
3347 * Event fired when a dialog is hidden.
3348 *
3349 * @event hide
3350 * @member CKEDITOR.dialog
3351 */
3352
3353/**
3354 * Event fired when a dialog is hidden.
3355 *
3356 * @event dialogHide
3357 * @member CKEDITOR.editor
3358 * @param {CKEDITOR.editor} editor This editor instance.
3359 * @param {CKEDITOR.dialog} data The hidden dialog instance.
3360 */
3361
3362/**
3363 * Event fired when a dialog is being resized. The event is fired on
3364 * both the {@link CKEDITOR.dialog} object and the dialog instance
3365 * since 3.5.3, previously it was only available in the global object.
3366 *
3367 * @static
3368 * @event resize
3369 * @member CKEDITOR.dialog
3370 * @param data
3371 * @param {CKEDITOR.dialog} data.dialog The dialog being resized (if
3372 * it is fired on the dialog itself, this parameter is not sent).
3373 * @param {String} data.skin The skin name.
3374 * @param {Number} data.width The new width.
3375 * @param {Number} data.height The new height.
3376 */
3377
3378/**
3379 * Event fired when a dialog is being resized. The event is fired on
3380 * both the {@link CKEDITOR.dialog} object and the dialog instance
3381 * since 3.5.3, previously it was only available in the global object.
3382 *
3383 * @since 3.5
3384 * @event resize
3385 * @member CKEDITOR.dialog
3386 * @param data
3387 * @param {Number} data.width The new width.
3388 * @param {Number} data.height The new height.
3389 */
3390
3391/**
3392 * Event fired when the dialog state changes, usually by {@link CKEDITOR.dialog#setState}.
3393 *
3394 * @since 4.5
3395 * @event state
3396 * @member CKEDITOR.dialog
3397 * @param data
3398 * @param {Number} data The new state. Either {@link CKEDITOR#DIALOG_STATE_IDLE} or {@link CKEDITOR#DIALOG_STATE_BUSY}.
3399 */
diff --git a/sources/plugins/dialog/samples/assets/my_dialog.js b/sources/plugins/dialog/samples/assets/my_dialog.js
new file mode 100644
index 0000000..6239dea
--- /dev/null
+++ b/sources/plugins/dialog/samples/assets/my_dialog.js
@@ -0,0 +1,49 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.dialog.add( 'myDialog', function() {
7 return {
8 title: 'My Dialog',
9 minWidth: 400,
10 minHeight: 200,
11 contents: [
12 {
13 id: 'tab1',
14 label: 'First Tab',
15 title: 'First Tab',
16 elements: [
17 {
18 id: 'input1',
19 type: 'text',
20 label: 'Text Field'
21 },
22 {
23 id: 'select1',
24 type: 'select',
25 label: 'Select Field',
26 items: [
27 [ 'option1', 'value1' ],
28 [ 'option2', 'value2' ]
29 ]
30 }
31 ]
32 },
33 {
34 id: 'tab2',
35 label: 'Second Tab',
36 title: 'Second Tab',
37 elements: [
38 {
39 id: 'button1',
40 type: 'button',
41 label: 'Button Field'
42 }
43 ]
44 }
45 ]
46 };
47} );
48
49// %LEAVE_UNMINIFIED% %REMOVE_LINE%
diff --git a/sources/plugins/dialog/samples/dialog.html b/sources/plugins/dialog/samples/dialog.html
new file mode 100644
index 0000000..0f22a1a
--- /dev/null
+++ b/sources/plugins/dialog/samples/dialog.html
@@ -0,0 +1,190 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Using API to Customize Dialog Windows &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link rel="stylesheet" href="../../../samples/old/sample.css">
12 <meta name="ckeditor-sample-name" content="Using the JavaScript API to customize dialog windows">
13 <meta name="ckeditor-sample-group" content="Advanced Samples">
14 <meta name="ckeditor-sample-description" content="Using the dialog windows API to customize dialog windows without changing the original editor code.">
15 <style>
16
17 .cke_button__mybutton_icon
18 {
19 display: none !important;
20 }
21
22 .cke_button__mybutton_label
23 {
24 display: inline !important;
25 }
26
27 </style>
28 <script>
29
30 CKEDITOR.on( 'instanceCreated', function( ev ){
31 var editor = ev.editor;
32
33 // Listen for the "pluginsLoaded" event, so we are sure that the
34 // "dialog" plugin has been loaded and we are able to do our
35 // customizations.
36 editor.on( 'pluginsLoaded', function() {
37
38 // If our custom dialog has not been registered, do that now.
39 if ( !CKEDITOR.dialog.exists( 'myDialog' ) ) {
40 // We need to do the following trick to find out the dialog
41 // definition file URL path. In the real world, you would simply
42 // point to an absolute path directly, like "/mydir/mydialog.js".
43 var href = document.location.href.split( '/' );
44 href.pop();
45 href.push( 'assets/my_dialog.js' );
46 href = href.join( '/' );
47
48 // Finally, register the dialog.
49 CKEDITOR.dialog.add( 'myDialog', href );
50 }
51
52 // Register the command used to open the dialog.
53 editor.addCommand( 'myDialogCmd', new CKEDITOR.dialogCommand( 'myDialog' ) );
54
55 // Add the a custom toolbar buttons, which fires the above
56 // command..
57 editor.ui.add( 'MyButton', CKEDITOR.UI_BUTTON, {
58 label: 'My Dialog',
59 command: 'myDialogCmd'
60 });
61 });
62 });
63
64 // When opening a dialog, its "definition" is created for it, for
65 // each editor instance. The "dialogDefinition" event is then
66 // fired. We should use this event to make customizations to the
67 // definition of existing dialogs.
68 CKEDITOR.on( 'dialogDefinition', function( ev ) {
69 // Take the dialog name and its definition from the event data.
70 var dialogName = ev.data.name;
71 var dialogDefinition = ev.data.definition;
72
73 // Check if the definition is from the dialog we're
74 // interested on (the "Link" dialog).
75 if ( dialogName == 'myDialog' && ev.editor.name == 'editor2' ) {
76 // Get a reference to the "Link Info" tab.
77 var infoTab = dialogDefinition.getContents( 'tab1' );
78
79 // Add a new text field to the "tab1" tab page.
80 infoTab.add( {
81 type: 'text',
82 label: 'My Custom Field',
83 id: 'customField',
84 'default': 'Sample!',
85 validate: function() {
86 if ( ( /\d/ ).test( this.getValue() ) )
87 return 'My Custom Field must not contain digits';
88 }
89 });
90
91 // Remove the "select1" field from the "tab1" tab.
92 infoTab.remove( 'select1' );
93
94 // Set the default value for "input1" field.
95 var input1 = infoTab.get( 'input1' );
96 input1[ 'default' ] = 'www.example.com';
97
98 // Remove the "tab2" tab page.
99 dialogDefinition.removeContents( 'tab2' );
100
101 // Add a new tab to the "Link" dialog.
102 dialogDefinition.addContents( {
103 id: 'customTab',
104 label: 'My Tab',
105 accessKey: 'M',
106 elements: [
107 {
108 id: 'myField1',
109 type: 'text',
110 label: 'My Text Field'
111 },
112 {
113 id: 'myField2',
114 type: 'text',
115 label: 'Another Text Field'
116 }
117 ]
118 });
119
120 // Provide the focus handler to start initial focus in "customField" field.
121 dialogDefinition.onFocus = function() {
122 var urlField = this.getContentElement( 'tab1', 'customField' );
123 urlField.select();
124 };
125 }
126 });
127
128 var config = {
129 extraPlugins: 'dialog',
130 toolbar: [ [ 'MyButton' ] ]
131 };
132
133 </script>
134</head>
135<body>
136 <h1 class="samples">
137 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Using CKEditor Dialog API
138 </h1>
139 <div class="warning deprecated">
140 This sample is not maintained anymore. Check out the <a href="http://sdk.ckeditor.com/">brand new samples in CKEditor SDK</a>.
141 </div>
142 <div class="description">
143 <p>
144 This sample shows how to use the
145 <a class="samples" href="http://docs.ckeditor.com/#!/api/CKEDITOR.dialog">CKEditor Dialog API</a>
146 to customize CKEditor dialog windows without changing the original editor code.
147 The following customizations are being done in the example below:
148 </p>
149 <p>
150 For details on how to create this setup check the source code of this sample page.
151 </p>
152 </div>
153 <p>A custom dialog is added to the editors using the <code>pluginsLoaded</code> event, from an external <a target="_blank" href="assets/my_dialog.js">dialog definition file</a>:</p>
154 <ol>
155 <li><strong>Creating a custom dialog window</strong> &ndash; "My Dialog" dialog window opened with the "My Dialog" toolbar button.</li>
156 <li><strong>Creating a custom button</strong> &ndash; Add button to open the dialog with "My Dialog" toolbar button.</li>
157 </ol>
158 <textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
159 <script>
160 // Replace the <textarea id="editor1"> with an CKEditor instance.
161 CKEDITOR.replace( 'editor1', config );
162 </script>
163 <p>The below editor modify the dialog definition of the above added dialog using the <code>dialogDefinition</code> event:</p>
164 <ol>
165 <li><strong>Adding dialog tab</strong> &ndash; Add new tab "My Tab" to dialog window.</li>
166 <li><strong>Removing a dialog window tab</strong> &ndash; Remove "Second Tab" page from the dialog window.</li>
167 <li><strong>Adding dialog window fields</strong> &ndash; Add "My Custom Field" to the dialog window.</li>
168 <li><strong>Removing dialog window field</strong> &ndash; Remove "Select Field" selection field from the dialog window.</li>
169 <li><strong>Setting default values for dialog window fields</strong> &ndash; Set default value of "Text Field" text field. </li>
170 <li><strong>Setup initial focus for dialog window</strong> &ndash; Put initial focus on "My Custom Field" text field. </li>
171 </ol>
172 <textarea cols="80" id="editor2" name="editor2" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
173 <script>
174
175 // Replace the <textarea id="editor1"> with an CKEditor instance.
176 CKEDITOR.replace( 'editor2', config );
177
178 </script>
179 <div id="footer">
180 <hr>
181 <p>
182 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
183 </p>
184 <p id="copy">
185 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
186 Knabben. All rights reserved.
187 </p>
188 </div>
189</body>
190</html>
diff --git a/sources/plugins/dialogadvtab/plugin.js b/sources/plugins/dialogadvtab/plugin.js
new file mode 100644
index 0000000..460b534
--- /dev/null
+++ b/sources/plugins/dialogadvtab/plugin.js
@@ -0,0 +1,196 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7
8 function setupAdvParams( element ) {
9 var attrName = this.att;
10
11 var value = element && element.hasAttribute( attrName ) && element.getAttribute( attrName ) || '';
12
13 if ( value !== undefined )
14 this.setValue( value );
15 }
16
17 function commitAdvParams() {
18 // Dialogs may use different parameters in the commit list, so, by
19 // definition, we take the first CKEDITOR.dom.element available.
20 var element;
21
22 for ( var i = 0; i < arguments.length; i++ ) {
23 if ( arguments[ i ] instanceof CKEDITOR.dom.element ) {
24 element = arguments[ i ];
25 break;
26 }
27 }
28
29 if ( element ) {
30 var attrName = this.att,
31 value = this.getValue();
32
33 if ( value )
34 element.setAttribute( attrName, value );
35 else
36 element.removeAttribute( attrName, value );
37 }
38 }
39
40 var defaultTabConfig = { id: 1, dir: 1, classes: 1, styles: 1 };
41
42 CKEDITOR.plugins.add( 'dialogadvtab', {
43 requires: 'dialog',
44
45 // Returns allowed content rule for the content created by this plugin.
46 allowedContent: function( tabConfig ) {
47 if ( !tabConfig )
48 tabConfig = defaultTabConfig;
49
50 var allowedAttrs = [];
51 if ( tabConfig.id )
52 allowedAttrs.push( 'id' );
53 if ( tabConfig.dir )
54 allowedAttrs.push( 'dir' );
55
56 var allowed = '';
57
58 if ( allowedAttrs.length )
59 allowed += '[' + allowedAttrs.join( ',' ) + ']';
60
61 if ( tabConfig.classes )
62 allowed += '(*)';
63 if ( tabConfig.styles )
64 allowed += '{*}';
65
66 return allowed;
67 },
68
69 // @param tabConfig
70 // id, dir, classes, styles
71 createAdvancedTab: function( editor, tabConfig, element ) {
72 if ( !tabConfig )
73 tabConfig = defaultTabConfig;
74
75 var lang = editor.lang.common;
76
77 var result = {
78 id: 'advanced',
79 label: lang.advancedTab,
80 title: lang.advancedTab,
81 elements: [ {
82 type: 'vbox',
83 padding: 1,
84 children: []
85 } ]
86 };
87
88 var contents = [];
89
90 if ( tabConfig.id || tabConfig.dir ) {
91 if ( tabConfig.id ) {
92 contents.push( {
93 id: 'advId',
94 att: 'id',
95 type: 'text',
96 requiredContent: element ? element + '[id]' : null,
97 label: lang.id,
98 setup: setupAdvParams,
99 commit: commitAdvParams
100 } );
101 }
102
103 if ( tabConfig.dir ) {
104 contents.push( {
105 id: 'advLangDir',
106 att: 'dir',
107 type: 'select',
108 requiredContent: element ? element + '[dir]' : null,
109 label: lang.langDir,
110 'default': '',
111 style: 'width:100%',
112 items: [
113 [ lang.notSet, '' ],
114 [ lang.langDirLTR, 'ltr' ],
115 [ lang.langDirRTL, 'rtl' ]
116 ],
117 setup: setupAdvParams,
118 commit: commitAdvParams
119 } );
120 }
121
122 result.elements[ 0 ].children.push( {
123 type: 'hbox',
124 widths: [ '50%', '50%' ],
125 children: [].concat( contents )
126 } );
127 }
128
129 if ( tabConfig.styles || tabConfig.classes ) {
130 contents = [];
131
132 if ( tabConfig.styles ) {
133 contents.push( {
134 id: 'advStyles',
135 att: 'style',
136 type: 'text',
137 requiredContent: element ? element + '{cke-xyz}' : null,
138 label: lang.styles,
139 'default': '',
140
141 validate: CKEDITOR.dialog.validate.inlineStyle( lang.invalidInlineStyle ),
142 onChange: function() {},
143
144 getStyle: function( name, defaultValue ) {
145 var match = this.getValue().match( new RegExp( '(?:^|;)\\s*' + name + '\\s*:\\s*([^;]*)', 'i' ) );
146 return match ? match[ 1 ] : defaultValue;
147 },
148
149 updateStyle: function( name, value ) {
150 var styles = this.getValue();
151
152 var tmp = editor.document.createElement( 'span' );
153 tmp.setAttribute( 'style', styles );
154 tmp.setStyle( name, value );
155 styles = CKEDITOR.tools.normalizeCssText( tmp.getAttribute( 'style' ) );
156
157 this.setValue( styles, 1 );
158 },
159
160 setup: setupAdvParams,
161
162 commit: commitAdvParams
163
164 } );
165 }
166
167 if ( tabConfig.classes ) {
168 contents.push( {
169 type: 'hbox',
170 widths: [ '45%', '55%' ],
171 children: [ {
172 id: 'advCSSClasses',
173 att: 'class',
174 type: 'text',
175 requiredContent: element ? element + '(cke-xyz)' : null,
176 label: lang.cssClasses,
177 'default': '',
178 setup: setupAdvParams,
179 commit: commitAdvParams
180
181 } ]
182 } );
183 }
184
185 result.elements[ 0 ].children.push( {
186 type: 'hbox',
187 widths: [ '50%', '50%' ],
188 children: [].concat( contents )
189 } );
190 }
191
192 return result;
193 }
194 } );
195
196} )();
diff --git a/sources/plugins/dialogui/plugin.js b/sources/plugins/dialogui/plugin.js
new file mode 100644
index 0000000..cf91407
--- /dev/null
+++ b/sources/plugins/dialogui/plugin.js
@@ -0,0 +1,1530 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The Dialog User Interface plugin.
8 */
9
10CKEDITOR.plugins.add( 'dialogui', {
11 onLoad: function() {
12
13 var initPrivateObject = function( elementDefinition ) {
14 this._ || ( this._ = {} );
15 this._[ 'default' ] = this._.initValue = elementDefinition[ 'default' ] || '';
16 this._.required = elementDefinition.required || false;
17 var args = [ this._ ];
18 for ( var i = 1; i < arguments.length; i++ )
19 args.push( arguments[ i ] );
20 args.push( true );
21 CKEDITOR.tools.extend.apply( CKEDITOR.tools, args );
22 return this._;
23 },
24 textBuilder = {
25 build: function( dialog, elementDefinition, output ) {
26 return new CKEDITOR.ui.dialog.textInput( dialog, elementDefinition, output );
27 }
28 },
29 commonBuilder = {
30 build: function( dialog, elementDefinition, output ) {
31 return new CKEDITOR.ui.dialog[ elementDefinition.type ]( dialog, elementDefinition, output );
32 }
33 },
34 containerBuilder = {
35 build: function( dialog, elementDefinition, output ) {
36 var children = elementDefinition.children,
37 child,
38 childHtmlList = [],
39 childObjList = [];
40 for ( var i = 0;
41 ( i < children.length && ( child = children[ i ] ) ); i++ ) {
42 var childHtml = [];
43 childHtmlList.push( childHtml );
44 childObjList.push( CKEDITOR.dialog._.uiElementBuilders[ child.type ].build( dialog, child, childHtml ) );
45 }
46 return new CKEDITOR.ui.dialog[ elementDefinition.type ]( dialog, childObjList, childHtmlList, output, elementDefinition );
47 }
48 },
49 commonPrototype = {
50 isChanged: function() {
51 return this.getValue() != this.getInitValue();
52 },
53
54 reset: function( noChangeEvent ) {
55 this.setValue( this.getInitValue(), noChangeEvent );
56 },
57
58 setInitValue: function() {
59 this._.initValue = this.getValue();
60 },
61
62 resetInitValue: function() {
63 this._.initValue = this._[ 'default' ];
64 },
65
66 getInitValue: function() {
67 return this._.initValue;
68 }
69 },
70 commonEventProcessors = CKEDITOR.tools.extend( {}, CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors, {
71 onChange: function( dialog, func ) {
72 if ( !this._.domOnChangeRegistered ) {
73 dialog.on( 'load', function() {
74 this.getInputElement().on( 'change', function() {
75 // Make sure 'onchange' doesn't get fired after dialog closed. (#5719)
76 if ( !dialog.parts.dialog.isVisible() )
77 return;
78
79 this.fire( 'change', { value: this.getValue() } );
80 }, this );
81 }, this );
82 this._.domOnChangeRegistered = true;
83 }
84
85 this.on( 'change', func );
86 }
87 }, true ),
88 eventRegex = /^on([A-Z]\w+)/,
89 cleanInnerDefinition = function( def ) {
90 // An inner UI element should not have the parent's type, title or events.
91 for ( var i in def ) {
92 if ( eventRegex.test( i ) || i == 'title' || i == 'type' )
93 delete def[ i ];
94 }
95 return def;
96 },
97 // @context {CKEDITOR.dialog.uiElement} UI element (textarea or textInput)
98 // @param {CKEDITOR.dom.event} evt
99 toggleBidiKeyUpHandler = function( evt ) {
100 var keystroke = evt.data.getKeystroke();
101
102 // ALT + SHIFT + Home for LTR direction.
103 if ( keystroke == CKEDITOR.SHIFT + CKEDITOR.ALT + 36 )
104 this.setDirectionMarker( 'ltr' );
105
106 // ALT + SHIFT + End for RTL direction.
107 else if ( keystroke == CKEDITOR.SHIFT + CKEDITOR.ALT + 35 )
108 this.setDirectionMarker( 'rtl' );
109 };
110
111 CKEDITOR.tools.extend( CKEDITOR.ui.dialog, {
112 /**
113 * Base class for all dialog window elements with a textual label on the left.
114 *
115 * @class CKEDITOR.ui.dialog.labeledElement
116 * @extends CKEDITOR.ui.dialog.uiElement
117 * @constructor Creates a labeledElement class instance.
118 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
119 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
120 * The element definition. Accepted fields:
121 *
122 * * `label` (Required) The label string.
123 * * `labelLayout` (Optional) Put 'horizontal' here if the
124 * label element is to be laid out horizontally. Otherwise a vertical
125 * layout will be used.
126 * * `widths` (Optional) This applies only to horizontal
127 * layouts &mdash; a two-element array of lengths to specify the widths of the
128 * label and the content element.
129 * * `role` (Optional) Value for the `role` attribute.
130 * * `includeLabel` (Optional) If set to `true`, the `aria-labelledby` attribute
131 * will be included.
132 *
133 * @param {Array} htmlList The list of HTML code to output to.
134 * @param {Function} contentHtml
135 * A function returning the HTML code string to be added inside the content
136 * cell.
137 */
138 labeledElement: function( dialog, elementDefinition, htmlList, contentHtml ) {
139 if ( arguments.length < 4 )
140 return;
141
142 var _ = initPrivateObject.call( this, elementDefinition );
143 _.labelId = CKEDITOR.tools.getNextId() + '_label';
144 this._.children = [];
145
146 var innerHTML = function() {
147 var html = [],
148 requiredClass = elementDefinition.required ? ' cke_required' : '';
149 if ( elementDefinition.labelLayout != 'horizontal' ) {
150 html.push(
151 '<label class="cke_dialog_ui_labeled_label' + requiredClass + '" ', ' id="' + _.labelId + '"',
152 ( _.inputId ? ' for="' + _.inputId + '"' : '' ),
153 ( elementDefinition.labelStyle ? ' style="' + elementDefinition.labelStyle + '"' : '' ) + '>',
154 elementDefinition.label,
155 '</label>',
156 '<div class="cke_dialog_ui_labeled_content"',
157 ( elementDefinition.controlStyle ? ' style="' + elementDefinition.controlStyle + '"' : '' ),
158 ' role="presentation">',
159 contentHtml.call( this, dialog, elementDefinition ),
160 '</div>' );
161 } else {
162 var hboxDefinition = {
163 type: 'hbox',
164 widths: elementDefinition.widths,
165 padding: 0,
166 children: [ {
167 type: 'html',
168 html: '<label class="cke_dialog_ui_labeled_label' + requiredClass + '"' +
169 ' id="' + _.labelId + '"' +
170 ' for="' + _.inputId + '"' +
171 ( elementDefinition.labelStyle ? ' style="' + elementDefinition.labelStyle + '"' : '' ) + '>' +
172 CKEDITOR.tools.htmlEncode( elementDefinition.label ) +
173 '</label>'
174 },
175 {
176 type: 'html',
177 html: '<span class="cke_dialog_ui_labeled_content"' + ( elementDefinition.controlStyle ? ' style="' + elementDefinition.controlStyle + '"' : '' ) + '>' +
178 contentHtml.call( this, dialog, elementDefinition ) +
179 '</span>'
180 } ]
181 };
182 CKEDITOR.dialog._.uiElementBuilders.hbox.build( dialog, hboxDefinition, html );
183 }
184 return html.join( '' );
185 };
186 var attributes = { role: elementDefinition.role || 'presentation' };
187
188 if ( elementDefinition.includeLabel )
189 attributes[ 'aria-labelledby' ] = _.labelId;
190
191 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'div', null, attributes, innerHTML );
192 },
193
194 /**
195 * A text input with a label. This UI element class represents both the
196 * single-line text inputs and password inputs in dialog boxes.
197 *
198 * @class CKEDITOR.ui.dialog.textInput
199 * @extends CKEDITOR.ui.dialog.labeledElement
200 * @constructor Creates a textInput class instance.
201 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
202 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
203 * The element definition. Accepted fields:
204 *
205 * * `default` (Optional) The default value.
206 * * `validate` (Optional) The validation function.
207 * * `maxLength` (Optional) The maximum length of text box contents.
208 * * `size` (Optional) The size of the text box. This is
209 * usually overridden by the size defined by the skin, though.
210 *
211 * @param {Array} htmlList List of HTML code to output to.
212 */
213 textInput: function( dialog, elementDefinition, htmlList ) {
214 if ( arguments.length < 3 )
215 return;
216
217 initPrivateObject.call( this, elementDefinition );
218 var domId = this._.inputId = CKEDITOR.tools.getNextId() + '_textInput',
219 attributes = { 'class': 'cke_dialog_ui_input_' + elementDefinition.type, id: domId, type: elementDefinition.type };
220
221 // Set the validator, if any.
222 if ( elementDefinition.validate )
223 this.validate = elementDefinition.validate;
224
225 // Set the max length and size.
226 if ( elementDefinition.maxLength )
227 attributes.maxlength = elementDefinition.maxLength;
228 if ( elementDefinition.size )
229 attributes.size = elementDefinition.size;
230
231 if ( elementDefinition.inputStyle )
232 attributes.style = elementDefinition.inputStyle;
233
234 // If user presses Enter in a text box, it implies clicking OK for the dialog.
235 var me = this,
236 keyPressedOnMe = false;
237 dialog.on( 'load', function() {
238 me.getInputElement().on( 'keydown', function( evt ) {
239 if ( evt.data.getKeystroke() == 13 )
240 keyPressedOnMe = true;
241 } );
242
243 // Lower the priority this 'keyup' since 'ok' will close the dialog.(#3749)
244 me.getInputElement().on( 'keyup', function( evt ) {
245 if ( evt.data.getKeystroke() == 13 && keyPressedOnMe ) {
246 dialog.getButton( 'ok' ) && setTimeout( function() {
247 dialog.getButton( 'ok' ).click();
248 }, 0 );
249 keyPressedOnMe = false;
250 }
251
252 if ( me.bidi )
253 toggleBidiKeyUpHandler.call( me, evt );
254 }, null, null, 1000 );
255 } );
256
257 var innerHTML = function() {
258 // IE BUG: Text input fields in IE at 100% would exceed a <td> or inline
259 // container's width, so need to wrap it inside a <div>.
260 var html = [ '<div class="cke_dialog_ui_input_', elementDefinition.type, '" role="presentation"' ];
261
262 if ( elementDefinition.width )
263 html.push( 'style="width:' + elementDefinition.width + '" ' );
264
265 html.push( '><input ' );
266
267 attributes[ 'aria-labelledby' ] = this._.labelId;
268 this._.required && ( attributes[ 'aria-required' ] = this._.required );
269 for ( var i in attributes )
270 html.push( i + '="' + attributes[ i ] + '" ' );
271 html.push( ' /></div>' );
272 return html.join( '' );
273 };
274 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );
275 },
276
277 /**
278 * A text area with a label at the top or on the left.
279 *
280 * @class CKEDITOR.ui.dialog.textarea
281 * @extends CKEDITOR.ui.dialog.labeledElement
282 * @constructor Creates a textarea class instance.
283 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
284 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
285 *
286 * The element definition. Accepted fields:
287 *
288 * * `rows` (Optional) The number of rows displayed.
289 * Defaults to 5 if not defined.
290 * * `cols` (Optional) The number of cols displayed.
291 * Defaults to 20 if not defined. Usually overridden by skins.
292 * * `default` (Optional) The default value.
293 * * `validate` (Optional) The validation function.
294 *
295 * @param {Array} htmlList List of HTML code to output to.
296 */
297 textarea: function( dialog, elementDefinition, htmlList ) {
298 if ( arguments.length < 3 )
299 return;
300
301 initPrivateObject.call( this, elementDefinition );
302 var me = this,
303 domId = this._.inputId = CKEDITOR.tools.getNextId() + '_textarea',
304 attributes = {};
305
306 if ( elementDefinition.validate )
307 this.validate = elementDefinition.validate;
308
309 // Generates the essential attributes for the textarea tag.
310 attributes.rows = elementDefinition.rows || 5;
311 attributes.cols = elementDefinition.cols || 20;
312
313 attributes[ 'class' ] = 'cke_dialog_ui_input_textarea ' + ( elementDefinition[ 'class' ] || '' );
314
315 if ( typeof elementDefinition.inputStyle != 'undefined' )
316 attributes.style = elementDefinition.inputStyle;
317
318 if ( elementDefinition.dir )
319 attributes.dir = elementDefinition.dir;
320
321 if ( me.bidi ) {
322 dialog.on( 'load', function() {
323 me.getInputElement().on( 'keyup', toggleBidiKeyUpHandler );
324 }, me );
325 }
326
327 var innerHTML = function() {
328 attributes[ 'aria-labelledby' ] = this._.labelId;
329 this._.required && ( attributes[ 'aria-required' ] = this._.required );
330 var html = [ '<div class="cke_dialog_ui_input_textarea" role="presentation"><textarea id="', domId, '" ' ];
331 for ( var i in attributes )
332 html.push( i + '="' + CKEDITOR.tools.htmlEncode( attributes[ i ] ) + '" ' );
333 html.push( '>', CKEDITOR.tools.htmlEncode( me._[ 'default' ] ), '</textarea></div>' );
334 return html.join( '' );
335 };
336 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );
337 },
338
339 /**
340 * A single checkbox with a label on the right.
341 *
342 * @class CKEDITOR.ui.dialog.checkbox
343 * @extends CKEDITOR.ui.dialog.uiElement
344 * @constructor Creates a checkbox class instance.
345 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
346 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
347 * The element definition. Accepted fields:
348 *
349 * * `checked` (Optional) Whether the checkbox is checked
350 * on instantiation. Defaults to `false`.
351 * * `validate` (Optional) The validation function.
352 * * `label` (Optional) The checkbox label.
353 *
354 * @param {Array} htmlList List of HTML code to output to.
355 */
356 checkbox: function( dialog, elementDefinition, htmlList ) {
357 if ( arguments.length < 3 )
358 return;
359
360 var _ = initPrivateObject.call( this, elementDefinition, { 'default': !!elementDefinition[ 'default' ] } );
361
362 if ( elementDefinition.validate )
363 this.validate = elementDefinition.validate;
364
365 var innerHTML = function() {
366 var myDefinition = CKEDITOR.tools.extend(
367 {},
368 elementDefinition,
369 {
370 id: elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextId() + '_checkbox'
371 },
372 true
373 ),
374 html = [];
375
376 var labelId = CKEDITOR.tools.getNextId() + '_label';
377 var attributes = { 'class': 'cke_dialog_ui_checkbox_input', type: 'checkbox', 'aria-labelledby': labelId };
378 cleanInnerDefinition( myDefinition );
379 if ( elementDefinition[ 'default' ] )
380 attributes.checked = 'checked';
381
382 if ( typeof myDefinition.inputStyle != 'undefined' )
383 myDefinition.style = myDefinition.inputStyle;
384
385 _.checkbox = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'input', null, attributes );
386 html.push(
387 ' <label id="',
388 labelId,
389 '" for="',
390 attributes.id,
391 '"' + ( elementDefinition.labelStyle ? ' style="' + elementDefinition.labelStyle + '"' : '' ) + '>',
392 CKEDITOR.tools.htmlEncode( elementDefinition.label ),
393 '</label>'
394 );
395 return html.join( '' );
396 };
397
398 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'span', null, null, innerHTML );
399 },
400
401 /**
402 * A group of radio buttons.
403 *
404 * @class CKEDITOR.ui.dialog.radio
405 * @extends CKEDITOR.ui.dialog.labeledElement
406 * @constructor Creates a radio class instance.
407 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
408 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
409 * The element definition. Accepted fields:
410 *
411 * * `default` (Required) The default value.
412 * * `validate` (Optional) The validation function.
413 * * `items` (Required) An array of options. Each option
414 * is a one- or two-item array of format `[ 'Description', 'Value' ]`. If `'Value'`
415 * is missing, then the value would be assumed to be the same as the description.
416 *
417 * @param {Array} htmlList List of HTML code to output to.
418 */
419 radio: function( dialog, elementDefinition, htmlList ) {
420 if ( arguments.length < 3 )
421 return;
422
423 initPrivateObject.call( this, elementDefinition );
424
425 if ( !this._[ 'default' ] )
426 this._[ 'default' ] = this._.initValue = elementDefinition.items[ 0 ][ 1 ];
427
428 if ( elementDefinition.validate )
429 this.validate = elementDefinition.validate;
430
431 var children = [],
432 me = this;
433
434 var innerHTML = function() {
435 var inputHtmlList = [],
436 html = [],
437 commonName = ( elementDefinition.id ? elementDefinition.id : CKEDITOR.tools.getNextId() ) + '_radio';
438
439 for ( var i = 0; i < elementDefinition.items.length; i++ ) {
440 var item = elementDefinition.items[ i ],
441 title = item[ 2 ] !== undefined ? item[ 2 ] : item[ 0 ],
442 value = item[ 1 ] !== undefined ? item[ 1 ] : item[ 0 ],
443 inputId = CKEDITOR.tools.getNextId() + '_radio_input',
444 labelId = inputId + '_label',
445
446 inputDefinition = CKEDITOR.tools.extend( {}, elementDefinition, {
447 id: inputId,
448 title: null,
449 type: null
450 }, true ),
451
452 labelDefinition = CKEDITOR.tools.extend( {}, inputDefinition, {
453 title: title
454 }, true ),
455
456 inputAttributes = {
457 type: 'radio',
458 'class': 'cke_dialog_ui_radio_input',
459 name: commonName,
460 value: value,
461 'aria-labelledby': labelId
462 },
463
464 inputHtml = [];
465
466 if ( me._[ 'default' ] == value )
467 inputAttributes.checked = 'checked';
468
469 cleanInnerDefinition( inputDefinition );
470 cleanInnerDefinition( labelDefinition );
471
472 if ( typeof inputDefinition.inputStyle != 'undefined' )
473 inputDefinition.style = inputDefinition.inputStyle;
474
475 // Make inputs of radio type focusable (#10866).
476 inputDefinition.keyboardFocusable = true;
477
478 children.push( new CKEDITOR.ui.dialog.uiElement( dialog, inputDefinition, inputHtml, 'input', null, inputAttributes ) );
479
480 inputHtml.push( ' ' );
481
482 new CKEDITOR.ui.dialog.uiElement( dialog, labelDefinition, inputHtml, 'label', null, {
483 id: labelId,
484 'for': inputAttributes.id
485 }, item[ 0 ] );
486
487 inputHtmlList.push( inputHtml.join( '' ) );
488 }
489
490 new CKEDITOR.ui.dialog.hbox( dialog, children, inputHtmlList, html );
491
492 return html.join( '' );
493 };
494
495 // Adding a role="radiogroup" to definition used for wrapper.
496 elementDefinition.role = 'radiogroup';
497 elementDefinition.includeLabel = true;
498
499 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );
500 this._.children = children;
501 },
502
503 /**
504 * A button with a label inside.
505 *
506 * @class CKEDITOR.ui.dialog.button
507 * @extends CKEDITOR.ui.dialog.uiElement
508 * @constructor Creates a button class instance.
509 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
510 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
511 * The element definition. Accepted fields:
512 *
513 * * `label` (Required) The button label.
514 * * `disabled` (Optional) Set to `true` if you want the
515 * button to appear in the disabled state.
516 *
517 * @param {Array} htmlList List of HTML code to output to.
518 */
519 button: function( dialog, elementDefinition, htmlList ) {
520 if ( !arguments.length )
521 return;
522
523 if ( typeof elementDefinition == 'function' )
524 elementDefinition = elementDefinition( dialog.getParentEditor() );
525
526 initPrivateObject.call( this, elementDefinition, { disabled: elementDefinition.disabled || false } );
527
528 // Add OnClick event to this input.
529 CKEDITOR.event.implementOn( this );
530
531 var me = this;
532
533 // Register an event handler for processing button clicks.
534 dialog.on( 'load', function() {
535 var element = this.getElement();
536
537 ( function() {
538 element.on( 'click', function( evt ) {
539 me.click();
540 // #9958
541 evt.data.preventDefault();
542 } );
543
544 element.on( 'keydown', function( evt ) {
545 if ( evt.data.getKeystroke() in { 32: 1 } ) {
546 me.click();
547 evt.data.preventDefault();
548 }
549 } );
550 } )();
551
552 element.unselectable();
553 }, this );
554
555 var outerDefinition = CKEDITOR.tools.extend( {}, elementDefinition );
556 delete outerDefinition.style;
557
558 var labelId = CKEDITOR.tools.getNextId() + '_label';
559 CKEDITOR.ui.dialog.uiElement.call( this, dialog, outerDefinition, htmlList, 'a', null, {
560 style: elementDefinition.style,
561 href: 'javascript:void(0)', // jshint ignore:line
562 title: elementDefinition.label,
563 hidefocus: 'true',
564 'class': elementDefinition[ 'class' ],
565 role: 'button',
566 'aria-labelledby': labelId
567 }, '<span id="' + labelId + '" class="cke_dialog_ui_button">' +
568 CKEDITOR.tools.htmlEncode( elementDefinition.label ) +
569 '</span>' );
570 },
571
572 /**
573 * A select box.
574 *
575 * @class CKEDITOR.ui.dialog.select
576 * @extends CKEDITOR.ui.dialog.uiElement
577 * @constructor Creates a button class instance.
578 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
579 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
580 * The element definition. Accepted fields:
581 *
582 * * `default` (Required) The default value.
583 * * `validate` (Optional) The validation function.
584 * * `items` (Required) An array of options. Each option
585 * is a one- or two-item array of format `[ 'Description', 'Value' ]`. If `'Value'`
586 * is missing, then the value would be assumed to be the same as the
587 * description.
588 * * `multiple` (Optional) Set this to `true` if you would like
589 * to have a multiple-choice select box.
590 * * `size` (Optional) The number of items to display in
591 * the select box.
592 *
593 * @param {Array} htmlList List of HTML code to output to.
594 */
595 select: function( dialog, elementDefinition, htmlList ) {
596 if ( arguments.length < 3 )
597 return;
598
599 var _ = initPrivateObject.call( this, elementDefinition );
600
601 if ( elementDefinition.validate )
602 this.validate = elementDefinition.validate;
603
604 _.inputId = CKEDITOR.tools.getNextId() + '_select';
605
606 var innerHTML = function() {
607 var myDefinition = CKEDITOR.tools.extend(
608 {},
609 elementDefinition,
610 {
611 id: ( elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextId() + '_select' )
612 },
613 true
614 ),
615 html = [],
616 innerHTML = [],
617 attributes = { 'id': _.inputId, 'class': 'cke_dialog_ui_input_select', 'aria-labelledby': this._.labelId };
618
619 html.push( '<div class="cke_dialog_ui_input_', elementDefinition.type, '" role="presentation"' );
620 if ( elementDefinition.width )
621 html.push( 'style="width:' + elementDefinition.width + '" ' );
622 html.push( '>' );
623
624 // Add multiple and size attributes from element definition.
625 if ( elementDefinition.size !== undefined )
626 attributes.size = elementDefinition.size;
627 if ( elementDefinition.multiple !== undefined )
628 attributes.multiple = elementDefinition.multiple;
629
630 cleanInnerDefinition( myDefinition );
631 for ( var i = 0, item; i < elementDefinition.items.length && ( item = elementDefinition.items[ i ] ); i++ ) {
632 innerHTML.push( '<option value="', CKEDITOR.tools.htmlEncode( item[ 1 ] !== undefined ? item[ 1 ] : item[ 0 ] ).replace( /"/g, '&quot;' ), '" /> ', CKEDITOR.tools.htmlEncode( item[ 0 ] ) );
633 }
634
635 if ( typeof myDefinition.inputStyle != 'undefined' )
636 myDefinition.style = myDefinition.inputStyle;
637
638 _.select = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'select', null, attributes, innerHTML.join( '' ) );
639
640 html.push( '</div>' );
641
642 return html.join( '' );
643 };
644
645 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );
646 },
647
648 /**
649 * A file upload input.
650 *
651 * @class CKEDITOR.ui.dialog.file
652 * @extends CKEDITOR.ui.dialog.labeledElement
653 * @constructor Creates a file class instance.
654 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
655 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
656 * The element definition. Accepted fields:
657 *
658 * * `validate` (Optional) The validation function.
659 *
660 * @param {Array} htmlList List of HTML code to output to.
661 */
662 file: function( dialog, elementDefinition, htmlList ) {
663 if ( arguments.length < 3 )
664 return;
665
666 if ( elementDefinition[ 'default' ] === undefined )
667 elementDefinition[ 'default' ] = '';
668
669 var _ = CKEDITOR.tools.extend( initPrivateObject.call( this, elementDefinition ), { definition: elementDefinition, buttons: [] } );
670
671 if ( elementDefinition.validate )
672 this.validate = elementDefinition.validate;
673
674 /** @ignore */
675 var innerHTML = function() {
676 _.frameId = CKEDITOR.tools.getNextId() + '_fileInput';
677
678 var html = [
679 '<iframe' +
680 ' frameborder="0"' +
681 ' allowtransparency="0"' +
682 ' class="cke_dialog_ui_input_file"' +
683 ' role="presentation"' +
684 ' id="', _.frameId, '"' +
685 ' title="', elementDefinition.label, '"' +
686 ' src="javascript:void('
687 ];
688
689 // Support for custom document.domain on IE. (#10165)
690 html.push( CKEDITOR.env.ie ?
691 '(function(){' + encodeURIComponent(
692 'document.open();' +
693 '(' + CKEDITOR.tools.fixDomain + ')();' +
694 'document.close();'
695 ) + '})()'
696 :
697 '0'
698 );
699
700 html.push( ')"></iframe>' );
701
702 return html.join( '' );
703 };
704
705 // IE BUG: Parent container does not resize to contain the iframe automatically.
706 dialog.on( 'load', function() {
707 var iframe = CKEDITOR.document.getById( _.frameId ),
708 contentDiv = iframe.getParent();
709 contentDiv.addClass( 'cke_dialog_ui_input_file' );
710 } );
711
712 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );
713 },
714
715 /**
716 * A button for submitting the file in a file upload input.
717 *
718 * @class CKEDITOR.ui.dialog.fileButton
719 * @extends CKEDITOR.ui.dialog.button
720 * @constructor Creates a fileButton class instance.
721 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
722 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
723 * The element definition. Accepted fields:
724 *
725 * * `for` (Required) The file input's page and element ID
726 * to associate with, in a two-item array format: `[ 'page_id', 'element_id' ]`.
727 * * `validate` (Optional) The validation function.
728 *
729 * @param {Array} htmlList List of HTML code to output to.
730 */
731 fileButton: function( dialog, elementDefinition, htmlList ) {
732 var me = this;
733 if ( arguments.length < 3 )
734 return;
735
736 initPrivateObject.call( this, elementDefinition );
737
738 if ( elementDefinition.validate )
739 this.validate = elementDefinition.validate;
740
741 var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition );
742 var onClick = myDefinition.onClick;
743 myDefinition.className = ( myDefinition.className ? myDefinition.className + ' ' : '' ) + 'cke_dialog_ui_button';
744 myDefinition.onClick = function( evt ) {
745 var target = elementDefinition[ 'for' ]; // [ pageId, elementId ]
746 if ( !onClick || onClick.call( this, evt ) !== false ) {
747 dialog.getContentElement( target[ 0 ], target[ 1 ] ).submit();
748 this.disable();
749 }
750 };
751
752 dialog.on( 'load', function() {
753 dialog.getContentElement( elementDefinition[ 'for' ][ 0 ], elementDefinition[ 'for' ][ 1 ] )._.buttons.push( me );
754 } );
755
756 CKEDITOR.ui.dialog.button.call( this, dialog, myDefinition, htmlList );
757 },
758
759 html: ( function() {
760 var myHtmlRe = /^\s*<[\w:]+\s+([^>]*)?>/,
761 theirHtmlRe = /^(\s*<[\w:]+(?:\s+[^>]*)?)((?:.|\r|\n)+)$/,
762 emptyTagRe = /\/$/;
763 /**
764 * A dialog window element made from raw HTML code.
765 *
766 * @class CKEDITOR.ui.dialog.html
767 * @extends CKEDITOR.ui.dialog.uiElement
768 * @constructor Creates a html class instance.
769 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
770 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition Element definition.
771 * Accepted fields:
772 *
773 * * `html` (Required) HTML code of this element.
774 *
775 * @param {Array} htmlList List of HTML code to be added to the dialog's content area.
776 */
777 return function( dialog, elementDefinition, htmlList ) {
778 if ( arguments.length < 3 )
779 return;
780
781 var myHtmlList = [],
782 myHtml,
783 theirHtml = elementDefinition.html,
784 myMatch, theirMatch;
785
786 // If the HTML input doesn't contain any tags at the beginning, add a <span> tag around it.
787 if ( theirHtml.charAt( 0 ) != '<' )
788 theirHtml = '<span>' + theirHtml + '</span>';
789
790 // Look for focus function in definition.
791 var focus = elementDefinition.focus;
792 if ( focus ) {
793 var oldFocus = this.focus;
794 this.focus = function() {
795 ( typeof focus == 'function' ? focus : oldFocus ).call( this );
796 this.fire( 'focus' );
797 };
798 if ( elementDefinition.isFocusable ) {
799 var oldIsFocusable = this.isFocusable;
800 this.isFocusable = oldIsFocusable;
801 }
802 this.keyboardFocusable = true;
803 }
804
805 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, myHtmlList, 'span', null, null, '' );
806
807 // Append the attributes created by the uiElement call to the real HTML.
808 myHtml = myHtmlList.join( '' );
809 myMatch = myHtml.match( myHtmlRe );
810 theirMatch = theirHtml.match( theirHtmlRe ) || [ '', '', '' ];
811
812 if ( emptyTagRe.test( theirMatch[ 1 ] ) ) {
813 theirMatch[ 1 ] = theirMatch[ 1 ].slice( 0, -1 );
814 theirMatch[ 2 ] = '/' + theirMatch[ 2 ];
815 }
816
817 htmlList.push( [ theirMatch[ 1 ], ' ', myMatch[ 1 ] || '', theirMatch[ 2 ] ].join( '' ) );
818 };
819 } )(),
820
821 /**
822 * Form fieldset for grouping dialog UI elements.
823 *
824 * @class CKEDITOR.ui.dialog.fieldset
825 * @extends CKEDITOR.ui.dialog.uiElement
826 * @constructor Creates a fieldset class instance.
827 * @param {CKEDITOR.dialog} dialog Parent dialog window object.
828 * @param {Array} childObjList
829 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container.
830 * @param {Array} childHtmlList Array of HTML code that corresponds to the HTML output of all the
831 * objects in childObjList.
832 * @param {Array} htmlList Array of HTML code that this element will output to.
833 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
834 * The element definition. Accepted fields:
835 *
836 * * `label` (Optional) The legend of the this fieldset.
837 * * `children` (Required) An array of dialog window field definitions which will be grouped inside this fieldset.
838 *
839 */
840 fieldset: function( dialog, childObjList, childHtmlList, htmlList, elementDefinition ) {
841 var legendLabel = elementDefinition.label;
842 /** @ignore */
843 var innerHTML = function() {
844 var html = [];
845 legendLabel && html.push( '<legend' +
846 ( elementDefinition.labelStyle ? ' style="' + elementDefinition.labelStyle + '"' : '' ) +
847 '>' + legendLabel + '</legend>' );
848 for ( var i = 0; i < childHtmlList.length; i++ )
849 html.push( childHtmlList[ i ] );
850 return html.join( '' );
851 };
852
853 this._ = { children: childObjList };
854 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'fieldset', null, null, innerHTML );
855 }
856
857 }, true );
858
859 CKEDITOR.ui.dialog.html.prototype = new CKEDITOR.ui.dialog.uiElement();
860
861 /** @class CKEDITOR.ui.dialog.labeledElement */
862 CKEDITOR.ui.dialog.labeledElement.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement(), {
863 /**
864 * Sets the label text of the element.
865 *
866 * @param {String} label The new label text.
867 * @returns {CKEDITOR.ui.dialog.labeledElement} The current labeled element.
868 */
869 setLabel: function( label ) {
870 var node = CKEDITOR.document.getById( this._.labelId );
871 if ( node.getChildCount() < 1 )
872 ( new CKEDITOR.dom.text( label, CKEDITOR.document ) ).appendTo( node );
873 else
874 node.getChild( 0 ).$.nodeValue = label;
875 return this;
876 },
877
878 /**
879 * Retrieves the current label text of the elment.
880 *
881 * @returns {String} The current label text.
882 */
883 getLabel: function() {
884 var node = CKEDITOR.document.getById( this._.labelId );
885 if ( !node || node.getChildCount() < 1 )
886 return '';
887 else
888 return node.getChild( 0 ).getText();
889 },
890
891 /**
892 * Defines the `onChange` event for UI element definitions.
893 * @property {Object}
894 */
895 eventProcessors: commonEventProcessors
896 }, true );
897
898 /** @class CKEDITOR.ui.dialog.button */
899 CKEDITOR.ui.dialog.button.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement(), {
900 /**
901 * Simulates a click to the button.
902 *
903 * @returns {Object} Return value of the `click` event.
904 */
905 click: function() {
906 if ( !this._.disabled )
907 return this.fire( 'click', { dialog: this._.dialog } );
908 return false;
909 },
910
911 /**
912 * Enables the button.
913 */
914 enable: function() {
915 this._.disabled = false;
916 var element = this.getElement();
917 element && element.removeClass( 'cke_disabled' );
918 },
919
920 /**
921 * Disables the button.
922 */
923 disable: function() {
924 this._.disabled = true;
925 this.getElement().addClass( 'cke_disabled' );
926 },
927
928 /**
929 * Checks whether a field is visible.
930 *
931 * @returns {Boolean}
932 */
933 isVisible: function() {
934 return this.getElement().getFirst().isVisible();
935 },
936
937 /**
938 * Checks whether a field is enabled. Fields can be disabled by using the
939 * {@link #disable} method and enabled by using the {@link #enable} method.
940 *
941 * @returns {Boolean}
942 */
943 isEnabled: function() {
944 return !this._.disabled;
945 },
946
947 /**
948 * Defines the `onChange` event and `onClick` for button element definitions.
949 *
950 * @property {Object}
951 */
952 eventProcessors: CKEDITOR.tools.extend( {}, CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors, {
953 onClick: function( dialog, func ) {
954 this.on( 'click', function() {
955 func.apply( this, arguments );
956 } );
957 }
958 }, true ),
959
960 /**
961 * Handler for the element's access key up event. Simulates a click to
962 * the button.
963 */
964 accessKeyUp: function() {
965 this.click();
966 },
967
968 /**
969 * Handler for the element's access key down event. Simulates a mouse
970 * down to the button.
971 */
972 accessKeyDown: function() {
973 this.focus();
974 },
975
976 keyboardFocusable: true
977 }, true );
978
979 /** @class CKEDITOR.ui.dialog.textInput */
980 CKEDITOR.ui.dialog.textInput.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.labeledElement(), {
981 /**
982 * Gets the text input DOM element under this UI object.
983 *
984 * @returns {CKEDITOR.dom.element} The DOM element of the text input.
985 */
986 getInputElement: function() {
987 return CKEDITOR.document.getById( this._.inputId );
988 },
989
990 /**
991 * Puts focus into the text input.
992 */
993 focus: function() {
994 var me = this.selectParentTab();
995
996 // GECKO BUG: setTimeout() is needed to workaround invisible selections.
997 setTimeout( function() {
998 var element = me.getInputElement();
999 element && element.$.focus();
1000 }, 0 );
1001 },
1002
1003 /**
1004 * Selects all the text in the text input.
1005 */
1006 select: function() {
1007 var me = this.selectParentTab();
1008
1009 // GECKO BUG: setTimeout() is needed to workaround invisible selections.
1010 setTimeout( function() {
1011 var e = me.getInputElement();
1012 if ( e ) {
1013 e.$.focus();
1014 e.$.select();
1015 }
1016 }, 0 );
1017 },
1018
1019 /**
1020 * Handler for the text input's access key up event. Makes a `select()`
1021 * call to the text input.
1022 */
1023 accessKeyUp: function() {
1024 this.select();
1025 },
1026
1027 /**
1028 * Sets the value of this text input object.
1029 *
1030 * uiElement.setValue( 'Blamo' );
1031 *
1032 * @param {Object} value The new value.
1033 * @returns {CKEDITOR.ui.dialog.textInput} The current UI element.
1034 */
1035 setValue: function( value ) {
1036 if ( this.bidi ) {
1037 var marker = value && value.charAt( 0 ),
1038 dir = ( marker == '\u202A' ? 'ltr' : marker == '\u202B' ? 'rtl' : null );
1039
1040 if ( dir ) {
1041 value = value.slice( 1 );
1042 }
1043
1044 // Set the marker or reset it (if dir==null).
1045 this.setDirectionMarker( dir );
1046 }
1047
1048 if ( !value ) {
1049 value = '';
1050 }
1051
1052 return CKEDITOR.ui.dialog.uiElement.prototype.setValue.apply( this, arguments );
1053 },
1054
1055 /**
1056 * Gets the value of this text input object.
1057 *
1058 * @returns {String} The value.
1059 */
1060 getValue: function() {
1061 var value = CKEDITOR.ui.dialog.uiElement.prototype.getValue.call( this );
1062
1063 if ( this.bidi && value ) {
1064 var dir = this.getDirectionMarker();
1065 if ( dir ) {
1066 value = ( dir == 'ltr' ? '\u202A' : '\u202B' ) + value;
1067 }
1068 }
1069
1070 return value;
1071 },
1072
1073 /**
1074 * Sets the text direction marker and the `dir` attribute of the input element.
1075 *
1076 * @since 4.5
1077 * @param {String} dir The text direction. Pass `null` to reset.
1078 */
1079 setDirectionMarker: function( dir ) {
1080 var inputElement = this.getInputElement();
1081
1082 if ( dir ) {
1083 inputElement.setAttributes( {
1084 dir: dir,
1085 'data-cke-dir-marker': dir
1086 } );
1087 // Don't remove the dir attribute if this field hasn't got the marker,
1088 // because the dir attribute could be set independently.
1089 } else if ( this.getDirectionMarker() ) {
1090 inputElement.removeAttributes( [ 'dir', 'data-cke-dir-marker' ] );
1091 }
1092 },
1093
1094 /**
1095 * Gets the value of the text direction marker.
1096 *
1097 * @since 4.5
1098 * @returns {String} `'ltr'`, `'rtl'` or `null` if the marker is not set.
1099 */
1100 getDirectionMarker: function() {
1101 return this.getInputElement().data( 'cke-dir-marker' );
1102 },
1103
1104 keyboardFocusable: true
1105 }, commonPrototype, true );
1106
1107 CKEDITOR.ui.dialog.textarea.prototype = new CKEDITOR.ui.dialog.textInput();
1108
1109 /** @class CKEDITOR.ui.dialog.select */
1110 CKEDITOR.ui.dialog.select.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.labeledElement(), {
1111 /**
1112 * Gets the DOM element of the select box.
1113 *
1114 * @returns {CKEDITOR.dom.element} The `<select>` element of this UI element.
1115 */
1116 getInputElement: function() {
1117 return this._.select.getElement();
1118 },
1119
1120 /**
1121 * Adds an option to the select box.
1122 *
1123 * @param {String} label Option label.
1124 * @param {String} value (Optional) Option value, if not defined it will be
1125 * assumed to be the same as the label.
1126 * @param {Number} index (Optional) Position of the option to be inserted
1127 * to. If not defined, the new option will be inserted to the end of list.
1128 * @returns {CKEDITOR.ui.dialog.select} The current select UI element.
1129 */
1130 add: function( label, value, index ) {
1131 var option = new CKEDITOR.dom.element( 'option', this.getDialog().getParentEditor().document ),
1132 selectElement = this.getInputElement().$;
1133 option.$.text = label;
1134 option.$.value = ( value === undefined || value === null ) ? label : value;
1135 if ( index === undefined || index === null ) {
1136 if ( CKEDITOR.env.ie ) {
1137 selectElement.add( option.$ );
1138 } else {
1139 selectElement.add( option.$, null );
1140 }
1141 } else {
1142 selectElement.add( option.$, index );
1143 }
1144 return this;
1145 },
1146
1147 /**
1148 * Removes an option from the selection list.
1149 *
1150 * @param {Number} index Index of the option to be removed.
1151 * @returns {CKEDITOR.ui.dialog.select} The current select UI element.
1152 */
1153 remove: function( index ) {
1154 var selectElement = this.getInputElement().$;
1155 selectElement.remove( index );
1156 return this;
1157 },
1158
1159 /**
1160 * Clears all options out of the selection list.
1161 *
1162 * @returns {CKEDITOR.ui.dialog.select} The current select UI element.
1163 */
1164 clear: function() {
1165 var selectElement = this.getInputElement().$;
1166 while ( selectElement.length > 0 )
1167 selectElement.remove( 0 );
1168 return this;
1169 },
1170
1171 keyboardFocusable: true
1172 }, commonPrototype, true );
1173
1174 /** @class CKEDITOR.ui.dialog.checkbox */
1175 CKEDITOR.ui.dialog.checkbox.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement(), {
1176 /**
1177 * Gets the checkbox DOM element.
1178 *
1179 * @returns {CKEDITOR.dom.element} The DOM element of the checkbox.
1180 */
1181 getInputElement: function() {
1182 return this._.checkbox.getElement();
1183 },
1184
1185 /**
1186 * Sets the state of the checkbox.
1187 *
1188 * @param {Boolean} checked `true` to tick the checkbox, `false` to untick it.
1189 * @param {Boolean} noChangeEvent Internal commit, to supress `change` event on this element.
1190 */
1191 setValue: function( checked, noChangeEvent ) {
1192 this.getInputElement().$.checked = checked;
1193 !noChangeEvent && this.fire( 'change', { value: checked } );
1194 },
1195
1196 /**
1197 * Gets the state of the checkbox.
1198 *
1199 * @returns {Boolean} `true` means that the checkbox is ticked, `false` means it is not ticked.
1200 */
1201 getValue: function() {
1202 return this.getInputElement().$.checked;
1203 },
1204
1205 /**
1206 * Handler for the access key up event. Toggles the checkbox.
1207 */
1208 accessKeyUp: function() {
1209 this.setValue( !this.getValue() );
1210 },
1211
1212 /**
1213 * Defines the `onChange` event for UI element definitions.
1214 *
1215 * @property {Object}
1216 */
1217 eventProcessors: {
1218 onChange: function( dialog, func ) {
1219 if ( !CKEDITOR.env.ie || ( CKEDITOR.env.version > 8 ) )
1220 return commonEventProcessors.onChange.apply( this, arguments );
1221 else {
1222 dialog.on( 'load', function() {
1223 var element = this._.checkbox.getElement();
1224 element.on( 'propertychange', function( evt ) {
1225 evt = evt.data.$;
1226 if ( evt.propertyName == 'checked' )
1227 this.fire( 'change', { value: element.$.checked } );
1228 }, this );
1229 }, this );
1230 this.on( 'change', func );
1231 }
1232 return null;
1233 }
1234 },
1235
1236 keyboardFocusable: true
1237 }, commonPrototype, true );
1238
1239 /** @class CKEDITOR.ui.dialog.radio */
1240 CKEDITOR.ui.dialog.radio.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement(), {
1241 /**
1242 * Selects one of the radio buttons in this button group.
1243 *
1244 * @param {String} value The value of the button to be chcked.
1245 * @param {Boolean} noChangeEvent Internal commit, to supress the `change` event on this element.
1246 */
1247 setValue: function( value, noChangeEvent ) {
1248 var children = this._.children,
1249 item;
1250 for ( var i = 0;
1251 ( i < children.length ) && ( item = children[ i ] ); i++ )
1252 item.getElement().$.checked = ( item.getValue() == value );
1253 !noChangeEvent && this.fire( 'change', { value: value } );
1254 },
1255
1256 /**
1257 * Gets the value of the currently selected radio button.
1258 *
1259 * @returns {String} The currently selected button's value.
1260 */
1261 getValue: function() {
1262 var children = this._.children;
1263 for ( var i = 0; i < children.length; i++ ) {
1264 if ( children[ i ].getElement().$.checked )
1265 return children[ i ].getValue();
1266 }
1267 return null;
1268 },
1269
1270 /**
1271 * Handler for the access key up event. Focuses the currently
1272 * selected radio button, or the first radio button if none is selected.
1273 */
1274 accessKeyUp: function() {
1275 var children = this._.children,
1276 i;
1277 for ( i = 0; i < children.length; i++ ) {
1278 if ( children[ i ].getElement().$.checked ) {
1279 children[ i ].getElement().focus();
1280 return;
1281 }
1282 }
1283 children[ 0 ].getElement().focus();
1284 },
1285
1286 /**
1287 * Defines the `onChange` event for UI element definitions.
1288 *
1289 * @property {Object}
1290 */
1291 eventProcessors: {
1292 onChange: function( dialog, func ) {
1293 if ( !CKEDITOR.env.ie || ( CKEDITOR.env.version > 8 ) )
1294 return commonEventProcessors.onChange.apply( this, arguments );
1295 else {
1296 dialog.on( 'load', function() {
1297 var children = this._.children,
1298 me = this;
1299 for ( var i = 0; i < children.length; i++ ) {
1300 var element = children[ i ].getElement();
1301 element.on( 'propertychange', function( evt ) {
1302 evt = evt.data.$;
1303 if ( evt.propertyName == 'checked' && this.$.checked )
1304 me.fire( 'change', { value: this.getAttribute( 'value' ) } );
1305 } );
1306 }
1307 }, this );
1308 this.on( 'change', func );
1309 }
1310 return null;
1311 }
1312 }
1313 }, commonPrototype, true );
1314
1315 /** @class CKEDITOR.ui.dialog.file */
1316 CKEDITOR.ui.dialog.file.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.labeledElement(), commonPrototype, {
1317 /**
1318 * Gets the `<input>` element of this file input.
1319 *
1320 * @returns {CKEDITOR.dom.element} The file input element.
1321 */
1322 getInputElement: function() {
1323 var frameDocument = CKEDITOR.document.getById( this._.frameId ).getFrameDocument();
1324 return frameDocument.$.forms.length > 0 ? new CKEDITOR.dom.element( frameDocument.$.forms[ 0 ].elements[ 0 ] ) : this.getElement();
1325 },
1326
1327 /**
1328 * Uploads the file in the file input.
1329 *
1330 * @returns {CKEDITOR.ui.dialog.file} This object.
1331 */
1332 submit: function() {
1333 this.getInputElement().getParent().$.submit();
1334 return this;
1335 },
1336
1337 /**
1338 * Gets the action assigned to the form.
1339 *
1340 * @returns {String} The value of the action.
1341 */
1342 getAction: function() {
1343 return this.getInputElement().getParent().$.action;
1344 },
1345
1346 /**
1347 * The events must be applied to the inner input element, and
1348 * this must be done when the iframe and form have been loaded.
1349 */
1350 registerEvents: function( definition ) {
1351 var regex = /^on([A-Z]\w+)/,
1352 match;
1353
1354 var registerDomEvent = function( uiElement, dialog, eventName, func ) {
1355 uiElement.on( 'formLoaded', function() {
1356 uiElement.getInputElement().on( eventName, func, uiElement );
1357 } );
1358 };
1359
1360 for ( var i in definition ) {
1361 if ( !( match = i.match( regex ) ) )
1362 continue;
1363
1364 if ( this.eventProcessors[ i ] )
1365 this.eventProcessors[ i ].call( this, this._.dialog, definition[ i ] );
1366 else
1367 registerDomEvent( this, this._.dialog, match[ 1 ].toLowerCase(), definition[ i ] );
1368 }
1369
1370 return this;
1371 },
1372
1373 /**
1374 * Redraws the file input and resets the file path in the file input.
1375 * The redrawing logic is necessary because non-IE browsers tend to clear
1376 * the `<iframe>` containing the file input after closing the dialog window.
1377 */
1378 reset: function() {
1379 var _ = this._,
1380 frameElement = CKEDITOR.document.getById( _.frameId ),
1381 frameDocument = frameElement.getFrameDocument(),
1382 elementDefinition = _.definition,
1383 buttons = _.buttons,
1384 callNumber = this.formLoadedNumber,
1385 unloadNumber = this.formUnloadNumber,
1386 langDir = _.dialog._.editor.lang.dir,
1387 langCode = _.dialog._.editor.langCode;
1388
1389 // The callback function for the iframe, but we must call tools.addFunction only once
1390 // so we store the function number in this.formLoadedNumber
1391 if ( !callNumber ) {
1392 callNumber = this.formLoadedNumber = CKEDITOR.tools.addFunction( function() {
1393 // Now we can apply the events to the input type=file
1394 this.fire( 'formLoaded' );
1395 }, this );
1396
1397 // Remove listeners attached to the content of the iframe (the file input)
1398 unloadNumber = this.formUnloadNumber = CKEDITOR.tools.addFunction( function() {
1399 this.getInputElement().clearCustomData();
1400 }, this );
1401
1402 this.getDialog()._.editor.on( 'destroy', function() {
1403 CKEDITOR.tools.removeFunction( callNumber );
1404 CKEDITOR.tools.removeFunction( unloadNumber );
1405 } );
1406 }
1407
1408 function generateFormField() {
1409 frameDocument.$.open();
1410
1411 var size = '';
1412 if ( elementDefinition.size )
1413 size = elementDefinition.size - ( CKEDITOR.env.ie ? 7 : 0 ); // "Browse" button is bigger in IE.
1414
1415 var inputId = _.frameId + '_input';
1416
1417 frameDocument.$.write( [
1418 '<html dir="' + langDir + '" lang="' + langCode + '"><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">',
1419 '<form enctype="multipart/form-data" method="POST" dir="' + langDir + '" lang="' + langCode + '" action="',
1420 CKEDITOR.tools.htmlEncode( elementDefinition.action ),
1421 '">',
1422 // Replicate the field label inside of iframe.
1423 '<label id="', _.labelId, '" for="', inputId, '" style="display:none">',
1424 CKEDITOR.tools.htmlEncode( elementDefinition.label ),
1425 '</label>',
1426 // Set width to make sure that input is not clipped by the iframe (#11253).
1427 '<input style="width:100%" id="', inputId, '" aria-labelledby="', _.labelId, '" type="file" name="',
1428 CKEDITOR.tools.htmlEncode( elementDefinition.id || 'cke_upload' ),
1429 '" size="',
1430 CKEDITOR.tools.htmlEncode( size > 0 ? size : '' ),
1431 '" />',
1432 '</form>',
1433 '</body></html>',
1434 '<script>',
1435 // Support for custom document.domain in IE.
1436 CKEDITOR.env.ie ? '(' + CKEDITOR.tools.fixDomain + ')();' : '',
1437
1438 'window.parent.CKEDITOR.tools.callFunction(' + callNumber + ');',
1439 'window.onbeforeunload = function() {window.parent.CKEDITOR.tools.callFunction(' + unloadNumber + ')}',
1440 '</script>'
1441 ].join( '' ) );
1442
1443 frameDocument.$.close();
1444
1445 for ( var i = 0; i < buttons.length; i++ )
1446 buttons[ i ].enable();
1447 }
1448
1449 // #3465: Wait for the browser to finish rendering the dialog first.
1450 if ( CKEDITOR.env.gecko )
1451 setTimeout( generateFormField, 500 );
1452 else
1453 generateFormField();
1454 },
1455
1456 getValue: function() {
1457 return this.getInputElement().$.value || '';
1458 },
1459
1460 /**
1461 * The default value of input `type="file"` is an empty string, but during the initialization
1462 * of this UI element, the iframe still is not ready so it cannot be read from that object.
1463 * Setting it manually prevents later issues with the current value (`''`) being different
1464 * than the initial value (undefined as it asked for `.value` of a div).
1465 */
1466 setInitValue: function() {
1467 this._.initValue = '';
1468 },
1469
1470 /**
1471 * Defines the `onChange` event for UI element definitions.
1472 *
1473 * @property {Object}
1474 */
1475 eventProcessors: {
1476 onChange: function( dialog, func ) {
1477 // If this method is called several times (I'm not sure about how this can happen but the default
1478 // onChange processor includes this protection)
1479 // In order to reapply to the new element, the property is deleted at the beggining of the registerEvents method
1480 if ( !this._.domOnChangeRegistered ) {
1481 // By listening for the formLoaded event, this handler will get reapplied when a new
1482 // form is created
1483 this.on( 'formLoaded', function() {
1484 this.getInputElement().on( 'change', function() {
1485 this.fire( 'change', { value: this.getValue() } );
1486 }, this );
1487 }, this );
1488 this._.domOnChangeRegistered = true;
1489 }
1490
1491 this.on( 'change', func );
1492 }
1493 },
1494
1495 keyboardFocusable: true
1496 }, true );
1497
1498 CKEDITOR.ui.dialog.fileButton.prototype = new CKEDITOR.ui.dialog.button();
1499
1500 CKEDITOR.ui.dialog.fieldset.prototype = CKEDITOR.tools.clone( CKEDITOR.ui.dialog.hbox.prototype );
1501
1502 CKEDITOR.dialog.addUIElement( 'text', textBuilder );
1503 CKEDITOR.dialog.addUIElement( 'password', textBuilder );
1504 CKEDITOR.dialog.addUIElement( 'textarea', commonBuilder );
1505 CKEDITOR.dialog.addUIElement( 'checkbox', commonBuilder );
1506 CKEDITOR.dialog.addUIElement( 'radio', commonBuilder );
1507 CKEDITOR.dialog.addUIElement( 'button', commonBuilder );
1508 CKEDITOR.dialog.addUIElement( 'select', commonBuilder );
1509 CKEDITOR.dialog.addUIElement( 'file', commonBuilder );
1510 CKEDITOR.dialog.addUIElement( 'fileButton', commonBuilder );
1511 CKEDITOR.dialog.addUIElement( 'html', commonBuilder );
1512 CKEDITOR.dialog.addUIElement( 'fieldset', containerBuilder );
1513 }
1514} );
1515
1516/**
1517 * Fired when the value of the uiElement is changed.
1518 *
1519 * @event change
1520 * @member CKEDITOR.ui.dialog.uiElement
1521 */
1522
1523/**
1524 * Fired when the inner frame created by the element is ready.
1525 * Each time the button is used or the dialog window is loaded, a new
1526 * form might be created.
1527 *
1528 * @event formLoaded
1529 * @member CKEDITOR.ui.dialog.fileButton
1530 */
diff --git a/sources/plugins/elementspath/lang/af.js b/sources/plugins/elementspath/lang/af.js
new file mode 100644
index 0000000..c07fa39
--- /dev/null
+++ b/sources/plugins/elementspath/lang/af.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'af', {
6 eleLabel: 'Elemente-pad',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/ar.js b/sources/plugins/elementspath/lang/ar.js
new file mode 100644
index 0000000..fa0147c
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ar.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ar', {
6 eleLabel: 'مسار العنصر',
7 eleTitle: 'عنصر 1%'
8} );
diff --git a/sources/plugins/elementspath/lang/az.js b/sources/plugins/elementspath/lang/az.js
new file mode 100644
index 0000000..c344c1e
--- /dev/null
+++ b/sources/plugins/elementspath/lang/az.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'az', {
6 eleLabel: 'Elementin izləri',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/bg.js b/sources/plugins/elementspath/lang/bg.js
new file mode 100644
index 0000000..07b990b
--- /dev/null
+++ b/sources/plugins/elementspath/lang/bg.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'bg', {
6 eleLabel: 'Път за елементите',
7 eleTitle: '%1 елемент'
8} );
diff --git a/sources/plugins/elementspath/lang/bn.js b/sources/plugins/elementspath/lang/bn.js
new file mode 100644
index 0000000..493caad
--- /dev/null
+++ b/sources/plugins/elementspath/lang/bn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'bn', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/bs.js b/sources/plugins/elementspath/lang/bs.js
new file mode 100644
index 0000000..f432973
--- /dev/null
+++ b/sources/plugins/elementspath/lang/bs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'bs', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/ca.js b/sources/plugins/elementspath/lang/ca.js
new file mode 100644
index 0000000..d9573c2
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ca', {
6 eleLabel: 'Ruta dels elements',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/cs.js b/sources/plugins/elementspath/lang/cs.js
new file mode 100644
index 0000000..427e5bf
--- /dev/null
+++ b/sources/plugins/elementspath/lang/cs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'cs', {
6 eleLabel: 'Cesta objektu',
7 eleTitle: '%1 objekt'
8} );
diff --git a/sources/plugins/elementspath/lang/cy.js b/sources/plugins/elementspath/lang/cy.js
new file mode 100644
index 0000000..5c9c77d
--- /dev/null
+++ b/sources/plugins/elementspath/lang/cy.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'cy', {
6 eleLabel: 'Llwybr elfennau',
7 eleTitle: 'Elfen %1'
8} );
diff --git a/sources/plugins/elementspath/lang/da.js b/sources/plugins/elementspath/lang/da.js
new file mode 100644
index 0000000..3cd404e
--- /dev/null
+++ b/sources/plugins/elementspath/lang/da.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'da', {
6 eleLabel: 'Sti på element',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/de-ch.js b/sources/plugins/elementspath/lang/de-ch.js
new file mode 100644
index 0000000..ad13b78
--- /dev/null
+++ b/sources/plugins/elementspath/lang/de-ch.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'de-ch', {
6 eleLabel: 'Elementepfad',
7 eleTitle: '%1 Element'
8} );
diff --git a/sources/plugins/elementspath/lang/de.js b/sources/plugins/elementspath/lang/de.js
new file mode 100644
index 0000000..5072d3b
--- /dev/null
+++ b/sources/plugins/elementspath/lang/de.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'de', {
6 eleLabel: 'Elementepfad',
7 eleTitle: '%1 Element'
8} );
diff --git a/sources/plugins/elementspath/lang/el.js b/sources/plugins/elementspath/lang/el.js
new file mode 100644
index 0000000..00a4812
--- /dev/null
+++ b/sources/plugins/elementspath/lang/el.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'el', {
6 eleLabel: 'Διαδρομή Στοιχείων',
7 eleTitle: 'Στοιχείο %1'
8} );
diff --git a/sources/plugins/elementspath/lang/en-au.js b/sources/plugins/elementspath/lang/en-au.js
new file mode 100644
index 0000000..60a838a
--- /dev/null
+++ b/sources/plugins/elementspath/lang/en-au.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'en-au', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/en-ca.js b/sources/plugins/elementspath/lang/en-ca.js
new file mode 100644
index 0000000..8acb5c4
--- /dev/null
+++ b/sources/plugins/elementspath/lang/en-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'en-ca', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/en-gb.js b/sources/plugins/elementspath/lang/en-gb.js
new file mode 100644
index 0000000..86fb78e
--- /dev/null
+++ b/sources/plugins/elementspath/lang/en-gb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'en-gb', {
6 eleLabel: 'Elements path',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/en.js b/sources/plugins/elementspath/lang/en.js
new file mode 100644
index 0000000..96feac7
--- /dev/null
+++ b/sources/plugins/elementspath/lang/en.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'en', {
6 eleLabel: 'Elements path',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/eo.js b/sources/plugins/elementspath/lang/eo.js
new file mode 100644
index 0000000..20e0320
--- /dev/null
+++ b/sources/plugins/elementspath/lang/eo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'eo', {
6 eleLabel: 'Vojo al Elementoj',
7 eleTitle: '%1 elementoj'
8} );
diff --git a/sources/plugins/elementspath/lang/es.js b/sources/plugins/elementspath/lang/es.js
new file mode 100644
index 0000000..815a18d
--- /dev/null
+++ b/sources/plugins/elementspath/lang/es.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'es', {
6 eleLabel: 'Ruta de los elementos',
7 eleTitle: '%1 elemento'
8} );
diff --git a/sources/plugins/elementspath/lang/et.js b/sources/plugins/elementspath/lang/et.js
new file mode 100644
index 0000000..ab62d21
--- /dev/null
+++ b/sources/plugins/elementspath/lang/et.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'et', {
6 eleLabel: 'Elementide asukoht',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/eu.js b/sources/plugins/elementspath/lang/eu.js
new file mode 100644
index 0000000..f3d0bb9
--- /dev/null
+++ b/sources/plugins/elementspath/lang/eu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'eu', {
6 eleLabel: 'Elementuen bidea',
7 eleTitle: '%1 elementua'
8} );
diff --git a/sources/plugins/elementspath/lang/fa.js b/sources/plugins/elementspath/lang/fa.js
new file mode 100644
index 0000000..faeb18e
--- /dev/null
+++ b/sources/plugins/elementspath/lang/fa.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'fa', {
6 eleLabel: 'مسیر عناصر',
7 eleTitle: '%1 عنصر'
8} );
diff --git a/sources/plugins/elementspath/lang/fi.js b/sources/plugins/elementspath/lang/fi.js
new file mode 100644
index 0000000..5f975cf
--- /dev/null
+++ b/sources/plugins/elementspath/lang/fi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'fi', {
6 eleLabel: 'Elementin polku',
7 eleTitle: '%1 elementti'
8} );
diff --git a/sources/plugins/elementspath/lang/fo.js b/sources/plugins/elementspath/lang/fo.js
new file mode 100644
index 0000000..0935eb9
--- /dev/null
+++ b/sources/plugins/elementspath/lang/fo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'fo', {
6 eleLabel: 'Slóð til elementir',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/fr-ca.js b/sources/plugins/elementspath/lang/fr-ca.js
new file mode 100644
index 0000000..0b8796c
--- /dev/null
+++ b/sources/plugins/elementspath/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'fr-ca', {
6 eleLabel: 'Chemin d\'éléments',
7 eleTitle: 'element %1'
8} );
diff --git a/sources/plugins/elementspath/lang/fr.js b/sources/plugins/elementspath/lang/fr.js
new file mode 100644
index 0000000..78488bb
--- /dev/null
+++ b/sources/plugins/elementspath/lang/fr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'fr', {
6 eleLabel: 'Chemin des éléments',
7 eleTitle: 'Élément %1'
8} );
diff --git a/sources/plugins/elementspath/lang/gl.js b/sources/plugins/elementspath/lang/gl.js
new file mode 100644
index 0000000..7dfc457
--- /dev/null
+++ b/sources/plugins/elementspath/lang/gl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'gl', {
6 eleLabel: 'Ruta dos elementos',
7 eleTitle: 'Elemento %1'
8} );
diff --git a/sources/plugins/elementspath/lang/gu.js b/sources/plugins/elementspath/lang/gu.js
new file mode 100644
index 0000000..d6f4f40
--- /dev/null
+++ b/sources/plugins/elementspath/lang/gu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'gu', {
6 eleLabel: 'એલીમેન્ટ્સ નો ',
7 eleTitle: 'એલીમેન્ટ %1'
8} );
diff --git a/sources/plugins/elementspath/lang/he.js b/sources/plugins/elementspath/lang/he.js
new file mode 100644
index 0000000..3e2773f
--- /dev/null
+++ b/sources/plugins/elementspath/lang/he.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'he', {
6 eleLabel: 'עץ האלמנטים',
7 eleTitle: '%1 אלמנט'
8} );
diff --git a/sources/plugins/elementspath/lang/hi.js b/sources/plugins/elementspath/lang/hi.js
new file mode 100644
index 0000000..3d514f2
--- /dev/null
+++ b/sources/plugins/elementspath/lang/hi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'hi', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/hr.js b/sources/plugins/elementspath/lang/hr.js
new file mode 100644
index 0000000..90a7fd0
--- /dev/null
+++ b/sources/plugins/elementspath/lang/hr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'hr', {
6 eleLabel: 'Putanja elemenata',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/hu.js b/sources/plugins/elementspath/lang/hu.js
new file mode 100644
index 0000000..23701f2
--- /dev/null
+++ b/sources/plugins/elementspath/lang/hu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'hu', {
6 eleLabel: 'Elem utak',
7 eleTitle: '%1 elem'
8} );
diff --git a/sources/plugins/elementspath/lang/is.js b/sources/plugins/elementspath/lang/is.js
new file mode 100644
index 0000000..b5711de
--- /dev/null
+++ b/sources/plugins/elementspath/lang/is.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'is', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/it.js b/sources/plugins/elementspath/lang/it.js
new file mode 100644
index 0000000..2e3ed4d
--- /dev/null
+++ b/sources/plugins/elementspath/lang/it.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'it', {
6 eleLabel: 'Percorso degli elementi',
7 eleTitle: '%1 elemento'
8} );
diff --git a/sources/plugins/elementspath/lang/ja.js b/sources/plugins/elementspath/lang/ja.js
new file mode 100644
index 0000000..6fba524
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ja.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ja', {
6 eleLabel: '要素パス',
7 eleTitle: '%1 要素'
8} );
diff --git a/sources/plugins/elementspath/lang/ka.js b/sources/plugins/elementspath/lang/ka.js
new file mode 100644
index 0000000..9923902
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ka.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ka', {
6 eleLabel: 'ელემეტის გზა',
7 eleTitle: '%1 ელემენტი'
8} );
diff --git a/sources/plugins/elementspath/lang/km.js b/sources/plugins/elementspath/lang/km.js
new file mode 100644
index 0000000..2fc661d
--- /dev/null
+++ b/sources/plugins/elementspath/lang/km.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'km', {
6 eleLabel: 'ទីតាំង​ធាតុ',
7 eleTitle: 'ធាតុ %1'
8} );
diff --git a/sources/plugins/elementspath/lang/ko.js b/sources/plugins/elementspath/lang/ko.js
new file mode 100644
index 0000000..843a2de
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ko.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ko', {
6 eleLabel: '요소 경로',
7 eleTitle: '%1 요소'
8} );
diff --git a/sources/plugins/elementspath/lang/ku.js b/sources/plugins/elementspath/lang/ku.js
new file mode 100644
index 0000000..f425c90
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ku.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ku', {
6 eleLabel: 'ڕێڕەوی توخمەکان',
7 eleTitle: '%1 توخم'
8} );
diff --git a/sources/plugins/elementspath/lang/lt.js b/sources/plugins/elementspath/lang/lt.js
new file mode 100644
index 0000000..14c5345
--- /dev/null
+++ b/sources/plugins/elementspath/lang/lt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'lt', {
6 eleLabel: 'Elemento kelias',
7 eleTitle: '%1 elementas'
8} );
diff --git a/sources/plugins/elementspath/lang/lv.js b/sources/plugins/elementspath/lang/lv.js
new file mode 100644
index 0000000..7459ce8
--- /dev/null
+++ b/sources/plugins/elementspath/lang/lv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'lv', {
6 eleLabel: 'Elementa ceļš',
7 eleTitle: '%1 elements'
8} );
diff --git a/sources/plugins/elementspath/lang/mk.js b/sources/plugins/elementspath/lang/mk.js
new file mode 100644
index 0000000..3fb1549
--- /dev/null
+++ b/sources/plugins/elementspath/lang/mk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'mk', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/mn.js b/sources/plugins/elementspath/lang/mn.js
new file mode 100644
index 0000000..e3e9285
--- /dev/null
+++ b/sources/plugins/elementspath/lang/mn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'mn', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/ms.js b/sources/plugins/elementspath/lang/ms.js
new file mode 100644
index 0000000..143b4cd
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ms.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ms', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/nb.js b/sources/plugins/elementspath/lang/nb.js
new file mode 100644
index 0000000..d797354
--- /dev/null
+++ b/sources/plugins/elementspath/lang/nb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'nb', {
6 eleLabel: 'Element-sti',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/nl.js b/sources/plugins/elementspath/lang/nl.js
new file mode 100644
index 0000000..14a3585
--- /dev/null
+++ b/sources/plugins/elementspath/lang/nl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'nl', {
6 eleLabel: 'Elementenpad',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/no.js b/sources/plugins/elementspath/lang/no.js
new file mode 100644
index 0000000..64d05f5
--- /dev/null
+++ b/sources/plugins/elementspath/lang/no.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'no', {
6 eleLabel: 'Element-sti',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/oc.js b/sources/plugins/elementspath/lang/oc.js
new file mode 100644
index 0000000..04c1b30
--- /dev/null
+++ b/sources/plugins/elementspath/lang/oc.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'oc', {
6 eleLabel: 'Camin dels elements',
7 eleTitle: 'Element %1'
8} );
diff --git a/sources/plugins/elementspath/lang/pl.js b/sources/plugins/elementspath/lang/pl.js
new file mode 100644
index 0000000..082224d
--- /dev/null
+++ b/sources/plugins/elementspath/lang/pl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'pl', {
6 eleLabel: 'Ścieżka elementów',
7 eleTitle: 'element %1'
8} );
diff --git a/sources/plugins/elementspath/lang/pt-br.js b/sources/plugins/elementspath/lang/pt-br.js
new file mode 100644
index 0000000..ec265b6
--- /dev/null
+++ b/sources/plugins/elementspath/lang/pt-br.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'pt-br', {
6 eleLabel: 'Caminho dos Elementos',
7 eleTitle: 'Elemento %1'
8} );
diff --git a/sources/plugins/elementspath/lang/pt.js b/sources/plugins/elementspath/lang/pt.js
new file mode 100644
index 0000000..5eed642
--- /dev/null
+++ b/sources/plugins/elementspath/lang/pt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'pt', {
6 eleLabel: 'Caminho dos elementos',
7 eleTitle: 'Elemento %1'
8} );
diff --git a/sources/plugins/elementspath/lang/ro.js b/sources/plugins/elementspath/lang/ro.js
new file mode 100644
index 0000000..bc79113
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ro.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ro', {
6 eleLabel: 'Calea elementelor',
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/ru.js b/sources/plugins/elementspath/lang/ru.js
new file mode 100644
index 0000000..ce9529e
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ru.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ru', {
6 eleLabel: 'Путь элементов',
7 eleTitle: 'Элемент %1'
8} );
diff --git a/sources/plugins/elementspath/lang/si.js b/sources/plugins/elementspath/lang/si.js
new file mode 100644
index 0000000..ff4e5dc
--- /dev/null
+++ b/sources/plugins/elementspath/lang/si.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'si', {
6 eleLabel: 'මුලද්‍රව්‍ය මාර්ගය',
7 eleTitle: '%1 මුල'
8} );
diff --git a/sources/plugins/elementspath/lang/sk.js b/sources/plugins/elementspath/lang/sk.js
new file mode 100644
index 0000000..b3eb725
--- /dev/null
+++ b/sources/plugins/elementspath/lang/sk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'sk', {
6 eleLabel: 'Cesta prvkov',
7 eleTitle: '%1 prvok'
8} );
diff --git a/sources/plugins/elementspath/lang/sl.js b/sources/plugins/elementspath/lang/sl.js
new file mode 100644
index 0000000..2d2a1c6
--- /dev/null
+++ b/sources/plugins/elementspath/lang/sl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'sl', {
6 eleLabel: 'Pot elementov',
7 eleTitle: 'Element %1'
8} );
diff --git a/sources/plugins/elementspath/lang/sq.js b/sources/plugins/elementspath/lang/sq.js
new file mode 100644
index 0000000..0018d6f
--- /dev/null
+++ b/sources/plugins/elementspath/lang/sq.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'sq', {
6 eleLabel: 'Rruga e elementeve',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/sr-latn.js b/sources/plugins/elementspath/lang/sr-latn.js
new file mode 100644
index 0000000..65ae9f4
--- /dev/null
+++ b/sources/plugins/elementspath/lang/sr-latn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'sr-latn', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/sr.js b/sources/plugins/elementspath/lang/sr.js
new file mode 100644
index 0000000..80d1ba4
--- /dev/null
+++ b/sources/plugins/elementspath/lang/sr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'sr', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/sv.js b/sources/plugins/elementspath/lang/sv.js
new file mode 100644
index 0000000..e34dd0e
--- /dev/null
+++ b/sources/plugins/elementspath/lang/sv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'sv', {
6 eleLabel: 'Elementets sökväg',
7 eleTitle: '%1 element'
8} );
diff --git a/sources/plugins/elementspath/lang/th.js b/sources/plugins/elementspath/lang/th.js
new file mode 100644
index 0000000..d56fb77
--- /dev/null
+++ b/sources/plugins/elementspath/lang/th.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'th', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 element' // MISSING
8} );
diff --git a/sources/plugins/elementspath/lang/tr.js b/sources/plugins/elementspath/lang/tr.js
new file mode 100644
index 0000000..e32e4ff
--- /dev/null
+++ b/sources/plugins/elementspath/lang/tr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'tr', {
6 eleLabel: 'Elementlerin yolu',
7 eleTitle: '%1 elementi'
8} );
diff --git a/sources/plugins/elementspath/lang/tt.js b/sources/plugins/elementspath/lang/tt.js
new file mode 100644
index 0000000..63b171c
--- /dev/null
+++ b/sources/plugins/elementspath/lang/tt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'tt', {
6 eleLabel: 'Elements path', // MISSING
7 eleTitle: '%1 элемент'
8} );
diff --git a/sources/plugins/elementspath/lang/ug.js b/sources/plugins/elementspath/lang/ug.js
new file mode 100644
index 0000000..5b66e0f
--- /dev/null
+++ b/sources/plugins/elementspath/lang/ug.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'ug', {
6 eleLabel: 'ئېلېمېنت يولى',
7 eleTitle: '%1 ئېلېمېنت'
8} );
diff --git a/sources/plugins/elementspath/lang/uk.js b/sources/plugins/elementspath/lang/uk.js
new file mode 100644
index 0000000..0d247c6
--- /dev/null
+++ b/sources/plugins/elementspath/lang/uk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'uk', {
6 eleLabel: 'Шлях',
7 eleTitle: '%1 елемент'
8} );
diff --git a/sources/plugins/elementspath/lang/vi.js b/sources/plugins/elementspath/lang/vi.js
new file mode 100644
index 0000000..5ba86b4
--- /dev/null
+++ b/sources/plugins/elementspath/lang/vi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'vi', {
6 eleLabel: 'Nhãn thành phần',
7 eleTitle: '%1 thành phần'
8} );
diff --git a/sources/plugins/elementspath/lang/zh-cn.js b/sources/plugins/elementspath/lang/zh-cn.js
new file mode 100644
index 0000000..e585d13
--- /dev/null
+++ b/sources/plugins/elementspath/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'zh-cn', {
6 eleLabel: '元素路径',
7 eleTitle: '%1 元素'
8} );
diff --git a/sources/plugins/elementspath/lang/zh.js b/sources/plugins/elementspath/lang/zh.js
new file mode 100644
index 0000000..5031d0f
--- /dev/null
+++ b/sources/plugins/elementspath/lang/zh.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'zh', {
6 eleLabel: '元件路徑',
7 eleTitle: '%1 個元件'
8} );
diff --git a/sources/plugins/elementspath/plugin.js b/sources/plugins/elementspath/plugin.js
new file mode 100644
index 0000000..07ba5c2
--- /dev/null
+++ b/sources/plugins/elementspath/plugin.js
@@ -0,0 +1,244 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The "elementspath" plugin. It shows all elements in the DOM
8 * parent tree relative to the current selection in the editing area.
9 */
10
11( function() {
12 var commands = {
13 toolbarFocus: {
14 editorFocus: false,
15 readOnly: 1,
16 exec: function( editor ) {
17 var idBase = editor._.elementsPath.idBase;
18 var element = CKEDITOR.document.getById( idBase + '0' );
19
20 // Make the first button focus accessible for IE. (#3417)
21 // Adobe AIR instead need while of delay.
22 element && element.focus( CKEDITOR.env.ie || CKEDITOR.env.air );
23 }
24 }
25 };
26
27 var emptyHtml = '<span class="cke_path_empty">&nbsp;</span>';
28
29 var extra = '';
30
31 // Some browsers don't cancel key events in the keydown but in the
32 // keypress.
33 // TODO: Check if really needed.
34 if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )
35 extra += ' onkeypress="return false;"';
36
37 // With Firefox, we need to force the button to redraw, otherwise it
38 // will remain in the focus state.
39 if ( CKEDITOR.env.gecko )
40 extra += ' onblur="this.style.cssText = this.style.cssText;"';
41
42 var pathItemTpl = CKEDITOR.addTemplate( 'pathItem', '<a' +
43 ' id="{id}"' +
44 ' href="{jsTitle}"' +
45 ' tabindex="-1"' +
46 ' class="cke_path_item"' +
47 ' title="{label}"' +
48 extra +
49 ' hidefocus="true" ' +
50 ' onkeydown="return CKEDITOR.tools.callFunction({keyDownFn},{index}, event );"' +
51 ' onclick="CKEDITOR.tools.callFunction({clickFn},{index}); return false;"' +
52 ' role="button" aria-label="{label}">' +
53 '{text}' +
54 '</a>' );
55
56 CKEDITOR.plugins.add( 'elementspath', {
57 // jscs:disable maximumLineLength
58 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,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%
59 // jscs:enable maximumLineLength
60 init: function( editor ) {
61 editor._.elementsPath = {
62 idBase: 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_',
63 filters: []
64 };
65
66 editor.on( 'uiSpace', function( event ) {
67 if ( event.data.space == 'bottom' )
68 initElementsPath( editor, event.data );
69 } );
70 }
71 } );
72
73 function initElementsPath( editor, bottomSpaceData ) {
74 var spaceId = editor.ui.spaceId( 'path' ),
75 spaceElement,
76 getSpaceElement = function() {
77 if ( !spaceElement )
78 spaceElement = CKEDITOR.document.getById( spaceId );
79 return spaceElement;
80 },
81 elementsPath = editor._.elementsPath,
82 idBase = elementsPath.idBase;
83
84 bottomSpaceData.html += '<span id="' + spaceId + '_label" class="cke_voice_label">' + editor.lang.elementspath.eleLabel + '</span>' +
85 '<span id="' + spaceId + '" class="cke_path" role="group" aria-labelledby="' + spaceId + '_label">' + emptyHtml + '</span>';
86
87 // Register the ui element to the focus manager.
88 editor.on( 'uiReady', function() {
89 var element = editor.ui.space( 'path' );
90 element && editor.focusManager.add( element, 1 );
91 } );
92
93 function onClick( elementIndex ) {
94 var element = elementsPath.list[ elementIndex ],
95 selection;
96
97 if ( element.equals( editor.editable() ) || element.getAttribute( 'contenteditable' ) == 'true' ) {
98 var range = editor.createRange();
99 range.selectNodeContents( element );
100
101 selection = range.select();
102 } else {
103 selection = editor.getSelection();
104 selection.selectElement( element );
105 }
106
107 // Explicitly fire selectionChange when clicking on an element path button. (#13548)
108 if ( CKEDITOR.env.ie ) {
109 editor.fire( 'selectionChange', { selection: selection, path: new CKEDITOR.dom.elementPath( element ) } );
110 }
111
112 // It is important to focus() *after* the above selection
113 // manipulation, otherwise Firefox will have troubles. #10119
114 editor.focus();
115 }
116
117 elementsPath.onClick = onClick;
118
119 var onClickHanlder = CKEDITOR.tools.addFunction( onClick ),
120 onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) {
121 var idBase = elementsPath.idBase,
122 element;
123
124 ev = new CKEDITOR.dom.event( ev );
125
126 var rtl = editor.lang.dir == 'rtl';
127 switch ( ev.getKeystroke() ) {
128 case rtl ? 39 : 37: // LEFT-ARROW
129 case 9: // TAB
130 element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) );
131 if ( !element )
132 element = CKEDITOR.document.getById( idBase + '0' );
133 element.focus();
134 return false;
135
136 case rtl ? 37 : 39: // RIGHT-ARROW
137 case CKEDITOR.SHIFT + 9: // SHIFT + TAB
138 element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) );
139 if ( !element )
140 element = CKEDITOR.document.getById( idBase + ( elementsPath.list.length - 1 ) );
141 element.focus();
142 return false;
143
144 case 27: // ESC
145 editor.focus();
146 return false;
147
148 case 13: // ENTER // Opera
149 case 32: // SPACE
150 onClick( elementIndex );
151 return false;
152 }
153 return true;
154 } );
155
156 editor.on( 'selectionChange', function() {
157 var html = [],
158 elementsList = elementsPath.list = [],
159 namesList = [],
160 filters = elementsPath.filters,
161 isContentEditable = true,
162
163 // Use elementPath to consider children of editable only (#11124).
164 elementsChain = editor.elementPath().elements,
165 name;
166
167 // Starts iteration from body element, skipping html.
168 for ( var j = elementsChain.length; j--; ) {
169 var element = elementsChain[ j ],
170 ignore = 0;
171
172 if ( element.data( 'cke-display-name' ) )
173 name = element.data( 'cke-display-name' );
174 else if ( element.data( 'cke-real-element-type' ) )
175 name = element.data( 'cke-real-element-type' );
176 else
177 name = element.getName();
178
179 isContentEditable = element.hasAttribute( 'contenteditable' ) ?
180 element.getAttribute( 'contenteditable' ) == 'true' : isContentEditable;
181
182 // If elem is non-contenteditable, and it's not specifying contenteditable
183 // attribute - then elem should be ignored.
184 if ( !isContentEditable && !element.hasAttribute( 'contenteditable' ) )
185 ignore = 1;
186
187 for ( var i = 0; i < filters.length; i++ ) {
188 var ret = filters[ i ]( element, name );
189 if ( ret === false ) {
190 ignore = 1;
191 break;
192 }
193 name = ret || name;
194 }
195
196 if ( !ignore ) {
197 elementsList.unshift( element );
198 namesList.unshift( name );
199 }
200 }
201
202 for ( var iterationLimit = elementsList.length, index = 0; index < iterationLimit; index++ ) {
203 name = namesList[ index ];
204 var label = editor.lang.elementspath.eleTitle.replace( /%1/, name ),
205 item = pathItemTpl.output( {
206 id: idBase + index,
207 label: label,
208 text: name,
209 jsTitle: 'javascript:void(\'' + name + '\')', // jshint ignore:line
210 index: index,
211 keyDownFn: onKeyDownHandler,
212 clickFn: onClickHanlder
213 } );
214
215 html.unshift( item );
216 }
217
218 var space = getSpaceElement();
219 space.setHtml( html.join( '' ) + emptyHtml );
220 editor.fire( 'elementsPathUpdate', { space: space } );
221 } );
222
223 function empty() {
224 spaceElement && spaceElement.setHtml( emptyHtml );
225 delete elementsPath.list;
226 }
227
228 editor.on( 'readOnly', empty );
229 editor.on( 'contentDomUnload', empty );
230
231 editor.addCommand( 'elementsPathFocus', commands.toolbarFocus );
232 editor.setKeystroke( CKEDITOR.ALT + 122 /*F11*/, 'elementsPathFocus' );
233 }
234} )();
235
236/**
237 * Fired when the contents of the elementsPath are changed.
238 *
239 * @event elementsPathUpdate
240 * @member CKEDITOR.editor
241 * @param {CKEDITOR.editor} editor This editor instance.
242 * @param data
243 * @param {CKEDITOR.dom.element} data.space The elementsPath container.
244 */
diff --git a/sources/plugins/enterkey/plugin.js b/sources/plugins/enterkey/plugin.js
new file mode 100644
index 0000000..9410bbd
--- /dev/null
+++ b/sources/plugins/enterkey/plugin.js
@@ -0,0 +1,566 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 CKEDITOR.plugins.add( 'enterkey', {
8 init: function( editor ) {
9 editor.addCommand( 'enter', {
10 modes: { wysiwyg: 1 },
11 editorFocus: false,
12 exec: function( editor ) {
13 enter( editor );
14 }
15 } );
16
17 editor.addCommand( 'shiftEnter', {
18 modes: { wysiwyg: 1 },
19 editorFocus: false,
20 exec: function( editor ) {
21 shiftEnter( editor );
22 }
23 } );
24
25 editor.setKeystroke( [
26 [ 13, 'enter' ],
27 [ CKEDITOR.SHIFT + 13, 'shiftEnter' ]
28 ] );
29 }
30 } );
31
32 var whitespaces = CKEDITOR.dom.walker.whitespaces(),
33 bookmark = CKEDITOR.dom.walker.bookmark();
34
35 CKEDITOR.plugins.enterkey = {
36 enterBlock: function( editor, mode, range, forceMode ) {
37 // Get the range for the current selection.
38 range = range || getRange( editor );
39
40 // We may not have valid ranges to work on, like when inside a
41 // contenteditable=false element.
42 if ( !range )
43 return;
44
45 // When range is in nested editable, we have to replace range with this one,
46 // which have root property set to closest editable, to make auto paragraphing work. (#12162)
47 range = replaceRangeWithClosestEditableRoot( range );
48
49 var doc = range.document;
50
51 var atBlockStart = range.checkStartOfBlock(),
52 atBlockEnd = range.checkEndOfBlock(),
53 path = editor.elementPath( range.startContainer ),
54 block = path.block,
55
56 // Determine the block element to be used.
57 blockTag = ( mode == CKEDITOR.ENTER_DIV ? 'div' : 'p' ),
58
59 newBlock;
60
61 // Exit the list when we're inside an empty list item block. (#5376)
62 if ( atBlockStart && atBlockEnd ) {
63 // Exit the list when we're inside an empty list item block. (#5376)
64 if ( block && ( block.is( 'li' ) || block.getParent().is( 'li' ) ) ) {
65 // Make sure to point to the li when dealing with empty list item.
66 if ( !block.is( 'li' ) )
67 block = block.getParent();
68
69 var blockParent = block.getParent(),
70 blockGrandParent = blockParent.getParent(),
71
72 firstChild = !block.hasPrevious(),
73 lastChild = !block.hasNext(),
74
75 selection = editor.getSelection(),
76 bookmarks = selection.createBookmarks(),
77
78 orgDir = block.getDirection( 1 ),
79 className = block.getAttribute( 'class' ),
80 style = block.getAttribute( 'style' ),
81 dirLoose = blockGrandParent.getDirection( 1 ) != orgDir,
82
83 enterMode = editor.enterMode,
84 needsBlock = enterMode != CKEDITOR.ENTER_BR || dirLoose || style || className,
85
86 child;
87
88 if ( blockGrandParent.is( 'li' ) ) {
89
90 // If block is the first or the last child of the parent
91 // list, degrade it and move to the outer list:
92 // before the parent list if block is first child and after
93 // the parent list if block is the last child, respectively.
94 //
95 // <ul> => <ul>
96 // <li> => <li>
97 // <ul> => <ul>
98 // <li>x</li> => <li>x</li>
99 // <li>^</li> => </ul>
100 // </ul> => </li>
101 // </li> => <li>^</li>
102 // </ul> => </ul>
103 //
104 // AND
105 //
106 // <ul> => <ul>
107 // <li> => <li>^</li>
108 // <ul> => <li>
109 // <li>^</li> => <ul>
110 // <li>x</li> => <li>x</li>
111 // </ul> => </ul>
112 // </li> => </li>
113 // </ul> => </ul>
114
115 if ( firstChild || lastChild ) {
116
117 // If it's only child, we don't want to keep perent ul anymore.
118 if ( firstChild && lastChild ) {
119 blockParent.remove();
120 }
121
122 block[lastChild ? 'insertAfter' : 'insertBefore']( blockGrandParent );
123
124 // If the empty block is neither first nor last child
125 // then split the list and the block as an element
126 // of outer list.
127 //
128 // => <ul>
129 // => <li>
130 // <ul> => <ul>
131 // <li> => <li>x</li>
132 // <ul> => </ul>
133 // <li>x</li> => </li>
134 // <li>^</li> => <li>^</li>
135 // <li>y</li> => <li>
136 // </ul> => <ul>
137 // </li> => <li>y</li>
138 // </ul> => </ul>
139 // => </li>
140 // => </ul>
141
142 } else {
143 block.breakParent( blockGrandParent );
144 }
145 }
146
147 else if ( !needsBlock ) {
148 block.appendBogus( true );
149
150 // If block is the first or last child of the parent
151 // list, move all block's children out of the list:
152 // before the list if block is first child and after the list
153 // if block is the last child, respectively.
154 //
155 // <ul> => <ul>
156 // <li>x</li> => <li>x</li>
157 // <li>^</li> => </ul>
158 // </ul> => ^
159 //
160 // AND
161 //
162 // <ul> => ^
163 // <li>^</li> => <ul>
164 // <li>x</li> => <li>x</li>
165 // </ul> => </ul>
166
167 if ( firstChild || lastChild ) {
168 while ( ( child = block[ firstChild ? 'getFirst' : 'getLast' ]() ) )
169 child[ firstChild ? 'insertBefore' : 'insertAfter' ]( blockParent );
170 }
171
172 // If the empty block is neither first nor last child
173 // then split the list and put all the block contents
174 // between two lists.
175 //
176 // <ul> => <ul>
177 // <li>x</li> => <li>x</li>
178 // <li>^</li> => </ul>
179 // <li>y</li> => ^
180 // </ul> => <ul>
181 // => <li>y</li>
182 // => </ul>
183
184 else {
185 block.breakParent( blockParent );
186
187 while ( ( child = block.getLast() ) )
188 child.insertAfter( blockParent );
189 }
190
191 block.remove();
192 } else {
193 // Original path block is the list item, create new block for the list item content.
194 if ( path.block.is( 'li' ) ) {
195 // Use <div> block for ENTER_BR and ENTER_DIV.
196 newBlock = doc.createElement( mode == CKEDITOR.ENTER_P ? 'p' : 'div' );
197
198 if ( dirLoose )
199 newBlock.setAttribute( 'dir', orgDir );
200
201 style && newBlock.setAttribute( 'style', style );
202 className && newBlock.setAttribute( 'class', className );
203
204 // Move all the child nodes to the new block.
205 block.moveChildren( newBlock );
206 }
207 // The original path block is not a list item, just copy the block to out side of the list.
208 else {
209 newBlock = path.block;
210 }
211
212 // If block is the first or last child of the parent
213 // list, move it out of the list:
214 // before the list if block is first child and after the list
215 // if block is the last child, respectively.
216 //
217 // <ul> => <ul>
218 // <li>x</li> => <li>x</li>
219 // <li>^</li> => </ul>
220 // </ul> => <p>^</p>
221 //
222 // AND
223 //
224 // <ul> => <p>^</p>
225 // <li>^</li> => <ul>
226 // <li>x</li> => <li>x</li>
227 // </ul> => </ul>
228
229 if ( firstChild || lastChild )
230 newBlock[ firstChild ? 'insertBefore' : 'insertAfter' ]( blockParent );
231
232 // If the empty block is neither first nor last child
233 // then split the list and put the new block between
234 // two lists.
235 //
236 // => <ul>
237 // <ul> => <li>x</li>
238 // <li>x</li> => </ul>
239 // <li>^</li> => <p>^</p>
240 // <li>y</li> => <ul>
241 // </ul> => <li>y</li>
242 // => </ul>
243
244 else {
245 block.breakParent( blockParent );
246 newBlock.insertAfter( blockParent );
247 }
248
249 block.remove();
250 }
251
252 selection.selectBookmarks( bookmarks );
253
254 return;
255 }
256
257 if ( block && block.getParent().is( 'blockquote' ) ) {
258 block.breakParent( block.getParent() );
259
260 // If we were at the start of <blockquote>, there will be an empty element before it now.
261 if ( !block.getPrevious().getFirst( CKEDITOR.dom.walker.invisible( 1 ) ) )
262 block.getPrevious().remove();
263
264 // If we were at the end of <blockquote>, there will be an empty element after it now.
265 if ( !block.getNext().getFirst( CKEDITOR.dom.walker.invisible( 1 ) ) )
266 block.getNext().remove();
267
268 range.moveToElementEditStart( block );
269 range.select();
270 return;
271 }
272 }
273 // Don't split <pre> if we're in the middle of it, act as shift enter key.
274 else if ( block && block.is( 'pre' ) ) {
275 if ( !atBlockEnd ) {
276 enterBr( editor, mode, range, forceMode );
277 return;
278 }
279 }
280
281 // Split the range.
282 var splitInfo = range.splitBlock( blockTag );
283
284 if ( !splitInfo )
285 return;
286
287 // Get the current blocks.
288 var previousBlock = splitInfo.previousBlock,
289 nextBlock = splitInfo.nextBlock;
290
291 var isStartOfBlock = splitInfo.wasStartOfBlock,
292 isEndOfBlock = splitInfo.wasEndOfBlock;
293
294 var node;
295
296 // If this is a block under a list item, split it as well. (#1647)
297 if ( nextBlock ) {
298 node = nextBlock.getParent();
299 if ( node.is( 'li' ) ) {
300 nextBlock.breakParent( node );
301 nextBlock.move( nextBlock.getNext(), 1 );
302 }
303 } else if ( previousBlock && ( node = previousBlock.getParent() ) && node.is( 'li' ) ) {
304 previousBlock.breakParent( node );
305 node = previousBlock.getNext();
306 range.moveToElementEditStart( node );
307 previousBlock.move( previousBlock.getPrevious() );
308 }
309
310 // If we have both the previous and next blocks, it means that the
311 // boundaries were on separated blocks, or none of them where on the
312 // block limits (start/end).
313 if ( !isStartOfBlock && !isEndOfBlock ) {
314 // If the next block is an <li> with another list tree as the first
315 // child, we'll need to append a filler (<br>/NBSP) or the list item
316 // wouldn't be editable. (#1420)
317 if ( nextBlock.is( 'li' ) ) {
318 var walkerRange = range.clone();
319 walkerRange.selectNodeContents( nextBlock );
320 var walker = new CKEDITOR.dom.walker( walkerRange );
321 walker.evaluator = function( node ) {
322 return !( bookmark( node ) || whitespaces( node ) || node.type == CKEDITOR.NODE_ELEMENT && node.getName() in CKEDITOR.dtd.$inline && !( node.getName() in CKEDITOR.dtd.$empty ) );
323 };
324
325 node = walker.next();
326 if ( node && node.type == CKEDITOR.NODE_ELEMENT && node.is( 'ul', 'ol' ) )
327 ( CKEDITOR.env.needsBrFiller ? doc.createElement( 'br' ) : doc.createText( '\xa0' ) ).insertBefore( node );
328 }
329
330 // Move the selection to the end block.
331 if ( nextBlock )
332 range.moveToElementEditStart( nextBlock );
333 } else {
334 var newBlockDir;
335
336 if ( previousBlock ) {
337 // Do not enter this block if it's a header tag, or we are in
338 // a Shift+Enter (#77). Create a new block element instead
339 // (later in the code).
340 if ( previousBlock.is( 'li' ) || !( headerTagRegex.test( previousBlock.getName() ) || previousBlock.is( 'pre' ) ) ) {
341 // Otherwise, duplicate the previous block.
342 newBlock = previousBlock.clone();
343 }
344 } else if ( nextBlock ) {
345 newBlock = nextBlock.clone();
346 }
347
348 if ( !newBlock ) {
349 // We have already created a new list item. (#6849)
350 if ( node && node.is( 'li' ) )
351 newBlock = node;
352 else {
353 newBlock = doc.createElement( blockTag );
354 if ( previousBlock && ( newBlockDir = previousBlock.getDirection() ) )
355 newBlock.setAttribute( 'dir', newBlockDir );
356 }
357 }
358 // Force the enter block unless we're talking of a list item.
359 else if ( forceMode && !newBlock.is( 'li' ) ) {
360 newBlock.renameNode( blockTag );
361 }
362
363 // Recreate the inline elements tree, which was available
364 // before hitting enter, so the same styles will be available in
365 // the new block.
366 var elementPath = splitInfo.elementPath;
367 if ( elementPath ) {
368 for ( var i = 0, len = elementPath.elements.length; i < len; i++ ) {
369 var element = elementPath.elements[ i ];
370
371 if ( element.equals( elementPath.block ) || element.equals( elementPath.blockLimit ) )
372 break;
373
374 if ( CKEDITOR.dtd.$removeEmpty[ element.getName() ] ) {
375 element = element.clone();
376 newBlock.moveChildren( element );
377 newBlock.append( element );
378 }
379 }
380 }
381
382 newBlock.appendBogus();
383
384 if ( !newBlock.getParent() )
385 range.insertNode( newBlock );
386
387 // list item start number should not be duplicated (#7330), but we need
388 // to remove the attribute after it's onto the DOM tree because of old IEs (#7581).
389 newBlock.is( 'li' ) && newBlock.removeAttribute( 'value' );
390
391 // This is tricky, but to make the new block visible correctly
392 // we must select it.
393 // The previousBlock check has been included because it may be
394 // empty if we have fixed a block-less space (like ENTER into an
395 // empty table cell).
396 if ( CKEDITOR.env.ie && isStartOfBlock && ( !isEndOfBlock || !previousBlock.getChildCount() ) ) {
397 // Move the selection to the new block.
398 range.moveToElementEditStart( isEndOfBlock ? previousBlock : newBlock );
399 range.select();
400 }
401
402 // Move the selection to the new block.
403 range.moveToElementEditStart( isStartOfBlock && !isEndOfBlock ? nextBlock : newBlock );
404 }
405
406 range.select();
407 range.scrollIntoView();
408 },
409
410 enterBr: function( editor, mode, range, forceMode ) {
411 // Get the range for the current selection.
412 range = range || getRange( editor );
413
414 // We may not have valid ranges to work on, like when inside a
415 // contenteditable=false element.
416 if ( !range )
417 return;
418
419 var doc = range.document;
420
421 var isEndOfBlock = range.checkEndOfBlock();
422
423 var elementPath = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() );
424
425 var startBlock = elementPath.block,
426 startBlockTag = startBlock && elementPath.block.getName();
427
428 if ( !forceMode && startBlockTag == 'li' ) {
429 enterBlock( editor, mode, range, forceMode );
430 return;
431 }
432
433 // If we are at the end of a header block.
434 if ( !forceMode && isEndOfBlock && headerTagRegex.test( startBlockTag ) ) {
435 var newBlock, newBlockDir;
436
437 if ( ( newBlockDir = startBlock.getDirection() ) ) {
438 newBlock = doc.createElement( 'div' );
439 newBlock.setAttribute( 'dir', newBlockDir );
440 newBlock.insertAfter( startBlock );
441 range.setStart( newBlock, 0 );
442 } else {
443 // Insert a <br> after the current paragraph.
444 doc.createElement( 'br' ).insertAfter( startBlock );
445
446 // A text node is required by Gecko only to make the cursor blink.
447 if ( CKEDITOR.env.gecko )
448 doc.createText( '' ).insertAfter( startBlock );
449
450 // IE has different behaviors regarding position.
451 range.setStartAt( startBlock.getNext(), CKEDITOR.env.ie ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_START );
452 }
453 } else {
454 var lineBreak;
455
456 // IE<8 prefers text node as line-break inside of <pre> (#4711).
457 if ( startBlockTag == 'pre' && CKEDITOR.env.ie && CKEDITOR.env.version < 8 )
458 lineBreak = doc.createText( '\r' );
459 else
460 lineBreak = doc.createElement( 'br' );
461
462 range.deleteContents();
463 range.insertNode( lineBreak );
464
465 // Old IEs have different behavior regarding position.
466 if ( !CKEDITOR.env.needsBrFiller )
467 range.setStartAt( lineBreak, CKEDITOR.POSITION_AFTER_END );
468 else {
469 // A text node is required by Gecko only to make the cursor blink.
470 // We need some text inside of it, so the bogus <br> is properly
471 // created.
472 doc.createText( '\ufeff' ).insertAfter( lineBreak );
473
474 // If we are at the end of a block, we must be sure the bogus node is available in that block.
475 if ( isEndOfBlock ) {
476 // In most situations we've got an elementPath.block (e.g. <p>), but in a
477 // blockless editor or when autoP is false that needs to be a block limit.
478 ( startBlock || elementPath.blockLimit ).appendBogus();
479 }
480
481 // Now we can remove the text node contents, so the caret doesn't
482 // stop on it.
483 lineBreak.getNext().$.nodeValue = '';
484
485 range.setStartAt( lineBreak.getNext(), CKEDITOR.POSITION_AFTER_START );
486
487 }
488 }
489
490 // This collapse guarantees the cursor will be blinking.
491 range.collapse( true );
492
493 range.select();
494 range.scrollIntoView();
495 }
496 };
497
498 var plugin = CKEDITOR.plugins.enterkey,
499 enterBr = plugin.enterBr,
500 enterBlock = plugin.enterBlock,
501 headerTagRegex = /^h[1-6]$/;
502
503 function shiftEnter( editor ) {
504 // On SHIFT+ENTER:
505 // 1. We want to enforce the mode to be respected, instead
506 // of cloning the current block. (#77)
507 return enter( editor, editor.activeShiftEnterMode, 1 );
508 }
509
510 function enter( editor, mode, forceMode ) {
511 forceMode = editor.config.forceEnterMode || forceMode;
512
513 // Only effective within document.
514 if ( editor.mode != 'wysiwyg' )
515 return;
516
517 if ( !mode )
518 mode = editor.activeEnterMode;
519
520 // TODO this should be handled by setting editor.activeEnterMode on selection change.
521 // Check path block specialities:
522 // 1. Cannot be a un-splittable element, e.g. table caption;
523 var path = editor.elementPath();
524 if ( !path.isContextFor( 'p' ) ) {
525 mode = CKEDITOR.ENTER_BR;
526 forceMode = 1;
527 }
528
529 editor.fire( 'saveSnapshot' ); // Save undo step.
530
531 if ( mode == CKEDITOR.ENTER_BR )
532 enterBr( editor, mode, null, forceMode );
533 else
534 enterBlock( editor, mode, null, forceMode );
535
536 editor.fire( 'saveSnapshot' );
537 }
538
539 function getRange( editor ) {
540 // Get the selection ranges.
541 var ranges = editor.getSelection().getRanges( true );
542
543 // Delete the contents of all ranges except the first one.
544 for ( var i = ranges.length - 1; i > 0; i-- ) {
545 ranges[ i ].deleteContents();
546 }
547
548 // Return the first range.
549 return ranges[ 0 ];
550 }
551
552 function replaceRangeWithClosestEditableRoot( range ) {
553 var closestEditable = range.startContainer.getAscendant( function( node ) {
554 return node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'true';
555 }, true );
556
557 if ( range.root.equals( closestEditable ) ) {
558 return range;
559 } else {
560 var newRange = new CKEDITOR.dom.range( closestEditable );
561
562 newRange.moveToRange( range );
563 return newRange;
564 }
565 }
566} )();
diff --git a/sources/plugins/enterkey/samples/enterkey.html b/sources/plugins/enterkey/samples/enterkey.html
new file mode 100644
index 0000000..79afee3
--- /dev/null
+++ b/sources/plugins/enterkey/samples/enterkey.html
@@ -0,0 +1,106 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>ENTER Key Configuration &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link href="../../../samples/old/sample.css" rel="stylesheet">
12 <meta name="ckeditor-sample-name" content="Using the &quot;Enter&quot; key in CKEditor">
13 <meta name="ckeditor-sample-group" content="Advanced Samples">
14 <meta name="ckeditor-sample-description" content="Configuring the behavior of &lt;em&gt;Enter&lt;/em&gt; and &lt;em&gt;Shift+Enter&lt;/em&gt; keys.">
15 <script>
16
17 var editor;
18
19 function changeEnter() {
20 // If we already have an editor, let's destroy it first.
21 if ( editor )
22 editor.destroy( true );
23
24 // Create the editor again, with the appropriate settings.
25 editor = CKEDITOR.replace( 'editor1', {
26 extraPlugins: 'enterkey',
27 enterMode: Number( document.getElementById( 'xEnter' ).value ),
28 shiftEnterMode: Number( document.getElementById( 'xShiftEnter' ).value )
29 });
30 }
31
32 window.onload = changeEnter;
33
34 </script>
35</head>
36<body>
37 <h1 class="samples">
38 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; ENTER Key Configuration
39 </h1>
40 <div class="warning deprecated">
41 This sample is not maintained anymore. Check out its <a href="http://sdk.ckeditor.com/samples/enterkey.html">brand new version in CKEditor SDK</a>.
42 </div>
43 <div class="description">
44 <p>
45 This sample shows how to configure the <em>Enter</em> and <em>Shift+Enter</em> keys
46 to perform actions specified in the
47 <a class="samples" href="http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-enterMode"><code>enterMode</code></a>
48 and <a class="samples" href="http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-shiftEnterMode"><code>shiftEnterMode</code></a>
49 parameters, respectively.
50 You can choose from the following options:
51 </p>
52 <ul class="samples">
53 <li><strong><code>ENTER_P</code></strong> &ndash; new <code>&lt;p&gt;</code> paragraphs are created;</li>
54 <li><strong><code>ENTER_BR</code></strong> &ndash; lines are broken with <code>&lt;br&gt;</code> elements;</li>
55 <li><strong><code>ENTER_DIV</code></strong> &ndash; new <code>&lt;div&gt;</code> blocks are created.</li>
56 </ul>
57 <p>
58 The sample code below shows how to configure CKEditor to create a <code>&lt;div&gt;</code> block when <em>Enter</em> key is pressed.
59 </p>
60<pre class="samples">
61CKEDITOR.replace( '<em>textarea_id</em>', {
62 <strong>enterMode: CKEDITOR.ENTER_DIV</strong>
63});</pre>
64 <p>
65 Note that <code><em>textarea_id</em></code> in the code above is the <code>id</code> attribute of
66 the <code>&lt;textarea&gt;</code> element to be replaced.
67 </p>
68 </div>
69 <div style="float: left; margin-right: 20px">
70 When <em>Enter</em> is pressed:<br>
71 <select id="xEnter" onchange="changeEnter();">
72 <option selected="selected" value="1">Create a new &lt;P&gt; (recommended)</option>
73 <option value="3">Create a new &lt;DIV&gt;</option>
74 <option value="2">Break the line with a &lt;BR&gt;</option>
75 </select>
76 </div>
77 <div style="float: left">
78 When <em>Shift+Enter</em> is pressed:<br>
79 <select id="xShiftEnter" onchange="changeEnter();">
80 <option value="1">Create a new &lt;P&gt;</option>
81 <option value="3">Create a new &lt;DIV&gt;</option>
82 <option selected="selected" value="2">Break the line with a &lt;BR&gt; (recommended)</option>
83 </select>
84 </div>
85 <br style="clear: both">
86 <form action="../../../samples/sample_posteddata.php" method="post">
87 <p>
88 <br>
89 <textarea cols="80" id="editor1" name="editor1" rows="10">This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.</textarea>
90 </p>
91 <p>
92 <input type="submit" value="Submit">
93 </p>
94 </form>
95 <div id="footer">
96 <hr>
97 <p>
98 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
99 </p>
100 <p id="copy">
101 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
102 Knabben. All rights reserved.
103 </p>
104 </div>
105</body>
106</html>
diff --git a/sources/plugins/entities/plugin.js b/sources/plugins/entities/plugin.js
new file mode 100644
index 0000000..d457ad1
--- /dev/null
+++ b/sources/plugins/entities/plugin.js
@@ -0,0 +1,239 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 // Basic HTML entities.
8 var htmlbase = 'nbsp,gt,lt,amp';
9
10 var entities =
11 // Latin-1 entities
12 'quot,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,' +
13 'not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,' +
14 'cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,' +
15
16 // Symbols
17 'fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,' +
18 'alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,' +
19 'forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,' +
20 'radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,' +
21 'equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,' +
22 'rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,' +
23
24 // Other special characters
25 'circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,' +
26 'rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,' +
27 'euro';
28
29 // Latin letters entities
30 var latin = 'Agrave,Aacute,Acirc,Atilde,Auml,Aring,AElig,Ccedil,Egrave,Eacute,' +
31 'Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,' +
32 'Otilde,Ouml,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,' +
33 'agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil,egrave,eacute,' +
34 'ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,' +
35 'otilde,ouml,oslash,ugrave,uacute,ucirc,uuml,yacute,thorn,yuml,' +
36 'OElig,oelig,Scaron,scaron,Yuml';
37
38 // Greek letters entities.
39 var greek = 'Alpha,Beta,Gamma,Delta,Epsilon,Zeta,Eta,Theta,Iota,Kappa,Lambda,Mu,' +
40 'Nu,Xi,Omicron,Pi,Rho,Sigma,Tau,Upsilon,Phi,Chi,Psi,Omega,alpha,' +
41 'beta,gamma,delta,epsilon,zeta,eta,theta,iota,kappa,lambda,mu,nu,xi,' +
42 'omicron,pi,rho,sigmaf,sigma,tau,upsilon,phi,chi,psi,omega,thetasym,' +
43 'upsih,piv';
44
45 // Create a mapping table between one character and its entity form from a list of entity names.
46 // @param reverse {Boolean} Whether to create a reverse map from the entity string form to an actual character.
47 function buildTable( entities, reverse ) {
48 var table = {},
49 regex = [];
50
51 // Entities that the browsers' DOM does not automatically transform to the
52 // final character.
53 var specialTable = {
54 nbsp: '\u00A0', // IE | FF
55 shy: '\u00AD', // IE
56 gt: '\u003E', // IE | FF | -- | Opera
57 lt: '\u003C', // IE | FF | Safari | Opera
58 amp: '\u0026', // ALL
59 apos: '\u0027', // IE
60 quot: '\u0022' // IE
61 };
62
63 entities = entities.replace( /\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g, function( match, entity ) {
64 var org = reverse ? '&' + entity + ';' : specialTable[ entity ],
65 result = reverse ? specialTable[ entity ] : '&' + entity + ';';
66
67 table[ org ] = result;
68 regex.push( org );
69 return '';
70 } );
71
72 if ( !reverse && entities ) {
73 // Transforms the entities string into an array.
74 entities = entities.split( ',' );
75
76 // Put all entities inside a DOM element, transforming them to their
77 // final characters.
78 var div = document.createElement( 'div' ),
79 chars;
80 div.innerHTML = '&' + entities.join( ';&' ) + ';';
81 chars = div.innerHTML;
82 div = null;
83
84 // Add all characters to the table.
85 for ( var i = 0; i < chars.length; i++ ) {
86 var charAt = chars.charAt( i );
87 table[ charAt ] = '&' + entities[ i ] + ';';
88 regex.push( charAt );
89 }
90 }
91
92 table.regex = regex.join( reverse ? '|' : '' );
93
94 return table;
95 }
96
97 CKEDITOR.plugins.add( 'entities', {
98 afterInit: function( editor ) {
99 var config = editor.config;
100
101 function getChar( character ) {
102 return baseEntitiesTable[ character ];
103 }
104
105 function getEntity( character ) {
106 return config.entities_processNumerical == 'force' || !entitiesTable[ character ] ? '&#' + character.charCodeAt( 0 ) + ';'
107 : entitiesTable[ character ];
108 }
109
110 var dataProcessor = editor.dataProcessor,
111 htmlFilter = dataProcessor && dataProcessor.htmlFilter;
112
113 if ( htmlFilter ) {
114 // Mandatory HTML basic entities.
115 var selectedEntities = [];
116
117 if ( config.basicEntities !== false )
118 selectedEntities.push( htmlbase );
119
120 if ( config.entities ) {
121 if ( selectedEntities.length )
122 selectedEntities.push( entities );
123
124 if ( config.entities_latin )
125 selectedEntities.push( latin );
126
127 if ( config.entities_greek )
128 selectedEntities.push( greek );
129
130 if ( config.entities_additional )
131 selectedEntities.push( config.entities_additional );
132 }
133
134 var entitiesTable = buildTable( selectedEntities.join( ',' ) );
135
136 // Create the Regex used to find entities in the text, leave it matches nothing if entities are empty.
137 var entitiesRegex = entitiesTable.regex ? '[' + entitiesTable.regex + ']' : 'a^';
138 delete entitiesTable.regex;
139
140 if ( config.entities && config.entities_processNumerical )
141 entitiesRegex = '[^ -~]|' + entitiesRegex;
142
143 entitiesRegex = new RegExp( entitiesRegex, 'g' );
144
145 // Decode entities that the browsers has transformed
146 // at first place.
147 var baseEntitiesTable = buildTable( [ htmlbase, 'shy' ].join( ',' ), true ),
148 baseEntitiesRegex = new RegExp( baseEntitiesTable.regex, 'g' );
149
150 htmlFilter.addRules( {
151 text: function( text ) {
152 return text.replace( baseEntitiesRegex, getChar ).replace( entitiesRegex, getEntity );
153 }
154 }, {
155 applyToAll: true,
156 excludeNestedEditable: true
157 } );
158 }
159 }
160 } );
161} )();
162
163/**
164 * Whether to escape basic HTML entities in the document, including:
165 *
166 * * `&nbsp;`
167 * * `&gt;`
168 * * `&lt;`
169 * * `&amp;`
170 *
171 * **Note:** This option should not be changed unless when outputting a non-HTML data format like BBCode.
172 *
173 * config.basicEntities = false;
174 *
175 * @cfg {Boolean} [basicEntities=true]
176 * @member CKEDITOR.config
177 */
178CKEDITOR.config.basicEntities = true;
179
180/**
181 * Whether to use HTML entities in the editor output.
182 *
183 * config.entities = false;
184 *
185 * @cfg {Boolean} [entities=true]
186 * @member CKEDITOR.config
187 */
188CKEDITOR.config.entities = true;
189
190/**
191 * Whether to convert some Latin characters (Latin alphabet No. 1, ISO 8859-1)
192 * to HTML entities. The list of entities can be found in the
193 * [W3C HTML 4.01 Specification, section 24.2.1](http://www.w3.org/TR/html4/sgml/entities.html#h-24.2.1).
194 *
195 * config.entities_latin = false;
196 *
197 * @cfg {Boolean} [entities_latin=true]
198 * @member CKEDITOR.config
199 */
200CKEDITOR.config.entities_latin = true;
201
202/**
203 * Whether to convert some symbols, mathematical symbols, and Greek letters to
204 * HTML entities. This may be more relevant for users typing text written in Greek.
205 * The list of entities can be found in the
206 * [W3C HTML 4.01 Specification, section 24.3.1](http://www.w3.org/TR/html4/sgml/entities.html#h-24.3.1).
207 *
208 * config.entities_greek = false;
209 *
210 * @cfg {Boolean} [entities_greek=true]
211 * @member CKEDITOR.config
212 */
213CKEDITOR.config.entities_greek = true;
214
215/**
216 * Whether to convert all remaining characters not included in the ASCII
217 * character table to their relative decimal numeric representation of HTML entity.
218 * When set to `force`, it will convert all entities into this format.
219 *
220 * For example the phrase: `'This is Chinese: 汉语.'` would be output
221 * as: `'This is Chinese: &#27721;&#35821;.'`
222 *
223 * config.entities_processNumerical = true;
224 * config.entities_processNumerical = 'force'; // Converts from '&nbsp;' into '&#160;';
225 *
226 * @cfg {Boolean/String} [entities_processNumerical=false]
227 * @member CKEDITOR.config
228 */
229
230/**
231 * A comma-separated list of additional entities to be used. Entity names
232 * or numbers must be used in a form that excludes the `'&amp;'` prefix and the `';'` ending.
233 *
234 * config.entities_additional = '#1049'; // Adds Cyrillic capital letter Short I (Й).
235 *
236 * @cfg {String} [entities_additional='#39' (The single quote (') character)]
237 * @member CKEDITOR.config
238 */
239CKEDITOR.config.entities_additional = '#39';
diff --git a/sources/plugins/fakeobjects/lang/af.js b/sources/plugins/fakeobjects/lang/af.js
new file mode 100644
index 0000000..835d45b
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/af.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'af', {
6 anchor: 'Anker',
7 flash: 'Flash animasie',
8 hiddenfield: 'Verborge veld',
9 iframe: 'IFrame',
10 unknown: 'Onbekende objek'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ar.js b/sources/plugins/fakeobjects/lang/ar.js
new file mode 100644
index 0000000..44363c9
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ar.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ar', {
6 anchor: 'إرساء',
7 flash: 'رسم متحرك بالفلاش',
8 hiddenfield: 'إدراج حقل خفي',
9 iframe: 'iframe',
10 unknown: 'عنصر غير معروف'
11} );
diff --git a/sources/plugins/fakeobjects/lang/az.js b/sources/plugins/fakeobjects/lang/az.js
new file mode 100644
index 0000000..01fa87d
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/az.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'az', {
6 anchor: 'Lövbər',
7 flash: 'Flash animasiya',
8 hiddenfield: 'Gizli xana',
9 iframe: 'IFrame',
10 unknown: 'Tanımamış obyekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/bg.js b/sources/plugins/fakeobjects/lang/bg.js
new file mode 100644
index 0000000..538cdf1
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/bg.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'bg', {
6 anchor: 'Кука',
7 flash: 'Флаш анимация',
8 hiddenfield: 'Скрито поле',
9 iframe: 'IFrame',
10 unknown: 'Неизвестен обект'
11} );
diff --git a/sources/plugins/fakeobjects/lang/bn.js b/sources/plugins/fakeobjects/lang/bn.js
new file mode 100644
index 0000000..70c9ce9
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/bn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'bn', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/bs.js b/sources/plugins/fakeobjects/lang/bs.js
new file mode 100644
index 0000000..4a17242
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/bs.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'bs', {
6 anchor: 'Anchor',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/ca.js b/sources/plugins/fakeobjects/lang/ca.js
new file mode 100644
index 0000000..cc09e6c
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ca.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ca', {
6 anchor: 'Àncora',
7 flash: 'Animació Flash',
8 hiddenfield: 'Camp ocult',
9 iframe: 'IFrame',
10 unknown: 'Objecte desconegut'
11} );
diff --git a/sources/plugins/fakeobjects/lang/cs.js b/sources/plugins/fakeobjects/lang/cs.js
new file mode 100644
index 0000000..7355f4a
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/cs.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'cs', {
6 anchor: 'Záložka',
7 flash: 'Flash animace',
8 hiddenfield: 'Skryté pole',
9 iframe: 'IFrame',
10 unknown: 'Neznámý objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/cy.js b/sources/plugins/fakeobjects/lang/cy.js
new file mode 100644
index 0000000..8b0ffc9
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/cy.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'cy', {
6 anchor: 'Angor',
7 flash: 'Animeiddiant Flash',
8 hiddenfield: 'Maes Cudd',
9 iframe: 'IFrame',
10 unknown: 'Gwrthrych Anhysbys'
11} );
diff --git a/sources/plugins/fakeobjects/lang/da.js b/sources/plugins/fakeobjects/lang/da.js
new file mode 100644
index 0000000..06a869f
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/da.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'da', {
6 anchor: 'Anker',
7 flash: 'Flashanimation',
8 hiddenfield: 'Skjult felt',
9 iframe: 'Iframe',
10 unknown: 'Ukendt objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/de-ch.js b/sources/plugins/fakeobjects/lang/de-ch.js
new file mode 100644
index 0000000..068a003
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/de-ch.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'de-ch', {
6 anchor: 'Anker',
7 flash: 'Flash-Animation',
8 hiddenfield: 'Verstecktes Feld',
9 iframe: 'IFrame',
10 unknown: 'Unbekanntes Objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/de.js b/sources/plugins/fakeobjects/lang/de.js
new file mode 100644
index 0000000..32326cf
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/de.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'de', {
6 anchor: 'Anker',
7 flash: 'Flash-Animation',
8 hiddenfield: 'Verstecktes Feld',
9 iframe: 'IFrame',
10 unknown: 'Unbekanntes Objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/el.js b/sources/plugins/fakeobjects/lang/el.js
new file mode 100644
index 0000000..211c8d4
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/el.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'el', {
6 anchor: 'Άγκυρα',
7 flash: 'Ταινία Flash',
8 hiddenfield: 'Κρυφό Πεδίο',
9 iframe: 'IFrame',
10 unknown: 'Άγνωστο Αντικείμενο'
11} );
diff --git a/sources/plugins/fakeobjects/lang/en-au.js b/sources/plugins/fakeobjects/lang/en-au.js
new file mode 100644
index 0000000..189e5c8
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/en-au.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'en-au', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/en-ca.js b/sources/plugins/fakeobjects/lang/en-ca.js
new file mode 100644
index 0000000..071bc10
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/en-ca.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'en-ca', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/en-gb.js b/sources/plugins/fakeobjects/lang/en-gb.js
new file mode 100644
index 0000000..e38f16c
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/en-gb.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'en-gb', {
6 anchor: 'Anchor',
7 flash: 'Flash Animation',
8 hiddenfield: 'Hidden Field',
9 iframe: 'IFrame',
10 unknown: 'Unknown Object'
11} );
diff --git a/sources/plugins/fakeobjects/lang/en.js b/sources/plugins/fakeobjects/lang/en.js
new file mode 100644
index 0000000..d871231
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/en.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'en', {
6 anchor: 'Anchor',
7 flash: 'Flash Animation',
8 hiddenfield: 'Hidden Field',
9 iframe: 'IFrame',
10 unknown: 'Unknown Object'
11} );
diff --git a/sources/plugins/fakeobjects/lang/eo.js b/sources/plugins/fakeobjects/lang/eo.js
new file mode 100644
index 0000000..bbce7f8
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/eo.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'eo', {
6 anchor: 'Ankro',
7 flash: 'FlaŝAnimacio',
8 hiddenfield: 'Kaŝita kampo',
9 iframe: 'Enlinia Kadro (IFrame)',
10 unknown: 'Nekonata objekto'
11} );
diff --git a/sources/plugins/fakeobjects/lang/es.js b/sources/plugins/fakeobjects/lang/es.js
new file mode 100644
index 0000000..46ac72f
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/es.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'es', {
6 anchor: 'Ancla',
7 flash: 'Animación flash',
8 hiddenfield: 'Campo oculto',
9 iframe: 'IFrame',
10 unknown: 'Objeto desconocido'
11} );
diff --git a/sources/plugins/fakeobjects/lang/et.js b/sources/plugins/fakeobjects/lang/et.js
new file mode 100644
index 0000000..2c25f43
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/et.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'et', {
6 anchor: 'Ankur',
7 flash: 'Flashi animatsioon',
8 hiddenfield: 'Varjatud väli',
9 iframe: 'IFrame',
10 unknown: 'Tundmatu objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/eu.js b/sources/plugins/fakeobjects/lang/eu.js
new file mode 100644
index 0000000..dfc4460
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/eu.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'eu', {
6 anchor: 'Aingura',
7 flash: 'Flash animazioa',
8 hiddenfield: 'Ezkutuko eremua',
9 iframe: 'IFrame-a',
10 unknown: 'Objektu ezezaguna'
11} );
diff --git a/sources/plugins/fakeobjects/lang/fa.js b/sources/plugins/fakeobjects/lang/fa.js
new file mode 100644
index 0000000..4104d1f
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/fa.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'fa', {
6 anchor: 'لنگر',
7 flash: 'انیمشن فلش',
8 hiddenfield: 'فیلد پنهان',
9 iframe: 'IFrame',
10 unknown: 'شیء ناشناخته'
11} );
diff --git a/sources/plugins/fakeobjects/lang/fi.js b/sources/plugins/fakeobjects/lang/fi.js
new file mode 100644
index 0000000..c663093
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/fi.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'fi', {
6 anchor: 'Ankkuri',
7 flash: 'Flash animaatio',
8 hiddenfield: 'Piilokenttä',
9 iframe: 'IFrame-kehys',
10 unknown: 'Tuntematon objekti'
11} );
diff --git a/sources/plugins/fakeobjects/lang/fo.js b/sources/plugins/fakeobjects/lang/fo.js
new file mode 100644
index 0000000..8b7c2f9
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/fo.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'fo', {
6 anchor: 'Anchor',
7 flash: 'Flash Animation',
8 hiddenfield: 'Fjaldur teigur',
9 iframe: 'IFrame',
10 unknown: 'Ókent Object'
11} );
diff --git a/sources/plugins/fakeobjects/lang/fr-ca.js b/sources/plugins/fakeobjects/lang/fr-ca.js
new file mode 100644
index 0000000..c281f4f
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/fr-ca.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'fr-ca', {
6 anchor: 'Ancre',
7 flash: 'Animation Flash',
8 hiddenfield: 'Champ caché',
9 iframe: 'IFrame',
10 unknown: 'Objet inconnu'
11} );
diff --git a/sources/plugins/fakeobjects/lang/fr.js b/sources/plugins/fakeobjects/lang/fr.js
new file mode 100644
index 0000000..be306ec
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/fr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'fr', {
6 anchor: 'Ancre',
7 flash: 'Animation Flash',
8 hiddenfield: 'Champ invisible',
9 iframe: 'Cadre de contenu incorporé',
10 unknown: 'Objet inconnu'
11} );
diff --git a/sources/plugins/fakeobjects/lang/gl.js b/sources/plugins/fakeobjects/lang/gl.js
new file mode 100644
index 0000000..2c353a4
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/gl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'gl', {
6 anchor: 'Ancoraxe',
7 flash: 'Animación «Flash»',
8 hiddenfield: 'Campo agochado',
9 iframe: 'IFrame',
10 unknown: 'Obxecto descoñecido'
11} );
diff --git a/sources/plugins/fakeobjects/lang/gu.js b/sources/plugins/fakeobjects/lang/gu.js
new file mode 100644
index 0000000..66fb428
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/gu.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'gu', {
6 anchor: 'અનકર',
7 flash: 'ફ્લેશ ',
8 hiddenfield: 'હિડન ',
9 iframe: 'IFrame',
10 unknown: 'અનનોન ઓબ્જેક્ટ'
11} );
diff --git a/sources/plugins/fakeobjects/lang/he.js b/sources/plugins/fakeobjects/lang/he.js
new file mode 100644
index 0000000..bc0d472
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/he.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'he', {
6 anchor: 'עוגן',
7 flash: 'סרטון פלאש',
8 hiddenfield: 'שדה חבוי',
9 iframe: 'חלון פנימי (iframe)',
10 unknown: 'אובייקט לא ידוע'
11} );
diff --git a/sources/plugins/fakeobjects/lang/hi.js b/sources/plugins/fakeobjects/lang/hi.js
new file mode 100644
index 0000000..e2cc724
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/hi.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'hi', {
6 anchor: 'ऐंकर इन्सर्ट/संपादन',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'गुप्त फ़ील्ड',
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/hr.js b/sources/plugins/fakeobjects/lang/hr.js
new file mode 100644
index 0000000..11f3574
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/hr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'hr', {
6 anchor: 'Sidro',
7 flash: 'Flash animacija',
8 hiddenfield: 'Sakriveno polje',
9 iframe: 'IFrame',
10 unknown: 'Nepoznati objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/hu.js b/sources/plugins/fakeobjects/lang/hu.js
new file mode 100644
index 0000000..24cec55
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/hu.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'hu', {
6 anchor: 'Horgony',
7 flash: 'Flash animáció',
8 hiddenfield: 'Rejtett mezõ',
9 iframe: 'IFrame',
10 unknown: 'Ismeretlen objektum'
11} );
diff --git a/sources/plugins/fakeobjects/lang/id.js b/sources/plugins/fakeobjects/lang/id.js
new file mode 100644
index 0000000..85d8c14
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/id.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'id', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Animasi Flash',
8 hiddenfield: 'Kolom Tersembunyi',
9 iframe: 'IFrame',
10 unknown: 'Obyek Tak Dikenal'
11} );
diff --git a/sources/plugins/fakeobjects/lang/is.js b/sources/plugins/fakeobjects/lang/is.js
new file mode 100644
index 0000000..40df479
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/is.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'is', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/it.js b/sources/plugins/fakeobjects/lang/it.js
new file mode 100644
index 0000000..8993951
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/it.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'it', {
6 anchor: 'Ancora',
7 flash: 'Animazione Flash',
8 hiddenfield: 'Campo Nascosto',
9 iframe: 'IFrame',
10 unknown: 'Oggetto sconosciuto'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ja.js b/sources/plugins/fakeobjects/lang/ja.js
new file mode 100644
index 0000000..db21eeb
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ja.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ja', {
6 anchor: 'アンカー',
7 flash: 'Flash Animation',
8 hiddenfield: '不可視フィールド',
9 iframe: 'IFrame',
10 unknown: 'Unknown Object'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ka.js b/sources/plugins/fakeobjects/lang/ka.js
new file mode 100644
index 0000000..3544161
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ka.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ka', {
6 anchor: 'ღუზა',
7 flash: 'Flash ანიმაცია',
8 hiddenfield: 'მალული ველი',
9 iframe: 'IFrame',
10 unknown: 'უცნობი ობიექტი'
11} );
diff --git a/sources/plugins/fakeobjects/lang/km.js b/sources/plugins/fakeobjects/lang/km.js
new file mode 100644
index 0000000..54be6d0
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/km.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'km', {
6 anchor: 'យុថ្កា',
7 flash: 'Flash មាន​ចលនា',
8 hiddenfield: 'វាល​កំបាំង',
9 iframe: 'IFrame',
10 unknown: 'វត្ថុ​មិន​ស្គាល់'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ko.js b/sources/plugins/fakeobjects/lang/ko.js
new file mode 100644
index 0000000..b5c0593
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ko.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ko', {
6 anchor: '책갈피',
7 flash: '플래시 애니메이션',
8 hiddenfield: '숨은 입력 칸',
9 iframe: '아이프레임',
10 unknown: '알 수 없는 객체'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ku.js b/sources/plugins/fakeobjects/lang/ku.js
new file mode 100644
index 0000000..bbfb9f6
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ku.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ku', {
6 anchor: 'لەنگەر',
7 flash: 'فلاش',
8 hiddenfield: 'شاردنەوەی خانه',
9 iframe: 'لەچوارچێوە',
10 unknown: 'بەرکارێکی نەناسراو'
11} );
diff --git a/sources/plugins/fakeobjects/lang/lt.js b/sources/plugins/fakeobjects/lang/lt.js
new file mode 100644
index 0000000..e14c211
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/lt.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'lt', {
6 anchor: 'Žymė',
7 flash: 'Flash animacija',
8 hiddenfield: 'Paslėptas laukas',
9 iframe: 'IFrame',
10 unknown: 'Nežinomas objektas'
11} );
diff --git a/sources/plugins/fakeobjects/lang/lv.js b/sources/plugins/fakeobjects/lang/lv.js
new file mode 100644
index 0000000..388e486
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/lv.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'lv', {
6 anchor: 'Iezīme',
7 flash: 'Flash animācija',
8 hiddenfield: 'Slēpts lauks',
9 iframe: 'Iframe',
10 unknown: 'Nezināms objekts'
11} );
diff --git a/sources/plugins/fakeobjects/lang/mk.js b/sources/plugins/fakeobjects/lang/mk.js
new file mode 100644
index 0000000..deacc87
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/mk.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'mk', {
6 anchor: 'Anchor',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Скриено поле',
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/mn.js b/sources/plugins/fakeobjects/lang/mn.js
new file mode 100644
index 0000000..a2857cc
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/mn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'mn', {
6 anchor: 'Зангуу',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Нууц талбар',
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/ms.js b/sources/plugins/fakeobjects/lang/ms.js
new file mode 100644
index 0000000..7325f14
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ms.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ms', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/nb.js b/sources/plugins/fakeobjects/lang/nb.js
new file mode 100644
index 0000000..b6a6527
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/nb.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'nb', {
6 anchor: 'Anker',
7 flash: 'Flash-animasjon',
8 hiddenfield: 'Skjult felt',
9 iframe: 'IFrame',
10 unknown: 'Ukjent objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/nl.js b/sources/plugins/fakeobjects/lang/nl.js
new file mode 100644
index 0000000..158985a
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/nl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'nl', {
6 anchor: 'Interne link',
7 flash: 'Flash animatie',
8 hiddenfield: 'Verborgen veld',
9 iframe: 'IFrame',
10 unknown: 'Onbekend object'
11} );
diff --git a/sources/plugins/fakeobjects/lang/no.js b/sources/plugins/fakeobjects/lang/no.js
new file mode 100644
index 0000000..cbbb4cf
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/no.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'no', {
6 anchor: 'Anker',
7 flash: 'Flash-animasjon',
8 hiddenfield: 'Skjult felt',
9 iframe: 'IFrame',
10 unknown: 'Ukjent objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/oc.js b/sources/plugins/fakeobjects/lang/oc.js
new file mode 100644
index 0000000..0ecfcf8
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/oc.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'oc', {
6 anchor: 'Ancòra',
7 flash: 'Animacion Flash',
8 hiddenfield: 'Camp invisible',
9 iframe: 'Quadre de contengut incorporat',
10 unknown: 'Objècte desconegut'
11} );
diff --git a/sources/plugins/fakeobjects/lang/pl.js b/sources/plugins/fakeobjects/lang/pl.js
new file mode 100644
index 0000000..06b3a20
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/pl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'pl', {
6 anchor: 'Kotwica',
7 flash: 'Animacja Flash',
8 hiddenfield: 'Pole ukryte',
9 iframe: 'IFrame',
10 unknown: 'Nieznany obiekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/pt-br.js b/sources/plugins/fakeobjects/lang/pt-br.js
new file mode 100644
index 0000000..6198bf3
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/pt-br.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'pt-br', {
6 anchor: 'Âncora',
7 flash: 'Animação em Flash',
8 hiddenfield: 'Campo Oculto',
9 iframe: 'IFrame',
10 unknown: 'Objeto desconhecido'
11} );
diff --git a/sources/plugins/fakeobjects/lang/pt.js b/sources/plugins/fakeobjects/lang/pt.js
new file mode 100644
index 0000000..c3d762f
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/pt.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'pt', {
6 anchor: ' Inserir/Editar âncora',
7 flash: 'Animação Flash',
8 hiddenfield: 'Campo oculto',
9 iframe: 'IFrame',
10 unknown: 'Objeto desconhecido'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ro.js b/sources/plugins/fakeobjects/lang/ro.js
new file mode 100644
index 0000000..25535d3
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ro.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ro', {
6 anchor: 'Inserează/Editează ancoră',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Câmp ascuns (HiddenField)',
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/ru.js b/sources/plugins/fakeobjects/lang/ru.js
new file mode 100644
index 0000000..7f93bc7
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ru.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ru', {
6 anchor: 'Якорь',
7 flash: 'Flash анимация',
8 hiddenfield: 'Скрытое поле',
9 iframe: 'iFrame',
10 unknown: 'Неизвестный объект'
11} );
diff --git a/sources/plugins/fakeobjects/lang/si.js b/sources/plugins/fakeobjects/lang/si.js
new file mode 100644
index 0000000..319240b
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/si.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'si', {
6 anchor: 'ආධාරය',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'සැඟවුණු ප්‍රදේශය',
9 iframe: 'IFrame',
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/sk.js b/sources/plugins/fakeobjects/lang/sk.js
new file mode 100644
index 0000000..1372c54
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/sk.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'sk', {
6 anchor: 'Kotva',
7 flash: 'Flash animácia',
8 hiddenfield: 'Skryté pole',
9 iframe: 'IFrame',
10 unknown: 'Neznámy objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/sl.js b/sources/plugins/fakeobjects/lang/sl.js
new file mode 100644
index 0000000..f6d9827
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/sl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'sl', {
6 anchor: 'Sidro',
7 flash: 'Animacija flash',
8 hiddenfield: 'Skrito polje',
9 iframe: 'IFrame',
10 unknown: 'Neznan objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/sq.js b/sources/plugins/fakeobjects/lang/sq.js
new file mode 100644
index 0000000..05f0987
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/sq.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'sq', {
6 anchor: 'Spirancë',
7 flash: 'Objekt flash',
8 hiddenfield: 'Fushë e fshehur',
9 iframe: 'IFrame',
10 unknown: 'Objekt i Panjohur'
11} );
diff --git a/sources/plugins/fakeobjects/lang/sr-latn.js b/sources/plugins/fakeobjects/lang/sr-latn.js
new file mode 100644
index 0000000..fb497f0
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/sr-latn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'sr-latn', {
6 anchor: 'Unesi/izmeni sidro',
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Skriveno polje',
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/sr.js b/sources/plugins/fakeobjects/lang/sr.js
new file mode 100644
index 0000000..82a59cb
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/sr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'sr', {
6 anchor: 'Anchor', // MISSING
7 flash: 'Flash Animation', // MISSING
8 hiddenfield: 'Hidden Field', // MISSING
9 iframe: 'IFrame', // MISSING
10 unknown: 'Unknown Object' // MISSING
11} );
diff --git a/sources/plugins/fakeobjects/lang/sv.js b/sources/plugins/fakeobjects/lang/sv.js
new file mode 100644
index 0000000..3db31fb
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/sv.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'sv', {
6 anchor: 'Ankare',
7 flash: 'Flashanimation',
8 hiddenfield: 'Gömt fält',
9 iframe: 'iFrame',
10 unknown: 'Okänt objekt'
11} );
diff --git a/sources/plugins/fakeobjects/lang/th.js b/sources/plugins/fakeobjects/lang/th.js
new file mode 100644
index 0000000..c0d1f4e
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/th.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'th', {
6 anchor: 'แทรก/แก้ไข Anchor',
7 flash: 'ภาพอนิเมชั่นแฟลช',
8 hiddenfield: 'ฮิดเดนฟิลด์',
9 iframe: 'IFrame',
10 unknown: 'วัตถุไม่ทราบชนิด'
11} );
diff --git a/sources/plugins/fakeobjects/lang/tr.js b/sources/plugins/fakeobjects/lang/tr.js
new file mode 100644
index 0000000..768b7c1
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/tr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'tr', {
6 anchor: 'Bağlantı',
7 flash: 'Flash Animasyonu',
8 hiddenfield: 'Gizli Alan',
9 iframe: 'IFrame',
10 unknown: 'Bilinmeyen Nesne'
11} );
diff --git a/sources/plugins/fakeobjects/lang/tt.js b/sources/plugins/fakeobjects/lang/tt.js
new file mode 100644
index 0000000..df1a714
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/tt.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'tt', {
6 anchor: 'Якорь',
7 flash: 'Флеш анимациясы',
8 hiddenfield: 'Яшерен кыр',
9 iframe: 'IFrame',
10 unknown: 'Танылмаган объект'
11} );
diff --git a/sources/plugins/fakeobjects/lang/ug.js b/sources/plugins/fakeobjects/lang/ug.js
new file mode 100644
index 0000000..c44b8de
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/ug.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'ug', {
6 anchor: 'لەڭگەرلىك نۇقتا',
7 flash: 'Flash جانلاندۇرۇم',
8 hiddenfield: 'يوشۇرۇن دائىرە',
9 iframe: 'IFrame',
10 unknown: 'يوچۇن نەڭ'
11} );
diff --git a/sources/plugins/fakeobjects/lang/uk.js b/sources/plugins/fakeobjects/lang/uk.js
new file mode 100644
index 0000000..81da8ca
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/uk.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'uk', {
6 anchor: 'Якір',
7 flash: 'Flash-анімація',
8 hiddenfield: 'Приховані Поля',
9 iframe: 'IFrame',
10 unknown: 'Невідомий об\'єкт'
11} );
diff --git a/sources/plugins/fakeobjects/lang/vi.js b/sources/plugins/fakeobjects/lang/vi.js
new file mode 100644
index 0000000..f1346aa
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/vi.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'vi', {
6 anchor: 'Điểm neo',
7 flash: 'Flash',
8 hiddenfield: 'Trường ẩn',
9 iframe: 'IFrame',
10 unknown: 'Đối tượng không rõ ràng'
11} );
diff --git a/sources/plugins/fakeobjects/lang/zh-cn.js b/sources/plugins/fakeobjects/lang/zh-cn.js
new file mode 100644
index 0000000..8d304c2
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/zh-cn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'zh-cn', {
6 anchor: '锚点',
7 flash: 'Flash 动画',
8 hiddenfield: '隐藏域',
9 iframe: 'IFrame',
10 unknown: '未知对象'
11} );
diff --git a/sources/plugins/fakeobjects/lang/zh.js b/sources/plugins/fakeobjects/lang/zh.js
new file mode 100644
index 0000000..1255003
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/zh.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'fakeobjects', 'zh', {
6 anchor: '錨點',
7 flash: 'Flash 動畫',
8 hiddenfield: '隱藏欄位',
9 iframe: 'IFrame',
10 unknown: '無法辨識的物件'
11} );
diff --git a/sources/plugins/fakeobjects/plugin.js b/sources/plugins/fakeobjects/plugin.js
new file mode 100644
index 0000000..d35698b
--- /dev/null
+++ b/sources/plugins/fakeobjects/plugin.js
@@ -0,0 +1,183 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 var cssStyle = CKEDITOR.htmlParser.cssStyle,
8 cssLength = CKEDITOR.tools.cssLength;
9
10 var cssLengthRegex = /^((?:\d*(?:\.\d+))|(?:\d+))(.*)?$/i;
11
12 // Replacing the former CSS length value with the later one, with
13 // adjustment to the length unit.
14 function replaceCssLength( length1, length2 ) {
15 var parts1 = cssLengthRegex.exec( length1 ),
16 parts2 = cssLengthRegex.exec( length2 );
17
18 // Omit pixel length unit when necessary,
19 // e.g. replaceCssLength( 10, '20px' ) -> 20
20 if ( parts1 ) {
21 if ( !parts1[ 2 ] && parts2[ 2 ] == 'px' )
22 return parts2[ 1 ];
23 if ( parts1[ 2 ] == 'px' && !parts2[ 2 ] )
24 return parts2[ 1 ] + 'px';
25 }
26
27 return length2;
28 }
29
30 var htmlFilterRules = {
31 elements: {
32 $: function( element ) {
33 var attributes = element.attributes,
34 realHtml = attributes && attributes[ 'data-cke-realelement' ],
35 realFragment = realHtml && new CKEDITOR.htmlParser.fragment.fromHtml( decodeURIComponent( realHtml ) ),
36 realElement = realFragment && realFragment.children[ 0 ];
37
38 // Width/height in the fake object are subjected to clone into the real element.
39 if ( realElement && element.attributes[ 'data-cke-resizable' ] ) {
40 var styles = new cssStyle( element ).rules,
41 realAttrs = realElement.attributes,
42 width = styles.width,
43 height = styles.height;
44
45 width && ( realAttrs.width = replaceCssLength( realAttrs.width, width ) );
46 height && ( realAttrs.height = replaceCssLength( realAttrs.height, height ) );
47 }
48
49 return realElement;
50 }
51 }
52 };
53
54 CKEDITOR.plugins.add( 'fakeobjects', {
55 // jscs:disable maximumLineLength
56 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
57 // jscs:enable maximumLineLength
58
59 init: function( editor ) {
60 // Allow image with all styles and classes plus src, alt and title attributes.
61 // We need them when fakeobject is pasted.
62 editor.filter.allow( 'img[!data-cke-realelement,src,alt,title](*){*}', 'fakeobjects' );
63 },
64
65 afterInit: function( editor ) {
66 var dataProcessor = editor.dataProcessor,
67 htmlFilter = dataProcessor && dataProcessor.htmlFilter;
68
69 if ( htmlFilter ) {
70 htmlFilter.addRules( htmlFilterRules, {
71 applyToAll: true
72 } );
73 }
74 }
75 } );
76
77 /**
78 * @member CKEDITOR.editor
79 * @todo
80 */
81 CKEDITOR.editor.prototype.createFakeElement = function( realElement, className, realElementType, isResizable ) {
82 var lang = this.lang.fakeobjects,
83 label = lang[ realElementType ] || lang.unknown;
84
85 var attributes = {
86 'class': className,
87 'data-cke-realelement': encodeURIComponent( realElement.getOuterHtml() ),
88 'data-cke-real-node-type': realElement.type,
89 alt: label,
90 title: label,
91 align: realElement.getAttribute( 'align' ) || ''
92 };
93
94 // Do not set "src" on high-contrast so the alt text is displayed. (#8945)
95 if ( !CKEDITOR.env.hc )
96 attributes.src = CKEDITOR.tools.transparentImageData;
97
98 if ( realElementType )
99 attributes[ 'data-cke-real-element-type' ] = realElementType;
100
101 if ( isResizable ) {
102 attributes[ 'data-cke-resizable' ] = isResizable;
103
104 var fakeStyle = new cssStyle();
105
106 var width = realElement.getAttribute( 'width' ),
107 height = realElement.getAttribute( 'height' );
108
109 width && ( fakeStyle.rules.width = cssLength( width ) );
110 height && ( fakeStyle.rules.height = cssLength( height ) );
111 fakeStyle.populate( attributes );
112 }
113
114 return this.document.createElement( 'img', { attributes: attributes } );
115 };
116
117 /**
118 * @member CKEDITOR.editor
119 * @todo
120 */
121 CKEDITOR.editor.prototype.createFakeParserElement = function( realElement, className, realElementType, isResizable ) {
122 var lang = this.lang.fakeobjects,
123 label = lang[ realElementType ] || lang.unknown,
124 html;
125
126 var writer = new CKEDITOR.htmlParser.basicWriter();
127 realElement.writeHtml( writer );
128 html = writer.getHtml();
129
130 var attributes = {
131 'class': className,
132 'data-cke-realelement': encodeURIComponent( html ),
133 'data-cke-real-node-type': realElement.type,
134 alt: label,
135 title: label,
136 align: realElement.attributes.align || ''
137 };
138
139 // Do not set "src" on high-contrast so the alt text is displayed. (#8945)
140 if ( !CKEDITOR.env.hc )
141 attributes.src = CKEDITOR.tools.transparentImageData;
142
143 if ( realElementType )
144 attributes[ 'data-cke-real-element-type' ] = realElementType;
145
146 if ( isResizable ) {
147 attributes[ 'data-cke-resizable' ] = isResizable;
148 var realAttrs = realElement.attributes,
149 fakeStyle = new cssStyle();
150
151 var width = realAttrs.width,
152 height = realAttrs.height;
153
154 width !== undefined && ( fakeStyle.rules.width = cssLength( width ) );
155 height !== undefined && ( fakeStyle.rules.height = cssLength( height ) );
156 fakeStyle.populate( attributes );
157 }
158
159 return new CKEDITOR.htmlParser.element( 'img', attributes );
160 };
161
162 /**
163 * @member CKEDITOR.editor
164 * @todo
165 */
166 CKEDITOR.editor.prototype.restoreRealElement = function( fakeElement ) {
167 if ( fakeElement.data( 'cke-real-node-type' ) != CKEDITOR.NODE_ELEMENT )
168 return null;
169
170 var element = CKEDITOR.dom.element.createFromHtml( decodeURIComponent( fakeElement.data( 'cke-realelement' ) ), this.document );
171
172 if ( fakeElement.data( 'cke-resizable' ) ) {
173 var width = fakeElement.getStyle( 'width' ),
174 height = fakeElement.getStyle( 'height' );
175
176 width && element.setAttribute( 'width', replaceCssLength( element.getAttribute( 'width' ), width ) );
177 height && element.setAttribute( 'height', replaceCssLength( element.getAttribute( 'height' ), height ) );
178 }
179
180 return element;
181 };
182
183} )();
diff --git a/sources/plugins/filebrowser/plugin.js b/sources/plugins/filebrowser/plugin.js
new file mode 100644
index 0000000..a622a37
--- /dev/null
+++ b/sources/plugins/filebrowser/plugin.js
@@ -0,0 +1,573 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The "filebrowser" plugin that adds support for file uploads and
8 * browsing.
9 *
10 * When a file is uploaded or selected inside the file browser, its URL is
11 * inserted automatically into a field defined in the <code>filebrowser</code>
12 * attribute. In order to specify a field that should be updated, pass the tab ID and
13 * the element ID, separated with a colon.<br /><br />
14 *
15 * <strong>Example 1: (Browse)</strong>
16 *
17 * <pre>
18 * {
19 * type : 'button',
20 * id : 'browse',
21 * filebrowser : 'tabId:elementId',
22 * label : editor.lang.common.browseServer
23 * }
24 * </pre>
25 *
26 * If you set the <code>filebrowser</code> attribute for an element other than
27 * the <code>fileButton</code>, the <code>Browse</code> action will be triggered.<br /><br />
28 *
29 * <strong>Example 2: (Quick Upload)</strong>
30 *
31 * <pre>
32 * {
33 * type : 'fileButton',
34 * id : 'uploadButton',
35 * filebrowser : 'tabId:elementId',
36 * label : editor.lang.common.uploadSubmit,
37 * 'for' : [ 'upload', 'upload' ]
38 * }
39 * </pre>
40 *
41 * If you set the <code>filebrowser</code> attribute for a <code>fileButton</code>
42 * element, the <code>QuickUpload</code> action will be executed.<br /><br />
43 *
44 * The filebrowser plugin also supports more advanced configuration performed through
45 * a JavaScript object.
46 *
47 * The following settings are supported:
48 *
49 * <ul>
50 * <li><code>action</code> &ndash; <code>Browse</code> or <code>QuickUpload</code>.</li>
51 * <li><code>target</code> &ndash; the field to update in the <code><em>tabId:elementId</em></code> format.</li>
52 * <li><code>params</code> &ndash; additional arguments to be passed to the server connector (optional).</li>
53 * <li><code>onSelect</code> &ndash; a function to execute when the file is selected/uploaded (optional).</li>
54 * <li><code>url</code> &ndash; the URL to be called (optional).</li>
55 * </ul>
56 *
57 * <strong>Example 3: (Quick Upload)</strong>
58 *
59 * <pre>
60 * {
61 * type : 'fileButton',
62 * label : editor.lang.common.uploadSubmit,
63 * id : 'buttonId',
64 * filebrowser :
65 * {
66 * action : 'QuickUpload', // required
67 * target : 'tab1:elementId', // required
68 * params : // optional
69 * {
70 * type : 'Files',
71 * currentFolder : '/folder/'
72 * },
73 * onSelect : function( fileUrl, errorMessage ) // optional
74 * {
75 * // Do not call the built-in selectFuntion.
76 * // return false;
77 * }
78 * },
79 * 'for' : [ 'tab1', 'myFile' ]
80 * }
81 * </pre>
82 *
83 * Suppose you have a file element with an ID of <code>myFile</code>, a text
84 * field with an ID of <code>elementId</code> and a <code>fileButton</code>.
85 * If the <code>filebowser.url</code> attribute is not specified explicitly,
86 * the form action will be set to <code>filebrowser[<em>DialogWindowName</em>]UploadUrl</code>
87 * or, if not specified, to <code>filebrowserUploadUrl</code>. Additional parameters
88 * from the <code>params</code> object will be added to the query string. It is
89 * possible to create your own <code>uploadHandler</code> and cancel the built-in
90 * <code>updateTargetElement</code> command.<br /><br />
91 *
92 * <strong>Example 4: (Browse)</strong>
93 *
94 * <pre>
95 * {
96 * type : 'button',
97 * id : 'buttonId',
98 * label : editor.lang.common.browseServer,
99 * filebrowser :
100 * {
101 * action : 'Browse',
102 * url : '/ckfinder/ckfinder.html&amp;type=Images',
103 * target : 'tab1:elementId'
104 * }
105 * }
106 * </pre>
107 *
108 * In this example, when the button is pressed, the file browser will be opened in a
109 * popup window. If you do not specify the <code>filebrowser.url</code> attribute,
110 * <code>filebrowser[<em>DialogName</em>]BrowseUrl</code> or
111 * <code>filebrowserBrowseUrl</code> will be used. After selecting a file in the file
112 * browser, an element with an ID of <code>elementId</code> will be updated. Just
113 * like in the third example, a custom <code>onSelect</code> function may be defined.
114 */
115
116( function() {
117 // Default input element name for CSRF protection token.
118 var TOKEN_INPUT_NAME = 'ckCsrfToken';
119
120 // Adds (additional) arguments to given url.
121 //
122 // @param {String}
123 // url The url.
124 // @param {Object}
125 // params Additional parameters.
126 function addQueryString( url, params ) {
127 var queryString = [];
128
129 if ( !params )
130 return url;
131 else {
132 for ( var i in params )
133 queryString.push( i + '=' + encodeURIComponent( params[ i ] ) );
134 }
135
136 return url + ( ( url.indexOf( '?' ) != -1 ) ? '&' : '?' ) + queryString.join( '&' );
137 }
138
139 // Make a string's first character uppercase.
140 //
141 // @param {String}
142 // str String.
143 function ucFirst( str ) {
144 str += '';
145 var f = str.charAt( 0 ).toUpperCase();
146 return f + str.substr( 1 );
147 }
148
149 // The onlick function assigned to the 'Browse Server' button. Opens the
150 // file browser and updates target field when file is selected.
151 //
152 // @param {CKEDITOR.event}
153 // evt The event object.
154 function browseServer() {
155 var dialog = this.getDialog();
156 var editor = dialog.getParentEditor();
157
158 editor._.filebrowserSe = this;
159
160 var width = editor.config[ 'filebrowser' + ucFirst( dialog.getName() ) + 'WindowWidth' ] || editor.config.filebrowserWindowWidth || '80%';
161 var height = editor.config[ 'filebrowser' + ucFirst( dialog.getName() ) + 'WindowHeight' ] || editor.config.filebrowserWindowHeight || '70%';
162
163 var params = this.filebrowser.params || {};
164 params.CKEditor = editor.name;
165 params.CKEditorFuncNum = editor._.filebrowserFn;
166 if ( !params.langCode )
167 params.langCode = editor.langCode;
168
169 var url = addQueryString( this.filebrowser.url, params );
170 // TODO: V4: Remove backward compatibility (#8163).
171 editor.popup( url, width, height, editor.config.filebrowserWindowFeatures || editor.config.fileBrowserWindowFeatures );
172 }
173
174 // Appends token preventing CSRF attacks to the form of provided file input.
175 //
176 // @since 4.5.6
177 // @param {CKEDITOR.dom.element} fileInput
178 function appendToken( fileInput ) {
179 var tokenElement;
180 var form = new CKEDITOR.dom.element( fileInput.$.form );
181
182 if ( form ) {
183 // Check if token input element already exists.
184 tokenElement = form.$.elements[ TOKEN_INPUT_NAME ];
185
186 // Create new if needed.
187 if ( !tokenElement ) {
188 tokenElement = new CKEDITOR.dom.element( 'input' );
189 tokenElement.setAttributes( {
190 name: TOKEN_INPUT_NAME,
191 type: 'hidden'
192 } );
193
194 form.append( tokenElement );
195 } else {
196 tokenElement = new CKEDITOR.dom.element( tokenElement );
197 }
198
199 tokenElement.setAttribute( 'value', CKEDITOR.tools.getCsrfToken() );
200 }
201 }
202
203 // The onlick function assigned to the 'Upload' button. Makes the final
204 // decision whether form is really submitted and updates target field when
205 // file is uploaded.
206 //
207 // @param {CKEDITOR.event}
208 // evt The event object.
209 function uploadFile() {
210 var dialog = this.getDialog();
211 var editor = dialog.getParentEditor();
212
213 editor._.filebrowserSe = this;
214
215 // If user didn't select the file, stop the upload.
216 if ( !dialog.getContentElement( this[ 'for' ][ 0 ], this[ 'for' ][ 1 ] ).getInputElement().$.value )
217 return false;
218
219 if ( !dialog.getContentElement( this[ 'for' ][ 0 ], this[ 'for' ][ 1 ] ).getAction() )
220 return false;
221
222 return true;
223 }
224
225 // Setups the file element.
226 //
227 // @param {CKEDITOR.ui.dialog.file}
228 // fileInput The file element used during file upload.
229 // @param {Object}
230 // filebrowser Object containing filebrowser settings assigned to
231 // the fileButton associated with this file element.
232 function setupFileElement( editor, fileInput, filebrowser ) {
233 var params = filebrowser.params || {};
234 params.CKEditor = editor.name;
235 params.CKEditorFuncNum = editor._.filebrowserFn;
236 if ( !params.langCode )
237 params.langCode = editor.langCode;
238
239 fileInput.action = addQueryString( filebrowser.url, params );
240 fileInput.filebrowser = filebrowser;
241 }
242
243 // Traverse through the content definition and attach filebrowser to
244 // elements with 'filebrowser' attribute.
245 //
246 // @param String
247 // dialogName Dialog name.
248 // @param {CKEDITOR.dialog.definitionObject}
249 // definition Dialog definition.
250 // @param {Array}
251 // elements Array of {@link CKEDITOR.dialog.definition.content}
252 // objects.
253 function attachFileBrowser( editor, dialogName, definition, elements ) {
254 if ( !elements || !elements.length )
255 return;
256
257 var element;
258
259 for ( var i = elements.length; i--; ) {
260 element = elements[ i ];
261
262 if ( element.type == 'hbox' || element.type == 'vbox' || element.type == 'fieldset' )
263 attachFileBrowser( editor, dialogName, definition, element.children );
264
265 if ( !element.filebrowser )
266 continue;
267
268 if ( typeof element.filebrowser == 'string' ) {
269 var fb = {
270 action: ( element.type == 'fileButton' ) ? 'QuickUpload' : 'Browse',
271 target: element.filebrowser
272 };
273 element.filebrowser = fb;
274 }
275
276 if ( element.filebrowser.action == 'Browse' ) {
277 var url = element.filebrowser.url;
278 if ( url === undefined ) {
279 url = editor.config[ 'filebrowser' + ucFirst( dialogName ) + 'BrowseUrl' ];
280 if ( url === undefined )
281 url = editor.config.filebrowserBrowseUrl;
282 }
283
284 if ( url ) {
285 element.onClick = browseServer;
286 element.filebrowser.url = url;
287 element.hidden = false;
288 }
289 } else if ( element.filebrowser.action == 'QuickUpload' && element[ 'for' ] ) {
290 url = element.filebrowser.url;
291 if ( url === undefined ) {
292 url = editor.config[ 'filebrowser' + ucFirst( dialogName ) + 'UploadUrl' ];
293 if ( url === undefined )
294 url = editor.config.filebrowserUploadUrl;
295 }
296
297 if ( url ) {
298 var onClick = element.onClick;
299 element.onClick = function( evt ) {
300 // "element" here means the definition object, so we need to find the correct
301 // button to scope the event call
302 var sender = evt.sender;
303 if ( onClick && onClick.call( sender, evt ) === false )
304 return false;
305
306 if ( uploadFile.call( sender, evt ) ) {
307 var fileInput = sender.getDialog().getContentElement( this[ 'for' ][ 0 ], this[ 'for' ][ 1 ] ).getInputElement();
308
309 // Append token preventing CSRF attacks.
310 appendToken( fileInput );
311 return true;
312 }
313
314
315 return false;
316 };
317
318 element.filebrowser.url = url;
319 element.hidden = false;
320 setupFileElement( editor, definition.getContents( element[ 'for' ][ 0 ] ).get( element[ 'for' ][ 1 ] ), element.filebrowser );
321 }
322 }
323 }
324 }
325
326 // Updates the target element with the url of uploaded/selected file.
327 //
328 // @param {String}
329 // url The url of a file.
330 function updateTargetElement( url, sourceElement ) {
331 var dialog = sourceElement.getDialog();
332 var targetElement = sourceElement.filebrowser.target || null;
333
334 // If there is a reference to targetElement, update it.
335 if ( targetElement ) {
336 var target = targetElement.split( ':' );
337 var element = dialog.getContentElement( target[ 0 ], target[ 1 ] );
338 if ( element ) {
339 element.setValue( url );
340 dialog.selectPage( target[ 0 ] );
341 }
342 }
343 }
344
345 // Returns true if filebrowser is configured in one of the elements.
346 //
347 // @param {CKEDITOR.dialog.definitionObject}
348 // definition Dialog definition.
349 // @param String
350 // tabId The tab id where element(s) can be found.
351 // @param String
352 // elementId The element id (or ids, separated with a semicolon) to check.
353 function isConfigured( definition, tabId, elementId ) {
354 if ( elementId.indexOf( ';' ) !== -1 ) {
355 var ids = elementId.split( ';' );
356 for ( var i = 0; i < ids.length; i++ ) {
357 if ( isConfigured( definition, tabId, ids[ i ] ) )
358 return true;
359 }
360 return false;
361 }
362
363 var elementFileBrowser = definition.getContents( tabId ).get( elementId ).filebrowser;
364 return ( elementFileBrowser && elementFileBrowser.url );
365 }
366
367 function setUrl( fileUrl, data ) {
368 var dialog = this._.filebrowserSe.getDialog(),
369 targetInput = this._.filebrowserSe[ 'for' ],
370 onSelect = this._.filebrowserSe.filebrowser.onSelect;
371
372 if ( targetInput )
373 dialog.getContentElement( targetInput[ 0 ], targetInput[ 1 ] ).reset();
374
375 if ( typeof data == 'function' && data.call( this._.filebrowserSe ) === false )
376 return;
377
378 if ( onSelect && onSelect.call( this._.filebrowserSe, fileUrl, data ) === false )
379 return;
380
381 // The "data" argument may be used to pass the error message to the editor.
382 if ( typeof data == 'string' && data )
383 alert( data ); // jshint ignore:line
384
385 if ( fileUrl )
386 updateTargetElement( fileUrl, this._.filebrowserSe );
387 }
388
389 CKEDITOR.plugins.add( 'filebrowser', {
390 requires: 'popup',
391 init: function( editor ) {
392 editor._.filebrowserFn = CKEDITOR.tools.addFunction( setUrl, editor );
393 editor.on( 'destroy', function() {
394 CKEDITOR.tools.removeFunction( this._.filebrowserFn );
395 } );
396 }
397 } );
398
399 CKEDITOR.on( 'dialogDefinition', function( evt ) {
400 // We require filebrowser plugin to be loaded.
401 if ( !evt.editor.plugins.filebrowser )
402 return;
403
404 var definition = evt.data.definition,
405 element;
406 // Associate filebrowser to elements with 'filebrowser' attribute.
407 for ( var i = 0; i < definition.contents.length; ++i ) {
408 if ( ( element = definition.contents[ i ] ) ) {
409 attachFileBrowser( evt.editor, evt.data.name, definition, element.elements );
410 if ( element.hidden && element.filebrowser )
411 element.hidden = !isConfigured( definition, element.id, element.filebrowser );
412
413 }
414 }
415 } );
416
417} )();
418
419/**
420 * The location of an external file manager that should be launched when the **Browse Server**
421 * button is pressed. If configured, the **Browse Server** button will appear in the
422 * **Link**, **Image**, and **Flash** dialog windows.
423 *
424 * Read more in the [documentation](#!/guide/dev_file_browse_upload)
425 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
426 *
427 * config.filebrowserBrowseUrl = '/browser/browse.php';
428 *
429 * @since 3.0
430 * @cfg {String} [filebrowserBrowseUrl='' (empty string = disabled)]
431 * @member CKEDITOR.config
432 */
433
434/**
435 * The location of the script that handles file uploads.
436 * If set, the **Upload** tab will appear in the **Link**, **Image**,
437 * and **Flash** dialog windows.
438 *
439 * Read more in the [documentation](#!/guide/dev_file_browse_upload)
440 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
441 *
442 * config.filebrowserUploadUrl = '/uploader/upload.php';
443 *
444 * **Note:** This is a configuration setting for a [file browser/uploader](#!/guide/dev_file_browse_upload).
445 * To configure [uploading dropped or pasted files](#!/guide/dev_file_upload) use the {@link CKEDITOR.config#uploadUrl}
446 * configuration option.
447 *
448 * @since 3.0
449 * @cfg {String} [filebrowserUploadUrl='' (empty string = disabled)]
450 * @member CKEDITOR.config
451 */
452
453/**
454 * The location of an external file manager that should be launched when the **Browse Server**
455 * button is pressed in the **Image** dialog window.
456 *
457 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserBrowseUrl}.
458 *
459 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
460 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
461 *
462 * config.filebrowserImageBrowseUrl = '/browser/browse.php?type=Images';
463 *
464 * @since 3.0
465 * @cfg {String} [filebrowserImageBrowseUrl='' (empty string = disabled)]
466 * @member CKEDITOR.config
467 */
468
469/**
470 * The location of an external file browser that should be launched when the **Browse Server**
471 * button is pressed in the **Flash** dialog window.
472 *
473 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserBrowseUrl}.
474 *
475 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
476 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
477 *
478 * config.filebrowserFlashBrowseUrl = '/browser/browse.php?type=Flash';
479 *
480 * @since 3.0
481 * @cfg {String} [filebrowserFlashBrowseUrl='' (empty string = disabled)]
482 * @member CKEDITOR.config
483 */
484
485/**
486 * The location of the script that handles file uploads in the **Image** dialog window.
487 *
488 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserUploadUrl}.
489 *
490 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
491 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
492 *
493 * config.filebrowserImageUploadUrl = '/uploader/upload.php?type=Images';
494 *
495 * **Note:** This is a configuration setting for a [file browser/uploader](#!/guide/dev_file_browse_upload).
496 * To configure [uploading dropped or pasted files](#!/guide/dev_file_upload) use the {@link CKEDITOR.config#uploadUrl}
497 * or {@link CKEDITOR.config#imageUploadUrl} configuration option.
498 *
499 * @since 3.0
500 * @cfg {String} [filebrowserImageUploadUrl='' (empty string = disabled)]
501 * @member CKEDITOR.config
502 */
503
504/**
505 * The location of the script that handles file uploads in the **Flash** dialog window.
506 *
507 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserUploadUrl}.
508 *
509 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
510 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
511 *
512 * config.filebrowserFlashUploadUrl = '/uploader/upload.php?type=Flash';
513 *
514 * @since 3.0
515 * @cfg {String} filebrowserFlashUploadUrl='' (empty string = disabled)]
516 * @member CKEDITOR.config
517 */
518
519/**
520 * The location of an external file manager that should be launched when the **Browse Server**
521 * button is pressed in the **Link** tab of the **Image** dialog window.
522 *
523 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserBrowseUrl}.
524 *
525 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
526 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
527 *
528 * config.filebrowserImageBrowseLinkUrl = '/browser/browse.php';
529 *
530 * @since 3.2
531 * @cfg {String} [filebrowserImageBrowseLinkUrl='' (empty string = disabled)]
532 * @member CKEDITOR.config
533 */
534
535/**
536 * The features to use in the file manager popup window.
537 *
538 * config.filebrowserWindowFeatures = 'resizable=yes,scrollbars=no';
539 *
540 * @since 3.4.1
541 * @cfg {String} [filebrowserWindowFeatures='location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes']
542 * @member CKEDITOR.config
543 */
544
545/**
546 * The width of the file manager popup window. It can be a number denoting a value in
547 * pixels or a percent string.
548 *
549 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-file-manager-window-size)
550 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
551 *
552 * config.filebrowserWindowWidth = 750;
553 *
554 * config.filebrowserWindowWidth = '50%';
555 *
556 * @cfg {Number/String} [filebrowserWindowWidth='80%']
557 * @member CKEDITOR.config
558 */
559
560/**
561 * The height of the file manager popup window. It can be a number denoting a value in
562 * pixels or a percent string.
563 *
564 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-file-manager-window-size)
565 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
566 *
567 * config.filebrowserWindowHeight = 580;
568 *
569 * config.filebrowserWindowHeight = '50%';
570 *
571 * @cfg {Number/String} [filebrowserWindowHeight='70%']
572 * @member CKEDITOR.config
573 */
diff --git a/sources/plugins/floatingspace/plugin.js b/sources/plugins/floatingspace/plugin.js
new file mode 100644
index 0000000..878d952
--- /dev/null
+++ b/sources/plugins/floatingspace/plugin.js
@@ -0,0 +1,406 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 var win = CKEDITOR.document.getWindow(),
8 pixelate = CKEDITOR.tools.cssLength;
9
10 CKEDITOR.plugins.add( 'floatingspace', {
11 init: function( editor ) {
12 // Add listener with lower priority than that in themedui creator.
13 // Thereby floatingspace will be created only if themedui wasn't used.
14 editor.on( 'loaded', function() {
15 attach( this );
16 }, null, null, 20 );
17 }
18 } );
19
20 function scrollOffset( side ) {
21 var pageOffset = side == 'left' ? 'pageXOffset' : 'pageYOffset',
22 docScrollOffset = side == 'left' ? 'scrollLeft' : 'scrollTop';
23
24 return ( pageOffset in win.$ ) ? win.$[ pageOffset ] : CKEDITOR.document.$.documentElement[ docScrollOffset ];
25 }
26
27 function attach( editor ) {
28 var config = editor.config,
29
30 // Get the HTML for the predefined spaces.
31 topHtml = editor.fire( 'uiSpace', { space: 'top', html: '' } ).html,
32
33 // Re-positioning of the space.
34 layout = ( function() {
35 // Mode indicates the vertical aligning mode.
36 var mode, editable,
37 spaceRect, editorRect, viewRect, spaceHeight, pageScrollX,
38
39 // Allow minor adjustments of the float space from custom configs.
40 dockedOffsetX = config.floatSpaceDockedOffsetX || 0,
41 dockedOffsetY = config.floatSpaceDockedOffsetY || 0,
42 pinnedOffsetX = config.floatSpacePinnedOffsetX || 0,
43 pinnedOffsetY = config.floatSpacePinnedOffsetY || 0;
44
45 // Update the float space position.
46 function updatePos( pos, prop, val ) {
47 floatSpace.setStyle( prop, pixelate( val ) );
48 floatSpace.setStyle( 'position', pos );
49 }
50
51 // Change the current mode and update float space position accordingly.
52 function changeMode( newMode ) {
53 var editorPos = editable.getDocumentPosition();
54
55 switch ( newMode ) {
56 case 'top':
57 updatePos( 'absolute', 'top', editorPos.y - spaceHeight - dockedOffsetY );
58 break;
59 case 'pin':
60 updatePos( 'fixed', 'top', pinnedOffsetY );
61 break;
62 case 'bottom':
63 updatePos( 'absolute', 'top', editorPos.y + ( editorRect.height || editorRect.bottom - editorRect.top ) + dockedOffsetY );
64 break;
65 }
66
67 mode = newMode;
68 }
69
70 return function( evt ) {
71 // #10112 Do not fail on editable-less editor.
72 if ( !( editable = editor.editable() ) )
73 return;
74
75 var show = ( evt && evt.name == 'focus' );
76
77 // Show up the space on focus gain.
78 if ( show ) {
79 floatSpace.show();
80 }
81
82 editor.fire( 'floatingSpaceLayout', { show: show } );
83
84 // Reset the horizontal position for below measurement.
85 floatSpace.removeStyle( 'left' );
86 floatSpace.removeStyle( 'right' );
87
88 // Compute the screen position from the TextRectangle object would
89 // be very simple, even though the "width"/"height" property is not
90 // available for all, it's safe to figure that out from the rest.
91
92 // http://help.dottoro.com/ljgupwlp.php
93 spaceRect = floatSpace.getClientRect();
94 editorRect = editable.getClientRect();
95 viewRect = win.getViewPaneSize();
96 spaceHeight = spaceRect.height;
97 pageScrollX = scrollOffset( 'left' );
98
99 // We initialize it as pin mode.
100 if ( !mode ) {
101 mode = 'pin';
102 changeMode( 'pin' );
103 // Call for a refresh to the actual layout.
104 layout( evt );
105 return;
106 }
107
108 // +------------------------ Viewport -+ \
109 // | | |-> floatSpaceDockedOffsetY
110 // | ................................. | /
111 // | |
112 // | +------ Space -+ |
113 // | | | |
114 // | +--------------+ |
115 // | +------------------ Editor -+ |
116 // | | | |
117 //
118 if ( spaceHeight + dockedOffsetY <= editorRect.top )
119 changeMode( 'top' );
120
121 // +- - - - - - - - - Editor -+
122 // | |
123 // +------------------------ Viewport -+ \
124 // | | | | |-> floatSpacePinnedOffsetY
125 // | ................................. | /
126 // | +------ Space -+ | |
127 // | | | | |
128 // | +--------------+ | |
129 // | | | |
130 // | +---------------------------+ |
131 // +-----------------------------------+
132 //
133 else if ( spaceHeight + dockedOffsetY > viewRect.height - editorRect.bottom )
134 changeMode( 'pin' );
135
136 // +- - - - - - - - - Editor -+
137 // | |
138 // +------------------------ Viewport -+ \
139 // | | | | |-> floatSpacePinnedOffsetY
140 // | ................................. | /
141 // | | | |
142 // | | | |
143 // | +---------------------------+ |
144 // | +------ Space -+ |
145 // | | | |
146 // | +--------------+ |
147 //
148 else
149 changeMode( 'bottom' );
150
151 var mid = viewRect.width / 2,
152 alignSide, offset;
153
154 if ( config.floatSpacePreferRight ) {
155 alignSide = 'right';
156 } else if ( editorRect.left > 0 && editorRect.right < viewRect.width && editorRect.width > spaceRect.width ) {
157 alignSide = config.contentsLangDirection == 'rtl' ? 'right' : 'left';
158 } else {
159 alignSide = mid - editorRect.left > editorRect.right - mid ? 'left' : 'right';
160 }
161
162 // (#9769) If viewport width is less than space width,
163 // make sure space never cross the left boundary of the viewport.
164 // In other words: top-left corner of the space is always visible.
165 if ( spaceRect.width > viewRect.width ) {
166 alignSide = 'left';
167 offset = 0;
168 }
169 else {
170 if ( alignSide == 'left' ) {
171 // If the space rect fits into viewport, align it
172 // to the left edge of editor:
173 //
174 // +------------------------ Viewport -+
175 // | |
176 // | +------------- Space -+ |
177 // | | | |
178 // | +---------------------+ |
179 // | +------------------ Editor -+ |
180 // | | | |
181 //
182 if ( editorRect.left > 0 )
183 offset = editorRect.left;
184
185 // If the left part of the editor is cut off by the left
186 // edge of the viewport, stick the space to the viewport:
187 //
188 // +------------------------ Viewport -+
189 // | |
190 // +---------------- Space -+ |
191 // | | |
192 // +------------------------+ |
193 // +----|------------- Editor -+ |
194 // | | | |
195 //
196 else
197 offset = 0;
198 }
199 else {
200 // If the space rect fits into viewport, align it
201 // to the right edge of editor:
202 //
203 // +------------------------ Viewport -+
204 // | |
205 // | +------------- Space -+ |
206 // | | | |
207 // | +---------------------+ |
208 // | +------------------ Editor -+ |
209 // | | | |
210 //
211 if ( editorRect.right < viewRect.width )
212 offset = viewRect.width - editorRect.right;
213
214 // If the right part of the editor is cut off by the right
215 // edge of the viewport, stick the space to the viewport:
216 //
217 // +------------------------ Viewport -+
218 // | |
219 // | +------------- Space -+
220 // | | |
221 // | +---------------------+
222 // | +-----------------|- Editor -+
223 // | | | |
224 //
225 else
226 offset = 0;
227 }
228
229 // (#9769) Finally, stick the space to the opposite side of
230 // the viewport when it's cut off horizontally on the left/right
231 // side like below.
232 //
233 // This trick reveals cut off space in some edge cases and
234 // hence it improves accessibility.
235 //
236 // +------------------------ Viewport -+
237 // | |
238 // | +--------------------|-- Space -+
239 // | | | |
240 // | +--------------------|----------+
241 // | +------- Editor -+ |
242 // | | | |
243 //
244 // becomes:
245 //
246 // +------------------------ Viewport -+
247 // | |
248 // | +----------------------- Space -+
249 // | | |
250 // | +-------------------------------+
251 // | +------- Editor -+ |
252 // | | | |
253 //
254 if ( offset + spaceRect.width > viewRect.width ) {
255 alignSide = alignSide == 'left' ? 'right' : 'left';
256 offset = 0;
257 }
258 }
259
260 // Pin mode is fixed, so don't include scroll-x.
261 // (#9903) For mode is "top" or "bottom", add opposite scroll-x for right-aligned space.
262 var scroll = mode == 'pin' ? 0 : alignSide == 'left' ? pageScrollX : -pageScrollX;
263
264 floatSpace.setStyle( alignSide, pixelate( ( mode == 'pin' ? pinnedOffsetX : dockedOffsetX ) + offset + scroll ) );
265 };
266 } )();
267
268 if ( topHtml ) {
269 var floatSpaceTpl = new CKEDITOR.template(
270 '<div' +
271 ' id="cke_{name}"' +
272 ' class="cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_float cke_{langDir} ' + CKEDITOR.env.cssClass + '"' +
273 ' dir="{langDir}"' +
274 ' title="' + ( CKEDITOR.env.gecko ? ' ' : '' ) + '"' +
275 ' lang="{langCode}"' +
276 ' role="application"' +
277 ' style="{style}"' +
278 ( editor.title ? ' aria-labelledby="cke_{name}_arialbl"' : ' ' ) +
279 '>' +
280 ( editor.title ? '<span id="cke_{name}_arialbl" class="cke_voice_label">{voiceLabel}</span>' : ' ' ) +
281 '<div class="cke_inner">' +
282 '<div id="{topId}" class="cke_top" role="presentation">{content}</div>' +
283 '</div>' +
284 '</div>' ),
285 floatSpace = CKEDITOR.document.getBody().append( CKEDITOR.dom.element.createFromHtml( floatSpaceTpl.output( {
286 content: topHtml,
287 id: editor.id,
288 langDir: editor.lang.dir,
289 langCode: editor.langCode,
290 name: editor.name,
291 style: 'display:none;z-index:' + ( config.baseFloatZIndex - 1 ),
292 topId: editor.ui.spaceId( 'top' ),
293 voiceLabel: editor.title
294 } ) ) ),
295
296 // Use event buffers to reduce CPU load when tons of events are fired.
297 changeBuffer = CKEDITOR.tools.eventsBuffer( 500, layout ),
298 uiBuffer = CKEDITOR.tools.eventsBuffer( 100, layout );
299
300 // There's no need for the floatSpace to be selectable.
301 floatSpace.unselectable();
302
303 // Prevent clicking on non-buttons area of the space from blurring editor.
304 floatSpace.on( 'mousedown', function( evt ) {
305 evt = evt.data;
306 if ( !evt.getTarget().hasAscendant( 'a', 1 ) )
307 evt.preventDefault();
308 } );
309
310 editor.on( 'focus', function( evt ) {
311 layout( evt );
312 editor.on( 'change', changeBuffer.input );
313 win.on( 'scroll', uiBuffer.input );
314 win.on( 'resize', uiBuffer.input );
315 } );
316
317 editor.on( 'blur', function() {
318 floatSpace.hide();
319 editor.removeListener( 'change', changeBuffer.input );
320 win.removeListener( 'scroll', uiBuffer.input );
321 win.removeListener( 'resize', uiBuffer.input );
322 } );
323
324 editor.on( 'destroy', function() {
325 win.removeListener( 'scroll', uiBuffer.input );
326 win.removeListener( 'resize', uiBuffer.input );
327 floatSpace.clearCustomData();
328 floatSpace.remove();
329 } );
330
331 // Handle initial focus.
332 if ( editor.focusManager.hasFocus )
333 floatSpace.show();
334
335 // Register this UI space to the focus manager.
336 editor.focusManager.add( floatSpace, 1 );
337 }
338 }
339} )();
340
341/**
342 * Along with {@link #floatSpaceDockedOffsetY} it defines the
343 * amount of offset (in pixels) between the float space and the editable left/right
344 * boundaries when the space element is docked on either side of the editable.
345 *
346 * config.floatSpaceDockedOffsetX = 10;
347 *
348 * @cfg {Number} [floatSpaceDockedOffsetX=0]
349 * @member CKEDITOR.config
350 */
351
352/**
353 * Along with {@link #floatSpaceDockedOffsetX} it defines the
354 * amount of offset (in pixels) between the float space and the editable top/bottom
355 * boundaries when the space element is docked on either side of the editable.
356 *
357 * config.floatSpaceDockedOffsetY = 10;
358 *
359 * @cfg {Number} [floatSpaceDockedOffsetY=0]
360 * @member CKEDITOR.config
361 */
362
363/**
364 * Along with {@link #floatSpacePinnedOffsetY} it defines the
365 * amount of offset (in pixels) between the float space and the viewport boundaries
366 * when the space element is pinned.
367 *
368 * config.floatSpacePinnedOffsetX = 20;
369 *
370 * @cfg {Number} [floatSpacePinnedOffsetX=0]
371 * @member CKEDITOR.config
372 */
373
374/**
375 * Along with {@link #floatSpacePinnedOffsetX} it defines the
376 * amount of offset (in pixels) between the float space and the viewport boundaries
377 * when the space element is pinned.
378 *
379 * config.floatSpacePinnedOffsetY = 20;
380 *
381 * @cfg {Number} [floatSpacePinnedOffsetY=0]
382 * @member CKEDITOR.config
383 */
384
385/**
386 * Indicates that the float space should be aligned to the right side
387 * of the editable area rather than to the left (if possible).
388 *
389 * config.floatSpacePreferRight = true;
390 *
391 * @since 4.5
392 * @cfg {Boolean} [floatSpacePreferRight=false]
393 * @member CKEDITOR.config
394 */
395
396/**
397 * Fired when the viewport or editor parameters change and the floating space needs to check and
398 * eventually update its position and dimensions.
399 *
400 * @since 4.5
401 * @event floatingSpaceLayout
402 * @member CKEDITOR.editor
403 * @param {CKEDITOR.editor} editor The editor instance.
404 * @param data
405 * @param {Boolean} data.show True if the float space should show up as a result of this event.
406 */
diff --git a/sources/plugins/floatpanel/plugin.js b/sources/plugins/floatpanel/plugin.js
new file mode 100644
index 0000000..1a851f9
--- /dev/null
+++ b/sources/plugins/floatpanel/plugin.js
@@ -0,0 +1,598 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'floatpanel', {
7 requires: 'panel'
8} );
9
10( function() {
11 var panels = {};
12
13 function getPanel( editor, doc, parentElement, definition, level ) {
14 // Generates the panel key: docId-eleId-skinName-langDir[-uiColor][-CSSs][-level]
15 var key = CKEDITOR.tools.genKey( doc.getUniqueId(), parentElement.getUniqueId(), editor.lang.dir, editor.uiColor || '', definition.css || '', level || '' ),
16 panel = panels[ key ];
17
18 if ( !panel ) {
19 panel = panels[ key ] = new CKEDITOR.ui.panel( doc, definition );
20 panel.element = parentElement.append( CKEDITOR.dom.element.createFromHtml( panel.render( editor ), doc ) );
21
22 panel.element.setStyles( {
23 display: 'none',
24 position: 'absolute'
25 } );
26 }
27
28 return panel;
29 }
30
31 /**
32 * Represents a floating panel UI element.
33 *
34 * It is reused by rich combos, color combos, menus, etc.
35 * and it renders its content using {@link CKEDITOR.ui.panel}.
36 *
37 * @class
38 * @todo
39 */
40 CKEDITOR.ui.floatPanel = CKEDITOR.tools.createClass( {
41 /**
42 * Creates a floatPanel class instance.
43 *
44 * @constructor
45 * @param {CKEDITOR.editor} editor
46 * @param {CKEDITOR.dom.element} parentElement
47 * @param {Object} definition Definition of the panel that will be floating.
48 * @param {Number} level
49 */
50 $: function( editor, parentElement, definition, level ) {
51 definition.forceIFrame = 1;
52
53 // In case of editor with floating toolbar append panels that should float
54 // to the main UI element.
55 if ( definition.toolbarRelated && editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE )
56 parentElement = CKEDITOR.document.getById( 'cke_' + editor.name );
57
58 var doc = parentElement.getDocument(),
59 panel = getPanel( editor, doc, parentElement, definition, level || 0 ),
60 element = panel.element,
61 iframe = element.getFirst(),
62 that = this;
63
64 // Disable native browser menu. (#4825)
65 element.disableContextMenu();
66
67 this.element = element;
68
69 this._ = {
70 editor: editor,
71 // The panel that will be floating.
72 panel: panel,
73 parentElement: parentElement,
74 definition: definition,
75 document: doc,
76 iframe: iframe,
77 children: [],
78 dir: editor.lang.dir,
79 showBlockParams: null
80 };
81
82 editor.on( 'mode', hide );
83 editor.on( 'resize', hide );
84
85 // When resize of the window is triggered floatpanel should be repositioned according to new dimensions.
86 // #11724. Fixes issue with undesired panel hiding on Android and iOS.
87 doc.getWindow().on( 'resize', function() {
88 this.reposition();
89 }, this );
90
91 // We need a wrapper because events implementation doesn't allow to attach
92 // one listener more than once for the same event on the same object.
93 // Remember that floatPanel#hide is shared between all instances.
94 function hide() {
95 that.hide();
96 }
97 },
98
99 proto: {
100 /**
101 * @todo
102 */
103 addBlock: function( name, block ) {
104 return this._.panel.addBlock( name, block );
105 },
106
107 /**
108 * @todo
109 */
110 addListBlock: function( name, multiSelect ) {
111 return this._.panel.addListBlock( name, multiSelect );
112 },
113
114 /**
115 * @todo
116 */
117 getBlock: function( name ) {
118 return this._.panel.getBlock( name );
119 },
120
121 /**
122 * Shows the panel block.
123 *
124 * @param {String} name
125 * @param {CKEDITOR.dom.element} offsetParent Positioned parent.
126 * @param {Number} corner
127 *
128 * * For LTR (left to right) oriented editor:
129 * * `1` = top-left
130 * * `2` = top-right
131 * * `3` = bottom-right
132 * * `4` = bottom-left
133 * * For RTL (right to left):
134 * * `1` = top-right
135 * * `2` = top-left
136 * * `3` = bottom-left
137 * * `4` = bottom-right
138 *
139 * @param {Number} [offsetX=0]
140 * @param {Number} [offsetY=0]
141 * @param {Function} [callback] A callback function executed when block positioning is done.
142 * @todo what do exactly these params mean (especially corner)?
143 */
144 showBlock: function( name, offsetParent, corner, offsetX, offsetY, callback ) {
145 var panel = this._.panel,
146 block = panel.showBlock( name );
147
148 this._.showBlockParams = [].slice.call( arguments );
149 this.allowBlur( false );
150
151 // Record from where the focus is when open panel.
152 var editable = this._.editor.editable();
153 this._.returnFocus = editable.hasFocus ? editable : new CKEDITOR.dom.element( CKEDITOR.document.$.activeElement );
154 this._.hideTimeout = 0;
155
156 var element = this.element,
157 iframe = this._.iframe,
158 // Edge prefers iframe's window to the iframe, just like the rest of the browsers (#13143).
159 focused = CKEDITOR.env.ie && !CKEDITOR.env.edge ? iframe : new CKEDITOR.dom.window( iframe.$.contentWindow ),
160 doc = element.getDocument(),
161 positionedAncestor = this._.parentElement.getPositionedAncestor(),
162 position = offsetParent.getDocumentPosition( doc ),
163 positionedAncestorPosition = positionedAncestor ? positionedAncestor.getDocumentPosition( doc ) : { x: 0, y: 0 },
164 rtl = this._.dir == 'rtl',
165 left = position.x + ( offsetX || 0 ) - positionedAncestorPosition.x,
166 top = position.y + ( offsetY || 0 ) - positionedAncestorPosition.y;
167
168 // Floating panels are off by (-1px, 0px) in RTL mode. (#3438)
169 if ( rtl && ( corner == 1 || corner == 4 ) )
170 left += offsetParent.$.offsetWidth;
171 else if ( !rtl && ( corner == 2 || corner == 3 ) )
172 left += offsetParent.$.offsetWidth - 1;
173
174 if ( corner == 3 || corner == 4 )
175 top += offsetParent.$.offsetHeight - 1;
176
177 // Memorize offsetParent by it's ID.
178 this._.panel._.offsetParentId = offsetParent.getId();
179
180 element.setStyles( {
181 top: top + 'px',
182 left: 0,
183 display: ''
184 } );
185
186 // Don't use display or visibility style because we need to
187 // calculate the rendering layout later and focus the element.
188 element.setOpacity( 0 );
189
190 // To allow the context menu to decrease back their width
191 element.getFirst().removeStyle( 'width' );
192
193 // Report to focus manager.
194 this._.editor.focusManager.add( focused );
195
196 // Configure the IFrame blur event. Do that only once.
197 if ( !this._.blurSet ) {
198
199 // With addEventListener compatible browsers, we must
200 // useCapture when registering the focus/blur events to
201 // guarantee they will be firing in all situations. (#3068, #3222 )
202 CKEDITOR.event.useCapture = true;
203
204 focused.on( 'blur', function( ev ) {
205 // As we are using capture to register the listener,
206 // the blur event may get fired even when focusing
207 // inside the window itself, so we must ensure the
208 // target is out of it.
209 if ( !this.allowBlur() || ev.data.getPhase() != CKEDITOR.EVENT_PHASE_AT_TARGET )
210 return;
211
212 if ( this.visible && !this._.activeChild ) {
213 // [iOS] Allow hide to be prevented if touch is bound
214 // to any parent of the iframe blur happens before touch (#10714).
215 if ( CKEDITOR.env.iOS ) {
216 if ( !this._.hideTimeout )
217 this._.hideTimeout = CKEDITOR.tools.setTimeout( doHide, 0, this );
218 } else {
219 doHide.call( this );
220 }
221 }
222
223 function doHide() {
224 // Panel close is caused by user's navigating away the focus, e.g. click outside the panel.
225 // DO NOT restore focus in this case.
226 delete this._.returnFocus;
227 this.hide();
228 }
229 }, this );
230
231 focused.on( 'focus', function() {
232 this._.focused = true;
233 this.hideChild();
234 this.allowBlur( true );
235 }, this );
236
237 // [iOS] if touch is bound to any parent of the iframe blur
238 // happens twice before touchstart and before touchend (#10714).
239 if ( CKEDITOR.env.iOS ) {
240 // Prevent false hiding on blur.
241 // We don't need to return focus here because touchend will fire anyway.
242 // If user scrolls and pointer gets out of the panel area touchend will also fire.
243 focused.on( 'touchstart', function() {
244 clearTimeout( this._.hideTimeout );
245 }, this );
246
247 // Set focus back to handle blur and hide panel when needed.
248 focused.on( 'touchend', function() {
249 this._.hideTimeout = 0;
250 this.focus();
251 }, this );
252 }
253
254 CKEDITOR.event.useCapture = false;
255
256 this._.blurSet = 1;
257 }
258
259 panel.onEscape = CKEDITOR.tools.bind( function( keystroke ) {
260 if ( this.onEscape && this.onEscape( keystroke ) === false )
261 return false;
262 }, this );
263
264 CKEDITOR.tools.setTimeout( function() {
265 var panelLoad = CKEDITOR.tools.bind( function() {
266 var target = element;
267
268 // Reset panel width as the new content can be narrower
269 // than the old one. (#9355)
270 target.removeStyle( 'width' );
271
272 if ( block.autoSize ) {
273 var panelDoc = block.element.getDocument(),
274 width = ( ( CKEDITOR.env.webkit || CKEDITOR.env.edge ) ? block.element : panelDoc.getBody() ).$.scrollWidth;
275
276 // Account for extra height needed due to IE quirks box model bug:
277 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
278 // (#3426)
279 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && width > 0 )
280 width += ( target.$.offsetWidth || 0 ) - ( target.$.clientWidth || 0 ) + 3;
281
282 // Add some extra pixels to improve the appearance.
283 width += 10;
284
285 target.setStyle( 'width', width + 'px' );
286
287 var height = block.element.$.scrollHeight;
288
289 // Account for extra height needed due to IE quirks box model bug:
290 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
291 // (#3426)
292 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && height > 0 )
293 height += ( target.$.offsetHeight || 0 ) - ( target.$.clientHeight || 0 ) + 3;
294
295 target.setStyle( 'height', height + 'px' );
296
297 // Fix IE < 8 visibility.
298 panel._.currentBlock.element.setStyle( 'display', 'none' ).removeStyle( 'display' );
299 } else {
300 target.removeStyle( 'height' );
301 }
302
303 // Flip panel layout horizontally in RTL with known width.
304 if ( rtl )
305 left -= element.$.offsetWidth;
306
307 // Pop the style now for measurement.
308 element.setStyle( 'left', left + 'px' );
309
310 /* panel layout smartly fit the viewport size. */
311 var panelElement = panel.element,
312 panelWindow = panelElement.getWindow(),
313 rect = element.$.getBoundingClientRect(),
314 viewportSize = panelWindow.getViewPaneSize();
315
316 // Compensation for browsers that dont support "width" and "height".
317 var rectWidth = rect.width || rect.right - rect.left,
318 rectHeight = rect.height || rect.bottom - rect.top;
319
320 // Check if default horizontal layout is impossible.
321 var spaceAfter = rtl ? rect.right : viewportSize.width - rect.left,
322 spaceBefore = rtl ? viewportSize.width - rect.right : rect.left;
323
324 if ( rtl ) {
325 if ( spaceAfter < rectWidth ) {
326 // Flip to show on right.
327 if ( spaceBefore > rectWidth )
328 left += rectWidth;
329 // Align to window left.
330 else if ( viewportSize.width > rectWidth )
331 left = left - rect.left;
332 // Align to window right, never cutting the panel at right.
333 else
334 left = left - rect.right + viewportSize.width;
335 }
336 } else if ( spaceAfter < rectWidth ) {
337 // Flip to show on left.
338 if ( spaceBefore > rectWidth )
339 left -= rectWidth;
340 // Align to window right.
341 else if ( viewportSize.width > rectWidth )
342 left = left - rect.right + viewportSize.width;
343 // Align to window left, never cutting the panel at left.
344 else
345 left = left - rect.left;
346 }
347
348
349 // Check if the default vertical layout is possible.
350 var spaceBelow = viewportSize.height - rect.top,
351 spaceAbove = rect.top;
352
353 if ( spaceBelow < rectHeight ) {
354 // Flip to show above.
355 if ( spaceAbove > rectHeight )
356 top -= rectHeight;
357 // Align to window bottom.
358 else if ( viewportSize.height > rectHeight )
359 top = top - rect.bottom + viewportSize.height;
360 // Align to top, never cutting the panel at top.
361 else
362 top = top - rect.top;
363 }
364
365 // If IE is in RTL, we have troubles with absolute
366 // position and horizontal scrolls. Here we have a
367 // series of hacks to workaround it. (#6146)
368 if ( CKEDITOR.env.ie ) {
369 var offsetParent = new CKEDITOR.dom.element( element.$.offsetParent ),
370 scrollParent = offsetParent;
371
372 // Quirks returns <body>, but standards returns <html>.
373 if ( scrollParent.getName() == 'html' )
374 scrollParent = scrollParent.getDocument().getBody();
375
376 if ( scrollParent.getComputedStyle( 'direction' ) == 'rtl' ) {
377 // For IE8, there is not much logic on this, but it works.
378 if ( CKEDITOR.env.ie8Compat )
379 left -= element.getDocument().getDocumentElement().$.scrollLeft * 2;
380 else
381 left -= ( offsetParent.$.scrollWidth - offsetParent.$.clientWidth );
382 }
383 }
384
385 // Trigger the onHide event of the previously active panel to prevent
386 // incorrect styles from being applied (#6170)
387 var innerElement = element.getFirst(),
388 activePanel;
389 if ( ( activePanel = innerElement.getCustomData( 'activePanel' ) ) )
390 activePanel.onHide && activePanel.onHide.call( this, 1 );
391 innerElement.setCustomData( 'activePanel', this );
392
393 element.setStyles( {
394 top: top + 'px',
395 left: left + 'px'
396 } );
397 element.setOpacity( 1 );
398
399 callback && callback();
400 }, this );
401
402 panel.isLoaded ? panelLoad() : panel.onLoad = panelLoad;
403
404 CKEDITOR.tools.setTimeout( function() {
405 var scrollTop = CKEDITOR.env.webkit && CKEDITOR.document.getWindow().getScrollPosition().y;
406
407 // Focus the panel frame first, so blur gets fired.
408 this.focus();
409
410 // Focus the block now.
411 block.element.focus();
412
413 // #10623, #10951 - restore the viewport's scroll position after focusing list element.
414 if ( CKEDITOR.env.webkit )
415 CKEDITOR.document.getBody().$.scrollTop = scrollTop;
416
417 // We need this get fired manually because of unfired focus() function.
418 this.allowBlur( true );
419 this._.editor.fire( 'panelShow', this );
420 }, 0, this );
421 }, CKEDITOR.env.air ? 200 : 0, this );
422 this.visible = 1;
423
424 if ( this.onShow )
425 this.onShow.call( this );
426 },
427
428 /**
429 * Repositions the panel with the same parameters that were used in the last {@link #showBlock} call.
430 *
431 * @since 4.5.4
432 */
433 reposition: function() {
434 var blockParams = this._.showBlockParams;
435
436 if ( this.visible && this._.showBlockParams ) {
437 this.hide();
438 this.showBlock.apply( this, blockParams );
439 }
440 },
441
442 /**
443 * Restores the last focused element or simply focuses the panel window.
444 */
445 focus: function() {
446 // Webkit requires to blur any previous focused page element, in
447 // order to properly fire the "focus" event.
448 if ( CKEDITOR.env.webkit ) {
449 var active = CKEDITOR.document.getActive();
450 active && !active.equals( this._.iframe ) && active.$.blur();
451 }
452
453 // Restore last focused element or simply focus panel window.
454 var focus = this._.lastFocused || this._.iframe.getFrameDocument().getWindow();
455 focus.focus();
456 },
457
458 /**
459 * @todo
460 */
461 blur: function() {
462 var doc = this._.iframe.getFrameDocument(),
463 active = doc.getActive();
464
465 active && active.is( 'a' ) && ( this._.lastFocused = active );
466 },
467
468 /**
469 * Hides the panel.
470 *
471 * @todo
472 */
473 hide: function( returnFocus ) {
474 if ( this.visible && ( !this.onHide || this.onHide.call( this ) !== true ) ) {
475 this.hideChild();
476 // Blur previously focused element. (#6671)
477 CKEDITOR.env.gecko && this._.iframe.getFrameDocument().$.activeElement.blur();
478 this.element.setStyle( 'display', 'none' );
479 this.visible = 0;
480 this.element.getFirst().removeCustomData( 'activePanel' );
481
482 // Return focus properly. (#6247)
483 var focusReturn = returnFocus && this._.returnFocus;
484 if ( focusReturn ) {
485 // Webkit requires focus moved out panel iframe first.
486 if ( CKEDITOR.env.webkit && focusReturn.type )
487 focusReturn.getWindow().$.focus();
488
489 focusReturn.focus();
490 }
491
492 delete this._.lastFocused;
493 this._.showBlockParams = null;
494
495 this._.editor.fire( 'panelHide', this );
496 }
497 },
498
499 /**
500 * @todo
501 */
502 allowBlur: function( allow ) {
503 // Prevent editor from hiding the panel. (#3222)
504 var panel = this._.panel;
505 if ( allow !== undefined )
506 panel.allowBlur = allow;
507
508 return panel.allowBlur;
509 },
510
511 /**
512 * Shows the specified panel as a child of one block of this one.
513 *
514 * @param {CKEDITOR.ui.floatPanel} panel
515 * @param {String} blockName
516 * @param {CKEDITOR.dom.element} offsetParent Positioned parent.
517 * @param {Number} corner
518 *
519 * * For LTR (left to right) oriented editor:
520 * * `1` = top-left
521 * * `2` = top-right
522 * * `3` = bottom-right
523 * * `4` = bottom-left
524 * * For RTL (right to left):
525 * * `1` = top-right
526 * * `2` = top-left
527 * * `3` = bottom-left
528 * * `4` = bottom-right
529 *
530 * @param {Number} [offsetX=0]
531 * @param {Number} [offsetY=0]
532 * @todo
533 */
534 showAsChild: function( panel, blockName, offsetParent, corner, offsetX, offsetY ) {
535 // Skip reshowing of child which is already visible.
536 if ( this._.activeChild == panel && panel._.panel._.offsetParentId == offsetParent.getId() )
537 return;
538
539 this.hideChild();
540
541 panel.onHide = CKEDITOR.tools.bind( function() {
542 // Use a timeout, so we give time for this menu to get
543 // potentially focused.
544 CKEDITOR.tools.setTimeout( function() {
545 if ( !this._.focused )
546 this.hide();
547 }, 0, this );
548 }, this );
549
550 this._.activeChild = panel;
551 this._.focused = false;
552
553 panel.showBlock( blockName, offsetParent, corner, offsetX, offsetY );
554 this.blur();
555
556 /* #3767 IE: Second level menu may not have borders */
557 if ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) {
558 setTimeout( function() {
559 panel.element.getChild( 0 ).$.style.cssText += '';
560 }, 100 );
561 }
562 },
563
564 /**
565 * @todo
566 */
567 hideChild: function( restoreFocus ) {
568 var activeChild = this._.activeChild;
569
570 if ( activeChild ) {
571 delete activeChild.onHide;
572 delete this._.activeChild;
573 activeChild.hide();
574
575 // At this point focus should be moved back to parent panel.
576 restoreFocus && this.focus();
577 }
578 }
579 }
580 } );
581
582 CKEDITOR.on( 'instanceDestroyed', function() {
583 var isLastInstance = CKEDITOR.tools.isEmpty( CKEDITOR.instances );
584
585 for ( var i in panels ) {
586 var panel = panels[ i ];
587 // Safe to destroy it since there're no more instances.(#4241)
588 if ( isLastInstance )
589 panel.destroy();
590 // Panel might be used by other instances, just hide them.(#4552)
591 else
592 panel.element.hide();
593 }
594 // Remove the registration.
595 isLastInstance && ( panels = {} );
596
597 } );
598} )();
diff --git a/sources/plugins/format/lang/af.js b/sources/plugins/format/lang/af.js
new file mode 100644
index 0000000..b38cd33
--- /dev/null
+++ b/sources/plugins/format/lang/af.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'af', {
6 label: 'Opmaak',
7 panelTitle: 'Opmaak',
8 tag_address: 'Adres',
9 tag_div: 'Normaal (DIV)',
10 tag_h1: 'Opskrif 1',
11 tag_h2: 'Opskrif 2',
12 tag_h3: 'Opskrif 3',
13 tag_h4: 'Opskrif 4',
14 tag_h5: 'Opskrif 5',
15 tag_h6: 'Opskrif 6',
16 tag_p: 'Normaal',
17 tag_pre: 'Opgemaak'
18} );
diff --git a/sources/plugins/format/lang/ar.js b/sources/plugins/format/lang/ar.js
new file mode 100644
index 0000000..8fc1c38
--- /dev/null
+++ b/sources/plugins/format/lang/ar.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ar', {
6 label: 'تنسيق',
7 panelTitle: 'تنسيق الفقرة',
8 tag_address: 'عنوان',
9 tag_div: 'عادي (DIV)',
10 tag_h1: 'العنوان 1',
11 tag_h2: 'العنوان 2',
12 tag_h3: 'العنوان 3',
13 tag_h4: 'العنوان 4',
14 tag_h5: 'العنوان 5',
15 tag_h6: 'العنوان 6',
16 tag_p: 'عادي',
17 tag_pre: 'منسّق'
18} );
diff --git a/sources/plugins/format/lang/az.js b/sources/plugins/format/lang/az.js
new file mode 100644
index 0000000..05b2d54
--- /dev/null
+++ b/sources/plugins/format/lang/az.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'az', {
6 label: 'Format',
7 panelTitle: 'Abzasın formatı',
8 tag_address: 'Ünvan',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Başlıq 1',
11 tag_h2: 'Başlıq 2',
12 tag_h3: 'Başlıq 3',
13 tag_h4: 'Başlıq 4',
14 tag_h5: 'Başlıq 5',
15 tag_h6: 'Başlıq 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatı saxla'
18} );
diff --git a/sources/plugins/format/lang/bg.js b/sources/plugins/format/lang/bg.js
new file mode 100644
index 0000000..3de0ac4
--- /dev/null
+++ b/sources/plugins/format/lang/bg.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'bg', {
6 label: 'Формат',
7 panelTitle: 'Формат',
8 tag_address: 'Адрес',
9 tag_div: 'Параграф (DIV)',
10 tag_h1: 'Заглавие 1',
11 tag_h2: 'Заглавие 2',
12 tag_h3: 'Заглавие 3',
13 tag_h4: 'Заглавие 4',
14 tag_h5: 'Заглавие 5',
15 tag_h6: 'Заглавие 6',
16 tag_p: 'Нормален',
17 tag_pre: 'Форматиран'
18} );
diff --git a/sources/plugins/format/lang/bn.js b/sources/plugins/format/lang/bn.js
new file mode 100644
index 0000000..45857a2
--- /dev/null
+++ b/sources/plugins/format/lang/bn.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'bn', {
6 label: 'ধরন-প্রকৃতি',
7 panelTitle: 'ফন্ট ফরমেট',
8 tag_address: 'ঠিকানা',
9 tag_div: 'শীর্ষক (DIV)',
10 tag_h1: 'শীর্ষক ১',
11 tag_h2: 'শীর্ষক ২',
12 tag_h3: 'শীর্ষক ৩',
13 tag_h4: 'শীর্ষক ৪',
14 tag_h5: 'শীর্ষক ৫',
15 tag_h6: 'শীর্ষক ৬',
16 tag_p: 'সাধারণ',
17 tag_pre: 'ফর্মেটেড'
18} );
diff --git a/sources/plugins/format/lang/bs.js b/sources/plugins/format/lang/bs.js
new file mode 100644
index 0000000..4e9482a
--- /dev/null
+++ b/sources/plugins/format/lang/bs.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'bs', {
6 label: 'Format',
7 panelTitle: 'Format',
8 tag_address: 'Address',
9 tag_div: 'Normal (DIV)', // MISSING
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/ca.js b/sources/plugins/format/lang/ca.js
new file mode 100644
index 0000000..5345898
--- /dev/null
+++ b/sources/plugins/format/lang/ca.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ca', {
6 label: 'Format',
7 panelTitle: 'Format',
8 tag_address: 'Adreça',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Encapçalament 1',
11 tag_h2: 'Encapçalament 2',
12 tag_h3: 'Encapçalament 3',
13 tag_h4: 'Encapçalament 4',
14 tag_h5: 'Encapçalament 5',
15 tag_h6: 'Encapçalament 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatejat'
18} );
diff --git a/sources/plugins/format/lang/cs.js b/sources/plugins/format/lang/cs.js
new file mode 100644
index 0000000..b96a6c4
--- /dev/null
+++ b/sources/plugins/format/lang/cs.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'cs', {
6 label: 'Formát',
7 panelTitle: 'Formát',
8 tag_address: 'Adresa',
9 tag_div: 'Normální (DIV)',
10 tag_h1: 'Nadpis 1',
11 tag_h2: 'Nadpis 2',
12 tag_h3: 'Nadpis 3',
13 tag_h4: 'Nadpis 4',
14 tag_h5: 'Nadpis 5',
15 tag_h6: 'Nadpis 6',
16 tag_p: 'Normální',
17 tag_pre: 'Naformátováno'
18} );
diff --git a/sources/plugins/format/lang/cy.js b/sources/plugins/format/lang/cy.js
new file mode 100644
index 0000000..a8f618f
--- /dev/null
+++ b/sources/plugins/format/lang/cy.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'cy', {
6 label: 'Fformat',
7 panelTitle: 'Fformat Paragraff',
8 tag_address: 'Cyfeiriad',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Pennawd 1',
11 tag_h2: 'Pennawd 2',
12 tag_h3: 'Pennawd 3',
13 tag_h4: 'Pennawd 4',
14 tag_h5: 'Pennawd 5',
15 tag_h6: 'Pennawd 6',
16 tag_p: 'Normal',
17 tag_pre: 'Wedi\'i Fformatio'
18} );
diff --git a/sources/plugins/format/lang/da.js b/sources/plugins/format/lang/da.js
new file mode 100644
index 0000000..1f7c654
--- /dev/null
+++ b/sources/plugins/format/lang/da.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'da', {
6 label: 'Formatering',
7 panelTitle: 'Formatering',
8 tag_address: 'Adresse',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Overskrift 1',
11 tag_h2: 'Overskrift 2',
12 tag_h3: 'Overskrift 3',
13 tag_h4: 'Overskrift 4',
14 tag_h5: 'Overskrift 5',
15 tag_h6: 'Overskrift 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formateret'
18} );
diff --git a/sources/plugins/format/lang/de-ch.js b/sources/plugins/format/lang/de-ch.js
new file mode 100644
index 0000000..68b8879
--- /dev/null
+++ b/sources/plugins/format/lang/de-ch.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'de-ch', {
6 label: 'Format',
7 panelTitle: 'Absatzformat',
8 tag_address: 'Adresse',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Überschrift 1',
11 tag_h2: 'Überschrift 2',
12 tag_h3: 'Überschrift 3',
13 tag_h4: 'Überschrift 4',
14 tag_h5: 'Überschrift 5',
15 tag_h6: 'Überschrift 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatiert'
18} );
diff --git a/sources/plugins/format/lang/de.js b/sources/plugins/format/lang/de.js
new file mode 100644
index 0000000..e6f6677
--- /dev/null
+++ b/sources/plugins/format/lang/de.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'de', {
6 label: 'Format',
7 panelTitle: 'Absatzformat',
8 tag_address: 'Adresse',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Überschrift 1',
11 tag_h2: 'Überschrift 2',
12 tag_h3: 'Überschrift 3',
13 tag_h4: 'Überschrift 4',
14 tag_h5: 'Überschrift 5',
15 tag_h6: 'Überschrift 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatiert'
18} );
diff --git a/sources/plugins/format/lang/el.js b/sources/plugins/format/lang/el.js
new file mode 100644
index 0000000..9b34051
--- /dev/null
+++ b/sources/plugins/format/lang/el.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'el', {
6 label: 'Μορφοποίηση',
7 panelTitle: 'Μορφοποίηση Παραγράφου',
8 tag_address: 'Διεύθυνση',
9 tag_div: 'Κανονική (DIV)',
10 tag_h1: 'Κεφαλίδα 1',
11 tag_h2: 'Κεφαλίδα 2',
12 tag_h3: 'Κεφαλίδα 3',
13 tag_h4: 'Κεφαλίδα 4',
14 tag_h5: 'Κεφαλίδα 5',
15 tag_h6: 'Κεφαλίδα 6',
16 tag_p: 'Κανονική',
17 tag_pre: 'Προ-μορφοποιημένη'
18} );
diff --git a/sources/plugins/format/lang/en-au.js b/sources/plugins/format/lang/en-au.js
new file mode 100644
index 0000000..5ec7d8e
--- /dev/null
+++ b/sources/plugins/format/lang/en-au.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'en-au', {
6 label: 'Format',
7 panelTitle: 'Paragraph Format',
8 tag_address: 'Address',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/en-ca.js b/sources/plugins/format/lang/en-ca.js
new file mode 100644
index 0000000..75d66c3
--- /dev/null
+++ b/sources/plugins/format/lang/en-ca.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'en-ca', {
6 label: 'Format',
7 panelTitle: 'Paragraph Format',
8 tag_address: 'Address',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/en-gb.js b/sources/plugins/format/lang/en-gb.js
new file mode 100644
index 0000000..a91bcbf
--- /dev/null
+++ b/sources/plugins/format/lang/en-gb.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'en-gb', {
6 label: 'Format',
7 panelTitle: 'Paragraph Format',
8 tag_address: 'Address',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/en.js b/sources/plugins/format/lang/en.js
new file mode 100644
index 0000000..3a6ebda
--- /dev/null
+++ b/sources/plugins/format/lang/en.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'en', {
6 label: 'Format',
7 panelTitle: 'Paragraph Format',
8 tag_address: 'Address',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/eo.js b/sources/plugins/format/lang/eo.js
new file mode 100644
index 0000000..0d77730
--- /dev/null
+++ b/sources/plugins/format/lang/eo.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'eo', {
6 label: 'Formato',
7 panelTitle: 'ParagrafFormato',
8 tag_address: 'Adreso',
9 tag_div: 'Normala (DIV)',
10 tag_h1: 'Titolo 1',
11 tag_h2: 'Titolo 2',
12 tag_h3: 'Titolo 3',
13 tag_h4: 'Titolo 4',
14 tag_h5: 'Titolo 5',
15 tag_h6: 'Titolo 6',
16 tag_p: 'Normala',
17 tag_pre: 'Formatita'
18} );
diff --git a/sources/plugins/format/lang/es.js b/sources/plugins/format/lang/es.js
new file mode 100644
index 0000000..549f611
--- /dev/null
+++ b/sources/plugins/format/lang/es.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'es', {
6 label: 'Formato',
7 panelTitle: 'Formato',
8 tag_address: 'Dirección',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Encabezado 1',
11 tag_h2: 'Encabezado 2',
12 tag_h3: 'Encabezado 3',
13 tag_h4: 'Encabezado 4',
14 tag_h5: 'Encabezado 5',
15 tag_h6: 'Encabezado 6',
16 tag_p: 'Normal',
17 tag_pre: 'Con formato'
18} );
diff --git a/sources/plugins/format/lang/et.js b/sources/plugins/format/lang/et.js
new file mode 100644
index 0000000..43bc350
--- /dev/null
+++ b/sources/plugins/format/lang/et.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'et', {
6 label: 'Vorming',
7 panelTitle: 'Vorming',
8 tag_address: 'Aadress',
9 tag_div: 'Tavaline (DIV)',
10 tag_h1: 'Pealkiri 1',
11 tag_h2: 'Pealkiri 2',
12 tag_h3: 'Pealkiri 3',
13 tag_h4: 'Pealkiri 4',
14 tag_h5: 'Pealkiri 5',
15 tag_h6: 'Pealkiri 6',
16 tag_p: 'Tavaline',
17 tag_pre: 'Vormindatud'
18} );
diff --git a/sources/plugins/format/lang/eu.js b/sources/plugins/format/lang/eu.js
new file mode 100644
index 0000000..18832bc
--- /dev/null
+++ b/sources/plugins/format/lang/eu.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'eu', {
6 label: 'Formatua',
7 panelTitle: 'Paragrafoaren formatua',
8 tag_address: 'Helbidea',
9 tag_div: 'Normala (DIV)',
10 tag_h1: 'Izenburua 1',
11 tag_h2: 'Izenburua 2',
12 tag_h3: 'Izenburua 3',
13 tag_h4: 'Izenburua 4',
14 tag_h5: 'Izenburua 5',
15 tag_h6: 'Izenburua 6',
16 tag_p: 'Normala',
17 tag_pre: 'Formatuduna'
18} );
diff --git a/sources/plugins/format/lang/fa.js b/sources/plugins/format/lang/fa.js
new file mode 100644
index 0000000..c92db53
--- /dev/null
+++ b/sources/plugins/format/lang/fa.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'fa', {
6 label: 'قالب',
7 panelTitle: 'قالب بند',
8 tag_address: 'نشانی',
9 tag_div: 'بند',
10 tag_h1: 'سرنویس ۱',
11 tag_h2: 'سرنویس ۲',
12 tag_h3: 'سرنویس ۳',
13 tag_h4: 'سرنویس ۴',
14 tag_h5: 'سرنویس ۵',
15 tag_h6: 'سرنویس ۶',
16 tag_p: 'معمولی',
17 tag_pre: 'قالب‌دار'
18} );
diff --git a/sources/plugins/format/lang/fi.js b/sources/plugins/format/lang/fi.js
new file mode 100644
index 0000000..249183d
--- /dev/null
+++ b/sources/plugins/format/lang/fi.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'fi', {
6 label: 'Muotoilu',
7 panelTitle: 'Muotoilu',
8 tag_address: 'Osoite',
9 tag_div: 'Normaali (DIV)',
10 tag_h1: 'Otsikko 1',
11 tag_h2: 'Otsikko 2',
12 tag_h3: 'Otsikko 3',
13 tag_h4: 'Otsikko 4',
14 tag_h5: 'Otsikko 5',
15 tag_h6: 'Otsikko 6',
16 tag_p: 'Normaali',
17 tag_pre: 'Muotoiltu'
18} );
diff --git a/sources/plugins/format/lang/fo.js b/sources/plugins/format/lang/fo.js
new file mode 100644
index 0000000..2c88021
--- /dev/null
+++ b/sources/plugins/format/lang/fo.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'fo', {
6 label: 'Skriftsnið',
7 panelTitle: 'Skriftsnið',
8 tag_address: 'Adressa',
9 tag_div: 'Vanligt (DIV)',
10 tag_h1: 'Yvirskrift 1',
11 tag_h2: 'Yvirskrift 2',
12 tag_h3: 'Yvirskrift 3',
13 tag_h4: 'Yvirskrift 4',
14 tag_h5: 'Yvirskrift 5',
15 tag_h6: 'Yvirskrift 6',
16 tag_p: 'Vanligt',
17 tag_pre: 'Sniðgivið'
18} );
diff --git a/sources/plugins/format/lang/fr-ca.js b/sources/plugins/format/lang/fr-ca.js
new file mode 100644
index 0000000..8f190c2
--- /dev/null
+++ b/sources/plugins/format/lang/fr-ca.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'fr-ca', {
6 label: 'Format',
7 panelTitle: 'Format de paragraphe',
8 tag_address: 'Adresse',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'En-tête 1',
11 tag_h2: 'En-tête 2',
12 tag_h3: 'En-tête 3',
13 tag_h4: 'En-tête 4',
14 tag_h5: 'En-tête 5',
15 tag_h6: 'En-tête 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formaté'
18} );
diff --git a/sources/plugins/format/lang/fr.js b/sources/plugins/format/lang/fr.js
new file mode 100644
index 0000000..6962da7
--- /dev/null
+++ b/sources/plugins/format/lang/fr.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'fr', {
6 label: 'Format',
7 panelTitle: 'Format de paragraphe',
8 tag_address: 'Adresse',
9 tag_div: 'Division',
10 tag_h1: 'Titre 1',
11 tag_h2: 'Titre 2',
12 tag_h3: 'Titre 3',
13 tag_h4: 'Titre 4',
14 tag_h5: 'Titre 5',
15 tag_h6: 'Titre 6',
16 tag_p: 'Normal',
17 tag_pre: 'Préformaté'
18} );
diff --git a/sources/plugins/format/lang/gl.js b/sources/plugins/format/lang/gl.js
new file mode 100644
index 0000000..d14946c
--- /dev/null
+++ b/sources/plugins/format/lang/gl.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'gl', {
6 label: 'Formato',
7 panelTitle: 'Formato do parágrafo',
8 tag_address: 'Enderezo',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Enacabezado 1',
11 tag_h2: 'Encabezado 2',
12 tag_h3: 'Encabezado 3',
13 tag_h4: 'Encabezado 4',
14 tag_h5: 'Encabezado 5',
15 tag_h6: 'Encabezado 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatado'
18} );
diff --git a/sources/plugins/format/lang/gu.js b/sources/plugins/format/lang/gu.js
new file mode 100644
index 0000000..8d8897a
--- /dev/null
+++ b/sources/plugins/format/lang/gu.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'gu', {
6 label: 'ફૉન્ટ ફૉર્મટ, રચનાની શૈલી',
7 panelTitle: 'ફૉન્ટ ફૉર્મટ, રચનાની શૈલી',
8 tag_address: 'સરનામું',
9 tag_div: 'શીર્ષક (DIV)',
10 tag_h1: 'શીર્ષક 1',
11 tag_h2: 'શીર્ષક 2',
12 tag_h3: 'શીર્ષક 3',
13 tag_h4: 'શીર્ષક 4',
14 tag_h5: 'શીર્ષક 5',
15 tag_h6: 'શીર્ષક 6',
16 tag_p: 'સામાન્ય',
17 tag_pre: 'ફૉર્મટેડ'
18} );
diff --git a/sources/plugins/format/lang/he.js b/sources/plugins/format/lang/he.js
new file mode 100644
index 0000000..5fb53a7
--- /dev/null
+++ b/sources/plugins/format/lang/he.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'he', {
6 label: 'עיצוב',
7 panelTitle: 'עיצוב',
8 tag_address: 'כתובת',
9 tag_div: 'נורמלי (DIV)',
10 tag_h1: 'כותרת',
11 tag_h2: 'כותרת 2',
12 tag_h3: 'כותרת 3',
13 tag_h4: 'כותרת 4',
14 tag_h5: 'כותרת 5',
15 tag_h6: 'כותרת 6',
16 tag_p: 'נורמלי',
17 tag_pre: 'קוד'
18} );
diff --git a/sources/plugins/format/lang/hi.js b/sources/plugins/format/lang/hi.js
new file mode 100644
index 0000000..ce4224d
--- /dev/null
+++ b/sources/plugins/format/lang/hi.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'hi', {
6 label: 'फ़ॉर्मैट',
7 panelTitle: 'फ़ॉर्मैट',
8 tag_address: 'पता',
9 tag_div: 'शीर्षक (DIV)',
10 tag_h1: 'शीर्षक 1',
11 tag_h2: 'शीर्षक 2',
12 tag_h3: 'शीर्षक 3',
13 tag_h4: 'शीर्षक 4',
14 tag_h5: 'शीर्षक 5',
15 tag_h6: 'शीर्षक 6',
16 tag_p: 'साधारण',
17 tag_pre: 'फ़ॉर्मैटॅड'
18} );
diff --git a/sources/plugins/format/lang/hr.js b/sources/plugins/format/lang/hr.js
new file mode 100644
index 0000000..2d6ec21
--- /dev/null
+++ b/sources/plugins/format/lang/hr.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'hr', {
6 label: 'Format',
7 panelTitle: 'Format',
8 tag_address: 'Address',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatirano'
18} );
diff --git a/sources/plugins/format/lang/hu.js b/sources/plugins/format/lang/hu.js
new file mode 100644
index 0000000..a5467cf
--- /dev/null
+++ b/sources/plugins/format/lang/hu.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'hu', {
6 label: 'Formátum',
7 panelTitle: 'Formátum',
8 tag_address: 'Címsor',
9 tag_div: 'Bekezdés (DIV)',
10 tag_h1: 'Fejléc 1',
11 tag_h2: 'Fejléc 2',
12 tag_h3: 'Fejléc 3',
13 tag_h4: 'Fejléc 4',
14 tag_h5: 'Fejléc 5',
15 tag_h6: 'Fejléc 6',
16 tag_p: 'Normál',
17 tag_pre: 'Formázott'
18} );
diff --git a/sources/plugins/format/lang/id.js b/sources/plugins/format/lang/id.js
new file mode 100644
index 0000000..e8e83f7
--- /dev/null
+++ b/sources/plugins/format/lang/id.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'id', {
6 label: 'Bentuk',
7 panelTitle: 'Bentuk Paragraf',
8 tag_address: 'Alamat',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Membentuk'
18} );
diff --git a/sources/plugins/format/lang/is.js b/sources/plugins/format/lang/is.js
new file mode 100644
index 0000000..862e52e
--- /dev/null
+++ b/sources/plugins/format/lang/is.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'is', {
6 label: 'Stílsnið',
7 panelTitle: 'Stílsnið',
8 tag_address: 'Vistfang',
9 tag_div: 'Venjulegt (DIV)',
10 tag_h1: 'Fyrirsögn 1',
11 tag_h2: 'Fyrirsögn 2',
12 tag_h3: 'Fyrirsögn 3',
13 tag_h4: 'Fyrirsögn 4',
14 tag_h5: 'Fyrirsögn 5',
15 tag_h6: 'Fyrirsögn 6',
16 tag_p: 'Venjulegt letur',
17 tag_pre: 'Forsniðið'
18} );
diff --git a/sources/plugins/format/lang/it.js b/sources/plugins/format/lang/it.js
new file mode 100644
index 0000000..6d47500
--- /dev/null
+++ b/sources/plugins/format/lang/it.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'it', {
6 label: 'Formato',
7 panelTitle: 'Formato',
8 tag_address: 'Indirizzo',
9 tag_div: 'Paragrafo (DIV)',
10 tag_h1: 'Titolo 1',
11 tag_h2: 'Titolo 2',
12 tag_h3: 'Titolo 3',
13 tag_h4: 'Titolo 4',
14 tag_h5: 'Titolo 5',
15 tag_h6: 'Titolo 6',
16 tag_p: 'Normale',
17 tag_pre: 'Formattato'
18} );
diff --git a/sources/plugins/format/lang/ja.js b/sources/plugins/format/lang/ja.js
new file mode 100644
index 0000000..a611f3d
--- /dev/null
+++ b/sources/plugins/format/lang/ja.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ja', {
6 label: '書式',
7 panelTitle: '段落の書式',
8 tag_address: 'アドレス',
9 tag_div: '標準 (DIV)',
10 tag_h1: '見出し 1',
11 tag_h2: '見出し 2',
12 tag_h3: '見出し 3',
13 tag_h4: '見出し 4',
14 tag_h5: '見出し 5',
15 tag_h6: '見出し 6',
16 tag_p: '標準',
17 tag_pre: '書式付き'
18} );
diff --git a/sources/plugins/format/lang/ka.js b/sources/plugins/format/lang/ka.js
new file mode 100644
index 0000000..f5c95b8
--- /dev/null
+++ b/sources/plugins/format/lang/ka.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ka', {
6 label: 'ფიორმატირება',
7 panelTitle: 'ფორმატირება',
8 tag_address: 'მისამართი',
9 tag_div: 'ჩვეულებრივი (DIV)',
10 tag_h1: 'სათაური 1',
11 tag_h2: 'სათაური 2',
12 tag_h3: 'სათაური 3',
13 tag_h4: 'სათაური 4',
14 tag_h5: 'სათაური 5',
15 tag_h6: 'სათაური 6',
16 tag_p: 'ჩვეულებრივი',
17 tag_pre: 'ფორმატირებული'
18} );
diff --git a/sources/plugins/format/lang/km.js b/sources/plugins/format/lang/km.js
new file mode 100644
index 0000000..74ca185
--- /dev/null
+++ b/sources/plugins/format/lang/km.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'km', {
6 label: 'ទម្រង់',
7 panelTitle: 'ទម្រង់​កថាខណ្ឌ',
8 tag_address: 'អាសយដ្ឋាន',
9 tag_div: 'ធម្មតា (DIV)',
10 tag_h1: 'ចំណង​ជើង 1',
11 tag_h2: 'ចំណង​ជើង 2',
12 tag_h3: 'ចំណង​ជើង 3',
13 tag_h4: 'ចំណង​ជើង 4',
14 tag_h5: 'ចំណង​ជើង 5',
15 tag_h6: 'ចំណង​ជើង 6',
16 tag_p: 'ធម្មតា',
17 tag_pre: 'Formatted' // MISSING
18} );
diff --git a/sources/plugins/format/lang/ko.js b/sources/plugins/format/lang/ko.js
new file mode 100644
index 0000000..e5ed44c
--- /dev/null
+++ b/sources/plugins/format/lang/ko.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ko', {
6 label: '문단',
7 panelTitle: '문단 형식',
8 tag_address: '글쓴이',
9 tag_div: '기본 (DIV)',
10 tag_h1: '제목 1',
11 tag_h2: '제목 2',
12 tag_h3: '제목 3',
13 tag_h4: '제목 4',
14 tag_h5: '제목 5',
15 tag_h6: '제목 6',
16 tag_p: '본문',
17 tag_pre: '정형 문단'
18} );
diff --git a/sources/plugins/format/lang/ku.js b/sources/plugins/format/lang/ku.js
new file mode 100644
index 0000000..277bf8e
--- /dev/null
+++ b/sources/plugins/format/lang/ku.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ku', {
6 label: 'ڕازاندنەوە',
7 panelTitle: 'بەشی ڕازاندنەوه',
8 tag_address: 'ناونیشان',
9 tag_div: '(DIV)-ی ئاسایی',
10 tag_h1: 'سەرنووسەی ١',
11 tag_h2: 'سەرنووسەی ٢',
12 tag_h3: 'سەرنووسەی ٣',
13 tag_h4: 'سەرنووسەی ٤',
14 tag_h5: 'سەرنووسەی ٥',
15 tag_h6: 'سەرنووسەی ٦',
16 tag_p: 'ئاسایی',
17 tag_pre: 'شێوازکراو'
18} );
diff --git a/sources/plugins/format/lang/lt.js b/sources/plugins/format/lang/lt.js
new file mode 100644
index 0000000..9733443
--- /dev/null
+++ b/sources/plugins/format/lang/lt.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'lt', {
6 label: 'Šrifto formatas',
7 panelTitle: 'Šrifto formatas',
8 tag_address: 'Kreipinio',
9 tag_div: 'Normalus (DIV)',
10 tag_h1: 'Antraštinis 1',
11 tag_h2: 'Antraštinis 2',
12 tag_h3: 'Antraštinis 3',
13 tag_h4: 'Antraštinis 4',
14 tag_h5: 'Antraštinis 5',
15 tag_h6: 'Antraštinis 6',
16 tag_p: 'Normalus',
17 tag_pre: 'Formuotas'
18} );
diff --git a/sources/plugins/format/lang/lv.js b/sources/plugins/format/lang/lv.js
new file mode 100644
index 0000000..ace8333
--- /dev/null
+++ b/sources/plugins/format/lang/lv.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'lv', {
6 label: 'Formāts',
7 panelTitle: 'Formāts',
8 tag_address: 'Adrese',
9 tag_div: 'Rindkopa (DIV)',
10 tag_h1: 'Virsraksts 1',
11 tag_h2: 'Virsraksts 2',
12 tag_h3: 'Virsraksts 3',
13 tag_h4: 'Virsraksts 4',
14 tag_h5: 'Virsraksts 5',
15 tag_h6: 'Virsraksts 6',
16 tag_p: 'Normāls teksts',
17 tag_pre: 'Formatēts teksts'
18} );
diff --git a/sources/plugins/format/lang/mk.js b/sources/plugins/format/lang/mk.js
new file mode 100644
index 0000000..5c0bb3b
--- /dev/null
+++ b/sources/plugins/format/lang/mk.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'mk', {
6 label: 'Format', // MISSING
7 panelTitle: 'Paragraph Format', // MISSING
8 tag_address: 'Address', // MISSING
9 tag_div: 'Normal (DIV)', // MISSING
10 tag_h1: 'Heading 1', // MISSING
11 tag_h2: 'Heading 2', // MISSING
12 tag_h3: 'Heading 3', // MISSING
13 tag_h4: 'Heading 4', // MISSING
14 tag_h5: 'Heading 5', // MISSING
15 tag_h6: 'Heading 6', // MISSING
16 tag_p: 'Normal', // MISSING
17 tag_pre: 'Formatted' // MISSING
18} );
diff --git a/sources/plugins/format/lang/mn.js b/sources/plugins/format/lang/mn.js
new file mode 100644
index 0000000..f3c0dfd
--- /dev/null
+++ b/sources/plugins/format/lang/mn.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'mn', {
6 label: 'Параргафын загвар',
7 panelTitle: 'Параргафын загвар',
8 tag_address: 'Хаяг',
9 tag_div: 'Paragraph (DIV)',
10 tag_h1: 'Гарчиг 1',
11 tag_h2: 'Гарчиг 2',
12 tag_h3: 'Гарчиг 3',
13 tag_h4: 'Гарчиг 4',
14 tag_h5: 'Гарчиг 5',
15 tag_h6: 'Гарчиг 6',
16 tag_p: 'Хэвийн',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/ms.js b/sources/plugins/format/lang/ms.js
new file mode 100644
index 0000000..56deba9
--- /dev/null
+++ b/sources/plugins/format/lang/ms.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ms', {
6 label: 'Format',
7 panelTitle: 'Format',
8 tag_address: 'Alamat',
9 tag_div: 'Perenggan (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Telah Diformat'
18} );
diff --git a/sources/plugins/format/lang/nb.js b/sources/plugins/format/lang/nb.js
new file mode 100644
index 0000000..6bfffb5
--- /dev/null
+++ b/sources/plugins/format/lang/nb.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'nb', {
6 label: 'Format',
7 panelTitle: 'Avsnittsformat',
8 tag_address: 'Adresse',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Overskrift 1',
11 tag_h2: 'Overskrift 2',
12 tag_h3: 'Overskrift 3',
13 tag_h4: 'Overskrift 4',
14 tag_h5: 'Overskrift 5',
15 tag_h6: 'Overskrift 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatert'
18} );
diff --git a/sources/plugins/format/lang/nl.js b/sources/plugins/format/lang/nl.js
new file mode 100644
index 0000000..ef2676a
--- /dev/null
+++ b/sources/plugins/format/lang/nl.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'nl', {
6 label: 'Opmaak',
7 panelTitle: 'Opmaak',
8 tag_address: 'Adres',
9 tag_div: 'Normaal (DIV)',
10 tag_h1: 'Kop 1',
11 tag_h2: 'Kop 2',
12 tag_h3: 'Kop 3',
13 tag_h4: 'Kop 4',
14 tag_h5: 'Kop 5',
15 tag_h6: 'Kop 6',
16 tag_p: 'Normaal',
17 tag_pre: 'Met opmaak'
18} );
diff --git a/sources/plugins/format/lang/no.js b/sources/plugins/format/lang/no.js
new file mode 100644
index 0000000..d9b0586
--- /dev/null
+++ b/sources/plugins/format/lang/no.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'no', {
6 label: 'Format',
7 panelTitle: 'Avsnittsformat',
8 tag_address: 'Adresse',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Overskrift 1',
11 tag_h2: 'Overskrift 2',
12 tag_h3: 'Overskrift 3',
13 tag_h4: 'Overskrift 4',
14 tag_h5: 'Overskrift 5',
15 tag_h6: 'Overskrift 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatert'
18} );
diff --git a/sources/plugins/format/lang/oc.js b/sources/plugins/format/lang/oc.js
new file mode 100644
index 0000000..5083f3f
--- /dev/null
+++ b/sources/plugins/format/lang/oc.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'oc', {
6 label: 'Format',
7 panelTitle: 'Format de paragraf',
8 tag_address: 'Adreça',
9 tag_div: 'Division (DIV)',
10 tag_h1: 'Títol 1',
11 tag_h2: 'Títol 2',
12 tag_h3: 'Títol 3',
13 tag_h4: 'Títol 4',
14 tag_h5: 'Títol 5',
15 tag_h6: 'Títol 6',
16 tag_p: 'Normal',
17 tag_pre: 'Preformatat'
18} );
diff --git a/sources/plugins/format/lang/pl.js b/sources/plugins/format/lang/pl.js
new file mode 100644
index 0000000..d1274f9
--- /dev/null
+++ b/sources/plugins/format/lang/pl.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'pl', {
6 label: 'Format',
7 panelTitle: 'Format',
8 tag_address: 'Adres',
9 tag_div: 'Normalny (DIV)',
10 tag_h1: 'Nagłówek 1',
11 tag_h2: 'Nagłówek 2',
12 tag_h3: 'Nagłówek 3',
13 tag_h4: 'Nagłówek 4',
14 tag_h5: 'Nagłówek 5',
15 tag_h6: 'Nagłówek 6',
16 tag_p: 'Normalny',
17 tag_pre: 'Tekst sformatowany'
18} );
diff --git a/sources/plugins/format/lang/pt-br.js b/sources/plugins/format/lang/pt-br.js
new file mode 100644
index 0000000..151d1d1
--- /dev/null
+++ b/sources/plugins/format/lang/pt-br.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'pt-br', {
6 label: 'Formatação',
7 panelTitle: 'Formatação',
8 tag_address: 'Endereço',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Título 1',
11 tag_h2: 'Título 2',
12 tag_h3: 'Título 3',
13 tag_h4: 'Título 4',
14 tag_h5: 'Título 5',
15 tag_h6: 'Título 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatado'
18} );
diff --git a/sources/plugins/format/lang/pt.js b/sources/plugins/format/lang/pt.js
new file mode 100644
index 0000000..013021d
--- /dev/null
+++ b/sources/plugins/format/lang/pt.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'pt', {
6 label: 'Formatar',
7 panelTitle: 'Formatar Parágrafo',
8 tag_address: 'Endereço',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Título 1',
11 tag_h2: 'Título 2',
12 tag_h3: 'Título 3',
13 tag_h4: 'Título 4',
14 tag_h5: 'Título 5',
15 tag_h6: 'Título 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatado'
18} );
diff --git a/sources/plugins/format/lang/ro.js b/sources/plugins/format/lang/ro.js
new file mode 100644
index 0000000..549a1b5
--- /dev/null
+++ b/sources/plugins/format/lang/ro.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ro', {
6 label: 'Formatare',
7 panelTitle: 'Formatare',
8 tag_address: 'Adresă',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatat'
18} );
diff --git a/sources/plugins/format/lang/ru.js b/sources/plugins/format/lang/ru.js
new file mode 100644
index 0000000..8e63455
--- /dev/null
+++ b/sources/plugins/format/lang/ru.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ru', {
6 label: 'Форматирование',
7 panelTitle: 'Форматирование',
8 tag_address: 'Адрес',
9 tag_div: 'Обычное (div)',
10 tag_h1: 'Заголовок 1',
11 tag_h2: 'Заголовок 2',
12 tag_h3: 'Заголовок 3',
13 tag_h4: 'Заголовок 4',
14 tag_h5: 'Заголовок 5',
15 tag_h6: 'Заголовок 6',
16 tag_p: 'Обычное',
17 tag_pre: 'Моноширинное'
18} );
diff --git a/sources/plugins/format/lang/si.js b/sources/plugins/format/lang/si.js
new file mode 100644
index 0000000..f27eb7f
--- /dev/null
+++ b/sources/plugins/format/lang/si.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'si', {
6 label: 'ආකෘතිය',
7 panelTitle: 'චේදයේ ',
8 tag_address: 'ලිපිනය',
9 tag_div: 'සාමාන්‍ය(DIV)',
10 tag_h1: 'ශීර්ෂය 1',
11 tag_h2: 'ශීර්ෂය 2',
12 tag_h3: 'ශීර්ෂය 3',
13 tag_h4: 'ශීර්ෂය 4',
14 tag_h5: 'ශීර්ෂය 5',
15 tag_h6: 'ශීර්ෂය 6',
16 tag_p: 'සාමාන්‍ය',
17 tag_pre: 'ආකෘතියන්'
18} );
diff --git a/sources/plugins/format/lang/sk.js b/sources/plugins/format/lang/sk.js
new file mode 100644
index 0000000..30ca66c
--- /dev/null
+++ b/sources/plugins/format/lang/sk.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'sk', {
6 label: 'Formát',
7 panelTitle: 'Odsek',
8 tag_address: 'Adresa',
9 tag_div: 'Normálny (DIV)',
10 tag_h1: 'Nadpis 1',
11 tag_h2: 'Nadpis 2',
12 tag_h3: 'Nadpis 3',
13 tag_h4: 'Nadpis 4',
14 tag_h5: 'Nadpis 5',
15 tag_h6: 'Nadpis 6',
16 tag_p: 'Normálny',
17 tag_pre: 'Formátovaný'
18} );
diff --git a/sources/plugins/format/lang/sl.js b/sources/plugins/format/lang/sl.js
new file mode 100644
index 0000000..2dad54f
--- /dev/null
+++ b/sources/plugins/format/lang/sl.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'sl', {
6 label: 'Oblika',
7 panelTitle: 'Oblika odstavka',
8 tag_address: 'Napis',
9 tag_div: 'Navaden (DIV)',
10 tag_h1: 'Naslov 1',
11 tag_h2: 'Naslov 2',
12 tag_h3: 'Naslov 3',
13 tag_h4: 'Naslov 4',
14 tag_h5: 'Naslov 5',
15 tag_h6: 'Naslov 6',
16 tag_p: 'Navaden',
17 tag_pre: 'Oblikovan'
18} );
diff --git a/sources/plugins/format/lang/sq.js b/sources/plugins/format/lang/sq.js
new file mode 100644
index 0000000..5ddb6ef
--- /dev/null
+++ b/sources/plugins/format/lang/sq.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'sq', {
6 label: 'Formati',
7 panelTitle: 'Formati i Paragrafit',
8 tag_address: 'Adresa',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Titulli 1',
11 tag_h2: 'Titulli 2',
12 tag_h3: 'Titulli 3',
13 tag_h4: 'Titulli 4',
14 tag_h5: 'Titulli 5',
15 tag_h6: 'Titulli 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatuar'
18} );
diff --git a/sources/plugins/format/lang/sr-latn.js b/sources/plugins/format/lang/sr-latn.js
new file mode 100644
index 0000000..d971950
--- /dev/null
+++ b/sources/plugins/format/lang/sr-latn.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'sr-latn', {
6 label: 'Format',
7 panelTitle: 'Format',
8 tag_address: 'Adresa',
9 tag_div: 'Normalno (DIV)',
10 tag_h1: 'Naslov 1',
11 tag_h2: 'Naslov 2',
12 tag_h3: 'Naslov 3',
13 tag_h4: 'Naslov 4',
14 tag_h5: 'Naslov 5',
15 tag_h6: 'Naslov 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatirano'
18} );
diff --git a/sources/plugins/format/lang/sr.js b/sources/plugins/format/lang/sr.js
new file mode 100644
index 0000000..012a14d
--- /dev/null
+++ b/sources/plugins/format/lang/sr.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'sr', {
6 label: 'Формат',
7 panelTitle: 'Формат',
8 tag_address: 'Adresa',
9 tag_div: 'Нормално (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatirano'
18} );
diff --git a/sources/plugins/format/lang/sv.js b/sources/plugins/format/lang/sv.js
new file mode 100644
index 0000000..31850e0
--- /dev/null
+++ b/sources/plugins/format/lang/sv.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'sv', {
6 label: 'Teckenformat',
7 panelTitle: 'Teckenformat',
8 tag_address: 'Adress',
9 tag_div: 'Normal (DIV)',
10 tag_h1: 'Rubrik 1',
11 tag_h2: 'Rubrik 2',
12 tag_h3: 'Rubrik 3',
13 tag_h4: 'Rubrik 4',
14 tag_h5: 'Rubrik 5',
15 tag_h6: 'Rubrik 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formaterad'
18} );
diff --git a/sources/plugins/format/lang/th.js b/sources/plugins/format/lang/th.js
new file mode 100644
index 0000000..4c8a1d2
--- /dev/null
+++ b/sources/plugins/format/lang/th.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'th', {
6 label: 'รูปแบบ',
7 panelTitle: 'รูปแบบ',
8 tag_address: 'Address',
9 tag_div: 'Paragraph (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Normal',
17 tag_pre: 'Formatted'
18} );
diff --git a/sources/plugins/format/lang/tr.js b/sources/plugins/format/lang/tr.js
new file mode 100644
index 0000000..2de6ce2
--- /dev/null
+++ b/sources/plugins/format/lang/tr.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'tr', {
6 label: 'Biçim',
7 panelTitle: 'Biçim',
8 tag_address: 'Adres',
9 tag_div: 'Paragraf (DIV)',
10 tag_h1: 'Başlık 1',
11 tag_h2: 'Başlık 2',
12 tag_h3: 'Başlık 3',
13 tag_h4: 'Başlık 4',
14 tag_h5: 'Başlık 5',
15 tag_h6: 'Başlık 6',
16 tag_p: 'Normal',
17 tag_pre: 'Biçimli'
18} );
diff --git a/sources/plugins/format/lang/tt.js b/sources/plugins/format/lang/tt.js
new file mode 100644
index 0000000..160a192
--- /dev/null
+++ b/sources/plugins/format/lang/tt.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'tt', {
6 label: 'Форматлау',
7 panelTitle: 'Параграф форматлавы',
8 tag_address: 'Адрес',
9 tag_div: 'Гади (DIV)',
10 tag_h1: 'Башлам 1',
11 tag_h2: 'Башлам 2',
12 tag_h3: 'Башлам 3',
13 tag_h4: 'Башлам 4',
14 tag_h5: 'Башлам 5',
15 tag_h6: 'Башлам 6',
16 tag_p: 'Гади',
17 tag_pre: 'Форматлаулы'
18} );
diff --git a/sources/plugins/format/lang/ug.js b/sources/plugins/format/lang/ug.js
new file mode 100644
index 0000000..0be2a15
--- /dev/null
+++ b/sources/plugins/format/lang/ug.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'ug', {
6 label: 'پىچىم',
7 panelTitle: 'پىچىم',
8 tag_address: 'ئادرېس',
9 tag_div: 'ئابزاس (DIV)',
10 tag_h1: 'ماۋزۇ 1',
11 tag_h2: 'ماۋزۇ 2',
12 tag_h3: 'ماۋزۇ 3',
13 tag_h4: 'ماۋزۇ 4',
14 tag_h5: 'ماۋزۇ 5',
15 tag_h6: 'ماۋزۇ 6',
16 tag_p: 'ئادەتتىكى',
17 tag_pre: 'تىزىلغان پىچىم'
18} );
diff --git a/sources/plugins/format/lang/uk.js b/sources/plugins/format/lang/uk.js
new file mode 100644
index 0000000..2e2726d
--- /dev/null
+++ b/sources/plugins/format/lang/uk.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'uk', {
6 label: 'Форматування',
7 panelTitle: 'Форматування параграфа',
8 tag_address: 'Адреса',
9 tag_div: 'Нормальний (div)',
10 tag_h1: 'Заголовок 1',
11 tag_h2: 'Заголовок 2',
12 tag_h3: 'Заголовок 3',
13 tag_h4: 'Заголовок 4',
14 tag_h5: 'Заголовок 5',
15 tag_h6: 'Заголовок 6',
16 tag_p: 'Нормальний',
17 tag_pre: 'Форматований'
18} );
diff --git a/sources/plugins/format/lang/vi.js b/sources/plugins/format/lang/vi.js
new file mode 100644
index 0000000..d051440
--- /dev/null
+++ b/sources/plugins/format/lang/vi.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'vi', {
6 label: 'Định dạng',
7 panelTitle: 'Định dạng',
8 tag_address: 'Address',
9 tag_div: 'Bình thường (DIV)',
10 tag_h1: 'Heading 1',
11 tag_h2: 'Heading 2',
12 tag_h3: 'Heading 3',
13 tag_h4: 'Heading 4',
14 tag_h5: 'Heading 5',
15 tag_h6: 'Heading 6',
16 tag_p: 'Bình thường (P)',
17 tag_pre: 'Đã thiết lập'
18} );
diff --git a/sources/plugins/format/lang/zh-cn.js b/sources/plugins/format/lang/zh-cn.js
new file mode 100644
index 0000000..addaa23
--- /dev/null
+++ b/sources/plugins/format/lang/zh-cn.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'zh-cn', {
6 label: '格式',
7 panelTitle: '格式',
8 tag_address: '地址',
9 tag_div: '段落(DIV)',
10 tag_h1: '标题 1',
11 tag_h2: '标题 2',
12 tag_h3: '标题 3',
13 tag_h4: '标题 4',
14 tag_h5: '标题 5',
15 tag_h6: '标题 6',
16 tag_p: '普通',
17 tag_pre: '已编排格式'
18} );
diff --git a/sources/plugins/format/lang/zh.js b/sources/plugins/format/lang/zh.js
new file mode 100644
index 0000000..bb044ad
--- /dev/null
+++ b/sources/plugins/format/lang/zh.js
@@ -0,0 +1,18 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'format', 'zh', {
6 label: '格式',
7 panelTitle: '段落格式',
8 tag_address: '地址',
9 tag_div: '標準 (DIV)',
10 tag_h1: '標題 1',
11 tag_h2: '標題 2',
12 tag_h3: '標題 3',
13 tag_h4: '標題 4',
14 tag_h5: '標題 5',
15 tag_h6: '標題 6',
16 tag_p: '標準',
17 tag_pre: '格式設定'
18} );
diff --git a/sources/plugins/format/plugin.js b/sources/plugins/format/plugin.js
new file mode 100644
index 0000000..826cbcf
--- /dev/null
+++ b/sources/plugins/format/plugin.js
@@ -0,0 +1,279 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'format', {
7 requires: 'richcombo',
8 // jscs:disable maximumLineLength
9 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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 )
13 return;
14
15 var config = editor.config,
16 lang = editor.lang.format;
17
18 // Gets the list of tags from the settings.
19 var tags = config.format_tags.split( ';' );
20
21 // Create style objects for all defined styles.
22 var styles = {},
23 stylesCount = 0,
24 allowedContent = [];
25 for ( var i = 0; i < tags.length; i++ ) {
26 var tag = tags[ i ];
27 var style = new CKEDITOR.style( config[ 'format_' + tag ] );
28 if ( !editor.filter.customConfig || editor.filter.check( style ) ) {
29 stylesCount++;
30 styles[ tag ] = style;
31 styles[ tag ]._.enterMode = editor.config.enterMode;
32 allowedContent.push( style );
33 }
34 }
35
36 // Hide entire combo when all formats are rejected.
37 if ( stylesCount === 0 )
38 return;
39
40 editor.ui.addRichCombo( 'Format', {
41 label: lang.label,
42 title: lang.panelTitle,
43 toolbar: 'styles,20',
44 allowedContent: allowedContent,
45
46 panel: {
47 css: [ CKEDITOR.skin.getPath( 'editor' ) ].concat( config.contentsCss ),
48 multiSelect: false,
49 attributes: { 'aria-label': lang.panelTitle }
50 },
51
52 init: function() {
53 this.startGroup( lang.panelTitle );
54
55 for ( var tag in styles ) {
56 var label = lang[ 'tag_' + tag ];
57
58 // Add the tag entry to the panel list.
59 this.add( tag, styles[ tag ].buildPreview( label ), label );
60 }
61 },
62
63 onClick: function( value ) {
64 editor.focus();
65 editor.fire( 'saveSnapshot' );
66
67 var style = styles[ value ],
68 elementPath = editor.elementPath();
69
70 editor[ style.checkActive( elementPath, editor ) ? 'removeStyle' : 'applyStyle' ]( style );
71
72 // Save the undo snapshot after all changes are affected. (#4899)
73 setTimeout( function() {
74 editor.fire( 'saveSnapshot' );
75 }, 0 );
76 },
77
78 onRender: function() {
79 editor.on( 'selectionChange', function( ev ) {
80 var currentTag = this.getValue(),
81 elementPath = ev.data.path;
82
83 this.refresh();
84
85 for ( var tag in styles ) {
86 if ( styles[ tag ].checkActive( elementPath, editor ) ) {
87 if ( tag != currentTag )
88 this.setValue( tag, editor.lang.format[ 'tag_' + tag ] );
89 return;
90 }
91 }
92
93 // If no styles match, just empty it.
94 this.setValue( '' );
95
96 }, this );
97 },
98
99 onOpen: function() {
100 this.showAll();
101 for ( var name in styles ) {
102 var style = styles[ name ];
103
104 // Check if that style is enabled in activeFilter.
105 if ( !editor.activeFilter.check( style ) )
106 this.hideItem( name );
107
108 }
109 },
110
111 refresh: function() {
112 var elementPath = editor.elementPath();
113
114 if ( !elementPath )
115 return;
116
117 // Check if element path contains 'p' element.
118 if ( !elementPath.isContextFor( 'p' ) ) {
119 this.setState( CKEDITOR.TRISTATE_DISABLED );
120 return;
121 }
122
123 // Check if there is any available style.
124 for ( var name in styles ) {
125 if ( editor.activeFilter.check( styles[ name ] ) )
126 return;
127 }
128 this.setState( CKEDITOR.TRISTATE_DISABLED );
129 }
130 } );
131 }
132} );
133
134/**
135 * A list of semicolon-separated style names (by default: tags) representing
136 * the style definition for each entry to be displayed in the Format drop-down list
137 * in the toolbar. Each entry must have a corresponding configuration in a
138 * setting named `'format_(tagName)'`. For example, the `'p'` entry has its
139 * definition taken from [config.format_p](#!/api/CKEDITOR.config-cfg-format_p).
140 *
141 * Read more in the [documentation](#!/guide/dev_format)
142 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
143 *
144 * config.format_tags = 'p;h2;h3;pre';
145 *
146 * @cfg {String} [format_tags='p;h1;h2;h3;h4;h5;h6;pre;address;div']
147 * @member CKEDITOR.config
148 */
149CKEDITOR.config.format_tags = 'p;h1;h2;h3;h4;h5;h6;pre;address;div';
150
151/**
152 * The style definition to be used to apply the `Normal` format.
153 *
154 * Read more in the [documentation](#!/guide/dev_format)
155 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
156 *
157 * config.format_p = { element: 'p', attributes: { 'class': 'normalPara' } };
158 *
159 * @cfg {Object} [format_p={ element: 'p' }]
160 * @member CKEDITOR.config
161 */
162CKEDITOR.config.format_p = { element: 'p' };
163
164/**
165 * The style definition to be used to apply the `Normal (DIV)` format.
166 *
167 * Read more in the [documentation](#!/guide/dev_format)
168 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
169 *
170 * config.format_div = { element: 'div', attributes: { 'class': 'normalDiv' } };
171 *
172 * @cfg {Object} [format_div={ element: 'div' }]
173 * @member CKEDITOR.config
174 */
175CKEDITOR.config.format_div = { element: 'div' };
176
177/**
178 * The style definition to be used to apply the `Formatted` format.
179 *
180 * Read more in the [documentation](#!/guide/dev_format)
181 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
182 *
183 * config.format_pre = { element: 'pre', attributes: { 'class': 'code' } };
184 *
185 * @cfg {Object} [format_pre={ element: 'pre' }]
186 * @member CKEDITOR.config
187 */
188CKEDITOR.config.format_pre = { element: 'pre' };
189
190/**
191 * The style definition to be used to apply the `Address` format.
192 *
193 * Read more in the [documentation](#!/guide/dev_format)
194 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
195 *
196 * config.format_address = { element: 'address', attributes: { 'class': 'styledAddress' } };
197 *
198 * @cfg {Object} [format_address={ element: 'address' }]
199 * @member CKEDITOR.config
200 */
201CKEDITOR.config.format_address = { element: 'address' };
202
203/**
204 * The style definition to be used to apply the `Heading 1` format.
205 *
206 * Read more in the [documentation](#!/guide/dev_format)
207 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
208 *
209 * config.format_h1 = { element: 'h1', attributes: { 'class': 'contentTitle1' } };
210 *
211 * @cfg {Object} [format_h1={ element: 'h1' }]
212 * @member CKEDITOR.config
213 */
214CKEDITOR.config.format_h1 = { element: 'h1' };
215
216/**
217 * The style definition to be used to apply the `Heading 2` format.
218 *
219 * Read more in the [documentation](#!/guide/dev_format)
220 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
221 *
222 * config.format_h2 = { element: 'h2', attributes: { 'class': 'contentTitle2' } };
223 *
224 * @cfg {Object} [format_h2={ element: 'h2' }]
225 * @member CKEDITOR.config
226 */
227CKEDITOR.config.format_h2 = { element: 'h2' };
228
229/**
230 * The style definition to be used to apply the `Heading 3` format.
231 *
232 * Read more in the [documentation](#!/guide/dev_format)
233 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
234 *
235 * config.format_h3 = { element: 'h3', attributes: { 'class': 'contentTitle3' } };
236 *
237 * @cfg {Object} [format_h3={ element: 'h3' }]
238 * @member CKEDITOR.config
239 */
240CKEDITOR.config.format_h3 = { element: 'h3' };
241
242/**
243 * The style definition to be used to apply the `Heading 4` format.
244 *
245 * Read more in the [documentation](#!/guide/dev_format)
246 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
247 *
248 * config.format_h4 = { element: 'h4', attributes: { 'class': 'contentTitle4' } };
249 *
250 * @cfg {Object} [format_h4={ element: 'h4' }]
251 * @member CKEDITOR.config
252 */
253CKEDITOR.config.format_h4 = { element: 'h4' };
254
255/**
256 * The style definition to be used to apply the `Heading 5` format.
257 *
258 * Read more in the [documentation](#!/guide/dev_format)
259 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
260 *
261 * config.format_h5 = { element: 'h5', attributes: { 'class': 'contentTitle5' } };
262 *
263 * @cfg {Object} [format_h5={ element: 'h5' }]
264 * @member CKEDITOR.config
265 */
266CKEDITOR.config.format_h5 = { element: 'h5' };
267
268/**
269 * The style definition to be used to apply the `Heading 6` format.
270 *
271 * Read more in the [documentation](#!/guide/dev_format)
272 * and see the [SDK sample](http://sdk.ckeditor.com/samples/format.html).
273 *
274 * config.format_h6 = { element: 'h6', attributes: { 'class': 'contentTitle6' } };
275 *
276 * @cfg {Object} [format_h6={ element: 'h6' }]
277 * @member CKEDITOR.config
278 */
279CKEDITOR.config.format_h6 = { element: 'h6' };
diff --git a/sources/plugins/horizontalrule/icons/hidpi/horizontalrule.png b/sources/plugins/horizontalrule/icons/hidpi/horizontalrule.png
new file mode 100644
index 0000000..ad97e09
--- /dev/null
+++ b/sources/plugins/horizontalrule/icons/hidpi/horizontalrule.png
Binary files differ
diff --git a/sources/plugins/horizontalrule/icons/horizontalrule.png b/sources/plugins/horizontalrule/icons/horizontalrule.png
new file mode 100644
index 0000000..0592614
--- /dev/null
+++ b/sources/plugins/horizontalrule/icons/horizontalrule.png
Binary files differ
diff --git a/sources/plugins/horizontalrule/lang/af.js b/sources/plugins/horizontalrule/lang/af.js
new file mode 100644
index 0000000..9232187
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/af.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'af', {
6 toolbar: 'Horisontale lyn invoeg'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ar.js b/sources/plugins/horizontalrule/lang/ar.js
new file mode 100644
index 0000000..edf9101
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ar.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ar', {
6 toolbar: 'خط فاصل'
7} );
diff --git a/sources/plugins/horizontalrule/lang/az.js b/sources/plugins/horizontalrule/lang/az.js
new file mode 100644
index 0000000..2343630
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/az.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'az', {
6 toolbar: 'Sərhəd xətti yarat'
7} );
diff --git a/sources/plugins/horizontalrule/lang/bg.js b/sources/plugins/horizontalrule/lang/bg.js
new file mode 100644
index 0000000..b20914c
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/bg.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'bg', {
6 toolbar: 'Вмъкване на хоризонтална линия'
7} );
diff --git a/sources/plugins/horizontalrule/lang/bn.js b/sources/plugins/horizontalrule/lang/bn.js
new file mode 100644
index 0000000..d846125
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/bn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'bn', {
6 toolbar: 'অনুভূমিক লাইন যোগ করি'
7} );
diff --git a/sources/plugins/horizontalrule/lang/bs.js b/sources/plugins/horizontalrule/lang/bs.js
new file mode 100644
index 0000000..3917873
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/bs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'bs', {
6 toolbar: 'Ubaci horizontalnu liniju'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ca.js b/sources/plugins/horizontalrule/lang/ca.js
new file mode 100644
index 0000000..81d9457
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ca', {
6 toolbar: 'Insereix línia horitzontal'
7} );
diff --git a/sources/plugins/horizontalrule/lang/cs.js b/sources/plugins/horizontalrule/lang/cs.js
new file mode 100644
index 0000000..5178139
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/cs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'cs', {
6 toolbar: 'Vložit vodorovnou linku'
7} );
diff --git a/sources/plugins/horizontalrule/lang/cy.js b/sources/plugins/horizontalrule/lang/cy.js
new file mode 100644
index 0000000..df74af5
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/cy.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'cy', {
6 toolbar: 'Mewnosod Llinell Lorweddol'
7} );
diff --git a/sources/plugins/horizontalrule/lang/da.js b/sources/plugins/horizontalrule/lang/da.js
new file mode 100644
index 0000000..cd8cb2a
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/da.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'da', {
6 toolbar: 'Indsæt vandret streg'
7} );
diff --git a/sources/plugins/horizontalrule/lang/de-ch.js b/sources/plugins/horizontalrule/lang/de-ch.js
new file mode 100644
index 0000000..64230b5
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/de-ch.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'de-ch', {
6 toolbar: 'Horizontale Linie einfügen'
7} );
diff --git a/sources/plugins/horizontalrule/lang/de.js b/sources/plugins/horizontalrule/lang/de.js
new file mode 100644
index 0000000..a1705a6
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/de.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'de', {
6 toolbar: 'Horizontale Linie einfügen'
7} );
diff --git a/sources/plugins/horizontalrule/lang/el.js b/sources/plugins/horizontalrule/lang/el.js
new file mode 100644
index 0000000..d281f47
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/el.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'el', {
6 toolbar: 'Εισαγωγή Οριζόντιας Γραμμής'
7} );
diff --git a/sources/plugins/horizontalrule/lang/en-au.js b/sources/plugins/horizontalrule/lang/en-au.js
new file mode 100644
index 0000000..0548518
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/en-au.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'en-au', {
6 toolbar: 'Insert Horizontal Line'
7} );
diff --git a/sources/plugins/horizontalrule/lang/en-ca.js b/sources/plugins/horizontalrule/lang/en-ca.js
new file mode 100644
index 0000000..feab44d
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/en-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'en-ca', {
6 toolbar: 'Insert Horizontal Line'
7} );
diff --git a/sources/plugins/horizontalrule/lang/en-gb.js b/sources/plugins/horizontalrule/lang/en-gb.js
new file mode 100644
index 0000000..5cf987f
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/en-gb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'en-gb', {
6 toolbar: 'Insert Horizontal Line'
7} );
diff --git a/sources/plugins/horizontalrule/lang/en.js b/sources/plugins/horizontalrule/lang/en.js
new file mode 100644
index 0000000..6c750d1
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/en.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'en', {
6 toolbar: 'Insert Horizontal Line'
7} );
diff --git a/sources/plugins/horizontalrule/lang/eo.js b/sources/plugins/horizontalrule/lang/eo.js
new file mode 100644
index 0000000..f2ddd72
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/eo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'eo', {
6 toolbar: 'Enmeti Horizontalan Linion'
7} );
diff --git a/sources/plugins/horizontalrule/lang/es.js b/sources/plugins/horizontalrule/lang/es.js
new file mode 100644
index 0000000..ac42e14
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/es.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'es', {
6 toolbar: 'Insertar Línea Horizontal'
7} );
diff --git a/sources/plugins/horizontalrule/lang/et.js b/sources/plugins/horizontalrule/lang/et.js
new file mode 100644
index 0000000..156b1c1
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/et.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'et', {
6 toolbar: 'Horisontaaljoone sisestamine'
7} );
diff --git a/sources/plugins/horizontalrule/lang/eu.js b/sources/plugins/horizontalrule/lang/eu.js
new file mode 100644
index 0000000..7eeabb8
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/eu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'eu', {
6 toolbar: 'Txertatu marra horizontala'
7} );
diff --git a/sources/plugins/horizontalrule/lang/fa.js b/sources/plugins/horizontalrule/lang/fa.js
new file mode 100644
index 0000000..f18d1d0
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/fa.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'fa', {
6 toolbar: 'گنجاندن خط افقی'
7} );
diff --git a/sources/plugins/horizontalrule/lang/fi.js b/sources/plugins/horizontalrule/lang/fi.js
new file mode 100644
index 0000000..c18cd70
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/fi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'fi', {
6 toolbar: 'Lisää murtoviiva'
7} );
diff --git a/sources/plugins/horizontalrule/lang/fo.js b/sources/plugins/horizontalrule/lang/fo.js
new file mode 100644
index 0000000..d0d3bea
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/fo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'fo', {
6 toolbar: 'Ger vatnrætta linju'
7} );
diff --git a/sources/plugins/horizontalrule/lang/fr-ca.js b/sources/plugins/horizontalrule/lang/fr-ca.js
new file mode 100644
index 0000000..a232a14
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/fr-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'fr-ca', {
6 toolbar: 'Insérer un séparateur horizontale'
7} );
diff --git a/sources/plugins/horizontalrule/lang/fr.js b/sources/plugins/horizontalrule/lang/fr.js
new file mode 100644
index 0000000..c0c6322
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/fr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'fr', {
6 toolbar: 'Ligne horizontale'
7} );
diff --git a/sources/plugins/horizontalrule/lang/gl.js b/sources/plugins/horizontalrule/lang/gl.js
new file mode 100644
index 0000000..6215e71
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/gl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'gl', {
6 toolbar: 'Inserir unha liña horizontal'
7} );
diff --git a/sources/plugins/horizontalrule/lang/gu.js b/sources/plugins/horizontalrule/lang/gu.js
new file mode 100644
index 0000000..f6abc17
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/gu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'gu', {
6 toolbar: 'સમસ્તરીય રેખા ઇન્સર્ટ/દાખલ કરવી'
7} );
diff --git a/sources/plugins/horizontalrule/lang/he.js b/sources/plugins/horizontalrule/lang/he.js
new file mode 100644
index 0000000..56c4ebd
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/he.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'he', {
6 toolbar: 'הוספת קו אופקי'
7} );
diff --git a/sources/plugins/horizontalrule/lang/hi.js b/sources/plugins/horizontalrule/lang/hi.js
new file mode 100644
index 0000000..1d576c2
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/hi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'hi', {
6 toolbar: 'हॉरिज़ॉन्टल रेखा इन्सर्ट करें'
7} );
diff --git a/sources/plugins/horizontalrule/lang/hr.js b/sources/plugins/horizontalrule/lang/hr.js
new file mode 100644
index 0000000..53d80f3
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/hr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'hr', {
6 toolbar: 'Ubaci vodoravnu liniju'
7} );
diff --git a/sources/plugins/horizontalrule/lang/hu.js b/sources/plugins/horizontalrule/lang/hu.js
new file mode 100644
index 0000000..31fcbfc
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/hu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'hu', {
6 toolbar: 'Elválasztóvonal beillesztése'
7} );
diff --git a/sources/plugins/horizontalrule/lang/id.js b/sources/plugins/horizontalrule/lang/id.js
new file mode 100644
index 0000000..3d341ad
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/id.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'id', {
6 toolbar: 'Sisip Garis Horisontal'
7} );
diff --git a/sources/plugins/horizontalrule/lang/is.js b/sources/plugins/horizontalrule/lang/is.js
new file mode 100644
index 0000000..1515abc
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/is.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'is', {
6 toolbar: 'Lóðrétt lína'
7} );
diff --git a/sources/plugins/horizontalrule/lang/it.js b/sources/plugins/horizontalrule/lang/it.js
new file mode 100644
index 0000000..c2e23fb
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/it.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'it', {
6 toolbar: 'Inserisci riga orizzontale'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ja.js b/sources/plugins/horizontalrule/lang/ja.js
new file mode 100644
index 0000000..e174c32
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ja.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ja', {
6 toolbar: '水平線'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ka.js b/sources/plugins/horizontalrule/lang/ka.js
new file mode 100644
index 0000000..2c798c2
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ka.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ka', {
6 toolbar: 'ჰორიზონტალური ხაზის ჩასმა'
7} );
diff --git a/sources/plugins/horizontalrule/lang/km.js b/sources/plugins/horizontalrule/lang/km.js
new file mode 100644
index 0000000..8c8ab9f
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/km.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'km', {
6 toolbar: 'បន្ថែមបន្ទាត់ផ្តេក'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ko.js b/sources/plugins/horizontalrule/lang/ko.js
new file mode 100644
index 0000000..69df02c
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ko.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ko', {
6 toolbar: '가로 줄 삽입'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ku.js b/sources/plugins/horizontalrule/lang/ku.js
new file mode 100644
index 0000000..c8a0fa5
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ku.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ku', {
6 toolbar: 'دانانی هێلی ئاسۆیی'
7} );
diff --git a/sources/plugins/horizontalrule/lang/lt.js b/sources/plugins/horizontalrule/lang/lt.js
new file mode 100644
index 0000000..86cbdaf
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/lt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'lt', {
6 toolbar: 'Įterpti horizontalią liniją'
7} );
diff --git a/sources/plugins/horizontalrule/lang/lv.js b/sources/plugins/horizontalrule/lang/lv.js
new file mode 100644
index 0000000..a227a00
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/lv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'lv', {
6 toolbar: 'Ievietot horizontālu Atdalītājsvītru'
7} );
diff --git a/sources/plugins/horizontalrule/lang/mk.js b/sources/plugins/horizontalrule/lang/mk.js
new file mode 100644
index 0000000..51efe3d
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/mk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'mk', {
6 toolbar: 'Insert Horizontal Line' // MISSING
7} );
diff --git a/sources/plugins/horizontalrule/lang/mn.js b/sources/plugins/horizontalrule/lang/mn.js
new file mode 100644
index 0000000..bd0ba0f
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/mn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'mn', {
6 toolbar: 'Хөндлөн зураас оруулах'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ms.js b/sources/plugins/horizontalrule/lang/ms.js
new file mode 100644
index 0000000..fa22359
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ms.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ms', {
6 toolbar: 'Masukkan Garisan Membujur'
7} );
diff --git a/sources/plugins/horizontalrule/lang/nb.js b/sources/plugins/horizontalrule/lang/nb.js
new file mode 100644
index 0000000..7edefa5
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/nb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'nb', {
6 toolbar: 'Sett inn horisontal linje'
7} );
diff --git a/sources/plugins/horizontalrule/lang/nl.js b/sources/plugins/horizontalrule/lang/nl.js
new file mode 100644
index 0000000..47efd3f
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/nl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'nl', {
6 toolbar: 'Horizontale lijn invoegen'
7} );
diff --git a/sources/plugins/horizontalrule/lang/no.js b/sources/plugins/horizontalrule/lang/no.js
new file mode 100644
index 0000000..009fc4b
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/no.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'no', {
6 toolbar: 'Sett inn horisontal linje'
7} );
diff --git a/sources/plugins/horizontalrule/lang/oc.js b/sources/plugins/horizontalrule/lang/oc.js
new file mode 100644
index 0000000..42d1797
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/oc.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'oc', {
6 toolbar: 'Inserir una linha orizontala'
7} );
diff --git a/sources/plugins/horizontalrule/lang/pl.js b/sources/plugins/horizontalrule/lang/pl.js
new file mode 100644
index 0000000..0604f4d
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/pl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'pl', {
6 toolbar: 'Wstaw poziomą linię'
7} );
diff --git a/sources/plugins/horizontalrule/lang/pt-br.js b/sources/plugins/horizontalrule/lang/pt-br.js
new file mode 100644
index 0000000..038616b
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/pt-br.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'pt-br', {
6 toolbar: 'Inserir Linha Horizontal'
7} );
diff --git a/sources/plugins/horizontalrule/lang/pt.js b/sources/plugins/horizontalrule/lang/pt.js
new file mode 100644
index 0000000..c8d710d
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/pt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'pt', {
6 toolbar: 'Inserir linha horizontal'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ro.js b/sources/plugins/horizontalrule/lang/ro.js
new file mode 100644
index 0000000..4b8f9b8
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ro.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ro', {
6 toolbar: 'Inserează linie orizontală'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ru.js b/sources/plugins/horizontalrule/lang/ru.js
new file mode 100644
index 0000000..5424765
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ru.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ru', {
6 toolbar: 'Вставить горизонтальную линию'
7} );
diff --git a/sources/plugins/horizontalrule/lang/si.js b/sources/plugins/horizontalrule/lang/si.js
new file mode 100644
index 0000000..b0bb9b1
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/si.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'si', {
6 toolbar: 'තිරස් රේඛාවක් ඇතුලත් කරන්න'
7} );
diff --git a/sources/plugins/horizontalrule/lang/sk.js b/sources/plugins/horizontalrule/lang/sk.js
new file mode 100644
index 0000000..07bce6c
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/sk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'sk', {
6 toolbar: 'Vložiť vodorovnú čiaru'
7} );
diff --git a/sources/plugins/horizontalrule/lang/sl.js b/sources/plugins/horizontalrule/lang/sl.js
new file mode 100644
index 0000000..44e19ae
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/sl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'sl', {
6 toolbar: 'Vstavi vodoravno črto'
7} );
diff --git a/sources/plugins/horizontalrule/lang/sq.js b/sources/plugins/horizontalrule/lang/sq.js
new file mode 100644
index 0000000..9fa6a40
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/sq.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'sq', {
6 toolbar: 'Vendos Vijë Horizontale'
7} );
diff --git a/sources/plugins/horizontalrule/lang/sr-latn.js b/sources/plugins/horizontalrule/lang/sr-latn.js
new file mode 100644
index 0000000..eb16b98
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/sr-latn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'sr-latn', {
6 toolbar: 'Unesi horizontalnu liniju'
7} );
diff --git a/sources/plugins/horizontalrule/lang/sr.js b/sources/plugins/horizontalrule/lang/sr.js
new file mode 100644
index 0000000..a260b4a
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/sr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'sr', {
6 toolbar: 'Унеси хоризонталну линију'
7} );
diff --git a/sources/plugins/horizontalrule/lang/sv.js b/sources/plugins/horizontalrule/lang/sv.js
new file mode 100644
index 0000000..bf6280f
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/sv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'sv', {
6 toolbar: 'Infoga horisontal linje'
7} );
diff --git a/sources/plugins/horizontalrule/lang/th.js b/sources/plugins/horizontalrule/lang/th.js
new file mode 100644
index 0000000..164f496
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/th.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'th', {
6 toolbar: 'แทรกเส้นคั่นบรรทัด'
7} );
diff --git a/sources/plugins/horizontalrule/lang/tr.js b/sources/plugins/horizontalrule/lang/tr.js
new file mode 100644
index 0000000..aeb6fb8
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/tr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'tr', {
6 toolbar: 'Yatay Satır Ekle'
7} );
diff --git a/sources/plugins/horizontalrule/lang/tt.js b/sources/plugins/horizontalrule/lang/tt.js
new file mode 100644
index 0000000..411166d
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/tt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'tt', {
6 toolbar: 'Ятма сызык өстәү'
7} );
diff --git a/sources/plugins/horizontalrule/lang/ug.js b/sources/plugins/horizontalrule/lang/ug.js
new file mode 100644
index 0000000..92f2434
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/ug.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'ug', {
6 toolbar: 'توغرا سىزىق قىستۇر'
7} );
diff --git a/sources/plugins/horizontalrule/lang/uk.js b/sources/plugins/horizontalrule/lang/uk.js
new file mode 100644
index 0000000..d84f428
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/uk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'uk', {
6 toolbar: 'Горизонтальна лінія'
7} );
diff --git a/sources/plugins/horizontalrule/lang/vi.js b/sources/plugins/horizontalrule/lang/vi.js
new file mode 100644
index 0000000..339eb06
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/vi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'vi', {
6 toolbar: 'Chèn đường phân cách ngang'
7} );
diff --git a/sources/plugins/horizontalrule/lang/zh-cn.js b/sources/plugins/horizontalrule/lang/zh-cn.js
new file mode 100644
index 0000000..2dfdb50
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/zh-cn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'zh-cn', {
6 toolbar: '插入水平线'
7} );
diff --git a/sources/plugins/horizontalrule/lang/zh.js b/sources/plugins/horizontalrule/lang/zh.js
new file mode 100644
index 0000000..b2e4272
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/zh.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'horizontalrule', 'zh', {
6 toolbar: '插入水平線'
7} );
diff --git a/sources/plugins/horizontalrule/plugin.js b/sources/plugins/horizontalrule/plugin.js
new file mode 100644
index 0000000..6e52c31
--- /dev/null
+++ b/sources/plugins/horizontalrule/plugin.js
@@ -0,0 +1,43 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Horizontal Rule plugin.
8 */
9
10( function() {
11 var horizontalruleCmd = {
12 canUndo: false, // The undo snapshot will be handled by 'insertElement'.
13 exec: function( editor ) {
14 var hr = editor.document.createElement( 'hr' );
15 editor.insertElement( hr );
16 },
17
18 allowedContent: 'hr',
19 requiredContent: 'hr'
20 };
21
22 var pluginName = 'horizontalrule';
23
24 // Register a plugin named "horizontalrule".
25 CKEDITOR.plugins.add( pluginName, {
26 // jscs:disable maximumLineLength
27 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
28 // jscs:enable maximumLineLength
29 icons: 'horizontalrule', // %REMOVE_LINE_CORE%
30 hidpi: true, // %REMOVE_LINE_CORE%
31 init: function( editor ) {
32 if ( editor.blockless )
33 return;
34
35 editor.addCommand( pluginName, horizontalruleCmd );
36 editor.ui.addButton && editor.ui.addButton( 'HorizontalRule', {
37 label: editor.lang.horizontalrule.toolbar,
38 command: pluginName,
39 toolbar: 'insert,40'
40 } );
41 }
42 } );
43} )();
diff --git a/sources/plugins/htmlwriter/plugin.js b/sources/plugins/htmlwriter/plugin.js
new file mode 100644
index 0000000..b6d2716
--- /dev/null
+++ b/sources/plugins/htmlwriter/plugin.js
@@ -0,0 +1,360 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'htmlwriter', {
7 init: function( editor ) {
8 var writer = new CKEDITOR.htmlWriter();
9
10 writer.forceSimpleAmpersand = editor.config.forceSimpleAmpersand;
11 writer.indentationChars = editor.config.dataIndentationChars || '\t';
12
13 // Overwrite default basicWriter initialized in hmtlDataProcessor constructor.
14 editor.dataProcessor.writer = writer;
15 }
16} );
17
18/**
19 * The class used to write HTML data.
20 *
21 * var writer = new CKEDITOR.htmlWriter();
22 * writer.openTag( 'p' );
23 * writer.attribute( 'class', 'MyClass' );
24 * writer.openTagClose( 'p' );
25 * writer.text( 'Hello' );
26 * writer.closeTag( 'p' );
27 * alert( writer.getHtml() ); // '<p class="MyClass">Hello</p>'
28 *
29 * @class
30 * @extends CKEDITOR.htmlParser.basicWriter
31 */
32CKEDITOR.htmlWriter = CKEDITOR.tools.createClass( {
33 base: CKEDITOR.htmlParser.basicWriter,
34
35 /**
36 * Creates an `htmlWriter` class instance.
37 *
38 * @constructor
39 */
40 $: function() {
41 // Call the base contructor.
42 this.base();
43
44 /**
45 * The characters to be used for each indentation step.
46 *
47 * // Use tab for indentation.
48 * editorInstance.dataProcessor.writer.indentationChars = '\t';
49 */
50 this.indentationChars = '\t';
51
52 /**
53 * The characters to be used to close "self-closing" elements, like `<br>` or `<img>`.
54 *
55 * // Use HTML4 notation for self-closing elements.
56 * editorInstance.dataProcessor.writer.selfClosingEnd = '>';
57 */
58 this.selfClosingEnd = ' />';
59
60 /**
61 * The characters to be used for line breaks.
62 *
63 * // Use CRLF for line breaks.
64 * editorInstance.dataProcessor.writer.lineBreakChars = '\r\n';
65 */
66 this.lineBreakChars = '\n';
67
68 this.sortAttributes = 1;
69
70 this._.indent = 0;
71 this._.indentation = '';
72 // Indicate preformatted block context status. (#5789)
73 this._.inPre = 0;
74 this._.rules = {};
75
76 var dtd = CKEDITOR.dtd;
77
78 for ( var e in CKEDITOR.tools.extend( {}, dtd.$nonBodyContent, dtd.$block, dtd.$listItem, dtd.$tableContent ) ) {
79 this.setRules( e, {
80 indent: !dtd[ e ][ '#' ],
81 breakBeforeOpen: 1,
82 breakBeforeClose: !dtd[ e ][ '#' ],
83 breakAfterClose: 1,
84 needsSpace: ( e in dtd.$block ) && !( e in { li: 1, dt: 1, dd: 1 } )
85 } );
86 }
87
88 this.setRules( 'br', { breakAfterOpen: 1 } );
89
90 this.setRules( 'title', {
91 indent: 0,
92 breakAfterOpen: 0
93 } );
94
95 this.setRules( 'style', {
96 indent: 0,
97 breakBeforeClose: 1
98 } );
99
100 this.setRules( 'pre', {
101 breakAfterOpen: 1, // Keep line break after the opening tag
102 indent: 0 // Disable indentation on <pre>.
103 } );
104 },
105
106 proto: {
107 /**
108 * Writes the tag opening part for an opener tag.
109 *
110 * // Writes '<p'.
111 * writer.openTag( 'p', { class : 'MyClass', id : 'MyId' } );
112 *
113 * @param {String} tagName The element name for this tag.
114 * @param {Object} attributes The attributes defined for this tag. The
115 * attributes could be used to inspect the tag.
116 */
117 openTag: function( tagName ) {
118 var rules = this._.rules[ tagName ];
119
120 if ( this._.afterCloser && rules && rules.needsSpace && this._.needsSpace )
121 this._.output.push( '\n' );
122
123 if ( this._.indent )
124 this.indentation();
125 // Do not break if indenting.
126 else if ( rules && rules.breakBeforeOpen ) {
127 this.lineBreak();
128 this.indentation();
129 }
130
131 this._.output.push( '<', tagName );
132
133 this._.afterCloser = 0;
134 },
135
136 /**
137 * Writes the tag closing part for an opener tag.
138 *
139 * // Writes '>'.
140 * writer.openTagClose( 'p', false );
141 *
142 * // Writes ' />'.
143 * writer.openTagClose( 'br', true );
144 *
145 * @param {String} tagName The element name for this tag.
146 * @param {Boolean} isSelfClose Indicates that this is a self-closing tag,
147 * like `<br>` or `<img>`.
148 */
149 openTagClose: function( tagName, isSelfClose ) {
150 var rules = this._.rules[ tagName ];
151
152 if ( isSelfClose ) {
153 this._.output.push( this.selfClosingEnd );
154
155 if ( rules && rules.breakAfterClose )
156 this._.needsSpace = rules.needsSpace;
157 } else {
158 this._.output.push( '>' );
159
160 if ( rules && rules.indent )
161 this._.indentation += this.indentationChars;
162 }
163
164 if ( rules && rules.breakAfterOpen )
165 this.lineBreak();
166 tagName == 'pre' && ( this._.inPre = 1 );
167 },
168
169 /**
170 * Writes an attribute. This function should be called after opening the
171 * tag with {@link #openTagClose}.
172 *
173 * // Writes ' class="MyClass"'.
174 * writer.attribute( 'class', 'MyClass' );
175 *
176 * @param {String} attName The attribute name.
177 * @param {String} attValue The attribute value.
178 */
179 attribute: function( attName, attValue ) {
180
181 if ( typeof attValue == 'string' ) {
182 this.forceSimpleAmpersand && ( attValue = attValue.replace( /&amp;/g, '&' ) );
183 // Browsers don't always escape special character in attribute values. (#4683, #4719).
184 attValue = CKEDITOR.tools.htmlEncodeAttr( attValue );
185 }
186
187 this._.output.push( ' ', attName, '="', attValue, '"' );
188 },
189
190 /**
191 * Writes a closer tag.
192 *
193 * // Writes '</p>'.
194 * writer.closeTag( 'p' );
195 *
196 * @param {String} tagName The element name for this tag.
197 */
198 closeTag: function( tagName ) {
199 var rules = this._.rules[ tagName ];
200
201 if ( rules && rules.indent )
202 this._.indentation = this._.indentation.substr( this.indentationChars.length );
203
204 if ( this._.indent )
205 this.indentation();
206 // Do not break if indenting.
207 else if ( rules && rules.breakBeforeClose ) {
208 this.lineBreak();
209 this.indentation();
210 }
211
212 this._.output.push( '</', tagName, '>' );
213 tagName == 'pre' && ( this._.inPre = 0 );
214
215 if ( rules && rules.breakAfterClose ) {
216 this.lineBreak();
217 this._.needsSpace = rules.needsSpace;
218 }
219
220 this._.afterCloser = 1;
221 },
222
223 /**
224 * Writes text.
225 *
226 * // Writes 'Hello Word'.
227 * writer.text( 'Hello Word' );
228 *
229 * @param {String} text The text value
230 */
231 text: function( text ) {
232 if ( this._.indent ) {
233 this.indentation();
234 !this._.inPre && ( text = CKEDITOR.tools.ltrim( text ) );
235 }
236
237 this._.output.push( text );
238 },
239
240 /**
241 * Writes a comment.
242 *
243 * // Writes "<!-- My comment -->".
244 * writer.comment( ' My comment ' );
245 *
246 * @param {String} comment The comment text.
247 */
248 comment: function( comment ) {
249 if ( this._.indent )
250 this.indentation();
251
252 this._.output.push( '<!--', comment, '-->' );
253 },
254
255 /**
256 * Writes a line break. It uses the {@link #lineBreakChars} property for it.
257 *
258 * // Writes '\n' (e.g.).
259 * writer.lineBreak();
260 */
261 lineBreak: function() {
262 if ( !this._.inPre && this._.output.length > 0 )
263 this._.output.push( this.lineBreakChars );
264 this._.indent = 1;
265 },
266
267 /**
268 * Writes the current indentation character. It uses the {@link #indentationChars}
269 * property, repeating it for the current indentation steps.
270 *
271 * // Writes '\t' (e.g.).
272 * writer.indentation();
273 */
274 indentation: function() {
275 if ( !this._.inPre && this._.indentation )
276 this._.output.push( this._.indentation );
277 this._.indent = 0;
278 },
279
280 /**
281 * Empties the current output buffer. It also brings back the default
282 * values of the writer flags.
283 *
284 * writer.reset();
285 */
286 reset: function() {
287 this._.output = [];
288 this._.indent = 0;
289 this._.indentation = '';
290 this._.afterCloser = 0;
291 this._.inPre = 0;
292 this._.needsSpace = 0;
293 },
294
295 /**
296 * Sets formatting rules for a given element. Possible rules are:
297 *
298 * * `indent` &ndash; indent the element content.
299 * * `breakBeforeOpen` &ndash; break line before the opener tag for this element.
300 * * `breakAfterOpen` &ndash; break line after the opener tag for this element.
301 * * `breakBeforeClose` &ndash; break line before the closer tag for this element.
302 * * `breakAfterClose` &ndash; break line after the closer tag for this element.
303 *
304 * All rules default to `false`. Each function call overrides rules that are
305 * already present, leaving the undefined ones untouched.
306 *
307 * By default, all elements available in the {@link CKEDITOR.dtd#$block},
308 * {@link CKEDITOR.dtd#$listItem}, and {@link CKEDITOR.dtd#$tableContent}
309 * lists have all the above rules set to `true`. Additionaly, the `<br>`
310 * element has the `breakAfterOpen` rule set to `true`.
311 *
312 * // Break line before and after "img" tags.
313 * writer.setRules( 'img', {
314 * breakBeforeOpen: true
315 * breakAfterOpen: true
316 * } );
317 *
318 * // Reset the rules for the "h1" tag.
319 * writer.setRules( 'h1', {} );
320 *
321 * @param {String} tagName The name of the element for which the rules are set.
322 * @param {Object} rules An object containing the element rules.
323 */
324 setRules: function( tagName, rules ) {
325 var currentRules = this._.rules[ tagName ];
326
327 if ( currentRules )
328 CKEDITOR.tools.extend( currentRules, rules, true );
329 else
330 this._.rules[ tagName ] = rules;
331 }
332 }
333} );
334
335/**
336 * Whether to force using `'&'` instead of `'&amp;'` in element attributes
337 * values. It is not recommended to change this setting for compliance with the
338 * W3C XHTML 1.0 standards ([C.12, XHTML 1.0](http://www.w3.org/TR/xhtml1/#C_12)).
339 *
340 * // Use `'&'` instead of `'&amp;'`
341 * CKEDITOR.config.forceSimpleAmpersand = true;
342 *
343 * @cfg {Boolean} [forceSimpleAmpersand=false]
344 * @member CKEDITOR.config
345 */
346
347/**
348 * The characters to be used for indenting HTML output produced by the editor.
349 * Using characters different from `' '` (space) and `'\t'` (tab) is not recommended
350 * as it will mess the code.
351 *
352 * // No indentation.
353 * CKEDITOR.config.dataIndentationChars = '';
354 *
355 * // Use two spaces for indentation.
356 * CKEDITOR.config.dataIndentationChars = ' ';
357 *
358 * @cfg {String} [dataIndentationChars='\t']
359 * @member CKEDITOR.config
360 */
diff --git a/sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.fla b/sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.fla
new file mode 100644
index 0000000..27e68cc
--- /dev/null
+++ b/sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.fla
Binary files differ
diff --git a/sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.swf b/sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.swf
new file mode 100644
index 0000000..dbe17b6
--- /dev/null
+++ b/sources/plugins/htmlwriter/samples/assets/outputforflash/outputforflash.swf
Binary files differ
diff --git a/sources/plugins/htmlwriter/samples/assets/outputforflash/swfobject.js b/sources/plugins/htmlwriter/samples/assets/outputforflash/swfobject.js
new file mode 100644
index 0000000..90cdcc9
--- /dev/null
+++ b/sources/plugins/htmlwriter/samples/assets/outputforflash/swfobject.js
@@ -0,0 +1,5 @@
1
2/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
3 is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
4*/
5var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
diff --git a/sources/plugins/htmlwriter/samples/outputforflash.html b/sources/plugins/htmlwriter/samples/outputforflash.html
new file mode 100644
index 0000000..f72616d
--- /dev/null
+++ b/sources/plugins/htmlwriter/samples/outputforflash.html
@@ -0,0 +1,283 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Output for Flash &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <script src="../../../samples/old/sample.js"></script>
12 <script src="assets/outputforflash/swfobject.js"></script>
13 <link href="../../../samples/old/sample.css" rel="stylesheet">
14 <meta name="ckeditor-sample-required-plugins" content="sourcearea">
15 <meta name="ckeditor-sample-name" content="Output for Flash">
16 <meta name="ckeditor-sample-group" content="Advanced Samples">
17 <meta name="ckeditor-sample-description" content="Configuring CKEditor to produce HTML code that can be used with Adobe Flash.">
18 <style>
19
20 .alert
21 {
22 background: #ffa84c;
23 padding: 10px 15px;
24 font-weight: bold;
25 display: block;
26 margin-bottom: 20px;
27 }
28
29 </style>
30</head>
31<body>
32 <h1 class="samples">
33 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Producing Flash Compliant HTML Output
34 </h1>
35 <div class="warning deprecated">
36 This sample is not maintained anymore. Check out the <a href="http://sdk.ckeditor.com/">brand new samples in CKEditor SDK</a>.
37 </div>
38 <div class="description">
39 <p>
40 This sample shows how to configure CKEditor to output
41 HTML code that can be used with
42 <a class="samples" href="http://www.adobe.com/livedocs/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00000922.html">
43 Adobe Flash</a>.
44 The code will contain a subset of standard HTML elements like <code>&lt;b&gt;</code>,
45 <code>&lt;i&gt;</code>, and <code>&lt;p&gt;</code> as well as HTML attributes.
46 </p>
47 <p>
48 To add a CKEditor instance outputting Flash compliant HTML code, load the editor using a standard
49 JavaScript call, and define CKEditor features to use HTML elements and attributes.
50 </p>
51 <p>
52 For details on how to create this setup check the source code of this sample page.
53 </p>
54 </div>
55 <p>
56 To see how it works, create some content in the editing area of CKEditor on the left
57 and send it to the Flash object on the right side of the page by using the
58 <strong>Send to Flash</strong> button.
59 </p>
60 <table style="width: 100%; border-spacing: 0; border-collapse:collapse;">
61 <tr>
62 <td style="width: 100%">
63 <textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;&lt;b&gt;&lt;font size=&quot;18&quot; style=&quot;font-size:18px;&quot;&gt;Flash and HTML&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;It is possible to have &lt;a href=&quot;http://ckeditor.com&quot;&gt;CKEditor&lt;/a&gt; creating content that will be later loaded inside &lt;b&gt;Flash&lt;/b&gt; objects and animations.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Flash has a few limitations when dealing with HTML:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It has limited support on tags.&lt;/li&gt;&lt;li&gt;There is no margin between block elements, like paragraphs.&lt;/li&gt;&lt;/ul&gt;</textarea>
64 <script>
65
66 if ( document.location.protocol == 'file:' )
67 alert( 'Warning: This samples does not work when loaded from local filesystem' +
68 'due to security restrictions implemented in Flash.' +
69 '\n\nPlease load the sample from a web server instead.' );
70
71 var editor = CKEDITOR.replace( 'editor1', {
72 /*
73 * Ensure that htmlwriter plugin, which is required for this sample, is loaded.
74 */
75 extraPlugins: 'htmlwriter',
76
77 height: 290,
78 width: '100%',
79 toolbar: [
80 [ 'Source', '-', 'Bold', 'Italic', 'Underline', '-', 'BulletedList', '-', 'Link', 'Unlink' ],
81 [ 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ],
82 '/',
83 [ 'Font', 'FontSize' ],
84 [ 'TextColor', '-', 'About' ]
85 ],
86
87 /*
88 * Style sheet for the contents
89 */
90 contentsCss: 'body {color:#000; background-color#FFF; font-family: Arial; font-size:80%;} p, ol, ul {margin-top: 0px; margin-bottom: 0px;}',
91
92 /*
93 * Quirks doctype
94 */
95 docType: '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',
96
97 /*
98 * Core styles.
99 */
100 coreStyles_bold: { element: 'b' },
101 coreStyles_italic: { element: 'i' },
102 coreStyles_underline: { element: 'u' },
103
104 /*
105 * Font face.
106 */
107
108 // Define the way font elements will be applied to the document. The "font"
109 // element will be used.
110 font_style: {
111 element: 'font',
112 attributes: { 'face': '#(family)' }
113 },
114
115 /*
116 * Font sizes.
117 */
118
119 // The CSS part of the font sizes isn't used by Flash, it is there to get the
120 // font rendered correctly in CKEditor.
121 fontSize_sizes: '8px/8;9px/9;10px/10;11px/11;12px/12;14px/14;16px/16;18px/18;20px/20;22px/22;24px/24;26px/26;28px/28;36px/36;48px/48;72px/72',
122 fontSize_style: {
123 element: 'font',
124 attributes: { 'size': '#(size)' },
125 styles: { 'font-size': '#(size)px' }
126 } ,
127
128 /*
129 * Font colors.
130 */
131 colorButton_enableMore: true,
132
133 colorButton_foreStyle: {
134 element: 'font',
135 attributes: { 'color': '#(color)' }
136 },
137
138 colorButton_backStyle: {
139 element: 'font',
140 styles: { 'background-color': '#(color)' }
141 },
142
143 on: { 'instanceReady': configureFlashOutput }
144 });
145
146 /*
147 * Adjust the behavior of the dataProcessor to match the
148 * requirements of Flash
149 */
150 function configureFlashOutput( ev ) {
151 var editor = ev.editor,
152 dataProcessor = editor.dataProcessor,
153 htmlFilter = dataProcessor && dataProcessor.htmlFilter;
154
155 // Out self closing tags the HTML4 way, like <br>.
156 dataProcessor.writer.selfClosingEnd = '>';
157
158 // Make output formatting match Flash expectations
159 var dtd = CKEDITOR.dtd;
160 for ( var e in CKEDITOR.tools.extend( {}, dtd.$nonBodyContent, dtd.$block, dtd.$listItem, dtd.$tableContent ) ) {
161 dataProcessor.writer.setRules( e, {
162 indent: false,
163 breakBeforeOpen: false,
164 breakAfterOpen: false,
165 breakBeforeClose: false,
166 breakAfterClose: false
167 });
168 }
169 dataProcessor.writer.setRules( 'br', {
170 indent: false,
171 breakBeforeOpen: false,
172 breakAfterOpen: false,
173 breakBeforeClose: false,
174 breakAfterClose: false
175 });
176
177 // Output properties as attributes, not styles.
178 htmlFilter.addRules( {
179 elements: {
180 $: function( element ) {
181 var style, match, width, height, align;
182
183 // Output dimensions of images as width and height
184 if ( element.name == 'img' ) {
185 style = element.attributes.style;
186
187 if ( style ) {
188 // Get the width from the style.
189 match = ( /(?:^|\s)width\s*:\s*(\d+)px/i ).exec( style );
190 width = match && match[1];
191
192 // Get the height from the style.
193 match = ( /(?:^|\s)height\s*:\s*(\d+)px/i ).exec( style );
194 height = match && match[1];
195
196 if ( width ) {
197 element.attributes.style = element.attributes.style.replace( /(?:^|\s)width\s*:\s*(\d+)px;?/i , '' );
198 element.attributes.width = width;
199 }
200
201 if ( height ) {
202 element.attributes.style = element.attributes.style.replace( /(?:^|\s)height\s*:\s*(\d+)px;?/i , '' );
203 element.attributes.height = height;
204 }
205 }
206 }
207
208 // Output alignment of paragraphs using align
209 if ( element.name == 'p' ) {
210 style = element.attributes.style;
211
212 if ( style ) {
213 // Get the align from the style.
214 match = ( /(?:^|\s)text-align\s*:\s*(\w*);?/i ).exec( style );
215 align = match && match[1];
216
217 if ( align ) {
218 element.attributes.style = element.attributes.style.replace( /(?:^|\s)text-align\s*:\s*(\w*);?/i , '' );
219 element.attributes.align = align;
220 }
221 }
222 }
223
224 if ( element.attributes.style === '' )
225 delete element.attributes.style;
226
227 return element;
228 }
229 }
230 });
231 }
232
233 function sendToFlash() {
234 var html = CKEDITOR.instances.editor1.getData() ;
235
236 // Quick fix for link color.
237 html = html.replace( /<a /g, '<font color="#0000FF"><u><a ' )
238 html = html.replace( /<\/a>/g, '</a></u></font>' )
239
240 var flash = document.getElementById( 'ckFlashContainer' ) ;
241 flash.setData( html ) ;
242 }
243
244 CKEDITOR.domReady( function() {
245 if ( !swfobject.hasFlashPlayerVersion( '8' ) ) {
246 CKEDITOR.dom.element.createFromHtml( '<span class="alert">' +
247 'At least Adobe Flash Player 8 is required to run this sample. ' +
248 'You can download it from <a href="http://get.adobe.com/flashplayer">Adobe\'s website</a>.' +
249 '</span>' ).insertBefore( editor.element );
250 }
251
252 swfobject.embedSWF(
253 'assets/outputforflash/outputforflash.swf',
254 'ckFlashContainer',
255 '550',
256 '400',
257 '8',
258 { wmode: 'transparent' }
259 );
260 });
261
262 </script>
263 <p>
264 <input type="button" value="Send to Flash" onclick="sendToFlash();">
265 </p>
266 </td>
267 <td style="vertical-align: top; padding-left: 20px">
268 <div id="ckFlashContainer"></div>
269 </td>
270 </tr>
271 </table>
272 <div id="footer">
273 <hr>
274 <p>
275 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
276 </p>
277 <p id="copy">
278 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
279 Knabben. All rights reserved.
280 </p>
281 </div>
282</body>
283</html>
diff --git a/sources/plugins/htmlwriter/samples/outputhtml.html b/sources/plugins/htmlwriter/samples/outputhtml.html
new file mode 100644
index 0000000..a433025
--- /dev/null
+++ b/sources/plugins/htmlwriter/samples/outputhtml.html
@@ -0,0 +1,224 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>HTML Compliant Output &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <script src="../../../samples/old/sample.js"></script>
12 <link href="../../../samples/old/sample.css" rel="stylesheet">
13 <meta name="ckeditor-sample-required-plugins" content="sourcearea">
14 <meta name="ckeditor-sample-name" content="Output HTML">
15 <meta name="ckeditor-sample-group" content="Advanced Samples">
16 <meta name="ckeditor-sample-description" content="Configuring CKEditor to produce legacy HTML 4 code.">
17</head>
18<body>
19 <h1 class="samples">
20 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Producing HTML Compliant Output
21 </h1>
22 <div class="warning deprecated">
23 This sample is not maintained anymore. Check out the <a href="http://sdk.ckeditor.com/">brand new samples in CKEditor SDK</a>.
24 </div>
25 <div class="description">
26 <p>
27 This sample shows how to configure CKEditor to output valid
28 <a class="samples" href="http://www.w3.org/TR/html401/">HTML 4.01</a> code.
29 Traditional HTML elements like <code>&lt;b&gt;</code>,
30 <code>&lt;i&gt;</code>, and <code>&lt;font&gt;</code> are used in place of
31 <code>&lt;strong&gt;</code>, <code>&lt;em&gt;</code>, and CSS styles.
32 </p>
33 <p>
34 To add a CKEditor instance outputting legacy HTML 4.01 code, load the editor using a standard
35 JavaScript call, and define CKEditor features to use the HTML compliant elements and attributes.
36 </p>
37 <p>
38 A snippet of the configuration code can be seen below; check the source of this page for
39 full definition:
40 </p>
41<pre class="samples">
42CKEDITOR.replace( '<em>textarea_id</em>', {
43 coreStyles_bold: { element: 'b' },
44 coreStyles_italic: { element: 'i' },
45
46 fontSize_style: {
47 element: 'font',
48 attributes: { 'size': '#(size)' }
49 }
50
51 ...
52});</pre>
53 </div>
54 <form action="../../../samples/sample_posteddata.php" method="post">
55 <p>
56 <label for="editor1">
57 Editor 1:
58 </label>
59 <textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;This is some &lt;b&gt;sample text&lt;/b&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
60 <script>
61
62 CKEDITOR.replace( 'editor1', {
63 /*
64 * Ensure that htmlwriter plugin, which is required for this sample, is loaded.
65 */
66 extraPlugins: 'htmlwriter',
67
68 /*
69 * Style sheet for the contents
70 */
71 contentsCss: 'body {color:#000; background-color#:FFF;}',
72
73 /*
74 * Simple HTML5 doctype
75 */
76 docType: '<!DOCTYPE HTML>',
77
78 /*
79 * Allowed content rules which beside limiting allowed HTML
80 * will also take care of transforming styles to attributes
81 * (currently only for img - see transformation rules defined below).
82 *
83 * Read more: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
84 */
85 allowedContent:
86 'h1 h2 h3 p pre[align]; ' +
87 'blockquote code kbd samp var del ins cite q b i u strike ul ol li hr table tbody tr td th caption; ' +
88 'img[!src,alt,align,width,height]; font[!face]; font[!family]; font[!color]; font[!size]; font{!background-color}; a[!href]; a[!name]',
89
90 /*
91 * Core styles.
92 */
93 coreStyles_bold: { element: 'b' },
94 coreStyles_italic: { element: 'i' },
95 coreStyles_underline: { element: 'u' },
96 coreStyles_strike: { element: 'strike' },
97
98 /*
99 * Font face.
100 */
101
102 // Define the way font elements will be applied to the document.
103 // The "font" element will be used.
104 font_style: {
105 element: 'font',
106 attributes: { 'face': '#(family)' }
107 },
108
109 /*
110 * Font sizes.
111 */
112 fontSize_sizes: 'xx-small/1;x-small/2;small/3;medium/4;large/5;x-large/6;xx-large/7',
113 fontSize_style: {
114 element: 'font',
115 attributes: { 'size': '#(size)' }
116 },
117
118 /*
119 * Font colors.
120 */
121
122 colorButton_foreStyle: {
123 element: 'font',
124 attributes: { 'color': '#(color)' }
125 },
126
127 colorButton_backStyle: {
128 element: 'font',
129 styles: { 'background-color': '#(color)' }
130 },
131
132 /*
133 * Styles combo.
134 */
135 stylesSet: [
136 { name: 'Computer Code', element: 'code' },
137 { name: 'Keyboard Phrase', element: 'kbd' },
138 { name: 'Sample Text', element: 'samp' },
139 { name: 'Variable', element: 'var' },
140 { name: 'Deleted Text', element: 'del' },
141 { name: 'Inserted Text', element: 'ins' },
142 { name: 'Cited Work', element: 'cite' },
143 { name: 'Inline Quotation', element: 'q' }
144 ],
145
146 on: {
147 pluginsLoaded: configureTransformations,
148 loaded: configureHtmlWriter
149 }
150 });
151
152 /*
153 * Add missing content transformations.
154 */
155 function configureTransformations( evt ) {
156 var editor = evt.editor;
157
158 editor.dataProcessor.htmlFilter.addRules( {
159 attributes: {
160 style: function( value, element ) {
161 // Return #RGB for background and border colors
162 return CKEDITOR.tools.convertRgbToHex( value );
163 }
164 }
165 } );
166
167 // Default automatic content transformations do not yet take care of
168 // align attributes on blocks, so we need to add our own transformation rules.
169 function alignToAttribute( element ) {
170 if ( element.styles[ 'text-align' ] ) {
171 element.attributes.align = element.styles[ 'text-align' ];
172 delete element.styles[ 'text-align' ];
173 }
174 }
175 editor.filter.addTransformations( [
176 [ { element: 'p', right: alignToAttribute } ],
177 [ { element: 'h1', right: alignToAttribute } ],
178 [ { element: 'h2', right: alignToAttribute } ],
179 [ { element: 'h3', right: alignToAttribute } ],
180 [ { element: 'pre', right: alignToAttribute } ]
181 ] );
182 }
183
184 /*
185 * Adjust the behavior of htmlWriter to make it output HTML like FCKeditor.
186 */
187 function configureHtmlWriter( evt ) {
188 var editor = evt.editor,
189 dataProcessor = editor.dataProcessor;
190
191 // Out self closing tags the HTML4 way, like <br>.
192 dataProcessor.writer.selfClosingEnd = '>';
193
194 // Make output formatting behave similar to FCKeditor.
195 var dtd = CKEDITOR.dtd;
196 for ( var e in CKEDITOR.tools.extend( {}, dtd.$nonBodyContent, dtd.$block, dtd.$listItem, dtd.$tableContent ) ) {
197 dataProcessor.writer.setRules( e, {
198 indent: true,
199 breakBeforeOpen: true,
200 breakAfterOpen: false,
201 breakBeforeClose: !dtd[ e ][ '#' ],
202 breakAfterClose: true
203 });
204 }
205 }
206
207 </script>
208 </p>
209 <p>
210 <input type="submit" value="Submit">
211 </p>
212 </form>
213 <div id="footer">
214 <hr>
215 <p>
216 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
217 </p>
218 <p id="copy">
219 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
220 Knabben. All rights reserved.
221 </p>
222 </div>
223</body>
224</html>
diff --git a/sources/plugins/iframe/dialogs/iframe.js b/sources/plugins/iframe/dialogs/iframe.js
new file mode 100644
index 0000000..bb39bdf
--- /dev/null
+++ b/sources/plugins/iframe/dialogs/iframe.js
@@ -0,0 +1,207 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 // Map 'true' and 'false' values to match W3C's specifications
8 // http://www.w3.org/TR/REC-html40/present/frames.html#h-16.5
9 var checkboxValues = {
10 scrolling: { 'true': 'yes', 'false': 'no' },
11 frameborder: { 'true': '1', 'false': '0' }
12 };
13
14 function loadValue( iframeNode ) {
15 var isCheckbox = this instanceof CKEDITOR.ui.dialog.checkbox;
16 if ( iframeNode.hasAttribute( this.id ) ) {
17 var value = iframeNode.getAttribute( this.id );
18 if ( isCheckbox )
19 this.setValue( checkboxValues[ this.id ][ 'true' ] == value.toLowerCase() );
20 else
21 this.setValue( value );
22 }
23 }
24
25 function commitValue( iframeNode ) {
26 var isRemove = this.getValue() === '',
27 isCheckbox = this instanceof CKEDITOR.ui.dialog.checkbox,
28 value = this.getValue();
29 if ( isRemove )
30 iframeNode.removeAttribute( this.att || this.id );
31 else if ( isCheckbox )
32 iframeNode.setAttribute( this.id, checkboxValues[ this.id ][ value ] );
33 else
34 iframeNode.setAttribute( this.att || this.id, value );
35 }
36
37 CKEDITOR.dialog.add( 'iframe', function( editor ) {
38 var iframeLang = editor.lang.iframe,
39 commonLang = editor.lang.common,
40 dialogadvtab = editor.plugins.dialogadvtab;
41 return {
42 title: iframeLang.title,
43 minWidth: 350,
44 minHeight: 260,
45 onShow: function() {
46 // Clear previously saved elements.
47 this.fakeImage = this.iframeNode = null;
48
49 var fakeImage = this.getSelectedElement();
50 if ( fakeImage && fakeImage.data( 'cke-real-element-type' ) && fakeImage.data( 'cke-real-element-type' ) == 'iframe' ) {
51 this.fakeImage = fakeImage;
52
53 var iframeNode = editor.restoreRealElement( fakeImage );
54 this.iframeNode = iframeNode;
55
56 this.setupContent( iframeNode );
57 }
58 },
59 onOk: function() {
60 var iframeNode;
61 if ( !this.fakeImage )
62 iframeNode = new CKEDITOR.dom.element( 'iframe' );
63 else
64 iframeNode = this.iframeNode;
65
66 // A subset of the specified attributes/styles
67 // should also be applied on the fake element to
68 // have better visual effect. (#5240)
69 var extraStyles = {},
70 extraAttributes = {};
71 this.commitContent( iframeNode, extraStyles, extraAttributes );
72
73 // Refresh the fake image.
74 var newFakeImage = editor.createFakeElement( iframeNode, 'cke_iframe', 'iframe', true );
75 newFakeImage.setAttributes( extraAttributes );
76 newFakeImage.setStyles( extraStyles );
77 if ( this.fakeImage ) {
78 newFakeImage.replace( this.fakeImage );
79 editor.getSelection().selectElement( newFakeImage );
80 } else {
81 editor.insertElement( newFakeImage );
82 }
83 },
84 contents: [ {
85 id: 'info',
86 label: commonLang.generalTab,
87 accessKey: 'I',
88 elements: [ {
89 type: 'vbox',
90 padding: 0,
91 children: [ {
92 id: 'src',
93 type: 'text',
94 label: commonLang.url,
95 required: true,
96 validate: CKEDITOR.dialog.validate.notEmpty( iframeLang.noUrl ),
97 setup: loadValue,
98 commit: commitValue
99 } ]
100 },
101 {
102 type: 'hbox',
103 children: [ {
104 id: 'width',
105 type: 'text',
106 requiredContent: 'iframe[width]',
107 style: 'width:100%',
108 labelLayout: 'vertical',
109 label: commonLang.width,
110 validate: CKEDITOR.dialog.validate.htmlLength( commonLang.invalidHtmlLength.replace( '%1', commonLang.width ) ),
111 setup: loadValue,
112 commit: commitValue
113 },
114 {
115 id: 'height',
116 type: 'text',
117 requiredContent: 'iframe[height]',
118 style: 'width:100%',
119 labelLayout: 'vertical',
120 label: commonLang.height,
121 validate: CKEDITOR.dialog.validate.htmlLength( commonLang.invalidHtmlLength.replace( '%1', commonLang.height ) ),
122 setup: loadValue,
123 commit: commitValue
124 },
125 {
126 id: 'align',
127 type: 'select',
128 requiredContent: 'iframe[align]',
129 'default': '',
130 items: [
131 [ commonLang.notSet, '' ],
132 [ commonLang.alignLeft, 'left' ],
133 [ commonLang.alignRight, 'right' ],
134 [ commonLang.alignTop, 'top' ],
135 [ commonLang.alignMiddle, 'middle' ],
136 [ commonLang.alignBottom, 'bottom' ]
137 ],
138 style: 'width:100%',
139 labelLayout: 'vertical',
140 label: commonLang.align,
141 setup: function( iframeNode, fakeImage ) {
142 loadValue.apply( this, arguments );
143 if ( fakeImage ) {
144 var fakeImageAlign = fakeImage.getAttribute( 'align' );
145 this.setValue( fakeImageAlign && fakeImageAlign.toLowerCase() || '' );
146 }
147 },
148 commit: function( iframeNode, extraStyles, extraAttributes ) {
149 commitValue.apply( this, arguments );
150 if ( this.getValue() )
151 extraAttributes.align = this.getValue();
152 }
153 } ]
154 },
155 {
156 type: 'hbox',
157 widths: [ '50%', '50%' ],
158 children: [ {
159 id: 'scrolling',
160 type: 'checkbox',
161 requiredContent: 'iframe[scrolling]',
162 label: iframeLang.scrolling,
163 setup: loadValue,
164 commit: commitValue
165 },
166 {
167 id: 'frameborder',
168 type: 'checkbox',
169 requiredContent: 'iframe[frameborder]',
170 label: iframeLang.border,
171 setup: loadValue,
172 commit: commitValue
173 } ]
174 },
175 {
176 type: 'hbox',
177 widths: [ '50%', '50%' ],
178 children: [ {
179 id: 'name',
180 type: 'text',
181 requiredContent: 'iframe[name]',
182 label: commonLang.name,
183 setup: loadValue,
184 commit: commitValue
185 },
186 {
187 id: 'title',
188 type: 'text',
189 requiredContent: 'iframe[title]',
190 label: commonLang.advisoryTitle,
191 setup: loadValue,
192 commit: commitValue
193 } ]
194 },
195 {
196 id: 'longdesc',
197 type: 'text',
198 requiredContent: 'iframe[longdesc]',
199 label: commonLang.longDescr,
200 setup: loadValue,
201 commit: commitValue
202 } ]
203 },
204 dialogadvtab && dialogadvtab.createAdvancedTab( editor, { id: 1, classes: 1, styles: 1 }, 'iframe' )
205 ] };
206 } );
207} )();
diff --git a/sources/plugins/iframe/icons/hidpi/iframe.png b/sources/plugins/iframe/icons/hidpi/iframe.png
new file mode 100644
index 0000000..d99d0f3
--- /dev/null
+++ b/sources/plugins/iframe/icons/hidpi/iframe.png
Binary files differ
diff --git a/sources/plugins/iframe/icons/iframe.png b/sources/plugins/iframe/icons/iframe.png
new file mode 100644
index 0000000..a2f5545
--- /dev/null
+++ b/sources/plugins/iframe/icons/iframe.png
Binary files differ
diff --git a/sources/plugins/iframe/images/placeholder.png b/sources/plugins/iframe/images/placeholder.png
new file mode 100644
index 0000000..4af0956
--- /dev/null
+++ b/sources/plugins/iframe/images/placeholder.png
Binary files differ
diff --git a/sources/plugins/iframe/lang/af.js b/sources/plugins/iframe/lang/af.js
new file mode 100644
index 0000000..9fa9387
--- /dev/null
+++ b/sources/plugins/iframe/lang/af.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'af', {
6 border: 'Wys rand van raam',
7 noUrl: 'Gee die iframe URL',
8 scrolling: 'Skuifbalke aan',
9 title: 'IFrame Eienskappe',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/ar.js b/sources/plugins/iframe/lang/ar.js
new file mode 100644
index 0000000..6388d75
--- /dev/null
+++ b/sources/plugins/iframe/lang/ar.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ar', {
6 border: 'إظهار حدود الإطار',
7 noUrl: 'فضلا أكتب رابط الـ iframe',
8 scrolling: 'تفعيل أشرطة الإنتقال',
9 title: 'خصائص iframe',
10 toolbar: 'iframe'
11} );
diff --git a/sources/plugins/iframe/lang/az.js b/sources/plugins/iframe/lang/az.js
new file mode 100644
index 0000000..e4b72e6
--- /dev/null
+++ b/sources/plugins/iframe/lang/az.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'az', {
6 border: 'Çərçivə sərhədlərini göstər',
7 noUrl: 'Çərçivənin ünvanı daxil edin',
8 scrolling: 'Şürüşdürmələri əlavə et',
9 title: 'İFRAME elementinin alətləri',
10 toolbar: 'İFRAME'
11} );
diff --git a/sources/plugins/iframe/lang/bg.js b/sources/plugins/iframe/lang/bg.js
new file mode 100644
index 0000000..4adb22c
--- /dev/null
+++ b/sources/plugins/iframe/lang/bg.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'bg', {
6 border: 'Показва рамка на карето',
7 noUrl: 'Моля въведете URL за iFrame',
8 scrolling: 'Вкл. скролбаровете',
9 title: 'IFrame настройки',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/bn.js b/sources/plugins/iframe/lang/bn.js
new file mode 100644
index 0000000..3479c1f
--- /dev/null
+++ b/sources/plugins/iframe/lang/bn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'bn', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/bs.js b/sources/plugins/iframe/lang/bs.js
new file mode 100644
index 0000000..51ca8a7
--- /dev/null
+++ b/sources/plugins/iframe/lang/bs.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'bs', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/ca.js b/sources/plugins/iframe/lang/ca.js
new file mode 100644
index 0000000..a0d7d92
--- /dev/null
+++ b/sources/plugins/iframe/lang/ca.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ca', {
6 border: 'Mostra la vora del marc',
7 noUrl: 'Si us plau, introdueixi la URL de l\'iframe',
8 scrolling: 'Activa les barres de desplaçament',
9 title: 'Propietats de l\'IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/cs.js b/sources/plugins/iframe/lang/cs.js
new file mode 100644
index 0000000..388fa61
--- /dev/null
+++ b/sources/plugins/iframe/lang/cs.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'cs', {
6 border: 'Zobrazit okraj',
7 noUrl: 'Zadejte prosím URL obsahu pro IFrame',
8 scrolling: 'Zapnout posuvníky',
9 title: 'Vlastnosti IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/cy.js b/sources/plugins/iframe/lang/cy.js
new file mode 100644
index 0000000..a23b2ff
--- /dev/null
+++ b/sources/plugins/iframe/lang/cy.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'cy', {
6 border: 'Dangos ymyl y ffrâm',
7 noUrl: 'Rhowch URL yr iframe',
8 scrolling: 'Galluogi bariau sgrolio',
9 title: 'Priodweddau IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/da.js b/sources/plugins/iframe/lang/da.js
new file mode 100644
index 0000000..88b4fab
--- /dev/null
+++ b/sources/plugins/iframe/lang/da.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'da', {
6 border: 'Vis kant på rammen',
7 noUrl: 'Venligst indsæt URL på iframen',
8 scrolling: 'Aktiver scrollbars',
9 title: 'Iframe egenskaber',
10 toolbar: 'Iframe'
11} );
diff --git a/sources/plugins/iframe/lang/de-ch.js b/sources/plugins/iframe/lang/de-ch.js
new file mode 100644
index 0000000..2a56ccf
--- /dev/null
+++ b/sources/plugins/iframe/lang/de-ch.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'de-ch', {
6 border: 'Rahmen anzeigen',
7 noUrl: 'Bitte geben Sie die IFrame-URL an',
8 scrolling: 'Rollbalken anzeigen',
9 title: 'IFrame-Eigenschaften',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/de.js b/sources/plugins/iframe/lang/de.js
new file mode 100644
index 0000000..7988dfa
--- /dev/null
+++ b/sources/plugins/iframe/lang/de.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'de', {
6 border: 'Rahmen anzeigen',
7 noUrl: 'Bitte geben Sie die IFrame-URL an',
8 scrolling: 'Rollbalken anzeigen',
9 title: 'IFrame-Eigenschaften',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/el.js b/sources/plugins/iframe/lang/el.js
new file mode 100644
index 0000000..5abdfb0
--- /dev/null
+++ b/sources/plugins/iframe/lang/el.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'el', {
6 border: 'Προβολή περιγράμματος πλαισίου',
7 noUrl: 'Παρακαλούμε εισάγεται το URL του iframe',
8 scrolling: 'Ενεργοποίηση μπαρών κύλισης',
9 title: 'Ιδιότητες IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/en-au.js b/sources/plugins/iframe/lang/en-au.js
new file mode 100644
index 0000000..59048db
--- /dev/null
+++ b/sources/plugins/iframe/lang/en-au.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'en-au', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/en-ca.js b/sources/plugins/iframe/lang/en-ca.js
new file mode 100644
index 0000000..401ff49
--- /dev/null
+++ b/sources/plugins/iframe/lang/en-ca.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'en-ca', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/en-gb.js b/sources/plugins/iframe/lang/en-gb.js
new file mode 100644
index 0000000..78d4000
--- /dev/null
+++ b/sources/plugins/iframe/lang/en-gb.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'en-gb', {
6 border: 'Show frame border',
7 noUrl: 'Please type the iframe URL',
8 scrolling: 'Enable scrollbars',
9 title: 'IFrame Properties',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/en.js b/sources/plugins/iframe/lang/en.js
new file mode 100644
index 0000000..1e224b9
--- /dev/null
+++ b/sources/plugins/iframe/lang/en.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'en', {
6 border: 'Show frame border',
7 noUrl: 'Please type the iframe URL',
8 scrolling: 'Enable scrollbars',
9 title: 'IFrame Properties',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/eo.js b/sources/plugins/iframe/lang/eo.js
new file mode 100644
index 0000000..eba244d
--- /dev/null
+++ b/sources/plugins/iframe/lang/eo.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'eo', {
6 border: 'Montri borderon de kadro (frame)',
7 noUrl: 'Bonvolu entajpi la retadreson de la ligilo al la enlinia kadro (IFrame)',
8 scrolling: 'Ebligi rulumskalon',
9 title: 'Atributoj de la enlinia kadro (IFrame)',
10 toolbar: 'Enlinia kadro (IFrame)'
11} );
diff --git a/sources/plugins/iframe/lang/es.js b/sources/plugins/iframe/lang/es.js
new file mode 100644
index 0000000..1cf5c29
--- /dev/null
+++ b/sources/plugins/iframe/lang/es.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'es', {
6 border: 'Mostrar borde del marco',
7 noUrl: 'Por favor, escriba la dirección del iframe',
8 scrolling: 'Activar barras de desplazamiento',
9 title: 'Propiedades de iframe',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/et.js b/sources/plugins/iframe/lang/et.js
new file mode 100644
index 0000000..aac467d
--- /dev/null
+++ b/sources/plugins/iframe/lang/et.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'et', {
6 border: 'Raami äärise näitamine',
7 noUrl: 'Vali iframe URLi liik',
8 scrolling: 'Kerimisribade lubamine',
9 title: 'IFrame omadused',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/eu.js b/sources/plugins/iframe/lang/eu.js
new file mode 100644
index 0000000..1f77367
--- /dev/null
+++ b/sources/plugins/iframe/lang/eu.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'eu', {
6 border: 'Erakutsi markoaren ertza',
7 noUrl: 'Idatzi iframe-aren URLa, mesedez.',
8 scrolling: 'Gaitu korritze-barrak',
9 title: 'IFrame-aren propietateak',
10 toolbar: 'IFrame-a'
11} );
diff --git a/sources/plugins/iframe/lang/fa.js b/sources/plugins/iframe/lang/fa.js
new file mode 100644
index 0000000..0c7a09f
--- /dev/null
+++ b/sources/plugins/iframe/lang/fa.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'fa', {
6 border: 'نمایش خطوط frame',
7 noUrl: 'لطفا مسیر URL iframe را درج کنید',
8 scrolling: 'نمایش خطکشها',
9 title: 'ویژگیهای IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/fi.js b/sources/plugins/iframe/lang/fi.js
new file mode 100644
index 0000000..0aa7f37
--- /dev/null
+++ b/sources/plugins/iframe/lang/fi.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'fi', {
6 border: 'Näytä kehyksen reunat',
7 noUrl: 'Anna IFrame-kehykselle lähdeosoite (src)',
8 scrolling: 'Näytä vierityspalkit',
9 title: 'IFrame-kehyksen ominaisuudet',
10 toolbar: 'IFrame-kehys'
11} );
diff --git a/sources/plugins/iframe/lang/fo.js b/sources/plugins/iframe/lang/fo.js
new file mode 100644
index 0000000..05fdfe8
--- /dev/null
+++ b/sources/plugins/iframe/lang/fo.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'fo', {
6 border: 'Vís frame kant',
7 noUrl: 'Vinarliga skriva URL til iframe',
8 scrolling: 'Loyv scrollbars',
9 title: 'Møguleikar fyri IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/fr-ca.js b/sources/plugins/iframe/lang/fr-ca.js
new file mode 100644
index 0000000..cf7947e
--- /dev/null
+++ b/sources/plugins/iframe/lang/fr-ca.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'fr-ca', {
6 border: 'Afficher la bordure du cadre',
7 noUrl: 'Veuillez entre l\'URL du IFrame',
8 scrolling: 'Activer les barres de défilement',
9 title: 'Propriétés du IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/fr.js b/sources/plugins/iframe/lang/fr.js
new file mode 100644
index 0000000..34fc64e
--- /dev/null
+++ b/sources/plugins/iframe/lang/fr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'fr', {
6 border: 'Afficher la bordure du cadre',
7 noUrl: 'Veuillez entrer l\'URL du contenu du cadre',
8 scrolling: 'Activer les barres de défilement',
9 title: 'Propriétés du cadre de contenu incorporé',
10 toolbar: 'Cadre de contenu incorporé'
11} );
diff --git a/sources/plugins/iframe/lang/gl.js b/sources/plugins/iframe/lang/gl.js
new file mode 100644
index 0000000..449e28d
--- /dev/null
+++ b/sources/plugins/iframe/lang/gl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'gl', {
6 border: 'Amosar o bordo do marco',
7 noUrl: 'Escriba o enderezo do iframe',
8 scrolling: 'Activar as barras de desprazamento',
9 title: 'Propiedades do iFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/gu.js b/sources/plugins/iframe/lang/gu.js
new file mode 100644
index 0000000..91bb8bb
--- /dev/null
+++ b/sources/plugins/iframe/lang/gu.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'gu', {
6 border: 'ફ્રેમ બોર્ડેર બતાવવી',
7 noUrl: 'iframe URL ટાઈપ્ કરો',
8 scrolling: 'સ્ક્રોલબાર ચાલુ કરવા',
9 title: 'IFrame વિકલ્પો',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/he.js b/sources/plugins/iframe/lang/he.js
new file mode 100644
index 0000000..87467be
--- /dev/null
+++ b/sources/plugins/iframe/lang/he.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'he', {
6 border: 'הראה מסגרת לחלון',
7 noUrl: 'יש להכניס כתובת לחלון.',
8 scrolling: 'אפשר פסי גלילה',
9 title: 'מאפייני חלון פנימי (iframe)',
10 toolbar: 'חלון פנימי (iframe)'
11} );
diff --git a/sources/plugins/iframe/lang/hi.js b/sources/plugins/iframe/lang/hi.js
new file mode 100644
index 0000000..96d30fb
--- /dev/null
+++ b/sources/plugins/iframe/lang/hi.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'hi', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/hr.js b/sources/plugins/iframe/lang/hr.js
new file mode 100644
index 0000000..986e000
--- /dev/null
+++ b/sources/plugins/iframe/lang/hr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'hr', {
6 border: 'Prikaži okvir IFrame-a',
7 noUrl: 'Unesite URL iframe-a',
8 scrolling: 'Omogući trake za skrolanje',
9 title: 'IFrame svojstva',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/hu.js b/sources/plugins/iframe/lang/hu.js
new file mode 100644
index 0000000..096d311
--- /dev/null
+++ b/sources/plugins/iframe/lang/hu.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'hu', {
6 border: 'Legyen keret',
7 noUrl: 'Kérem írja be a iframe URL-t',
8 scrolling: 'Gördítősáv bekapcsolása',
9 title: 'IFrame Tulajdonságok',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/id.js b/sources/plugins/iframe/lang/id.js
new file mode 100644
index 0000000..c351eda
--- /dev/null
+++ b/sources/plugins/iframe/lang/id.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'id', {
6 border: 'Tampilkan Batas Bingkai',
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Aktifkan Scrollbar',
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/is.js b/sources/plugins/iframe/lang/is.js
new file mode 100644
index 0000000..bc7cf08
--- /dev/null
+++ b/sources/plugins/iframe/lang/is.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'is', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/it.js b/sources/plugins/iframe/lang/it.js
new file mode 100644
index 0000000..e020c27
--- /dev/null
+++ b/sources/plugins/iframe/lang/it.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'it', {
6 border: 'Mostra il bordo',
7 noUrl: 'Inserire l\'URL del campo IFrame',
8 scrolling: 'Abilita scrollbar',
9 title: 'Proprietà IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/ja.js b/sources/plugins/iframe/lang/ja.js
new file mode 100644
index 0000000..b104ccd
--- /dev/null
+++ b/sources/plugins/iframe/lang/ja.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ja', {
6 border: 'フレームの枠を表示',
7 noUrl: 'iframeのURLを入力してください。',
8 scrolling: 'スクロールバーの表示を許可',
9 title: 'iFrameのプロパティ',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/ka.js b/sources/plugins/iframe/lang/ka.js
new file mode 100644
index 0000000..7d98f68
--- /dev/null
+++ b/sources/plugins/iframe/lang/ka.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ka', {
6 border: 'ჩარჩოს გამოჩენა',
7 noUrl: 'აკრიფეთ iframe-ის URL',
8 scrolling: 'გადახვევის ზოლების დაშვება',
9 title: 'IFrame-ის პარამეტრები',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/km.js b/sources/plugins/iframe/lang/km.js
new file mode 100644
index 0000000..9331b23
--- /dev/null
+++ b/sources/plugins/iframe/lang/km.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'km', {
6 border: 'បង្ហាញ​បន្ទាត់​ស៊ុម',
7 noUrl: 'សូម​បញ្ចូល URL របស់ iframe',
8 scrolling: 'ប្រើ​របារ​រំកិល',
9 title: 'លក្ខណៈ​សម្បត្តិ IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/ko.js b/sources/plugins/iframe/lang/ko.js
new file mode 100644
index 0000000..f5c16a0
--- /dev/null
+++ b/sources/plugins/iframe/lang/ko.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ko', {
6 border: '프레임 테두리 표시',
7 noUrl: '아이프레임 주소(URL)를 입력해주세요.',
8 scrolling: '스크롤바 사용',
9 title: '아이프레임 속성',
10 toolbar: '아이프레임'
11} );
diff --git a/sources/plugins/iframe/lang/ku.js b/sources/plugins/iframe/lang/ku.js
new file mode 100644
index 0000000..852c3b4
--- /dev/null
+++ b/sources/plugins/iframe/lang/ku.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ku', {
6 border: 'نیشاندانی لاکێشه بە چوواردەوری چووارچێوە',
7 noUrl: 'تکایه ناونیشانی بەستەر بنووسه بۆ چووارچێوه',
8 scrolling: 'چالاککردنی هاتووچۆپێکردن',
9 title: 'دیالۆگی چووارچێوه',
10 toolbar: 'چووارچێوه'
11} );
diff --git a/sources/plugins/iframe/lang/lt.js b/sources/plugins/iframe/lang/lt.js
new file mode 100644
index 0000000..c69817f
--- /dev/null
+++ b/sources/plugins/iframe/lang/lt.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'lt', {
6 border: 'Rodyti rėmelį',
7 noUrl: 'Nurodykite iframe nuorodą',
8 scrolling: 'Įjungti slankiklius',
9 title: 'IFrame nustatymai',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/lv.js b/sources/plugins/iframe/lang/lv.js
new file mode 100644
index 0000000..50a6743
--- /dev/null
+++ b/sources/plugins/iframe/lang/lv.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'lv', {
6 border: 'Rādīt rāmi',
7 noUrl: 'Norādiet iframe adresi',
8 scrolling: 'Atļaut ritjoslas',
9 title: 'IFrame uzstādījumi',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/mk.js b/sources/plugins/iframe/lang/mk.js
new file mode 100644
index 0000000..d576e21
--- /dev/null
+++ b/sources/plugins/iframe/lang/mk.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'mk', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/mn.js b/sources/plugins/iframe/lang/mn.js
new file mode 100644
index 0000000..dd9d927
--- /dev/null
+++ b/sources/plugins/iframe/lang/mn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'mn', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/ms.js b/sources/plugins/iframe/lang/ms.js
new file mode 100644
index 0000000..f0342bf
--- /dev/null
+++ b/sources/plugins/iframe/lang/ms.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ms', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/nb.js b/sources/plugins/iframe/lang/nb.js
new file mode 100644
index 0000000..c02990e
--- /dev/null
+++ b/sources/plugins/iframe/lang/nb.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'nb', {
6 border: 'Vis ramme rundt iframe',
7 noUrl: 'Vennligst skriv inn URL for iframe',
8 scrolling: 'Aktiver scrollefelt',
9 title: 'Egenskaper for IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/nl.js b/sources/plugins/iframe/lang/nl.js
new file mode 100644
index 0000000..555025d
--- /dev/null
+++ b/sources/plugins/iframe/lang/nl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'nl', {
6 border: 'Framerand tonen',
7 noUrl: 'Vul de IFrame URL in',
8 scrolling: 'Scrollbalken inschakelen',
9 title: 'IFrame-eigenschappen',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/no.js b/sources/plugins/iframe/lang/no.js
new file mode 100644
index 0000000..bb44fe5
--- /dev/null
+++ b/sources/plugins/iframe/lang/no.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'no', {
6 border: 'Viss ramme rundt iframe',
7 noUrl: 'Vennligst skriv inn URL for iframe',
8 scrolling: 'Aktiver scrollefelt',
9 title: 'Egenskaper for IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/oc.js b/sources/plugins/iframe/lang/oc.js
new file mode 100644
index 0000000..890a571
--- /dev/null
+++ b/sources/plugins/iframe/lang/oc.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'oc', {
6 border: 'Afichar la bordadura del quadre',
7 noUrl: 'Entratz l\'URL del contengut del quadre',
8 scrolling: 'Activar las barras de desfilament',
9 title: 'Proprietats del quadre de contengut incorporat',
10 toolbar: 'Quadre de contengut incorporat'
11} );
diff --git a/sources/plugins/iframe/lang/pl.js b/sources/plugins/iframe/lang/pl.js
new file mode 100644
index 0000000..6d05dd1
--- /dev/null
+++ b/sources/plugins/iframe/lang/pl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'pl', {
6 border: 'Pokaż obramowanie obiektu IFrame',
7 noUrl: 'Podaj adres URL elementu IFrame',
8 scrolling: 'Włącz paski przewijania',
9 title: 'Właściwości elementu IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/pt-br.js b/sources/plugins/iframe/lang/pt-br.js
new file mode 100644
index 0000000..58ec356
--- /dev/null
+++ b/sources/plugins/iframe/lang/pt-br.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'pt-br', {
6 border: 'Mostra borda do iframe',
7 noUrl: 'Insira a URL do iframe',
8 scrolling: 'Abilita scrollbars',
9 title: 'Propriedade do IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/pt.js b/sources/plugins/iframe/lang/pt.js
new file mode 100644
index 0000000..1b1cd9f
--- /dev/null
+++ b/sources/plugins/iframe/lang/pt.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'pt', {
6 border: 'Mostrar a borda da Frame',
7 noUrl: 'Por favor, digite o URL da iframe',
8 scrolling: 'Ativar barras de rolamento',
9 title: 'Propriedades da IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/ro.js b/sources/plugins/iframe/lang/ro.js
new file mode 100644
index 0000000..deeb0c4
--- /dev/null
+++ b/sources/plugins/iframe/lang/ro.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ro', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/ru.js b/sources/plugins/iframe/lang/ru.js
new file mode 100644
index 0000000..e352aa3
--- /dev/null
+++ b/sources/plugins/iframe/lang/ru.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ru', {
6 border: 'Показать границы фрейма',
7 noUrl: 'Пожалуйста, введите ссылку фрейма',
8 scrolling: 'Отображать полосы прокрутки',
9 title: 'Свойства iFrame',
10 toolbar: 'iFrame'
11} );
diff --git a/sources/plugins/iframe/lang/si.js b/sources/plugins/iframe/lang/si.js
new file mode 100644
index 0000000..d7660ef
--- /dev/null
+++ b/sources/plugins/iframe/lang/si.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'si', {
6 border: 'සැකිල්ලේ කඩයිම් ',
7 noUrl: 'කරුණාකර රුපයේ URL ලියන්න',
8 scrolling: 'සක්ක්‍රිය කරන්න',
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/sk.js b/sources/plugins/iframe/lang/sk.js
new file mode 100644
index 0000000..ac0b91d
--- /dev/null
+++ b/sources/plugins/iframe/lang/sk.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'sk', {
6 border: 'Zobraziť rám frame-u',
7 noUrl: 'Prosím, vložte URL iframe',
8 scrolling: 'Povoliť skrolovanie',
9 title: 'Vlastnosti IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/sl.js b/sources/plugins/iframe/lang/sl.js
new file mode 100644
index 0000000..2b0e375
--- /dev/null
+++ b/sources/plugins/iframe/lang/sl.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'sl', {
6 border: 'Pokaži obrobo okvirja',
7 noUrl: 'Prosimo, vnesite iframe URL',
8 scrolling: 'Omogoči drsnike',
9 title: 'Lastnosti IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/sq.js b/sources/plugins/iframe/lang/sq.js
new file mode 100644
index 0000000..a274000
--- /dev/null
+++ b/sources/plugins/iframe/lang/sq.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'sq', {
6 border: 'Shfaq kufirin e kornizës',
7 noUrl: 'Ju lutemi shkruani URL-në e iframe-it',
8 scrolling: 'Lejo shiritët zvarritës',
9 title: 'Karakteristikat e IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/sr-latn.js b/sources/plugins/iframe/lang/sr-latn.js
new file mode 100644
index 0000000..29685a9
--- /dev/null
+++ b/sources/plugins/iframe/lang/sr-latn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'sr-latn', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/sr.js b/sources/plugins/iframe/lang/sr.js
new file mode 100644
index 0000000..acd9876
--- /dev/null
+++ b/sources/plugins/iframe/lang/sr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'sr', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame' // MISSING
11} );
diff --git a/sources/plugins/iframe/lang/sv.js b/sources/plugins/iframe/lang/sv.js
new file mode 100644
index 0000000..fab04a5
--- /dev/null
+++ b/sources/plugins/iframe/lang/sv.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'sv', {
6 border: 'Visa ramkant',
7 noUrl: 'Skriv in URL för iFrame',
8 scrolling: 'Aktivera rullningslister',
9 title: 'iFrame-egenskaper',
10 toolbar: 'iFrame'
11} );
diff --git a/sources/plugins/iframe/lang/th.js b/sources/plugins/iframe/lang/th.js
new file mode 100644
index 0000000..57926b9
--- /dev/null
+++ b/sources/plugins/iframe/lang/th.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'th', {
6 border: 'Show frame border', // MISSING
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame Properties', // MISSING
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/tr.js b/sources/plugins/iframe/lang/tr.js
new file mode 100644
index 0000000..d828f65
--- /dev/null
+++ b/sources/plugins/iframe/lang/tr.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'tr', {
6 border: 'Çerceve sınırlarını göster',
7 noUrl: 'Lütfen IFrame köprü (URL) bağlantısını yazın',
8 scrolling: 'Kaydırma çubuklarını aktif et',
9 title: 'IFrame Özellikleri',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/tt.js b/sources/plugins/iframe/lang/tt.js
new file mode 100644
index 0000000..869f67b
--- /dev/null
+++ b/sources/plugins/iframe/lang/tt.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'tt', {
6 border: 'Frame чикләрен күрсәтү',
7 noUrl: 'Please type the iframe URL', // MISSING
8 scrolling: 'Enable scrollbars', // MISSING
9 title: 'IFrame үзлекләре',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/ug.js b/sources/plugins/iframe/lang/ug.js
new file mode 100644
index 0000000..b46f6da
--- /dev/null
+++ b/sources/plugins/iframe/lang/ug.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'ug', {
6 border: 'كاندۇك گىرۋەكلىرىنى كۆرسەت',
7 noUrl: 'كاندۇكنىڭ ئادرېسى(Url)نى كىرگۈزۈڭ',
8 scrolling: 'دومىلىما سۈرگۈچكە يول قوي',
9 title: 'IFrame خاسلىق',
10 toolbar: 'IFrame '
11} );
diff --git a/sources/plugins/iframe/lang/uk.js b/sources/plugins/iframe/lang/uk.js
new file mode 100644
index 0000000..3f91ef6
--- /dev/null
+++ b/sources/plugins/iframe/lang/uk.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'uk', {
6 border: 'Показати рамки фрейму',
7 noUrl: 'Будь ласка введіть URL посилання для IFrame',
8 scrolling: 'Увімкнути прокрутку',
9 title: 'Налаштування для IFrame',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/vi.js b/sources/plugins/iframe/lang/vi.js
new file mode 100644
index 0000000..be8ebfb
--- /dev/null
+++ b/sources/plugins/iframe/lang/vi.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'vi', {
6 border: 'Hiển thị viền khung',
7 noUrl: 'Vui lòng nhập địa chỉ iframe',
8 scrolling: 'Kích hoạt thanh cuộn',
9 title: 'Thuộc tính iframe',
10 toolbar: 'Iframe'
11} );
diff --git a/sources/plugins/iframe/lang/zh-cn.js b/sources/plugins/iframe/lang/zh-cn.js
new file mode 100644
index 0000000..a35bd8c
--- /dev/null
+++ b/sources/plugins/iframe/lang/zh-cn.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'zh-cn', {
6 border: '显示框架边框',
7 noUrl: '请输入框架的 URL',
8 scrolling: '允许滚动条',
9 title: 'IFrame 属性',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/lang/zh.js b/sources/plugins/iframe/lang/zh.js
new file mode 100644
index 0000000..4f7472a
--- /dev/null
+++ b/sources/plugins/iframe/lang/zh.js
@@ -0,0 +1,11 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'iframe', 'zh', {
6 border: '顯示框架框線',
7 noUrl: '請輸入 iframe URL',
8 scrolling: '啟用捲軸列',
9 title: 'IFrame 屬性',
10 toolbar: 'IFrame'
11} );
diff --git a/sources/plugins/iframe/plugin.js b/sources/plugins/iframe/plugin.js
new file mode 100644
index 0000000..52c816a
--- /dev/null
+++ b/sources/plugins/iframe/plugin.js
@@ -0,0 +1,85 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 CKEDITOR.plugins.add( 'iframe', {
8 requires: 'dialog,fakeobjects',
9 // jscs:disable maximumLineLength
10 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
11 // jscs:enable maximumLineLength
12 icons: 'iframe', // %REMOVE_LINE_CORE%
13 hidpi: true, // %REMOVE_LINE_CORE%
14 onLoad: function() {
15 CKEDITOR.addCss( 'img.cke_iframe' +
16 '{' +
17 'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/placeholder.png' ) + ');' +
18 'background-position: center center;' +
19 'background-repeat: no-repeat;' +
20 'border: 1px solid #a9a9a9;' +
21 'width: 80px;' +
22 'height: 80px;' +
23 '}'
24 );
25 },
26 init: function( editor ) {
27 var pluginName = 'iframe',
28 lang = editor.lang.iframe,
29 allowed = 'iframe[align,longdesc,frameborder,height,name,scrolling,src,title,width]';
30
31 if ( editor.plugins.dialogadvtab )
32 allowed += ';iframe' + editor.plugins.dialogadvtab.allowedContent( { id: 1, classes: 1, styles: 1 } );
33
34 CKEDITOR.dialog.add( pluginName, this.path + 'dialogs/iframe.js' );
35 editor.addCommand( pluginName, new CKEDITOR.dialogCommand( pluginName, {
36 allowedContent: allowed,
37 requiredContent: 'iframe'
38 } ) );
39
40 editor.ui.addButton && editor.ui.addButton( 'Iframe', {
41 label: lang.toolbar,
42 command: pluginName,
43 toolbar: 'insert,80'
44 } );
45
46 editor.on( 'doubleclick', function( evt ) {
47 var element = evt.data.element;
48 if ( element.is( 'img' ) && element.data( 'cke-real-element-type' ) == 'iframe' )
49 evt.data.dialog = 'iframe';
50 } );
51
52 if ( editor.addMenuItems ) {
53 editor.addMenuItems( {
54 iframe: {
55 label: lang.title,
56 command: 'iframe',
57 group: 'image'
58 }
59 } );
60 }
61
62 // If the "contextmenu" plugin is loaded, register the listeners.
63 if ( editor.contextMenu ) {
64 editor.contextMenu.addListener( function( element ) {
65 if ( element && element.is( 'img' ) && element.data( 'cke-real-element-type' ) == 'iframe' )
66 return { iframe: CKEDITOR.TRISTATE_OFF };
67 } );
68 }
69 },
70 afterInit: function( editor ) {
71 var dataProcessor = editor.dataProcessor,
72 dataFilter = dataProcessor && dataProcessor.dataFilter;
73
74 if ( dataFilter ) {
75 dataFilter.addRules( {
76 elements: {
77 iframe: function( element ) {
78 return editor.createFakeParserElement( element, 'cke_iframe', 'iframe', true );
79 }
80 }
81 } );
82 }
83 }
84 } );
85} )();
diff --git a/sources/plugins/image/dialogs/image.js b/sources/plugins/image/dialogs/image.js
new file mode 100644
index 0000000..7d7537a
--- /dev/null
+++ b/sources/plugins/image/dialogs/image.js
@@ -0,0 +1,1254 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 var imageDialog = function( editor, dialogType ) {
8 // Load image preview.
9 var IMAGE = 1,
10 LINK = 2,
11 PREVIEW = 4,
12 CLEANUP = 8,
13 regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i,
14 regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i,
15 pxLengthRegex = /^\d+px$/;
16
17 var onSizeChange = function() {
18 var value = this.getValue(),
19 // This = input element.
20 dialog = this.getDialog(),
21 aMatch = value.match( regexGetSize ); // Check value
22 if ( aMatch ) {
23 if ( aMatch[ 2 ] == '%' ) // % is allowed - > unlock ratio.
24 switchLockRatio( dialog, false ); // Unlock.
25 value = aMatch[ 1 ];
26 }
27
28 // Only if ratio is locked
29 if ( dialog.lockRatio ) {
30 var oImageOriginal = dialog.originalElement;
31 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) {
32 if ( this.id == 'txtHeight' ) {
33 if ( value && value != '0' )
34 value = Math.round( oImageOriginal.$.width * ( value / oImageOriginal.$.height ) );
35 if ( !isNaN( value ) )
36 dialog.setValueOf( 'info', 'txtWidth', value );
37 }
38 // this.id = txtWidth.
39 else {
40 if ( value && value != '0' )
41 value = Math.round( oImageOriginal.$.height * ( value / oImageOriginal.$.width ) );
42 if ( !isNaN( value ) )
43 dialog.setValueOf( 'info', 'txtHeight', value );
44 }
45 }
46 }
47 updatePreview( dialog );
48 };
49
50 var updatePreview = function( dialog ) {
51 //Don't load before onShow.
52 if ( !dialog.originalElement || !dialog.preview )
53 return 1;
54
55 // Read attributes and update imagePreview;
56 dialog.commitContent( PREVIEW, dialog.preview );
57 return 0;
58 };
59
60 // Custom commit dialog logic, where we're intended to give inline style
61 // field (txtdlgGenStyle) higher priority to avoid overwriting styles contribute
62 // by other fields.
63 function commitContent() {
64 var args = arguments;
65 var inlineStyleField = this.getContentElement( 'advanced', 'txtdlgGenStyle' );
66 inlineStyleField && inlineStyleField.commit.apply( inlineStyleField, args );
67
68 this.foreach( function( widget ) {
69 if ( widget.commit && widget.id != 'txtdlgGenStyle' )
70 widget.commit.apply( widget, args );
71 } );
72 }
73
74 // Avoid recursions.
75 var incommit;
76
77 // Synchronous field values to other impacted fields is required, e.g. border
78 // size change should alter inline-style text as well.
79 function commitInternally( targetFields ) {
80 if ( incommit )
81 return;
82
83 incommit = 1;
84
85 var dialog = this.getDialog(),
86 element = dialog.imageElement;
87 if ( element ) {
88 // Commit this field and broadcast to target fields.
89 this.commit( IMAGE, element );
90
91 targetFields = [].concat( targetFields );
92 var length = targetFields.length,
93 field;
94 for ( var i = 0; i < length; i++ ) {
95 field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) );
96 // May cause recursion.
97 field && field.setup( IMAGE, element );
98 }
99 }
100
101 incommit = 0;
102 }
103
104 var switchLockRatio = function( dialog, value ) {
105 if ( !dialog.getContentElement( 'info', 'ratioLock' ) )
106 return null;
107
108 var oImageOriginal = dialog.originalElement;
109
110 // Dialog may already closed. (#5505)
111 if ( !oImageOriginal )
112 return null;
113
114 // Check image ratio and original image ratio, but respecting user's preference.
115 if ( value == 'check' ) {
116 if ( !dialog.userlockRatio && oImageOriginal.getCustomData( 'isReady' ) == 'true' ) {
117 var width = dialog.getValueOf( 'info', 'txtWidth' ),
118 height = dialog.getValueOf( 'info', 'txtHeight' ),
119 originalRatio = oImageOriginal.$.width * 1000 / oImageOriginal.$.height,
120 thisRatio = width * 1000 / height;
121 dialog.lockRatio = false; // Default: unlock ratio
122
123 if ( !width && !height )
124 dialog.lockRatio = true;
125 else if ( !isNaN( originalRatio ) && !isNaN( thisRatio ) ) {
126 if ( Math.round( originalRatio ) == Math.round( thisRatio ) )
127 dialog.lockRatio = true;
128 }
129 }
130 } else if ( value !== undefined )
131 dialog.lockRatio = value;
132 else {
133 dialog.userlockRatio = 1;
134 dialog.lockRatio = !dialog.lockRatio;
135 }
136
137 var ratioButton = CKEDITOR.document.getById( btnLockSizesId );
138 if ( dialog.lockRatio )
139 ratioButton.removeClass( 'cke_btn_unlocked' );
140 else
141 ratioButton.addClass( 'cke_btn_unlocked' );
142
143 ratioButton.setAttribute( 'aria-checked', dialog.lockRatio );
144
145 // Ratio button hc presentation - WHITE SQUARE / BLACK SQUARE
146 if ( CKEDITOR.env.hc ) {
147 var icon = ratioButton.getChild( 0 );
148 icon.setHtml( dialog.lockRatio ? CKEDITOR.env.ie ? '\u25A0' : '\u25A3' : CKEDITOR.env.ie ? '\u25A1' : '\u25A2' );
149 }
150
151 return dialog.lockRatio;
152 };
153
154 var resetSize = function( dialog, emptyValues ) {
155 var oImageOriginal = dialog.originalElement,
156 ready = oImageOriginal.getCustomData( 'isReady' ) == 'true';
157
158 if ( ready ) {
159 var widthField = dialog.getContentElement( 'info', 'txtWidth' ),
160 heightField = dialog.getContentElement( 'info', 'txtHeight' ),
161 widthValue, heightValue;
162
163 if ( emptyValues ) {
164 widthValue = 0;
165 heightValue = 0;
166 } else {
167 widthValue = oImageOriginal.$.width;
168 heightValue = oImageOriginal.$.height;
169 }
170
171 widthField && widthField.setValue( widthValue );
172 heightField && heightField.setValue( heightValue );
173 }
174 updatePreview( dialog );
175 };
176
177 var setupDimension = function( type, element ) {
178 if ( type != IMAGE )
179 return;
180
181 function checkDimension( size, defaultValue ) {
182 var aMatch = size.match( regexGetSize );
183 if ( aMatch ) {
184 // % is allowed.
185 if ( aMatch[ 2 ] == '%' ) {
186 aMatch[ 1 ] += '%';
187 switchLockRatio( dialog, false ); // Unlock ratio
188 }
189 return aMatch[ 1 ];
190 }
191 return defaultValue;
192 }
193
194 var dialog = this.getDialog(),
195 value = '',
196 dimension = this.id == 'txtWidth' ? 'width' : 'height',
197 size = element.getAttribute( dimension );
198
199 if ( size )
200 value = checkDimension( size, value );
201 value = checkDimension( element.getStyle( dimension ), value );
202
203 this.setValue( value );
204 };
205
206 var previewPreloader;
207
208 var onImgLoadEvent = function() {
209 // Image is ready.
210 var original = this.originalElement,
211 loader = CKEDITOR.document.getById( imagePreviewLoaderId );
212
213 original.setCustomData( 'isReady', 'true' );
214 original.removeListener( 'load', onImgLoadEvent );
215 original.removeListener( 'error', onImgLoadErrorEvent );
216 original.removeListener( 'abort', onImgLoadErrorEvent );
217
218 // Hide loader.
219 if ( loader )
220 loader.setStyle( 'display', 'none' );
221
222 // New image -> new dimensions
223 if ( !this.dontResetSize ) {
224 resetSize( this, editor.config.image_prefillDimensions === false );
225 }
226
227 if ( this.firstLoad ) {
228 CKEDITOR.tools.setTimeout( function() {
229 switchLockRatio( this, 'check' );
230 }, 0, this );
231 }
232
233 this.firstLoad = false;
234 this.dontResetSize = false;
235
236 // Possible fix for #12818.
237 updatePreview( this );
238 };
239
240 var onImgLoadErrorEvent = function() {
241 // Error. Image is not loaded.
242 var original = this.originalElement,
243 loader = CKEDITOR.document.getById( imagePreviewLoaderId );
244
245 original.removeListener( 'load', onImgLoadEvent );
246 original.removeListener( 'error', onImgLoadErrorEvent );
247 original.removeListener( 'abort', onImgLoadErrorEvent );
248
249 // Set Error image.
250 var noimage = CKEDITOR.getUrl( CKEDITOR.plugins.get( 'image' ).path + 'images/noimage.png' );
251
252 if ( this.preview )
253 this.preview.setAttribute( 'src', noimage );
254
255 // Hide loader.
256 if ( loader )
257 loader.setStyle( 'display', 'none' );
258
259 switchLockRatio( this, false ); // Unlock.
260 };
261
262 var numbering = function( id ) {
263 return CKEDITOR.tools.getNextId() + '_' + id;
264 },
265 btnLockSizesId = numbering( 'btnLockSizes' ),
266 btnResetSizeId = numbering( 'btnResetSize' ),
267 imagePreviewLoaderId = numbering( 'ImagePreviewLoader' ),
268 previewLinkId = numbering( 'previewLink' ),
269 previewImageId = numbering( 'previewImage' );
270
271 return {
272 title: editor.lang.image[ dialogType == 'image' ? 'title' : 'titleButton' ],
273 minWidth: ( CKEDITOR.skinName || editor.config.skin ) == 'moono-lisa' ? 500 : 420,
274 minHeight: 360,
275 onShow: function() {
276 this.imageElement = false;
277 this.linkElement = false;
278
279 // Default: create a new element.
280 this.imageEditMode = false;
281 this.linkEditMode = false;
282
283 this.lockRatio = true;
284 this.userlockRatio = 0;
285 this.dontResetSize = false;
286 this.firstLoad = true;
287 this.addLink = false;
288
289 var editor = this.getParentEditor(),
290 sel = editor.getSelection(),
291 element = sel && sel.getSelectedElement(),
292 link = element && editor.elementPath( element ).contains( 'a', 1 ),
293 loader = CKEDITOR.document.getById( imagePreviewLoaderId );
294
295 // Hide loader.
296 if ( loader )
297 loader.setStyle( 'display', 'none' );
298
299 // Create the preview before setup the dialog contents.
300 previewPreloader = new CKEDITOR.dom.element( 'img', editor.document );
301 this.preview = CKEDITOR.document.getById( previewImageId );
302
303 // Copy of the image
304 this.originalElement = editor.document.createElement( 'img' );
305 this.originalElement.setAttribute( 'alt', '' );
306 this.originalElement.setCustomData( 'isReady', 'false' );
307
308 if ( link ) {
309 this.linkElement = link;
310 this.linkEditMode = true;
311
312 // If there is an existing link, by default keep it (true).
313 // It will be removed if certain conditions are met and Link tab is enabled. (#13351)
314 this.addLink = true;
315
316 // Look for Image element.
317 var linkChildren = link.getChildren();
318 if ( linkChildren.count() == 1 ) {
319 var childTag = linkChildren.getItem( 0 );
320
321 if ( childTag.type == CKEDITOR.NODE_ELEMENT ) {
322 if ( childTag.is( 'img' ) || childTag.is( 'input' ) ) {
323 this.imageElement = linkChildren.getItem( 0 );
324 if ( this.imageElement.is( 'img' ) )
325 this.imageEditMode = 'img';
326 else if ( this.imageElement.is( 'input' ) )
327 this.imageEditMode = 'input';
328 }
329 }
330 }
331 // Fill out all fields.
332 if ( dialogType == 'image' )
333 this.setupContent( LINK, link );
334 }
335
336 // Edit given image element instead the one from selection.
337 if ( this.customImageElement ) {
338 this.imageEditMode = 'img';
339 this.imageElement = this.customImageElement;
340 delete this.customImageElement;
341 }
342 else if ( element && element.getName() == 'img' && !element.data( 'cke-realelement' ) ||
343 element && element.getName() == 'input' && element.getAttribute( 'type' ) == 'image' ) {
344 this.imageEditMode = element.getName();
345 this.imageElement = element;
346 }
347
348 if ( this.imageEditMode ) {
349 // Use the original element as a buffer from since we don't want
350 // temporary changes to be committed, e.g. if the dialog is canceled.
351 this.cleanImageElement = this.imageElement;
352 this.imageElement = this.cleanImageElement.clone( true, true );
353
354 // Fill out all fields.
355 this.setupContent( IMAGE, this.imageElement );
356 }
357
358 // Refresh LockRatio button
359 switchLockRatio( this, true );
360
361 // Dont show preview if no URL given.
362 if ( !CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtUrl' ) ) ) {
363 this.preview.removeAttribute( 'src' );
364 this.preview.setStyle( 'display', 'none' );
365 }
366 },
367 onOk: function() {
368 // Edit existing Image.
369 if ( this.imageEditMode ) {
370 var imgTagName = this.imageEditMode;
371
372 // Image dialog and Input element.
373 if ( dialogType == 'image' && imgTagName == 'input' && confirm( editor.lang.image.button2Img ) ) { // jshint ignore:line
374 // Replace INPUT-> IMG
375 imgTagName = 'img';
376 this.imageElement = editor.document.createElement( 'img' );
377 this.imageElement.setAttribute( 'alt', '' );
378 editor.insertElement( this.imageElement );
379 }
380 // ImageButton dialog and Image element.
381 else if ( dialogType != 'image' && imgTagName == 'img' && confirm( editor.lang.image.img2Button ) ) { // jshint ignore:line
382 // Replace IMG -> INPUT
383 imgTagName = 'input';
384 this.imageElement = editor.document.createElement( 'input' );
385 this.imageElement.setAttributes( {
386 type: 'image',
387 alt: ''
388 } );
389 editor.insertElement( this.imageElement );
390 } else {
391 // Restore the original element before all commits.
392 this.imageElement = this.cleanImageElement;
393 delete this.cleanImageElement;
394 }
395 }
396 // Create a new image.
397 else {
398 // Image dialog -> create IMG element.
399 if ( dialogType == 'image' )
400 this.imageElement = editor.document.createElement( 'img' );
401 else {
402 this.imageElement = editor.document.createElement( 'input' );
403 this.imageElement.setAttribute( 'type', 'image' );
404 }
405 this.imageElement.setAttribute( 'alt', '' );
406 }
407
408 // Create a new link.
409 if ( !this.linkEditMode )
410 this.linkElement = editor.document.createElement( 'a' );
411
412 // Set attributes.
413 this.commitContent( IMAGE, this.imageElement );
414 this.commitContent( LINK, this.linkElement );
415
416 // Remove empty style attribute.
417 if ( !this.imageElement.getAttribute( 'style' ) )
418 this.imageElement.removeAttribute( 'style' );
419
420 // Insert a new Image.
421 if ( !this.imageEditMode ) {
422 if ( this.addLink ) {
423 if ( !this.linkEditMode ) {
424 // Insert a new link.
425 editor.insertElement( this.linkElement );
426 this.linkElement.append( this.imageElement, false );
427 } else {
428 // We already have a link in editor.
429 if ( this.linkElement.equals( editor.getSelection().getSelectedElement() ) ) {
430 // If the link is selected outside, replace it's content rather than the link itself. ([<a>foo</a>])
431 this.linkElement.setHtml( '' );
432 this.linkElement.append( this.imageElement, false );
433 } else {
434 // Only inside of the link is selected, so replace it with image. (<a>[foo]</a>, <a>[f]oo</a>)
435 editor.insertElement( this.imageElement );
436 }
437 }
438 } else {
439 editor.insertElement( this.imageElement );
440 }
441 }
442 // Image already exists.
443 else {
444 // Add a new link element.
445 if ( !this.linkEditMode && this.addLink ) {
446 editor.insertElement( this.linkElement );
447 this.imageElement.appendTo( this.linkElement );
448 }
449 // Remove Link, Image exists.
450 else if ( this.linkEditMode && !this.addLink ) {
451 editor.getSelection().selectElement( this.linkElement );
452 editor.insertElement( this.imageElement );
453 }
454 }
455 },
456 onLoad: function() {
457 if ( dialogType != 'image' )
458 this.hidePage( 'Link' ); //Hide Link tab.
459 var doc = this._.element.getDocument();
460
461 if ( this.getContentElement( 'info', 'ratioLock' ) ) {
462 this.addFocusable( doc.getById( btnResetSizeId ), 5 );
463 this.addFocusable( doc.getById( btnLockSizesId ), 5 );
464 }
465
466 this.commitContent = commitContent;
467 },
468 onHide: function() {
469 if ( this.preview )
470 this.commitContent( CLEANUP, this.preview );
471
472 if ( this.originalElement ) {
473 this.originalElement.removeListener( 'load', onImgLoadEvent );
474 this.originalElement.removeListener( 'error', onImgLoadErrorEvent );
475 this.originalElement.removeListener( 'abort', onImgLoadErrorEvent );
476 this.originalElement.remove();
477 this.originalElement = false; // Dialog is closed.
478 }
479
480 delete this.imageElement;
481 },
482 contents: [ {
483 id: 'info',
484 label: editor.lang.image.infoTab,
485 accessKey: 'I',
486 elements: [ {
487 type: 'vbox',
488 padding: 0,
489 children: [ {
490 type: 'hbox',
491 widths: [ '280px', '110px' ],
492 align: 'right',
493 className: 'cke_dialog_image_url',
494 children: [ {
495 id: 'txtUrl',
496 type: 'text',
497 label: editor.lang.common.url,
498 required: true,
499 onChange: function() {
500 var dialog = this.getDialog(),
501 newUrl = this.getValue();
502
503 // Update original image.
504 // Prevent from load before onShow.
505 if ( newUrl.length > 0 ) {
506 dialog = this.getDialog();
507 var original = dialog.originalElement;
508
509 if ( dialog.preview ) {
510 dialog.preview.removeStyle( 'display' );
511 }
512
513 original.setCustomData( 'isReady', 'false' );
514 // Show loader.
515 var loader = CKEDITOR.document.getById( imagePreviewLoaderId );
516 if ( loader )
517 loader.setStyle( 'display', '' );
518
519 original.on( 'load', onImgLoadEvent, dialog );
520 original.on( 'error', onImgLoadErrorEvent, dialog );
521 original.on( 'abort', onImgLoadErrorEvent, dialog );
522 original.setAttribute( 'src', newUrl );
523
524 if ( dialog.preview ) {
525 // Query the preloader to figure out the url impacted by based href.
526 previewPreloader.setAttribute( 'src', newUrl );
527 dialog.preview.setAttribute( 'src', previewPreloader.$.src );
528 updatePreview( dialog );
529 }
530 }
531 // Dont show preview if no URL given.
532 else if ( dialog.preview ) {
533 dialog.preview.removeAttribute( 'src' );
534 dialog.preview.setStyle( 'display', 'none' );
535 }
536 },
537 setup: function( type, element ) {
538 if ( type == IMAGE ) {
539 var url = element.data( 'cke-saved-src' ) || element.getAttribute( 'src' );
540 var field = this;
541
542 this.getDialog().dontResetSize = true;
543
544 field.setValue( url ); // And call this.onChange()
545 // Manually set the initial value.(#4191)
546 field.setInitValue();
547 }
548 },
549 commit: function( type, element ) {
550 if ( type == IMAGE && ( this.getValue() || this.isChanged() ) ) {
551 element.data( 'cke-saved-src', this.getValue() );
552 element.setAttribute( 'src', this.getValue() );
553 } else if ( type == CLEANUP ) {
554 element.setAttribute( 'src', '' ); // If removeAttribute doesn't work.
555 element.removeAttribute( 'src' );
556 }
557 },
558 validate: CKEDITOR.dialog.validate.notEmpty( editor.lang.image.urlMissing )
559 },
560 {
561 type: 'button',
562 id: 'browse',
563 // v-align with the 'txtUrl' field.
564 // TODO: We need something better than a fixed size here.
565 style: 'display:inline-block;margin-top:14px;',
566 align: 'center',
567 label: editor.lang.common.browseServer,
568 hidden: true,
569 filebrowser: 'info:txtUrl'
570 } ]
571 } ]
572 },
573 {
574 id: 'txtAlt',
575 type: 'text',
576 label: editor.lang.image.alt,
577 accessKey: 'T',
578 'default': '',
579 onChange: function() {
580 updatePreview( this.getDialog() );
581 },
582 setup: function( type, element ) {
583 if ( type == IMAGE )
584 this.setValue( element.getAttribute( 'alt' ) );
585 },
586 commit: function( type, element ) {
587 if ( type == IMAGE ) {
588 if ( this.getValue() || this.isChanged() )
589 element.setAttribute( 'alt', this.getValue() );
590 } else if ( type == PREVIEW )
591 element.setAttribute( 'alt', this.getValue() );
592 else if ( type == CLEANUP ) {
593 element.removeAttribute( 'alt' );
594 }
595
596 }
597 },
598 {
599 type: 'hbox',
600 children: [ {
601 id: 'basic',
602 type: 'vbox',
603 children: [ {
604 type: 'hbox',
605 requiredContent: 'img{width,height}',
606 widths: [ '50%', '50%' ],
607 children: [ {
608 type: 'vbox',
609 padding: 1,
610 children: [ {
611 type: 'text',
612 width: '45px',
613 id: 'txtWidth',
614 label: editor.lang.common.width,
615 onKeyUp: onSizeChange,
616 onChange: function() {
617 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
618 },
619 validate: function() {
620 var aMatch = this.getValue().match( regexGetSizeOrEmpty ),
621 isValid = !!( aMatch && parseInt( aMatch[ 1 ], 10 ) !== 0 );
622 if ( !isValid )
623 alert( editor.lang.common.invalidWidth ); // jshint ignore:line
624 return isValid;
625 },
626 setup: setupDimension,
627 commit: function( type, element ) {
628 var value = this.getValue();
629 if ( type == IMAGE ) {
630 if ( value && editor.activeFilter.check( 'img{width,height}' ) )
631 element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
632 else
633 element.removeStyle( 'width' );
634
635 element.removeAttribute( 'width' );
636 } else if ( type == PREVIEW ) {
637 var aMatch = value.match( regexGetSize );
638 if ( !aMatch ) {
639 var oImageOriginal = this.getDialog().originalElement;
640 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
641 element.setStyle( 'width', oImageOriginal.$.width + 'px' );
642 } else {
643 element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
644 }
645 } else if ( type == CLEANUP ) {
646 element.removeAttribute( 'width' );
647 element.removeStyle( 'width' );
648 }
649 }
650 },
651 {
652 type: 'text',
653 id: 'txtHeight',
654 width: '45px',
655 label: editor.lang.common.height,
656 onKeyUp: onSizeChange,
657 onChange: function() {
658 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
659 },
660 validate: function() {
661 var aMatch = this.getValue().match( regexGetSizeOrEmpty ),
662 isValid = !!( aMatch && parseInt( aMatch[ 1 ], 10 ) !== 0 );
663 if ( !isValid )
664 alert( editor.lang.common.invalidHeight ); // jshint ignore:line
665 return isValid;
666 },
667 setup: setupDimension,
668 commit: function( type, element ) {
669 var value = this.getValue();
670 if ( type == IMAGE ) {
671 if ( value && editor.activeFilter.check( 'img{width,height}' ) )
672 element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) );
673 else
674 element.removeStyle( 'height' );
675
676 element.removeAttribute( 'height' );
677 } else if ( type == PREVIEW ) {
678 var aMatch = value.match( regexGetSize );
679 if ( !aMatch ) {
680 var oImageOriginal = this.getDialog().originalElement;
681 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
682 element.setStyle( 'height', oImageOriginal.$.height + 'px' );
683 } else {
684 element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) );
685 }
686 } else if ( type == CLEANUP ) {
687 element.removeAttribute( 'height' );
688 element.removeStyle( 'height' );
689 }
690 }
691 } ]
692 },
693 {
694 id: 'ratioLock',
695 type: 'html',
696 className: 'cke_dialog_image_ratiolock',
697 style: 'margin-top:30px;width:40px;height:40px;',
698 onLoad: function() {
699 // Activate Reset button
700 var resetButton = CKEDITOR.document.getById( btnResetSizeId ),
701 ratioButton = CKEDITOR.document.getById( btnLockSizesId );
702 if ( resetButton ) {
703 resetButton.on( 'click', function( evt ) {
704 resetSize( this );
705 evt.data && evt.data.preventDefault();
706 }, this.getDialog() );
707 resetButton.on( 'mouseover', function() {
708 this.addClass( 'cke_btn_over' );
709 }, resetButton );
710 resetButton.on( 'mouseout', function() {
711 this.removeClass( 'cke_btn_over' );
712 }, resetButton );
713 }
714 // Activate (Un)LockRatio button
715 if ( ratioButton ) {
716 ratioButton.on( 'click', function( evt ) {
717 switchLockRatio( this );
718
719 var oImageOriginal = this.originalElement,
720 width = this.getValueOf( 'info', 'txtWidth' );
721
722 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' && width ) {
723 var height = oImageOriginal.$.height / oImageOriginal.$.width * width;
724 if ( !isNaN( height ) ) {
725 this.setValueOf( 'info', 'txtHeight', Math.round( height ) );
726 updatePreview( this );
727 }
728 }
729 evt.data && evt.data.preventDefault();
730 }, this.getDialog() );
731 ratioButton.on( 'mouseover', function() {
732 this.addClass( 'cke_btn_over' );
733 }, ratioButton );
734 ratioButton.on( 'mouseout', function() {
735 this.removeClass( 'cke_btn_over' );
736 }, ratioButton );
737 }
738 },
739 html: '<div>' +
740 '<a href="javascript:void(0)" tabindex="-1" title="' + editor.lang.image.lockRatio +
741 '" class="cke_btn_locked" id="' + btnLockSizesId + '" role="checkbox"><span class="cke_icon"></span><span class="cke_label">' + editor.lang.image.lockRatio + '</span></a>' +
742 '<a href="javascript:void(0)" tabindex="-1" title="' + editor.lang.image.resetSize +
743 '" class="cke_btn_reset" id="' + btnResetSizeId + '" role="button"><span class="cke_label">' + editor.lang.image.resetSize + '</span></a>' +
744 '</div>'
745 } ]
746 },
747 {
748 type: 'vbox',
749 padding: 1,
750 children: [ {
751 type: 'text',
752 id: 'txtBorder',
753 requiredContent: 'img{border-width}',
754 width: '60px',
755 label: editor.lang.image.border,
756 'default': '',
757 onKeyUp: function() {
758 updatePreview( this.getDialog() );
759 },
760 onChange: function() {
761 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
762 },
763 validate: CKEDITOR.dialog.validate.integer( editor.lang.image.validateBorder ),
764 setup: function( type, element ) {
765 if ( type == IMAGE ) {
766 var value,
767 borderStyle = element.getStyle( 'border-width' );
768 borderStyle = borderStyle && borderStyle.match( /^(\d+px)(?: \1 \1 \1)?$/ );
769 value = borderStyle && parseInt( borderStyle[ 1 ], 10 );
770 isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'border' ) );
771 this.setValue( value );
772 }
773 },
774 commit: function( type, element ) {
775 var value = parseInt( this.getValue(), 10 );
776 if ( type == IMAGE || type == PREVIEW ) {
777 if ( !isNaN( value ) ) {
778 element.setStyle( 'border-width', CKEDITOR.tools.cssLength( value ) );
779 element.setStyle( 'border-style', 'solid' );
780 } else if ( !value && this.isChanged() ) {
781 element.removeStyle( 'border' );
782 }
783
784 if ( type == IMAGE )
785 element.removeAttribute( 'border' );
786 } else if ( type == CLEANUP ) {
787 element.removeAttribute( 'border' );
788 element.removeStyle( 'border-width' );
789 element.removeStyle( 'border-style' );
790 element.removeStyle( 'border-color' );
791 }
792 }
793 },
794 {
795 type: 'text',
796 id: 'txtHSpace',
797 requiredContent: 'img{margin-left,margin-right}',
798 width: '60px',
799 label: editor.lang.image.hSpace,
800 'default': '',
801 onKeyUp: function() {
802 updatePreview( this.getDialog() );
803 },
804 onChange: function() {
805 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
806 },
807 validate: CKEDITOR.dialog.validate.integer( editor.lang.image.validateHSpace ),
808 setup: function( type, element ) {
809 if ( type == IMAGE ) {
810 var value, marginLeftPx, marginRightPx,
811 marginLeftStyle = element.getStyle( 'margin-left' ),
812 marginRightStyle = element.getStyle( 'margin-right' );
813
814 marginLeftStyle = marginLeftStyle && marginLeftStyle.match( pxLengthRegex );
815 marginRightStyle = marginRightStyle && marginRightStyle.match( pxLengthRegex );
816 marginLeftPx = parseInt( marginLeftStyle, 10 );
817 marginRightPx = parseInt( marginRightStyle, 10 );
818
819 value = ( marginLeftPx == marginRightPx ) && marginLeftPx;
820 isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'hspace' ) );
821
822 this.setValue( value );
823 }
824 },
825 commit: function( type, element ) {
826 var value = parseInt( this.getValue(), 10 );
827 if ( type == IMAGE || type == PREVIEW ) {
828 if ( !isNaN( value ) ) {
829 element.setStyle( 'margin-left', CKEDITOR.tools.cssLength( value ) );
830 element.setStyle( 'margin-right', CKEDITOR.tools.cssLength( value ) );
831 } else if ( !value && this.isChanged() ) {
832 element.removeStyle( 'margin-left' );
833 element.removeStyle( 'margin-right' );
834 }
835
836 if ( type == IMAGE )
837 element.removeAttribute( 'hspace' );
838 } else if ( type == CLEANUP ) {
839 element.removeAttribute( 'hspace' );
840 element.removeStyle( 'margin-left' );
841 element.removeStyle( 'margin-right' );
842 }
843 }
844 },
845 {
846 type: 'text',
847 id: 'txtVSpace',
848 requiredContent: 'img{margin-top,margin-bottom}',
849 width: '60px',
850 label: editor.lang.image.vSpace,
851 'default': '',
852 onKeyUp: function() {
853 updatePreview( this.getDialog() );
854 },
855 onChange: function() {
856 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
857 },
858 validate: CKEDITOR.dialog.validate.integer( editor.lang.image.validateVSpace ),
859 setup: function( type, element ) {
860 if ( type == IMAGE ) {
861 var value, marginTopPx, marginBottomPx,
862 marginTopStyle = element.getStyle( 'margin-top' ),
863 marginBottomStyle = element.getStyle( 'margin-bottom' );
864
865 marginTopStyle = marginTopStyle && marginTopStyle.match( pxLengthRegex );
866 marginBottomStyle = marginBottomStyle && marginBottomStyle.match( pxLengthRegex );
867 marginTopPx = parseInt( marginTopStyle, 10 );
868 marginBottomPx = parseInt( marginBottomStyle, 10 );
869
870 value = ( marginTopPx == marginBottomPx ) && marginTopPx;
871 isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'vspace' ) );
872 this.setValue( value );
873 }
874 },
875 commit: function( type, element ) {
876 var value = parseInt( this.getValue(), 10 );
877 if ( type == IMAGE || type == PREVIEW ) {
878 if ( !isNaN( value ) ) {
879 element.setStyle( 'margin-top', CKEDITOR.tools.cssLength( value ) );
880 element.setStyle( 'margin-bottom', CKEDITOR.tools.cssLength( value ) );
881 } else if ( !value && this.isChanged() ) {
882 element.removeStyle( 'margin-top' );
883 element.removeStyle( 'margin-bottom' );
884 }
885
886 if ( type == IMAGE )
887 element.removeAttribute( 'vspace' );
888 } else if ( type == CLEANUP ) {
889 element.removeAttribute( 'vspace' );
890 element.removeStyle( 'margin-top' );
891 element.removeStyle( 'margin-bottom' );
892 }
893 }
894 },
895 {
896 id: 'cmbAlign',
897 requiredContent: 'img{float}',
898 type: 'select',
899 widths: [ '35%', '65%' ],
900 style: 'width:90px',
901 label: editor.lang.common.align,
902 'default': '',
903 items: [
904 [ editor.lang.common.notSet, '' ],
905 [ editor.lang.common.alignLeft, 'left' ],
906 [ editor.lang.common.alignRight, 'right' ]
907 // Backward compatible with v2 on setup when specified as attribute value,
908 // while these values are no more available as select options.
909 // [ editor.lang.image.alignAbsBottom , 'absBottom'],
910 // [ editor.lang.image.alignAbsMiddle , 'absMiddle'],
911 // [ editor.lang.image.alignBaseline , 'baseline'],
912 // [ editor.lang.image.alignTextTop , 'text-top'],
913 // [ editor.lang.image.alignBottom , 'bottom'],
914 // [ editor.lang.image.alignMiddle , 'middle'],
915 // [ editor.lang.image.alignTop , 'top']
916 ],
917 onChange: function() {
918 updatePreview( this.getDialog() );
919 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
920 },
921 setup: function( type, element ) {
922 if ( type == IMAGE ) {
923 var value = element.getStyle( 'float' );
924 switch ( value ) {
925 // Ignore those unrelated values.
926 case 'inherit':
927 case 'none':
928 value = '';
929 }
930
931 !value && ( value = ( element.getAttribute( 'align' ) || '' ).toLowerCase() );
932 this.setValue( value );
933 }
934 },
935 commit: function( type, element ) {
936 var value = this.getValue();
937 if ( type == IMAGE || type == PREVIEW ) {
938 if ( value )
939 element.setStyle( 'float', value );
940 else
941 element.removeStyle( 'float' );
942
943 if ( type == IMAGE ) {
944 value = ( element.getAttribute( 'align' ) || '' ).toLowerCase();
945 switch ( value ) {
946 // we should remove it only if it matches "left" or "right",
947 // otherwise leave it intact.
948 case 'left':
949 case 'right':
950 element.removeAttribute( 'align' );
951 }
952 }
953 } else if ( type == CLEANUP ) {
954 element.removeStyle( 'float' );
955 }
956 }
957 } ]
958 } ]
959 },
960 {
961 type: 'vbox',
962 height: '250px',
963 children: [ {
964 type: 'html',
965 id: 'htmlPreview',
966 style: 'width:95%;',
967 html: '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.common.preview ) + '<br>' +
968 '<div id="' + imagePreviewLoaderId + '" class="ImagePreviewLoader" style="display:none"><div class="loading">&nbsp;</div></div>' +
969 '<div class="ImagePreviewBox"><table><tr><td>' +
970 '<a href="javascript:void(0)" target="_blank" onclick="return false;" id="' + previewLinkId + '">' +
971 '<img id="' + previewImageId + '" alt="" /></a>' +
972 // jscs:disable maximumLineLength
973 ( editor.config.image_previewText || 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ' +
974 'Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, ' +
975 'nulla. Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris.' ) +
976 // jscs:enable maximumLineLength
977 '</td></tr></table></div></div>'
978 } ]
979 } ]
980 } ]
981 },
982 {
983 id: 'Link',
984 requiredContent: 'a[href]',
985 label: editor.lang.image.linkTab,
986 padding: 0,
987 elements: [ {
988 id: 'txtUrl',
989 type: 'text',
990 label: editor.lang.common.url,
991 style: 'width: 100%',
992 'default': '',
993 setup: function( type, element ) {
994 if ( type == LINK ) {
995 var href = element.data( 'cke-saved-href' );
996 if ( !href )
997 href = element.getAttribute( 'href' );
998 this.setValue( href );
999 }
1000 },
1001 commit: function( type, element ) {
1002 if ( type == LINK ) {
1003 if ( this.getValue() || this.isChanged() ) {
1004 var url = this.getValue();
1005 element.data( 'cke-saved-href', url );
1006 element.setAttribute( 'href', url );
1007
1008 if ( this.getValue() || !editor.config.image_removeLinkByEmptyURL )
1009 this.getDialog().addLink = true;
1010 else
1011 this.getDialog().addLink = false;
1012 }
1013 }
1014 }
1015 },
1016 {
1017 type: 'button',
1018 id: 'browse',
1019 className: 'cke_dialog_image_browse',
1020 filebrowser: {
1021 action: 'Browse',
1022 target: 'Link:txtUrl',
1023 url: editor.config.filebrowserImageBrowseLinkUrl
1024 },
1025 style: 'float:right',
1026 hidden: true,
1027 label: editor.lang.common.browseServer
1028 },
1029 {
1030 id: 'cmbTarget',
1031 type: 'select',
1032 requiredContent: 'a[target]',
1033 label: editor.lang.common.target,
1034 'default': '',
1035 items: [
1036 [ editor.lang.common.notSet, '' ],
1037 [ editor.lang.common.targetNew, '_blank' ],
1038 [ editor.lang.common.targetTop, '_top' ],
1039 [ editor.lang.common.targetSelf, '_self' ],
1040 [ editor.lang.common.targetParent, '_parent' ]
1041 ],
1042 setup: function( type, element ) {
1043 if ( type == LINK )
1044 this.setValue( element.getAttribute( 'target' ) || '' );
1045 },
1046 commit: function( type, element ) {
1047 if ( type == LINK ) {
1048 if ( this.getValue() || this.isChanged() )
1049 element.setAttribute( 'target', this.getValue() );
1050 }
1051 }
1052 } ]
1053 },
1054 {
1055 id: 'Upload',
1056 hidden: true,
1057 filebrowser: 'uploadButton',
1058 label: editor.lang.image.upload,
1059 elements: [ {
1060 type: 'file',
1061 id: 'upload',
1062 label: editor.lang.image.btnUpload,
1063 style: 'height:40px',
1064 size: 38
1065 },
1066 {
1067 type: 'fileButton',
1068 id: 'uploadButton',
1069 filebrowser: 'info:txtUrl',
1070 label: editor.lang.image.btnUpload,
1071 'for': [ 'Upload', 'upload' ]
1072 } ]
1073 },
1074 {
1075 id: 'advanced',
1076 label: editor.lang.common.advancedTab,
1077 elements: [ {
1078 type: 'hbox',
1079 widths: [ '50%', '25%', '25%' ],
1080 children: [ {
1081 type: 'text',
1082 id: 'linkId',
1083 requiredContent: 'img[id]',
1084 label: editor.lang.common.id,
1085 setup: function( type, element ) {
1086 if ( type == IMAGE )
1087 this.setValue( element.getAttribute( 'id' ) );
1088 },
1089 commit: function( type, element ) {
1090 if ( type == IMAGE ) {
1091 if ( this.getValue() || this.isChanged() )
1092 element.setAttribute( 'id', this.getValue() );
1093 }
1094 }
1095 },
1096 {
1097 id: 'cmbLangDir',
1098 type: 'select',
1099 requiredContent: 'img[dir]',
1100 style: 'width : 100px;',
1101 label: editor.lang.common.langDir,
1102 'default': '',
1103 items: [
1104 [ editor.lang.common.notSet, '' ],
1105 [ editor.lang.common.langDirLtr, 'ltr' ],
1106 [ editor.lang.common.langDirRtl, 'rtl' ]
1107 ],
1108 setup: function( type, element ) {
1109 if ( type == IMAGE )
1110 this.setValue( element.getAttribute( 'dir' ) );
1111 },
1112 commit: function( type, element ) {
1113 if ( type == IMAGE ) {
1114 if ( this.getValue() || this.isChanged() )
1115 element.setAttribute( 'dir', this.getValue() );
1116 }
1117 }
1118 },
1119 {
1120 type: 'text',
1121 id: 'txtLangCode',
1122 requiredContent: 'img[lang]',
1123 label: editor.lang.common.langCode,
1124 'default': '',
1125 setup: function( type, element ) {
1126 if ( type == IMAGE )
1127 this.setValue( element.getAttribute( 'lang' ) );
1128 },
1129 commit: function( type, element ) {
1130 if ( type == IMAGE ) {
1131 if ( this.getValue() || this.isChanged() )
1132 element.setAttribute( 'lang', this.getValue() );
1133 }
1134 }
1135 } ]
1136 },
1137 {
1138 type: 'text',
1139 id: 'txtGenLongDescr',
1140 requiredContent: 'img[longdesc]',
1141 label: editor.lang.common.longDescr,
1142 setup: function( type, element ) {
1143 if ( type == IMAGE )
1144 this.setValue( element.getAttribute( 'longDesc' ) );
1145 },
1146 commit: function( type, element ) {
1147 if ( type == IMAGE ) {
1148 if ( this.getValue() || this.isChanged() )
1149 element.setAttribute( 'longDesc', this.getValue() );
1150 }
1151 }
1152 },
1153 {
1154 type: 'hbox',
1155 widths: [ '50%', '50%' ],
1156 children: [ {
1157 type: 'text',
1158 id: 'txtGenClass',
1159 requiredContent: 'img(cke-xyz)', // Random text like 'xyz' will check if all are allowed.
1160 label: editor.lang.common.cssClass,
1161 'default': '',
1162 setup: function( type, element ) {
1163 if ( type == IMAGE )
1164 this.setValue( element.getAttribute( 'class' ) );
1165 },
1166 commit: function( type, element ) {
1167 if ( type == IMAGE ) {
1168 if ( this.getValue() || this.isChanged() )
1169 element.setAttribute( 'class', this.getValue() );
1170 }
1171 }
1172 },
1173 {
1174 type: 'text',
1175 id: 'txtGenTitle',
1176 requiredContent: 'img[title]',
1177 label: editor.lang.common.advisoryTitle,
1178 'default': '',
1179 onChange: function() {
1180 updatePreview( this.getDialog() );
1181 },
1182 setup: function( type, element ) {
1183 if ( type == IMAGE )
1184 this.setValue( element.getAttribute( 'title' ) );
1185 },
1186 commit: function( type, element ) {
1187 if ( type == IMAGE ) {
1188 if ( this.getValue() || this.isChanged() )
1189 element.setAttribute( 'title', this.getValue() );
1190 } else if ( type == PREVIEW )
1191 element.setAttribute( 'title', this.getValue() );
1192 else if ( type == CLEANUP ) {
1193 element.removeAttribute( 'title' );
1194 }
1195 }
1196 } ]
1197 },
1198 {
1199 type: 'text',
1200 id: 'txtdlgGenStyle',
1201 requiredContent: 'img{cke-xyz}', // Random text like 'xyz' will check if all are allowed.
1202 label: editor.lang.common.cssStyle,
1203 validate: CKEDITOR.dialog.validate.inlineStyle( editor.lang.common.invalidInlineStyle ),
1204 'default': '',
1205 setup: function( type, element ) {
1206 if ( type == IMAGE ) {
1207 var genStyle = element.getAttribute( 'style' );
1208 if ( !genStyle && element.$.style.cssText )
1209 genStyle = element.$.style.cssText;
1210 this.setValue( genStyle );
1211
1212 var height = element.$.style.height,
1213 width = element.$.style.width,
1214 aMatchH = ( height ? height : '' ).match( regexGetSize ),
1215 aMatchW = ( width ? width : '' ).match( regexGetSize );
1216
1217 this.attributesInStyle = {
1218 height: !!aMatchH,
1219 width: !!aMatchW
1220 };
1221 }
1222 },
1223 onChange: function() {
1224 commitInternally.call(
1225 this, [
1226 'info:cmbFloat',
1227 'info:cmbAlign',
1228 'info:txtVSpace',
1229 'info:txtHSpace',
1230 'info:txtBorder',
1231 'info:txtWidth',
1232 'info:txtHeight'
1233 ]
1234 );
1235 updatePreview( this );
1236 },
1237 commit: function( type, element ) {
1238 if ( type == IMAGE && ( this.getValue() || this.isChanged() ) )
1239 element.setAttribute( 'style', this.getValue() );
1240
1241 }
1242 } ]
1243 } ]
1244 };
1245 };
1246
1247 CKEDITOR.dialog.add( 'image', function( editor ) {
1248 return imageDialog( editor, 'image' );
1249 } );
1250
1251 CKEDITOR.dialog.add( 'imagebutton', function( editor ) {
1252 return imageDialog( editor, 'imagebutton' );
1253 } );
1254} )();
diff --git a/sources/plugins/image/icons/hidpi/image.png b/sources/plugins/image/icons/hidpi/image.png
new file mode 100644
index 0000000..d0f21ae
--- /dev/null
+++ b/sources/plugins/image/icons/hidpi/image.png
Binary files differ
diff --git a/sources/plugins/image/icons/image.png b/sources/plugins/image/icons/image.png
new file mode 100644
index 0000000..8ea9725
--- /dev/null
+++ b/sources/plugins/image/icons/image.png
Binary files differ
diff --git a/sources/plugins/image/images/noimage.png b/sources/plugins/image/images/noimage.png
new file mode 100644
index 0000000..74c6ee9
--- /dev/null
+++ b/sources/plugins/image/images/noimage.png
Binary files differ
diff --git a/sources/plugins/image/lang/af.js b/sources/plugins/image/lang/af.js
new file mode 100644
index 0000000..8cc5b5f
--- /dev/null
+++ b/sources/plugins/image/lang/af.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'af', {
6 alt: 'Alternatiewe teks',
7 border: 'Rand',
8 btnUpload: 'Stuur na bediener',
9 button2Img: 'Wil u die geselekteerde afbeeldingsknop vervang met \'n eenvoudige afbeelding?',
10 hSpace: 'HSpasie',
11 img2Button: 'Wil u die geselekteerde afbeelding vervang met \'n afbeeldingsknop?',
12 infoTab: 'Afbeelding informasie',
13 linkTab: 'Skakel',
14 lockRatio: 'Vaste proporsie',
15 menu: 'Afbeelding eienskappe',
16 resetSize: 'Herstel grootte',
17 title: 'Afbeelding eienskappe',
18 titleButton: 'Afbeeldingsknop eienskappe',
19 upload: 'Oplaai',
20 urlMissing: 'Die URL na die afbeelding ontbreek.',
21 vSpace: 'VSpasie',
22 validateBorder: 'Rand moet \'n heelgetal wees.',
23 validateHSpace: 'HSpasie moet \'n heelgetal wees.',
24 validateVSpace: 'VSpasie moet \'n heelgetal wees.'
25} );
diff --git a/sources/plugins/image/lang/ar.js b/sources/plugins/image/lang/ar.js
new file mode 100644
index 0000000..a755b3e
--- /dev/null
+++ b/sources/plugins/image/lang/ar.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ar', {
6 alt: 'عنوان الصورة',
7 border: 'سمك الحدود',
8 btnUpload: 'أرسلها للخادم',
9 button2Img: 'هل تريد تحويل زر الصورة المختار إلى صورة بسيطة؟',
10 hSpace: 'تباعد أفقي',
11 img2Button: 'هل تريد تحويل الصورة المختارة إلى زر صورة؟',
12 infoTab: 'معلومات الصورة',
13 linkTab: 'الرابط',
14 lockRatio: 'تناسق الحجم',
15 menu: 'خصائص الصورة',
16 resetSize: 'إستعادة الحجم الأصلي',
17 title: 'خصائص الصورة',
18 titleButton: 'خصائص زر الصورة',
19 upload: 'رفع',
20 urlMissing: 'عنوان مصدر الصورة مفقود',
21 vSpace: 'تباعد عمودي',
22 validateBorder: 'الإطار يجب أن يكون عددا',
23 validateHSpace: 'HSpace يجب أن يكون عدداً.',
24 validateVSpace: 'VSpace يجب أن يكون عدداً.'
25} );
diff --git a/sources/plugins/image/lang/az.js b/sources/plugins/image/lang/az.js
new file mode 100644
index 0000000..79009fa
--- /dev/null
+++ b/sources/plugins/image/lang/az.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'az', {
6 alt: 'Alternativ mətn',
7 border: 'Sərhəd',
8 btnUpload: 'Serverə yüklə',
9 button2Img: 'Şəkil tipli düyməni şəklə çevirmək istədiyinizə əminsinizmi?',
10 hSpace: 'Üfüqi boşluq',
11 img2Button: 'Şəkli şəkil tipli düyməyə çevirmək istədiyinizə əminsinizmi?',
12 infoTab: 'Şəkil haqqında məlumat',
13 linkTab: 'Link',
14 lockRatio: 'Ölçülərin uyğunluğu saxla',
15 menu: 'Şəklin seçimləri',
16 resetSize: 'Ölçüləri qaytar',
17 title: 'Şəklin seçimləri',
18 titleButton: 'Şəkil tipli düyməsinin seçimləri',
19 upload: 'Serverə yüklə',
20 urlMissing: 'Şəklin ünvanı yanlışdır.',
21 vSpace: 'Şaquli boşluq',
22 validateBorder: 'Sərhədin eni rəqəm olmalıdır.',
23 validateHSpace: 'Üfüqi boşluq rəqəm olmalıdır.',
24 validateVSpace: 'Şaquli boşluq rəqəm olmalıdır.'
25} );
diff --git a/sources/plugins/image/lang/bg.js b/sources/plugins/image/lang/bg.js
new file mode 100644
index 0000000..6c0b064
--- /dev/null
+++ b/sources/plugins/image/lang/bg.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'bg', {
6 alt: 'Алтернативен текст',
7 border: 'Рамка',
8 btnUpload: 'Изпрати я на сървъра',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'Хоризонтален отстъп',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Инфо за снимка',
13 linkTab: 'Връзка',
14 lockRatio: 'Заключване на съотношението',
15 menu: 'Настройки за снимка',
16 resetSize: 'Нулиране на размер',
17 title: 'Настройки за снимка',
18 titleButton: 'Настойки за бутон за снимка',
19 upload: 'Качване',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'Вертикален отстъп',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/bn.js b/sources/plugins/image/lang/bn.js
new file mode 100644
index 0000000..bbecfc6
--- /dev/null
+++ b/sources/plugins/image/lang/bn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'bn', {
6 alt: 'বিকল্প টেক্সট',
7 border: 'বর্ডার',
8 btnUpload: 'ইহাকে সার্ভারে প্রেরন কর',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'হরাইজন্টাল স্পেস',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'ছবির তথ্য',
13 linkTab: 'লিংক',
14 lockRatio: 'অনুপাত লক কর',
15 menu: 'ছবির প্রোপার্টি',
16 resetSize: 'সাইজ পূর্বাবস্থায় ফিরিয়ে দাও',
17 title: 'ছবির প্রোপার্টি',
18 titleButton: 'ছবির বাটন সম্বন্ধীয়',
19 upload: 'আপলোড',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'ভার্টিকেল স্পেস',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/bs.js b/sources/plugins/image/lang/bs.js
new file mode 100644
index 0000000..06dd8bf
--- /dev/null
+++ b/sources/plugins/image/lang/bs.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'bs', {
6 alt: 'Tekst na slici',
7 border: 'Okvir',
8 btnUpload: 'Šalji na server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Info slike',
13 linkTab: 'Link',
14 lockRatio: 'Zakljuèaj odnos',
15 menu: 'Svojstva slike',
16 resetSize: 'Resetuj dimenzije',
17 title: 'Svojstva slike',
18 titleButton: 'Image Button Properties', // MISSING
19 upload: 'Šalji',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'VSpace',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/ca.js b/sources/plugins/image/lang/ca.js
new file mode 100644
index 0000000..858013e
--- /dev/null
+++ b/sources/plugins/image/lang/ca.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ca', {
6 alt: 'Text alternatiu',
7 border: 'Vora',
8 btnUpload: 'Envia-la al servidor',
9 button2Img: 'Voleu transformar el botó d\'imatge seleccionat en una simple imatge?',
10 hSpace: 'Espaiat horit.',
11 img2Button: 'Voleu transformar la imatge seleccionada en un botó d\'imatge?',
12 infoTab: 'Informació de la imatge',
13 linkTab: 'Enllaç',
14 lockRatio: 'Bloqueja les proporcions',
15 menu: 'Propietats de la imatge',
16 resetSize: 'Restaura la mida',
17 title: 'Propietats de la imatge',
18 titleButton: 'Propietats del botó d\'imatge',
19 upload: 'Puja',
20 urlMissing: 'Falta la URL de la imatge.',
21 vSpace: 'Espaiat vert.',
22 validateBorder: 'La vora ha de ser un nombre enter.',
23 validateHSpace: 'HSpace ha de ser un nombre enter.',
24 validateVSpace: 'VSpace ha de ser un nombre enter.'
25} );
diff --git a/sources/plugins/image/lang/cs.js b/sources/plugins/image/lang/cs.js
new file mode 100644
index 0000000..a18a753
--- /dev/null
+++ b/sources/plugins/image/lang/cs.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'cs', {
6 alt: 'Alternativní text',
7 border: 'Okraje',
8 btnUpload: 'Odeslat na server',
9 button2Img: 'Skutečně chcete převést zvolené obrázkové tlačítko na obyčejný obrázek?',
10 hSpace: 'Horizontální mezera',
11 img2Button: 'Skutečně chcete převést zvolený obrázek na obrázkové tlačítko?',
12 infoTab: 'Informace o obrázku',
13 linkTab: 'Odkaz',
14 lockRatio: 'Zámek',
15 menu: 'Vlastnosti obrázku',
16 resetSize: 'Původní velikost',
17 title: 'Vlastnosti obrázku',
18 titleButton: 'Vlastností obrázkového tlačítka',
19 upload: 'Odeslat',
20 urlMissing: 'Zadané URL zdroje obrázku nebylo nalezeno.',
21 vSpace: 'Vertikální mezera',
22 validateBorder: 'Okraj musí být nastaven v celých číslech.',
23 validateHSpace: 'Horizontální mezera musí být nastavena v celých číslech.',
24 validateVSpace: 'Vertikální mezera musí být nastavena v celých číslech.'
25} );
diff --git a/sources/plugins/image/lang/cy.js b/sources/plugins/image/lang/cy.js
new file mode 100644
index 0000000..7407310
--- /dev/null
+++ b/sources/plugins/image/lang/cy.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'cy', {
6 alt: 'Testun Amgen',
7 border: 'Ymyl',
8 btnUpload: 'Anfon i\'r Gweinydd',
9 button2Img: 'Ydych am drawsffurfio\'r botwm ddelwedd hwn ar ddelwedd syml?',
10 hSpace: 'BwlchLl',
11 img2Button: 'Ydych am drawsffurfio\'r ddelwedd hon ar fotwm delwedd?',
12 infoTab: 'Gwyb Delwedd',
13 linkTab: 'Dolen',
14 lockRatio: 'Cloi Cymhareb',
15 menu: 'Priodweddau Delwedd',
16 resetSize: 'Ailosod Maint',
17 title: 'Priodweddau Delwedd',
18 titleButton: 'Priodweddau Botwm Delwedd',
19 upload: 'Lanlwytho',
20 urlMissing: 'URL gwreiddiol y ddelwedd ar goll.',
21 vSpace: 'BwlchF',
22 validateBorder: 'Rhaid i\'r ymyl fod yn gyfanrif.',
23 validateHSpace: 'Rhaid i\'r HSpace fod yn gyfanrif.',
24 validateVSpace: 'Rhaid i\'r VSpace fod yn gyfanrif.'
25} );
diff --git a/sources/plugins/image/lang/da.js b/sources/plugins/image/lang/da.js
new file mode 100644
index 0000000..bec69ba
--- /dev/null
+++ b/sources/plugins/image/lang/da.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'da', {
6 alt: 'Alternativ tekst',
7 border: 'Ramme',
8 btnUpload: 'Upload fil til serveren',
9 button2Img: 'Vil du lave billedknappen om til et almindeligt billede?',
10 hSpace: 'Vandret margen',
11 img2Button: 'Vil du lave billedet om til en billedknap?',
12 infoTab: 'Generelt',
13 linkTab: 'Hyperlink',
14 lockRatio: 'Lås størrelsesforhold',
15 menu: 'Egenskaber for billede',
16 resetSize: 'Nulstil størrelse',
17 title: 'Egenskaber for billede',
18 titleButton: 'Egenskaber for billedknap',
19 upload: 'Upload',
20 urlMissing: 'Kilde på billed-URL mangler',
21 vSpace: 'Lodret margen',
22 validateBorder: 'Kant skal være et helt nummer.',
23 validateHSpace: 'HSpace skal være et helt nummer.',
24 validateVSpace: 'VSpace skal være et helt nummer.'
25} );
diff --git a/sources/plugins/image/lang/de-ch.js b/sources/plugins/image/lang/de-ch.js
new file mode 100644
index 0000000..6ba1570
--- /dev/null
+++ b/sources/plugins/image/lang/de-ch.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'de-ch', {
6 alt: 'Alternativer Text',
7 border: 'Rahmen',
8 btnUpload: 'Zum Server senden',
9 button2Img: 'Möchten Sie die ausgewählte Bildschaltfläche in ein einfaches Bild umwandeln?',
10 hSpace: 'Horizontal-Abstand',
11 img2Button: 'Möchten Sie das ausgewählte Bild in eine Bildschaltfläche umwandeln?',
12 infoTab: 'Bildinfo',
13 linkTab: 'Link',
14 lockRatio: 'Grössenverhältnis beibehalten',
15 menu: 'Bildeigenschaften',
16 resetSize: 'Grösse zurücksetzen',
17 title: 'Bildeigenschaften',
18 titleButton: 'Bildschaltflächeneigenschaften',
19 upload: 'Hochladen',
20 urlMissing: 'Bildquellen-URL fehlt.',
21 vSpace: 'Vertikal-Abstand',
22 validateBorder: 'Rahmen muss eine ganze Zahl sein.',
23 validateHSpace: 'Horizontal-Abstand muss eine ganze Zahl sein.',
24 validateVSpace: 'Vertikal-Abstand muss eine ganze Zahl sein.'
25} );
diff --git a/sources/plugins/image/lang/de.js b/sources/plugins/image/lang/de.js
new file mode 100644
index 0000000..a391934
--- /dev/null
+++ b/sources/plugins/image/lang/de.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'de', {
6 alt: 'Alternativer Text',
7 border: 'Rahmen',
8 btnUpload: 'Zum Server senden',
9 button2Img: 'Möchten Sie die ausgewählte Bildschaltfläche in ein einfaches Bild umwandeln?',
10 hSpace: 'Horizontal-Abstand',
11 img2Button: 'Möchten Sie das ausgewählte Bild in eine Bildschaltfläche umwandeln?',
12 infoTab: 'Bildinfo',
13 linkTab: 'Link',
14 lockRatio: 'Größenverhältnis beibehalten',
15 menu: 'Bildeigenschaften',
16 resetSize: 'Größe zurücksetzen',
17 title: 'Bildeigenschaften',
18 titleButton: 'Bildschaltflächeneigenschaften',
19 upload: 'Hochladen',
20 urlMissing: 'Bildquellen-URL fehlt.',
21 vSpace: 'Vertikal-Abstand',
22 validateBorder: 'Rahmen muss eine ganze Zahl sein.',
23 validateHSpace: 'Horizontal-Abstand muss eine ganze Zahl sein.',
24 validateVSpace: 'Vertikal-Abstand muss eine ganze Zahl sein.'
25} );
diff --git a/sources/plugins/image/lang/el.js b/sources/plugins/image/lang/el.js
new file mode 100644
index 0000000..3453c3d
--- /dev/null
+++ b/sources/plugins/image/lang/el.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'el', {
6 alt: 'Εναλλακτικό Κείμενο',
7 border: 'Περίγραμμα',
8 btnUpload: 'Αποστολή στον Διακομιστή',
9 button2Img: 'Θέλετε να μετατρέψετε το επιλεγμένο κουμπί εικόνας σε απλή εικόνα;',
10 hSpace: 'HSpace',
11 img2Button: 'Θέλετε να μεταμορφώσετε την επιλεγμένη εικόνα που είναι πάνω σε ένα κουμπί;',
12 infoTab: 'Πληροφορίες Εικόνας',
13 linkTab: 'Σύνδεσμος',
14 lockRatio: 'Κλείδωμα Αναλογίας',
15 menu: 'Ιδιότητες Εικόνας',
16 resetSize: 'Επαναφορά Αρχικού Μεγέθους',
17 title: 'Ιδιότητες Εικόνας',
18 titleButton: 'Ιδιότητες Κουμπιού Εικόνας',
19 upload: 'Αποστολή',
20 urlMissing: 'Το URL πηγής για την εικόνα λείπει.',
21 vSpace: 'VSpace',
22 validateBorder: 'Το περίγραμμα πρέπει να είναι ένας ακέραιος αριθμός.',
23 validateHSpace: 'Το HSpace πρέπει να είναι ένας ακέραιος αριθμός.',
24 validateVSpace: 'Το VSpace πρέπει να είναι ένας ακέραιος αριθμός.'
25} );
diff --git a/sources/plugins/image/lang/en-au.js b/sources/plugins/image/lang/en-au.js
new file mode 100644
index 0000000..dba29c7
--- /dev/null
+++ b/sources/plugins/image/lang/en-au.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'en-au', {
6 alt: 'Alternative Text',
7 border: 'Border',
8 btnUpload: 'Send it to the Server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?',
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?',
12 infoTab: 'Image Info',
13 linkTab: 'Link',
14 lockRatio: 'Lock Ratio',
15 menu: 'Image Properties',
16 resetSize: 'Reset Size',
17 title: 'Image Properties',
18 titleButton: 'Image Button Properties',
19 upload: 'Upload',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'VSpace',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/en-ca.js b/sources/plugins/image/lang/en-ca.js
new file mode 100644
index 0000000..e78f83e
--- /dev/null
+++ b/sources/plugins/image/lang/en-ca.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'en-ca', {
6 alt: 'Alternative Text',
7 border: 'Border',
8 btnUpload: 'Send it to the Server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?',
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?',
12 infoTab: 'Image Info',
13 linkTab: 'Link',
14 lockRatio: 'Lock Ratio',
15 menu: 'Image Properties',
16 resetSize: 'Reset Size',
17 title: 'Image Properties',
18 titleButton: 'Image Button Properties',
19 upload: 'Upload',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'VSpace',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/en-gb.js b/sources/plugins/image/lang/en-gb.js
new file mode 100644
index 0000000..dcf335e
--- /dev/null
+++ b/sources/plugins/image/lang/en-gb.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'en-gb', {
6 alt: 'Alternative Text',
7 border: 'Border',
8 btnUpload: 'Send it to the Server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?',
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?',
12 infoTab: 'Image Info',
13 linkTab: 'Link',
14 lockRatio: 'Lock Ratio',
15 menu: 'Image Properties',
16 resetSize: 'Reset Size',
17 title: 'Image Properties',
18 titleButton: 'Image Button Properties',
19 upload: 'Upload',
20 urlMissing: 'Image source URL is missing.',
21 vSpace: 'VSpace',
22 validateBorder: 'Border must be a whole number.',
23 validateHSpace: 'HSpace must be a whole number.',
24 validateVSpace: 'VSpace must be a whole number.'
25} );
diff --git a/sources/plugins/image/lang/en.js b/sources/plugins/image/lang/en.js
new file mode 100644
index 0000000..4d0f50b
--- /dev/null
+++ b/sources/plugins/image/lang/en.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'en', {
6 alt: 'Alternative Text',
7 border: 'Border',
8 btnUpload: 'Send it to the Server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?',
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?',
12 infoTab: 'Image Info',
13 linkTab: 'Link',
14 lockRatio: 'Lock Ratio',
15 menu: 'Image Properties',
16 resetSize: 'Reset Size',
17 title: 'Image Properties',
18 titleButton: 'Image Button Properties',
19 upload: 'Upload',
20 urlMissing: 'Image source URL is missing.',
21 vSpace: 'VSpace',
22 validateBorder: 'Border must be a whole number.',
23 validateHSpace: 'HSpace must be a whole number.',
24 validateVSpace: 'VSpace must be a whole number.'
25} );
diff --git a/sources/plugins/image/lang/eo.js b/sources/plugins/image/lang/eo.js
new file mode 100644
index 0000000..276ef33
--- /dev/null
+++ b/sources/plugins/image/lang/eo.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'eo', {
6 alt: 'Anstataŭiga Teksto',
7 border: 'Bordero',
8 btnUpload: 'Sendu al Servilo',
9 button2Img: 'Ĉu vi volas transformi la selektitan bildbutonon en simplan bildon?',
10 hSpace: 'Horizontala Spaco',
11 img2Button: 'Ĉu vi volas transformi la selektitan bildon en bildbutonon?',
12 infoTab: 'Informoj pri Bildo',
13 linkTab: 'Ligilo',
14 lockRatio: 'Konservi Proporcion',
15 menu: 'Atributoj de Bildo',
16 resetSize: 'Origina Grando',
17 title: 'Atributoj de Bildo',
18 titleButton: 'Bildbutonaj Atributoj',
19 upload: 'Alŝuti',
20 urlMissing: 'La fontretadreso de la bildo mankas.',
21 vSpace: 'Vertikala Spaco',
22 validateBorder: 'La bordero devas esti entjera nombro.',
23 validateHSpace: 'La horizontala spaco devas esti entjera nombro.',
24 validateVSpace: 'La vertikala spaco devas esti entjera nombro.'
25} );
diff --git a/sources/plugins/image/lang/es.js b/sources/plugins/image/lang/es.js
new file mode 100644
index 0000000..1302a19
--- /dev/null
+++ b/sources/plugins/image/lang/es.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'es', {
6 alt: 'Texto Alternativo',
7 border: 'Borde',
8 btnUpload: 'Enviar al Servidor',
9 button2Img: '¿Desea convertir el botón de imagen en una simple imagen?',
10 hSpace: 'Esp.Horiz',
11 img2Button: '¿Desea convertir la imagen en un botón de imagen?',
12 infoTab: 'Información de Imagen',
13 linkTab: 'Vínculo',
14 lockRatio: 'Proporcional',
15 menu: 'Propiedades de Imagen',
16 resetSize: 'Tamaño Original',
17 title: 'Propiedades de Imagen',
18 titleButton: 'Propiedades de Botón de Imagen',
19 upload: 'Cargar',
20 urlMissing: 'Debe indicar la URL de la imagen.',
21 vSpace: 'Esp.Vert',
22 validateBorder: 'El borde debe ser un número.',
23 validateHSpace: 'El espaciado horizontal debe ser un número.',
24 validateVSpace: 'El espaciado vertical debe ser un número.'
25} );
diff --git a/sources/plugins/image/lang/et.js b/sources/plugins/image/lang/et.js
new file mode 100644
index 0000000..4c7153a
--- /dev/null
+++ b/sources/plugins/image/lang/et.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'et', {
6 alt: 'Alternatiivne tekst',
7 border: 'Joon',
8 btnUpload: 'Saada serverisse',
9 button2Img: 'Kas tahad teisendada valitud pildiga nupu tavaliseks pildiks?',
10 hSpace: 'H. vaheruum',
11 img2Button: 'Kas tahad teisendada valitud tavalise pildi pildiga nupuks?',
12 infoTab: 'Pildi info',
13 linkTab: 'Link',
14 lockRatio: 'Lukusta kuvasuhe',
15 menu: 'Pildi omadused',
16 resetSize: 'Lähtesta suurus',
17 title: 'Pildi omadused',
18 titleButton: 'Piltnupu omadused',
19 upload: 'Lae üles',
20 urlMissing: 'Pildi lähte-URL on puudu.',
21 vSpace: 'V. vaheruum',
22 validateBorder: 'Äärise laius peab olema täisarv.',
23 validateHSpace: 'Horisontaalne vaheruum peab olema täisarv.',
24 validateVSpace: 'Vertikaalne vaheruum peab olema täisarv.'
25} );
diff --git a/sources/plugins/image/lang/eu.js b/sources/plugins/image/lang/eu.js
new file mode 100644
index 0000000..52f8289
--- /dev/null
+++ b/sources/plugins/image/lang/eu.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'eu', {
6 alt: 'Ordezko testua',
7 border: 'Ertza',
8 btnUpload: 'Bidali zerbitzarira',
9 button2Img: 'Hautatutako irudi-botoia irudi arrunt bihurtu nahi duzu?',
10 hSpace: 'HSpace',
11 img2Button: 'Hautatutako irudia irudi-botoi bihurtu nahi duzu?',
12 infoTab: 'Irudiaren informazioa',
13 linkTab: 'Esteka',
14 lockRatio: 'Blokeatu erlazioa',
15 menu: 'Irudiaren propietateak',
16 resetSize: 'Berrezarri tamaina',
17 title: 'Irudiaren propietateak',
18 titleButton: 'Irudi-botoiaren propietateak',
19 upload: 'Kargatu',
20 urlMissing: 'Irudiaren iturburuaren URLa falta da.',
21 vSpace: 'VSpace',
22 validateBorder: 'Ertza zenbaki oso bat izan behar da.',
23 validateHSpace: 'HSpace zenbaki oso bat izan behar da.',
24 validateVSpace: 'VSpace zenbaki oso bat izan behar da.'
25} );
diff --git a/sources/plugins/image/lang/fa.js b/sources/plugins/image/lang/fa.js
new file mode 100644
index 0000000..6628e99
--- /dev/null
+++ b/sources/plugins/image/lang/fa.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'fa', {
6 alt: 'متن جایگزین',
7 border: 'لبه',
8 btnUpload: 'به سرور بفرست',
9 button2Img: 'آیا مایلید از یک تصویر ساده روی دکمه تصویری انتخاب شده استفاده کنید؟',
10 hSpace: 'فاصلهٴ افقی',
11 img2Button: 'آیا مایلید از یک دکمه تصویری روی تصویر انتخاب شده استفاده کنید؟',
12 infoTab: 'اطلاعات تصویر',
13 linkTab: 'پیوند',
14 lockRatio: 'قفل کردن نسبت',
15 menu: 'ویژگی​های تصویر',
16 resetSize: 'بازنشانی اندازه',
17 title: 'ویژگی​های تصویر',
18 titleButton: 'ویژگی​های دکمهٴ تصویری',
19 upload: 'انتقال به سرور',
20 urlMissing: 'آدرس URL اصلی تصویر یافت نشد.',
21 vSpace: 'فاصلهٴ عمودی',
22 validateBorder: 'مقدار خطوط باید یک عدد باشد.',
23 validateHSpace: 'مقدار فاصله گذاری افقی باید یک عدد باشد.',
24 validateVSpace: 'مقدار فاصله گذاری عمودی باید یک عدد باشد.'
25} );
diff --git a/sources/plugins/image/lang/fi.js b/sources/plugins/image/lang/fi.js
new file mode 100644
index 0000000..665b615
--- /dev/null
+++ b/sources/plugins/image/lang/fi.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'fi', {
6 alt: 'Vaihtoehtoinen teksti',
7 border: 'Kehys',
8 btnUpload: 'Lähetä palvelimelle',
9 button2Img: 'Haluatko muuntaa valitun kuvanäppäimen kuvaksi?',
10 hSpace: 'Vaakatila',
11 img2Button: 'Haluatko muuntaa valitun kuvan kuvanäppäimeksi?',
12 infoTab: 'Kuvan tiedot',
13 linkTab: 'Linkki',
14 lockRatio: 'Lukitse suhteet',
15 menu: 'Kuvan ominaisuudet',
16 resetSize: 'Alkuperäinen koko',
17 title: 'Kuvan ominaisuudet',
18 titleButton: 'Kuvapainikkeen ominaisuudet',
19 upload: 'Lisää kuva',
20 urlMissing: 'Kuvan lähdeosoite puuttuu.',
21 vSpace: 'Pystytila',
22 validateBorder: 'Kehyksen täytyy olla kokonaisluku.',
23 validateHSpace: 'HSpace-määrityksen täytyy olla kokonaisluku.',
24 validateVSpace: 'VSpace-määrityksen täytyy olla kokonaisluku.'
25} );
diff --git a/sources/plugins/image/lang/fo.js b/sources/plugins/image/lang/fo.js
new file mode 100644
index 0000000..8332a38
--- /dev/null
+++ b/sources/plugins/image/lang/fo.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'fo', {
6 alt: 'Alternativur tekstur',
7 border: 'Bordi',
8 btnUpload: 'Send til ambætaran',
9 button2Img: 'Skal valdi myndaknøttur gerast til vanliga mynd?',
10 hSpace: 'Høgri breddi',
11 img2Button: 'Skal valda mynd gerast til myndaknøtt?',
12 infoTab: 'Myndaupplýsingar',
13 linkTab: 'Tilknýti',
14 lockRatio: 'Læs lutfallið',
15 menu: 'Myndaeginleikar',
16 resetSize: 'Upprunastødd',
17 title: 'Myndaeginleikar',
18 titleButton: 'Eginleikar fyri myndaknøtt',
19 upload: 'Send',
20 urlMissing: 'URL til mynd manglar.',
21 vSpace: 'Vinstri breddi',
22 validateBorder: 'Bordi má vera eitt heiltal.',
23 validateHSpace: 'HSpace má vera eitt heiltal.',
24 validateVSpace: 'VSpace má vera eitt heiltal.'
25} );
diff --git a/sources/plugins/image/lang/fr-ca.js b/sources/plugins/image/lang/fr-ca.js
new file mode 100644
index 0000000..644a9f3
--- /dev/null
+++ b/sources/plugins/image/lang/fr-ca.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'fr-ca', {
6 alt: 'Texte alternatif',
7 border: 'Bordure',
8 btnUpload: 'Envoyer sur le serveur',
9 button2Img: 'Désirez-vous transformer l\'image sélectionnée en image simple?',
10 hSpace: 'Espacement horizontal',
11 img2Button: 'Désirez-vous transformer l\'image sélectionnée en bouton image?',
12 infoTab: 'Informations sur l\'image',
13 linkTab: 'Lien',
14 lockRatio: 'Verrouiller les proportions',
15 menu: 'Propriétés de l\'image',
16 resetSize: 'Taille originale',
17 title: 'Propriétés de l\'image',
18 titleButton: 'Propriétés du bouton image',
19 upload: 'Téléverser',
20 urlMissing: 'L\'URL de la source de l\'image est manquant.',
21 vSpace: 'Espacement vertical',
22 validateBorder: 'La bordure doit être un entier.',
23 validateHSpace: 'L\'espacement horizontal doit être un entier.',
24 validateVSpace: 'L\'espacement vertical doit être un entier.'
25} );
diff --git a/sources/plugins/image/lang/fr.js b/sources/plugins/image/lang/fr.js
new file mode 100644
index 0000000..299c379
--- /dev/null
+++ b/sources/plugins/image/lang/fr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'fr', {
6 alt: 'Texte alternatif',
7 border: 'Bordure',
8 btnUpload: 'Envoyer sur le serveur',
9 button2Img: 'Voulez-vous transformer le bouton avec image sélectionné en simple image ?',
10 hSpace: 'Espacement horizontal',
11 img2Button: 'Voulez-vous transformer l\'image sélectionnée en bouton avec image ?',
12 infoTab: 'Informations sur l\'image',
13 linkTab: 'Lien',
14 lockRatio: 'Conserver les proportions',
15 menu: 'Propriétés de l\'image',
16 resetSize: 'Réinitialiser la taille',
17 title: 'Propriétés de l\'image',
18 titleButton: 'Propriétés du bouton avec image',
19 upload: 'Téléverser',
20 urlMissing: 'L\'URL source de l\'image est manquante.',
21 vSpace: 'Espacement vertical',
22 validateBorder: 'La bordure doit être un nombre entier.',
23 validateHSpace: 'L\'espacement horizontal doit être un nombre entier.',
24 validateVSpace: 'L\'espacement vertical doit être un nombre entier.'
25} );
diff --git a/sources/plugins/image/lang/gl.js b/sources/plugins/image/lang/gl.js
new file mode 100644
index 0000000..ba632b8
--- /dev/null
+++ b/sources/plugins/image/lang/gl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'gl', {
6 alt: 'Texto alternativo',
7 border: 'Bordo',
8 btnUpload: 'Enviar ao servidor',
9 button2Img: 'Quere converter o botón da imaxe seleccionada nunha imaxe sinxela?',
10 hSpace: 'Esp.Horiz.',
11 img2Button: 'Quere converter a imaxe seleccionada nun botón de imaxe?',
12 infoTab: 'Información da imaxe',
13 linkTab: 'Ligazón',
14 lockRatio: 'Proporcional',
15 menu: 'Propiedades da imaxe',
16 resetSize: 'Tamaño orixinal',
17 title: 'Propiedades da imaxe',
18 titleButton: 'Propiedades do botón de imaxe',
19 upload: 'Cargar',
20 urlMissing: 'Non se atopa o URL da imaxe.',
21 vSpace: 'Esp.Vert.',
22 validateBorder: 'O bordo debe ser un número.',
23 validateHSpace: 'O espazado horizontal debe ser un número.',
24 validateVSpace: 'O espazado vertical debe ser un número.'
25} );
diff --git a/sources/plugins/image/lang/gu.js b/sources/plugins/image/lang/gu.js
new file mode 100644
index 0000000..f70ae28
--- /dev/null
+++ b/sources/plugins/image/lang/gu.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'gu', {
6 alt: 'ઑલ્ટર્નટ ટેક્સ્ટ',
7 border: 'બોર્ડર',
8 btnUpload: 'આ સર્વરને મોકલવું',
9 button2Img: 'તમારે ઈમેજ બટનને સાદી ઈમેજમાં બદલવું છે.',
10 hSpace: 'સમસ્તરીય જગ્યા',
11 img2Button: 'તમારે સાદી ઈમેજને ઈમેજ બટનમાં બદલવું છે.',
12 infoTab: 'ચિત્ર ની જાણકારી',
13 linkTab: 'લિંક',
14 lockRatio: 'લૉક ગુણોત્તર',
15 menu: 'ચિત્રના ગુણ',
16 resetSize: 'રીસેટ સાઇઝ',
17 title: 'ચિત્રના ગુણ',
18 titleButton: 'ચિત્ર બટનના ગુણ',
19 upload: 'અપલોડ',
20 urlMissing: 'ઈમેજની મૂળ URL છે નહી.',
21 vSpace: 'લંબરૂપ જગ્યા',
22 validateBorder: 'બોર્ડેર આંકડો હોવો જોઈએ.',
23 validateHSpace: 'HSpaceઆંકડો હોવો જોઈએ.',
24 validateVSpace: 'VSpace આંકડો હોવો જોઈએ. '
25} );
diff --git a/sources/plugins/image/lang/he.js b/sources/plugins/image/lang/he.js
new file mode 100644
index 0000000..41f207a
--- /dev/null
+++ b/sources/plugins/image/lang/he.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'he', {
6 alt: 'טקסט חלופי',
7 border: 'מסגרת',
8 btnUpload: 'שליחה לשרת',
9 button2Img: 'האם להפוך את תמונת הכפתור לתמונה פשוטה?',
10 hSpace: 'מרווח אופקי',
11 img2Button: 'האם להפוך את התמונה לכפתור תמונה?',
12 infoTab: 'מידע על התמונה',
13 linkTab: 'קישור',
14 lockRatio: 'נעילת היחס',
15 menu: 'תכונות התמונה',
16 resetSize: 'איפוס הגודל',
17 title: 'מאפייני התמונה',
18 titleButton: 'מאפיני כפתור תמונה',
19 upload: 'העלאה',
20 urlMissing: 'כתובת התמונה חסרה.',
21 vSpace: 'מרווח אנכי',
22 validateBorder: 'שדה המסגרת חייב להיות מספר שלם.',
23 validateHSpace: 'שדה המרווח האופקי חייב להיות מספר שלם.',
24 validateVSpace: 'שדה המרווח האנכי חייב להיות מספר שלם.'
25} );
diff --git a/sources/plugins/image/lang/hi.js b/sources/plugins/image/lang/hi.js
new file mode 100644
index 0000000..d4604b3
--- /dev/null
+++ b/sources/plugins/image/lang/hi.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'hi', {
6 alt: 'वैकल्पिक टेक्स्ट',
7 border: 'बॉर्डर',
8 btnUpload: 'इसे सर्वर को भेजें',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'हॉरिज़ॉन्टल स्पेस',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'तस्वीर की जानकारी',
13 linkTab: 'लिंक',
14 lockRatio: 'लॉक अनुपात',
15 menu: 'तस्वीर प्रॉपर्टीज़',
16 resetSize: 'रीसॅट साइज़',
17 title: 'तस्वीर प्रॉपर्टीज़',
18 titleButton: 'तस्वीर बटन प्रॉपर्टीज़',
19 upload: 'अपलोड',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'वर्टिकल स्पेस',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/hr.js b/sources/plugins/image/lang/hr.js
new file mode 100644
index 0000000..8c272eb
--- /dev/null
+++ b/sources/plugins/image/lang/hr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'hr', {
6 alt: 'Alternativni tekst',
7 border: 'Okvir',
8 btnUpload: 'Pošalji na server',
9 button2Img: 'Želite li promijeniti odabrani gumb u jednostavnu sliku?',
10 hSpace: 'HSpace',
11 img2Button: 'Želite li promijeniti odabranu sliku u gumb?',
12 infoTab: 'Info slike',
13 linkTab: 'Link',
14 lockRatio: 'Zaključaj odnos',
15 menu: 'Svojstva slika',
16 resetSize: 'Obriši veličinu',
17 title: 'Svojstva slika',
18 titleButton: 'Image Button svojstva',
19 upload: 'Pošalji',
20 urlMissing: 'Nedostaje URL slike.',
21 vSpace: 'VSpace',
22 validateBorder: 'Okvir mora biti cijeli broj.',
23 validateHSpace: 'HSpace mora biti cijeli broj',
24 validateVSpace: 'VSpace mora biti cijeli broj.'
25} );
diff --git a/sources/plugins/image/lang/hu.js b/sources/plugins/image/lang/hu.js
new file mode 100644
index 0000000..5a9e990
--- /dev/null
+++ b/sources/plugins/image/lang/hu.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'hu', {
6 alt: 'Alternatív szöveg',
7 border: 'Keret',
8 btnUpload: 'Küldés a szerverre',
9 button2Img: 'A kiválasztott képgombból sima képet szeretne csinálni?',
10 hSpace: 'Vízsz. táv',
11 img2Button: 'A kiválasztott képből képgombot szeretne csinálni?',
12 infoTab: 'Alaptulajdonságok',
13 linkTab: 'Hivatkozás',
14 lockRatio: 'Arány megtartása',
15 menu: 'Kép tulajdonságai',
16 resetSize: 'Eredeti méret',
17 title: 'Kép tulajdonságai',
18 titleButton: 'Képgomb tulajdonságai',
19 upload: 'Feltöltés',
20 urlMissing: 'Hiányzik a kép URL-je',
21 vSpace: 'Függ. táv',
22 validateBorder: 'A keret méretének egész számot kell beírni!',
23 validateHSpace: 'Vízszintes távolságnak egész számot kell beírni!',
24 validateVSpace: 'Függőleges távolságnak egész számot kell beírni!'
25} );
diff --git a/sources/plugins/image/lang/id.js b/sources/plugins/image/lang/id.js
new file mode 100644
index 0000000..8d27ad6
--- /dev/null
+++ b/sources/plugins/image/lang/id.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'id', {
6 alt: 'Teks alternatif',
7 border: 'Batas',
8 btnUpload: 'Kirim ke Server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'HSpace', // MISSING
11 img2Button: 'Apakah anda ingin mengubah gambar yang dipilih pada tombol gambar?',
12 infoTab: 'Info Gambar',
13 linkTab: 'Tautan',
14 lockRatio: 'Lock Ratio', // MISSING
15 menu: 'Image Properties', // MISSING
16 resetSize: 'Atur Ulang Ukuran',
17 title: 'Image Properties', // MISSING
18 titleButton: 'Image Button Properties', // MISSING
19 upload: 'Unggah',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'VSpace',
22 validateBorder: 'Border harus berupa angka',
23 validateHSpace: 'HSpace harus berupa angka',
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/is.js b/sources/plugins/image/lang/is.js
new file mode 100644
index 0000000..fc02308
--- /dev/null
+++ b/sources/plugins/image/lang/is.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'is', {
6 alt: 'Baklægur texti',
7 border: 'Rammi',
8 btnUpload: 'Hlaða upp',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'Vinstri bil',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Almennt',
13 linkTab: 'Stikla',
14 lockRatio: 'Festa stærðarhlutfall',
15 menu: 'Eigindi myndar',
16 resetSize: 'Reikna stærð',
17 title: 'Eigindi myndar',
18 titleButton: 'Eigindi myndahnapps',
19 upload: 'Hlaða upp',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'Hægri bil',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/it.js b/sources/plugins/image/lang/it.js
new file mode 100644
index 0000000..7b066ca
--- /dev/null
+++ b/sources/plugins/image/lang/it.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'it', {
6 alt: 'Testo alternativo',
7 border: 'Bordo',
8 btnUpload: 'Invia al server',
9 button2Img: 'Vuoi trasformare il bottone immagine selezionato in un\'immagine semplice?',
10 hSpace: 'HSpace',
11 img2Button: 'Vuoi trasferomare l\'immagine selezionata in un bottone immagine?',
12 infoTab: 'Informazioni immagine',
13 linkTab: 'Collegamento',
14 lockRatio: 'Blocca rapporto',
15 menu: 'Proprietà immagine',
16 resetSize: 'Reimposta dimensione',
17 title: 'Proprietà immagine',
18 titleButton: 'Proprietà bottone immagine',
19 upload: 'Carica',
20 urlMissing: 'Manca l\'URL dell\'immagine.',
21 vSpace: 'VSpace',
22 validateBorder: 'Il campo Bordo deve essere un numero intero.',
23 validateHSpace: 'Il campo HSpace deve essere un numero intero.',
24 validateVSpace: 'Il campo VSpace deve essere un numero intero.'
25} );
diff --git a/sources/plugins/image/lang/ja.js b/sources/plugins/image/lang/ja.js
new file mode 100644
index 0000000..a2d500c
--- /dev/null
+++ b/sources/plugins/image/lang/ja.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ja', {
6 alt: '代替テキスト',
7 border: '枠線の幅',
8 btnUpload: 'サーバーに送信',
9 button2Img: '選択した画像ボタンを画像に変換しますか?',
10 hSpace: '水平間隔',
11 img2Button: '選択した画像を画像ボタンに変換しますか?',
12 infoTab: '画像情報',
13 linkTab: 'リンク',
14 lockRatio: '比率を固定',
15 menu: '画像のプロパティ',
16 resetSize: 'サイズをリセット',
17 title: '画像のプロパティ',
18 titleButton: '画像ボタンのプロパティ',
19 upload: 'アップロード',
20 urlMissing: '画像のURLを入力してください。',
21 vSpace: '垂直間隔',
22 validateBorder: '枠線の幅は数値で入力してください。',
23 validateHSpace: '水平間隔は数値で入力してください。',
24 validateVSpace: '垂直間隔は数値で入力してください。'
25} );
diff --git a/sources/plugins/image/lang/ka.js b/sources/plugins/image/lang/ka.js
new file mode 100644
index 0000000..0a634f0
--- /dev/null
+++ b/sources/plugins/image/lang/ka.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ka', {
6 alt: 'სანაცვლო ტექსტი',
7 border: 'ჩარჩო',
8 btnUpload: 'სერვერისთვის გაგზავნა',
9 button2Img: 'გსურთ არჩეული სურათიანი ღილაკის გადაქცევა ჩვეულებრივ ღილაკად?',
10 hSpace: 'ჰორიზონტალური სივრცე',
11 img2Button: 'გსურთ არჩეული ჩვეულებრივი ღილაკის გადაქცევა სურათიან ღილაკად?',
12 infoTab: 'სურათის ინფორმცია',
13 linkTab: 'ბმული',
14 lockRatio: 'პროპორციის შენარჩუნება',
15 menu: 'სურათის პარამეტრები',
16 resetSize: 'ზომის დაბრუნება',
17 title: 'სურათის პარამეტრები',
18 titleButton: 'სურათიანი ღილაკის პარამეტრები',
19 upload: 'ატვირთვა',
20 urlMissing: 'სურათის URL არაა შევსებული.',
21 vSpace: 'ვერტიკალური სივრცე',
22 validateBorder: 'ჩარჩო მთელი რიცხვი უნდა იყოს.',
23 validateHSpace: 'ჰორიზონტალური სივრცე მთელი რიცხვი უნდა იყოს.',
24 validateVSpace: 'ვერტიკალური სივრცე მთელი რიცხვი უნდა იყოს.'
25} );
diff --git a/sources/plugins/image/lang/km.js b/sources/plugins/image/lang/km.js
new file mode 100644
index 0000000..d60562a
--- /dev/null
+++ b/sources/plugins/image/lang/km.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'km', {
6 alt: 'អត្ថបទជំនួស',
7 border: 'ស៊ុម',
8 btnUpload: 'ផ្ញើ​ទៅ​ម៉ាស៊ីន​បម្រើ',
9 button2Img: 'តើ​អ្នក​ចង់​ផ្លាស់​ប្ដូរ​ប៊ូតុង​រូបភាព​ដែល​បាន​ជ្រើស នៅ​លើ​រូបភាព​ធម្មតា​មួយ​មែនទេ?',
10 hSpace: 'គម្លាត​ផ្ដេក',
11 img2Button: 'តើ​អ្នក​ចង់​ផ្លាស់​ប្ដូរ​រូបភាព​ដែល​បាន​ជ្រើស នៅ​លើ​ប៊ូតុង​រូបភាព​មែនទេ?',
12 infoTab: 'ពត៌មានអំពីរូបភាព',
13 linkTab: 'តំណ',
14 lockRatio: 'ចាក់​សោ​ផល​ធៀប',
15 menu: 'លក្ខណៈ​រូបភាព',
16 resetSize: 'កំណត់ទំហំឡើងវិញ',
17 title: 'លក្ខណៈ​រូបភាព',
18 titleButton: 'លក្ខណៈ​ប៊ូតុង​រូបភាព',
19 upload: 'ផ្ទុកឡើង',
20 urlMissing: 'ខ្វះ URL ប្រភព​រូប​ភាព។',
21 vSpace: 'គម្លាត​បញ្ឈរ',
22 validateBorder: 'ស៊ុម​ត្រូវ​តែ​ជា​លេខ។',
23 validateHSpace: 'គម្លាត​ផ្ដេក​ត្រូវ​តែ​ជា​លេខ។',
24 validateVSpace: 'គម្លាត​បញ្ឈរ​ត្រូវ​តែ​ជា​លេខ។'
25} );
diff --git a/sources/plugins/image/lang/ko.js b/sources/plugins/image/lang/ko.js
new file mode 100644
index 0000000..75e5252
--- /dev/null
+++ b/sources/plugins/image/lang/ko.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ko', {
6 alt: '대체 문자열',
7 border: '테두리',
8 btnUpload: '서버로 전송',
9 button2Img: '단순 이미지에서 선택한 이미지 버튼을 변환하시겠습니까?',
10 hSpace: '가로 여백',
11 img2Button: '이미지 버튼에 선택한 이미지를 변환하시겠습니까?',
12 infoTab: '이미지 정보',
13 linkTab: '링크',
14 lockRatio: '비율 유지',
15 menu: '이미지 속성',
16 resetSize: '원래 크기로',
17 title: '이미지 속성',
18 titleButton: '이미지 버튼 속성',
19 upload: '업로드',
20 urlMissing: '이미지 원본 주소(URL)가 없습니다.',
21 vSpace: '세로 여백',
22 validateBorder: '테두리 두께는 정수여야 합니다.',
23 validateHSpace: '가로 길이는 정수여야 합니다.',
24 validateVSpace: '세로 길이는 정수여야 합니다.'
25} );
diff --git a/sources/plugins/image/lang/ku.js b/sources/plugins/image/lang/ku.js
new file mode 100644
index 0000000..2b70145
--- /dev/null
+++ b/sources/plugins/image/lang/ku.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ku', {
6 alt: 'جێگرەوەی دەق',
7 border: 'پەراوێز',
8 btnUpload: 'ناردنی بۆ ڕاژه',
9 button2Img: 'تۆ دەتەوێت دوگمەی وێنەی دیاریکراو بگۆڕیت بۆ وێنەیەکی ئاسایی؟',
10 hSpace: 'بۆشایی ئاسۆیی',
11 img2Button: 'تۆ دەتەوێت وێنەی دیاریکراو بگۆڕیت بۆ دوگمەی وێنه؟',
12 infoTab: 'زانیاری وێنه',
13 linkTab: 'بەستەر',
14 lockRatio: 'داخستنی ڕێژه',
15 menu: 'خاسیەتی وێنه',
16 resetSize: 'ڕێکخستنەوەی قەباره',
17 title: 'خاسیەتی وێنه',
18 titleButton: 'خاسیەتی دوگمەی وێنه',
19 upload: 'بارکردن',
20 urlMissing: 'سەرچاوەی بەستەری وێنه بزره',
21 vSpace: 'بۆشایی ئەستونی',
22 validateBorder: 'پەراوێز دەبێت بەتەواوی تەنها ژماره بێت.',
23 validateHSpace: 'بۆشایی ئاسۆیی دەبێت بەتەواوی تەنها ژمارە بێت.',
24 validateVSpace: 'بۆشایی ئەستونی دەبێت بەتەواوی تەنها ژماره بێت.'
25} );
diff --git a/sources/plugins/image/lang/lt.js b/sources/plugins/image/lang/lt.js
new file mode 100644
index 0000000..2343934
--- /dev/null
+++ b/sources/plugins/image/lang/lt.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'lt', {
6 alt: 'Alternatyvus Tekstas',
7 border: 'Rėmelis',
8 btnUpload: 'Siųsti į serverį',
9 button2Img: 'Ar norite mygtuką paversti paprastu paveiksliuku?',
10 hSpace: 'Hor.Erdvė',
11 img2Button: 'Ar norite paveiksliuką paversti mygtuku?',
12 infoTab: 'Vaizdo informacija',
13 linkTab: 'Nuoroda',
14 lockRatio: 'Išlaikyti proporciją',
15 menu: 'Vaizdo savybės',
16 resetSize: 'Atstatyti dydį',
17 title: 'Vaizdo savybės',
18 titleButton: 'Vaizdinio mygtuko savybės',
19 upload: 'Nusiųsti',
20 urlMissing: 'Paveiksliuko nuorodos nėra.',
21 vSpace: 'Vert.Erdvė',
22 validateBorder: 'Reikšmė turi būti sveikas skaičius.',
23 validateHSpace: 'Reikšmė turi būti sveikas skaičius.',
24 validateVSpace: 'Reikšmė turi būti sveikas skaičius.'
25} );
diff --git a/sources/plugins/image/lang/lv.js b/sources/plugins/image/lang/lv.js
new file mode 100644
index 0000000..cf20166
--- /dev/null
+++ b/sources/plugins/image/lang/lv.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'lv', {
6 alt: 'Alternatīvais teksts',
7 border: 'Rāmis',
8 btnUpload: 'Nosūtīt serverim',
9 button2Img: 'Vai vēlaties pārveidot izvēlēto attēla pogu uz attēla?',
10 hSpace: 'Horizontālā telpa',
11 img2Button: 'Vai vēlaties pārveidot izvēlēto attēlu uz attēla pogas?',
12 infoTab: 'Informācija par attēlu',
13 linkTab: 'Hipersaite',
14 lockRatio: 'Nemainīga Augstuma/Platuma attiecība',
15 menu: 'Attēla īpašības',
16 resetSize: 'Atjaunot sākotnējo izmēru',
17 title: 'Attēla īpašības',
18 titleButton: 'Attēlpogas īpašības',
19 upload: 'Augšupielādēt',
20 urlMissing: 'Trūkst attēla atrašanās adrese.',
21 vSpace: 'Vertikālā telpa',
22 validateBorder: 'Apmalei jābūt veselam skaitlim',
23 validateHSpace: 'HSpace jābūt veselam skaitlim',
24 validateVSpace: 'VSpace jābūt veselam skaitlim'
25} );
diff --git a/sources/plugins/image/lang/mk.js b/sources/plugins/image/lang/mk.js
new file mode 100644
index 0000000..9dd01cc
--- /dev/null
+++ b/sources/plugins/image/lang/mk.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'mk', {
6 alt: 'Алтернативен текст',
7 border: 'Раб',
8 btnUpload: 'Прикачи на сервер',
9 button2Img: 'Дали сакате да направите сликата-копче да биде само слика?',
10 hSpace: 'Хоризонтален простор',
11 img2Button: 'Дали сакате да ја претворите сликата во слика-копче?',
12 infoTab: 'Информации за сликата',
13 linkTab: 'Врска',
14 lockRatio: 'Зачувај пропорција',
15 menu: 'Својства на сликата',
16 resetSize: 'Ресетирај големина',
17 title: 'Својства на сликата',
18 titleButton: 'Својства на копче-сликата',
19 upload: 'Прикачи',
20 urlMissing: 'Недостасува URL-то на сликата.',
21 vSpace: 'Вертикален простор',
22 validateBorder: 'Работ мора да биде цел број.',
23 validateHSpace: 'Хор. простор мора да биде цел број.',
24 validateVSpace: 'Верт. простор мора да биде цел број.'
25} );
diff --git a/sources/plugins/image/lang/mn.js b/sources/plugins/image/lang/mn.js
new file mode 100644
index 0000000..4daf38a
--- /dev/null
+++ b/sources/plugins/image/lang/mn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'mn', {
6 alt: 'Зургийг орлох бичвэр',
7 border: 'Хүрээ',
8 btnUpload: 'Үүнийг сервэррүү илгээ',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'Хөндлөн зай',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Зурагны мэдээлэл',
13 linkTab: 'Холбоос',
14 lockRatio: 'Радио түгжих',
15 menu: 'Зураг',
16 resetSize: 'хэмжээ дахин оноох',
17 title: 'Зураг',
18 titleButton: 'Зурган товчны шинж чанар',
19 upload: 'Хуулах',
20 urlMissing: 'Зургийн эх сурвалжийн хаяг (URL) байхгүй байна.',
21 vSpace: 'Босоо зай',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/ms.js b/sources/plugins/image/lang/ms.js
new file mode 100644
index 0000000..28511d0
--- /dev/null
+++ b/sources/plugins/image/lang/ms.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ms', {
6 alt: 'Text Alternatif',
7 border: 'Border',
8 btnUpload: 'Hantar ke Server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'Ruang Melintang',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Info Imej',
13 linkTab: 'Sambungan',
14 lockRatio: 'Tetapkan Nisbah',
15 menu: 'Ciri-ciri Imej',
16 resetSize: 'Saiz Set Semula',
17 title: 'Ciri-ciri Imej',
18 titleButton: 'Ciri-ciri Butang Bergambar',
19 upload: 'Muat Naik',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'Ruang Menegak',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/nb.js b/sources/plugins/image/lang/nb.js
new file mode 100644
index 0000000..87208af
--- /dev/null
+++ b/sources/plugins/image/lang/nb.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'nb', {
6 alt: 'Alternativ tekst',
7 border: 'Ramme',
8 btnUpload: 'Send det til serveren',
9 button2Img: 'Vil du endre den valgte bildeknappen til et vanlig bilde?',
10 hSpace: 'HMarg',
11 img2Button: 'Vil du endre det valgte bildet til en bildeknapp?',
12 infoTab: 'Bildeinformasjon',
13 linkTab: 'Lenke',
14 lockRatio: 'Lås forhold',
15 menu: 'Bildeegenskaper',
16 resetSize: 'Tilbakestill størrelse',
17 title: 'Bildeegenskaper',
18 titleButton: 'Egenskaper for bildeknapp',
19 upload: 'Last opp',
20 urlMissing: 'Bildets adresse mangler.',
21 vSpace: 'VMarg',
22 validateBorder: 'Ramme må være et heltall.',
23 validateHSpace: 'HMarg må være et heltall.',
24 validateVSpace: 'VMarg må være et heltall.'
25} );
diff --git a/sources/plugins/image/lang/nl.js b/sources/plugins/image/lang/nl.js
new file mode 100644
index 0000000..bbe4943
--- /dev/null
+++ b/sources/plugins/image/lang/nl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'nl', {
6 alt: 'Alternatieve tekst',
7 border: 'Rand',
8 btnUpload: 'Naar server verzenden',
9 button2Img: 'Wilt u de geselecteerde afbeeldingsknop vervangen door een eenvoudige afbeelding?',
10 hSpace: 'HSpace',
11 img2Button: 'Wilt u de geselecteerde afbeelding vervangen door een afbeeldingsknop?',
12 infoTab: 'Informatie afbeelding',
13 linkTab: 'Link',
14 lockRatio: 'Afmetingen vergrendelen',
15 menu: 'Eigenschappen afbeelding',
16 resetSize: 'Afmetingen resetten',
17 title: 'Eigenschappen afbeelding',
18 titleButton: 'Eigenschappen afbeeldingsknop',
19 upload: 'Upload',
20 urlMissing: 'De URL naar de afbeelding ontbreekt.',
21 vSpace: 'VSpace',
22 validateBorder: 'Rand moet een heel nummer zijn.',
23 validateHSpace: 'HSpace moet een heel nummer zijn.',
24 validateVSpace: 'VSpace moet een heel nummer zijn.'
25} );
diff --git a/sources/plugins/image/lang/no.js b/sources/plugins/image/lang/no.js
new file mode 100644
index 0000000..9d4898a
--- /dev/null
+++ b/sources/plugins/image/lang/no.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'no', {
6 alt: 'Alternativ tekst',
7 border: 'Ramme',
8 btnUpload: 'Send det til serveren',
9 button2Img: 'Vil du endre den valgte bildeknappen til et vanlig bilde?',
10 hSpace: 'HMarg',
11 img2Button: 'Vil du endre det valgte bildet til en bildeknapp?',
12 infoTab: 'Bildeinformasjon',
13 linkTab: 'Lenke',
14 lockRatio: 'Lås forhold',
15 menu: 'Bildeegenskaper',
16 resetSize: 'Tilbakestill størrelse',
17 title: 'Bildeegenskaper',
18 titleButton: 'Egenskaper for bildeknapp',
19 upload: 'Last opp',
20 urlMissing: 'Bildets adresse mangler.',
21 vSpace: 'VMarg',
22 validateBorder: 'Ramme må være et heltall.',
23 validateHSpace: 'HMarg må være et heltall.',
24 validateVSpace: 'VMarg må være et heltall.'
25} );
diff --git a/sources/plugins/image/lang/oc.js b/sources/plugins/image/lang/oc.js
new file mode 100644
index 0000000..fa595c6
--- /dev/null
+++ b/sources/plugins/image/lang/oc.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'oc', {
6 alt: 'Tèxte alternatiu',
7 border: 'Bordadura',
8 btnUpload: 'Mandar sul servidor',
9 button2Img: 'Volètz transformar lo boton amb imatge seleccionat en imatge simple ?',
10 hSpace: 'Espaçament orizontal',
11 img2Button: 'Volètz transformar l\'imatge seleccionat en boton amb imatge ?',
12 infoTab: 'Informacions sus l\'imatge',
13 linkTab: 'Ligam',
14 lockRatio: 'Conservar las proporcions',
15 menu: 'Proprietats de l\'imatge',
16 resetSize: 'Reïnicializar la talha',
17 title: 'Proprietats de l\'imatge',
18 titleButton: 'Proprietats del boton amb imatge',
19 upload: 'Mandar',
20 urlMissing: 'L\'URL font de l\'imatge es mancanta.',
21 vSpace: 'Espaçament vertical',
22 validateBorder: 'La bordadura deu èsser un nombre entièr.',
23 validateHSpace: 'L\'espaçament orizontal deu èsser un nombre entièr.',
24 validateVSpace: 'L\'espaçament vertical deu èsser un nombre entièr.'
25} );
diff --git a/sources/plugins/image/lang/pl.js b/sources/plugins/image/lang/pl.js
new file mode 100644
index 0000000..93afb85
--- /dev/null
+++ b/sources/plugins/image/lang/pl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'pl', {
6 alt: 'Tekst zastępczy',
7 border: 'Obramowanie',
8 btnUpload: 'Wyślij',
9 button2Img: 'Czy chcesz przekonwertować zaznaczony przycisk graficzny do zwykłego obrazka?',
10 hSpace: 'Odstęp poziomy',
11 img2Button: 'Czy chcesz przekonwertować zaznaczony obrazek do przycisku graficznego?',
12 infoTab: 'Informacje o obrazku',
13 linkTab: 'Hiperłącze',
14 lockRatio: 'Zablokuj proporcje',
15 menu: 'Właściwości obrazka',
16 resetSize: 'Przywróć rozmiar',
17 title: 'Właściwości obrazka',
18 titleButton: 'Właściwości przycisku graficznego',
19 upload: 'Wyślij',
20 urlMissing: 'Podaj adres URL obrazka.',
21 vSpace: 'Odstęp pionowy',
22 validateBorder: 'Wartość obramowania musi być liczbą całkowitą.',
23 validateHSpace: 'Wartość odstępu poziomego musi być liczbą całkowitą.',
24 validateVSpace: 'Wartość odstępu pionowego musi być liczbą całkowitą.'
25} );
diff --git a/sources/plugins/image/lang/pt-br.js b/sources/plugins/image/lang/pt-br.js
new file mode 100644
index 0000000..0d13a9a
--- /dev/null
+++ b/sources/plugins/image/lang/pt-br.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'pt-br', {
6 alt: 'Texto Alternativo',
7 border: 'Borda',
8 btnUpload: 'Enviar para o Servidor',
9 button2Img: 'Deseja transformar o botão de imagem em uma imagem comum?',
10 hSpace: 'HSpace',
11 img2Button: 'Deseja transformar a imagem em um botão de imagem?',
12 infoTab: 'Informações da Imagem',
13 linkTab: 'Link',
14 lockRatio: 'Travar Proporções',
15 menu: 'Formatar Imagem',
16 resetSize: 'Redefinir para o Tamanho Original',
17 title: 'Formatar Imagem',
18 titleButton: 'Formatar Botão de Imagem',
19 upload: 'Enviar',
20 urlMissing: 'URL da imagem está faltando.',
21 vSpace: 'VSpace',
22 validateBorder: 'A borda deve ser um número inteiro.',
23 validateHSpace: 'O HSpace deve ser um número inteiro.',
24 validateVSpace: 'O VSpace deve ser um número inteiro.'
25} );
diff --git a/sources/plugins/image/lang/pt.js b/sources/plugins/image/lang/pt.js
new file mode 100644
index 0000000..2b8f50c
--- /dev/null
+++ b/sources/plugins/image/lang/pt.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'pt', {
6 alt: 'Texto alternativo',
7 border: 'Limite',
8 btnUpload: 'Enviar para o servidor',
9 button2Img: 'Deseja transformar o botão com imagem selecionado em uma imagem?',
10 hSpace: 'Esp. Horiz',
11 img2Button: 'Deseja transformar a imagem selecionada em um botão com imagem?',
12 infoTab: 'Informação da imagem',
13 linkTab: 'Hiperligação',
14 lockRatio: 'Proporcional',
15 menu: 'Propriedades da Imagem',
16 resetSize: 'Tamanho original',
17 title: 'Propriedades da imagem',
18 titleButton: 'Propriedades do botão de imagem',
19 upload: 'Carregar',
20 urlMissing: 'O URL da fonte da imagem está em falta.',
21 vSpace: 'Esp. Vert',
22 validateBorder: 'A borda tem de ser um numero.',
23 validateHSpace: 'HSpace tem de ser um numero.',
24 validateVSpace: 'VSpace tem de ser um numero.'
25} );
diff --git a/sources/plugins/image/lang/ro.js b/sources/plugins/image/lang/ro.js
new file mode 100644
index 0000000..067dee2
--- /dev/null
+++ b/sources/plugins/image/lang/ro.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ro', {
6 alt: 'Text alternativ',
7 border: 'Margine',
8 btnUpload: 'Trimite la server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Informaţii despre imagine',
13 linkTab: 'Link (Legătură web)',
14 lockRatio: 'Păstrează proporţiile',
15 menu: 'Proprietăţile imaginii',
16 resetSize: 'Resetează mărimea',
17 title: 'Proprietăţile imaginii',
18 titleButton: 'Proprietăţi buton imagine (Image Button)',
19 upload: 'Încarcă',
20 urlMissing: 'Sursa URL a imaginii lipsește.',
21 vSpace: 'VSpace',
22 validateBorder: 'Bordura trebuie să fie un număr întreg.',
23 validateHSpace: 'Hspace trebuie să fie un număr întreg.',
24 validateVSpace: 'Vspace trebuie să fie un număr întreg.'
25} );
diff --git a/sources/plugins/image/lang/ru.js b/sources/plugins/image/lang/ru.js
new file mode 100644
index 0000000..cb937c9
--- /dev/null
+++ b/sources/plugins/image/lang/ru.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ru', {
6 alt: 'Альтернативный текст',
7 border: 'Граница',
8 btnUpload: 'Загрузить на сервер',
9 button2Img: 'Вы желаете преобразовать это изображение-кнопку в обычное изображение?',
10 hSpace: 'Гориз. отступ',
11 img2Button: 'Вы желаете преобразовать это обычное изображение в изображение-кнопку?',
12 infoTab: 'Данные об изображении',
13 linkTab: 'Ссылка',
14 lockRatio: 'Сохранять пропорции',
15 menu: 'Свойства изображения',
16 resetSize: 'Вернуть обычные размеры',
17 title: 'Свойства изображения',
18 titleButton: 'Свойства изображения-кнопки',
19 upload: 'Загрузить',
20 urlMissing: 'Не указана ссылка на изображение.',
21 vSpace: 'Вертик. отступ',
22 validateBorder: 'Размер границ должен быть задан числом.',
23 validateHSpace: 'Горизонтальный отступ должен быть задан числом.',
24 validateVSpace: 'Вертикальный отступ должен быть задан числом.'
25} );
diff --git a/sources/plugins/image/lang/si.js b/sources/plugins/image/lang/si.js
new file mode 100644
index 0000000..84cbace
--- /dev/null
+++ b/sources/plugins/image/lang/si.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'si', {
6 alt: 'විකල්ප ',
7 border: 'සීමාවවල ',
8 btnUpload: 'සේවාදායකය වෙත යොමුකිරිම',
9 button2Img: 'ඔබට තෝරන ලද රුපය පරිවර්තනය කිරීමට අවශ්‍යද?',
10 hSpace: 'HSpace',
11 img2Button: 'ඔබට තෝරන ලද රුපය පරිවර්තනය කිරීමට අවශ්‍යද?',
12 infoTab: 'රුපයේ තොරතුරු',
13 linkTab: 'සබැඳිය',
14 lockRatio: 'නවතන අනුපාතය ',
15 menu: 'රුපයේ ගුණ',
16 resetSize: 'නැවතත් විශාලත්වය වෙනස් කිරීම',
17 title: 'රුපයේ ',
18 titleButton: 'රුප බොත්තමේ ගුණ',
19 upload: 'උඩුගතකිරීම',
20 urlMissing: 'රුප මුලාශ්‍ර URL නැත.',
21 vSpace: 'VSpace',
22 validateBorder: 'මාඉම් සම්පුර්ණ සංක්‍යාවක් විය යුතුය.',
23 validateHSpace: 'HSpace සම්පුර්ණ සංක්‍යාවක් විය යුතුය',
24 validateVSpace: 'VSpace සම්පුර්ණ සංක්‍යාවක් විය යුතුය.'
25} );
diff --git a/sources/plugins/image/lang/sk.js b/sources/plugins/image/lang/sk.js
new file mode 100644
index 0000000..38bc38a
--- /dev/null
+++ b/sources/plugins/image/lang/sk.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'sk', {
6 alt: 'Alternatívny text',
7 border: 'Rám (border)',
8 btnUpload: 'Odoslať to na server',
9 button2Img: 'Chcete zmeniť vybrané obrázkové tlačidlo na jednoduchý obrázok?',
10 hSpace: 'H-medzera',
11 img2Button: 'Chcete zmeniť vybraný obrázok na obrázkové tlačidlo?',
12 infoTab: 'Informácie o obrázku',
13 linkTab: 'Odkaz',
14 lockRatio: 'Pomer zámky',
15 menu: 'Vlastnosti obrázka',
16 resetSize: 'Pôvodná veľkosť',
17 title: 'Vlastnosti obrázka',
18 titleButton: 'Vlastnosti obrázkového tlačidla',
19 upload: 'Nahrať',
20 urlMissing: 'Chýba URL zdroja obrázka.',
21 vSpace: 'V-medzera',
22 validateBorder: 'Rám (border) musí byť celé číslo.',
23 validateHSpace: 'H-medzera musí byť celé číslo.',
24 validateVSpace: 'V-medzera musí byť celé číslo.'
25} );
diff --git a/sources/plugins/image/lang/sl.js b/sources/plugins/image/lang/sl.js
new file mode 100644
index 0000000..29c440f
--- /dev/null
+++ b/sources/plugins/image/lang/sl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'sl', {
6 alt: 'Nadomestno besedilo',
7 border: 'Obroba',
8 btnUpload: 'Pošlji na strežnik',
9 button2Img: 'Želite pretvoriti izbrani gumb s sliko v preprosto sliko?',
10 hSpace: 'Vodoravni odmik',
11 img2Button: 'Želite pretvoriti izbrano sliko v gumb s sliko?',
12 infoTab: 'Podatki o sliki',
13 linkTab: 'Povezava',
14 lockRatio: 'Zakleni razmerje',
15 menu: 'Lastnosti slike',
16 resetSize: 'Ponastavi velikost',
17 title: 'Lastnosti slike',
18 titleButton: 'Lastnosti gumba s sliko',
19 upload: 'Naloži',
20 urlMissing: 'Manjka URL vira slike.',
21 vSpace: 'Navpični odmik',
22 validateBorder: 'Meja mora biti celo število.',
23 validateHSpace: 'Vodoravni odmik mora biti celo število.',
24 validateVSpace: 'VSpace mora biti celo število.'
25} );
diff --git a/sources/plugins/image/lang/sq.js b/sources/plugins/image/lang/sq.js
new file mode 100644
index 0000000..072a96d
--- /dev/null
+++ b/sources/plugins/image/lang/sq.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'sq', {
6 alt: 'Tekst Alternativ',
7 border: 'Korniza',
8 btnUpload: 'Dërgo në server',
9 button2Img: 'Dëshironi të e ndërroni pullën e fotos së selektuar në një foto të thjeshtë?',
10 hSpace: 'HSpace',
11 img2Button: 'Dëshironi të ndryshoni foton e përzgjedhur në pullë?',
12 infoTab: 'Informacione mbi Fotografinë',
13 linkTab: 'Nyja',
14 lockRatio: 'Mbyll Racionin',
15 menu: 'Karakteristikat e Fotografisë',
16 resetSize: 'Rikthe Madhësinë',
17 title: 'Karakteristikat e Fotografisë',
18 titleButton: 'Karakteristikat e Pullës së Fotografisë',
19 upload: 'Ngarko',
20 urlMissing: 'Mungon URL e burimit të fotografisë.',
21 vSpace: 'Hapësira Vertikale',
22 validateBorder: 'Korniza duhet të jetë numër i plotë.',
23 validateHSpace: 'Hapësira horizontale duhet të jetë numër i plotë.',
24 validateVSpace: 'Hapësira vertikale duhet të jetë numër i plotë.'
25} );
diff --git a/sources/plugins/image/lang/sr-latn.js b/sources/plugins/image/lang/sr-latn.js
new file mode 100644
index 0000000..b3c2a98
--- /dev/null
+++ b/sources/plugins/image/lang/sr-latn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'sr-latn', {
6 alt: 'Alternativni tekst',
7 border: 'Okvir',
8 btnUpload: 'Pošalji na server',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'HSpace',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Info slike',
13 linkTab: 'Link',
14 lockRatio: 'Zaključaj odnos',
15 menu: 'Osobine slika',
16 resetSize: 'Resetuj veličinu',
17 title: 'Osobine slika',
18 titleButton: 'Osobine dugmeta sa slikom',
19 upload: 'Pošalji',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'VSpace',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/sr.js b/sources/plugins/image/lang/sr.js
new file mode 100644
index 0000000..4a269d9
--- /dev/null
+++ b/sources/plugins/image/lang/sr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'sr', {
6 alt: 'Алтернативни текст',
7 border: 'Оквир',
8 btnUpload: 'Пошаљи на сервер',
9 button2Img: 'Да ли желите да промените одабрану слику дугмета као једноставну слику?',
10 hSpace: 'HSpace',
11 img2Button: 'Да ли желите да промените одабрану слику у слику дугмета?',
12 infoTab: 'Инфо слике',
13 linkTab: 'Линк',
14 lockRatio: 'Закључај однос',
15 menu: 'Особине слика',
16 resetSize: 'Ресетуј величину',
17 title: 'Особине слика',
18 titleButton: 'Особине дугмета са сликом',
19 upload: 'Пошаљи',
20 urlMissing: 'Недостаје УРЛ слике.',
21 vSpace: 'VSpace',
22 validateBorder: 'Ивица треба да буде цифра.',
23 validateHSpace: 'HSpace треба да буде цифра.',
24 validateVSpace: 'VSpace треба да буде цифра.'
25} );
diff --git a/sources/plugins/image/lang/sv.js b/sources/plugins/image/lang/sv.js
new file mode 100644
index 0000000..db07c37
--- /dev/null
+++ b/sources/plugins/image/lang/sv.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'sv', {
6 alt: 'Alternativ text',
7 border: 'Kant',
8 btnUpload: 'Skicka till server',
9 button2Img: 'Vill du omvandla den valda bildknappen på en enkel bild?',
10 hSpace: 'Horis. marginal',
11 img2Button: 'Vill du omvandla den valda bildknappen på en enkel bild?',
12 infoTab: 'Bildinformation',
13 linkTab: 'Länk',
14 lockRatio: 'Lås höjd/bredd förhållanden',
15 menu: 'Bildegenskaper',
16 resetSize: 'Återställ storlek',
17 title: 'Bildegenskaper',
18 titleButton: 'Egenskaper för bildknapp',
19 upload: 'Ladda upp',
20 urlMissing: 'Bildkällans URL saknas.',
21 vSpace: 'Vert. marginal',
22 validateBorder: 'Kantlinje måste vara ett heltal.',
23 validateHSpace: 'HSpace måste vara ett heltal.',
24 validateVSpace: 'VSpace måste vara ett heltal.'
25} );
diff --git a/sources/plugins/image/lang/th.js b/sources/plugins/image/lang/th.js
new file mode 100644
index 0000000..0d33bb3
--- /dev/null
+++ b/sources/plugins/image/lang/th.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'th', {
6 alt: 'คำประกอบรูปภาพ',
7 border: 'ขนาดขอบรูป',
8 btnUpload: 'อัพโหลดไฟล์ไปเก็บไว้ที่เครื่องแม่ข่าย (เซิร์ฟเวอร์)',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'ระยะแนวนอน',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'ข้อมูลของรูปภาพ',
13 linkTab: 'ลิ้งค์',
14 lockRatio: 'กำหนดอัตราส่วน กว้าง-สูง แบบคงที่',
15 menu: 'คุณสมบัติของ รูปภาพ',
16 resetSize: 'กำหนดรูปเท่าขนาดจริง',
17 title: 'คุณสมบัติของ รูปภาพ',
18 titleButton: 'คุณสมบัติของ ปุ่มแบบรูปภาพ',
19 upload: 'อัพโหลดไฟล์',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'ระยะแนวตั้ง',
22 validateBorder: 'Border must be a whole number.', // MISSING
23 validateHSpace: 'HSpace must be a whole number.', // MISSING
24 validateVSpace: 'VSpace must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/image/lang/tr.js b/sources/plugins/image/lang/tr.js
new file mode 100644
index 0000000..2f707a1
--- /dev/null
+++ b/sources/plugins/image/lang/tr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'tr', {
6 alt: 'Alternatif Yazı',
7 border: 'Kenar',
8 btnUpload: 'Sunucuya Yolla',
9 button2Img: 'Seçili resim butonunu basit resime çevirmek istermisiniz?',
10 hSpace: 'Yatay Boşluk',
11 img2Button: 'Seçili olan resimi, resimli butona çevirmek istermisiniz?',
12 infoTab: 'Resim Bilgisi',
13 linkTab: 'Köprü',
14 lockRatio: 'Oranı Kilitle',
15 menu: 'Resim Özellikleri',
16 resetSize: 'Boyutu Başa Döndür',
17 title: 'Resim Özellikleri',
18 titleButton: 'Resimli Düğme Özellikleri',
19 upload: 'Karşıya Yükle',
20 urlMissing: 'Resmin URL kaynağı eksiktir.',
21 vSpace: 'Dikey Boşluk',
22 validateBorder: 'Çerçeve tam sayı olmalıdır.',
23 validateHSpace: 'HSpace tam sayı olmalıdır.',
24 validateVSpace: 'VSpace tam sayı olmalıdır.'
25} );
diff --git a/sources/plugins/image/lang/tt.js b/sources/plugins/image/lang/tt.js
new file mode 100644
index 0000000..e659066
--- /dev/null
+++ b/sources/plugins/image/lang/tt.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'tt', {
6 alt: 'Альтернатив текст',
7 border: 'Чик',
8 btnUpload: 'Серверга җибәрү',
9 button2Img: 'Do you want to transform the selected image button on a simple image?', // MISSING
10 hSpace: 'Горизонталь ара',
11 img2Button: 'Do you want to transform the selected image on a image button?', // MISSING
12 infoTab: 'Рәсем тасвирламасы',
13 linkTab: 'Сылталама',
14 lockRatio: 'Lock Ratio', // MISSING
15 menu: 'Рәсем үзлекләре',
16 resetSize: 'Баштагы зурлык',
17 title: 'Рәсем үзлекләре',
18 titleButton: 'Рәсемле төймə үзлекләре',
19 upload: 'Йөкләү',
20 urlMissing: 'Image source URL is missing.', // MISSING
21 vSpace: 'Вертикаль ара',
22 validateBorder: 'Чик киңлеге сан булырга тиеш.',
23 validateHSpace: 'Горизонталь ара бөтен сан булырга тиеш.',
24 validateVSpace: 'Вертикаль ара бөтен сан булырга тиеш.'
25} );
diff --git a/sources/plugins/image/lang/ug.js b/sources/plugins/image/lang/ug.js
new file mode 100644
index 0000000..d2a28ef
--- /dev/null
+++ b/sources/plugins/image/lang/ug.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'ug', {
6 alt: 'تېكىست ئالماشتۇر',
7 border: 'گىرۋەك چوڭلۇقى',
8 btnUpload: 'مۇلازىمېتىرغا يۈكلە',
9 button2Img: 'نۆۋەتتىكى توپچىنى سۈرەتكە ئۆزگەرتەمسىز؟',
10 hSpace: 'توغرىسىغا ئارىلىقى',
11 img2Button: 'نۆۋەتتىكى سۈرەتنى توپچىغا ئۆزگەرتەمسىز؟',
12 infoTab: 'سۈرەت',
13 linkTab: 'ئۇلانما',
14 lockRatio: 'نىسبەتنى قۇلۇپلا',
15 menu: 'سۈرەت خاسلىقى',
16 resetSize: 'ئەسلى چوڭلۇق',
17 title: 'سۈرەت خاسلىقى',
18 titleButton: 'سۈرەت دائىرە خاسلىقى',
19 upload: 'يۈكلە',
20 urlMissing: 'سۈرەتنىڭ ئەسلى ھۆججەت ئادرېسى كەم',
21 vSpace: 'بويىغا ئارىلىقى',
22 validateBorder: 'گىرۋەك چوڭلۇقى چوقۇم سان بولىدۇ',
23 validateHSpace: 'توغرىسىغا ئارىلىق چوقۇم پۈتۈن سان بولىدۇ',
24 validateVSpace: 'بويىغا ئارىلىق چوقۇم پۈتۈن سان بولىدۇ'
25} );
diff --git a/sources/plugins/image/lang/uk.js b/sources/plugins/image/lang/uk.js
new file mode 100644
index 0000000..ace2eea
--- /dev/null
+++ b/sources/plugins/image/lang/uk.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'uk', {
6 alt: 'Альтернативний текст',
7 border: 'Рамка',
8 btnUpload: 'Надіслати на сервер',
9 button2Img: 'Бажаєте перетворити обрану кнопку-зображення на просте зображення?',
10 hSpace: 'Гориз. відступ',
11 img2Button: 'Бажаєте перетворити обране зображення на кнопку-зображення?',
12 infoTab: 'Інформація про зображення',
13 linkTab: 'Посилання',
14 lockRatio: 'Зберегти пропорції',
15 menu: 'Властивості зображення',
16 resetSize: 'Очистити поля розмірів',
17 title: 'Властивості зображення',
18 titleButton: 'Властивості кнопки із зображенням',
19 upload: 'Надіслати',
20 urlMissing: 'Вкажіть URL зображення.',
21 vSpace: 'Верт. відступ',
22 validateBorder: 'Ширина рамки повинна бути цілим числом.',
23 validateHSpace: 'Гориз. відступ повинен бути цілим числом.',
24 validateVSpace: 'Верт. відступ повинен бути цілим числом.'
25} );
diff --git a/sources/plugins/image/lang/vi.js b/sources/plugins/image/lang/vi.js
new file mode 100644
index 0000000..4c33fd5
--- /dev/null
+++ b/sources/plugins/image/lang/vi.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'vi', {
6 alt: 'Chú thích ảnh',
7 border: 'Đường viền',
8 btnUpload: 'Tải lên máy chủ',
9 button2Img: 'Bạn có muốn chuyển nút bấm bằng ảnh được chọn thành ảnh?',
10 hSpace: 'Khoảng đệm ngang',
11 img2Button: 'Bạn có muốn chuyển đổi ảnh được chọn thành nút bấm bằng ảnh?',
12 infoTab: 'Thông tin của ảnh',
13 linkTab: 'Tab liên kết',
14 lockRatio: 'Giữ nguyên tỷ lệ',
15 menu: 'Thuộc tính của ảnh',
16 resetSize: 'Kích thước gốc',
17 title: 'Thuộc tính của ảnh',
18 titleButton: 'Thuộc tính nút của ảnh',
19 upload: 'Tải lên',
20 urlMissing: 'Thiếu đường dẫn hình ảnh',
21 vSpace: 'Khoảng đệm dọc',
22 validateBorder: 'Chiều rộng của đường viền phải là một số nguyên dương',
23 validateHSpace: 'Khoảng đệm ngang phải là một số nguyên dương',
24 validateVSpace: 'Khoảng đệm dọc phải là một số nguyên dương'
25} );
diff --git a/sources/plugins/image/lang/zh-cn.js b/sources/plugins/image/lang/zh-cn.js
new file mode 100644
index 0000000..287a362
--- /dev/null
+++ b/sources/plugins/image/lang/zh-cn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'zh-cn', {
6 alt: '替换文本',
7 border: '边框大小',
8 btnUpload: '上传到服务器',
9 button2Img: '确定要把当前图像按钮转换为普通图像吗?',
10 hSpace: '水平间距',
11 img2Button: '确定要把当前图像改变为图像按钮吗?',
12 infoTab: '图像信息',
13 linkTab: '链接',
14 lockRatio: '锁定比例',
15 menu: '图像属性',
16 resetSize: '原始尺寸',
17 title: '图像属性',
18 titleButton: '图像域属性',
19 upload: '上传',
20 urlMissing: '缺少图像源文件地址',
21 vSpace: '垂直间距',
22 validateBorder: '边框大小必须为整数格式',
23 validateHSpace: '水平间距必须为整数格式',
24 validateVSpace: '垂直间距必须为整数格式'
25} );
diff --git a/sources/plugins/image/lang/zh.js b/sources/plugins/image/lang/zh.js
new file mode 100644
index 0000000..920b554
--- /dev/null
+++ b/sources/plugins/image/lang/zh.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'image', 'zh', {
6 alt: '替代文字',
7 border: '框線',
8 btnUpload: '傳送到伺服器',
9 button2Img: '請問您確定要將「圖片按鈕」轉換成「圖片」嗎?',
10 hSpace: 'HSpace',
11 img2Button: '請問您確定要將「圖片」轉換成「圖片按鈕」嗎?',
12 infoTab: '影像資訊',
13 linkTab: '連結',
14 lockRatio: '固定比例',
15 menu: '影像屬性',
16 resetSize: '重設大小',
17 title: '影像屬性',
18 titleButton: '影像按鈕屬性',
19 upload: '上傳',
20 urlMissing: '遺失圖片來源之 URL ',
21 vSpace: 'VSpace',
22 validateBorder: '框線必須是整數。',
23 validateHSpace: 'HSpace 必須是整數。',
24 validateVSpace: 'VSpace 必須是整數。'
25} );
diff --git a/sources/plugins/image/plugin.js b/sources/plugins/image/plugin.js
new file mode 100644
index 0000000..1394510
--- /dev/null
+++ b/sources/plugins/image/plugin.js
@@ -0,0 +1,183 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The Image plugin.
8 */
9
10( function() {
11
12 CKEDITOR.plugins.add( 'image', {
13 requires: 'dialog',
14 // jscs:disable maximumLineLength
15 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
16 // jscs:enable maximumLineLength
17 icons: 'image', // %REMOVE_LINE_CORE%
18 hidpi: true, // %REMOVE_LINE_CORE%
19 init: function( editor ) {
20 // Abort when Image2 is to be loaded since both plugins
21 // share the same button, command, etc. names (#11222).
22 if ( editor.plugins.image2 )
23 return;
24
25 var pluginName = 'image';
26
27 // Register the dialog.
28 CKEDITOR.dialog.add( pluginName, this.path + 'dialogs/image.js' );
29
30 var allowed = 'img[alt,!src]{border-style,border-width,float,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}',
31 required = 'img[alt,src]';
32
33 if ( CKEDITOR.dialog.isTabEnabled( editor, pluginName, 'advanced' ) )
34 allowed = 'img[alt,dir,id,lang,longdesc,!src,title]{*}(*)';
35
36 // Register the command.
37 editor.addCommand( pluginName, new CKEDITOR.dialogCommand( pluginName, {
38 allowedContent: allowed,
39 requiredContent: required,
40 contentTransformations: [
41 [ 'img{width}: sizeToStyle', 'img[width]: sizeToAttribute' ],
42 [ 'img{float}: alignmentToStyle', 'img[align]: alignmentToAttribute' ]
43 ]
44 } ) );
45
46 // Register the toolbar button.
47 editor.ui.addButton && editor.ui.addButton( 'Image', {
48 label: editor.lang.common.image,
49 command: pluginName,
50 toolbar: 'insert,10'
51 } );
52
53 editor.on( 'doubleclick', function( evt ) {
54 var element = evt.data.element;
55
56 if ( element.is( 'img' ) && !element.data( 'cke-realelement' ) && !element.isReadOnly() )
57 evt.data.dialog = 'image';
58 } );
59
60 // If the "menu" plugin is loaded, register the menu items.
61 if ( editor.addMenuItems ) {
62 editor.addMenuItems( {
63 image: {
64 label: editor.lang.image.menu,
65 command: 'image',
66 group: 'image'
67 }
68 } );
69 }
70
71 // If the "contextmenu" plugin is loaded, register the listeners.
72 if ( editor.contextMenu ) {
73 editor.contextMenu.addListener( function( element ) {
74 if ( getSelectedImage( editor, element ) )
75 return { image: CKEDITOR.TRISTATE_OFF };
76 } );
77 }
78 },
79 afterInit: function( editor ) {
80 // Abort when Image2 is to be loaded since both plugins
81 // share the same button, command, etc. names (#11222).
82 if ( editor.plugins.image2 )
83 return;
84
85 // Customize the behavior of the alignment commands. (#7430)
86 setupAlignCommand( 'left' );
87 setupAlignCommand( 'right' );
88 setupAlignCommand( 'center' );
89 setupAlignCommand( 'block' );
90
91 function setupAlignCommand( value ) {
92 var command = editor.getCommand( 'justify' + value );
93 if ( command ) {
94 if ( value == 'left' || value == 'right' ) {
95 command.on( 'exec', function( evt ) {
96 var img = getSelectedImage( editor ),
97 align;
98 if ( img ) {
99 align = getImageAlignment( img );
100 if ( align == value ) {
101 img.removeStyle( 'float' );
102
103 // Remove "align" attribute when necessary.
104 if ( value == getImageAlignment( img ) )
105 img.removeAttribute( 'align' );
106 } else {
107 img.setStyle( 'float', value );
108 }
109
110 evt.cancel();
111 }
112 } );
113 }
114
115 command.on( 'refresh', function( evt ) {
116 var img = getSelectedImage( editor ),
117 align;
118 if ( img ) {
119 align = getImageAlignment( img );
120
121 this.setState(
122 ( align == value ) ? CKEDITOR.TRISTATE_ON : ( value == 'right' || value == 'left' ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED );
123
124 evt.cancel();
125 }
126 } );
127 }
128 }
129 }
130 } );
131
132 function getSelectedImage( editor, element ) {
133 if ( !element ) {
134 var sel = editor.getSelection();
135 element = sel.getSelectedElement();
136 }
137
138 if ( element && element.is( 'img' ) && !element.data( 'cke-realelement' ) && !element.isReadOnly() )
139 return element;
140 }
141
142 function getImageAlignment( element ) {
143 var align = element.getStyle( 'float' );
144
145 if ( align == 'inherit' || align == 'none' )
146 align = 0;
147
148 if ( !align )
149 align = element.getAttribute( 'align' );
150
151 return align;
152 }
153
154} )();
155
156/**
157 * Determines whether dimension inputs should be automatically filled when the image URL changes in the Image plugin dialog window.
158 *
159 * config.image_prefillDimensions = false;
160 *
161 * @since 4.5
162 * @cfg {Boolean} [image_prefillDimensions=true]
163 * @member CKEDITOR.config
164 */
165
166/**
167 * Whether to remove links when emptying the link URL field in the Image dialog window.
168 *
169 * config.image_removeLinkByEmptyURL = false;
170 *
171 * @cfg {Boolean} [image_removeLinkByEmptyURL=true]
172 * @member CKEDITOR.config
173 */
174CKEDITOR.config.image_removeLinkByEmptyURL = true;
175
176/**
177 * Padding text to set off the image in the preview area.
178 *
179 * config.image_previewText = CKEDITOR.tools.repeat( '___ ', 100 );
180 *
181 * @cfg {String} [image_previewText='Lorem ipsum dolor...' (placeholder text)]
182 * @member CKEDITOR.config
183 */
diff --git a/sources/plugins/indent/dev/indent.html b/sources/plugins/indent/dev/indent.html
new file mode 100644
index 0000000..8b935ae
--- /dev/null
+++ b/sources/plugins/indent/dev/indent.html
@@ -0,0 +1,284 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Indent DEV sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <style>
12 body {
13 padding: 20px;
14 margin: 0;
15 }
16 .editors {
17 display: block;
18 overflow: hidden;
19 width: 100%;
20 margin: 0px auto;
21 list-style-type: none;
22 margin: 0;
23 padding: 0;
24
25 box-sizing: content-box;
26
27 background: #eee;
28 }
29 .editors li {
30 width: 50%;
31 margin: 0;
32 padding: 10px;
33 float: left;
34
35 box-sizing: border-box;
36 }
37 .editors li:nth-child(2n) {
38 background: #D4E59A;
39 }
40 #menu {
41 position: fixed;
42 top: 0;
43 right: 20px;
44 padding: 5px;
45 border: 1px solid #aaa;
46 background: #eee;
47 }
48
49 </style>
50</head>
51<body>
52 <p id="menu">
53 <a href="#listnblock">List &amp; Block</a>,
54 <a href="#classes">Classes</a>,
55 <a href="#list">List</a>,
56 <a href="#block">Block</a>,
57 <a href="#br">ENTER_BR</a>
58 </p>
59
60 <h1 class="samples">Indent DEV sample</h1>
61 <h2 id="listnblock">List &amp; Block</h2>
62 <ul class="editors">
63 <li>
64 <textarea cols="80" id="editor1" rows="10">
65 <p>xx</p>
66 <ul>
67 <li>x</li>
68 <li>y</li>
69 </ul>
70 <p>xx</p>
71
72 <br>
73
74 <ul><li><ol><li>xx</li></ol></li><li>yy</li></ul>
75 </textarea>
76 </li>
77 <li>
78 <pre id="editor1_out"></pre>
79 </li>
80 </ul>
81
82 <h2 id="classes">Indent classes</h2>
83 <ul class="editors">
84 <li>
85 <textarea cols="80" id="editor2" rows="10">
86 <ul>
87 <li>a</li>
88 <li>
89 b
90 <ol>
91 <li>inner</li>
92 </ol>
93 </li>
94 <li>c</li>
95 </ul>
96 <p>moo</p>
97 </textarea>
98 </li>
99 <li>
100 <pre id="editor2_out"></pre>
101 </li>
102 </ul>
103
104 <h2 id="list">List only</h2>
105 <ul class="editors">
106 <li>
107 <textarea cols="80" id="editor3" rows="10">
108 <ul>
109 <li>a</li>
110 <li>
111 b
112 <ol>
113 <li>inner</li>
114 </ol>
115 </li>
116 <li>c</li>
117 </ul>
118 <p>moo</p>
119 </textarea>
120 </li>
121 <li>
122 <pre id="editor3_out"></pre>
123 </li>
124 </ul>
125
126 <h2 id="block">Block only</h2>
127 <ul class="editors">
128 <li>
129 <textarea cols="80" id="editor4" rows="10">
130 <ul>
131 <li>a</li>
132 <li>
133 b
134 <ol>
135 <li>inner</li>
136 </ol>
137 </li>
138 <li>c</li>
139 </ul>
140 <p>moo</p>
141 </textarea>
142 </li>
143 <li>
144 <pre id="editor4_out"></pre>
145 </li>
146 </ul>
147
148 <h2 id="br">CKEDITOR.ENTER_BR</h2>
149 <ul class="editors">
150 <li>
151 <textarea cols="80" id="editor5" rows="10">
152 Text
153 <br>
154 <ul>
155 <li>a</li>
156 <li>b</li>
157 </ul>
158 </textarea>
159 </li>
160 <li>
161 <pre id="editor5_out"></pre>
162 </li>
163 </ul>
164 <script>
165
166 var plugins = 'enterkey,toolbar,htmlwriter,wysiwygarea,undo,sourcearea,clipboard,list,justify,indent,indentlist,indentblock';
167
168 CKEDITOR.config.indentOffset = 10;
169 CKEDITOR.addCss( '\
170 .i1{ margin-left: 10px}\
171 .i2{ margin-left: 20px}\
172 .i3{ margin-left: 30px}' );
173
174 function showData( event ) {
175 CKEDITOR.document.getById( this.name + '_out' ).setText( getHtmlWithSelection( this ) );
176 }
177
178 function browserHtmlFix( html ) {
179 if ( CKEDITOR.env.ie && ( document.documentMode || CKEDITOR.env.version ) < 9 ) {
180 // Fix output base href on anchored link.
181 html = html.replace( /href="(.*?)#(.*?)"/gi,
182 function( m, base, anchor ) {
183 if ( base == window.location.href.replace( window.location.hash, '' ) )
184 return 'href="#' + anchor + '"';
185
186 return m;
187 } );
188
189 // Fix output line break after HR.
190 html = html.replace( /(<HR>)\r\n/gi, function( m, hr ) { return hr; } );
191 }
192
193 return html;
194 }
195
196 function getHtmlWithSelection( editorOrElement, root ) {
197 var isEditor = editorOrElement instanceof CKEDITOR.editor,
198 element = isEditor ? editorOrElement.editable() : editorOrElement;
199
200 root = isEditor ? element :
201 root instanceof CKEDITOR.dom.document ?
202 root.getBody() : root || CKEDITOR.document.getBody();
203
204 function replaceWithBookmark( match, startOrEnd ) {
205 var bookmark;
206 switch( startOrEnd ) {
207 case 'S' :
208 bookmark = '[';
209 break;
210 case 'E' :
211 bookmark = ']';
212 break;
213 case 'C' :
214 bookmark = '^';
215 break;
216 }
217 return bookmark;
218 }
219
220 // Hack: force remove the filling char hack in Webkit.
221 isEditor && CKEDITOR.env.webkit && editorOrElement.fire( 'beforeSetMode' );
222
223 var sel = isEditor ? editorOrElement.getSelection()
224 : new CKEDITOR.dom.selection( root );
225
226 var doc = sel.document;
227 var ranges = sel.getRanges(),
228 range;
229
230 var bms = [];
231 var iter = ranges.createIterator();
232 while( range = iter.getNextRange() )
233 bms.push( range.createBookmark( 1 ) );
234
235 var html = browserHtmlFix( isEditor ? editorOrElement.getData() : element.getHtml() );
236 html = html.replace( /<span\b[^>]*?id="?cke_bm_\d+(\w)"?\b[^>]*?>.*?<\/span>/gi,
237 replaceWithBookmark );
238
239 for ( var i = 0, bm; i < bms.length; i++ ) {
240 bm = bms[ i ];
241 var start = doc.getById( bm.startNode ),
242 end = doc.getById( bm.endNode );
243
244 start && start.remove();
245 end && end.remove();
246 }
247
248 return html;
249 }
250
251 CKEDITOR.on( 'instanceReady', function ( event ) {
252 var editor = event.editor;
253
254 showData.call( editor );
255
256 editor.on( 'afterCommandExec', showData, editor );
257 });
258
259 CKEDITOR.replace( 'editor1', {
260 plugins: plugins
261 } );
262
263 CKEDITOR.replace( 'editor2', {
264 plugins: plugins,
265 indentClasses: [ 'i1', 'i2', 'i3' ]
266 } );
267
268 CKEDITOR.replace( 'editor3', {
269 plugins: plugins,
270 removePlugins: 'indentblock'
271 } );
272
273 CKEDITOR.replace( 'editor4', {
274 plugins: plugins,
275 removePlugins: 'indentlist'
276 } );
277
278 CKEDITOR.replace( 'editor5', {
279 plugins: plugins,
280 enterMode: CKEDITOR.ENTER_BR
281 } );
282 </script>
283</body>
284</html>
diff --git a/sources/plugins/indent/icons/hidpi/indent-rtl.png b/sources/plugins/indent/icons/hidpi/indent-rtl.png
new file mode 100644
index 0000000..72bf567
--- /dev/null
+++ b/sources/plugins/indent/icons/hidpi/indent-rtl.png
Binary files differ
diff --git a/sources/plugins/indent/icons/hidpi/indent.png b/sources/plugins/indent/icons/hidpi/indent.png
new file mode 100644
index 0000000..6381b23
--- /dev/null
+++ b/sources/plugins/indent/icons/hidpi/indent.png
Binary files differ
diff --git a/sources/plugins/indent/icons/hidpi/outdent-rtl.png b/sources/plugins/indent/icons/hidpi/outdent-rtl.png
new file mode 100644
index 0000000..441e204
--- /dev/null
+++ b/sources/plugins/indent/icons/hidpi/outdent-rtl.png
Binary files differ
diff --git a/sources/plugins/indent/icons/hidpi/outdent.png b/sources/plugins/indent/icons/hidpi/outdent.png
new file mode 100644
index 0000000..8fa4e5e
--- /dev/null
+++ b/sources/plugins/indent/icons/hidpi/outdent.png
Binary files differ
diff --git a/sources/plugins/indent/icons/indent-rtl.png b/sources/plugins/indent/icons/indent-rtl.png
new file mode 100644
index 0000000..0327578
--- /dev/null
+++ b/sources/plugins/indent/icons/indent-rtl.png
Binary files differ
diff --git a/sources/plugins/indent/icons/indent.png b/sources/plugins/indent/icons/indent.png
new file mode 100644
index 0000000..0a5d293
--- /dev/null
+++ b/sources/plugins/indent/icons/indent.png
Binary files differ
diff --git a/sources/plugins/indent/icons/outdent-rtl.png b/sources/plugins/indent/icons/outdent-rtl.png
new file mode 100644
index 0000000..ce9ce08
--- /dev/null
+++ b/sources/plugins/indent/icons/outdent-rtl.png
Binary files differ
diff --git a/sources/plugins/indent/icons/outdent.png b/sources/plugins/indent/icons/outdent.png
new file mode 100644
index 0000000..351f05d
--- /dev/null
+++ b/sources/plugins/indent/icons/outdent.png
Binary files differ
diff --git a/sources/plugins/indent/lang/af.js b/sources/plugins/indent/lang/af.js
new file mode 100644
index 0000000..14fff63
--- /dev/null
+++ b/sources/plugins/indent/lang/af.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'af', {
6 indent: 'Vergroot inspring',
7 outdent: 'Verklein inspring'
8} );
diff --git a/sources/plugins/indent/lang/ar.js b/sources/plugins/indent/lang/ar.js
new file mode 100644
index 0000000..fe078cb
--- /dev/null
+++ b/sources/plugins/indent/lang/ar.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ar', {
6 indent: 'زيادة المسافة البادئة',
7 outdent: 'إنقاص المسافة البادئة'
8} );
diff --git a/sources/plugins/indent/lang/az.js b/sources/plugins/indent/lang/az.js
new file mode 100644
index 0000000..389d1d9
--- /dev/null
+++ b/sources/plugins/indent/lang/az.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'az', {
6 indent: 'Sol boşluqu artır',
7 outdent: 'Sol boşluqu azalt'
8} );
diff --git a/sources/plugins/indent/lang/bg.js b/sources/plugins/indent/lang/bg.js
new file mode 100644
index 0000000..f4e0163
--- /dev/null
+++ b/sources/plugins/indent/lang/bg.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'bg', {
6 indent: 'Увеличаване на отстъпа',
7 outdent: 'Намаляване на отстъпа'
8} );
diff --git a/sources/plugins/indent/lang/bn.js b/sources/plugins/indent/lang/bn.js
new file mode 100644
index 0000000..88a3393
--- /dev/null
+++ b/sources/plugins/indent/lang/bn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'bn', {
6 indent: 'ইনডেন্ট বাড়াই',
7 outdent: 'ইনডেন্ট কমাও'
8} );
diff --git a/sources/plugins/indent/lang/bs.js b/sources/plugins/indent/lang/bs.js
new file mode 100644
index 0000000..62df508
--- /dev/null
+++ b/sources/plugins/indent/lang/bs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'bs', {
6 indent: 'Poveæaj uvod',
7 outdent: 'Smanji uvod'
8} );
diff --git a/sources/plugins/indent/lang/ca.js b/sources/plugins/indent/lang/ca.js
new file mode 100644
index 0000000..38f299a
--- /dev/null
+++ b/sources/plugins/indent/lang/ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ca', {
6 indent: 'Augmenta el sagnat',
7 outdent: 'Redueix el sagnat'
8} );
diff --git a/sources/plugins/indent/lang/cs.js b/sources/plugins/indent/lang/cs.js
new file mode 100644
index 0000000..854aac8
--- /dev/null
+++ b/sources/plugins/indent/lang/cs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'cs', {
6 indent: 'Zvětšit odsazení',
7 outdent: 'Zmenšit odsazení'
8} );
diff --git a/sources/plugins/indent/lang/cy.js b/sources/plugins/indent/lang/cy.js
new file mode 100644
index 0000000..d1df873
--- /dev/null
+++ b/sources/plugins/indent/lang/cy.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'cy', {
6 indent: 'Cynyddu\'r Mewnoliad',
7 outdent: 'Lleihau\'r Mewnoliad'
8} );
diff --git a/sources/plugins/indent/lang/da.js b/sources/plugins/indent/lang/da.js
new file mode 100644
index 0000000..27e5731
--- /dev/null
+++ b/sources/plugins/indent/lang/da.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'da', {
6 indent: 'Forøg indrykning',
7 outdent: 'Formindsk indrykning'
8} );
diff --git a/sources/plugins/indent/lang/de-ch.js b/sources/plugins/indent/lang/de-ch.js
new file mode 100644
index 0000000..0696275
--- /dev/null
+++ b/sources/plugins/indent/lang/de-ch.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'de-ch', {
6 indent: 'Einzug erhöhen',
7 outdent: 'Einzug verringern'
8} );
diff --git a/sources/plugins/indent/lang/de.js b/sources/plugins/indent/lang/de.js
new file mode 100644
index 0000000..3f7a53c
--- /dev/null
+++ b/sources/plugins/indent/lang/de.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'de', {
6 indent: 'Einzug erhöhen',
7 outdent: 'Einzug verringern'
8} );
diff --git a/sources/plugins/indent/lang/el.js b/sources/plugins/indent/lang/el.js
new file mode 100644
index 0000000..57ac0f5
--- /dev/null
+++ b/sources/plugins/indent/lang/el.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'el', {
6 indent: 'Αύξηση Εσοχής',
7 outdent: 'Μείωση Εσοχής'
8} );
diff --git a/sources/plugins/indent/lang/en-au.js b/sources/plugins/indent/lang/en-au.js
new file mode 100644
index 0000000..6fd80ea
--- /dev/null
+++ b/sources/plugins/indent/lang/en-au.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'en-au', {
6 indent: 'Increase Indent',
7 outdent: 'Decrease Indent'
8} );
diff --git a/sources/plugins/indent/lang/en-ca.js b/sources/plugins/indent/lang/en-ca.js
new file mode 100644
index 0000000..b103510
--- /dev/null
+++ b/sources/plugins/indent/lang/en-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'en-ca', {
6 indent: 'Increase Indent',
7 outdent: 'Decrease Indent'
8} );
diff --git a/sources/plugins/indent/lang/en-gb.js b/sources/plugins/indent/lang/en-gb.js
new file mode 100644
index 0000000..0d2edf3
--- /dev/null
+++ b/sources/plugins/indent/lang/en-gb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'en-gb', {
6 indent: 'Increase Indent',
7 outdent: 'Decrease Indent'
8} );
diff --git a/sources/plugins/indent/lang/en.js b/sources/plugins/indent/lang/en.js
new file mode 100644
index 0000000..c5dba75
--- /dev/null
+++ b/sources/plugins/indent/lang/en.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'en', {
6 indent: 'Increase Indent',
7 outdent: 'Decrease Indent'
8} );
diff --git a/sources/plugins/indent/lang/eo.js b/sources/plugins/indent/lang/eo.js
new file mode 100644
index 0000000..eb8b8ea
--- /dev/null
+++ b/sources/plugins/indent/lang/eo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'eo', {
6 indent: 'Pligrandigi Krommarĝenon',
7 outdent: 'Malpligrandigi Krommarĝenon'
8} );
diff --git a/sources/plugins/indent/lang/es.js b/sources/plugins/indent/lang/es.js
new file mode 100644
index 0000000..d7b01c6
--- /dev/null
+++ b/sources/plugins/indent/lang/es.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'es', {
6 indent: 'Aumentar Sangría',
7 outdent: 'Disminuir Sangría'
8} );
diff --git a/sources/plugins/indent/lang/et.js b/sources/plugins/indent/lang/et.js
new file mode 100644
index 0000000..ce10b13
--- /dev/null
+++ b/sources/plugins/indent/lang/et.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'et', {
6 indent: 'Taande suurendamine',
7 outdent: 'Taande vähendamine'
8} );
diff --git a/sources/plugins/indent/lang/eu.js b/sources/plugins/indent/lang/eu.js
new file mode 100644
index 0000000..7934a48
--- /dev/null
+++ b/sources/plugins/indent/lang/eu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'eu', {
6 indent: 'Handitu koska',
7 outdent: 'Txikitu koska'
8} );
diff --git a/sources/plugins/indent/lang/fa.js b/sources/plugins/indent/lang/fa.js
new file mode 100644
index 0000000..932734a
--- /dev/null
+++ b/sources/plugins/indent/lang/fa.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'fa', {
6 indent: 'افزایش تورفتگی',
7 outdent: 'کاهش تورفتگی'
8} );
diff --git a/sources/plugins/indent/lang/fi.js b/sources/plugins/indent/lang/fi.js
new file mode 100644
index 0000000..c6a5b21
--- /dev/null
+++ b/sources/plugins/indent/lang/fi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'fi', {
6 indent: 'Suurenna sisennystä',
7 outdent: 'Pienennä sisennystä'
8} );
diff --git a/sources/plugins/indent/lang/fo.js b/sources/plugins/indent/lang/fo.js
new file mode 100644
index 0000000..f6e6671
--- /dev/null
+++ b/sources/plugins/indent/lang/fo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'fo', {
6 indent: 'Økja reglubrotarinntriv',
7 outdent: 'Minka reglubrotarinntriv'
8} );
diff --git a/sources/plugins/indent/lang/fr-ca.js b/sources/plugins/indent/lang/fr-ca.js
new file mode 100644
index 0000000..74bbed5
--- /dev/null
+++ b/sources/plugins/indent/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'fr-ca', {
6 indent: 'Augmenter le retrait',
7 outdent: 'Diminuer le retrait'
8} );
diff --git a/sources/plugins/indent/lang/fr.js b/sources/plugins/indent/lang/fr.js
new file mode 100644
index 0000000..0fb1347
--- /dev/null
+++ b/sources/plugins/indent/lang/fr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'fr', {
6 indent: 'Augmenter le retrait',
7 outdent: 'Diminuer le retrait'
8} );
diff --git a/sources/plugins/indent/lang/gl.js b/sources/plugins/indent/lang/gl.js
new file mode 100644
index 0000000..832b0ad
--- /dev/null
+++ b/sources/plugins/indent/lang/gl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'gl', {
6 indent: 'Aumentar a sangría',
7 outdent: 'Reducir a sangría'
8} );
diff --git a/sources/plugins/indent/lang/gu.js b/sources/plugins/indent/lang/gu.js
new file mode 100644
index 0000000..e69a3ce
--- /dev/null
+++ b/sources/plugins/indent/lang/gu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'gu', {
6 indent: 'ઇન્ડેન્ટ, લીટીના આરંભમાં જગ્યા વધારવી',
7 outdent: 'ઇન્ડેન્ટ લીટીના આરંભમાં જગ્યા ઘટાડવી'
8} );
diff --git a/sources/plugins/indent/lang/he.js b/sources/plugins/indent/lang/he.js
new file mode 100644
index 0000000..6fa5ed7
--- /dev/null
+++ b/sources/plugins/indent/lang/he.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'he', {
6 indent: 'הגדלת הזחה',
7 outdent: 'הקטנת הזחה'
8} );
diff --git a/sources/plugins/indent/lang/hi.js b/sources/plugins/indent/lang/hi.js
new file mode 100644
index 0000000..a3c39d8
--- /dev/null
+++ b/sources/plugins/indent/lang/hi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'hi', {
6 indent: 'इन्डॅन्ट बढ़ायें',
7 outdent: 'इन्डॅन्ट कम करें'
8} );
diff --git a/sources/plugins/indent/lang/hr.js b/sources/plugins/indent/lang/hr.js
new file mode 100644
index 0000000..dfa90d4
--- /dev/null
+++ b/sources/plugins/indent/lang/hr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'hr', {
6 indent: 'Pomakni udesno',
7 outdent: 'Pomakni ulijevo'
8} );
diff --git a/sources/plugins/indent/lang/hu.js b/sources/plugins/indent/lang/hu.js
new file mode 100644
index 0000000..22cd8e0
--- /dev/null
+++ b/sources/plugins/indent/lang/hu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'hu', {
6 indent: 'Behúzás növelése',
7 outdent: 'Behúzás csökkentése'
8} );
diff --git a/sources/plugins/indent/lang/id.js b/sources/plugins/indent/lang/id.js
new file mode 100644
index 0000000..2c66b70
--- /dev/null
+++ b/sources/plugins/indent/lang/id.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'id', {
6 indent: 'Tingkatkan Lekuk',
7 outdent: 'Kurangi Lekuk'
8} );
diff --git a/sources/plugins/indent/lang/is.js b/sources/plugins/indent/lang/is.js
new file mode 100644
index 0000000..71f80b1
--- /dev/null
+++ b/sources/plugins/indent/lang/is.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'is', {
6 indent: 'Minnka inndrátt',
7 outdent: 'Auka inndrátt'
8} );
diff --git a/sources/plugins/indent/lang/it.js b/sources/plugins/indent/lang/it.js
new file mode 100644
index 0000000..36e0922
--- /dev/null
+++ b/sources/plugins/indent/lang/it.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'it', {
6 indent: 'Aumenta rientro',
7 outdent: 'Riduci rientro'
8} );
diff --git a/sources/plugins/indent/lang/ja.js b/sources/plugins/indent/lang/ja.js
new file mode 100644
index 0000000..838f4cb
--- /dev/null
+++ b/sources/plugins/indent/lang/ja.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ja', {
6 indent: 'インデント',
7 outdent: 'インデント解除'
8} );
diff --git a/sources/plugins/indent/lang/ka.js b/sources/plugins/indent/lang/ka.js
new file mode 100644
index 0000000..a0ce0e8
--- /dev/null
+++ b/sources/plugins/indent/lang/ka.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ka', {
6 indent: 'მეტად შეწევა',
7 outdent: 'ნაკლებად შეწევა'
8} );
diff --git a/sources/plugins/indent/lang/km.js b/sources/plugins/indent/lang/km.js
new file mode 100644
index 0000000..514fba2
--- /dev/null
+++ b/sources/plugins/indent/lang/km.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'km', {
6 indent: 'បន្ថែមការចូលបន្ទាត់',
7 outdent: 'បន្ថយការចូលបន្ទាត់'
8} );
diff --git a/sources/plugins/indent/lang/ko.js b/sources/plugins/indent/lang/ko.js
new file mode 100644
index 0000000..c77afbd
--- /dev/null
+++ b/sources/plugins/indent/lang/ko.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ko', {
6 indent: '들여쓰기',
7 outdent: '내어쓰기'
8} );
diff --git a/sources/plugins/indent/lang/ku.js b/sources/plugins/indent/lang/ku.js
new file mode 100644
index 0000000..728bfe3
--- /dev/null
+++ b/sources/plugins/indent/lang/ku.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ku', {
6 indent: 'زیادکردنی بۆشایی',
7 outdent: 'کەمکردنەوەی بۆشایی'
8} );
diff --git a/sources/plugins/indent/lang/lt.js b/sources/plugins/indent/lang/lt.js
new file mode 100644
index 0000000..4458598
--- /dev/null
+++ b/sources/plugins/indent/lang/lt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'lt', {
6 indent: 'Padidinti įtrauką',
7 outdent: 'Sumažinti įtrauką'
8} );
diff --git a/sources/plugins/indent/lang/lv.js b/sources/plugins/indent/lang/lv.js
new file mode 100644
index 0000000..74d36a4
--- /dev/null
+++ b/sources/plugins/indent/lang/lv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'lv', {
6 indent: 'Palielināt atkāpi',
7 outdent: 'Samazināt atkāpi'
8} );
diff --git a/sources/plugins/indent/lang/mk.js b/sources/plugins/indent/lang/mk.js
new file mode 100644
index 0000000..440995e
--- /dev/null
+++ b/sources/plugins/indent/lang/mk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'mk', {
6 indent: 'Increase Indent', // MISSING
7 outdent: 'Decrease Indent' // MISSING
8} );
diff --git a/sources/plugins/indent/lang/mn.js b/sources/plugins/indent/lang/mn.js
new file mode 100644
index 0000000..d9c74ba
--- /dev/null
+++ b/sources/plugins/indent/lang/mn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'mn', {
6 indent: 'Догол мөр хасах',
7 outdent: 'Догол мөр нэмэх'
8} );
diff --git a/sources/plugins/indent/lang/ms.js b/sources/plugins/indent/lang/ms.js
new file mode 100644
index 0000000..5fd53e2
--- /dev/null
+++ b/sources/plugins/indent/lang/ms.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ms', {
6 indent: 'Tambahkan Inden',
7 outdent: 'Kurangkan Inden'
8} );
diff --git a/sources/plugins/indent/lang/nb.js b/sources/plugins/indent/lang/nb.js
new file mode 100644
index 0000000..e69a947
--- /dev/null
+++ b/sources/plugins/indent/lang/nb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'nb', {
6 indent: 'Øk innrykk',
7 outdent: 'Reduser innrykk'
8} );
diff --git a/sources/plugins/indent/lang/nl.js b/sources/plugins/indent/lang/nl.js
new file mode 100644
index 0000000..8979f8f
--- /dev/null
+++ b/sources/plugins/indent/lang/nl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'nl', {
6 indent: 'Inspringing vergroten',
7 outdent: 'Inspringing verkleinen'
8} );
diff --git a/sources/plugins/indent/lang/no.js b/sources/plugins/indent/lang/no.js
new file mode 100644
index 0000000..a01c1bb
--- /dev/null
+++ b/sources/plugins/indent/lang/no.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'no', {
6 indent: 'Øk innrykk',
7 outdent: 'Reduser innrykk'
8} );
diff --git a/sources/plugins/indent/lang/oc.js b/sources/plugins/indent/lang/oc.js
new file mode 100644
index 0000000..00e9cf9
--- /dev/null
+++ b/sources/plugins/indent/lang/oc.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'oc', {
6 indent: 'Aumentar l\'alinèa',
7 outdent: 'Dmesir l\'alinèa'
8} );
diff --git a/sources/plugins/indent/lang/pl.js b/sources/plugins/indent/lang/pl.js
new file mode 100644
index 0000000..ef78a2e
--- /dev/null
+++ b/sources/plugins/indent/lang/pl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'pl', {
6 indent: 'Zwiększ wcięcie',
7 outdent: 'Zmniejsz wcięcie'
8} );
diff --git a/sources/plugins/indent/lang/pt-br.js b/sources/plugins/indent/lang/pt-br.js
new file mode 100644
index 0000000..45ae5e6
--- /dev/null
+++ b/sources/plugins/indent/lang/pt-br.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'pt-br', {
6 indent: 'Aumentar Recuo',
7 outdent: 'Diminuir Recuo'
8} );
diff --git a/sources/plugins/indent/lang/pt.js b/sources/plugins/indent/lang/pt.js
new file mode 100644
index 0000000..6d26cb2
--- /dev/null
+++ b/sources/plugins/indent/lang/pt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'pt', {
6 indent: 'Aumentar avanço',
7 outdent: 'Diminuir avanço'
8} );
diff --git a/sources/plugins/indent/lang/ro.js b/sources/plugins/indent/lang/ro.js
new file mode 100644
index 0000000..708b09d
--- /dev/null
+++ b/sources/plugins/indent/lang/ro.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ro', {
6 indent: 'Creşte indentarea',
7 outdent: 'Scade indentarea'
8} );
diff --git a/sources/plugins/indent/lang/ru.js b/sources/plugins/indent/lang/ru.js
new file mode 100644
index 0000000..aa21b7a
--- /dev/null
+++ b/sources/plugins/indent/lang/ru.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ru', {
6 indent: 'Увеличить отступ',
7 outdent: 'Уменьшить отступ'
8} );
diff --git a/sources/plugins/indent/lang/si.js b/sources/plugins/indent/lang/si.js
new file mode 100644
index 0000000..98b8dd3
--- /dev/null
+++ b/sources/plugins/indent/lang/si.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'si', {
6 indent: 'අතර පරතරය වැඩිකරන්න',
7 outdent: 'අතර පරතරය අඩුකරන්න'
8} );
diff --git a/sources/plugins/indent/lang/sk.js b/sources/plugins/indent/lang/sk.js
new file mode 100644
index 0000000..3135f4f
--- /dev/null
+++ b/sources/plugins/indent/lang/sk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'sk', {
6 indent: 'Zväčšiť odsadenie',
7 outdent: 'Zmenšiť odsadenie'
8} );
diff --git a/sources/plugins/indent/lang/sl.js b/sources/plugins/indent/lang/sl.js
new file mode 100644
index 0000000..15be2f7
--- /dev/null
+++ b/sources/plugins/indent/lang/sl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'sl', {
6 indent: 'Povečaj zamik',
7 outdent: 'Zmanjšaj zamik'
8} );
diff --git a/sources/plugins/indent/lang/sq.js b/sources/plugins/indent/lang/sq.js
new file mode 100644
index 0000000..9a2dd63
--- /dev/null
+++ b/sources/plugins/indent/lang/sq.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'sq', {
6 indent: 'Rrite Identin',
7 outdent: 'Zvogëlo Identin'
8} );
diff --git a/sources/plugins/indent/lang/sr-latn.js b/sources/plugins/indent/lang/sr-latn.js
new file mode 100644
index 0000000..ca5a140
--- /dev/null
+++ b/sources/plugins/indent/lang/sr-latn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'sr-latn', {
6 indent: 'Uvećaj levu marginu',
7 outdent: 'Smanji levu marginu'
8} );
diff --git a/sources/plugins/indent/lang/sr.js b/sources/plugins/indent/lang/sr.js
new file mode 100644
index 0000000..f7498be
--- /dev/null
+++ b/sources/plugins/indent/lang/sr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'sr', {
6 indent: 'Увећај леву маргину',
7 outdent: 'Смањи леву маргину'
8} );
diff --git a/sources/plugins/indent/lang/sv.js b/sources/plugins/indent/lang/sv.js
new file mode 100644
index 0000000..46b0692
--- /dev/null
+++ b/sources/plugins/indent/lang/sv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'sv', {
6 indent: 'Öka indrag',
7 outdent: 'Minska indrag'
8} );
diff --git a/sources/plugins/indent/lang/th.js b/sources/plugins/indent/lang/th.js
new file mode 100644
index 0000000..2f60e53
--- /dev/null
+++ b/sources/plugins/indent/lang/th.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'th', {
6 indent: 'เพิ่มระยะย่อหน้า',
7 outdent: 'ลดระยะย่อหน้า'
8} );
diff --git a/sources/plugins/indent/lang/tr.js b/sources/plugins/indent/lang/tr.js
new file mode 100644
index 0000000..21520b6
--- /dev/null
+++ b/sources/plugins/indent/lang/tr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'tr', {
6 indent: 'Sekme Arttır',
7 outdent: 'Sekme Azalt'
8} );
diff --git a/sources/plugins/indent/lang/tt.js b/sources/plugins/indent/lang/tt.js
new file mode 100644
index 0000000..604bbba
--- /dev/null
+++ b/sources/plugins/indent/lang/tt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'tt', {
6 indent: 'Отступны арттыру',
7 outdent: 'Отступны кечерәйтү'
8} );
diff --git a/sources/plugins/indent/lang/ug.js b/sources/plugins/indent/lang/ug.js
new file mode 100644
index 0000000..6fec573
--- /dev/null
+++ b/sources/plugins/indent/lang/ug.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'ug', {
6 indent: 'تارايت',
7 outdent: 'كەڭەيت'
8} );
diff --git a/sources/plugins/indent/lang/uk.js b/sources/plugins/indent/lang/uk.js
new file mode 100644
index 0000000..c68ca96
--- /dev/null
+++ b/sources/plugins/indent/lang/uk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'uk', {
6 indent: 'Збільшити відступ',
7 outdent: 'Зменшити відступ'
8} );
diff --git a/sources/plugins/indent/lang/vi.js b/sources/plugins/indent/lang/vi.js
new file mode 100644
index 0000000..7f44c5d
--- /dev/null
+++ b/sources/plugins/indent/lang/vi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'vi', {
6 indent: 'Dịch vào trong',
7 outdent: 'Dịch ra ngoài'
8} );
diff --git a/sources/plugins/indent/lang/zh-cn.js b/sources/plugins/indent/lang/zh-cn.js
new file mode 100644
index 0000000..2c9c383
--- /dev/null
+++ b/sources/plugins/indent/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'zh-cn', {
6 indent: '增加缩进量',
7 outdent: '减少缩进量'
8} );
diff --git a/sources/plugins/indent/lang/zh.js b/sources/plugins/indent/lang/zh.js
new file mode 100644
index 0000000..ee681cb
--- /dev/null
+++ b/sources/plugins/indent/lang/zh.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'indent', 'zh', {
6 indent: '增加縮排',
7 outdent: '減少縮排'
8} );
diff --git a/sources/plugins/indent/plugin.js b/sources/plugins/indent/plugin.js
new file mode 100644
index 0000000..0e887cf
--- /dev/null
+++ b/sources/plugins/indent/plugin.js
@@ -0,0 +1,461 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Increase and Decrease Indent commands.
8 */
9
10( function() {
11 'use strict';
12
13 var TRISTATE_DISABLED = CKEDITOR.TRISTATE_DISABLED,
14 TRISTATE_OFF = CKEDITOR.TRISTATE_OFF;
15
16 CKEDITOR.plugins.add( 'indent', {
17 // jscs:disable maximumLineLength
18 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
19 // jscs:enable maximumLineLength
20 icons: 'indent,indent-rtl,outdent,outdent-rtl', // %REMOVE_LINE_CORE%
21 hidpi: true, // %REMOVE_LINE_CORE%
22
23 init: function( editor ) {
24 var genericDefinition = CKEDITOR.plugins.indent.genericDefinition;
25
26 // Register generic commands.
27 setupGenericListeners( editor, editor.addCommand( 'indent', new genericDefinition( true ) ) );
28 setupGenericListeners( editor, editor.addCommand( 'outdent', new genericDefinition() ) );
29
30 // Create and register toolbar button if possible.
31 if ( editor.ui.addButton ) {
32 editor.ui.addButton( 'Indent', {
33 label: editor.lang.indent.indent,
34 command: 'indent',
35 directional: true,
36 toolbar: 'indent,20'
37 } );
38
39 editor.ui.addButton( 'Outdent', {
40 label: editor.lang.indent.outdent,
41 command: 'outdent',
42 directional: true,
43 toolbar: 'indent,10'
44 } );
45 }
46
47 // Register dirChanged listener.
48 editor.on( 'dirChanged', function( evt ) {
49 var range = editor.createRange(),
50 dataNode = evt.data.node;
51
52 range.setStartBefore( dataNode );
53 range.setEndAfter( dataNode );
54
55 var walker = new CKEDITOR.dom.walker( range ),
56 node;
57
58 while ( ( node = walker.next() ) ) {
59 if ( node.type == CKEDITOR.NODE_ELEMENT ) {
60 // A child with the defined dir is to be ignored.
61 if ( !node.equals( dataNode ) && node.getDirection() ) {
62 range.setStartAfter( node );
63 walker = new CKEDITOR.dom.walker( range );
64 continue;
65 }
66
67 // Switch alignment classes.
68 var classes = editor.config.indentClasses;
69 if ( classes ) {
70 var suffix = ( evt.data.dir == 'ltr' ) ? [ '_rtl', '' ] : [ '', '_rtl' ];
71 for ( var i = 0; i < classes.length; i++ ) {
72 if ( node.hasClass( classes[ i ] + suffix[ 0 ] ) ) {
73 node.removeClass( classes[ i ] + suffix[ 0 ] );
74 node.addClass( classes[ i ] + suffix[ 1 ] );
75 }
76 }
77 }
78
79 // Switch the margins.
80 var marginLeft = node.getStyle( 'margin-right' ),
81 marginRight = node.getStyle( 'margin-left' );
82
83 marginLeft ? node.setStyle( 'margin-left', marginLeft ) : node.removeStyle( 'margin-left' );
84 marginRight ? node.setStyle( 'margin-right', marginRight ) : node.removeStyle( 'margin-right' );
85 }
86 }
87 } );
88 }
89 } );
90
91 /**
92 * Global command class definitions and global helpers.
93 *
94 * @class
95 * @singleton
96 */
97 CKEDITOR.plugins.indent = {
98 /**
99 * A base class for a generic command definition, responsible mainly for creating
100 * Increase Indent and Decrease Indent toolbar buttons as well as for refreshing
101 * UI states.
102 *
103 * Commands of this class do not perform any indentation by themselves. They
104 * delegate this job to content-specific indentation commands (i.e. indentlist).
105 *
106 * @class CKEDITOR.plugins.indent.genericDefinition
107 * @extends CKEDITOR.commandDefinition
108 * @param {CKEDITOR.editor} editor The editor instance this command will be
109 * applied to.
110 * @param {String} name The name of the command.
111 * @param {Boolean} [isIndent] Defines the command as indenting or outdenting.
112 */
113 genericDefinition: function( isIndent ) {
114 /**
115 * Determines whether the command belongs to the indentation family.
116 * Otherwise it is assumed to be an outdenting command.
117 *
118 * @readonly
119 * @property {Boolean} [=false]
120 */
121 this.isIndent = !!isIndent;
122
123 // Mimic naive startDisabled behavior for outdent.
124 this.startDisabled = !this.isIndent;
125 },
126
127 /**
128 * A base class for specific indentation command definitions responsible for
129 * handling a pre-defined set of elements i.e. indentlist for lists or
130 * indentblock for text block elements.
131 *
132 * Commands of this class perform indentation operations and modify the DOM structure.
133 * They listen for events fired by {@link CKEDITOR.plugins.indent.genericDefinition}
134 * and execute defined actions.
135 *
136 * **NOTE**: This is not an {@link CKEDITOR.command editor command}.
137 * Context-specific commands are internal, for indentation system only.
138 *
139 * @class CKEDITOR.plugins.indent.specificDefinition
140 * @param {CKEDITOR.editor} editor The editor instance this command will be
141 * applied to.
142 * @param {String} name The name of the command.
143 * @param {Boolean} [isIndent] Defines the command as indenting or outdenting.
144 */
145 specificDefinition: function( editor, name, isIndent ) {
146 this.name = name;
147 this.editor = editor;
148
149 /**
150 * An object of jobs handled by the command. Each job consists
151 * of two functions: `refresh` and `exec` as well as the execution priority.
152 *
153 * * The `refresh` function determines whether a job is doable for
154 * a particular context. These functions are executed in the
155 * order of priorities, one by one, for all plugins that registered
156 * jobs. As jobs are related to generic commands, refreshing
157 * occurs when the global command is firing the `refresh` event.
158 *
159 * **Note**: This function must return either {@link CKEDITOR#TRISTATE_DISABLED}
160 * or {@link CKEDITOR#TRISTATE_OFF}.
161 *
162 * * The `exec` function modifies the DOM if possible. Just like
163 * `refresh`, `exec` functions are executed in the order of priorities
164 * while the generic command is executed. This function is not executed
165 * if `refresh` for this job returned {@link CKEDITOR#TRISTATE_DISABLED}.
166 *
167 * **Note**: This function must return a Boolean value, indicating whether it
168 * was successful. If a job was successful, then no other jobs are being executed.
169 *
170 * Sample definition:
171 *
172 * command.jobs = {
173 * // Priority = 20.
174 * '20': {
175 * refresh( editor, path ) {
176 * if ( condition )
177 * return CKEDITOR.TRISTATE_OFF;
178 * else
179 * return CKEDITOR.TRISTATE_DISABLED;
180 * },
181 * exec( editor ) {
182 * // DOM modified! This was OK.
183 * return true;
184 * }
185 * },
186 * // Priority = 60. This job is done later.
187 * '60': {
188 * // Another job.
189 * }
190 * };
191 *
192 * For additional information, please check comments for
193 * the `setupGenericListeners` function.
194 *
195 * @readonly
196 * @property {Object} [={}]
197 */
198 this.jobs = {};
199
200 /**
201 * Determines whether the editor that the command belongs to has
202 * {@link CKEDITOR.config#enterMode config.enterMode} set to {@link CKEDITOR#ENTER_BR}.
203 *
204 * @readonly
205 * @see CKEDITOR.config#enterMode
206 * @property {Boolean} [=false]
207 */
208 this.enterBr = editor.config.enterMode == CKEDITOR.ENTER_BR;
209
210 /**
211 * Determines whether the command belongs to the indentation family.
212 * Otherwise it is assumed to be an outdenting command.
213 *
214 * @readonly
215 * @property {Boolean} [=false]
216 */
217 this.isIndent = !!isIndent;
218
219 /**
220 * The name of the global command related to this one.
221 *
222 * @readonly
223 */
224 this.relatedGlobal = isIndent ? 'indent' : 'outdent';
225
226 /**
227 * A keystroke associated with this command (*Tab* or *Shift+Tab*).
228 *
229 * @readonly
230 */
231 this.indentKey = isIndent ? 9 : CKEDITOR.SHIFT + 9;
232
233 /**
234 * Stores created markers for the command so they can eventually be
235 * purged after the `exec` function is run.
236 */
237 this.database = {};
238 },
239
240 /**
241 * Registers content-specific commands as a part of the indentation system
242 * directed by generic commands. Once a command is registered,
243 * it listens for events of a related generic command.
244 *
245 * CKEDITOR.plugins.indent.registerCommands( editor, {
246 * 'indentlist': new indentListCommand( editor, 'indentlist' ),
247 * 'outdentlist': new indentListCommand( editor, 'outdentlist' )
248 * } );
249 *
250 * Content-specific commands listen for the generic command's `exec` and
251 * try to execute their own jobs, one after another. If some execution is
252 * successful, `evt.data.done` is set so no more jobs (commands) are involved.
253 *
254 * Content-specific commands also listen for the generic command's `refresh`
255 * and fill the `evt.data.states` object with states of jobs. A generic command
256 * uses this data to determine its own state and to update the UI.
257 *
258 * @member CKEDITOR.plugins.indent
259 * @param {CKEDITOR.editor} editor The editor instance this command is
260 * applied to.
261 * @param {Object} commands An object of {@link CKEDITOR.command}.
262 */
263 registerCommands: function( editor, commands ) {
264 editor.on( 'pluginsLoaded', function() {
265 for ( var name in commands ) {
266 ( function( editor, command ) {
267 var relatedGlobal = editor.getCommand( command.relatedGlobal );
268
269 for ( var priority in command.jobs ) {
270 // Observe generic exec event and execute command when necessary.
271 // If the command was successfully handled by the command and
272 // DOM has been modified, stop event propagation so no other plugin
273 // will bother. Job is done.
274 relatedGlobal.on( 'exec', function( evt ) {
275 if ( evt.data.done )
276 return;
277
278 // Make sure that anything this command will do is invisible
279 // for undoManager. What undoManager only can see and
280 // remember is the execution of the global command (relatedGlobal).
281 editor.fire( 'lockSnapshot' );
282
283 if ( command.execJob( editor, priority ) )
284 evt.data.done = true;
285
286 editor.fire( 'unlockSnapshot' );
287
288 // Clean up the markers.
289 CKEDITOR.dom.element.clearAllMarkers( command.database );
290 }, this, null, priority );
291
292 // Observe generic refresh event and force command refresh.
293 // Once refreshed, save command state in event data
294 // so generic command plugin can update its own state and UI.
295 relatedGlobal.on( 'refresh', function( evt ) {
296 if ( !evt.data.states )
297 evt.data.states = {};
298
299 evt.data.states[ command.name + '@' + priority ] =
300 command.refreshJob( editor, priority, evt.data.path );
301 }, this, null, priority );
302 }
303
304 // Since specific indent commands have no UI elements,
305 // they need to be manually registered as a editor feature.
306 editor.addFeature( command );
307 } )( this, commands[ name ] );
308 }
309 } );
310 }
311 };
312
313 CKEDITOR.plugins.indent.genericDefinition.prototype = {
314 context: 'p',
315
316 exec: function() {}
317 };
318
319 CKEDITOR.plugins.indent.specificDefinition.prototype = {
320 /**
321 * Executes the content-specific procedure if the context is correct.
322 * It calls the `exec` function of a job of the given `priority`
323 * that modifies the DOM.
324 *
325 * @param {CKEDITOR.editor} editor The editor instance this command
326 * will be applied to.
327 * @param {Number} priority The priority of the job to be executed.
328 * @returns {Boolean} Indicates whether the job was successful.
329 */
330 execJob: function( editor, priority ) {
331 var job = this.jobs[ priority ];
332
333 if ( job.state != TRISTATE_DISABLED )
334 return job.exec.call( this, editor );
335 },
336
337 /**
338 * Calls the `refresh` function of a job of the given `priority`.
339 * The function returns the state of the job which can be either
340 * {@link CKEDITOR#TRISTATE_DISABLED} or {@link CKEDITOR#TRISTATE_OFF}.
341 *
342 * @param {CKEDITOR.editor} editor The editor instance this command
343 * will be applied to.
344 * @param {Number} priority The priority of the job to be executed.
345 * @returns {Number} The state of the job.
346 */
347 refreshJob: function( editor, priority, path ) {
348 var job = this.jobs[ priority ];
349
350 if ( !editor.activeFilter.checkFeature( this ) )
351 job.state = TRISTATE_DISABLED;
352 else
353 job.state = job.refresh.call( this, editor, path );
354
355 return job.state;
356 },
357
358 /**
359 * Checks if the element path contains the element handled
360 * by this indentation command.
361 *
362 * @param {CKEDITOR.dom.elementPath} node A path to be checked.
363 * @returns {CKEDITOR.dom.element}
364 */
365 getContext: function( path ) {
366 return path.contains( this.context );
367 }
368 };
369
370 /**
371 * Attaches event listeners for this generic command. Since the indentation
372 * system is event-oriented, generic commands communicate with
373 * content-specific commands using the `exec` and `refresh` events.
374 *
375 * Listener priorities are crucial. Different indentation phases
376 * are executed with different priorities.
377 *
378 * For the `exec` event:
379 *
380 * * 0: Selection and bookmarks are saved by the generic command.
381 * * 1-99: Content-specific commands try to indent the code by executing
382 * their own jobs ({@link CKEDITOR.plugins.indent.specificDefinition#jobs}).
383 * * 100: Bookmarks are re-selected by the generic command.
384 *
385 * The visual interpretation looks as follows:
386 *
387 * +------------------+
388 * | Exec event fired |
389 * +------ + ---------+
390 * |
391 * 0 -<----------+ Selection and bookmarks saved.
392 * |
393 * |
394 * 25 -<---+ Exec 1st job of plugin#1 (return false, continuing...).
395 * |
396 * |
397 * 50 -<---+ Exec 1st job of plugin#2 (return false, continuing...).
398 * |
399 * |
400 * 75 -<---+ Exec 2nd job of plugin#1 (only if plugin#2 failed).
401 * |
402 * |
403 * 100 -<-----------+ Re-select bookmarks, clean-up.
404 * |
405 * +-------- v ----------+
406 * | Exec event finished |
407 * +---------------------+
408 *
409 * For the `refresh` event:
410 *
411 * * <100: Content-specific commands refresh their job states according
412 * to the given path. Jobs save their states in the `evt.data.states` object
413 * passed along with the event. This can be either {@link CKEDITOR#TRISTATE_DISABLED}
414 * or {@link CKEDITOR#TRISTATE_OFF}.
415 * * 100: Command state is determined according to what states
416 * have been returned by content-specific jobs (`evt.data.states`).
417 * UI elements are updated at this stage.
418 *
419 * **Note**: If there is at least one job with the {@link CKEDITOR#TRISTATE_OFF} state,
420 * then the generic command state is also {@link CKEDITOR#TRISTATE_OFF}. Otherwise,
421 * the command state is {@link CKEDITOR#TRISTATE_DISABLED}.
422 *
423 * @param {CKEDITOR.command} command The command to be set up.
424 * @private
425 */
426 function setupGenericListeners( editor, command ) {
427 var selection, bookmarks;
428
429 // Set the command state according to content-specific
430 // command states.
431 command.on( 'refresh', function( evt ) {
432 // If no state comes with event data, disable command.
433 var states = [ TRISTATE_DISABLED ];
434
435 for ( var s in evt.data.states )
436 states.push( evt.data.states[ s ] );
437
438 this.setState( CKEDITOR.tools.search( states, TRISTATE_OFF ) ? TRISTATE_OFF : TRISTATE_DISABLED );
439 }, command, null, 100 );
440
441 // Initialization. Save bookmarks and mark event as not handled
442 // by any plugin (command) yet.
443 command.on( 'exec', function( evt ) {
444 selection = editor.getSelection();
445 bookmarks = selection.createBookmarks( 1 );
446
447 // Mark execution as not handled yet.
448 if ( !evt.data )
449 evt.data = {};
450
451 evt.data.done = false;
452 }, command, null, 0 );
453
454 // Housekeeping. Make sure selectionChange will be called.
455 // Also re-select previously saved bookmarks.
456 command.on( 'exec', function() {
457 editor.forceNextSelectionCheck();
458 selection.selectBookmarks( bookmarks );
459 }, command, null, 100 );
460 }
461} )();
diff --git a/sources/plugins/indentblock/plugin.js b/sources/plugins/indentblock/plugin.js
new file mode 100644
index 0000000..b39fd73
--- /dev/null
+++ b/sources/plugins/indentblock/plugin.js
@@ -0,0 +1,312 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Handles the indentation of block elements.
8 */
9
10( function() {
11 'use strict';
12
13 var $listItem = CKEDITOR.dtd.$listItem,
14 $list = CKEDITOR.dtd.$list,
15 TRISTATE_DISABLED = CKEDITOR.TRISTATE_DISABLED,
16 TRISTATE_OFF = CKEDITOR.TRISTATE_OFF;
17
18 CKEDITOR.plugins.add( 'indentblock', {
19 requires: 'indent',
20 init: function( editor ) {
21 var globalHelpers = CKEDITOR.plugins.indent,
22 classes = editor.config.indentClasses;
23
24 // Register commands.
25 globalHelpers.registerCommands( editor, {
26 indentblock: new commandDefinition( editor, 'indentblock', true ),
27 outdentblock: new commandDefinition( editor, 'outdentblock' )
28 } );
29
30 function commandDefinition() {
31 globalHelpers.specificDefinition.apply( this, arguments );
32
33 this.allowedContent = {
34 'div h1 h2 h3 h4 h5 h6 ol p pre ul': {
35 // Do not add elements, but only text-align style if element is validated by other rule.
36 propertiesOnly: true,
37 styles: !classes ? 'margin-left,margin-right' : null,
38 classes: classes || null
39 }
40 };
41
42 this.contentTransformations = [
43 [ 'div: splitMarginShorthand' ],
44 [ 'h1: splitMarginShorthand' ],
45 [ 'h2: splitMarginShorthand' ],
46 [ 'h3: splitMarginShorthand' ],
47 [ 'h4: splitMarginShorthand' ],
48 [ 'h5: splitMarginShorthand' ],
49 [ 'h6: splitMarginShorthand' ],
50 [ 'ol: splitMarginShorthand' ],
51 [ 'p: splitMarginShorthand' ],
52 [ 'pre: splitMarginShorthand' ],
53 [ 'ul: splitMarginShorthand' ]
54 ];
55
56 if ( this.enterBr )
57 this.allowedContent.div = true;
58
59 this.requiredContent = ( this.enterBr ? 'div' : 'p' ) +
60 ( classes ? '(' + classes.join( ',' ) + ')' : '{margin-left}' );
61
62 this.jobs = {
63 '20': {
64 refresh: function( editor, path ) {
65 var firstBlock = path.block || path.blockLimit;
66
67 // Switch context from somewhere inside list item to list item,
68 // if not found just assign self (doing nothing).
69 if ( !firstBlock.is( $listItem ) ) {
70 var ascendant = firstBlock.getAscendant( $listItem );
71
72 firstBlock = ( ascendant && path.contains( ascendant ) ) || firstBlock;
73 }
74
75 // Switch context from list item to list
76 // because indentblock can indent entire list
77 // but not a single list element.
78
79 if ( firstBlock.is( $listItem ) )
80 firstBlock = firstBlock.getParent();
81
82 // [-] Context in the path or ENTER_BR
83 //
84 // Don't try to indent if the element is out of
85 // this plugin's scope. This assertion is omitted
86 // if ENTER_BR is in use since there may be no block
87 // in the path.
88
89 if ( !this.enterBr && !this.getContext( path ) )
90 return TRISTATE_DISABLED;
91
92 else if ( classes ) {
93
94 // [+] Context in the path or ENTER_BR
95 // [+] IndentClasses
96 //
97 // If there are indentation classes, check if reached
98 // the highest level of indentation. If so, disable
99 // the command.
100
101 if ( indentClassLeft.call( this, firstBlock, classes ) )
102 return TRISTATE_OFF;
103 else
104 return TRISTATE_DISABLED;
105 } else {
106
107 // [+] Context in the path or ENTER_BR
108 // [-] IndentClasses
109 // [+] Indenting
110 //
111 // No indent-level limitations due to indent classes.
112 // Indent-like command can always be executed.
113
114 if ( this.isIndent )
115 return TRISTATE_OFF;
116
117 // [+] Context in the path or ENTER_BR
118 // [-] IndentClasses
119 // [-] Indenting
120 // [-] Block in the path
121 //
122 // No block in path. There's no element to apply indentation
123 // so disable the command.
124
125 else if ( !firstBlock )
126 return TRISTATE_DISABLED;
127
128 // [+] Context in the path or ENTER_BR
129 // [-] IndentClasses
130 // [-] Indenting
131 // [+] Block in path.
132 //
133 // Not using indentClasses but there is firstBlock.
134 // We can calculate current indentation level and
135 // try to increase/decrease it.
136
137 else {
138 return CKEDITOR[
139 ( getIndent( firstBlock ) || 0 ) <= 0 ? 'TRISTATE_DISABLED' : 'TRISTATE_OFF'
140 ];
141 }
142 }
143 },
144
145 exec: function( editor ) {
146 var selection = editor.getSelection(),
147 range = selection && selection.getRanges()[ 0 ],
148 nearestListBlock;
149
150 // If there's some list in the path, then it will be
151 // a full-list indent by increasing or decreasing margin property.
152 if ( ( nearestListBlock = editor.elementPath().contains( $list ) ) )
153 indentElement.call( this, nearestListBlock, classes );
154
155 // If no list in the path, use iterator to indent all the possible
156 // paragraphs in the range, creating them if necessary.
157 else {
158 var iterator = range.createIterator(),
159 enterMode = editor.config.enterMode,
160 block;
161
162 iterator.enforceRealBlocks = true;
163 iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
164
165 while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) ) {
166 if ( !block.isReadOnly() )
167 indentElement.call( this, block, classes );
168 }
169 }
170
171 return true;
172 }
173 }
174 };
175 }
176
177 CKEDITOR.tools.extend( commandDefinition.prototype, globalHelpers.specificDefinition.prototype, {
178 // Elements that, if in an elementpath, will be handled by this
179 // command. They restrict the scope of the plugin.
180 context: { div: 1, dl: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, ul: 1, ol: 1, p: 1, pre: 1, table: 1 },
181
182 // A regex built on config#indentClasses to detect whether an
183 // element has some indentClass or not.
184 classNameRegex: classes ? new RegExp( '(?:^|\\s+)(' + classes.join( '|' ) + ')(?=$|\\s)' ) : null
185 } );
186 }
187 } );
188
189 // Generic indentation procedure for indentation of any element
190 // either with margin property or config#indentClass.
191 function indentElement( element, classes, dir ) {
192 if ( element.getCustomData( 'indent_processed' ) )
193 return;
194
195 var editor = this.editor,
196 isIndent = this.isIndent;
197
198 if ( classes ) {
199 // Transform current class f to indent step index.
200 var indentClass = element.$.className.match( this.classNameRegex ),
201 indentStep = 0;
202
203 if ( indentClass ) {
204 indentClass = indentClass[ 1 ];
205 indentStep = CKEDITOR.tools.indexOf( classes, indentClass ) + 1;
206 }
207
208 // Operate on indent step index, transform indent step index
209 // back to class name.
210 if ( ( indentStep += isIndent ? 1 : -1 ) < 0 )
211 return;
212
213 indentStep = Math.min( indentStep, classes.length );
214 indentStep = Math.max( indentStep, 0 );
215 element.$.className = CKEDITOR.tools.ltrim( element.$.className.replace( this.classNameRegex, '' ) );
216
217 if ( indentStep > 0 )
218 element.addClass( classes[ indentStep - 1 ] );
219 } else {
220 var indentCssProperty = getIndentCss( element, dir ),
221 currentOffset = parseInt( element.getStyle( indentCssProperty ), 10 ),
222 indentOffset = editor.config.indentOffset || 40;
223
224 if ( isNaN( currentOffset ) )
225 currentOffset = 0;
226
227 currentOffset += ( isIndent ? 1 : -1 ) * indentOffset;
228
229 if ( currentOffset < 0 )
230 return;
231
232 currentOffset = Math.max( currentOffset, 0 );
233 currentOffset = Math.ceil( currentOffset / indentOffset ) * indentOffset;
234
235 element.setStyle(
236 indentCssProperty,
237 currentOffset ? currentOffset + ( editor.config.indentUnit || 'px' ) : ''
238 );
239
240 if ( element.getAttribute( 'style' ) === '' )
241 element.removeAttribute( 'style' );
242 }
243
244 CKEDITOR.dom.element.setMarker( this.database, element, 'indent_processed', 1 );
245
246 return;
247 }
248
249 // Method that checks if current indentation level for an element
250 // reached the limit determined by config#indentClasses.
251 function indentClassLeft( node, classes ) {
252 var indentClass = node.$.className.match( this.classNameRegex ),
253 isIndent = this.isIndent;
254
255 // If node has one of the indentClasses:
256 // * If it holds the topmost indentClass, then
257 // no more classes have left.
258 // * If it holds any other indentClass, it can use the next one
259 // or the previous one.
260 // * Outdent is always possible. We can remove indentClass.
261 if ( indentClass )
262 return isIndent ? indentClass[ 1 ] != classes.slice( -1 ) : true;
263
264 // If node has no class which belongs to indentClasses,
265 // then it is at 0-level. It can be indented but not outdented.
266 else
267 return isIndent;
268 }
269
270 // Determines indent CSS property for an element according to
271 // what is the direction of such element. It can be either `margin-left`
272 // or `margin-right`.
273 function getIndentCss( element, dir ) {
274 return ( dir || element.getComputedStyle( 'direction' ) ) == 'ltr' ? 'margin-left' : 'margin-right';
275 }
276
277 // Return the numerical indent value of margin-left|right of an element,
278 // considering element's direction. If element has no margin specified,
279 // NaN is returned.
280 function getIndent( element ) {
281 return parseInt( element.getStyle( getIndentCss( element ) ), 10 );
282 }
283} )();
284
285/**
286 * A list of classes to use for indenting the contents. If set to `null`, no classes will be used
287 * and instead the {@link #indentUnit} and {@link #indentOffset} properties will be used.
288 *
289 * // Use the 'Indent1', 'Indent2', 'Indent3' classes.
290 * config.indentClasses = ['Indent1', 'Indent2', 'Indent3'];
291 *
292 * @cfg {Array} [indentClasses=null]
293 * @member CKEDITOR.config
294 */
295
296/**
297 * The size in {@link CKEDITOR.config#indentUnit indentation units} of each indentation step.
298 *
299 * config.indentOffset = 4;
300 *
301 * @cfg {Number} [indentOffset=40]
302 * @member CKEDITOR.config
303 */
304
305/**
306 * The unit used for {@link CKEDITOR.config#indentOffset indentation offset}.
307 *
308 * config.indentUnit = 'em';
309 *
310 * @cfg {String} [indentUnit='px']
311 * @member CKEDITOR.config
312 */
diff --git a/sources/plugins/indentlist/plugin.js b/sources/plugins/indentlist/plugin.js
new file mode 100644
index 0000000..15c661f
--- /dev/null
+++ b/sources/plugins/indentlist/plugin.js
@@ -0,0 +1,318 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Handles the indentation of lists.
8 */
9
10( function() {
11 'use strict';
12
13 var isNotWhitespaces = CKEDITOR.dom.walker.whitespaces( true ),
14 isNotBookmark = CKEDITOR.dom.walker.bookmark( false, true ),
15 TRISTATE_DISABLED = CKEDITOR.TRISTATE_DISABLED,
16 TRISTATE_OFF = CKEDITOR.TRISTATE_OFF;
17
18 CKEDITOR.plugins.add( 'indentlist', {
19 requires: 'indent',
20 init: function( editor ) {
21 var globalHelpers = CKEDITOR.plugins.indent;
22
23 // Register commands.
24 globalHelpers.registerCommands( editor, {
25 indentlist: new commandDefinition( editor, 'indentlist', true ),
26 outdentlist: new commandDefinition( editor, 'outdentlist' )
27 } );
28
29 function commandDefinition( editor ) {
30 globalHelpers.specificDefinition.apply( this, arguments );
31
32 // Require ul OR ol list.
33 this.requiredContent = [ 'ul', 'ol' ];
34
35 // Indent and outdent lists with TAB/SHIFT+TAB key. Indenting can
36 // be done for any list item that isn't the first child of the parent.
37 editor.on( 'key', function( evt ) {
38 if ( editor.mode != 'wysiwyg' )
39 return;
40
41 if ( evt.data.keyCode == this.indentKey ) {
42 var list = this.getContext( editor.elementPath() );
43
44 if ( list ) {
45 // Don't indent if in first list item of the parent.
46 // Outdent, however, can always be done to collapse
47 // the list into a paragraph (div).
48 if ( this.isIndent && CKEDITOR.plugins.indentList.firstItemInPath( this.context, editor.elementPath(), list ) )
49 return;
50
51 // Exec related global indentation command. Global
52 // commands take care of bookmarks and selection,
53 // so it's much easier to use them instead of
54 // content-specific commands.
55 editor.execCommand( this.relatedGlobal );
56
57 // Cancel the key event so editor doesn't lose focus.
58 evt.cancel();
59 }
60 }
61 }, this );
62
63 // There are two different jobs for this plugin:
64 //
65 // * Indent job (priority=10), before indentblock.
66 //
67 // This job is before indentblock because, if this plugin is
68 // loaded it has higher priority over indentblock. It means that,
69 // if possible, nesting is performed, and then block manipulation,
70 // if necessary.
71 //
72 // * Outdent job (priority=30), after outdentblock.
73 //
74 // This job got to be after outdentblock because in some cases
75 // (margin, config#indentClass on list) outdent must be done on
76 // block-level.
77
78 this.jobs[ this.isIndent ? 10 : 30 ] = {
79 refresh: this.isIndent ?
80 function( editor, path ) {
81 var list = this.getContext( path ),
82 inFirstListItem = CKEDITOR.plugins.indentList.firstItemInPath( this.context, path, list );
83
84 if ( !list || !this.isIndent || inFirstListItem )
85 return TRISTATE_DISABLED;
86
87 return TRISTATE_OFF;
88 } : function( editor, path ) {
89 var list = this.getContext( path );
90
91 if ( !list || this.isIndent )
92 return TRISTATE_DISABLED;
93
94 return TRISTATE_OFF;
95 },
96
97 exec: CKEDITOR.tools.bind( indentList, this )
98 };
99 }
100
101 CKEDITOR.tools.extend( commandDefinition.prototype, globalHelpers.specificDefinition.prototype, {
102 // Elements that, if in an elementpath, will be handled by this
103 // command. They restrict the scope of the plugin.
104 context: { ol: 1, ul: 1 }
105 } );
106 }
107 } );
108
109 function indentList( editor ) {
110 var that = this,
111 database = this.database,
112 context = this.context;
113
114 function indent( listNode ) {
115 // Our starting and ending points of the range might be inside some blocks under a list item...
116 // So before playing with the iterator, we need to expand the block to include the list items.
117 var startContainer = range.startContainer,
118 endContainer = range.endContainer;
119 while ( startContainer && !startContainer.getParent().equals( listNode ) )
120 startContainer = startContainer.getParent();
121 while ( endContainer && !endContainer.getParent().equals( listNode ) )
122 endContainer = endContainer.getParent();
123
124 if ( !startContainer || !endContainer )
125 return false;
126
127 // Now we can iterate over the individual items on the same tree depth.
128 var block = startContainer,
129 itemsToMove = [],
130 stopFlag = false;
131
132 while ( !stopFlag ) {
133 if ( block.equals( endContainer ) )
134 stopFlag = true;
135
136 itemsToMove.push( block );
137 block = block.getNext();
138 }
139
140 if ( itemsToMove.length < 1 )
141 return false;
142
143 // Do indent or outdent operations on the array model of the list, not the
144 // list's DOM tree itself. The array model demands that it knows as much as
145 // possible about the surrounding lists, we need to feed it the further
146 // ancestor node that is still a list.
147 var listParents = listNode.getParents( true );
148 for ( var i = 0; i < listParents.length; i++ ) {
149 if ( listParents[ i ].getName && context[ listParents[ i ].getName() ] ) {
150 listNode = listParents[ i ];
151 break;
152 }
153 }
154
155 var indentOffset = that.isIndent ? 1 : -1,
156 startItem = itemsToMove[ 0 ],
157 lastItem = itemsToMove[ itemsToMove.length - 1 ],
158
159 // Convert the list DOM tree into a one dimensional array.
160 listArray = CKEDITOR.plugins.list.listToArray( listNode, database ),
161
162 // Apply indenting or outdenting on the array.
163 baseIndent = listArray[ lastItem.getCustomData( 'listarray_index' ) ].indent;
164
165 for ( i = startItem.getCustomData( 'listarray_index' ); i <= lastItem.getCustomData( 'listarray_index' ); i++ ) {
166 listArray[ i ].indent += indentOffset;
167 // Make sure the newly created sublist get a brand-new element of the same type. (#5372)
168 if ( indentOffset > 0 ) {
169 var listRoot = listArray[ i ].parent;
170 listArray[ i ].parent = new CKEDITOR.dom.element( listRoot.getName(), listRoot.getDocument() );
171 }
172 }
173
174 for ( i = lastItem.getCustomData( 'listarray_index' ) + 1; i < listArray.length && listArray[ i ].indent > baseIndent; i++ )
175 listArray[ i ].indent += indentOffset;
176
177 // Convert the array back to a DOM forest (yes we might have a few subtrees now).
178 // And replace the old list with the new forest.
179 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, listNode.getDirection() );
180
181 // Avoid nested <li> after outdent even they're visually same,
182 // recording them for later refactoring.(#3982)
183 if ( !that.isIndent ) {
184 var parentLiElement;
185 if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) ) {
186 var children = newList.listNode.getChildren(),
187 pendingLis = [],
188 count = children.count(),
189 child;
190
191 for ( i = count - 1; i >= 0; i-- ) {
192 if ( ( child = children.getItem( i ) ) && child.is && child.is( 'li' ) )
193 pendingLis.push( child );
194 }
195 }
196 }
197
198 if ( newList )
199 newList.listNode.replace( listNode );
200
201 // Move the nested <li> to be appeared after the parent.
202 if ( pendingLis && pendingLis.length ) {
203 for ( i = 0; i < pendingLis.length; i++ ) {
204 var li = pendingLis[ i ],
205 followingList = li;
206
207 // Nest preceding <ul>/<ol> inside current <li> if any.
208 while ( ( followingList = followingList.getNext() ) && followingList.is && followingList.getName() in context ) {
209 // IE requires a filler NBSP for nested list inside empty list item,
210 // otherwise the list item will be inaccessiable. (#4476)
211 if ( CKEDITOR.env.needsNbspFiller && !li.getFirst( neitherWhitespacesNorBookmark ) )
212 li.append( range.document.createText( '\u00a0' ) );
213
214 li.append( followingList );
215 }
216
217 li.insertAfter( parentLiElement );
218 }
219 }
220
221 if ( newList )
222 editor.fire( 'contentDomInvalidated' );
223
224 return true;
225 }
226
227 var selection = editor.getSelection(),
228 ranges = selection && selection.getRanges(),
229 iterator = ranges.createIterator(),
230 range;
231
232 while ( ( range = iterator.getNextRange() ) ) {
233 var nearestListBlock = range.getCommonAncestor();
234
235 while ( nearestListBlock && !( nearestListBlock.type == CKEDITOR.NODE_ELEMENT && context[ nearestListBlock.getName() ] ) ) {
236 // Avoid having plugin propagate to parent of editor in inline mode by canceling the indentation. (#12796)
237 if ( editor.editable().equals( nearestListBlock ) ) {
238 nearestListBlock = false;
239 break;
240 }
241 nearestListBlock = nearestListBlock.getParent();
242 }
243
244 // Avoid having selection boundaries out of the list.
245 // <ul><li>[...</li></ul><p>...]</p> => <ul><li>[...]</li></ul><p>...</p>
246 if ( !nearestListBlock ) {
247 if ( ( nearestListBlock = range.startPath().contains( context ) ) )
248 range.setEndAt( nearestListBlock, CKEDITOR.POSITION_BEFORE_END );
249 }
250
251 // Avoid having selection enclose the entire list. (#6138)
252 // [<ul><li>...</li></ul>] =><ul><li>[...]</li></ul>
253 if ( !nearestListBlock ) {
254 var selectedNode = range.getEnclosedNode();
255 if ( selectedNode && selectedNode.type == CKEDITOR.NODE_ELEMENT && selectedNode.getName() in context ) {
256 range.setStartAt( selectedNode, CKEDITOR.POSITION_AFTER_START );
257 range.setEndAt( selectedNode, CKEDITOR.POSITION_BEFORE_END );
258 nearestListBlock = selectedNode;
259 }
260 }
261
262 // Avoid selection anchors under list root.
263 // <ul>[<li>...</li>]</ul> => <ul><li>[...]</li></ul>
264 if ( nearestListBlock && range.startContainer.type == CKEDITOR.NODE_ELEMENT && range.startContainer.getName() in context ) {
265 var walker = new CKEDITOR.dom.walker( range );
266 walker.evaluator = listItem;
267 range.startContainer = walker.next();
268 }
269
270 if ( nearestListBlock && range.endContainer.type == CKEDITOR.NODE_ELEMENT && range.endContainer.getName() in context ) {
271 walker = new CKEDITOR.dom.walker( range );
272 walker.evaluator = listItem;
273 range.endContainer = walker.previous();
274 }
275
276 if ( nearestListBlock )
277 return indent( nearestListBlock );
278 }
279 return 0;
280 }
281
282 // Determines whether a node is a list <li> element.
283 function listItem( node ) {
284 return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );
285 }
286
287 function neitherWhitespacesNorBookmark( node ) {
288 return isNotWhitespaces( node ) && isNotBookmark( node );
289 }
290
291 /**
292 * Global namespace for methods exposed by the Indent List plugin.
293 *
294 * @singleton
295 * @class
296 */
297 CKEDITOR.plugins.indentList = {};
298
299 /**
300 * Checks whether the first child of the list is in the path.
301 * The list can be extracted from the path or given explicitly
302 * e.g. for better performance if cached.
303 *
304 * @since 4.4.6
305 * @param {Object} query See the {@link CKEDITOR.dom.elementPath#contains} method arguments.
306 * @param {CKEDITOR.dom.elementPath} path
307 * @param {CKEDITOR.dom.element} [list]
308 * @returns {Boolean}
309 * @member CKEDITOR.plugins.indentList
310 */
311 CKEDITOR.plugins.indentList.firstItemInPath = function( query, path, list ) {
312 var firstListItemInPath = path.contains( listItem );
313 if ( !list )
314 list = path.contains( query );
315
316 return list && firstListItemInPath && firstListItemInPath.equals( list.getFirst( listItem ) );
317 };
318} )();
diff --git a/sources/plugins/justify/icons/hidpi/justifyblock.png b/sources/plugins/justify/icons/hidpi/justifyblock.png
new file mode 100644
index 0000000..5c0cf43
--- /dev/null
+++ b/sources/plugins/justify/icons/hidpi/justifyblock.png
Binary files differ
diff --git a/sources/plugins/justify/icons/hidpi/justifycenter.png b/sources/plugins/justify/icons/hidpi/justifycenter.png
new file mode 100644
index 0000000..fd751be
--- /dev/null
+++ b/sources/plugins/justify/icons/hidpi/justifycenter.png
Binary files differ
diff --git a/sources/plugins/justify/icons/hidpi/justifyleft.png b/sources/plugins/justify/icons/hidpi/justifyleft.png
new file mode 100644
index 0000000..a109ad3
--- /dev/null
+++ b/sources/plugins/justify/icons/hidpi/justifyleft.png
Binary files differ
diff --git a/sources/plugins/justify/icons/hidpi/justifyright.png b/sources/plugins/justify/icons/hidpi/justifyright.png
new file mode 100644
index 0000000..5125d56
--- /dev/null
+++ b/sources/plugins/justify/icons/hidpi/justifyright.png
Binary files differ
diff --git a/sources/plugins/justify/icons/justifyblock.png b/sources/plugins/justify/icons/justifyblock.png
new file mode 100644
index 0000000..ffe0620
--- /dev/null
+++ b/sources/plugins/justify/icons/justifyblock.png
Binary files differ
diff --git a/sources/plugins/justify/icons/justifycenter.png b/sources/plugins/justify/icons/justifycenter.png
new file mode 100644
index 0000000..8b5b40f
--- /dev/null
+++ b/sources/plugins/justify/icons/justifycenter.png
Binary files differ
diff --git a/sources/plugins/justify/icons/justifyleft.png b/sources/plugins/justify/icons/justifyleft.png
new file mode 100644
index 0000000..a60d079
--- /dev/null
+++ b/sources/plugins/justify/icons/justifyleft.png
Binary files differ
diff --git a/sources/plugins/justify/icons/justifyright.png b/sources/plugins/justify/icons/justifyright.png
new file mode 100644
index 0000000..21de814
--- /dev/null
+++ b/sources/plugins/justify/icons/justifyright.png
Binary files differ
diff --git a/sources/plugins/justify/lang/af.js b/sources/plugins/justify/lang/af.js
new file mode 100644
index 0000000..9f5c303
--- /dev/null
+++ b/sources/plugins/justify/lang/af.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'af', {
6 block: 'Uitvul',
7 center: 'Sentreer',
8 left: 'Links oplyn',
9 right: 'Regs oplyn'
10} );
diff --git a/sources/plugins/justify/lang/ar.js b/sources/plugins/justify/lang/ar.js
new file mode 100644
index 0000000..6c414be
--- /dev/null
+++ b/sources/plugins/justify/lang/ar.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ar', {
6 block: 'ضبط',
7 center: 'توسيط',
8 left: 'محاذاة إلى اليسار',
9 right: 'محاذاة إلى اليمين'
10} );
diff --git a/sources/plugins/justify/lang/az.js b/sources/plugins/justify/lang/az.js
new file mode 100644
index 0000000..9360568
--- /dev/null
+++ b/sources/plugins/justify/lang/az.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'az', {
6 block: 'Eninə görə',
7 center: 'Mərkəz',
8 left: 'Soldan düzləndir',
9 right: 'Sağdan düzləndir'
10} );
diff --git a/sources/plugins/justify/lang/bg.js b/sources/plugins/justify/lang/bg.js
new file mode 100644
index 0000000..1724947
--- /dev/null
+++ b/sources/plugins/justify/lang/bg.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'bg', {
6 block: 'Двустранно подравняване',
7 center: 'Център',
8 left: 'Подравни в ляво',
9 right: 'Подравни в дясно'
10} );
diff --git a/sources/plugins/justify/lang/bn.js b/sources/plugins/justify/lang/bn.js
new file mode 100644
index 0000000..002a633
--- /dev/null
+++ b/sources/plugins/justify/lang/bn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'bn', {
6 block: 'যাচাই করি',
7 center: 'মাঝ বরাবর ঘেষা',
8 left: 'বা দিকে ঘেঁষা',
9 right: 'ডান দিকে ঘেঁষা'
10} );
diff --git a/sources/plugins/justify/lang/bs.js b/sources/plugins/justify/lang/bs.js
new file mode 100644
index 0000000..0fbedfc
--- /dev/null
+++ b/sources/plugins/justify/lang/bs.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'bs', {
6 block: 'Puno poravnanje',
7 center: 'Centralno poravnanje',
8 left: 'Lijevo poravnanje',
9 right: 'Desno poravnanje'
10} );
diff --git a/sources/plugins/justify/lang/ca.js b/sources/plugins/justify/lang/ca.js
new file mode 100644
index 0000000..afb7adb
--- /dev/null
+++ b/sources/plugins/justify/lang/ca.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ca', {
6 block: 'Justificat',
7 center: 'Centrat',
8 left: 'Alinea a l\'esquerra',
9 right: 'Alinea a la dreta'
10} );
diff --git a/sources/plugins/justify/lang/cs.js b/sources/plugins/justify/lang/cs.js
new file mode 100644
index 0000000..467ae6f
--- /dev/null
+++ b/sources/plugins/justify/lang/cs.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'cs', {
6 block: 'Zarovnat do bloku',
7 center: 'Zarovnat na střed',
8 left: 'Zarovnat vlevo',
9 right: 'Zarovnat vpravo'
10} );
diff --git a/sources/plugins/justify/lang/cy.js b/sources/plugins/justify/lang/cy.js
new file mode 100644
index 0000000..6b39beb
--- /dev/null
+++ b/sources/plugins/justify/lang/cy.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'cy', {
6 block: 'Unioni',
7 center: 'Alinio i\'r Canol',
8 left: 'Alinio i\'r Chwith',
9 right: 'Alinio i\'r Dde'
10} );
diff --git a/sources/plugins/justify/lang/da.js b/sources/plugins/justify/lang/da.js
new file mode 100644
index 0000000..ac8ee29
--- /dev/null
+++ b/sources/plugins/justify/lang/da.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'da', {
6 block: 'Lige margener',
7 center: 'Centreret',
8 left: 'Venstrestillet',
9 right: 'Højrestillet'
10} );
diff --git a/sources/plugins/justify/lang/de-ch.js b/sources/plugins/justify/lang/de-ch.js
new file mode 100644
index 0000000..a2c24eb
--- /dev/null
+++ b/sources/plugins/justify/lang/de-ch.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'de-ch', {
6 block: 'Blocksatz',
7 center: 'Zentriert',
8 left: 'Linksbündig',
9 right: 'Rechtsbündig'
10} );
diff --git a/sources/plugins/justify/lang/de.js b/sources/plugins/justify/lang/de.js
new file mode 100644
index 0000000..4db8725
--- /dev/null
+++ b/sources/plugins/justify/lang/de.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'de', {
6 block: 'Blocksatz',
7 center: 'Zentriert',
8 left: 'Linksbündig',
9 right: 'Rechtsbündig'
10} );
diff --git a/sources/plugins/justify/lang/el.js b/sources/plugins/justify/lang/el.js
new file mode 100644
index 0000000..1bdc64f
--- /dev/null
+++ b/sources/plugins/justify/lang/el.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'el', {
6 block: 'Πλήρης Στοίχιση',
7 center: 'Στο Κέντρο',
8 left: 'Στοίχιση Αριστερά',
9 right: 'Στοίχιση Δεξιά'
10} );
diff --git a/sources/plugins/justify/lang/en-au.js b/sources/plugins/justify/lang/en-au.js
new file mode 100644
index 0000000..68eb09c
--- /dev/null
+++ b/sources/plugins/justify/lang/en-au.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'en-au', {
6 block: 'Justify',
7 center: 'Centre',
8 left: 'Align Left',
9 right: 'Align Right'
10} );
diff --git a/sources/plugins/justify/lang/en-ca.js b/sources/plugins/justify/lang/en-ca.js
new file mode 100644
index 0000000..27718a2
--- /dev/null
+++ b/sources/plugins/justify/lang/en-ca.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'en-ca', {
6 block: 'Justify',
7 center: 'Centre',
8 left: 'Align Left',
9 right: 'Align Right'
10} );
diff --git a/sources/plugins/justify/lang/en-gb.js b/sources/plugins/justify/lang/en-gb.js
new file mode 100644
index 0000000..d6db4ff
--- /dev/null
+++ b/sources/plugins/justify/lang/en-gb.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'en-gb', {
6 block: 'Justify',
7 center: 'Centre',
8 left: 'Align Left',
9 right: 'Align Right'
10} );
diff --git a/sources/plugins/justify/lang/en.js b/sources/plugins/justify/lang/en.js
new file mode 100644
index 0000000..8a72e85
--- /dev/null
+++ b/sources/plugins/justify/lang/en.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'en', {
6 block: 'Justify',
7 center: 'Center',
8 left: 'Align Left',
9 right: 'Align Right'
10} );
diff --git a/sources/plugins/justify/lang/eo.js b/sources/plugins/justify/lang/eo.js
new file mode 100644
index 0000000..7531dde
--- /dev/null
+++ b/sources/plugins/justify/lang/eo.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'eo', {
6 block: 'Ĝisrandigi Ambaŭflanke',
7 center: 'Centrigi',
8 left: 'Ĝisrandigi maldekstren',
9 right: 'Ĝisrandigi dekstren'
10} );
diff --git a/sources/plugins/justify/lang/es.js b/sources/plugins/justify/lang/es.js
new file mode 100644
index 0000000..2e89bc0
--- /dev/null
+++ b/sources/plugins/justify/lang/es.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'es', {
6 block: 'Justificado',
7 center: 'Centrar',
8 left: 'Alinear a Izquierda',
9 right: 'Alinear a Derecha'
10} );
diff --git a/sources/plugins/justify/lang/et.js b/sources/plugins/justify/lang/et.js
new file mode 100644
index 0000000..0fc4915
--- /dev/null
+++ b/sources/plugins/justify/lang/et.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'et', {
6 block: 'Rööpjoondus',
7 center: 'Keskjoondus',
8 left: 'Vasakjoondus',
9 right: 'Paremjoondus'
10} );
diff --git a/sources/plugins/justify/lang/eu.js b/sources/plugins/justify/lang/eu.js
new file mode 100644
index 0000000..f7d291e
--- /dev/null
+++ b/sources/plugins/justify/lang/eu.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'eu', {
6 block: 'Justifikatu',
7 center: 'Erdian',
8 left: 'Lerrokatu ezkerrean',
9 right: 'Lerrokatu eskuinean'
10} );
diff --git a/sources/plugins/justify/lang/fa.js b/sources/plugins/justify/lang/fa.js
new file mode 100644
index 0000000..03c3c6b
--- /dev/null
+++ b/sources/plugins/justify/lang/fa.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'fa', {
6 block: 'بلوک چین',
7 center: 'میان چین',
8 left: 'چپ چین',
9 right: 'راست چین'
10} );
diff --git a/sources/plugins/justify/lang/fi.js b/sources/plugins/justify/lang/fi.js
new file mode 100644
index 0000000..6993f10
--- /dev/null
+++ b/sources/plugins/justify/lang/fi.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'fi', {
6 block: 'Tasaa molemmat reunat',
7 center: 'Keskitä',
8 left: 'Tasaa vasemmat reunat',
9 right: 'Tasaa oikeat reunat'
10} );
diff --git a/sources/plugins/justify/lang/fo.js b/sources/plugins/justify/lang/fo.js
new file mode 100644
index 0000000..f11a575
--- /dev/null
+++ b/sources/plugins/justify/lang/fo.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'fo', {
6 block: 'Javnir tekstkantar',
7 center: 'Miðsett',
8 left: 'Vinstrasett',
9 right: 'Høgrasett'
10} );
diff --git a/sources/plugins/justify/lang/fr-ca.js b/sources/plugins/justify/lang/fr-ca.js
new file mode 100644
index 0000000..8d59e5e
--- /dev/null
+++ b/sources/plugins/justify/lang/fr-ca.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'fr-ca', {
6 block: 'Justifié',
7 center: 'Centré',
8 left: 'Aligner à gauche',
9 right: 'Aligner à Droite'
10} );
diff --git a/sources/plugins/justify/lang/fr.js b/sources/plugins/justify/lang/fr.js
new file mode 100644
index 0000000..e44df52
--- /dev/null
+++ b/sources/plugins/justify/lang/fr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'fr', {
6 block: 'Justifier',
7 center: 'Centrer',
8 left: 'Aligner à gauche',
9 right: 'Aligner à droite'
10} );
diff --git a/sources/plugins/justify/lang/gl.js b/sources/plugins/justify/lang/gl.js
new file mode 100644
index 0000000..1995e8c
--- /dev/null
+++ b/sources/plugins/justify/lang/gl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'gl', {
6 block: 'Xustificado',
7 center: 'Centrado',
8 left: 'Aliñar á esquerda',
9 right: 'Aliñar á dereita'
10} );
diff --git a/sources/plugins/justify/lang/gu.js b/sources/plugins/justify/lang/gu.js
new file mode 100644
index 0000000..d491684
--- /dev/null
+++ b/sources/plugins/justify/lang/gu.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'gu', {
6 block: 'બ્લૉક, અંતરાય જસ્ટિફાઇ',
7 center: 'સંકેંદ્રણ/સેંટરિંગ',
8 left: 'ડાબી બાજુએ/બાજુ તરફ',
9 right: 'જમણી બાજુએ/બાજુ તરફ'
10} );
diff --git a/sources/plugins/justify/lang/he.js b/sources/plugins/justify/lang/he.js
new file mode 100644
index 0000000..ab5c759
--- /dev/null
+++ b/sources/plugins/justify/lang/he.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'he', {
6 block: 'יישור לשוליים',
7 center: 'מרכוז',
8 left: 'יישור לשמאל',
9 right: 'יישור לימין'
10} );
diff --git a/sources/plugins/justify/lang/hi.js b/sources/plugins/justify/lang/hi.js
new file mode 100644
index 0000000..6a4fae8
--- /dev/null
+++ b/sources/plugins/justify/lang/hi.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'hi', {
6 block: 'ब्लॉक जस्टीफ़ाई',
7 center: 'बीच में',
8 left: 'बायीं तरफ',
9 right: 'दायीं तरफ'
10} );
diff --git a/sources/plugins/justify/lang/hr.js b/sources/plugins/justify/lang/hr.js
new file mode 100644
index 0000000..852c686
--- /dev/null
+++ b/sources/plugins/justify/lang/hr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'hr', {
6 block: 'Blok poravnanje',
7 center: 'Središnje poravnanje',
8 left: 'Lijevo poravnanje',
9 right: 'Desno poravnanje'
10} );
diff --git a/sources/plugins/justify/lang/hu.js b/sources/plugins/justify/lang/hu.js
new file mode 100644
index 0000000..c7b8dad
--- /dev/null
+++ b/sources/plugins/justify/lang/hu.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'hu', {
6 block: 'Sorkizárt',
7 center: 'Középre',
8 left: 'Balra',
9 right: 'Jobbra'
10} );
diff --git a/sources/plugins/justify/lang/id.js b/sources/plugins/justify/lang/id.js
new file mode 100644
index 0000000..d67247c
--- /dev/null
+++ b/sources/plugins/justify/lang/id.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'id', {
6 block: 'Rata kiri-kanan',
7 center: 'Pusat',
8 left: 'Align Left', // MISSING
9 right: 'Align Right' // MISSING
10} );
diff --git a/sources/plugins/justify/lang/is.js b/sources/plugins/justify/lang/is.js
new file mode 100644
index 0000000..d01a43a
--- /dev/null
+++ b/sources/plugins/justify/lang/is.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'is', {
6 block: 'Jafna báðum megin',
7 center: 'Miðja texta',
8 left: 'Vinstrijöfnun',
9 right: 'Hægrijöfnun'
10} );
diff --git a/sources/plugins/justify/lang/it.js b/sources/plugins/justify/lang/it.js
new file mode 100644
index 0000000..fd4ae51
--- /dev/null
+++ b/sources/plugins/justify/lang/it.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'it', {
6 block: 'Giustifica',
7 center: 'Centra',
8 left: 'Allinea a sinistra',
9 right: 'Allinea a destra'
10} );
diff --git a/sources/plugins/justify/lang/ja.js b/sources/plugins/justify/lang/ja.js
new file mode 100644
index 0000000..6c71c86
--- /dev/null
+++ b/sources/plugins/justify/lang/ja.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ja', {
6 block: '両端揃え',
7 center: '中央揃え',
8 left: '左揃え',
9 right: '右揃え'
10} );
diff --git a/sources/plugins/justify/lang/ka.js b/sources/plugins/justify/lang/ka.js
new file mode 100644
index 0000000..4ba0bcb
--- /dev/null
+++ b/sources/plugins/justify/lang/ka.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ka', {
6 block: 'გადასწორება',
7 center: 'შუაში სწორება',
8 left: 'მარცხნივ სწორება',
9 right: 'მარჯვნივ სწორება'
10} );
diff --git a/sources/plugins/justify/lang/km.js b/sources/plugins/justify/lang/km.js
new file mode 100644
index 0000000..a7546c3
--- /dev/null
+++ b/sources/plugins/justify/lang/km.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'km', {
6 block: 'តម្រឹម​ពេញ',
7 center: 'កណ្ដាល',
8 left: 'តម្រឹម​ឆ្វេង',
9 right: 'តម្រឹម​ស្ដាំ'
10} );
diff --git a/sources/plugins/justify/lang/ko.js b/sources/plugins/justify/lang/ko.js
new file mode 100644
index 0000000..346405d
--- /dev/null
+++ b/sources/plugins/justify/lang/ko.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ko', {
6 block: '양쪽 맞춤',
7 center: '가운데 정렬',
8 left: '왼쪽 정렬',
9 right: '오른쪽 정렬'
10} );
diff --git a/sources/plugins/justify/lang/ku.js b/sources/plugins/justify/lang/ku.js
new file mode 100644
index 0000000..24ed914
--- /dev/null
+++ b/sources/plugins/justify/lang/ku.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ku', {
6 block: 'هاوستوونی',
7 center: 'ناوەڕاست',
8 left: 'بەهێڵ کردنی چەپ',
9 right: 'بەهێڵ کردنی ڕاست'
10} );
diff --git a/sources/plugins/justify/lang/lt.js b/sources/plugins/justify/lang/lt.js
new file mode 100644
index 0000000..08202cb
--- /dev/null
+++ b/sources/plugins/justify/lang/lt.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'lt', {
6 block: 'Lygiuoti abi puses',
7 center: 'Centruoti',
8 left: 'Lygiuoti kairę',
9 right: 'Lygiuoti dešinę'
10} );
diff --git a/sources/plugins/justify/lang/lv.js b/sources/plugins/justify/lang/lv.js
new file mode 100644
index 0000000..8c729c9
--- /dev/null
+++ b/sources/plugins/justify/lang/lv.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'lv', {
6 block: 'Izlīdzināt malas',
7 center: 'Izlīdzināt pret centru',
8 left: 'Izlīdzināt pa kreisi',
9 right: 'Izlīdzināt pa labi'
10} );
diff --git a/sources/plugins/justify/lang/mk.js b/sources/plugins/justify/lang/mk.js
new file mode 100644
index 0000000..f45fb19
--- /dev/null
+++ b/sources/plugins/justify/lang/mk.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'mk', {
6 block: 'Justify', // MISSING
7 center: 'Во средина',
8 left: 'Align Left', // MISSING
9 right: 'Align Right' // MISSING
10} );
diff --git a/sources/plugins/justify/lang/mn.js b/sources/plugins/justify/lang/mn.js
new file mode 100644
index 0000000..850e474
--- /dev/null
+++ b/sources/plugins/justify/lang/mn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'mn', {
6 block: 'Тэгшлэх',
7 center: 'Голлуулах',
8 left: 'Зүүн талд тулгах',
9 right: 'Баруун талд тулгах'
10} );
diff --git a/sources/plugins/justify/lang/ms.js b/sources/plugins/justify/lang/ms.js
new file mode 100644
index 0000000..323f8e9
--- /dev/null
+++ b/sources/plugins/justify/lang/ms.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ms', {
6 block: 'Jajaran Blok',
7 center: 'Jajaran Tengah',
8 left: 'Jajaran Kiri',
9 right: 'Jajaran Kanan'
10} );
diff --git a/sources/plugins/justify/lang/nb.js b/sources/plugins/justify/lang/nb.js
new file mode 100644
index 0000000..98a3c44
--- /dev/null
+++ b/sources/plugins/justify/lang/nb.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'nb', {
6 block: 'Blokkjuster',
7 center: 'Midtstill',
8 left: 'Venstrejuster',
9 right: 'Høyrejuster'
10} );
diff --git a/sources/plugins/justify/lang/nl.js b/sources/plugins/justify/lang/nl.js
new file mode 100644
index 0000000..972bf82
--- /dev/null
+++ b/sources/plugins/justify/lang/nl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'nl', {
6 block: 'Uitvullen',
7 center: 'Centreren',
8 left: 'Links uitlijnen',
9 right: 'Rechts uitlijnen'
10} );
diff --git a/sources/plugins/justify/lang/no.js b/sources/plugins/justify/lang/no.js
new file mode 100644
index 0000000..cfcd72a
--- /dev/null
+++ b/sources/plugins/justify/lang/no.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'no', {
6 block: 'Blokkjuster',
7 center: 'Midtstill',
8 left: 'Venstrejuster',
9 right: 'Høyrejuster'
10} );
diff --git a/sources/plugins/justify/lang/oc.js b/sources/plugins/justify/lang/oc.js
new file mode 100644
index 0000000..a13e528
--- /dev/null
+++ b/sources/plugins/justify/lang/oc.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'oc', {
6 block: 'Justificar',
7 center: 'Centrar',
8 left: 'Alinhar a esquèrra',
9 right: 'Alinhar a dreita'
10} );
diff --git a/sources/plugins/justify/lang/pl.js b/sources/plugins/justify/lang/pl.js
new file mode 100644
index 0000000..60922b9
--- /dev/null
+++ b/sources/plugins/justify/lang/pl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'pl', {
6 block: 'Wyjustuj',
7 center: 'Wyśrodkuj',
8 left: 'Wyrównaj do lewej',
9 right: 'Wyrównaj do prawej'
10} );
diff --git a/sources/plugins/justify/lang/pt-br.js b/sources/plugins/justify/lang/pt-br.js
new file mode 100644
index 0000000..cf40ad0
--- /dev/null
+++ b/sources/plugins/justify/lang/pt-br.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'pt-br', {
6 block: 'Justificado',
7 center: 'Centralizar',
8 left: 'Alinhar Esquerda',
9 right: 'Alinhar Direita'
10} );
diff --git a/sources/plugins/justify/lang/pt.js b/sources/plugins/justify/lang/pt.js
new file mode 100644
index 0000000..46ac43b
--- /dev/null
+++ b/sources/plugins/justify/lang/pt.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'pt', {
6 block: 'Justificado',
7 center: 'Alinhar ao centro',
8 left: 'Alinhar à esquerda',
9 right: 'Alinhar à direita'
10} );
diff --git a/sources/plugins/justify/lang/ro.js b/sources/plugins/justify/lang/ro.js
new file mode 100644
index 0000000..21caeca
--- /dev/null
+++ b/sources/plugins/justify/lang/ro.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ro', {
6 block: 'Aliniere în bloc (Block Justify)',
7 center: 'Aliniere centrală',
8 left: 'Aliniere la stânga',
9 right: 'Aliniere la dreapta'
10} );
diff --git a/sources/plugins/justify/lang/ru.js b/sources/plugins/justify/lang/ru.js
new file mode 100644
index 0000000..47c98bb
--- /dev/null
+++ b/sources/plugins/justify/lang/ru.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ru', {
6 block: 'По ширине',
7 center: 'По центру',
8 left: 'По левому краю',
9 right: 'По правому краю'
10} );
diff --git a/sources/plugins/justify/lang/si.js b/sources/plugins/justify/lang/si.js
new file mode 100644
index 0000000..6d9f373
--- /dev/null
+++ b/sources/plugins/justify/lang/si.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'si', {
6 block: 'Justify', // MISSING
7 center: 'මධ්‍ය',
8 left: 'Align Left', // MISSING
9 right: 'Align Right' // MISSING
10} );
diff --git a/sources/plugins/justify/lang/sk.js b/sources/plugins/justify/lang/sk.js
new file mode 100644
index 0000000..08c3991
--- /dev/null
+++ b/sources/plugins/justify/lang/sk.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'sk', {
6 block: 'Zarovnať do bloku',
7 center: 'Zarovnať na stred',
8 left: 'Zarovnať vľavo',
9 right: 'Zarovnať vpravo'
10} );
diff --git a/sources/plugins/justify/lang/sl.js b/sources/plugins/justify/lang/sl.js
new file mode 100644
index 0000000..d776354
--- /dev/null
+++ b/sources/plugins/justify/lang/sl.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'sl', {
6 block: 'Obojestranska poravnava',
7 center: 'Sredinska poravnava',
8 left: 'Leva poravnava',
9 right: 'Desna poravnava'
10} );
diff --git a/sources/plugins/justify/lang/sq.js b/sources/plugins/justify/lang/sq.js
new file mode 100644
index 0000000..1ed002c
--- /dev/null
+++ b/sources/plugins/justify/lang/sq.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'sq', {
6 block: 'Zgjero',
7 center: 'Qendër',
8 left: 'Rreshto majtas',
9 right: 'Rreshto Djathtas'
10} );
diff --git a/sources/plugins/justify/lang/sr-latn.js b/sources/plugins/justify/lang/sr-latn.js
new file mode 100644
index 0000000..7fdba23
--- /dev/null
+++ b/sources/plugins/justify/lang/sr-latn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'sr-latn', {
6 block: 'Obostrano ravnanje',
7 center: 'Centriran tekst',
8 left: 'Levo ravnanje',
9 right: 'Desno ravnanje'
10} );
diff --git a/sources/plugins/justify/lang/sr.js b/sources/plugins/justify/lang/sr.js
new file mode 100644
index 0000000..2314a96
--- /dev/null
+++ b/sources/plugins/justify/lang/sr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'sr', {
6 block: 'Обострано равнање',
7 center: 'Центриран текст',
8 left: 'Лево равнање',
9 right: 'Десно равнање'
10} );
diff --git a/sources/plugins/justify/lang/sv.js b/sources/plugins/justify/lang/sv.js
new file mode 100644
index 0000000..cac94c0
--- /dev/null
+++ b/sources/plugins/justify/lang/sv.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'sv', {
6 block: 'Justera till marginaler',
7 center: 'Centrera',
8 left: 'Vänsterjustera',
9 right: 'Högerjustera'
10} );
diff --git a/sources/plugins/justify/lang/th.js b/sources/plugins/justify/lang/th.js
new file mode 100644
index 0000000..4a9d4f9
--- /dev/null
+++ b/sources/plugins/justify/lang/th.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'th', {
6 block: 'จัดพอดีหน้ากระดาษ',
7 center: 'จัดกึ่งกลาง',
8 left: 'จัดชิดซ้าย',
9 right: 'จัดชิดขวา'
10} );
diff --git a/sources/plugins/justify/lang/tr.js b/sources/plugins/justify/lang/tr.js
new file mode 100644
index 0000000..fbc512f
--- /dev/null
+++ b/sources/plugins/justify/lang/tr.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'tr', {
6 block: 'İki Kenara Yaslanmış',
7 center: 'Ortalanmış',
8 left: 'Sola Dayalı',
9 right: 'Sağa Dayalı'
10} );
diff --git a/sources/plugins/justify/lang/tt.js b/sources/plugins/justify/lang/tt.js
new file mode 100644
index 0000000..b36f69c
--- /dev/null
+++ b/sources/plugins/justify/lang/tt.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'tt', {
6 block: 'Киңлеккә карап тигезләү',
7 center: 'Үзәккә тигезләү',
8 left: 'Сул як кырыйдан тигезләү',
9 right: 'Уң як кырыйдан тигезләү'
10} );
diff --git a/sources/plugins/justify/lang/ug.js b/sources/plugins/justify/lang/ug.js
new file mode 100644
index 0000000..e5861f5
--- /dev/null
+++ b/sources/plugins/justify/lang/ug.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'ug', {
6 block: 'ئىككى تەرەپتىن توغرىلا',
7 center: 'ئوتتۇرىغا توغرىلا',
8 left: 'سولغا توغرىلا',
9 right: 'ئوڭغا توغرىلا'
10} );
diff --git a/sources/plugins/justify/lang/uk.js b/sources/plugins/justify/lang/uk.js
new file mode 100644
index 0000000..5807f25
--- /dev/null
+++ b/sources/plugins/justify/lang/uk.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'uk', {
6 block: 'По ширині',
7 center: 'По центру',
8 left: 'По лівому краю',
9 right: 'По правому краю'
10} );
diff --git a/sources/plugins/justify/lang/vi.js b/sources/plugins/justify/lang/vi.js
new file mode 100644
index 0000000..de0c170
--- /dev/null
+++ b/sources/plugins/justify/lang/vi.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'vi', {
6 block: 'Canh đều',
7 center: 'Canh giữa',
8 left: 'Canh trái',
9 right: 'Canh phải'
10} );
diff --git a/sources/plugins/justify/lang/zh-cn.js b/sources/plugins/justify/lang/zh-cn.js
new file mode 100644
index 0000000..4c19627
--- /dev/null
+++ b/sources/plugins/justify/lang/zh-cn.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'zh-cn', {
6 block: '两端对齐',
7 center: '居中',
8 left: '左对齐',
9 right: '右对齐'
10} );
diff --git a/sources/plugins/justify/lang/zh.js b/sources/plugins/justify/lang/zh.js
new file mode 100644
index 0000000..0865d51
--- /dev/null
+++ b/sources/plugins/justify/lang/zh.js
@@ -0,0 +1,10 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'justify', 'zh', {
6 block: '左右對齊',
7 center: '置中',
8 left: '靠左對齊',
9 right: '靠右對齊'
10} );
diff --git a/sources/plugins/justify/plugin.js b/sources/plugins/justify/plugin.js
new file mode 100644
index 0000000..ce5cab3
--- /dev/null
+++ b/sources/plugins/justify/plugin.js
@@ -0,0 +1,245 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Justify commands.
8 */
9
10( function() {
11 function getAlignment( element, useComputedState ) {
12 useComputedState = useComputedState === undefined || useComputedState;
13
14 var align;
15 if ( useComputedState )
16 align = element.getComputedStyle( 'text-align' );
17 else {
18 while ( !element.hasAttribute || !( element.hasAttribute( 'align' ) || element.getStyle( 'text-align' ) ) ) {
19 var parent = element.getParent();
20 if ( !parent )
21 break;
22 element = parent;
23 }
24 align = element.getStyle( 'text-align' ) || element.getAttribute( 'align' ) || '';
25 }
26
27 // Sometimes computed values doesn't tell.
28 align && ( align = align.replace( /(?:-(?:moz|webkit)-)?(?:start|auto)/i, '' ) );
29
30 !align && useComputedState && ( align = element.getComputedStyle( 'direction' ) == 'rtl' ? 'right' : 'left' );
31
32 return align;
33 }
34
35 function justifyCommand( editor, name, value ) {
36 this.editor = editor;
37 this.name = name;
38 this.value = value;
39 this.context = 'p';
40
41 var classes = editor.config.justifyClasses,
42 blockTag = editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div';
43
44 if ( classes ) {
45 switch ( value ) {
46 case 'left':
47 this.cssClassName = classes[ 0 ];
48 break;
49 case 'center':
50 this.cssClassName = classes[ 1 ];
51 break;
52 case 'right':
53 this.cssClassName = classes[ 2 ];
54 break;
55 case 'justify':
56 this.cssClassName = classes[ 3 ];
57 break;
58 }
59
60 this.cssClassRegex = new RegExp( '(?:^|\\s+)(?:' + classes.join( '|' ) + ')(?=$|\\s)' );
61 this.requiredContent = blockTag + '(' + this.cssClassName + ')';
62 }
63 else {
64 this.requiredContent = blockTag + '{text-align}';
65 }
66
67 this.allowedContent = {
68 'caption div h1 h2 h3 h4 h5 h6 p pre td th li': {
69 // Do not add elements, but only text-align style if element is validated by other rule.
70 propertiesOnly: true,
71 styles: this.cssClassName ? null : 'text-align',
72 classes: this.cssClassName || null
73 }
74 };
75
76 // In enter mode BR we need to allow here for div, because when non other
77 // feature allows div justify is the only plugin that uses it.
78 if ( editor.config.enterMode == CKEDITOR.ENTER_BR )
79 this.allowedContent.div = true;
80 }
81
82 function onDirChanged( e ) {
83 var editor = e.editor;
84
85 var range = editor.createRange();
86 range.setStartBefore( e.data.node );
87 range.setEndAfter( e.data.node );
88
89 var walker = new CKEDITOR.dom.walker( range ),
90 node;
91
92 while ( ( node = walker.next() ) ) {
93 if ( node.type == CKEDITOR.NODE_ELEMENT ) {
94 // A child with the defined dir is to be ignored.
95 if ( !node.equals( e.data.node ) && node.getDirection() ) {
96 range.setStartAfter( node );
97 walker = new CKEDITOR.dom.walker( range );
98 continue;
99 }
100
101 // Switch the alignment.
102 var classes = editor.config.justifyClasses;
103 if ( classes ) {
104 // The left align class.
105 if ( node.hasClass( classes[ 0 ] ) ) {
106 node.removeClass( classes[ 0 ] );
107 node.addClass( classes[ 2 ] );
108 }
109 // The right align class.
110 else if ( node.hasClass( classes[ 2 ] ) ) {
111 node.removeClass( classes[ 2 ] );
112 node.addClass( classes[ 0 ] );
113 }
114 }
115
116 // Always switch CSS margins.
117 var style = 'text-align';
118 var align = node.getStyle( style );
119
120 if ( align == 'left' )
121 node.setStyle( style, 'right' );
122 else if ( align == 'right' )
123 node.setStyle( style, 'left' );
124 }
125 }
126 }
127
128 justifyCommand.prototype = {
129 exec: function( editor ) {
130 var selection = editor.getSelection(),
131 enterMode = editor.config.enterMode;
132
133 if ( !selection )
134 return;
135
136 var bookmarks = selection.createBookmarks(),
137 ranges = selection.getRanges();
138
139 var cssClassName = this.cssClassName,
140 iterator, block;
141
142 var useComputedState = editor.config.useComputedState;
143 useComputedState = useComputedState === undefined || useComputedState;
144
145 for ( var i = ranges.length - 1; i >= 0; i-- ) {
146 iterator = ranges[ i ].createIterator();
147 iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
148
149 while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) ) {
150 if ( block.isReadOnly() )
151 continue;
152
153 block.removeAttribute( 'align' );
154 block.removeStyle( 'text-align' );
155
156 // Remove any of the alignment classes from the className.
157 var className = cssClassName && ( block.$.className = CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) ) );
158
159 var apply = ( this.state == CKEDITOR.TRISTATE_OFF ) && ( !useComputedState || ( getAlignment( block, true ) != this.value ) );
160
161 if ( cssClassName ) {
162 // Append the desired class name.
163 if ( apply )
164 block.addClass( cssClassName );
165 else if ( !className )
166 block.removeAttribute( 'class' );
167 } else if ( apply ) {
168 block.setStyle( 'text-align', this.value );
169 }
170 }
171
172 }
173
174 editor.focus();
175 editor.forceNextSelectionCheck();
176 selection.selectBookmarks( bookmarks );
177 },
178
179 refresh: function( editor, path ) {
180 var firstBlock = path.block || path.blockLimit;
181
182 this.setState( firstBlock.getName() != 'body' && getAlignment( firstBlock, this.editor.config.useComputedState ) == this.value ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
183 }
184 };
185
186 CKEDITOR.plugins.add( 'justify', {
187 // jscs:disable maximumLineLength
188 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
189 // jscs:enable maximumLineLength
190 icons: 'justifyblock,justifycenter,justifyleft,justifyright', // %REMOVE_LINE_CORE%
191 hidpi: true, // %REMOVE_LINE_CORE%
192 init: function( editor ) {
193 if ( editor.blockless )
194 return;
195
196 var left = new justifyCommand( editor, 'justifyleft', 'left' ),
197 center = new justifyCommand( editor, 'justifycenter', 'center' ),
198 right = new justifyCommand( editor, 'justifyright', 'right' ),
199 justify = new justifyCommand( editor, 'justifyblock', 'justify' );
200
201 editor.addCommand( 'justifyleft', left );
202 editor.addCommand( 'justifycenter', center );
203 editor.addCommand( 'justifyright', right );
204 editor.addCommand( 'justifyblock', justify );
205
206 if ( editor.ui.addButton ) {
207 editor.ui.addButton( 'JustifyLeft', {
208 label: editor.lang.justify.left,
209 command: 'justifyleft',
210 toolbar: 'align,10'
211 } );
212 editor.ui.addButton( 'JustifyCenter', {
213 label: editor.lang.justify.center,
214 command: 'justifycenter',
215 toolbar: 'align,20'
216 } );
217 editor.ui.addButton( 'JustifyRight', {
218 label: editor.lang.justify.right,
219 command: 'justifyright',
220 toolbar: 'align,30'
221 } );
222 editor.ui.addButton( 'JustifyBlock', {
223 label: editor.lang.justify.block,
224 command: 'justifyblock',
225 toolbar: 'align,40'
226 } );
227 }
228
229 editor.on( 'dirChanged', onDirChanged );
230 }
231 } );
232} )();
233
234/**
235 * List of classes to use for aligning the contents. If it's `null`, no classes will be used
236 * and instead the corresponding CSS values will be used.
237 *
238 * The array should contain 4 members, in the following order: left, center, right, justify.
239 *
240 * // Use the classes 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify'
241 * config.justifyClasses = [ 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify' ];
242 *
243 * @cfg {Array} [justifyClasses=null]
244 * @member CKEDITOR.config
245 */
diff --git a/sources/plugins/lineutils/dev/dnd.html b/sources/plugins/lineutils/dev/dnd.html
new file mode 100644
index 0000000..7293daa
--- /dev/null
+++ b/sources/plugins/lineutils/dev/dnd.html
@@ -0,0 +1,172 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Widget Drag &amp; Drop with Lineutils &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <script>
12 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
13 CKEDITOR.tools.enableHtml5Elements( document );
14 </script>
15 <link href="../../../samples/old/sample.css" rel="stylesheet">
16 <link href="../../image2/samples/contents.css" rel="stylesheet">
17</head>
18<body>
19 <h1 class="samples">
20 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Widget Drag &amp; Drop with Lineutils
21 </h1>
22
23 <h3>Classic (iframe-based) Editor</h3>
24
25 <textarea id="editor1" cols="10" rows="10">
26 <h1>Apollo 11</h1>
27
28 <figure class="caption" style="float:right"><img alt="Saturn V" src="../../image2/samples/assets/image1.jpg" width="200" />
29 <figcaption>Roll out of Saturn V on launch pad</figcaption>
30 </figure>
31
32 <p><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.</p>
33
34 <p>Armstrong spent about <s>three and a half</s> two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5&nbsp;kg) of lunar material for return to Earth. A third member of the mission, <a href="http://en.wikipedia.org/wiki/Michael_Collins_(astronaut)" title="Michael Collins (astronaut)">Michael Collins</a>, piloted the <a href="http://en.wikipedia.org/wiki/Apollo_Command/Service_Module" title="Apollo Command/Service Module">command</a> spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.</p>
35
36 <h2>Broadcasting and <em>quotes</em> <a id="quotes" name="quotes"></a></h2>
37
38 <p>Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:</p>
39
40 <blockquote>
41 <p>One small step for [a] man, one giant leap for mankind.</p>
42 </blockquote>
43
44 <p>Apollo 11 effectively ended the <a href="http://en.wikipedia.org/wiki/Space_Race" title="Space Race">Space Race</a> and fulfilled a national goal proposed in 1961 by the late U.S. President <a href="http://en.wikipedia.org/wiki/John_F._Kennedy" title="John F. Kennedy">John F. Kennedy</a> in a speech before the United States Congress:</p>
45
46 <div style="text-align:center">
47 <figure class="caption" style="display:inline-block"><img alt="The Eagle" height="123" src="../../image2/samples/assets/image2.jpg" width="136" />
48 <figcaption>The Eagle in lunar orbit</figcaption>
49 </figure>
50 </div>
51
52 <blockquote>
53 <p>[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.</p>
54 </blockquote>
55
56 <figure class="caption" style="float:right"><img alt="The Eagle" src="../../image2/samples/assets/image2.jpg" width="200" />
57 <figcaption>The Eagle in lunar orbit</figcaption>
58 </figure>
59
60 <h2>Technical details <a id="tech-details" name="tech-details"></a></h2>
61
62 <p>Launched by a <strong>Saturn V</strong> rocket from <a href="http://en.wikipedia.org/wiki/Kennedy_Space_Center" title="Kennedy Space Center">Kennedy Space Center</a> in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of <a href="http://en.wikipedia.org/wiki/NASA" title="NASA">NASA</a>&#39;s Apollo program. The Apollo spacecraft had three parts:</p>
63
64 <ol>
65 <li><strong>Command Module</strong> with a cabin for the three astronauts which was the only part which landed back on Earth</li>
66 <li><strong>Service Module</strong> which supported the Command Module with propulsion, electrical power, oxygen and water</li>
67 <li><strong>Lunar Module</strong> for landing on the Moon.</li>
68 </ol>
69
70 <p>After being sent to the Moon by the Saturn V&#39;s upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the <a href="http://en.wikipedia.org/wiki/Mare_Tranquillitatis" title="Mare Tranquillitatis">Sea of Tranquility</a>. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the <a href="http://en.wikipedia.org/wiki/Pacific_Ocean" title="Pacific Ocean">Pacific Ocean</a> on July 24.</p>
71
72 <figure class="caption"><img alt="Saturn V" height="129" src="../../image2/samples/assets/image1.jpg" width="101" />
73 <figcaption>Roll out of Saturn V on launch pad</figcaption>
74 </figure>
75
76 <hr />
77 <p style="text-align:right"><small>Source: <a href="http://en.wikipedia.org/wiki/Apollo_11">Wikipedia.org</a></small></p>
78
79 </textarea>
80
81 <h3>Inline Editor</h3>
82
83 <div id="editor2" contenteditable="true" style="outline: 2px solid #ccc">
84 <table border="0" cellpadding="1" cellspacing="1" style="width: 100%; ">
85 <tbody>
86 <tr>
87 <td>This table</td>
88 <td>is the</td>
89 <td>very first</td>
90 <td>element of the document.</td>
91 </tr>
92 <tr>
93 <td>We are still</td>
94 <td>able to acces</td>
95 <td>the space before it.</td>
96 <td style="padding: 25px">
97 <table border="0" cellpadding="1" cellspacing="1" style="width: 100%; ">
98 <tbody>
99 <tr>
100 <td>This table is inside of a cell of another table.</td>
101 </tr>
102 <tr>
103 <td>We can type&nbsp;either before or after it though.</td>
104 </tr>
105 </tbody>
106 </table>
107 </td>
108 </tr>
109 </tbody>
110 </table>
111
112 <hr />
113 <hr />
114 <ol style="width: 300px">
115 <li>This numbered list...</li>
116 <li>...is a neighbour of a horizontal line...</li>
117 <li style="padding: 20px;">
118 <ol>
119 <li>Nested list!</li>
120 </ol>
121 </li>
122 </ol>
123
124 <figure class="caption"><img alt="Saturn V" src="../../image2/samples/assets/image1.jpg" width="100" />
125 <figcaption>Roll out of Saturn V on launch pad</figcaption>
126 </figure>
127
128 <ul style="width: 450px">
129 <li>We can type between the lists...</li>
130 <li>...thanks to <strong>Magicline</strong>.</li>
131 </ul>
132
133 <p>Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.</p>
134
135 <p>Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.</p>
136
137 <p>Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.</p>
138
139 <div id="last" style="padding: 10px; text-align: center;">
140 <p>This text is wrapped in a&nbsp;<tt>DIV</tt>&nbsp;element. We can type after this element though.</p>
141 </div>
142 </div>
143
144 <script>
145
146 CKEDITOR.replace( 'editor1', {
147 extraPlugins: 'image2',
148 height: 450,
149 removePlugins: 'image,forms',
150 contentsCss: [ '../../../contents.css', '../../image2/samples/contents.css' ]
151 } );
152
153 CKEDITOR.inline( 'editor2', {
154 extraPlugins: 'image2',
155 height: 450,
156 removePlugins: 'image,forms'
157 } );
158
159 </script>
160
161 <div id="footer">
162 <hr>
163 <p>
164 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
165 </p>
166 <p id="copy">
167 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
168 Knabben. All rights reserved.
169 </p>
170 </div>
171</body>
172</html>
diff --git a/sources/plugins/lineutils/dev/magicfinger.html b/sources/plugins/lineutils/dev/magicfinger.html
new file mode 100644
index 0000000..3172d22
--- /dev/null
+++ b/sources/plugins/lineutils/dev/magicfinger.html
@@ -0,0 +1,285 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Lineutils &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link href="../../../samples/old/sample.css" rel="stylesheet">
12</head>
13<body>
14 <h1 class="samples">
15 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Lineutils
16 </h1>
17
18 <h3>Classic (iframe-based) Editor</h3>
19
20 <textarea id="editor1" cols="10" rows="10">
21 <table border="0" cellpadding="1" cellspacing="1" style="width: 100%; ">
22 <tbody>
23 <tr>
24 <td>This table</td>
25 <td>is the</td>
26 <td>very first</td>
27 <td>element of the document.</td>
28 </tr>
29 <tr>
30 <td>We are still</td>
31 <td>able to acces</td>
32 <td>the space before it.</td>
33 <td style="padding: 25px">
34 <table border="0" cellpadding="1" cellspacing="1" style="width: 100%; ">
35 <tbody>
36 <tr>
37 <td>This table is inside of a cell of another table.</td>
38 </tr>
39 <tr>
40 <td>We can type&nbsp;either before or after it though.</td>
41 </tr>
42 </tbody>
43 </table>
44 </td>
45 </tr>
46 </tbody>
47 </table>
48
49 <p>Two succesive horizontal lines (<tt>HR</tt> tags). We can access the space in between:</p>
50
51 <hr />
52 <hr />
53 <ol style="width: 300px">
54 <li>This numbered list...</li>
55 <li>...is a neighbour of a horizontal line...</li>
56 <li style="padding: 20px;">
57 <ol>
58 <li>Nested list!</li>
59 </ol>
60 </li>
61 </ol>
62
63 <ul style="width: 450px">
64 <li>We can type between the lists...</li>
65 <li>...thanks to <strong>Magicline</strong>.</li>
66 </ul>
67
68 <p>Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.</p>
69
70 <p>Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.</p>
71
72 <p>Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.</p>
73
74 <div id="last" style="padding: 10px; text-align: center;">
75 <p>This text is wrapped in a&nbsp;<tt>DIV</tt>&nbsp;element. We can type after this element though.</p>
76 </div>
77 </textarea>
78
79 <h3>Inline Editor</h3>
80
81 <div id="editor2" contenteditable="true" style="outline: 2px solid #ccc">
82 <table border="0" cellpadding="1" cellspacing="1" style="width: 100%; ">
83 <tbody>
84 <tr>
85 <td>This table</td>
86 <td>is the</td>
87 <td>very first</td>
88 <td>element of the document.</td>
89 </tr>
90 <tr>
91 <td>We are still</td>
92 <td>able to acces</td>
93 <td>the space before it.</td>
94 <td style="padding: 25px">
95 <table border="0" cellpadding="1" cellspacing="1" style="width: 100%; ">
96 <tbody>
97 <tr>
98 <td>This table is inside of a cell of another table.</td>
99 </tr>
100 <tr>
101 <td>We can type&nbsp;either before or after it though.</td>
102 </tr>
103 </tbody>
104 </table>
105 </td>
106 </tr>
107 </tbody>
108 </table>
109
110 <p>Two succesive horizontal lines (<tt>HR</tt> tags). We can access the space in between:</p>
111
112 <hr />
113 <hr />
114 <ol style="width: 300px">
115 <li>This numbered list...</li>
116 <li>...is a neighbour of a horizontal line...</li>
117 <li style="padding: 20px;">
118 <ol>
119 <li>Nested list!</li>
120 </ol>
121 </li>
122 </ol>
123
124 <ul style="width: 450px">
125 <li>We can type between the lists...</li>
126 <li>...thanks to <strong>Magicline</strong>.</li>
127 </ul>
128
129 <p>Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.</p>
130
131 <p>Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.</p>
132
133 <p>Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.</p>
134
135 <div id="last" style="padding: 10px; text-align: center;">
136 <p>This text is wrapped in a&nbsp;<tt>DIV</tt>&nbsp;element. We can type after this element though.</p>
137 </div>
138 </div>
139
140 <h3>Extreme inline</h3>
141
142 <div id="editor3" contenteditable="true" style="left: 123px; outline: 1px solid red; border: 15px solid green; position: relative; top: 30; left: 30px;">
143 <div style="padding: 20px; background: gray; width: 300px" class="1">Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim.</div>
144 <div style="background: violet; padding: 30px;" class="static">
145 Position static
146 <div style="background: green; padding: 30px; border: 14px solid orange">foo</div>
147 </div>
148 <dl class="2">
149 <dt>Key</dt><dd>Value</dd>
150 </dl>
151 <div>Whatever</div>
152 <hr id="hr">
153 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
154 <hr>
155 <hr>
156 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
157 <div style="background: green; padding: 30px; width: 200px">foo</div>
158 </div>
159
160 <h3>Classic (iframe-based) Editor, H-scroll</h3>
161
162 <textarea id="editor4" cols="10" rows="10">
163 <hr />
164 <hr />
165 <ol style="width: 1500px">
166 <li>This numbered list...</li>
167 <li>...is a neighbour of a horizontal line...</li>
168 <li style="padding: 20px;">
169 <ol>
170 <li>Nested list!</li>
171 </ol>
172 </li>
173 </ol>
174
175 <ul style="width: 450px">
176 <li>We can type between the lists...</li>
177 <li>...thanks to <strong>Magicline</strong>.</li>
178 </ul>
179
180 <p>Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.</p>
181
182 <p>Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.</p>
183
184 <p>Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.</p>
185
186 <div id="last" style="padding: 10px; text-align: center;">
187 <p>This text is wrapped in a&nbsp;<tt>DIV</tt>&nbsp;element. We can type after this element though.</p>
188 </div>
189 </textarea>
190
191 <script>
192
193 CKEDITOR.addCss(
194 '.cke_editable * { outline: 1px solid #BCEBFF }'
195 );
196
197 function callback() {
198 var helpers = CKEDITOR.plugins.lineutils;
199 var liner = new helpers.liner( this );
200 var locator = new helpers.locator( this );
201 var finder = new helpers.finder( this, {
202 lookups: {
203 'is block and first child': function( el ) {
204 if ( el.is( CKEDITOR.dtd.$listItem ) )
205 return;
206
207 if ( el.is( CKEDITOR.dtd.$block ) )
208 return CKEDITOR.LINEUTILS_BEFORE | CKEDITOR.LINEUTILS_AFTER;
209 }
210 }
211 } ).start( function( relations, x, y ) {
212 locator.locate( relations );
213
214 var locations = locator.locations,
215 uid, type;
216
217 liner.prepare( relations, locations );
218
219 for ( uid in locations ) {
220 for ( type in locations[ uid ] )
221 liner.placeLine( { uid: uid, type: type } );
222 }
223
224 liner.cleanup();
225 } );
226 }
227
228 CKEDITOR.disableAutoInline = true;
229
230 CKEDITOR.replace( 'editor1', {
231 extraPlugins: 'lineutils',
232 height: 450,
233 removePlugins: 'magicline',
234 allowedContent: true,
235 contentsCss: [ '../../../contents.css' ],
236 on: {
237 contentDom: callback
238 }
239 } );
240
241 CKEDITOR.inline( 'editor2', {
242 extraPlugins: 'lineutils',
243 removePlugins: 'magicline',
244 allowedContent: true,
245 contentsCss: [ '../../../contents.css' ],
246 on: {
247 contentDom: callback
248 }
249 } );
250
251 CKEDITOR.inline( 'editor3', {
252 extraPlugins: 'lineutils',
253 removePlugins: 'magicline',
254 allowedContent: true,
255 contentsCss: [ '../../../contents.css' ],
256 on: {
257 contentDom: callback
258 }
259 } );
260
261 CKEDITOR.replace( 'editor4', {
262 extraPlugins: 'lineutils',
263 removePlugins: 'magicline',
264 allowedContent: true,
265 contentsCss: [ '../../../contents.css' ],
266 on: {
267 contentDom: callback
268 }
269 } );
270
271
272 </script>
273
274 <div id="footer">
275 <hr>
276 <p>
277 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
278 </p>
279 <p id="copy">
280 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
281 Knabben. All rights reserved.
282 </p>
283 </div>
284</body>
285</html>
diff --git a/sources/plugins/lineutils/plugin.js b/sources/plugins/lineutils/plugin.js
new file mode 100644
index 0000000..e0473ee
--- /dev/null
+++ b/sources/plugins/lineutils/plugin.js
@@ -0,0 +1,1018 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6 /**
7 * @fileOverview A set of utilities to find and create horizontal spaces in edited content.
8 */
9
10'use strict';
11
12( function() {
13
14 CKEDITOR.plugins.add( 'lineutils' );
15
16 /**
17 * Determines a position relative to an element in DOM (before).
18 *
19 * @readonly
20 * @property {Number} [=0]
21 * @member CKEDITOR
22 */
23 CKEDITOR.LINEUTILS_BEFORE = 1;
24
25 /**
26 * Determines a position relative to an element in DOM (after).
27 *
28 * @readonly
29 * @property {Number} [=2]
30 * @member CKEDITOR
31 */
32 CKEDITOR.LINEUTILS_AFTER = 2;
33
34 /**
35 * Determines a position relative to an element in DOM (inside).
36 *
37 * @readonly
38 * @property {Number} [=4]
39 * @member CKEDITOR
40 */
41 CKEDITOR.LINEUTILS_INSIDE = 4;
42
43 /**
44 * A utility that traverses the DOM tree and discovers elements
45 * (relations) matching user-defined lookups.
46 *
47 * @private
48 * @class CKEDITOR.plugins.lineutils.finder
49 * @constructor Creates a Finder class instance.
50 * @param {CKEDITOR.editor} editor Editor instance that the Finder belongs to.
51 * @param {Object} def Finder's definition.
52 * @since 4.3
53 */
54 function Finder( editor, def ) {
55 CKEDITOR.tools.extend( this, {
56 editor: editor,
57 editable: editor.editable(),
58 doc: editor.document,
59 win: editor.window
60 }, def, true );
61
62 this.inline = this.editable.isInline();
63
64 if ( !this.inline ) {
65 this.frame = this.win.getFrame();
66 }
67
68 this.target = this[ this.inline ? 'editable' : 'doc' ];
69 }
70
71 Finder.prototype = {
72 /**
73 * Initializes searching for elements with every mousemove event fired.
74 * To stop searching use {@link #stop}.
75 *
76 * @param {Function} [callback] Function executed on every iteration.
77 */
78 start: function( callback ) {
79 var that = this,
80 editor = this.editor,
81 doc = this.doc,
82 el, elfp, x, y;
83
84 var moveBuffer = CKEDITOR.tools.eventsBuffer( 50, function() {
85 if ( editor.readOnly || editor.mode != 'wysiwyg' )
86 return;
87
88 that.relations = {};
89
90 // Sometimes it happens that elementFromPoint returns null (especially on IE).
91 // Any further traversal makes no sense if there's no start point. Abort.
92 // Note: In IE8 elementFromPoint may return zombie nodes of undefined nodeType,
93 // so rejecting those as well.
94 if ( !( elfp = doc.$.elementFromPoint( x, y ) ) || !elfp.nodeType ) {
95 return;
96 }
97
98 el = new CKEDITOR.dom.element( elfp );
99
100 that.traverseSearch( el );
101
102 if ( !isNaN( x + y ) ) {
103 that.pixelSearch( el, x, y );
104 }
105
106 callback && callback( that.relations, x, y );
107 } );
108
109 // Searching starting from element from point on mousemove.
110 this.listener = this.editable.attachListener( this.target, 'mousemove', function( evt ) {
111 x = evt.data.$.clientX;
112 y = evt.data.$.clientY;
113
114 moveBuffer.input();
115 } );
116
117 this.editable.attachListener( this.inline ? this.editable : this.frame, 'mouseout', function() {
118 moveBuffer.reset();
119 } );
120 },
121
122 /**
123 * Stops observing mouse events attached by {@link #start}.
124 */
125 stop: function() {
126 if ( this.listener ) {
127 this.listener.removeListener();
128 }
129 },
130
131 /**
132 * Returns a range representing the relation, according to its element
133 * and type.
134 *
135 * @param {Object} location Location containing a unique identifier and type.
136 * @returns {CKEDITOR.dom.range} Range representing the relation.
137 */
138 getRange: ( function() {
139 var where = {};
140
141 where[ CKEDITOR.LINEUTILS_BEFORE ] = CKEDITOR.POSITION_BEFORE_START;
142 where[ CKEDITOR.LINEUTILS_AFTER ] = CKEDITOR.POSITION_AFTER_END;
143 where[ CKEDITOR.LINEUTILS_INSIDE ] = CKEDITOR.POSITION_AFTER_START;
144
145 return function( location ) {
146 var range = this.editor.createRange();
147
148 range.moveToPosition( this.relations[ location.uid ].element, where[ location.type ] );
149
150 return range;
151 };
152 } )(),
153
154 /**
155 * Stores given relation in a {@link #relations} object. Processes the relation
156 * to normalize and avoid duplicates.
157 *
158 * @param {CKEDITOR.dom.element} el Element of the relation.
159 * @param {Number} type Relation, one of `CKEDITOR.LINEUTILS_AFTER`, `CKEDITOR.LINEUTILS_BEFORE`, `CKEDITOR.LINEUTILS_INSIDE`.
160 */
161 store: ( function() {
162 function merge( el, type, relations ) {
163 var uid = el.getUniqueId();
164
165 if ( uid in relations ) {
166 relations[ uid ].type |= type;
167 } else {
168 relations[ uid ] = { element: el, type: type };
169 }
170 }
171
172 return function( el, type ) {
173 var alt;
174
175 // Normalization to avoid duplicates:
176 // CKEDITOR.LINEUTILS_AFTER becomes CKEDITOR.LINEUTILS_BEFORE of el.getNext().
177 if ( is( type, CKEDITOR.LINEUTILS_AFTER ) && isStatic( alt = el.getNext() ) && alt.isVisible() ) {
178 merge( alt, CKEDITOR.LINEUTILS_BEFORE, this.relations );
179 type ^= CKEDITOR.LINEUTILS_AFTER;
180 }
181
182 // Normalization to avoid duplicates:
183 // CKEDITOR.LINEUTILS_INSIDE becomes CKEDITOR.LINEUTILS_BEFORE of el.getFirst().
184 if ( is( type, CKEDITOR.LINEUTILS_INSIDE ) && isStatic( alt = el.getFirst() ) && alt.isVisible() ) {
185 merge( alt, CKEDITOR.LINEUTILS_BEFORE, this.relations );
186 type ^= CKEDITOR.LINEUTILS_INSIDE;
187 }
188
189 merge( el, type, this.relations );
190 };
191 } )(),
192
193 /**
194 * Traverses the DOM tree towards root, checking all ancestors
195 * with lookup rules, avoiding duplicates. Stores positive relations
196 * in the {@link #relations} object.
197 *
198 * @param {CKEDITOR.dom.element} el Element which is the starting point.
199 */
200 traverseSearch: function( el ) {
201 var l, type, uid;
202
203 // Go down DOM towards root (or limit).
204 do {
205 uid = el.$[ 'data-cke-expando' ];
206
207 // This element was already visited and checked.
208 if ( uid && uid in this.relations ) {
209 continue;
210 }
211
212 if ( el.equals( this.editable ) ) {
213 return;
214 }
215
216 if ( isStatic( el ) ) {
217 // Collect all addresses yielded by lookups for that element.
218 for ( l in this.lookups ) {
219
220 if ( ( type = this.lookups[ l ]( el ) ) ) {
221 this.store( el, type );
222 }
223 }
224 }
225 } while ( !isLimit( el ) && ( el = el.getParent() ) );
226 },
227
228 /**
229 * Iterates vertically pixel-by-pixel within a given element starting
230 * from given coordinates, searching for elements in the neighborhood.
231 * Once an element is found it is processed by {@link #traverseSearch}.
232 *
233 * @param {CKEDITOR.dom.element} el Element which is the starting point.
234 * @param {Number} [x] Horizontal mouse coordinate relative to the viewport.
235 * @param {Number} [y] Vertical mouse coordinate relative to the viewport.
236 */
237 pixelSearch: ( function() {
238 var contains = CKEDITOR.env.ie || CKEDITOR.env.webkit ?
239 function( el, found ) {
240 return el.contains( found );
241 } : function( el, found ) {
242 return !!( el.compareDocumentPosition( found ) & 16 );
243 };
244
245 // Iterates pixel-by-pixel from starting coordinates, moving by defined
246 // step and getting elementFromPoint in every iteration. Iteration stops when:
247 // * A valid element is found.
248 // * Condition function returns `false` (i.e. reached boundaries of viewport).
249 // * No element is found (i.e. coordinates out of viewport).
250 // * Element found is ascendant of starting element.
251 //
252 // @param {Object} doc Native DOM document.
253 // @param {Object} el Native DOM element.
254 // @param {Number} xStart Horizontal starting coordinate to use.
255 // @param {Number} yStart Vertical starting coordinate to use.
256 // @param {Number} step Step of the algorithm.
257 // @param {Function} condition A condition relative to current vertical coordinate.
258 function iterate( el, xStart, yStart, step, condition ) {
259 var y = yStart,
260 tryouts = 0,
261 found;
262
263 while ( condition( y ) ) {
264 y += step;
265
266 // If we try and we try, and still nothing's found, let's end
267 // that party.
268 if ( ++tryouts == 25 ) {
269 return;
270 }
271
272 found = this.doc.$.elementFromPoint( xStart, y );
273
274 // Nothing found. This is crazy... but...
275 // It might be that a line, which is in different document,
276 // covers that pixel (elementFromPoint is doc-sensitive).
277 // Better let's have another try.
278 if ( !found ) {
279 continue;
280 }
281
282 // Still in the same element.
283 else if ( found == el ) {
284 tryouts = 0;
285 continue;
286 }
287
288 // Reached the edge of an element and found an ancestor or...
289 // A line, that covers that pixel. Better let's have another try.
290 else if ( !contains( el, found ) ) {
291 continue;
292 }
293
294 tryouts = 0;
295
296 // Found a valid element. Stop iterating.
297 if ( isStatic( ( found = new CKEDITOR.dom.element( found ) ) ) ) {
298 return found;
299 }
300 }
301 }
302
303 return function( el, x, y ) {
304 var paneHeight = this.win.getViewPaneSize().height,
305
306 // Try to find an element iterating *up* from the starting point.
307 neg = iterate.call( this, el.$, x, y, -1, function( y ) {
308 return y > 0;
309 } ),
310
311 // Try to find an element iterating *down* from the starting point.
312 pos = iterate.call( this, el.$, x, y, 1, function( y ) {
313 return y < paneHeight;
314 } );
315
316 if ( neg ) {
317 this.traverseSearch( neg );
318
319 // Iterate towards DOM root until neg is a direct child of el.
320 while ( !neg.getParent().equals( el ) ) {
321 neg = neg.getParent();
322 }
323 }
324
325 if ( pos ) {
326 this.traverseSearch( pos );
327
328 // Iterate towards DOM root until pos is a direct child of el.
329 while ( !pos.getParent().equals( el ) ) {
330 pos = pos.getParent();
331 }
332 }
333
334 // Iterate forwards starting from neg and backwards from
335 // pos to harvest all children of el between those elements.
336 // Stop when neg and pos meet each other or there's none of them.
337 // TODO (?) reduce number of hops forwards/backwards.
338 while ( neg || pos ) {
339 if ( neg ) {
340 neg = neg.getNext( isStatic );
341 }
342
343 if ( !neg || neg.equals( pos ) ) {
344 break;
345 }
346
347 this.traverseSearch( neg );
348
349 if ( pos ) {
350 pos = pos.getPrevious( isStatic );
351 }
352
353 if ( !pos || pos.equals( neg ) ) {
354 break;
355 }
356
357 this.traverseSearch( pos );
358 }
359 };
360 } )(),
361
362 /**
363 * Unlike {@link #traverseSearch}, it collects **all** elements from editable's DOM tree
364 * and runs lookups for every one of them, collecting relations.
365 *
366 * @returns {Object} {@link #relations}.
367 */
368 greedySearch: function() {
369 this.relations = {};
370
371 var all = this.editable.getElementsByTag( '*' ),
372 i = 0,
373 el, type, l;
374
375 while ( ( el = all.getItem( i++ ) ) ) {
376 // Don't consider editable, as it might be inline,
377 // and i.e. checking it's siblings is pointless.
378 if ( el.equals( this.editable ) ) {
379 continue;
380 }
381
382 // On IE8 element.getElementsByTagName returns comments... sic! (#13176)
383 if ( el.type != CKEDITOR.NODE_ELEMENT ) {
384 continue;
385 }
386
387 // Don't visit non-editable internals, for example widget's
388 // guts (above wrapper, below nested). Still check editable limits,
389 // as they are siblings with editable contents.
390 if ( !el.hasAttribute( 'contenteditable' ) && el.isReadOnly() ) {
391 continue;
392 }
393
394 if ( isStatic( el ) && el.isVisible() ) {
395 // Collect all addresses yielded by lookups for that element.
396 for ( l in this.lookups ) {
397 if ( ( type = this.lookups[ l ]( el ) ) ) {
398 this.store( el, type );
399 }
400 }
401 }
402 }
403
404 return this.relations;
405 }
406
407 /**
408 * Relations express elements in DOM that match user-defined {@link #lookups}.
409 * Every relation has its own `type` that determines whether
410 * it refers to the space before, after or inside the `element`.
411 * This object stores relations found by {@link #traverseSearch} or {@link #greedySearch}, structured
412 * in the following way:
413 *
414 * relations: {
415 * // Unique identifier of the element.
416 * Number: {
417 * // Element of this relation.
418 * element: {@link CKEDITOR.dom.element}
419 * // Conjunction of CKEDITOR.LINEUTILS_BEFORE, CKEDITOR.LINEUTILS_AFTER and CKEDITOR.LINEUTILS_INSIDE.
420 * type: Number
421 * },
422 * ...
423 * }
424 *
425 * @property {Object} relations
426 * @readonly
427 */
428
429 /**
430 * A set of user-defined functions used by Finder to check if an element
431 * is a valid relation, belonging to {@link #relations}.
432 * When the criterion is met, lookup returns a logical conjunction of `CKEDITOR.LINEUTILS_BEFORE`,
433 * `CKEDITOR.LINEUTILS_AFTER` or `CKEDITOR.LINEUTILS_INSIDE`.
434 *
435 * Lookups are passed along with Finder's definition.
436 *
437 * lookups: {
438 * 'some lookup': function( el ) {
439 * if ( someCondition )
440 * return CKEDITOR.LINEUTILS_BEFORE;
441 * },
442 * ...
443 * }
444 *
445 * @property {Object} lookups
446 */
447 };
448
449
450 /**
451 * A utility that analyses relations found by
452 * CKEDITOR.plugins.lineutils.finder and locates them
453 * in the viewport as horizontal lines of specific coordinates.
454 *
455 * @private
456 * @class CKEDITOR.plugins.lineutils.locator
457 * @constructor Creates a Locator class instance.
458 * @param {CKEDITOR.editor} editor Editor instance that Locator belongs to.
459 * @since 4.3
460 */
461 function Locator( editor, def ) {
462 CKEDITOR.tools.extend( this, def, {
463 editor: editor
464 }, true );
465 }
466
467 Locator.prototype = {
468 /**
469 * Locates the Y coordinate for all types of every single relation and stores
470 * them in an object.
471 *
472 * @param {Object} relations {@link CKEDITOR.plugins.lineutils.finder#relations}.
473 * @returns {Object} {@link #locations}.
474 */
475 locate: ( function() {
476 function locateSibling( rel, type ) {
477 var sib = rel.element[ type === CKEDITOR.LINEUTILS_BEFORE ? 'getPrevious' : 'getNext' ]();
478
479 // Return the middle point between siblings.
480 if ( sib && isStatic( sib ) ) {
481 rel.siblingRect = sib.getClientRect();
482
483 if ( type == CKEDITOR.LINEUTILS_BEFORE ) {
484 return ( rel.siblingRect.bottom + rel.elementRect.top ) / 2;
485 } else {
486 return ( rel.elementRect.bottom + rel.siblingRect.top ) / 2;
487 }
488 }
489
490 // If there's no sibling, use the edge of an element.
491 else {
492 if ( type == CKEDITOR.LINEUTILS_BEFORE ) {
493 return rel.elementRect.top;
494 } else {
495 return rel.elementRect.bottom;
496 }
497 }
498 }
499
500 return function( relations ) {
501 var rel;
502
503 this.locations = {};
504
505 for ( var uid in relations ) {
506 rel = relations[ uid ];
507 rel.elementRect = rel.element.getClientRect();
508
509 if ( is( rel.type, CKEDITOR.LINEUTILS_BEFORE ) ) {
510 this.store( uid, CKEDITOR.LINEUTILS_BEFORE, locateSibling( rel, CKEDITOR.LINEUTILS_BEFORE ) );
511 }
512
513 if ( is( rel.type, CKEDITOR.LINEUTILS_AFTER ) ) {
514 this.store( uid, CKEDITOR.LINEUTILS_AFTER, locateSibling( rel, CKEDITOR.LINEUTILS_AFTER ) );
515 }
516
517 // The middle point of the element.
518 if ( is( rel.type, CKEDITOR.LINEUTILS_INSIDE ) ) {
519 this.store( uid, CKEDITOR.LINEUTILS_INSIDE, ( rel.elementRect.top + rel.elementRect.bottom ) / 2 );
520 }
521 }
522
523 return this.locations;
524 };
525 } )(),
526
527 /**
528 * Calculates distances from every location to given vertical coordinate
529 * and sorts locations according to that distance.
530 *
531 * @param {Number} y The vertical coordinate used for sorting, used as a reference.
532 * @param {Number} [howMany] Determines the number of "closest locations" to be returned.
533 * @returns {Array} Sorted, array representation of {@link #locations}.
534 */
535 sort: ( function() {
536 var locations, sorted,
537 dist, i;
538
539 function distance( y, uid, type ) {
540 return Math.abs( y - locations[ uid ][ type ] );
541 }
542
543 return function( y, howMany ) {
544 locations = this.locations;
545 sorted = [];
546
547 for ( var uid in locations ) {
548 for ( var type in locations[ uid ] ) {
549 dist = distance( y, uid, type );
550
551 // An array is empty.
552 if ( !sorted.length ) {
553 sorted.push( { uid: +uid, type: type, dist: dist } );
554 } else {
555 // Sort the array on fly when it's populated.
556 for ( i = 0; i < sorted.length; i++ ) {
557 if ( dist < sorted[ i ].dist ) {
558 sorted.splice( i, 0, { uid: +uid, type: type, dist: dist } );
559 break;
560 }
561 }
562
563 // Nothing was inserted, so the distance is bigger than
564 // any of already calculated: push to the end.
565 if ( i == sorted.length ) {
566 sorted.push( { uid: +uid, type: type, dist: dist } );
567 }
568 }
569 }
570 }
571
572 if ( typeof howMany != 'undefined' ) {
573 return sorted.slice( 0, howMany );
574 } else {
575 return sorted;
576 }
577 };
578 } )(),
579
580 /**
581 * Stores the location in a collection.
582 *
583 * @param {Number} uid Unique identifier of the relation.
584 * @param {Number} type One of `CKEDITOR.LINEUTILS_BEFORE`, `CKEDITOR.LINEUTILS_AFTER` and `CKEDITOR.LINEUTILS_INSIDE`.
585 * @param {Number} y Vertical position of the relation.
586 */
587 store: function( uid, type, y ) {
588 if ( !this.locations[ uid ] ) {
589 this.locations[ uid ] = {};
590 }
591
592 this.locations[ uid ][ type ] = y;
593 }
594
595 /**
596 * @readonly
597 * @property {Object} locations
598 */
599 };
600
601 var tipCss = {
602 display: 'block',
603 width: '0px',
604 height: '0px',
605 'border-color': 'transparent',
606 'border-style': 'solid',
607 position: 'absolute',
608 top: '-6px'
609 },
610
611 lineStyle = {
612 height: '0px',
613 'border-top': '1px dashed red',
614 position: 'absolute',
615 'z-index': 9999
616 },
617
618 lineTpl =
619 '<div data-cke-lineutils-line="1" class="cke_reset_all" style="{lineStyle}">' +
620 '<span style="{tipLeftStyle}">&nbsp;</span>' +
621 '<span style="{tipRightStyle}">&nbsp;</span>' +
622 '</div>';
623
624 /**
625 * A utility that draws horizontal lines in DOM according to locations
626 * returned by CKEDITOR.plugins.lineutils.locator.
627 *
628 * @private
629 * @class CKEDITOR.plugins.lineutils.liner
630 * @constructor Creates a Liner class instance.
631 * @param {CKEDITOR.editor} editor Editor instance that Liner belongs to.
632 * @param {Object} def Liner's definition.
633 * @since 4.3
634 */
635 function Liner( editor, def ) {
636 var editable = editor.editable();
637
638 CKEDITOR.tools.extend( this, {
639 editor: editor,
640 editable: editable,
641 inline: editable.isInline(),
642 doc: editor.document,
643 win: editor.window,
644 container: CKEDITOR.document.getBody(),
645 winTop: CKEDITOR.document.getWindow()
646 }, def, true );
647
648 this.hidden = {};
649 this.visible = {};
650
651 if ( !this.inline ) {
652 this.frame = this.win.getFrame();
653 }
654
655 this.queryViewport();
656
657 // Callbacks must be wrapped. Otherwise they're not attached
658 // to global DOM objects (i.e. topmost window) for every editor
659 // because they're treated as duplicates. They belong to the
660 // same prototype shared among Liner instances.
661 var queryViewport = CKEDITOR.tools.bind( this.queryViewport, this ),
662 hideVisible = CKEDITOR.tools.bind( this.hideVisible, this ),
663 removeAll = CKEDITOR.tools.bind( this.removeAll, this );
664
665 editable.attachListener( this.winTop, 'resize', queryViewport );
666 editable.attachListener( this.winTop, 'scroll', queryViewport );
667
668 editable.attachListener( this.winTop, 'resize', hideVisible );
669 editable.attachListener( this.win, 'scroll', hideVisible );
670
671 editable.attachListener( this.inline ? editable : this.frame, 'mouseout', function( evt ) {
672 var x = evt.data.$.clientX,
673 y = evt.data.$.clientY;
674
675 this.queryViewport();
676
677 // Check if mouse is out of the element (iframe/editable).
678 if ( x <= this.rect.left || x >= this.rect.right || y <= this.rect.top || y >= this.rect.bottom ) {
679 this.hideVisible();
680 }
681
682 // Check if mouse is out of the top-window vieport.
683 if ( x <= 0 || x >= this.winTopPane.width || y <= 0 || y >= this.winTopPane.height ) {
684 this.hideVisible();
685 }
686 }, this );
687
688 editable.attachListener( editor, 'resize', queryViewport );
689 editable.attachListener( editor, 'mode', removeAll );
690 editor.on( 'destroy', removeAll );
691
692 this.lineTpl = new CKEDITOR.template( lineTpl ).output( {
693 lineStyle: CKEDITOR.tools.writeCssText(
694 CKEDITOR.tools.extend( {}, lineStyle, this.lineStyle, true )
695 ),
696 tipLeftStyle: CKEDITOR.tools.writeCssText(
697 CKEDITOR.tools.extend( {}, tipCss, {
698 left: '0px',
699 'border-left-color': 'red',
700 'border-width': '6px 0 6px 6px'
701 }, this.tipCss, this.tipLeftStyle, true )
702 ),
703 tipRightStyle: CKEDITOR.tools.writeCssText(
704 CKEDITOR.tools.extend( {}, tipCss, {
705 right: '0px',
706 'border-right-color': 'red',
707 'border-width': '6px 6px 6px 0'
708 }, this.tipCss, this.tipRightStyle, true )
709 )
710 } );
711 }
712
713 Liner.prototype = {
714 /**
715 * Permanently removes all lines (both hidden and visible) from DOM.
716 */
717 removeAll: function() {
718 var l;
719
720 for ( l in this.hidden ) {
721 this.hidden[ l ].remove();
722 delete this.hidden[ l ];
723 }
724
725 for ( l in this.visible ) {
726 this.visible[ l ].remove();
727 delete this.visible[ l ];
728 }
729 },
730
731 /**
732 * Hides a given line.
733 *
734 * @param {CKEDITOR.dom.element} line The line to be hidden.
735 */
736 hideLine: function( line ) {
737 var uid = line.getUniqueId();
738
739 line.hide();
740
741 this.hidden[ uid ] = line;
742 delete this.visible[ uid ];
743 },
744
745 /**
746 * Shows a given line.
747 *
748 * @param {CKEDITOR.dom.element} line The line to be shown.
749 */
750 showLine: function( line ) {
751 var uid = line.getUniqueId();
752
753 line.show();
754
755 this.visible[ uid ] = line;
756 delete this.hidden[ uid ];
757 },
758
759 /**
760 * Hides all visible lines.
761 */
762 hideVisible: function() {
763 for ( var l in this.visible ) {
764 this.hideLine( this.visible[ l ] );
765 }
766 },
767
768 /**
769 * Shows a line at given location.
770 *
771 * @param {Object} location Location object containing the unique identifier of the relation
772 * and its type. Usually returned by {@link CKEDITOR.plugins.lineutils.locator#sort}.
773 * @param {Function} [callback] A callback to be called once the line is shown.
774 */
775 placeLine: function( location, callback ) {
776 var styles, line, l;
777
778 // No style means that line would be out of viewport.
779 if ( !( styles = this.getStyle( location.uid, location.type ) ) ) {
780 return;
781 }
782
783 // Search for any visible line of a different hash first.
784 // It's faster to re-position visible line than to show it.
785 for ( l in this.visible ) {
786 if ( this.visible[ l ].getCustomData( 'hash' ) !== this.hash ) {
787 line = this.visible[ l ];
788 break;
789 }
790 }
791
792 // Search for any hidden line of a different hash.
793 if ( !line ) {
794 for ( l in this.hidden ) {
795 if ( this.hidden[ l ].getCustomData( 'hash' ) !== this.hash ) {
796 this.showLine( ( line = this.hidden[ l ] ) );
797 break;
798 }
799 }
800 }
801
802 // If no line available, add the new one.
803 if ( !line ) {
804 this.showLine( ( line = this.addLine() ) );
805 }
806
807 // Mark the line with current hash.
808 line.setCustomData( 'hash', this.hash );
809
810 // Mark the line as visible.
811 this.visible[ line.getUniqueId() ] = line;
812
813 line.setStyles( styles );
814
815 callback && callback( line );
816 },
817
818 /**
819 * Creates a style set to be used by the line, representing a particular
820 * relation (location).
821 *
822 * @param {Number} uid Unique identifier of the relation.
823 * @param {Number} type Type of the relation.
824 * @returns {Object} An object containing styles.
825 */
826 getStyle: function( uid, type ) {
827 var rel = this.relations[ uid ],
828 loc = this.locations[ uid ][ type ],
829 styles = {},
830 hdiff;
831
832 // Line should be between two elements.
833 if ( rel.siblingRect ) {
834 styles.width = Math.max( rel.siblingRect.width, rel.elementRect.width );
835 }
836 // Line is relative to a single element.
837 else {
838 styles.width = rel.elementRect.width;
839 }
840
841 // Let's calculate the vertical position of the line.
842 if ( this.inline ) {
843 // (#13155)
844 styles.top = loc + this.winTopScroll.y - this.rect.relativeY;
845 } else {
846 styles.top = this.rect.top + this.winTopScroll.y + loc;
847 }
848
849 // Check if line would be vertically out of the viewport.
850 if ( styles.top - this.winTopScroll.y < this.rect.top || styles.top - this.winTopScroll.y > this.rect.bottom ) {
851 return false;
852 }
853
854 // Now let's calculate the horizontal alignment (left and width).
855 if ( this.inline ) {
856 // (#13155)
857 styles.left = rel.elementRect.left - this.rect.relativeX;
858 } else {
859 if ( rel.elementRect.left > 0 )
860 styles.left = this.rect.left + rel.elementRect.left;
861
862 // H-scroll case. Left edge of element may be out of viewport.
863 else {
864 styles.width += rel.elementRect.left;
865 styles.left = this.rect.left;
866 }
867
868 // H-scroll case. Right edge of element may be out of viewport.
869 if ( ( hdiff = styles.left + styles.width - ( this.rect.left + this.winPane.width ) ) > 0 ) {
870 styles.width -= hdiff;
871 }
872 }
873
874 // Finally include horizontal scroll of the global window.
875 styles.left += this.winTopScroll.x;
876
877 // Append 'px' to style values.
878 for ( var style in styles ) {
879 styles[ style ] = CKEDITOR.tools.cssLength( styles[ style ] );
880 }
881
882 return styles;
883 },
884
885 /**
886 * Adds a new line to DOM.
887 *
888 * @returns {CKEDITOR.dom.element} A brand-new line.
889 */
890 addLine: function() {
891 var line = CKEDITOR.dom.element.createFromHtml( this.lineTpl );
892
893 line.appendTo( this.container );
894
895 return line;
896 },
897
898 /**
899 * Assigns a unique hash to the instance that is later used
900 * to tell unwanted lines from new ones. This method **must** be called
901 * before a new set of relations is to be visualized so {@link #cleanup}
902 * eventually hides obsolete lines. This is because lines
903 * are re-used between {@link #placeLine} calls and the number of
904 * necessary ones may vary depending on the number of relations.
905 *
906 * @param {Object} relations {@link CKEDITOR.plugins.lineutils.finder#relations}.
907 * @param {Object} locations {@link CKEDITOR.plugins.lineutils.locator#locations}.
908 */
909 prepare: function( relations, locations ) {
910 this.relations = relations;
911 this.locations = locations;
912 this.hash = Math.random();
913 },
914
915 /**
916 * Hides all visible lines that do not belong to current hash
917 * and no longer represent relations (locations).
918 *
919 * See also: {@link #prepare}.
920 */
921 cleanup: function() {
922 var line;
923
924 for ( var l in this.visible ) {
925 line = this.visible[ l ];
926
927 if ( line.getCustomData( 'hash' ) !== this.hash ) {
928 this.hideLine( line );
929 }
930 }
931 },
932
933 /**
934 * Queries dimensions of the viewport, editable, frame etc.
935 * that are used for correct positioning of the line.
936 */
937 queryViewport: function() {
938 this.winPane = this.win.getViewPaneSize();
939 this.winTopScroll = this.winTop.getScrollPosition();
940 this.winTopPane = this.winTop.getViewPaneSize();
941
942 // (#13155)
943 this.rect = this.getClientRect( this.inline ? this.editable : this.frame );
944 },
945
946 /**
947 * Returns `boundingClientRect` of an element, shifted by the position
948 * of `container` when the container is not `static` (#13155).
949 *
950 * See also: {@link CKEDITOR.dom.element#getClientRect}.
951 *
952 * @param {CKEDITOR.dom.element} el A DOM element.
953 * @returns {Object} A shifted rect, extended by `relativeY` and `relativeX` properties.
954 */
955 getClientRect: function( el ) {
956 var rect = el.getClientRect(),
957 relativeContainerDocPosition = this.container.getDocumentPosition(),
958 relativeContainerComputedPosition = this.container.getComputedStyle( 'position' );
959
960 // Static or not, those values are used to offset the position of the line so they cannot be undefined.
961 rect.relativeX = rect.relativeY = 0;
962
963 if ( relativeContainerComputedPosition != 'static' ) {
964 // Remember the offset used to shift the clientRect.
965 rect.relativeY = relativeContainerDocPosition.y;
966 rect.relativeX = relativeContainerDocPosition.x;
967
968 rect.top -= rect.relativeY;
969 rect.bottom -= rect.relativeY;
970 rect.left -= rect.relativeX;
971 rect.right -= rect.relativeX;
972 }
973
974 return rect;
975 }
976 };
977
978 function is( type, flag ) {
979 return type & flag;
980 }
981
982 var floats = { left: 1, right: 1, center: 1 },
983 positions = { absolute: 1, fixed: 1 };
984
985 function isElement( node ) {
986 return node && node.type == CKEDITOR.NODE_ELEMENT;
987 }
988
989 function isFloated( el ) {
990 return !!( floats[ el.getComputedStyle( 'float' ) ] || floats[ el.getAttribute( 'align' ) ] );
991 }
992
993 function isPositioned( el ) {
994 return !!positions[ el.getComputedStyle( 'position' ) ];
995 }
996
997 function isLimit( node ) {
998 return isElement( node ) && node.getAttribute( 'contenteditable' ) == 'true';
999 }
1000
1001 function isStatic( node ) {
1002 return isElement( node ) && !isFloated( node ) && !isPositioned( node );
1003 }
1004
1005 /**
1006 * Global namespace storing definitions and global helpers for the Line Utilities plugin.
1007 *
1008 * @private
1009 * @class
1010 * @singleton
1011 * @since 4.3
1012 */
1013 CKEDITOR.plugins.lineutils = {
1014 finder: Finder,
1015 locator: Locator,
1016 liner: Liner
1017 };
1018} )();
diff --git a/sources/plugins/link/dialogs/anchor.js b/sources/plugins/link/dialogs/anchor.js
new file mode 100644
index 0000000..2b32b71
--- /dev/null
+++ b/sources/plugins/link/dialogs/anchor.js
@@ -0,0 +1,105 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.dialog.add( 'anchor', function( editor ) {
7 // Function called in onShow to load selected element.
8 var loadElements = function( element ) {
9 this._.selectedElement = element;
10
11 var attributeValue = element.data( 'cke-saved-name' );
12 this.setValueOf( 'info', 'txtName', attributeValue || '' );
13 };
14
15 function createFakeAnchor( editor, attributes ) {
16 return editor.createFakeElement( editor.document.createElement( 'a', {
17 attributes: attributes
18 } ), 'cke_anchor', 'anchor' );
19 }
20
21 return {
22 title: editor.lang.link.anchor.title,
23 minWidth: 300,
24 minHeight: 60,
25 onOk: function() {
26 var name = CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtName' ) );
27 var attributes = {
28 id: name,
29 name: name,
30 'data-cke-saved-name': name
31 };
32
33 if ( this._.selectedElement ) {
34 if ( this._.selectedElement.data( 'cke-realelement' ) ) {
35 var newFake = createFakeAnchor( editor, attributes );
36 newFake.replace( this._.selectedElement );
37
38 // Selecting fake element for IE. (#11377)
39 if ( CKEDITOR.env.ie )
40 editor.getSelection().selectElement( newFake );
41 } else {
42 this._.selectedElement.setAttributes( attributes );
43 }
44 } else {
45 var sel = editor.getSelection(),
46 range = sel && sel.getRanges()[ 0 ];
47
48 // Empty anchor
49 if ( range.collapsed ) {
50 var anchor = createFakeAnchor( editor, attributes );
51 range.insertNode( anchor );
52 } else {
53 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
54 attributes[ 'class' ] = 'cke_anchor';
55
56 // Apply style.
57 var style = new CKEDITOR.style( { element: 'a', attributes: attributes } );
58 style.type = CKEDITOR.STYLE_INLINE;
59 editor.applyStyle( style );
60 }
61 }
62 },
63
64 onHide: function() {
65 delete this._.selectedElement;
66 },
67
68 onShow: function() {
69 var sel = editor.getSelection(),
70 fullySelected = sel.getSelectedElement(),
71 fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ),
72 linkElement = fakeSelected ?
73 CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) :
74 CKEDITOR.plugins.link.getSelectedLink( editor );
75
76 if ( linkElement ) {
77 loadElements.call( this, linkElement );
78 !fakeSelected && sel.selectElement( linkElement );
79
80 if ( fullySelected )
81 this._.selectedElement = fullySelected;
82 }
83
84 this.getContentElement( 'info', 'txtName' ).focus();
85 },
86 contents: [ {
87 id: 'info',
88 label: editor.lang.link.anchor.title,
89 accessKey: 'I',
90 elements: [ {
91 type: 'text',
92 id: 'txtName',
93 label: editor.lang.link.anchor.name,
94 required: true,
95 validate: function() {
96 if ( !this.getValue() ) {
97 alert( editor.lang.link.anchor.errorName ); // jshint ignore:line
98 return false;
99 }
100 return true;
101 }
102 } ]
103 } ]
104 };
105} );
diff --git a/sources/plugins/link/dialogs/link.js b/sources/plugins/link/dialogs/link.js
new file mode 100644
index 0000000..914471f
--- /dev/null
+++ b/sources/plugins/link/dialogs/link.js
@@ -0,0 +1,979 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6'use strict';
7
8( function() {
9 CKEDITOR.dialog.add( 'link', function( editor ) {
10 var plugin = CKEDITOR.plugins.link,
11 initialLinkText;
12
13 // Handles the event when the "Target" selection box is changed.
14 var targetChanged = function() {
15 var dialog = this.getDialog(),
16 popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ),
17 targetName = dialog.getContentElement( 'target', 'linkTargetName' ),
18 value = this.getValue();
19
20 if ( !popupFeatures || !targetName )
21 return;
22
23 popupFeatures = popupFeatures.getElement();
24 popupFeatures.hide();
25 targetName.setValue( '' );
26
27 switch ( value ) {
28 case 'frame':
29 targetName.setLabel( editor.lang.link.targetFrameName );
30 targetName.getElement().show();
31 break;
32 case 'popup':
33 popupFeatures.show();
34 targetName.setLabel( editor.lang.link.targetPopupName );
35 targetName.getElement().show();
36 break;
37 default:
38 targetName.setValue( value );
39 targetName.getElement().hide();
40 break;
41 }
42
43 };
44
45 // Handles the event when the "Type" selection box is changed.
46 var linkTypeChanged = function() {
47 var dialog = this.getDialog(),
48 partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions' ],
49 typeValue = this.getValue(),
50 uploadTab = dialog.definition.getContents( 'upload' ),
51 uploadInitiallyHidden = uploadTab && uploadTab.hidden;
52
53 if ( typeValue == 'url' ) {
54 if ( editor.config.linkShowTargetTab )
55 dialog.showPage( 'target' );
56 if ( !uploadInitiallyHidden )
57 dialog.showPage( 'upload' );
58 } else {
59 dialog.hidePage( 'target' );
60 if ( !uploadInitiallyHidden )
61 dialog.hidePage( 'upload' );
62 }
63
64 for ( var i = 0; i < partIds.length; i++ ) {
65 var element = dialog.getContentElement( 'info', partIds[ i ] );
66 if ( !element )
67 continue;
68
69 element = element.getElement().getParent().getParent();
70 if ( partIds[ i ] == typeValue + 'Options' )
71 element.show();
72 else
73 element.hide();
74 }
75
76 dialog.layout();
77 };
78
79 var setupParams = function( page, data ) {
80 if ( data[ page ] )
81 this.setValue( data[ page ][ this.id ] || '' );
82 };
83
84 var setupPopupParams = function( data ) {
85 return setupParams.call( this, 'target', data );
86 };
87
88 var setupAdvParams = function( data ) {
89 return setupParams.call( this, 'advanced', data );
90 };
91
92 var commitParams = function( page, data ) {
93 if ( !data[ page ] )
94 data[ page ] = {};
95
96 data[ page ][ this.id ] = this.getValue() || '';
97 };
98
99 var commitPopupParams = function( data ) {
100 return commitParams.call( this, 'target', data );
101 };
102
103 var commitAdvParams = function( data ) {
104 return commitParams.call( this, 'advanced', data );
105 };
106
107 var commonLang = editor.lang.common,
108 linkLang = editor.lang.link,
109 anchors;
110
111 return {
112 title: linkLang.title,
113 minWidth: ( CKEDITOR.skinName || editor.config.skin ) == 'moono-lisa' ? 450 : 350,
114 minHeight: 240,
115 contents: [ {
116 id: 'info',
117 label: linkLang.info,
118 title: linkLang.info,
119 elements: [ {
120 type: 'text',
121 id: 'linkDisplayText',
122 label: linkLang.displayText,
123 setup: function() {
124 this.enable();
125
126 this.setValue( editor.getSelection().getSelectedText() );
127
128 // Keep inner text so that it can be compared in commit function. By obtaining value from getData()
129 // we get value stripped from new line chars which is important when comparing the value later on.
130 initialLinkText = this.getValue();
131 },
132 commit: function( data ) {
133 data.linkText = this.isEnabled() ? this.getValue() : '';
134 }
135 },
136 {
137 id: 'linkType',
138 type: 'select',
139 label: linkLang.type,
140 'default': 'url',
141 items: [
142 [ linkLang.toUrl, 'url' ],
143 [ linkLang.toAnchor, 'anchor' ],
144 [ linkLang.toEmail, 'email' ]
145 ],
146 onChange: linkTypeChanged,
147 setup: function( data ) {
148 this.setValue( data.type || 'url' );
149 },
150 commit: function( data ) {
151 data.type = this.getValue();
152 }
153 },
154 {
155 type: 'vbox',
156 id: 'urlOptions',
157 children: [ {
158 type: 'hbox',
159 widths: [ '25%', '75%' ],
160 children: [ {
161 id: 'protocol',
162 type: 'select',
163 label: commonLang.protocol,
164 'default': 'http://',
165 items: [
166 // Force 'ltr' for protocol names in BIDI. (#5433)
167 [ 'http://\u200E', 'http://' ],
168 [ 'https://\u200E', 'https://' ],
169 [ 'ftp://\u200E', 'ftp://' ],
170 [ 'news://\u200E', 'news://' ],
171 [ linkLang.other, '' ]
172 ],
173 setup: function( data ) {
174 if ( data.url )
175 this.setValue( data.url.protocol || '' );
176 },
177 commit: function( data ) {
178 if ( !data.url )
179 data.url = {};
180
181 data.url.protocol = this.getValue();
182 }
183 },
184 {
185 type: 'text',
186 id: 'url',
187 label: commonLang.url,
188 required: true,
189 onLoad: function() {
190 this.allowOnChange = true;
191 },
192 onKeyUp: function() {
193 this.allowOnChange = false;
194 var protocolCmb = this.getDialog().getContentElement( 'info', 'protocol' ),
195 url = this.getValue(),
196 urlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/i,
197 urlOnChangeTestOther = /^((javascript:)|[#\/\.\?])/i;
198
199 var protocol = urlOnChangeProtocol.exec( url );
200 if ( protocol ) {
201 this.setValue( url.substr( protocol[ 0 ].length ) );
202 protocolCmb.setValue( protocol[ 0 ].toLowerCase() );
203 } else if ( urlOnChangeTestOther.test( url ) ) {
204 protocolCmb.setValue( '' );
205 }
206
207 this.allowOnChange = true;
208 },
209 onChange: function() {
210 if ( this.allowOnChange ) // Dont't call on dialog load.
211 this.onKeyUp();
212 },
213 validate: function() {
214 var dialog = this.getDialog();
215
216 if ( dialog.getContentElement( 'info', 'linkType' ) && dialog.getValueOf( 'info', 'linkType' ) != 'url' )
217 return true;
218
219 if ( !editor.config.linkJavaScriptLinksAllowed && ( /javascript\:/ ).test( this.getValue() ) ) {
220 alert( commonLang.invalidValue ); // jshint ignore:line
221 return false;
222 }
223
224 if ( this.getDialog().fakeObj ) // Edit Anchor.
225 return true;
226
227 var func = CKEDITOR.dialog.validate.notEmpty( linkLang.noUrl );
228 return func.apply( this );
229 },
230 setup: function( data ) {
231 this.allowOnChange = false;
232 if ( data.url )
233 this.setValue( data.url.url );
234 this.allowOnChange = true;
235
236 },
237 commit: function( data ) {
238 // IE will not trigger the onChange event if the mouse has been used
239 // to carry all the operations #4724
240 this.onChange();
241
242 if ( !data.url )
243 data.url = {};
244
245 data.url.url = this.getValue();
246 this.allowOnChange = false;
247 }
248 } ],
249 setup: function() {
250 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
251 this.getElement().show();
252 }
253 },
254 {
255 type: 'button',
256 id: 'browse',
257 hidden: 'true',
258 filebrowser: 'info:url',
259 label: commonLang.browseServer
260 } ]
261 },
262 {
263 type: 'vbox',
264 id: 'anchorOptions',
265 width: 260,
266 align: 'center',
267 padding: 0,
268 children: [ {
269 type: 'fieldset',
270 id: 'selectAnchorText',
271 label: linkLang.selectAnchor,
272 setup: function() {
273 anchors = plugin.getEditorAnchors( editor );
274
275 this.getElement()[ anchors && anchors.length ? 'show' : 'hide' ]();
276 },
277 children: [ {
278 type: 'hbox',
279 id: 'selectAnchor',
280 children: [ {
281 type: 'select',
282 id: 'anchorName',
283 'default': '',
284 label: linkLang.anchorName,
285 style: 'width: 100%;',
286 items: [
287 [ '' ]
288 ],
289 setup: function( data ) {
290 this.clear();
291 this.add( '' );
292
293 if ( anchors ) {
294 for ( var i = 0; i < anchors.length; i++ ) {
295 if ( anchors[ i ].name )
296 this.add( anchors[ i ].name );
297 }
298 }
299
300 if ( data.anchor )
301 this.setValue( data.anchor.name );
302
303 var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
304 if ( linkType && linkType.getValue() == 'email' )
305 this.focus();
306 },
307 commit: function( data ) {
308 if ( !data.anchor )
309 data.anchor = {};
310
311 data.anchor.name = this.getValue();
312 }
313 },
314 {
315 type: 'select',
316 id: 'anchorId',
317 'default': '',
318 label: linkLang.anchorId,
319 style: 'width: 100%;',
320 items: [
321 [ '' ]
322 ],
323 setup: function( data ) {
324 this.clear();
325 this.add( '' );
326
327 if ( anchors ) {
328 for ( var i = 0; i < anchors.length; i++ ) {
329 if ( anchors[ i ].id )
330 this.add( anchors[ i ].id );
331 }
332 }
333
334 if ( data.anchor )
335 this.setValue( data.anchor.id );
336 },
337 commit: function( data ) {
338 if ( !data.anchor )
339 data.anchor = {};
340
341 data.anchor.id = this.getValue();
342 }
343 } ],
344 setup: function() {
345 this.getElement()[ anchors && anchors.length ? 'show' : 'hide' ]();
346 }
347 } ]
348 },
349 {
350 type: 'html',
351 id: 'noAnchors',
352 style: 'text-align: center;',
353 html: '<div role="note" tabIndex="-1">' + CKEDITOR.tools.htmlEncode( linkLang.noAnchors ) + '</div>',
354 // Focus the first element defined in above html.
355 focus: true,
356 setup: function() {
357 this.getElement()[ anchors && anchors.length ? 'hide' : 'show' ]();
358 }
359 } ],
360 setup: function() {
361 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
362 this.getElement().hide();
363 }
364 },
365 {
366 type: 'vbox',
367 id: 'emailOptions',
368 padding: 1,
369 children: [ {
370 type: 'text',
371 id: 'emailAddress',
372 label: linkLang.emailAddress,
373 required: true,
374 validate: function() {
375 var dialog = this.getDialog();
376
377 if ( !dialog.getContentElement( 'info', 'linkType' ) || dialog.getValueOf( 'info', 'linkType' ) != 'email' )
378 return true;
379
380 var func = CKEDITOR.dialog.validate.notEmpty( linkLang.noEmail );
381 return func.apply( this );
382 },
383 setup: function( data ) {
384 if ( data.email )
385 this.setValue( data.email.address );
386
387 var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
388 if ( linkType && linkType.getValue() == 'email' )
389 this.select();
390 },
391 commit: function( data ) {
392 if ( !data.email )
393 data.email = {};
394
395 data.email.address = this.getValue();
396 }
397 },
398 {
399 type: 'text',
400 id: 'emailSubject',
401 label: linkLang.emailSubject,
402 setup: function( data ) {
403 if ( data.email )
404 this.setValue( data.email.subject );
405 },
406 commit: function( data ) {
407 if ( !data.email )
408 data.email = {};
409
410 data.email.subject = this.getValue();
411 }
412 },
413 {
414 type: 'textarea',
415 id: 'emailBody',
416 label: linkLang.emailBody,
417 rows: 3,
418 'default': '',
419 setup: function( data ) {
420 if ( data.email )
421 this.setValue( data.email.body );
422 },
423 commit: function( data ) {
424 if ( !data.email )
425 data.email = {};
426
427 data.email.body = this.getValue();
428 }
429 } ],
430 setup: function() {
431 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
432 this.getElement().hide();
433 }
434 } ]
435 },
436 {
437 id: 'target',
438 requiredContent: 'a[target]', // This is not fully correct, because some target option requires JS.
439 label: linkLang.target,
440 title: linkLang.target,
441 elements: [ {
442 type: 'hbox',
443 widths: [ '50%', '50%' ],
444 children: [ {
445 type: 'select',
446 id: 'linkTargetType',
447 label: commonLang.target,
448 'default': 'notSet',
449 style: 'width : 100%;',
450 'items': [
451 [ commonLang.notSet, 'notSet' ],
452 [ linkLang.targetFrame, 'frame' ],
453 [ linkLang.targetPopup, 'popup' ],
454 [ commonLang.targetNew, '_blank' ],
455 [ commonLang.targetTop, '_top' ],
456 [ commonLang.targetSelf, '_self' ],
457 [ commonLang.targetParent, '_parent' ]
458 ],
459 onChange: targetChanged,
460 setup: function( data ) {
461 if ( data.target )
462 this.setValue( data.target.type || 'notSet' );
463 targetChanged.call( this );
464 },
465 commit: function( data ) {
466 if ( !data.target )
467 data.target = {};
468
469 data.target.type = this.getValue();
470 }
471 },
472 {
473 type: 'text',
474 id: 'linkTargetName',
475 label: linkLang.targetFrameName,
476 'default': '',
477 setup: function( data ) {
478 if ( data.target )
479 this.setValue( data.target.name );
480 },
481 commit: function( data ) {
482 if ( !data.target )
483 data.target = {};
484
485 data.target.name = this.getValue().replace( /([^\x00-\x7F]|\s)/gi, '' );
486 }
487 } ]
488 },
489 {
490 type: 'vbox',
491 width: '100%',
492 align: 'center',
493 padding: 2,
494 id: 'popupFeatures',
495 children: [ {
496 type: 'fieldset',
497 label: linkLang.popupFeatures,
498 children: [ {
499 type: 'hbox',
500 children: [ {
501 type: 'checkbox',
502 id: 'resizable',
503 label: linkLang.popupResizable,
504 setup: setupPopupParams,
505 commit: commitPopupParams
506 },
507 {
508 type: 'checkbox',
509 id: 'status',
510 label: linkLang.popupStatusBar,
511 setup: setupPopupParams,
512 commit: commitPopupParams
513
514 } ]
515 },
516 {
517 type: 'hbox',
518 children: [ {
519 type: 'checkbox',
520 id: 'location',
521 label: linkLang.popupLocationBar,
522 setup: setupPopupParams,
523 commit: commitPopupParams
524
525 },
526 {
527 type: 'checkbox',
528 id: 'toolbar',
529 label: linkLang.popupToolbar,
530 setup: setupPopupParams,
531 commit: commitPopupParams
532
533 } ]
534 },
535 {
536 type: 'hbox',
537 children: [ {
538 type: 'checkbox',
539 id: 'menubar',
540 label: linkLang.popupMenuBar,
541 setup: setupPopupParams,
542 commit: commitPopupParams
543
544 },
545 {
546 type: 'checkbox',
547 id: 'fullscreen',
548 label: linkLang.popupFullScreen,
549 setup: setupPopupParams,
550 commit: commitPopupParams
551
552 } ]
553 },
554 {
555 type: 'hbox',
556 children: [ {
557 type: 'checkbox',
558 id: 'scrollbars',
559 label: linkLang.popupScrollBars,
560 setup: setupPopupParams,
561 commit: commitPopupParams
562
563 },
564 {
565 type: 'checkbox',
566 id: 'dependent',
567 label: linkLang.popupDependent,
568 setup: setupPopupParams,
569 commit: commitPopupParams
570
571 } ]
572 },
573 {
574 type: 'hbox',
575 children: [ {
576 type: 'text',
577 widths: [ '50%', '50%' ],
578 labelLayout: 'horizontal',
579 label: commonLang.width,
580 id: 'width',
581 setup: setupPopupParams,
582 commit: commitPopupParams
583
584 },
585 {
586 type: 'text',
587 labelLayout: 'horizontal',
588 widths: [ '50%', '50%' ],
589 label: linkLang.popupLeft,
590 id: 'left',
591 setup: setupPopupParams,
592 commit: commitPopupParams
593
594 } ]
595 },
596 {
597 type: 'hbox',
598 children: [ {
599 type: 'text',
600 labelLayout: 'horizontal',
601 widths: [ '50%', '50%' ],
602 label: commonLang.height,
603 id: 'height',
604 setup: setupPopupParams,
605 commit: commitPopupParams
606
607 },
608 {
609 type: 'text',
610 labelLayout: 'horizontal',
611 label: linkLang.popupTop,
612 widths: [ '50%', '50%' ],
613 id: 'top',
614 setup: setupPopupParams,
615 commit: commitPopupParams
616
617 } ]
618 } ]
619 } ]
620 } ]
621 },
622 {
623 id: 'upload',
624 label: linkLang.upload,
625 title: linkLang.upload,
626 hidden: true,
627 filebrowser: 'uploadButton',
628 elements: [ {
629 type: 'file',
630 id: 'upload',
631 label: commonLang.upload,
632 style: 'height:40px',
633 size: 29
634 },
635 {
636 type: 'fileButton',
637 id: 'uploadButton',
638 label: commonLang.uploadSubmit,
639 filebrowser: 'info:url',
640 'for': [ 'upload', 'upload' ]
641 } ]
642 },
643 {
644 id: 'advanced',
645 label: linkLang.advanced,
646 title: linkLang.advanced,
647 elements: [ {
648 type: 'vbox',
649 padding: 1,
650 children: [ {
651 type: 'hbox',
652 widths: [ '45%', '35%', '20%' ],
653 children: [ {
654 type: 'text',
655 id: 'advId',
656 requiredContent: 'a[id]',
657 label: linkLang.id,
658 setup: setupAdvParams,
659 commit: commitAdvParams
660 },
661 {
662 type: 'select',
663 id: 'advLangDir',
664 requiredContent: 'a[dir]',
665 label: linkLang.langDir,
666 'default': '',
667 style: 'width:110px',
668 items: [
669 [ commonLang.notSet, '' ],
670 [ linkLang.langDirLTR, 'ltr' ],
671 [ linkLang.langDirRTL, 'rtl' ]
672 ],
673 setup: setupAdvParams,
674 commit: commitAdvParams
675 },
676 {
677 type: 'text',
678 id: 'advAccessKey',
679 requiredContent: 'a[accesskey]',
680 width: '80px',
681 label: linkLang.acccessKey,
682 maxLength: 1,
683 setup: setupAdvParams,
684 commit: commitAdvParams
685
686 } ]
687 },
688 {
689 type: 'hbox',
690 widths: [ '45%', '35%', '20%' ],
691 children: [ {
692 type: 'text',
693 label: linkLang.name,
694 id: 'advName',
695 requiredContent: 'a[name]',
696 setup: setupAdvParams,
697 commit: commitAdvParams
698
699 },
700 {
701 type: 'text',
702 label: linkLang.langCode,
703 id: 'advLangCode',
704 requiredContent: 'a[lang]',
705 width: '110px',
706 'default': '',
707 setup: setupAdvParams,
708 commit: commitAdvParams
709
710 },
711 {
712 type: 'text',
713 label: linkLang.tabIndex,
714 id: 'advTabIndex',
715 requiredContent: 'a[tabindex]',
716 width: '80px',
717 maxLength: 5,
718 setup: setupAdvParams,
719 commit: commitAdvParams
720
721 } ]
722 } ]
723 },
724 {
725 type: 'vbox',
726 padding: 1,
727 children: [ {
728 type: 'hbox',
729 widths: [ '45%', '55%' ],
730 children: [ {
731 type: 'text',
732 label: linkLang.advisoryTitle,
733 requiredContent: 'a[title]',
734 'default': '',
735 id: 'advTitle',
736 setup: setupAdvParams,
737 commit: commitAdvParams
738
739 },
740 {
741 type: 'text',
742 label: linkLang.advisoryContentType,
743 requiredContent: 'a[type]',
744 'default': '',
745 id: 'advContentType',
746 setup: setupAdvParams,
747 commit: commitAdvParams
748
749 } ]
750 },
751 {
752 type: 'hbox',
753 widths: [ '45%', '55%' ],
754 children: [ {
755 type: 'text',
756 label: linkLang.cssClasses,
757 requiredContent: 'a(cke-xyz)', // Random text like 'xyz' will check if all are allowed.
758 'default': '',
759 id: 'advCSSClasses',
760 setup: setupAdvParams,
761 commit: commitAdvParams
762
763 },
764 {
765 type: 'text',
766 label: linkLang.charset,
767 requiredContent: 'a[charset]',
768 'default': '',
769 id: 'advCharset',
770 setup: setupAdvParams,
771 commit: commitAdvParams
772
773 } ]
774 },
775 {
776 type: 'hbox',
777 widths: [ '45%', '55%' ],
778 children: [ {
779 type: 'text',
780 label: linkLang.rel,
781 requiredContent: 'a[rel]',
782 'default': '',
783 id: 'advRel',
784 setup: setupAdvParams,
785 commit: commitAdvParams
786 },
787 {
788 type: 'text',
789 label: linkLang.styles,
790 requiredContent: 'a{cke-xyz}', // Random text like 'xyz' will check if all are allowed.
791 'default': '',
792 id: 'advStyles',
793 validate: CKEDITOR.dialog.validate.inlineStyle( editor.lang.common.invalidInlineStyle ),
794 setup: setupAdvParams,
795 commit: commitAdvParams
796 } ]
797 },
798 {
799 type: 'hbox',
800 widths: [ '45%', '55%' ],
801 children: [ {
802 type: 'checkbox',
803 id: 'download',
804 requiredContent: 'a[download]',
805 label: linkLang.download,
806 setup: function( data ) {
807 if ( data.download !== undefined )
808 this.setValue( 'checked', 'checked' );
809 },
810 commit: function( data ) {
811 if ( this.getValue() ) {
812 data.download = this.getValue();
813 }
814 }
815 } ]
816 } ]
817 } ]
818 } ],
819 onShow: function() {
820 var editor = this.getParentEditor(),
821 selection = editor.getSelection(),
822 selectedElement = selection.getSelectedElement(),
823 displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(),
824 element = null;
825
826 // Fill in all the relevant fields if there's already one link selected.
827 if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) ) {
828 // Don't change selection if some element is already selected.
829 // For example - don't destroy fake selection.
830 if ( !selectedElement ) {
831 selection.selectElement( element );
832 selectedElement = element;
833 }
834 } else {
835 element = null;
836 }
837
838 // Here we'll decide whether or not we want to show Display Text field.
839 if ( plugin.showDisplayTextForElement( selectedElement, editor ) ) {
840 displayTextField.show();
841 } else {
842 displayTextField.hide();
843 }
844
845 var data = plugin.parseLinkAttributes( editor, element );
846
847 // Record down the selected element in the dialog.
848 this._.selectedElement = element;
849
850 this.setupContent( data );
851 },
852 onOk: function() {
853 var data = {};
854
855 // Collect data from fields.
856 this.commitContent( data );
857
858 var selection = editor.getSelection(),
859 attributes = plugin.getLinkAttributes( editor, data ),
860 bm,
861 nestedLinks;
862
863 if ( !this._.selectedElement ) {
864 var range = selection.getRanges()[ 0 ],
865 text;
866
867 // Use link URL as text with a collapsed cursor.
868 if ( range.collapsed ) {
869 // Short mailto link text view (#5736).
870 text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ?
871 data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document );
872 range.insertNode( text );
873 range.selectNodeContents( text );
874 } else if ( initialLinkText !== data.linkText ) {
875 text = new CKEDITOR.dom.text( data.linkText, editor.document );
876
877 // Shrink range to preserve block element.
878 range.shrink( CKEDITOR.SHRINK_TEXT );
879
880 // Use extractHtmlFromRange to remove markup within the selection. Also this method is a little
881 // smarter than range#deleteContents as it plays better e.g. with table cells.
882 editor.editable().extractHtmlFromRange( range );
883
884 range.insertNode( text );
885 }
886
887 // Editable links nested within current range should be removed, so that the link is applied to whole selection.
888 nestedLinks = range._find( 'a' );
889
890 for ( var i = 0; i < nestedLinks.length; i++ ) {
891 nestedLinks[ i ].remove( true );
892 }
893
894 // Apply style.
895 var style = new CKEDITOR.style( {
896 element: 'a',
897 attributes: attributes.set
898 } );
899
900 style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
901 style.applyToRange( range, editor );
902 range.select();
903 } else {
904 // We're only editing an existing link, so just overwrite the attributes.
905 var element = this._.selectedElement,
906 href = element.data( 'cke-saved-href' ),
907 textView = element.getHtml(),
908 newText;
909
910 element.setAttributes( attributes.set );
911 element.removeAttributes( attributes.removed );
912
913 if ( data.linkText && initialLinkText != data.linkText ) {
914 // Display text has been changed.
915 newText = data.linkText;
916 } else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {
917 // Update text view when user changes protocol (#4612).
918 // Short mailto link text view (#5736).
919 newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ];
920 }
921
922 if ( newText ) {
923 element.setText( newText );
924 // We changed the content, so need to select it again.
925 selection.selectElement( element );
926 }
927
928 delete this._.selectedElement;
929 }
930 },
931 onLoad: function() {
932 if ( !editor.config.linkShowAdvancedTab )
933 this.hidePage( 'advanced' ); //Hide Advanded tab.
934
935 if ( !editor.config.linkShowTargetTab )
936 this.hidePage( 'target' ); //Hide Target tab.
937 },
938 // Inital focus on 'url' field if link is of type URL.
939 onFocus: function() {
940 var linkType = this.getContentElement( 'info', 'linkType' ),
941 urlField;
942
943 if ( linkType && linkType.getValue() == 'url' ) {
944 urlField = this.getContentElement( 'info', 'url' );
945 urlField.select();
946 }
947 }
948 };
949 } );
950} )();
951// jscs:disable maximumLineLength
952/**
953 * The e-mail address anti-spam protection option. The protection will be
954 * applied when creating or modifying e-mail links through the editor interface.
955 *
956 * Two methods of protection can be chosen:
957 *
958 * 1. The e-mail parts (name, domain, and any other query string) are
959 * assembled into a function call pattern. Such function must be
960 * provided by the developer in the pages that will use the contents.
961 * 2. Only the e-mail address is obfuscated into a special string that
962 * has no meaning for humans or spam bots, but which is properly
963 * rendered and accepted by the browser.
964 *
965 * Both approaches require JavaScript to be enabled.
966 *
967 * // href="mailto:tester@ckeditor.com?subject=subject&body=body"
968 * config.emailProtection = '';
969 *
970 * // href="<a href=\"javascript:void(location.href=\'mailto:\'+String.fromCharCode(116,101,115,116,101,114,64,99,107,101,100,105,116,111,114,46,99,111,109)+\'?subject=subject&body=body\')\">e-mail</a>"
971 * config.emailProtection = 'encode';
972 *
973 * // href="javascript:mt('tester','ckeditor.com','subject','body')"
974 * config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)';
975 *
976 * @since 3.1
977 * @cfg {String} [emailProtection='' (empty string = disabled)]
978 * @member CKEDITOR.config
979 */
diff --git a/sources/plugins/link/icons/anchor-rtl.png b/sources/plugins/link/icons/anchor-rtl.png
new file mode 100644
index 0000000..b068855
--- /dev/null
+++ b/sources/plugins/link/icons/anchor-rtl.png
Binary files differ
diff --git a/sources/plugins/link/icons/anchor.png b/sources/plugins/link/icons/anchor.png
new file mode 100644
index 0000000..e50d6cd
--- /dev/null
+++ b/sources/plugins/link/icons/anchor.png
Binary files differ
diff --git a/sources/plugins/link/icons/hidpi/anchor-rtl.png b/sources/plugins/link/icons/hidpi/anchor-rtl.png
new file mode 100644
index 0000000..3533c38
--- /dev/null
+++ b/sources/plugins/link/icons/hidpi/anchor-rtl.png
Binary files differ
diff --git a/sources/plugins/link/icons/hidpi/anchor.png b/sources/plugins/link/icons/hidpi/anchor.png
new file mode 100644
index 0000000..99eeadd
--- /dev/null
+++ b/sources/plugins/link/icons/hidpi/anchor.png
Binary files differ
diff --git a/sources/plugins/link/icons/hidpi/link.png b/sources/plugins/link/icons/hidpi/link.png
new file mode 100644
index 0000000..43ce99e
--- /dev/null
+++ b/sources/plugins/link/icons/hidpi/link.png
Binary files differ
diff --git a/sources/plugins/link/icons/hidpi/unlink.png b/sources/plugins/link/icons/hidpi/unlink.png
new file mode 100644
index 0000000..8ace29d
--- /dev/null
+++ b/sources/plugins/link/icons/hidpi/unlink.png
Binary files differ
diff --git a/sources/plugins/link/icons/link.png b/sources/plugins/link/icons/link.png
new file mode 100644
index 0000000..c2c450f
--- /dev/null
+++ b/sources/plugins/link/icons/link.png
Binary files differ
diff --git a/sources/plugins/link/icons/unlink.png b/sources/plugins/link/icons/unlink.png
new file mode 100644
index 0000000..c2f3f64
--- /dev/null
+++ b/sources/plugins/link/icons/unlink.png
Binary files differ
diff --git a/sources/plugins/link/images/anchor.png b/sources/plugins/link/images/anchor.png
new file mode 100644
index 0000000..d94adb4
--- /dev/null
+++ b/sources/plugins/link/images/anchor.png
Binary files differ
diff --git a/sources/plugins/link/images/hidpi/anchor.png b/sources/plugins/link/images/hidpi/anchor.png
new file mode 100644
index 0000000..186c3e9
--- /dev/null
+++ b/sources/plugins/link/images/hidpi/anchor.png
Binary files differ
diff --git a/sources/plugins/link/lang/af.js b/sources/plugins/link/lang/af.js
new file mode 100644
index 0000000..3032beb
--- /dev/null
+++ b/sources/plugins/link/lang/af.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'af', {
6 acccessKey: 'Toegangsleutel',
7 advanced: 'Gevorderd',
8 advisoryContentType: 'Aanbevole inhoudstipe',
9 advisoryTitle: 'Aanbevole titel',
10 anchor: {
11 toolbar: 'Anker byvoeg/verander',
12 menu: 'Anker-eienskappe',
13 title: 'Anker-eienskappe',
14 name: 'Ankernaam',
15 errorName: 'Voltooi die ankernaam asseblief',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'Op element Id',
19 anchorName: 'Op ankernaam',
20 charset: 'Karakterstel van geskakelde bron',
21 cssClasses: 'CSS klasse',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-posadres',
25 emailBody: 'Berig-inhoud',
26 emailSubject: 'Berig-onderwerp',
27 id: 'Id',
28 info: 'Skakel informasie',
29 langCode: 'Taalkode',
30 langDir: 'Skryfrigting',
31 langDirLTR: 'Links na regs (LTR)',
32 langDirRTL: 'Regs na links (RTL)',
33 menu: 'Wysig skakel',
34 name: 'Naam',
35 noAnchors: '(Geen ankers beskikbaar in dokument)',
36 noEmail: 'Gee die e-posadres',
37 noUrl: 'Gee die skakel se URL',
38 other: '<ander>',
39 popupDependent: 'Afhanklik (Netscape)',
40 popupFeatures: 'Eienskappe van opspringvenster',
41 popupFullScreen: 'Volskerm (IE)',
42 popupLeft: 'Posisie links',
43 popupLocationBar: 'Adresbalk',
44 popupMenuBar: 'Spyskaartbalk',
45 popupResizable: 'Herskaalbaar',
46 popupScrollBars: 'Skuifbalke',
47 popupStatusBar: 'Statusbalk',
48 popupToolbar: 'Werkbalk',
49 popupTop: 'Posisie bo',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Kies \'n anker',
52 styles: 'Styl',
53 tabIndex: 'Tab indeks',
54 target: 'Doel',
55 targetFrame: '<raam>',
56 targetFrameName: 'Naam van doelraam',
57 targetPopup: '<opspringvenster>',
58 targetPopupName: 'Naam van opspringvenster',
59 title: 'Skakel',
60 toAnchor: 'Anker in bladsy',
61 toEmail: 'E-pos',
62 toUrl: 'URL',
63 toolbar: 'Skakel invoeg/wysig',
64 type: 'Skakelsoort',
65 unlink: 'Verwyder skakel',
66 upload: 'Oplaai'
67} );
diff --git a/sources/plugins/link/lang/ar.js b/sources/plugins/link/lang/ar.js
new file mode 100644
index 0000000..e0dd0d9
--- /dev/null
+++ b/sources/plugins/link/lang/ar.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ar', {
6 acccessKey: 'مفاتيح الإختصار',
7 advanced: 'متقدم',
8 advisoryContentType: 'نوع التقرير',
9 advisoryTitle: 'عنوان التقرير',
10 anchor: {
11 toolbar: 'إشارة مرجعية',
12 menu: 'تحرير الإشارة المرجعية',
13 title: 'خصائص الإشارة المرجعية',
14 name: 'اسم الإشارة المرجعية',
15 errorName: 'الرجاء كتابة اسم الإشارة المرجعية',
16 remove: 'إزالة الإشارة المرجعية'
17 },
18 anchorId: 'حسب رقم العنصر',
19 anchorName: 'حسب إسم الإشارة المرجعية',
20 charset: 'ترميز المادة المطلوبة',
21 cssClasses: 'فئات التنسيق',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'البريد الإلكتروني',
25 emailBody: 'محتوى الرسالة',
26 emailSubject: 'موضوع الرسالة',
27 id: 'هوية',
28 info: 'معلومات الرابط',
29 langCode: 'رمز اللغة',
30 langDir: 'إتجاه نص اللغة',
31 langDirLTR: 'اليسار لليمين (LTR)',
32 langDirRTL: 'اليمين لليسار (RTL)',
33 menu: 'تحرير الرابط',
34 name: 'إسم',
35 noAnchors: '(لا توجد علامات مرجعية في هذا المستند)',
36 noEmail: 'الرجاء كتابة الريد الإلكتروني',
37 noUrl: 'الرجاء كتابة رابط الموقع',
38 other: '<أخرى>',
39 popupDependent: 'تابع (Netscape)',
40 popupFeatures: 'خصائص النافذة المنبثقة',
41 popupFullScreen: 'ملئ الشاشة (IE)',
42 popupLeft: 'التمركز لليسار',
43 popupLocationBar: 'شريط العنوان',
44 popupMenuBar: 'القوائم الرئيسية',
45 popupResizable: 'قابلة التشكيل',
46 popupScrollBars: 'أشرطة التمرير',
47 popupStatusBar: 'شريط الحالة',
48 popupToolbar: 'شريط الأدوات',
49 popupTop: 'التمركز للأعلى',
50 rel: 'العلاقة',
51 selectAnchor: 'اختر علامة مرجعية',
52 styles: 'نمط',
53 tabIndex: 'الترتيب',
54 target: 'هدف الرابط',
55 targetFrame: '<إطار>',
56 targetFrameName: 'اسم الإطار المستهدف',
57 targetPopup: '<نافذة منبثقة>',
58 targetPopupName: 'اسم النافذة المنبثقة',
59 title: 'رابط',
60 toAnchor: 'مكان في هذا المستند',
61 toEmail: 'بريد إلكتروني',
62 toUrl: 'الرابط',
63 toolbar: 'رابط',
64 type: 'نوع الربط',
65 unlink: 'إزالة رابط',
66 upload: 'رفع'
67} );
diff --git a/sources/plugins/link/lang/az.js b/sources/plugins/link/lang/az.js
new file mode 100644
index 0000000..33588fe
--- /dev/null
+++ b/sources/plugins/link/lang/az.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'az', {
6 acccessKey: 'Qısayol düyməsi',
7 advanced: 'Geniş seçimləri',
8 advisoryContentType: 'Məsləhətli məzmunun növü',
9 advisoryTitle: 'Məsləhətli başlıq',
10 anchor: {
11 toolbar: 'Xeş',
12 menu: 'Xeşi redaktə et',
13 title: 'Xeşin seçimləri',
14 name: 'Xeşin adı',
15 errorName: 'Xeşin adı yanlışdır',
16 remove: 'Xeşin adı sil'
17 },
18 anchorId: 'ID görə',
19 anchorName: 'Xeşin adına görə',
20 charset: 'Hədəfin kodlaşdırması',
21 cssClasses: 'Üslub klası',
22 download: 'Məcburi yükləmə',
23 displayText: 'Göstərilən mətn',
24 emailAddress: 'E-poçt ünvanı',
25 emailBody: 'Mesajın məzmunu',
26 emailSubject: 'Mesajın başlığı',
27 id: 'ID',
28 info: 'Linkin xüsusiyyətləri',
29 langCode: 'Dilin kodu',
30 langDir: 'Yaziların istiqaməti',
31 langDirLTR: 'Soldan sağa (LTR)',
32 langDirRTL: 'Sağdan sola (RTL)',
33 menu: 'Linki redaktə et',
34 name: 'Ad',
35 noAnchors: '(heç bir xeş tapılmayıb)',
36 noEmail: 'E-poçt ünvanı daxil edin',
37 noUrl: 'Linkin URL-ı daxil edin',
38 other: '<digər>',
39 popupDependent: 'Asılı (Netscape)',
40 popupFeatures: 'Pəncərənin xüsusiyyətləri',
41 popupFullScreen: 'Tam ekran rejimi (IE)',
42 popupLeft: 'Solda',
43 popupLocationBar: 'Ünvan paneli',
44 popupMenuBar: 'Menyu paneli',
45 popupResizable: 'Olçülər dəyişilir',
46 popupScrollBars: 'Sürüşdürmələr göstər',
47 popupStatusBar: 'Bildirişlərin paneli',
48 popupToolbar: 'Alətlərin paneli',
49 popupTop: 'Yuxarıda',
50 rel: 'Münasibət',
51 selectAnchor: 'Xeşi seçin',
52 styles: 'Üslub',
53 tabIndex: 'Tabın nömrəsi',
54 target: 'Hədəf çərçivə',
55 targetFrame: '<freym>',
56 targetFrameName: 'Freymin adı',
57 targetPopup: '<yeni pəncərə>',
58 targetPopupName: 'Pəncərənin adı',
59 title: 'Link',
60 toAnchor: 'Xeş',
61 toEmail: 'E-poçt',
62 toUrl: 'URL',
63 toolbar: 'Link',
64 type: 'Linkin növü',
65 unlink: 'Linki sil',
66 upload: 'Serverə yüklə'
67} );
diff --git a/sources/plugins/link/lang/bg.js b/sources/plugins/link/lang/bg.js
new file mode 100644
index 0000000..ad32915
--- /dev/null
+++ b/sources/plugins/link/lang/bg.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'bg', {
6 acccessKey: 'Ключ за достъп',
7 advanced: 'Разширено',
8 advisoryContentType: 'Препоръчителен тип на съдържанието',
9 advisoryTitle: 'Препоръчително заглавие',
10 anchor: {
11 toolbar: 'Котва',
12 menu: 'Промяна на котва',
13 title: 'Настройки на котва',
14 name: 'Име на котва',
15 errorName: 'Моля въведете име на котвата',
16 remove: 'Премахване на котва'
17 },
18 anchorId: 'По ID на елемент',
19 anchorName: 'По име на котва',
20 charset: 'Тип на свързания ресурс',
21 cssClasses: 'Класове за CSS',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-mail aдрес',
25 emailBody: 'Съдържание',
26 emailSubject: 'Тема',
27 id: 'ID',
28 info: 'Инфо за връзката',
29 langCode: 'Код за езика',
30 langDir: 'Посока на езика',
31 langDirLTR: 'Ляво на Дясно (ЛнД)',
32 langDirRTL: 'Дясно на Ляво (ДнЛ)',
33 menu: 'Промяна на връзка',
34 name: 'Име',
35 noAnchors: '(Няма котви в текущия документ)',
36 noEmail: 'Моля въведете e-mail aдрес',
37 noUrl: 'Моля въведете URL адреса',
38 other: '<друго>',
39 popupDependent: 'Зависимост (Netscape)',
40 popupFeatures: 'Функции на изкачащ прозорец',
41 popupFullScreen: 'Цял екран (IE)',
42 popupLeft: 'Лява позиция',
43 popupLocationBar: 'Лента с локацията',
44 popupMenuBar: 'Лента за меню',
45 popupResizable: 'Оразмеряем',
46 popupScrollBars: 'Скролери',
47 popupStatusBar: 'Статусна лента',
48 popupToolbar: 'Лента с инструменти',
49 popupTop: 'Горна позиция',
50 rel: 'Връзка',
51 selectAnchor: 'Изберете котва',
52 styles: 'Стил',
53 tabIndex: 'Ред на достъп',
54 target: 'Цел',
55 targetFrame: '<frame>',
56 targetFrameName: 'Име на целевият прозорец',
57 targetPopup: '<изкачащ прозорец>',
58 targetPopupName: 'Име на изкачащ прозорец',
59 title: 'Връзка',
60 toAnchor: 'Връзка към котва в текста',
61 toEmail: 'E-mail',
62 toUrl: 'Уеб адрес',
63 toolbar: 'Връзка',
64 type: 'Тип на връзката',
65 unlink: 'Премахни връзката',
66 upload: 'Качване'
67} );
diff --git a/sources/plugins/link/lang/bn.js b/sources/plugins/link/lang/bn.js
new file mode 100644
index 0000000..c071821
--- /dev/null
+++ b/sources/plugins/link/lang/bn.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'bn', {
6 acccessKey: 'প্রবেশ কী',
7 advanced: 'এডভান্সড',
8 advisoryContentType: 'পরামর্শ কন্টেন্টের প্রকার',
9 advisoryTitle: 'পরামর্শ শীর্ষক',
10 anchor: {
11 toolbar: 'নোঙ্গর',
12 menu: 'নোঙর প্রোপার্টি',
13 title: 'নোঙর প্রোপার্টি',
14 name: 'নোঙরের নাম',
15 errorName: 'নোঙরের নাম টাইপ করুন',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'নোঙরের আইডি দিয়ে',
19 anchorName: 'নোঙরের নাম দিয়ে',
20 charset: 'লিংক রিসোর্স ক্যারেক্টর সেট',
21 cssClasses: 'স্টাইল-শীট ক্লাস',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'ইমেইল ঠিকানা',
25 emailBody: 'মেসেজের দেহ',
26 emailSubject: 'মেসেজের বিষয়',
27 id: 'আইডি',
28 info: 'লিংক তথ্য',
29 langCode: 'ভাষা লেখার দিক',
30 langDir: 'ভাষা লেখার দিক',
31 langDirLTR: 'বাম থেকে ডান (LTR)',
32 langDirRTL: 'ডান থেকে বাম (RTL)',
33 menu: 'লিংক সম্পাদন',
34 name: 'নাম',
35 noAnchors: '(No anchors available in the document)', // MISSING
36 noEmail: 'অনুগ্রহ করে ইমেইল এড্রেস টাইপ করুন',
37 noUrl: 'অনুগ্রহ করে URL লিংক টাইপ করুন',
38 other: '<other>', // MISSING
39 popupDependent: 'ডিপেন্ডেন্ট (Netscape)',
40 popupFeatures: 'পপআপ উইন্ডো ফীচার সমূহ',
41 popupFullScreen: 'পূর্ণ পর্দা জুড়ে (IE)',
42 popupLeft: 'বামের পজিশন',
43 popupLocationBar: 'লোকেশন বার',
44 popupMenuBar: 'মেন্যু বার',
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'স্ক্রল বার',
47 popupStatusBar: 'স্ট্যাটাস বার',
48 popupToolbar: 'টুল বার',
49 popupTop: 'ডানের পজিশন',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'নোঙর বাছাই',
52 styles: 'স্টাইল',
53 tabIndex: 'ট্যাব ইন্ডেক্স',
54 target: 'টার্গেট',
55 targetFrame: '<ফ্রেম>',
56 targetFrameName: 'টার্গেট ফ্রেমের নাম',
57 targetPopup: '<পপআপ উইন্ডো>',
58 targetPopupName: 'পপআপ উইন্ডোর নাম',
59 title: 'লিংক',
60 toAnchor: 'এই পেজে নোঙর কর',
61 toEmail: 'ইমেইল',
62 toUrl: 'URL',
63 toolbar: 'লিংক যুক্ত কর',
64 type: 'লিংক প্রকার',
65 unlink: 'লিংক সরাও',
66 upload: 'আপলোড'
67} );
diff --git a/sources/plugins/link/lang/bs.js b/sources/plugins/link/lang/bs.js
new file mode 100644
index 0000000..d23ae35
--- /dev/null
+++ b/sources/plugins/link/lang/bs.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'bs', {
6 acccessKey: 'Pristupna tipka',
7 advanced: 'Naprednije',
8 advisoryContentType: 'Advisory vrsta sadržaja',
9 advisoryTitle: 'Advisory title',
10 anchor: {
11 toolbar: 'Anchor',
12 menu: 'Edit Anchor',
13 title: 'Anchor Properties',
14 name: 'Anchor Name',
15 errorName: 'Please type the anchor name',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'Po Id-u elementa',
19 anchorName: 'Po nazivu sidra',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Klase CSS stilova',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail Adresa',
25 emailBody: 'Poruka',
26 emailSubject: 'Subjekt poruke',
27 id: 'Id',
28 info: 'Link info',
29 langCode: 'Smjer pisanja',
30 langDir: 'Smjer pisanja',
31 langDirLTR: 'S lijeva na desno (LTR)',
32 langDirRTL: 'S desna na lijevo (RTL)',
33 menu: 'Izmjeni link',
34 name: 'Naziv',
35 noAnchors: '(Nema dostupnih sidra na stranici)',
36 noEmail: 'Molimo ukucajte e-mail adresu',
37 noUrl: 'Molimo ukucajte URL link',
38 other: '<other>', // MISSING
39 popupDependent: 'Ovisno (Netscape)',
40 popupFeatures: 'Moguænosti popup prozora',
41 popupFullScreen: 'Cijeli ekran (IE)',
42 popupLeft: 'Lijeva pozicija',
43 popupLocationBar: 'Traka za lokaciju',
44 popupMenuBar: 'Izborna traka',
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Scroll traka',
47 popupStatusBar: 'Statusna traka',
48 popupToolbar: 'Traka sa alatima',
49 popupTop: 'Gornja pozicija',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Izaberi sidro',
52 styles: 'Stil',
53 tabIndex: 'Tab indeks',
54 target: 'Prozor',
55 targetFrame: '<frejm>',
56 targetFrameName: 'Target Frame Name', // MISSING
57 targetPopup: '<popup prozor>',
58 targetPopupName: 'Naziv popup prozora',
59 title: 'Link',
60 toAnchor: 'Sidro na ovoj stranici',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Ubaci/Izmjeni link',
64 type: 'Tip linka',
65 unlink: 'Izbriši link',
66 upload: 'Šalji'
67} );
diff --git a/sources/plugins/link/lang/ca.js b/sources/plugins/link/lang/ca.js
new file mode 100644
index 0000000..44a9ebd
--- /dev/null
+++ b/sources/plugins/link/lang/ca.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ca', {
6 acccessKey: 'Clau d\'accés',
7 advanced: 'Avançat',
8 advisoryContentType: 'Tipus de contingut consultiu',
9 advisoryTitle: 'Títol consultiu',
10 anchor: {
11 toolbar: 'Insereix/Edita àncora',
12 menu: 'Propietats de l\'àncora',
13 title: 'Propietats de l\'àncora',
14 name: 'Nom de l\'àncora',
15 errorName: 'Si us plau, escriviu el nom de l\'ancora',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'Per Id d\'element',
19 anchorName: 'Per nom d\'àncora',
20 charset: 'Conjunt de caràcters font enllaçat',
21 cssClasses: 'Classes del full d\'estil',
22 download: 'Force Download', // MISSING
23 displayText: 'Text a mostrar',
24 emailAddress: 'Adreça de correu electrònic',
25 emailBody: 'Cos del missatge',
26 emailSubject: 'Assumpte del missatge',
27 id: 'Id',
28 info: 'Informació de l\'enllaç',
29 langCode: 'Direcció de l\'idioma',
30 langDir: 'Direcció de l\'idioma',
31 langDirLTR: 'D\'esquerra a dreta (LTR)',
32 langDirRTL: 'De dreta a esquerra (RTL)',
33 menu: 'Edita l\'enllaç',
34 name: 'Nom',
35 noAnchors: '(No hi ha àncores disponibles en aquest document)',
36 noEmail: 'Si us plau, escrigui l\'adreça correu electrònic',
37 noUrl: 'Si us plau, escrigui l\'enllaç URL',
38 other: '<altre>',
39 popupDependent: 'Depenent (Netscape)',
40 popupFeatures: 'Característiques finestra popup',
41 popupFullScreen: 'Pantalla completa (IE)',
42 popupLeft: 'Posició esquerra',
43 popupLocationBar: 'Barra d\'adreça',
44 popupMenuBar: 'Barra de menú',
45 popupResizable: 'Redimensionable',
46 popupScrollBars: 'Barres d\'scroll',
47 popupStatusBar: 'Barra d\'estat',
48 popupToolbar: 'Barra d\'eines',
49 popupTop: 'Posició dalt',
50 rel: 'Relació',
51 selectAnchor: 'Selecciona una àncora',
52 styles: 'Estil',
53 tabIndex: 'Index de Tab',
54 target: 'Destí',
55 targetFrame: '<marc>',
56 targetFrameName: 'Nom del marc de destí',
57 targetPopup: '<finestra emergent>',
58 targetPopupName: 'Nom finestra popup',
59 title: 'Enllaç',
60 toAnchor: 'Àncora en aquesta pàgina',
61 toEmail: 'Correu electrònic',
62 toUrl: 'URL',
63 toolbar: 'Insereix/Edita enllaç',
64 type: 'Tipus d\'enllaç',
65 unlink: 'Elimina l\'enllaç',
66 upload: 'Puja'
67} );
diff --git a/sources/plugins/link/lang/cs.js b/sources/plugins/link/lang/cs.js
new file mode 100644
index 0000000..508c133
--- /dev/null
+++ b/sources/plugins/link/lang/cs.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'cs', {
6 acccessKey: 'Přístupový klíč',
7 advanced: 'Rozšířené',
8 advisoryContentType: 'Pomocný typ obsahu',
9 advisoryTitle: 'Pomocný titulek',
10 anchor: {
11 toolbar: 'Záložka',
12 menu: 'Vlastnosti záložky',
13 title: 'Vlastnosti záložky',
14 name: 'Název záložky',
15 errorName: 'Zadejte prosím název záložky',
16 remove: 'Odstranit záložku'
17 },
18 anchorId: 'Podle Id objektu',
19 anchorName: 'Podle jména kotvy',
20 charset: 'Přiřazená znaková sada',
21 cssClasses: 'Třída stylu',
22 download: 'Force Download', // MISSING
23 displayText: 'Zobrazit text',
24 emailAddress: 'E-mailová adresa',
25 emailBody: 'Tělo zprávy',
26 emailSubject: 'Předmět zprávy',
27 id: 'Id',
28 info: 'Informace o odkazu',
29 langCode: 'Kód jazyka',
30 langDir: 'Směr jazyka',
31 langDirLTR: 'Zleva doprava (LTR)',
32 langDirRTL: 'Zprava doleva (RTL)',
33 menu: 'Změnit odkaz',
34 name: 'Jméno',
35 noAnchors: '(Ve stránce není definována žádná kotva!)',
36 noEmail: 'Zadejte prosím e-mailovou adresu',
37 noUrl: 'Zadejte prosím URL odkazu',
38 other: '<jiný>',
39 popupDependent: 'Závislost (Netscape)',
40 popupFeatures: 'Vlastnosti vyskakovacího okna',
41 popupFullScreen: 'Celá obrazovka (IE)',
42 popupLeft: 'Levý okraj',
43 popupLocationBar: 'Panel umístění',
44 popupMenuBar: 'Panel nabídky',
45 popupResizable: 'Umožňující měnit velikost',
46 popupScrollBars: 'Posuvníky',
47 popupStatusBar: 'Stavový řádek',
48 popupToolbar: 'Panel nástrojů',
49 popupTop: 'Horní okraj',
50 rel: 'Vztah',
51 selectAnchor: 'Vybrat kotvu',
52 styles: 'Styl',
53 tabIndex: 'Pořadí prvku',
54 target: 'Cíl',
55 targetFrame: '<rámec>',
56 targetFrameName: 'Název cílového rámu',
57 targetPopup: '<vyskakovací okno>',
58 targetPopupName: 'Název vyskakovacího okna',
59 title: 'Odkaz',
60 toAnchor: 'Kotva v této stránce',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Odkaz',
64 type: 'Typ odkazu',
65 unlink: 'Odstranit odkaz',
66 upload: 'Odeslat'
67} );
diff --git a/sources/plugins/link/lang/cy.js b/sources/plugins/link/lang/cy.js
new file mode 100644
index 0000000..024b669
--- /dev/null
+++ b/sources/plugins/link/lang/cy.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'cy', {
6 acccessKey: 'Allwedd Mynediad',
7 advanced: 'Uwch',
8 advisoryContentType: 'Math y Cynnwys Cynghorol',
9 advisoryTitle: 'Teitl Cynghorol',
10 anchor: {
11 toolbar: 'Angor',
12 menu: 'Golygu\'r Angor',
13 title: 'Priodweddau\'r Angor',
14 name: 'Enw\'r Angor',
15 errorName: 'Teipiwch enw\'r angor',
16 remove: 'Tynnwch yr Angor'
17 },
18 anchorId: 'Gan Id yr Elfen',
19 anchorName: 'Gan Enw\'r Angor',
20 charset: 'Set Nodau\'r Adnodd Cysylltiedig',
21 cssClasses: 'Dosbarthiadau Dalen Arddull',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Cyfeiriad E-Bost',
25 emailBody: 'Corff y Neges',
26 emailSubject: 'Testun y Neges',
27 id: 'Id',
28 info: 'Gwyb y Ddolen',
29 langCode: 'Cod Iaith',
30 langDir: 'Cyfeiriad Iaith',
31 langDirLTR: 'Chwith i\'r Dde (LTR)',
32 langDirRTL: 'Dde i\'r Chwith (RTL)',
33 menu: 'Golygu Dolen',
34 name: 'Enw',
35 noAnchors: '(Dim angorau ar gael yn y ddogfen)',
36 noEmail: 'Teipiwch gyfeiriad yr e-bost',
37 noUrl: 'Teipiwch URL y ddolen',
38 other: '<eraill>',
39 popupDependent: 'Dibynnol (Netscape)',
40 popupFeatures: 'Nodweddion Ffenestr Bop',
41 popupFullScreen: 'Sgrin Llawn (IE)',
42 popupLeft: 'Safle Chwith',
43 popupLocationBar: 'Bar Safle',
44 popupMenuBar: 'Dewislen',
45 popupResizable: 'Ailfeintiol',
46 popupScrollBars: 'Barrau Sgrolio',
47 popupStatusBar: 'Bar Statws',
48 popupToolbar: 'Bar Offer',
49 popupTop: 'Safle Top',
50 rel: 'Perthynas',
51 selectAnchor: 'Dewiswch Angor',
52 styles: 'Arddull',
53 tabIndex: 'Indecs Tab',
54 target: 'Targed',
55 targetFrame: '<ffrâm>',
56 targetFrameName: 'Enw Ffrâm y Targed',
57 targetPopup: '<ffenestr bop>',
58 targetPopupName: 'Enw Ffenestr Bop',
59 title: 'Dolen',
60 toAnchor: 'Dolen at angor yn y testun',
61 toEmail: 'E-bost',
62 toUrl: 'URL',
63 toolbar: 'Dolen',
64 type: 'Math y Ddolen',
65 unlink: 'Datgysylltu',
66 upload: 'Lanlwytho'
67} );
diff --git a/sources/plugins/link/lang/da.js b/sources/plugins/link/lang/da.js
new file mode 100644
index 0000000..47adf58
--- /dev/null
+++ b/sources/plugins/link/lang/da.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'da', {
6 acccessKey: 'Genvejstast',
7 advanced: 'Avanceret',
8 advisoryContentType: 'Indholdstype',
9 advisoryTitle: 'Titel',
10 anchor: {
11 toolbar: 'Indsæt/redigér bogmærke',
12 menu: 'Egenskaber for bogmærke',
13 title: 'Egenskaber for bogmærke',
14 name: 'Bogmærkenavn',
15 errorName: 'Indtast bogmærkenavn',
16 remove: 'Fjern bogmærke'
17 },
18 anchorId: 'Efter element-Id',
19 anchorName: 'Efter ankernavn',
20 charset: 'Tegnsæt',
21 cssClasses: 'Typografiark',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-mailadresse',
25 emailBody: 'Besked',
26 emailSubject: 'Emne',
27 id: 'Id',
28 info: 'Generelt',
29 langCode: 'Tekstretning',
30 langDir: 'Tekstretning',
31 langDirLTR: 'Fra venstre mod højre (LTR)',
32 langDirRTL: 'Fra højre mod venstre (RTL)',
33 menu: 'Redigér hyperlink',
34 name: 'Navn',
35 noAnchors: '(Ingen bogmærker i dokumentet)',
36 noEmail: 'Indtast e-mailadresse!',
37 noUrl: 'Indtast hyperlink-URL!',
38 other: '<anden>',
39 popupDependent: 'Koblet/dependent (Netscape)',
40 popupFeatures: 'Egenskaber for popup',
41 popupFullScreen: 'Fuld skærm (IE)',
42 popupLeft: 'Position fra venstre',
43 popupLocationBar: 'Adresselinje',
44 popupMenuBar: 'Menulinje',
45 popupResizable: 'Justérbar',
46 popupScrollBars: 'Scrollbar',
47 popupStatusBar: 'Statuslinje',
48 popupToolbar: 'Værktøjslinje',
49 popupTop: 'Position fra toppen',
50 rel: 'Relation',
51 selectAnchor: 'Vælg et anker',
52 styles: 'Typografi',
53 tabIndex: 'Tabulatorindeks',
54 target: 'Mål',
55 targetFrame: '<ramme>',
56 targetFrameName: 'Destinationsvinduets navn',
57 targetPopup: '<popup vindue>',
58 targetPopupName: 'Popupvinduets navn',
59 title: 'Egenskaber for hyperlink',
60 toAnchor: 'Bogmærke på denne side',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Indsæt/redigér hyperlink',
64 type: 'Type',
65 unlink: 'Fjern hyperlink',
66 upload: 'Upload'
67} );
diff --git a/sources/plugins/link/lang/de-ch.js b/sources/plugins/link/lang/de-ch.js
new file mode 100644
index 0000000..eba8c7e
--- /dev/null
+++ b/sources/plugins/link/lang/de-ch.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'de-ch', {
6 acccessKey: 'Zugriffstaste',
7 advanced: 'Erweitert',
8 advisoryContentType: 'Inhaltstyp',
9 advisoryTitle: 'Titel Beschreibung',
10 anchor: {
11 toolbar: 'Anker',
12 menu: 'Anker bearbeiten',
13 title: 'Ankereigenschaften',
14 name: 'Ankername',
15 errorName: 'Bitte geben Sie den Namen des Ankers ein',
16 remove: 'Anker entfernen'
17 },
18 anchorId: 'Nach Elementkennung',
19 anchorName: 'Nach Ankername',
20 charset: 'Verknüpfter Ressourcenzeichensatz',
21 cssClasses: 'Formatvorlagenklasse',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail-Adresse',
25 emailBody: 'Nachrichtentext',
26 emailSubject: 'Betreffzeile',
27 id: 'Kennung',
28 info: 'Linkinfo',
29 langCode: 'Sprachcode',
30 langDir: 'Schreibrichtung',
31 langDirLTR: 'Links nach Rechts (LTR)',
32 langDirRTL: 'Rechts nach Links (RTL)',
33 menu: 'Link bearbeiten',
34 name: 'Name',
35 noAnchors: '(Keine Anker im Dokument vorhanden)',
36 noEmail: 'Bitte geben Sie E-Mail-Adresse an',
37 noUrl: 'Bitte geben Sie die Link-URL an',
38 other: '<andere>',
39 popupDependent: 'Abhängig (Netscape)',
40 popupFeatures: 'Pop-up Fenstereigenschaften',
41 popupFullScreen: 'Vollbild (IE)',
42 popupLeft: 'Linke Position',
43 popupLocationBar: 'Adressleiste',
44 popupMenuBar: 'Menüleiste',
45 popupResizable: 'Grösse änderbar',
46 popupScrollBars: 'Rollbalken',
47 popupStatusBar: 'Statusleiste',
48 popupToolbar: 'Werkzeugleiste',
49 popupTop: 'Obere Position',
50 rel: 'Beziehung',
51 selectAnchor: 'Anker auswählen',
52 styles: 'Style',
53 tabIndex: 'Tab-Index',
54 target: 'Zielseite',
55 targetFrame: '<Frame>',
56 targetFrameName: 'Ziel-Fenster-Name',
57 targetPopup: '<Pop-up Fenster>',
58 targetPopupName: 'Pop-up Fenster-Name',
59 title: 'Link',
60 toAnchor: 'Anker in dieser Seite',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Link einfügen/editieren',
64 type: 'Link-Typ',
65 unlink: 'Link entfernen',
66 upload: 'Hochladen'
67} );
diff --git a/sources/plugins/link/lang/de.js b/sources/plugins/link/lang/de.js
new file mode 100644
index 0000000..e73093f
--- /dev/null
+++ b/sources/plugins/link/lang/de.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'de', {
6 acccessKey: 'Zugriffstaste',
7 advanced: 'Erweitert',
8 advisoryContentType: 'Inhaltstyp',
9 advisoryTitle: 'Titel Beschreibung',
10 anchor: {
11 toolbar: 'Anker',
12 menu: 'Anker bearbeiten',
13 title: 'Ankereigenschaften',
14 name: 'Ankername',
15 errorName: 'Bitte geben Sie den Namen des Ankers ein',
16 remove: 'Anker entfernen'
17 },
18 anchorId: 'Nach Elementkennung',
19 anchorName: 'Nach Ankername',
20 charset: 'Verknüpfter Ressourcenzeichensatz',
21 cssClasses: 'Formatvorlagenklasse',
22 download: 'Herunterladen erzwingen',
23 displayText: 'Anzeigetext',
24 emailAddress: 'E-Mail-Adresse',
25 emailBody: 'Nachrichtentext',
26 emailSubject: 'Betreffzeile',
27 id: 'Kennung',
28 info: 'Linkinfo',
29 langCode: 'Sprachcode',
30 langDir: 'Schreibrichtung',
31 langDirLTR: 'Links nach Rechts (LTR)',
32 langDirRTL: 'Rechts nach Links (RTL)',
33 menu: 'Link bearbeiten',
34 name: 'Name',
35 noAnchors: '(Keine Anker im Dokument vorhanden)',
36 noEmail: 'Bitte geben Sie E-Mail-Adresse an',
37 noUrl: 'Bitte geben Sie die Link-URL an',
38 other: '<andere>',
39 popupDependent: 'Abhängig (Netscape)',
40 popupFeatures: 'Pop-up Fenstereigenschaften',
41 popupFullScreen: 'Vollbild (IE)',
42 popupLeft: 'Linke Position',
43 popupLocationBar: 'Adressleiste',
44 popupMenuBar: 'Menüleiste',
45 popupResizable: 'Größe änderbar',
46 popupScrollBars: 'Rollbalken',
47 popupStatusBar: 'Statusleiste',
48 popupToolbar: 'Werkzeugleiste',
49 popupTop: 'Obere Position',
50 rel: 'Beziehung',
51 selectAnchor: 'Anker auswählen',
52 styles: 'Style',
53 tabIndex: 'Tab-Index',
54 target: 'Zielseite',
55 targetFrame: '<Frame>',
56 targetFrameName: 'Ziel-Fenster-Name',
57 targetPopup: '<Pop-up Fenster>',
58 targetPopupName: 'Pop-up Fenster-Name',
59 title: 'Link',
60 toAnchor: 'Anker in dieser Seite',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Link einfügen/editieren',
64 type: 'Link-Typ',
65 unlink: 'Link entfernen',
66 upload: 'Hochladen'
67} );
diff --git a/sources/plugins/link/lang/el.js b/sources/plugins/link/lang/el.js
new file mode 100644
index 0000000..bf0fbb9
--- /dev/null
+++ b/sources/plugins/link/lang/el.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'el', {
6 acccessKey: 'Συντόμευση',
7 advanced: 'Για Προχωρημένους',
8 advisoryContentType: 'Ενδεικτικός Τύπος Περιεχομένου',
9 advisoryTitle: 'Ενδεικτικός Τίτλος',
10 anchor: {
11 toolbar: 'Εισαγωγή/επεξεργασία Άγκυρας',
12 menu: 'Ιδιότητες άγκυρας',
13 title: 'Ιδιότητες άγκυρας',
14 name: 'Όνομα άγκυρας',
15 errorName: 'Παρακαλούμε εισάγετε όνομα άγκυρας',
16 remove: 'Αφαίρεση Άγκυρας'
17 },
18 anchorId: 'Βάσει του Element Id',
19 anchorName: 'Βάσει του Ονόματος Άγκυρας',
20 charset: 'Κωδικοποίηση Χαρακτήρων Προσαρτημένης Πηγής',
21 cssClasses: 'Κλάσεις Φύλλων Στυλ',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Διεύθυνση E-mail',
25 emailBody: 'Κείμενο Μηνύματος',
26 emailSubject: 'Θέμα Μηνύματος',
27 id: 'Id',
28 info: 'Πληροφορίες Συνδέσμου',
29 langCode: 'Κατεύθυνση Κειμένου',
30 langDir: 'Κατεύθυνση Κειμένου',
31 langDirLTR: 'Αριστερά προς Δεξιά (LTR)',
32 langDirRTL: 'Δεξιά προς Αριστερά (RTL)',
33 menu: 'Επεξεργασία Συνδέσμου',
34 name: 'Όνομα',
35 noAnchors: '(Δεν υπάρχουν άγκυρες στο κείμενο)',
36 noEmail: 'Εισάγετε τη διεύθυνση ηλεκτρονικού ταχυδρομείου',
37 noUrl: 'Εισάγετε την τοποθεσία (URL) του συνδέσμου',
38 other: '<άλλο>',
39 popupDependent: 'Εξαρτημένο (Netscape)',
40 popupFeatures: 'Επιλογές Αναδυόμενου Παραθύρου',
41 popupFullScreen: 'Πλήρης Οθόνη (IE)',
42 popupLeft: 'Θέση Αριστερά',
43 popupLocationBar: 'Γραμμή Τοποθεσίας',
44 popupMenuBar: 'Γραμμή Επιλογών',
45 popupResizable: 'Προσαρμοζόμενο Μέγεθος',
46 popupScrollBars: 'Μπάρες Κύλισης',
47 popupStatusBar: 'Γραμμή Κατάστασης',
48 popupToolbar: 'Εργαλειοθήκη',
49 popupTop: 'Θέση Πάνω',
50 rel: 'Σχέση',
51 selectAnchor: 'Επιλέξτε μια Άγκυρα',
52 styles: 'Μορφή',
53 tabIndex: 'Σειρά Μεταπήδησης',
54 target: 'Παράθυρο Προορισμού',
55 targetFrame: '<πλαίσιο>',
56 targetFrameName: 'Όνομα Πλαισίου Προορισμού',
57 targetPopup: '<αναδυόμενο παράθυρο>',
58 targetPopupName: 'Όνομα Αναδυόμενου Παραθύρου',
59 title: 'Σύνδεσμος',
60 toAnchor: 'Άγκυρα σε αυτήν τη σελίδα',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Σύνδεσμος',
64 type: 'Τύπος Συνδέσμου',
65 unlink: 'Αφαίρεση Συνδέσμου',
66 upload: 'Αποστολή'
67} );
diff --git a/sources/plugins/link/lang/en-au.js b/sources/plugins/link/lang/en-au.js
new file mode 100644
index 0000000..f67a6f7
--- /dev/null
+++ b/sources/plugins/link/lang/en-au.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'en-au', {
6 acccessKey: 'Access Key',
7 advanced: 'Advanced',
8 advisoryContentType: 'Advisory Content Type',
9 advisoryTitle: 'Advisory Title',
10 anchor: {
11 toolbar: 'Anchor',
12 menu: 'Edit Anchor',
13 title: 'Anchor Properties',
14 name: 'Anchor Name',
15 errorName: 'Please type the anchor name',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'By Element Id',
19 anchorName: 'By Anchor Name',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Stylesheet Classes',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail Address',
25 emailBody: 'Message Body',
26 emailSubject: 'Message Subject',
27 id: 'Id',
28 info: 'Link Info',
29 langCode: 'Language Code',
30 langDir: 'Language Direction',
31 langDirLTR: 'Left to Right (LTR)',
32 langDirRTL: 'Right to Left (RTL)',
33 menu: 'Edit Link',
34 name: 'Name',
35 noAnchors: '(No anchors available in the document)',
36 noEmail: 'Please type the e-mail address',
37 noUrl: 'Please type the link URL',
38 other: '<other>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: 'Popup Window Features',
41 popupFullScreen: 'Full Screen (IE)',
42 popupLeft: 'Left Position',
43 popupLocationBar: 'Location Bar',
44 popupMenuBar: 'Menu Bar',
45 popupResizable: 'Resizable',
46 popupScrollBars: 'Scroll Bars',
47 popupStatusBar: 'Status Bar',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Top Position',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Select an Anchor',
52 styles: 'Style',
53 tabIndex: 'Tab Index',
54 target: 'Target',
55 targetFrame: '<frame>',
56 targetFrameName: 'Target Frame Name',
57 targetPopup: '<popup window>',
58 targetPopupName: 'Popup Window Name',
59 title: 'Link',
60 toAnchor: 'Link to anchor in the text',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Link',
64 type: 'Link Type',
65 unlink: 'Unlink',
66 upload: 'Upload'
67} );
diff --git a/sources/plugins/link/lang/en-ca.js b/sources/plugins/link/lang/en-ca.js
new file mode 100644
index 0000000..636ee5c
--- /dev/null
+++ b/sources/plugins/link/lang/en-ca.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'en-ca', {
6 acccessKey: 'Access Key',
7 advanced: 'Advanced',
8 advisoryContentType: 'Advisory Content Type',
9 advisoryTitle: 'Advisory Title',
10 anchor: {
11 toolbar: 'Anchor',
12 menu: 'Edit Anchor',
13 title: 'Anchor Properties',
14 name: 'Anchor Name',
15 errorName: 'Please type the anchor name',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'By Element Id',
19 anchorName: 'By Anchor Name',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Stylesheet Classes',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail Address',
25 emailBody: 'Message Body',
26 emailSubject: 'Message Subject',
27 id: 'Id',
28 info: 'Link Info',
29 langCode: 'Language Code',
30 langDir: 'Language Direction',
31 langDirLTR: 'Left to Right (LTR)',
32 langDirRTL: 'Right to Left (RTL)',
33 menu: 'Edit Link',
34 name: 'Name',
35 noAnchors: '(No anchors available in the document)',
36 noEmail: 'Please type the e-mail address',
37 noUrl: 'Please type the link URL',
38 other: '<other>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: 'Popup Window Features',
41 popupFullScreen: 'Full Screen (IE)',
42 popupLeft: 'Left Position',
43 popupLocationBar: 'Location Bar',
44 popupMenuBar: 'Menu Bar',
45 popupResizable: 'Resizable',
46 popupScrollBars: 'Scroll Bars',
47 popupStatusBar: 'Status Bar',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Top Position',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Select an Anchor',
52 styles: 'Style',
53 tabIndex: 'Tab Index',
54 target: 'Target',
55 targetFrame: '<frame>',
56 targetFrameName: 'Target Frame Name',
57 targetPopup: '<popup window>',
58 targetPopupName: 'Popup Window Name',
59 title: 'Link',
60 toAnchor: 'Link to anchor in the text',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Link',
64 type: 'Link Type',
65 unlink: 'Unlink',
66 upload: 'Upload'
67} );
diff --git a/sources/plugins/link/lang/en-gb.js b/sources/plugins/link/lang/en-gb.js
new file mode 100644
index 0000000..f0f3506
--- /dev/null
+++ b/sources/plugins/link/lang/en-gb.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'en-gb', {
6 acccessKey: 'Access Key',
7 advanced: 'Advanced',
8 advisoryContentType: 'Advisory Content Type',
9 advisoryTitle: 'Advisory Title',
10 anchor: {
11 toolbar: 'Anchor',
12 menu: 'Edit Anchor',
13 title: 'Anchor Properties',
14 name: 'Anchor Name',
15 errorName: 'Please type the anchor name',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'By Element Id',
19 anchorName: 'By Anchor Name',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Stylesheet Classes',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail Address',
25 emailBody: 'Message Body',
26 emailSubject: 'Message Subject',
27 id: 'Id',
28 info: 'Link Info',
29 langCode: 'Language Code',
30 langDir: 'Language Direction',
31 langDirLTR: 'Left to Right (LTR)',
32 langDirRTL: 'Right to Left (RTL)',
33 menu: 'Edit Link',
34 name: 'Name',
35 noAnchors: '(No anchors available in the document)',
36 noEmail: 'Please type the e-mail address',
37 noUrl: 'Please type the link URL',
38 other: '<other>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: 'Popup Window Features',
41 popupFullScreen: 'Full Screen (IE)',
42 popupLeft: 'Left Position',
43 popupLocationBar: 'Location Bar',
44 popupMenuBar: 'Menu Bar',
45 popupResizable: 'Resizable',
46 popupScrollBars: 'Scroll Bars',
47 popupStatusBar: 'Status Bar',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Top Position',
50 rel: 'Relationship',
51 selectAnchor: 'Select an Anchor',
52 styles: 'Style',
53 tabIndex: 'Tab Index',
54 target: 'Target',
55 targetFrame: '<frame>',
56 targetFrameName: 'Target Frame Name',
57 targetPopup: '<popup window>',
58 targetPopupName: 'Popup Window Name',
59 title: 'Link',
60 toAnchor: 'Link to anchor in the text',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Link',
64 type: 'Link Type',
65 unlink: 'Unlink',
66 upload: 'Upload'
67} );
diff --git a/sources/plugins/link/lang/en.js b/sources/plugins/link/lang/en.js
new file mode 100644
index 0000000..8f613de
--- /dev/null
+++ b/sources/plugins/link/lang/en.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'en', {
6 acccessKey: 'Access Key',
7 advanced: 'Advanced',
8 advisoryContentType: 'Advisory Content Type',
9 advisoryTitle: 'Advisory Title',
10 anchor: {
11 toolbar: 'Anchor',
12 menu: 'Edit Anchor',
13 title: 'Anchor Properties',
14 name: 'Anchor Name',
15 errorName: 'Please type the anchor name',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'By Element Id',
19 anchorName: 'By Anchor Name',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Stylesheet Classes',
22 download: 'Force Download',
23 displayText: 'Display Text',
24 emailAddress: 'E-Mail Address',
25 emailBody: 'Message Body',
26 emailSubject: 'Message Subject',
27 id: 'Id',
28 info: 'Link Info',
29 langCode: 'Language Code',
30 langDir: 'Language Direction',
31 langDirLTR: 'Left to Right (LTR)',
32 langDirRTL: 'Right to Left (RTL)',
33 menu: 'Edit Link',
34 name: 'Name',
35 noAnchors: '(No anchors available in the document)',
36 noEmail: 'Please type the e-mail address',
37 noUrl: 'Please type the link URL',
38 other: '<other>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: 'Popup Window Features',
41 popupFullScreen: 'Full Screen (IE)',
42 popupLeft: 'Left Position',
43 popupLocationBar: 'Location Bar',
44 popupMenuBar: 'Menu Bar',
45 popupResizable: 'Resizable',
46 popupScrollBars: 'Scroll Bars',
47 popupStatusBar: 'Status Bar',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Top Position',
50 rel: 'Relationship',
51 selectAnchor: 'Select an Anchor',
52 styles: 'Style',
53 tabIndex: 'Tab Index',
54 target: 'Target',
55 targetFrame: '<frame>',
56 targetFrameName: 'Target Frame Name',
57 targetPopup: '<popup window>',
58 targetPopupName: 'Popup Window Name',
59 title: 'Link',
60 toAnchor: 'Link to anchor in the text',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Link',
64 type: 'Link Type',
65 unlink: 'Unlink',
66 upload: 'Upload'
67} );
diff --git a/sources/plugins/link/lang/eo.js b/sources/plugins/link/lang/eo.js
new file mode 100644
index 0000000..7991231
--- /dev/null
+++ b/sources/plugins/link/lang/eo.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'eo', {
6 acccessKey: 'Fulmoklavo',
7 advanced: 'Speciala',
8 advisoryContentType: 'Enhavotipo',
9 advisoryTitle: 'Priskriba Titolo',
10 anchor: {
11 toolbar: 'Ankro',
12 menu: 'Enmeti/Ŝanĝi Ankron',
13 title: 'Ankraj Atributoj',
14 name: 'Ankra Nomo',
15 errorName: 'Bv entajpi la ankran nomon',
16 remove: 'Forigi Ankron'
17 },
18 anchorId: 'Per Elementidentigilo',
19 anchorName: 'Per Ankronomo',
20 charset: 'Signaro de la Ligita Rimedo',
21 cssClasses: 'Klasoj de Stilfolioj',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Retpoŝto',
25 emailBody: 'Mesaĝa korpo',
26 emailSubject: 'Mesaĝa Temo',
27 id: 'Id',
28 info: 'Informoj pri la Ligilo',
29 langCode: 'Lingva Kodo',
30 langDir: 'Skribdirekto',
31 langDirLTR: 'De maldekstro dekstren (LTR)',
32 langDirRTL: 'De dekstro maldekstren (RTL)',
33 menu: 'Ŝanĝi Ligilon',
34 name: 'Nomo',
35 noAnchors: '<Ne disponeblas ankroj en la dokumento>',
36 noEmail: 'Bonvolu entajpi la retpoŝtadreson',
37 noUrl: 'Bonvolu entajpi la URL-on',
38 other: '<alia>',
39 popupDependent: 'Dependa (Netscape)',
40 popupFeatures: 'Atributoj de la Ŝprucfenestro',
41 popupFullScreen: 'Tutekrane (IE)',
42 popupLeft: 'Maldekstra Pozicio',
43 popupLocationBar: 'Adresobreto',
44 popupMenuBar: 'Menubreto',
45 popupResizable: 'Dimensiŝanĝebla',
46 popupScrollBars: 'Rulumskaloj',
47 popupStatusBar: 'Statobreto',
48 popupToolbar: 'Ilobreto',
49 popupTop: 'Supra Pozicio',
50 rel: 'Rilato',
51 selectAnchor: 'Elekti Ankron',
52 styles: 'Stilo',
53 tabIndex: 'Taba Indekso',
54 target: 'Celo',
55 targetFrame: '<kadro>',
56 targetFrameName: 'Nomo de CelKadro',
57 targetPopup: '<ŝprucfenestro>',
58 targetPopupName: 'Nomo de Ŝprucfenestro',
59 title: 'Ligilo',
60 toAnchor: 'Ankri en tiu ĉi paĝo',
61 toEmail: 'Retpoŝto',
62 toUrl: 'URL',
63 toolbar: 'Enmeti/Ŝanĝi Ligilon',
64 type: 'Tipo de Ligilo',
65 unlink: 'Forigi Ligilon',
66 upload: 'Alŝuti'
67} );
diff --git a/sources/plugins/link/lang/es.js b/sources/plugins/link/lang/es.js
new file mode 100644
index 0000000..700ad86
--- /dev/null
+++ b/sources/plugins/link/lang/es.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'es', {
6 acccessKey: 'Tecla de Acceso',
7 advanced: 'Avanzado',
8 advisoryContentType: 'Tipo de Contenido',
9 advisoryTitle: 'Título',
10 anchor: {
11 toolbar: 'Referencia',
12 menu: 'Propiedades de Referencia',
13 title: 'Propiedades de Referencia',
14 name: 'Nombre de la Referencia',
15 errorName: 'Por favor, complete el nombre de la Referencia',
16 remove: 'Quitar Referencia'
17 },
18 anchorId: 'Por ID de elemento',
19 anchorName: 'Por Nombre de Referencia',
20 charset: 'Fuente de caracteres vinculado',
21 cssClasses: 'Clases de hojas de estilo',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Dirección de E-Mail',
25 emailBody: 'Cuerpo del Mensaje',
26 emailSubject: 'Título del Mensaje',
27 id: 'Id',
28 info: 'Información de Vínculo',
29 langCode: 'Código idioma',
30 langDir: 'Orientación',
31 langDirLTR: 'Izquierda a Derecha (LTR)',
32 langDirRTL: 'Derecha a Izquierda (RTL)',
33 menu: 'Editar Vínculo',
34 name: 'Nombre',
35 noAnchors: '(No hay referencias disponibles en el documento)',
36 noEmail: 'Por favor escriba la dirección de e-mail',
37 noUrl: 'Por favor escriba el vínculo URL',
38 other: '<otro>',
39 popupDependent: 'Dependiente (Netscape)',
40 popupFeatures: 'Características de Ventana Emergente',
41 popupFullScreen: 'Pantalla Completa (IE)',
42 popupLeft: 'Posición Izquierda',
43 popupLocationBar: 'Barra de ubicación',
44 popupMenuBar: 'Barra de Menú',
45 popupResizable: 'Redimensionable',
46 popupScrollBars: 'Barras de desplazamiento',
47 popupStatusBar: 'Barra de Estado',
48 popupToolbar: 'Barra de Herramientas',
49 popupTop: 'Posición Derecha',
50 rel: 'Relación',
51 selectAnchor: 'Seleccionar una referencia',
52 styles: 'Estilo',
53 tabIndex: 'Indice de tabulación',
54 target: 'Destino',
55 targetFrame: '<marco>',
56 targetFrameName: 'Nombre del Marco Destino',
57 targetPopup: '<ventana emergente>',
58 targetPopupName: 'Nombre de Ventana Emergente',
59 title: 'Vínculo',
60 toAnchor: 'Referencia en esta página',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Insertar/Editar Vínculo',
64 type: 'Tipo de vínculo',
65 unlink: 'Eliminar Vínculo',
66 upload: 'Cargar'
67} );
diff --git a/sources/plugins/link/lang/et.js b/sources/plugins/link/lang/et.js
new file mode 100644
index 0000000..7e31aa6
--- /dev/null
+++ b/sources/plugins/link/lang/et.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'et', {
6 acccessKey: 'Juurdepääsu võti',
7 advanced: 'Täpsemalt',
8 advisoryContentType: 'Juhendava sisu tüüp',
9 advisoryTitle: 'Juhendav tiitel',
10 anchor: {
11 toolbar: 'Ankru sisestamine/muutmine',
12 menu: 'Ankru omadused',
13 title: 'Ankru omadused',
14 name: 'Ankru nimi',
15 errorName: 'Palun sisesta ankru nimi',
16 remove: 'Eemalda ankur'
17 },
18 anchorId: 'Elemendi id järgi',
19 anchorName: 'Ankru nime järgi',
20 charset: 'Lingitud ressursi märgistik',
21 cssClasses: 'Stiilistiku klassid',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-posti aadress',
25 emailBody: 'Sõnumi tekst',
26 emailSubject: 'Sõnumi teema',
27 id: 'ID',
28 info: 'Lingi info',
29 langCode: 'Keele suund',
30 langDir: 'Keele suund',
31 langDirLTR: 'Vasakult paremale (LTR)',
32 langDirRTL: 'Paremalt vasakule (RTL)',
33 menu: 'Muuda linki',
34 name: 'Nimi',
35 noAnchors: '(Selles dokumendis pole ankruid)',
36 noEmail: 'Palun kirjuta e-posti aadress',
37 noUrl: 'Palun kirjuta lingi URL',
38 other: '<muu>',
39 popupDependent: 'Sõltuv (Netscape)',
40 popupFeatures: 'Hüpikakna omadused',
41 popupFullScreen: 'Täisekraan (IE)',
42 popupLeft: 'Vasak asukoht',
43 popupLocationBar: 'Aadressiriba',
44 popupMenuBar: 'Menüüriba',
45 popupResizable: 'Suurust saab muuta',
46 popupScrollBars: 'Kerimisribad',
47 popupStatusBar: 'Olekuriba',
48 popupToolbar: 'Tööriistariba',
49 popupTop: 'Ülemine asukoht',
50 rel: 'Suhe',
51 selectAnchor: 'Vali ankur',
52 styles: 'Laad',
53 tabIndex: 'Tab indeks',
54 target: 'Sihtkoht',
55 targetFrame: '<raam>',
56 targetFrameName: 'Sihtmärk raami nimi',
57 targetPopup: '<hüpikaken>',
58 targetPopupName: 'Hüpikakna nimi',
59 title: 'Link',
60 toAnchor: 'Ankur sellel lehel',
61 toEmail: 'E-post',
62 toUrl: 'URL',
63 toolbar: 'Lingi lisamine/muutmine',
64 type: 'Lingi liik',
65 unlink: 'Lingi eemaldamine',
66 upload: 'Lae üles'
67} );
diff --git a/sources/plugins/link/lang/eu.js b/sources/plugins/link/lang/eu.js
new file mode 100644
index 0000000..7a2727e
--- /dev/null
+++ b/sources/plugins/link/lang/eu.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'eu', {
6 acccessKey: 'Sarbide-tekla',
7 advanced: 'Aurreratua',
8 advisoryContentType: 'Aholkatutako eduki-mota',
9 advisoryTitle: 'Aholkatutako izenburua',
10 anchor: {
11 toolbar: 'Aingura',
12 menu: 'Editatu aingura',
13 title: 'Ainguraren propietateak',
14 name: 'Ainguraren izena',
15 errorName: 'Idatzi ainguraren izena',
16 remove: 'Kendu aingura'
17 },
18 anchorId: 'Elementuaren Id-aren arabera',
19 anchorName: 'Aingura-izenaren arabera',
20 charset: 'Estekatutako baliabide karaktere-jokoa',
21 cssClasses: 'Estilo-orriko klaseak',
22 download: 'Force Download', // MISSING
23 displayText: 'Bistaratu testua',
24 emailAddress: 'E-posta helbidea',
25 emailBody: 'Mezuaren gorputza',
26 emailSubject: 'Mezuaren gaia',
27 id: 'Id',
28 info: 'Estekaren informazioa',
29 langCode: 'Hizkuntzaren kodea',
30 langDir: 'Hizkuntzaren norabidea',
31 langDirLTR: 'Ezkerretik eskuinera (LTR)',
32 langDirRTL: 'Eskuinetik ezkerrera (RTL)',
33 menu: 'Editatu esteka',
34 name: 'Izena',
35 noAnchors: '(Ez dago aingurarik erabilgarri dokumentuan)',
36 noEmail: 'Mesedez idatzi e-posta helbidea',
37 noUrl: 'Mesedez idatzi estekaren URLa',
38 other: '<bestelakoa>',
39 popupDependent: 'Menpekoa (Netscape)',
40 popupFeatures: 'Laster-leihoaren ezaugarriak',
41 popupFullScreen: 'Pantaila osoa (IE)',
42 popupLeft: 'Ezkerreko posizioa',
43 popupLocationBar: 'Kokaleku-barra',
44 popupMenuBar: 'Menu-barra',
45 popupResizable: 'Tamaina aldakorra',
46 popupScrollBars: 'Korritze-barrak',
47 popupStatusBar: 'Egoera-barra',
48 popupToolbar: 'Tresna-barra',
49 popupTop: 'Goiko posizioa',
50 rel: 'Erlazioa',
51 selectAnchor: 'Hautatu aingura',
52 styles: 'Estiloa',
53 tabIndex: 'Tabulazio indizea',
54 target: 'Helburua',
55 targetFrame: '<frame>',
56 targetFrameName: 'Helburuko markoaren izena',
57 targetPopup: '<laster-leihoa>',
58 targetPopupName: 'Laster-leihoaren izena',
59 title: 'Esteka',
60 toAnchor: 'Estekatu testuko aingurara',
61 toEmail: 'E-posta',
62 toUrl: 'URLa',
63 toolbar: 'Esteka',
64 type: 'Esteka-mota',
65 unlink: 'Kendu esteka',
66 upload: 'Kargatu'
67} );
diff --git a/sources/plugins/link/lang/fa.js b/sources/plugins/link/lang/fa.js
new file mode 100644
index 0000000..525d899
--- /dev/null
+++ b/sources/plugins/link/lang/fa.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'fa', {
6 acccessKey: 'کلید دستیابی',
7 advanced: 'پیشرفته',
8 advisoryContentType: 'نوع محتوای کمکی',
9 advisoryTitle: 'عنوان کمکی',
10 anchor: {
11 toolbar: 'گنجاندن/ویرایش لنگر',
12 menu: 'ویژگی​های لنگر',
13 title: 'ویژگی​های لنگر',
14 name: 'نام لنگر',
15 errorName: 'لطفا نام لنگر را بنویسید',
16 remove: 'حذف لنگر'
17 },
18 anchorId: 'با شناسهٴ المان',
19 anchorName: 'با نام لنگر',
20 charset: 'نویسه​گان منبع پیوند شده',
21 cssClasses: 'کلاس​های شیوه​نامه(Stylesheet)',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'نشانی پست الکترونیکی',
25 emailBody: 'متن پیام',
26 emailSubject: 'موضوع پیام',
27 id: 'شناسه',
28 info: 'اطلاعات پیوند',
29 langCode: 'جهت​نمای زبان',
30 langDir: 'جهت​نمای زبان',
31 langDirLTR: 'چپ به راست (LTR)',
32 langDirRTL: 'راست به چپ (RTL)',
33 menu: 'ویرایش پیوند',
34 name: 'نام',
35 noAnchors: '(در این سند لنگری دردسترس نیست)',
36 noEmail: 'لطفا نشانی پست الکترونیکی را بنویسید',
37 noUrl: 'لطفا URL پیوند را بنویسید',
38 other: '<سایر>',
39 popupDependent: 'وابسته (Netscape)',
40 popupFeatures: 'ویژگی​های پنجرهٴ پاپاپ',
41 popupFullScreen: 'تمام صفحه (IE)',
42 popupLeft: 'موقعیت چپ',
43 popupLocationBar: 'نوار موقعیت',
44 popupMenuBar: 'نوار منو',
45 popupResizable: 'قابل تغییر اندازه',
46 popupScrollBars: 'میله​های پیمایش',
47 popupStatusBar: 'نوار وضعیت',
48 popupToolbar: 'نوار ابزار',
49 popupTop: 'موقعیت بالا',
50 rel: 'وابستگی',
51 selectAnchor: 'یک لنگر برگزینید',
52 styles: 'شیوه (style)',
53 tabIndex: 'نمایهٴ دسترسی با برگه',
54 target: 'مقصد',
55 targetFrame: '<فریم>',
56 targetFrameName: 'نام فریم مقصد',
57 targetPopup: '<پنجرهٴ پاپاپ>',
58 targetPopupName: 'نام پنجرهٴ پاپاپ',
59 title: 'پیوند',
60 toAnchor: 'لنگر در همین صفحه',
61 toEmail: 'پست الکترونیکی',
62 toUrl: 'URL',
63 toolbar: 'گنجاندن/ویرایش پیوند',
64 type: 'نوع پیوند',
65 unlink: 'برداشتن پیوند',
66 upload: 'انتقال به سرور'
67} );
diff --git a/sources/plugins/link/lang/fi.js b/sources/plugins/link/lang/fi.js
new file mode 100644
index 0000000..9ab5224
--- /dev/null
+++ b/sources/plugins/link/lang/fi.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'fi', {
6 acccessKey: 'Pikanäppäin',
7 advanced: 'Lisäominaisuudet',
8 advisoryContentType: 'Avustava sisällön tyyppi',
9 advisoryTitle: 'Avustava otsikko',
10 anchor: {
11 toolbar: 'Lisää ankkuri/muokkaa ankkuria',
12 menu: 'Ankkurin ominaisuudet',
13 title: 'Ankkurin ominaisuudet',
14 name: 'Nimi',
15 errorName: 'Ankkurille on kirjoitettava nimi',
16 remove: 'Poista ankkuri'
17 },
18 anchorId: 'Ankkurin ID:n mukaan',
19 anchorName: 'Ankkurin nimen mukaan',
20 charset: 'Linkitetty kirjaimisto',
21 cssClasses: 'Tyyliluokat',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Sähköpostiosoite',
25 emailBody: 'Viesti',
26 emailSubject: 'Aihe',
27 id: 'Tunniste',
28 info: 'Linkin tiedot',
29 langCode: 'Kielen suunta',
30 langDir: 'Kielen suunta',
31 langDirLTR: 'Vasemmalta oikealle (LTR)',
32 langDirRTL: 'Oikealta vasemmalle (RTL)',
33 menu: 'Muokkaa linkkiä',
34 name: 'Nimi',
35 noAnchors: '(Ei ankkureita tässä dokumentissa)',
36 noEmail: 'Kirjoita sähköpostiosoite',
37 noUrl: 'Linkille on kirjoitettava URL',
38 other: '<muu>',
39 popupDependent: 'Riippuva (Netscape)',
40 popupFeatures: 'Popup ikkunan ominaisuudet',
41 popupFullScreen: 'Täysi ikkuna (IE)',
42 popupLeft: 'Vasemmalta (px)',
43 popupLocationBar: 'Osoiterivi',
44 popupMenuBar: 'Valikkorivi',
45 popupResizable: 'Venytettävä',
46 popupScrollBars: 'Vierityspalkit',
47 popupStatusBar: 'Tilarivi',
48 popupToolbar: 'Vakiopainikkeet',
49 popupTop: 'Ylhäältä (px)',
50 rel: 'Suhde',
51 selectAnchor: 'Valitse ankkuri',
52 styles: 'Tyyli',
53 tabIndex: 'Tabulaattori indeksi',
54 target: 'Kohde',
55 targetFrame: '<kehys>',
56 targetFrameName: 'Kohdekehyksen nimi',
57 targetPopup: '<popup ikkuna>',
58 targetPopupName: 'Popup ikkunan nimi',
59 title: 'Linkki',
60 toAnchor: 'Ankkuri tässä sivussa',
61 toEmail: 'Sähköposti',
62 toUrl: 'Osoite',
63 toolbar: 'Lisää linkki/muokkaa linkkiä',
64 type: 'Linkkityyppi',
65 unlink: 'Poista linkki',
66 upload: 'Lisää tiedosto'
67} );
diff --git a/sources/plugins/link/lang/fo.js b/sources/plugins/link/lang/fo.js
new file mode 100644
index 0000000..90ab1ed
--- /dev/null
+++ b/sources/plugins/link/lang/fo.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'fo', {
6 acccessKey: 'Snarvegisknöttur',
7 advanced: 'Fjølbroytt',
8 advisoryContentType: 'Vegleiðandi innihaldsslag',
9 advisoryTitle: 'Vegleiðandi heiti',
10 anchor: {
11 toolbar: 'Ger/broyt marknastein',
12 menu: 'Eginleikar fyri marknastein',
13 title: 'Eginleikar fyri marknastein',
14 name: 'Heiti marknasteinsins',
15 errorName: 'Vinarliga rita marknasteinsins heiti',
16 remove: 'Strika marknastein'
17 },
18 anchorId: 'Eftir element Id',
19 anchorName: 'Eftir navni á marknasteini',
20 charset: 'Atknýtt teknsett',
21 cssClasses: 'Typografi klassar',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Teldupost-adressa',
25 emailBody: 'Breyðtekstur',
26 emailSubject: 'Evni',
27 id: 'Id',
28 info: 'Tilknýtis upplýsingar',
29 langCode: 'Tekstkós',
30 langDir: 'Tekstkós',
31 langDirLTR: 'Frá vinstru til høgru (LTR)',
32 langDirRTL: 'Frá høgru til vinstru (RTL)',
33 menu: 'Broyt tilknýti',
34 name: 'Navn',
35 noAnchors: '(Eingir marknasteinar eru í hesum dokumentið)',
36 noEmail: 'Vinarliga skriva teldupost-adressu',
37 noUrl: 'Vinarliga skriva tilknýti (URL)',
38 other: '<annað>',
39 popupDependent: 'Bundið (Netscape)',
40 popupFeatures: 'Popup vindeygans víðkaðu eginleikar',
41 popupFullScreen: 'Fullur skermur (IE)',
42 popupLeft: 'Frástøða frá vinstru',
43 popupLocationBar: 'Adressulinja',
44 popupMenuBar: 'Skrábjálki',
45 popupResizable: 'Stødd kann broytast',
46 popupScrollBars: 'Rullibjálki',
47 popupStatusBar: 'Støðufrágreiðingarbjálki',
48 popupToolbar: 'Amboðsbjálki',
49 popupTop: 'Frástøða frá íerva',
50 rel: 'Relatión',
51 selectAnchor: 'Vel ein marknastein',
52 styles: 'Typografi',
53 tabIndex: 'Tabulator indeks',
54 target: 'Target',
55 targetFrame: '<ramma>',
56 targetFrameName: 'Vís navn vindeygans',
57 targetPopup: '<popup vindeyga>',
58 targetPopupName: 'Popup vindeygans navn',
59 title: 'Tilknýti',
60 toAnchor: 'Tilknýti til marknastein í tekstinum',
61 toEmail: 'Teldupostur',
62 toUrl: 'URL',
63 toolbar: 'Ger/broyt tilknýti',
64 type: 'Tilknýtisslag',
65 unlink: 'Strika tilknýti',
66 upload: 'Send til ambætaran'
67} );
diff --git a/sources/plugins/link/lang/fr-ca.js b/sources/plugins/link/lang/fr-ca.js
new file mode 100644
index 0000000..ddf2dde
--- /dev/null
+++ b/sources/plugins/link/lang/fr-ca.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'fr-ca', {
6 acccessKey: 'Touche d\'accessibilité',
7 advanced: 'Avancé',
8 advisoryContentType: 'Type de contenu',
9 advisoryTitle: 'Description',
10 anchor: {
11 toolbar: 'Ancre',
12 menu: 'Modifier l\'ancre',
13 title: 'Propriétés de l\'ancre',
14 name: 'Nom de l\'ancre',
15 errorName: 'Veuillez saisir le nom de l\'ancre',
16 remove: 'Supprimer l\'ancre'
17 },
18 anchorId: 'Par ID',
19 anchorName: 'Par nom',
20 charset: 'Encodage de la cible',
21 cssClasses: 'Classes CSS',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Courriel',
25 emailBody: 'Corps du message',
26 emailSubject: 'Objet du message',
27 id: 'ID',
28 info: 'Informations sur le lien',
29 langCode: 'Code de langue',
30 langDir: 'Sens d\'écriture',
31 langDirLTR: 'De gauche à droite (LTR)',
32 langDirRTL: 'De droite à gauche (RTL)',
33 menu: 'Modifier le lien',
34 name: 'Nom',
35 noAnchors: '(Pas d\'ancre disponible dans le document)',
36 noEmail: 'Veuillez saisir le courriel',
37 noUrl: 'Veuillez saisir l\'URL',
38 other: '<autre>',
39 popupDependent: 'Dépendante (Netscape)',
40 popupFeatures: 'Caractéristiques de la fenêtre popup',
41 popupFullScreen: 'Plein écran (IE)',
42 popupLeft: 'Position de la gauche',
43 popupLocationBar: 'Barre d\'adresse',
44 popupMenuBar: 'Barre de menu',
45 popupResizable: 'Redimensionnable',
46 popupScrollBars: 'Barres de défilement',
47 popupStatusBar: 'Barre d\'état',
48 popupToolbar: 'Barre d\'outils',
49 popupTop: 'Position à partir du haut',
50 rel: 'Relation',
51 selectAnchor: 'Sélectionner une ancre',
52 styles: 'Style',
53 tabIndex: 'Ordre de tabulation',
54 target: 'Destination',
55 targetFrame: '<Cadre>',
56 targetFrameName: 'Nom du cadre de destination',
57 targetPopup: '<fenêtre popup>',
58 targetPopupName: 'Nom de la fenêtre popup',
59 title: 'Lien',
60 toAnchor: 'Ancre dans cette page',
61 toEmail: 'Courriel',
62 toUrl: 'URL',
63 toolbar: 'Lien',
64 type: 'Type de lien',
65 unlink: 'Supprimer le lien',
66 upload: 'Téléverser'
67} );
diff --git a/sources/plugins/link/lang/fr.js b/sources/plugins/link/lang/fr.js
new file mode 100644
index 0000000..a4561cb
--- /dev/null
+++ b/sources/plugins/link/lang/fr.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'fr', {
6 acccessKey: 'Touche d\'accessibilité',
7 advanced: 'Avancé',
8 advisoryContentType: 'Type de contenu (indicatif)',
9 advisoryTitle: 'Infobulle',
10 anchor: {
11 toolbar: 'Ancre',
12 menu: 'Modifier l\'ancre',
13 title: 'Propriétés de l\'ancre',
14 name: 'Nom de l\'ancre',
15 errorName: 'Veuillez entrer le nom de l\'ancre.',
16 remove: 'Supprimer l\'ancre'
17 },
18 anchorId: 'Par ID d\'élément',
19 anchorName: 'Par nom d\'ancre',
20 charset: 'Encodage de la ressource liée',
21 cssClasses: 'Classes de style',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Adresse électronique',
25 emailBody: 'Corps du message',
26 emailSubject: 'Sujet du message',
27 id: 'ID',
28 info: 'Informations sur le lien',
29 langCode: 'Code de langue',
30 langDir: 'Sens d\'écriture',
31 langDirLTR: 'Gauche à droite',
32 langDirRTL: 'Droite à gauche (RTL)',
33 menu: 'Modifier le lien',
34 name: 'Nom',
35 noAnchors: '(Aucune ancre disponible dans ce document)',
36 noEmail: 'Veuillez entrer l\'adresse électronique',
37 noUrl: 'Veuillez entrer l\'URL du lien',
38 other: '<autre>',
39 popupDependent: 'Dépendante (Netscape)',
40 popupFeatures: 'Caractéristiques de la fenêtre surgissante',
41 popupFullScreen: 'Plein écran (IE)',
42 popupLeft: 'À gauche',
43 popupLocationBar: 'Barre d\'adresse',
44 popupMenuBar: 'Barre de menu',
45 popupResizable: 'Redimensionnable',
46 popupScrollBars: 'Barres de défilement',
47 popupStatusBar: 'Barre d\'état',
48 popupToolbar: 'Barre d\'outils',
49 popupTop: 'En haut',
50 rel: 'Relation',
51 selectAnchor: 'Sélectionner une ancre',
52 styles: 'Style',
53 tabIndex: 'Indice de tabulation',
54 target: 'Cible',
55 targetFrame: '<cadre>',
56 targetFrameName: 'Nom du cadre affecté',
57 targetPopup: '<fenêtre surgissante>',
58 targetPopupName: 'Nom de la fenêtre surgissante',
59 title: 'Lien',
60 toAnchor: 'Ancre',
61 toEmail: 'Courriel',
62 toUrl: 'URL',
63 toolbar: 'Lien',
64 type: 'Type de lien',
65 unlink: 'Supprimer le lien',
66 upload: 'Téléverser'
67} );
diff --git a/sources/plugins/link/lang/gl.js b/sources/plugins/link/lang/gl.js
new file mode 100644
index 0000000..45ced42
--- /dev/null
+++ b/sources/plugins/link/lang/gl.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'gl', {
6 acccessKey: 'Chave de acceso',
7 advanced: 'Avanzado',
8 advisoryContentType: 'Tipo de contido informativo',
9 advisoryTitle: 'Título',
10 anchor: {
11 toolbar: 'Ancoraxe',
12 menu: 'Editar a ancoraxe',
13 title: 'Propiedades da ancoraxe',
14 name: 'Nome da ancoraxe',
15 errorName: 'Escriba o nome da ancoraxe',
16 remove: 'Retirar a ancoraxe'
17 },
18 anchorId: 'Polo ID do elemento',
19 anchorName: 'Polo nome da ancoraxe',
20 charset: 'Codificación do recurso ligado',
21 cssClasses: 'Clases da folla de estilos',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Enderezo de correo',
25 emailBody: 'Corpo da mensaxe',
26 emailSubject: 'Asunto da mensaxe',
27 id: 'ID',
28 info: 'Información da ligazón',
29 langCode: 'Código do idioma',
30 langDir: 'Dirección de escritura do idioma',
31 langDirLTR: 'Esquerda a dereita (LTR)',
32 langDirRTL: 'Dereita a esquerda (RTL)',
33 menu: 'Editar a ligazón',
34 name: 'Nome',
35 noAnchors: '(Non hai ancoraxes dispoñíbeis no documento)',
36 noEmail: 'Escriba o enderezo de correo',
37 noUrl: 'Escriba a ligazón URL',
38 other: '<outro>',
39 popupDependent: 'Dependente (Netscape)',
40 popupFeatures: 'Características da xanela emerxente',
41 popupFullScreen: 'Pantalla completa (IE)',
42 popupLeft: 'Posición esquerda',
43 popupLocationBar: 'Barra de localización',
44 popupMenuBar: 'Barra do menú',
45 popupResizable: 'Redimensionábel',
46 popupScrollBars: 'Barras de desprazamento',
47 popupStatusBar: 'Barra de estado',
48 popupToolbar: 'Barra de ferramentas',
49 popupTop: 'Posición superior',
50 rel: 'Relación',
51 selectAnchor: 'Seleccionar unha ancoraxe',
52 styles: 'Estilo',
53 tabIndex: 'Índice de tabulación',
54 target: 'Destino',
55 targetFrame: '<marco>',
56 targetFrameName: 'Nome do marco de destino',
57 targetPopup: '<xanela emerxente>',
58 targetPopupName: 'Nome da xanela emerxente',
59 title: 'Ligazón',
60 toAnchor: 'Ligar coa ancoraxe no testo',
61 toEmail: 'Correo',
62 toUrl: 'URL',
63 toolbar: 'Ligazón',
64 type: 'Tipo de ligazón',
65 unlink: 'Eliminar a ligazón',
66 upload: 'Enviar'
67} );
diff --git a/sources/plugins/link/lang/gu.js b/sources/plugins/link/lang/gu.js
new file mode 100644
index 0000000..2bbf577
--- /dev/null
+++ b/sources/plugins/link/lang/gu.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'gu', {
6 acccessKey: 'ઍક્સેસ કી',
7 advanced: 'અડ્વાન્સડ',
8 advisoryContentType: 'મુખ્ય કન્ટેન્ટ પ્રકાર',
9 advisoryTitle: 'મુખ્ય મથાળું',
10 anchor: {
11 toolbar: 'ઍંકર ઇન્સર્ટ/દાખલ કરવી',
12 menu: 'ઍંકરના ગુણ',
13 title: 'ઍંકરના ગુણ',
14 name: 'ઍંકરનું નામ',
15 errorName: 'ઍંકરનું નામ ટાઈપ કરો',
16 remove: 'સ્થિર નકરવું'
17 },
18 anchorId: 'ઍંકર એલિમન્ટ Id થી પસંદ કરો',
19 anchorName: 'ઍંકર નામથી પસંદ કરો',
20 charset: 'લિંક રિસૉર્સ કૅરિક્ટર સેટ',
21 cssClasses: 'સ્ટાઇલ-શીટ ક્લાસ',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'ઈ-મેલ સરનામું',
25 emailBody: 'સંદેશ',
26 emailSubject: 'ઈ-મેલ વિષય',
27 id: 'Id',
28 info: 'લિંક ઇન્ફૉ ટૅબ',
29 langCode: 'ભાષા લેખવાની પદ્ધતિ',
30 langDir: 'ભાષા લેખવાની પદ્ધતિ',
31 langDirLTR: 'ડાબે થી જમણે (LTR)',
32 langDirRTL: 'જમણે થી ડાબે (RTL)',
33 menu: ' લિંક એડિટ/માં ફેરફાર કરવો',
34 name: 'નામ',
35 noAnchors: '(ડૉક્યુમન્ટમાં ઍંકરની સંખ્યા)',
36 noEmail: 'ઈ-મેલ સરનામું ટાઇપ કરો',
37 noUrl: 'લિંક URL ટાઇપ કરો',
38 other: '<other> <અન્ય>',
39 popupDependent: 'ડિપેન્ડન્ટ (Netscape)',
40 popupFeatures: 'પૉપ-અપ વિન્ડો ફીચરસૅ',
41 popupFullScreen: 'ફુલ સ્ક્રીન (IE)',
42 popupLeft: 'ડાબી બાજુ',
43 popupLocationBar: 'લોકેશન બાર',
44 popupMenuBar: 'મેન્યૂ બાર',
45 popupResizable: 'રીસાઈઝએબલ',
46 popupScrollBars: 'સ્ક્રોલ બાર',
47 popupStatusBar: 'સ્ટૅટસ બાર',
48 popupToolbar: 'ટૂલ બાર',
49 popupTop: 'જમણી બાજુ',
50 rel: 'સંબંધની સ્થિતિ',
51 selectAnchor: 'ઍંકર પસંદ કરો',
52 styles: 'સ્ટાઇલ',
53 tabIndex: 'ટૅબ ઇન્ડેક્સ',
54 target: 'ટાર્ગેટ/લક્ષ્ય',
55 targetFrame: '<ફ્રેમ>',
56 targetFrameName: 'ટાર્ગેટ ફ્રેમ નું નામ',
57 targetPopup: '<પૉપ-અપ વિન્ડો>',
58 targetPopupName: 'પૉપ-અપ વિન્ડો નું નામ',
59 title: 'લિંક',
60 toAnchor: 'આ પેજનો ઍંકર',
61 toEmail: 'ઈ-મેલ',
62 toUrl: 'URL',
63 toolbar: 'લિંક ઇન્સર્ટ/દાખલ કરવી',
64 type: 'લિંક પ્રકાર',
65 unlink: 'લિંક કાઢવી',
66 upload: 'અપલોડ'
67} );
diff --git a/sources/plugins/link/lang/he.js b/sources/plugins/link/lang/he.js
new file mode 100644
index 0000000..a00f60a
--- /dev/null
+++ b/sources/plugins/link/lang/he.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'he', {
6 acccessKey: 'מקש גישה',
7 advanced: 'אפשרויות מתקדמות',
8 advisoryContentType: 'Content Type מוצע',
9 advisoryTitle: 'כותרת מוצעת',
10 anchor: {
11 toolbar: 'הוספת/עריכת נקודת עיגון',
12 menu: 'מאפייני נקודת עיגון',
13 title: 'מאפייני נקודת עיגון',
14 name: 'שם לנקודת עיגון',
15 errorName: 'יש להקליד שם לנקודת עיגון',
16 remove: 'מחיקת נקודת עיגון'
17 },
18 anchorId: 'עפ"י זיהוי (ID) האלמנט',
19 anchorName: 'עפ"י שם העוגן',
20 charset: 'קידוד המשאב המקושר',
21 cssClasses: 'גיליונות עיצוב קבוצות',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'כתובת הדוא"ל',
25 emailBody: 'גוף ההודעה',
26 emailSubject: 'נושא ההודעה',
27 id: 'זיהוי (ID)',
28 info: 'מידע על הקישור',
29 langCode: 'קוד שפה',
30 langDir: 'כיוון שפה',
31 langDirLTR: 'שמאל לימין (LTR)',
32 langDirRTL: 'ימין לשמאל (RTL)',
33 menu: 'מאפייני קישור',
34 name: 'שם',
35 noAnchors: '(אין עוגנים זמינים בדף)',
36 noEmail: 'יש להקליד את כתובת הדוא"ל',
37 noUrl: 'יש להקליד את כתובת הקישור (URL)',
38 other: '<אחר>',
39 popupDependent: 'תלוי (Netscape)',
40 popupFeatures: 'תכונות החלון הקופץ',
41 popupFullScreen: 'מסך מלא (IE)',
42 popupLeft: 'מיקום צד שמאל',
43 popupLocationBar: 'סרגל כתובת',
44 popupMenuBar: 'סרגל תפריט',
45 popupResizable: 'שינוי גודל',
46 popupScrollBars: 'ניתן לגלילה',
47 popupStatusBar: 'סרגל חיווי',
48 popupToolbar: 'סרגל הכלים',
49 popupTop: 'מיקום צד עליון',
50 rel: 'קשר גומלין',
51 selectAnchor: 'בחירת עוגן',
52 styles: 'סגנון',
53 tabIndex: 'מספר טאב',
54 target: 'מטרה',
55 targetFrame: '<מסגרת>',
56 targetFrameName: 'שם מסגרת היעד',
57 targetPopup: '<חלון קופץ>',
58 targetPopupName: 'שם החלון הקופץ',
59 title: 'קישור',
60 toAnchor: 'עוגן בעמוד זה',
61 toEmail: 'דוא"ל',
62 toUrl: 'כתובת (URL)',
63 toolbar: 'הוספת/עריכת קישור',
64 type: 'סוג קישור',
65 unlink: 'הסרת הקישור',
66 upload: 'העלאה'
67} );
diff --git a/sources/plugins/link/lang/hi.js b/sources/plugins/link/lang/hi.js
new file mode 100644
index 0000000..88b7df9
--- /dev/null
+++ b/sources/plugins/link/lang/hi.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'hi', {
6 acccessKey: 'ऍक्सॅस की',
7 advanced: 'ऍड्वान्स्ड',
8 advisoryContentType: 'परामर्श कन्टॅन्ट प्रकार',
9 advisoryTitle: 'परामर्श शीर्शक',
10 anchor: {
11 toolbar: 'ऐंकर इन्सर्ट/संपादन',
12 menu: 'ऐंकर प्रॉपर्टीज़',
13 title: 'ऐंकर प्रॉपर्टीज़',
14 name: 'ऐंकर का नाम',
15 errorName: 'ऐंकर का नाम टाइप करें',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'ऍलीमॅन्ट Id से',
19 anchorName: 'ऐंकर नाम से',
20 charset: 'लिंक रिसोर्स करॅक्टर सॅट',
21 cssClasses: 'स्टाइल-शीट क्लास',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'ई-मेल पता',
25 emailBody: 'संदेश',
26 emailSubject: 'संदेश विषय',
27 id: 'Id',
28 info: 'लिंक ',
29 langCode: 'भाषा लिखने की दिशा',
30 langDir: 'भाषा लिखने की दिशा',
31 langDirLTR: 'बायें से दायें (LTR)',
32 langDirRTL: 'दायें से बायें (RTL)',
33 menu: 'लिंक संपादन',
34 name: 'नाम',
35 noAnchors: '(डॉक्यूमॅन्ट में ऐंकर्स की संख्या)',
36 noEmail: 'ई-मेल पता टाइप करें',
37 noUrl: 'लिंक URL टाइप करें',
38 other: '<अन्य>',
39 popupDependent: 'डिपेन्डॅन्ट (Netscape)',
40 popupFeatures: 'पॉप-अप विन्डो फ़ीचर्स',
41 popupFullScreen: 'फ़ुल स्क्रीन (IE)',
42 popupLeft: 'बायीं तरफ',
43 popupLocationBar: 'लोकेशन बार',
44 popupMenuBar: 'मॅन्यू बार',
45 popupResizable: 'आकार बदलने लायक',
46 popupScrollBars: 'स्क्रॉल बार',
47 popupStatusBar: 'स्टेटस बार',
48 popupToolbar: 'टूल बार',
49 popupTop: 'दायीं तरफ',
50 rel: 'संबंध',
51 selectAnchor: 'ऐंकर चुनें',
52 styles: 'स्टाइल',
53 tabIndex: 'टैब इन्डॅक्स',
54 target: 'टार्गेट',
55 targetFrame: '<फ़्रेम>',
56 targetFrameName: 'टार्गेट फ़्रेम का नाम',
57 targetPopup: '<पॉप-अप विन्डो>',
58 targetPopupName: 'पॉप-अप विन्डो का नाम',
59 title: 'लिंक',
60 toAnchor: 'इस पेज का ऐंकर',
61 toEmail: 'ई-मेल',
62 toUrl: 'URL',
63 toolbar: 'लिंक इन्सर्ट/संपादन',
64 type: 'लिंक प्रकार',
65 unlink: 'लिंक हटायें',
66 upload: 'अपलोड'
67} );
diff --git a/sources/plugins/link/lang/hr.js b/sources/plugins/link/lang/hr.js
new file mode 100644
index 0000000..898b18b
--- /dev/null
+++ b/sources/plugins/link/lang/hr.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'hr', {
6 acccessKey: 'Pristupna tipka',
7 advanced: 'Napredno',
8 advisoryContentType: 'Advisory vrsta sadržaja',
9 advisoryTitle: 'Advisory naslov',
10 anchor: {
11 toolbar: 'Ubaci/promijeni sidro',
12 menu: 'Svojstva sidra',
13 title: 'Svojstva sidra',
14 name: 'Ime sidra',
15 errorName: 'Molimo unesite ime sidra',
16 remove: 'Ukloni sidro'
17 },
18 anchorId: 'Po Id elementa',
19 anchorName: 'Po nazivu sidra',
20 charset: 'Kodna stranica povezanih resursa',
21 cssClasses: 'Stylesheet klase',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail adresa',
25 emailBody: 'Sadržaj poruke',
26 emailSubject: 'Naslov',
27 id: 'Id',
28 info: 'Link Info',
29 langCode: 'Smjer jezika',
30 langDir: 'Smjer jezika',
31 langDirLTR: 'S lijeva na desno (LTR)',
32 langDirRTL: 'S desna na lijevo (RTL)',
33 menu: 'Promijeni link',
34 name: 'Naziv',
35 noAnchors: '(Nema dostupnih sidra)',
36 noEmail: 'Molimo upišite e-mail adresu',
37 noUrl: 'Molimo upišite URL link',
38 other: '<drugi>',
39 popupDependent: 'Ovisno (Netscape)',
40 popupFeatures: 'Mogućnosti popup prozora',
41 popupFullScreen: 'Cijeli ekran (IE)',
42 popupLeft: 'Lijeva pozicija',
43 popupLocationBar: 'Traka za lokaciju',
44 popupMenuBar: 'Izborna traka',
45 popupResizable: 'Promjenjiva veličina',
46 popupScrollBars: 'Scroll traka',
47 popupStatusBar: 'Statusna traka',
48 popupToolbar: 'Traka s alatima',
49 popupTop: 'Gornja pozicija',
50 rel: 'Veza',
51 selectAnchor: 'Odaberi sidro',
52 styles: 'Stil',
53 tabIndex: 'Tab Indeks',
54 target: 'Meta',
55 targetFrame: '<okvir>',
56 targetFrameName: 'Ime ciljnog okvira',
57 targetPopup: '<popup prozor>',
58 targetPopupName: 'Naziv popup prozora',
59 title: 'Link',
60 toAnchor: 'Sidro na ovoj stranici',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Ubaci/promijeni link',
64 type: 'Link vrsta',
65 unlink: 'Ukloni link',
66 upload: 'Pošalji'
67} );
diff --git a/sources/plugins/link/lang/hu.js b/sources/plugins/link/lang/hu.js
new file mode 100644
index 0000000..52c09a8
--- /dev/null
+++ b/sources/plugins/link/lang/hu.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'hu', {
6 acccessKey: 'Billentyűkombináció',
7 advanced: 'További opciók',
8 advisoryContentType: 'Súgó tartalomtípusa',
9 advisoryTitle: 'Súgócimke',
10 anchor: {
11 toolbar: 'Horgony beillesztése/szerkesztése',
12 menu: 'Horgony tulajdonságai',
13 title: 'Horgony tulajdonságai',
14 name: 'Horgony neve',
15 errorName: 'Kérem adja meg a horgony nevét',
16 remove: 'Horgony eltávolítása'
17 },
18 anchorId: 'Azonosító szerint',
19 anchorName: 'Horgony név szerint',
20 charset: 'Hivatkozott tartalom kódlapja',
21 cssClasses: 'Stíluskészlet',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail cím',
25 emailBody: 'Üzenet',
26 emailSubject: 'Üzenet tárgya',
27 id: 'Id',
28 info: 'Alaptulajdonságok',
29 langCode: 'Írás iránya',
30 langDir: 'Írás iránya',
31 langDirLTR: 'Balról jobbra',
32 langDirRTL: 'Jobbról balra',
33 menu: 'Hivatkozás módosítása',
34 name: 'Név',
35 noAnchors: '(Nincs horgony a dokumentumban)',
36 noEmail: 'Adja meg az E-Mail címet',
37 noUrl: 'Adja meg a hivatkozás webcímét',
38 other: '<más>',
39 popupDependent: 'Szülőhöz kapcsolt (csak Netscape)',
40 popupFeatures: 'Felugró ablak jellemzői',
41 popupFullScreen: 'Teljes képernyő (csak IE)',
42 popupLeft: 'Bal pozíció',
43 popupLocationBar: 'Címsor',
44 popupMenuBar: 'Menü sor',
45 popupResizable: 'Átméretezés',
46 popupScrollBars: 'Gördítősáv',
47 popupStatusBar: 'Állapotsor',
48 popupToolbar: 'Eszköztár',
49 popupTop: 'Felső pozíció',
50 rel: 'Kapcsolat típusa',
51 selectAnchor: 'Horgony választása',
52 styles: 'Stílus',
53 tabIndex: 'Tabulátor index',
54 target: 'Tartalom megjelenítése',
55 targetFrame: '<keretben>',
56 targetFrameName: 'Keret neve',
57 targetPopup: '<felugró ablakban>',
58 targetPopupName: 'Felugró ablak neve',
59 title: 'Hivatkozás tulajdonságai',
60 toAnchor: 'Horgony az oldalon',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Hivatkozás beillesztése/módosítása',
64 type: 'Hivatkozás típusa',
65 unlink: 'Hivatkozás törlése',
66 upload: 'Feltöltés'
67} );
diff --git a/sources/plugins/link/lang/id.js b/sources/plugins/link/lang/id.js
new file mode 100644
index 0000000..e255eb5
--- /dev/null
+++ b/sources/plugins/link/lang/id.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'id', {
6 acccessKey: 'Access Key', // MISSING
7 advanced: 'Advanced', // MISSING
8 advisoryContentType: 'Advisory Content Type', // MISSING
9 advisoryTitle: 'Penasehat Judul',
10 anchor: {
11 toolbar: 'Anchor', // MISSING
12 menu: 'Edit Anchor', // MISSING
13 title: 'Anchor Properties', // MISSING
14 name: 'Anchor Name', // MISSING
15 errorName: 'Please type the anchor name', // MISSING
16 remove: 'Remove Anchor' // MISSING
17 },
18 anchorId: 'By Element Id', // MISSING
19 anchorName: 'By Anchor Name', // MISSING
20 charset: 'Linked Resource Charset', // MISSING
21 cssClasses: 'Kelas Stylesheet',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Alamat E-mail',
25 emailBody: 'Message Body', // MISSING
26 emailSubject: 'Judul Pesan',
27 id: 'Id',
28 info: 'Link Info', // MISSING
29 langCode: 'Kode Bahasa',
30 langDir: 'Arah Bahasa',
31 langDirLTR: 'Kiri ke Kanan (LTR)',
32 langDirRTL: 'Kanan ke Kiri (RTL)',
33 menu: 'Sunting Tautan',
34 name: 'Nama',
35 noAnchors: '(No anchors available in the document)', // MISSING
36 noEmail: 'Silahkan ketikkan alamat e-mail',
37 noUrl: 'Silahkan ketik URL tautan',
38 other: '<lainnya>',
39 popupDependent: 'Dependent (Netscape)', // MISSING
40 popupFeatures: 'Popup Window Features', // MISSING
41 popupFullScreen: 'Full Screen (IE)', // MISSING
42 popupLeft: 'Left Position', // MISSING
43 popupLocationBar: 'Location Bar', // MISSING
44 popupMenuBar: 'Menu Bar', // MISSING
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Scroll Bars', // MISSING
47 popupStatusBar: 'Status Bar', // MISSING
48 popupToolbar: 'Toolbar', // MISSING
49 popupTop: 'Top Position', // MISSING
50 rel: 'Hubungan',
51 selectAnchor: 'Select an Anchor', // MISSING
52 styles: 'Gaya',
53 tabIndex: 'Tab Index', // MISSING
54 target: 'Sasaran',
55 targetFrame: '<frame>', // MISSING
56 targetFrameName: 'Target Frame Name', // MISSING
57 targetPopup: '<popup window>', // MISSING
58 targetPopupName: 'Popup Window Name', // MISSING
59 title: 'Tautan',
60 toAnchor: 'Link to anchor in the text', // MISSING
61 toEmail: 'E-mail', // MISSING
62 toUrl: 'URL',
63 toolbar: 'Tautan',
64 type: 'Link Type', // MISSING
65 unlink: 'Unlink', // MISSING
66 upload: 'Unggah'
67} );
diff --git a/sources/plugins/link/lang/is.js b/sources/plugins/link/lang/is.js
new file mode 100644
index 0000000..ccdea0a
--- /dev/null
+++ b/sources/plugins/link/lang/is.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'is', {
6 acccessKey: 'Skammvalshnappur',
7 advanced: 'Tæknilegt',
8 advisoryContentType: 'Tegund innihalds',
9 advisoryTitle: 'Titill',
10 anchor: {
11 toolbar: 'Stofna/breyta kaflamerki',
12 menu: 'Eigindi kaflamerkis',
13 title: 'Eigindi kaflamerkis',
14 name: 'Nafn bókamerkis',
15 errorName: 'Sláðu inn nafn bókamerkis!',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'Eftir auðkenni einingar',
19 anchorName: 'Eftir akkerisnafni',
20 charset: 'Táknróf',
21 cssClasses: 'Stílsniðsflokkur',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Netfang',
25 emailBody: 'Meginmál',
26 emailSubject: 'Efni',
27 id: 'Auðkenni',
28 info: 'Almennt',
29 langCode: 'Lesstefna',
30 langDir: 'Lesstefna',
31 langDirLTR: 'Frá vinstri til hægri (LTR)',
32 langDirRTL: 'Frá hægri til vinstri (RTL)',
33 menu: 'Breyta stiklu',
34 name: 'Nafn',
35 noAnchors: '<Engin bókamerki á skrá>',
36 noEmail: 'Sláðu inn netfang!',
37 noUrl: 'Sláðu inn veffang stiklunnar!',
38 other: '<annar>',
39 popupDependent: 'Háð venslum (Netscape)',
40 popupFeatures: 'Eigindi sprettiglugga',
41 popupFullScreen: 'Heilskjár (IE)',
42 popupLeft: 'Fjarlægð frá vinstri',
43 popupLocationBar: 'Fanglína',
44 popupMenuBar: 'Vallína',
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Skrunstikur',
47 popupStatusBar: 'Stöðustika',
48 popupToolbar: 'Verkfærastika',
49 popupTop: 'Fjarlægð frá efri brún',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Veldu akkeri',
52 styles: 'Stíll',
53 tabIndex: 'Raðnúmer innsláttarreits',
54 target: 'Mark',
55 targetFrame: '<rammi>',
56 targetFrameName: 'Nafn markglugga',
57 targetPopup: '<sprettigluggi>',
58 targetPopupName: 'Nafn sprettiglugga',
59 title: 'Stikla',
60 toAnchor: 'Bókamerki á þessari síðu',
61 toEmail: 'Netfang',
62 toUrl: 'Vefslóð',
63 toolbar: 'Stofna/breyta stiklu',
64 type: 'Stikluflokkur',
65 unlink: 'Fjarlægja stiklu',
66 upload: 'Senda upp'
67} );
diff --git a/sources/plugins/link/lang/it.js b/sources/plugins/link/lang/it.js
new file mode 100644
index 0000000..b6b93bf
--- /dev/null
+++ b/sources/plugins/link/lang/it.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'it', {
6 acccessKey: 'Scorciatoia da tastiera',
7 advanced: 'Avanzate',
8 advisoryContentType: 'Tipo della risorsa collegata',
9 advisoryTitle: 'Titolo',
10 anchor: {
11 toolbar: 'Inserisci/Modifica Ancora',
12 menu: 'Proprietà ancora',
13 title: 'Proprietà ancora',
14 name: 'Nome ancora',
15 errorName: 'Inserici il nome dell\'ancora',
16 remove: 'Rimuovi l\'ancora'
17 },
18 anchorId: 'Per id elemento',
19 anchorName: 'Per Nome',
20 charset: 'Set di caretteri della risorsa collegata',
21 cssClasses: 'Nome classe CSS',
22 download: 'Forza scaricamento',
23 displayText: 'Mostra testo',
24 emailAddress: 'Indirizzo E-Mail',
25 emailBody: 'Corpo del messaggio',
26 emailSubject: 'Oggetto del messaggio',
27 id: 'Id',
28 info: 'Informazioni collegamento',
29 langCode: 'Direzione scrittura',
30 langDir: 'Direzione scrittura',
31 langDirLTR: 'Da Sinistra a Destra (LTR)',
32 langDirRTL: 'Da Destra a Sinistra (RTL)',
33 menu: 'Modifica collegamento',
34 name: 'Nome',
35 noAnchors: '(Nessuna ancora disponibile nel documento)',
36 noEmail: 'Devi inserire un\'indirizzo e-mail',
37 noUrl: 'Devi inserire l\'URL del collegamento',
38 other: '<altro>',
39 popupDependent: 'Dipendente (Netscape)',
40 popupFeatures: 'Caratteristiche finestra popup',
41 popupFullScreen: 'A tutto schermo (IE)',
42 popupLeft: 'Posizione da sinistra',
43 popupLocationBar: 'Barra degli indirizzi',
44 popupMenuBar: 'Barra del menu',
45 popupResizable: 'Ridimensionabile',
46 popupScrollBars: 'Barre di scorrimento',
47 popupStatusBar: 'Barra di stato',
48 popupToolbar: 'Barra degli strumenti',
49 popupTop: 'Posizione dall\'alto',
50 rel: 'Relazioni',
51 selectAnchor: 'Scegli Ancora',
52 styles: 'Stile',
53 tabIndex: 'Ordine di tabulazione',
54 target: 'Destinazione',
55 targetFrame: '<riquadro>',
56 targetFrameName: 'Nome del riquadro di destinazione',
57 targetPopup: '<finestra popup>',
58 targetPopupName: 'Nome finestra popup',
59 title: 'Collegamento',
60 toAnchor: 'Ancora nel testo',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Collegamento',
64 type: 'Tipo di Collegamento',
65 unlink: 'Elimina collegamento',
66 upload: 'Carica'
67} );
diff --git a/sources/plugins/link/lang/ja.js b/sources/plugins/link/lang/ja.js
new file mode 100644
index 0000000..94108b5
--- /dev/null
+++ b/sources/plugins/link/lang/ja.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ja', {
6 acccessKey: 'アクセスキー',
7 advanced: '高度な設定',
8 advisoryContentType: 'Content Type属性',
9 advisoryTitle: 'Title属性',
10 anchor: {
11 toolbar: 'アンカー挿入/編集',
12 menu: 'アンカーの編集',
13 title: 'アンカーのプロパティ',
14 name: 'アンカー名',
15 errorName: 'アンカー名を入力してください。',
16 remove: 'アンカーを削除'
17 },
18 anchorId: 'エレメントID',
19 anchorName: 'アンカー名',
20 charset: 'リンク先のcharset',
21 cssClasses: 'スタイルシートクラス',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail アドレス',
25 emailBody: '本文',
26 emailSubject: '件名',
27 id: 'Id',
28 info: 'ハイパーリンク情報',
29 langCode: '言語コード',
30 langDir: '文字表記の方向',
31 langDirLTR: '左から右 (LTR)',
32 langDirRTL: '右から左 (RTL)',
33 menu: 'リンクを編集',
34 name: 'Name属性',
35 noAnchors: '(このドキュメント内にアンカーはありません)',
36 noEmail: 'メールアドレスを入力してください。',
37 noUrl: 'リンクURLを入力してください。',
38 other: '<その他の>',
39 popupDependent: '開いたウィンドウに連動して閉じる (Netscape)',
40 popupFeatures: 'ポップアップウィンドウ特徴',
41 popupFullScreen: '全画面モード(IE)',
42 popupLeft: '左端からの座標で指定',
43 popupLocationBar: 'ロケーションバー',
44 popupMenuBar: 'メニューバー',
45 popupResizable: 'サイズ可変',
46 popupScrollBars: 'スクロールバー',
47 popupStatusBar: 'ステータスバー',
48 popupToolbar: 'ツールバー',
49 popupTop: '上端からの座標で指定',
50 rel: '関連リンク',
51 selectAnchor: 'アンカーを選択',
52 styles: 'スタイルシート',
53 tabIndex: 'タブインデックス',
54 target: 'ターゲット',
55 targetFrame: '<フレーム>',
56 targetFrameName: 'ターゲットのフレーム名',
57 targetPopup: '<ポップアップウィンドウ>',
58 targetPopupName: 'ポップアップウィンドウ名',
59 title: 'ハイパーリンク',
60 toAnchor: 'ページ内のアンカー',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'リンク挿入/編集',
64 type: 'リンクタイプ',
65 unlink: 'リンクを削除',
66 upload: 'アップロード'
67} );
diff --git a/sources/plugins/link/lang/ka.js b/sources/plugins/link/lang/ka.js
new file mode 100644
index 0000000..439c43d
--- /dev/null
+++ b/sources/plugins/link/lang/ka.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ka', {
6 acccessKey: 'წვდომის ღილაკი',
7 advanced: 'დაწვრილებით',
8 advisoryContentType: 'შიგთავსის ტიპი',
9 advisoryTitle: 'სათაური',
10 anchor: {
11 toolbar: 'ღუზა',
12 menu: 'ღუზის რედაქტირება',
13 title: 'ღუზის პარამეტრები',
14 name: 'ღუზუს სახელი',
15 errorName: 'აკრიფეთ ღუზის სახელი',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'ელემენტის Id-თ',
19 anchorName: 'ღუზის სახელით',
20 charset: 'კოდირება',
21 cssClasses: 'CSS კლასი',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'ელფოსტის მისამართები',
25 emailBody: 'წერილის ტექსტი',
26 emailSubject: 'წერილის სათაური',
27 id: 'Id',
28 info: 'ბმულის ინფორმაცია',
29 langCode: 'ენის კოდი',
30 langDir: 'ენის მიმართულება',
31 langDirLTR: 'მარცხნიდან მარჯვნივ (LTR)',
32 langDirRTL: 'მარჯვნიდან მარცხნივ (RTL)',
33 menu: 'ბმულის რედაქტირება',
34 name: 'სახელი',
35 noAnchors: '(ამ დოკუმენტში ღუზა არაა)',
36 noEmail: 'აკრიფეთ ელფოსტის მისამართი',
37 noUrl: 'აკრიფეთ ბმულის URL',
38 other: '<სხვა>',
39 popupDependent: 'დამოკიდებული (Netscape)',
40 popupFeatures: 'Popup ფანჯრის პარამეტრები',
41 popupFullScreen: 'მთელი ეკრანი (IE)',
42 popupLeft: 'მარცხენა პოზიცია',
43 popupLocationBar: 'ნავიგაციის ზოლი',
44 popupMenuBar: 'მენიუს ზოლი',
45 popupResizable: 'ცვალებადი ზომით',
46 popupScrollBars: 'გადახვევის ზოლები',
47 popupStatusBar: 'სტატუსის ზოლი',
48 popupToolbar: 'ხელსაწყოთა ზოლი',
49 popupTop: 'ზედა პოზიცია',
50 rel: 'კავშირი',
51 selectAnchor: 'აირჩიეთ ღუზა',
52 styles: 'CSS სტილი',
53 tabIndex: 'Tab-ის ინდექსი',
54 target: 'გახსნის ადგილი',
55 targetFrame: '<frame>',
56 targetFrameName: 'Frame-ის სახელი',
57 targetPopup: '<popup ფანჯარა>',
58 targetPopupName: 'Popup ფანჯრის სახელი',
59 title: 'ბმული',
60 toAnchor: 'ბმული ტექსტში ღუზაზე',
61 toEmail: 'ელფოსტა',
62 toUrl: 'URL',
63 toolbar: 'ბმული',
64 type: 'ბმულის ტიპი',
65 unlink: 'ბმულის მოხსნა',
66 upload: 'აქაჩვა'
67} );
diff --git a/sources/plugins/link/lang/km.js b/sources/plugins/link/lang/km.js
new file mode 100644
index 0000000..5d0be03
--- /dev/null
+++ b/sources/plugins/link/lang/km.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'km', {
6 acccessKey: 'សោរ​ចូល',
7 advanced: 'កម្រិត​ខ្ពស់',
8 advisoryContentType: 'ប្រភេទអត្ថបទ​ប្រឹក្សា',
9 advisoryTitle: 'ចំណងជើង​ប្រឹក្សា',
10 anchor: {
11 toolbar: 'យុថ្កា',
12 menu: 'កែ​យុថ្កា',
13 title: 'លក្ខណៈ​យុថ្កា',
14 name: 'ឈ្មោះ​យុថ្កា',
15 errorName: 'សូម​បញ្ចូល​ឈ្មោះ​យុថ្កា',
16 remove: 'ដក​យុថ្កា​ចេញ'
17 },
18 anchorId: 'តាម ID ធាតុ',
19 anchorName: 'តាម​ឈ្មោះ​យុថ្កា',
20 charset: 'លេខកូតអក្សររបស់ឈ្នាប់',
21 cssClasses: 'Stylesheet Classes',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'អាសយដ្ឋាន​អ៊ីមែល',
25 emailBody: 'តួ​អត្ថបទ',
26 emailSubject: 'ប្រធានបទ​សារ',
27 id: 'Id',
28 info: 'ព័ត៌មាន​ពី​តំណ',
29 langCode: 'កូដ​ភាសា',
30 langDir: 'ទិសដៅភាសា',
31 langDirLTR: 'ពីឆ្វេងទៅស្តាំ(LTR)',
32 langDirRTL: 'ពីស្តាំទៅឆ្វេង(RTL)',
33 menu: 'កែ​តំណ',
34 name: 'ឈ្មោះ',
35 noAnchors: '(មិន​មាន​យុថ្កា​នៅ​ក្នុង​ឯកសារ​អត្ថថបទ​ទេ)',
36 noEmail: 'សូម​បញ្ចូល​អាសយដ្ឋាន​អ៊ីមែល',
37 noUrl: 'សូម​បញ្ចូល​តំណ URL',
38 other: '<ផ្សេង​ទៀត>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: 'មុខ​ងារ​ផុស​ផ្ទាំង​វីនដូ​ឡើង',
41 popupFullScreen: 'ពេញ​អេក្រង់ (IE)',
42 popupLeft: 'ទីតាំងខាងឆ្វេង',
43 popupLocationBar: 'របារ​ទីតាំង',
44 popupMenuBar: 'របារ​ម៉ឺនុយ',
45 popupResizable: 'អាច​ប្ដូរ​ទំហំ',
46 popupScrollBars: 'របារ​រំកិល',
47 popupStatusBar: 'របារ​ស្ថានភាព',
48 popupToolbar: 'របារ​ឧបករណ៍',
49 popupTop: 'ទីតាំង​កំពូល',
50 rel: 'សម្ពន្ធ​ភាព',
51 selectAnchor: 'រើស​យក​យុថ្កា​មួយ',
52 styles: 'ស្ទីល',
53 tabIndex: 'លេខ Tab',
54 target: 'គោលដៅ',
55 targetFrame: '<ស៊ុម>',
56 targetFrameName: 'ឈ្មោះ​ស៊ុម​ជា​គោល​ដៅ',
57 targetPopup: '<វីនដូ​ផុស​ឡើង>',
58 targetPopupName: 'ឈ្មោះ​វីនដូត​ផុស​ឡើង',
59 title: 'តំណ',
60 toAnchor: 'ត​ភ្ជាប់​ទៅ​យុថ្កា​ក្នុង​អត្ថបទ',
61 toEmail: 'អ៊ីមែល',
62 toUrl: 'URL',
63 toolbar: 'តំណ',
64 type: 'ប្រភេទ​តំណ',
65 unlink: 'ផ្ដាច់​តំណ',
66 upload: 'ផ្ទុក​ឡើង'
67} );
diff --git a/sources/plugins/link/lang/ko.js b/sources/plugins/link/lang/ko.js
new file mode 100644
index 0000000..86a797d
--- /dev/null
+++ b/sources/plugins/link/lang/ko.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ko', {
6 acccessKey: '액세스 키',
7 advanced: '고급',
8 advisoryContentType: '보조 콘텐츠 유형',
9 advisoryTitle: '보조 제목',
10 anchor: {
11 toolbar: '책갈피',
12 menu: '책갈피 편집',
13 title: '책갈피 속성',
14 name: '책갈피 이름',
15 errorName: '책갈피 이름을 입력하십시오',
16 remove: '책갈피 제거'
17 },
18 anchorId: '책갈피 ID',
19 anchorName: '책갈피 이름',
20 charset: '링크된 자료 문자열 인코딩',
21 cssClasses: '스타일시트 클래스',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: '이메일 주소',
25 emailBody: '메시지 내용',
26 emailSubject: '메시지 제목',
27 id: 'ID',
28 info: '링크 정보',
29 langCode: '언어 코드',
30 langDir: '언어 방향',
31 langDirLTR: '왼쪽에서 오른쪽 (LTR)',
32 langDirRTL: '오른쪽에서 왼쪽 (RTL)',
33 menu: '링크 수정',
34 name: '이름',
35 noAnchors: '(문서에 책갈피가 없습니다.)',
36 noEmail: '이메일 주소를 입력하십시오',
37 noUrl: '링크 주소(URL)를 입력하십시오',
38 other: '<기타>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: '팝업창 속성',
41 popupFullScreen: '전체화면 (IE)',
42 popupLeft: '왼쪽 위치',
43 popupLocationBar: '주소 표시줄',
44 popupMenuBar: '메뉴 바',
45 popupResizable: '크기 조절 가능',
46 popupScrollBars: '스크롤 바',
47 popupStatusBar: '상태 바',
48 popupToolbar: '툴바',
49 popupTop: '위쪽 위치',
50 rel: '관계',
51 selectAnchor: '책갈피 선택',
52 styles: '스타일',
53 tabIndex: '탭 순서',
54 target: '타겟',
55 targetFrame: '<프레임>',
56 targetFrameName: '타겟 프레임 이름',
57 targetPopup: '<팝업 창>',
58 targetPopupName: '팝업 창 이름',
59 title: '링크',
60 toAnchor: '책갈피',
61 toEmail: '이메일',
62 toUrl: '주소(URL)',
63 toolbar: '링크 삽입/변경',
64 type: '링크 종류',
65 unlink: '링크 지우기',
66 upload: '업로드'
67} );
diff --git a/sources/plugins/link/lang/ku.js b/sources/plugins/link/lang/ku.js
new file mode 100644
index 0000000..16faf24
--- /dev/null
+++ b/sources/plugins/link/lang/ku.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ku', {
6 acccessKey: 'کلیلی دەستپێگەیشتن',
7 advanced: 'پێشکەوتوو',
8 advisoryContentType: 'جۆری ناوەڕۆکی ڕاویژکار',
9 advisoryTitle: 'ڕاوێژکاری سەردێڕ',
10 anchor: {
11 toolbar: 'دانان/چاکسازی لەنگەر',
12 menu: 'چاکسازی لەنگەر',
13 title: 'خاسیەتی لەنگەر',
14 name: 'ناوی لەنگەر',
15 errorName: 'تکایه ناوی لەنگەر بنووسه',
16 remove: 'لابردنی لەنگەر'
17 },
18 anchorId: 'بەپێی ناسنامەی توخم',
19 anchorName: 'بەپێی ناوی لەنگەر',
20 charset: 'بەستەری سەرچاوەی نووسە',
21 cssClasses: 'شێوازی چینی پەڕه',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'ناونیشانی ئیمەیل',
25 emailBody: 'ناوەڕۆکی نامە',
26 emailSubject: 'بابەتی نامە',
27 id: 'ناسنامە',
28 info: 'زانیاری بەستەر',
29 langCode: 'هێمای زمان',
30 langDir: 'ئاراستەی زمان',
31 langDirLTR: 'چەپ بۆ ڕاست (LTR)',
32 langDirRTL: 'ڕاست بۆ چەپ (RTL)',
33 menu: 'چاکسازی بەستەر',
34 name: 'ناو',
35 noAnchors: '(هیچ جۆرێکی لەنگەر ئامادە نیە لەم پەڕەیه)',
36 noEmail: 'تکایە ناونیشانی ئیمەیل بنووسە',
37 noUrl: 'تکایە ناونیشانی بەستەر بنووسە',
38 other: '<هیتر>',
39 popupDependent: 'پێوەبەستراو (Netscape)',
40 popupFeatures: 'خاسیەتی پەنجەرەی سەرهەڵدەر',
41 popupFullScreen: 'پڕ بەپڕی شاشە (IE)',
42 popupLeft: 'جێگای چەپ',
43 popupLocationBar: 'هێڵی ناونیشانی بەستەر',
44 popupMenuBar: 'هێڵی لیسته',
45 popupResizable: 'توانای گۆڕینی قەباره',
46 popupScrollBars: 'هێڵی هاتووچۆپێکردن',
47 popupStatusBar: 'هێڵی دۆخ',
48 popupToolbar: 'هێڵی تووڵامراز',
49 popupTop: 'جێگای سەرەوە',
50 rel: 'پەیوەندی',
51 selectAnchor: 'هەڵبژاردنی لەنگەرێك',
52 styles: 'شێواز',
53 tabIndex: 'بازدەری تابی ئیندێکس',
54 target: 'ئامانج',
55 targetFrame: '<چووارچێوە>',
56 targetFrameName: 'ناوی ئامانجی چووارچێوە',
57 targetPopup: '<پەنجەرەی سەرهەڵدەر>',
58 targetPopupName: 'ناوی پەنجەرەی سەرهەڵدەر',
59 title: 'بەستەر',
60 toAnchor: 'بەستەر بۆ لەنگەر له دەق',
61 toEmail: 'ئیمەیل',
62 toUrl: 'ناونیشانی بەستەر',
63 toolbar: 'دانان/ڕێکخستنی بەستەر',
64 type: 'جۆری بەستەر',
65 unlink: 'لابردنی بەستەر',
66 upload: 'بارکردن'
67} );
diff --git a/sources/plugins/link/lang/lt.js b/sources/plugins/link/lang/lt.js
new file mode 100644
index 0000000..27aa8b7
--- /dev/null
+++ b/sources/plugins/link/lang/lt.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'lt', {
6 acccessKey: 'Prieigos raktas',
7 advanced: 'Papildomas',
8 advisoryContentType: 'Konsultacinio turinio tipas',
9 advisoryTitle: 'Konsultacinė antraštė',
10 anchor: {
11 toolbar: 'Įterpti/modifikuoti žymę',
12 menu: 'Žymės savybės',
13 title: 'Žymės savybės',
14 name: 'Žymės vardas',
15 errorName: 'Prašome įvesti žymės vardą',
16 remove: 'Pašalinti žymę'
17 },
18 anchorId: 'Pagal žymės Id',
19 anchorName: 'Pagal žymės vardą',
20 charset: 'Susietų išteklių simbolių lentelė',
21 cssClasses: 'Stilių lentelės klasės',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'El.pašto adresas',
25 emailBody: 'Žinutės turinys',
26 emailSubject: 'Žinutės tema',
27 id: 'Id',
28 info: 'Nuorodos informacija',
29 langCode: 'Teksto kryptis',
30 langDir: 'Teksto kryptis',
31 langDirLTR: 'Iš kairės į dešinę (LTR)',
32 langDirRTL: 'Iš dešinės į kairę (RTL)',
33 menu: 'Taisyti nuorodą',
34 name: 'Vardas',
35 noAnchors: '(Šiame dokumente žymių nėra)',
36 noEmail: 'Prašome įvesti el.pašto adresą',
37 noUrl: 'Prašome įvesti nuorodos URL',
38 other: '<kitas>',
39 popupDependent: 'Priklausomas (Netscape)',
40 popupFeatures: 'Išskleidžiamo lango savybės',
41 popupFullScreen: 'Visas ekranas (IE)',
42 popupLeft: 'Kairė pozicija',
43 popupLocationBar: 'Adreso juosta',
44 popupMenuBar: 'Meniu juosta',
45 popupResizable: 'Kintamas dydis',
46 popupScrollBars: 'Slinkties juostos',
47 popupStatusBar: 'Būsenos juosta',
48 popupToolbar: 'Mygtukų juosta',
49 popupTop: 'Viršutinė pozicija',
50 rel: 'Sąsajos',
51 selectAnchor: 'Pasirinkite žymę',
52 styles: 'Stilius',
53 tabIndex: 'Tabuliavimo indeksas',
54 target: 'Paskirties vieta',
55 targetFrame: '<kadras>',
56 targetFrameName: 'Paskirties kadro vardas',
57 targetPopup: '<išskleidžiamas langas>',
58 targetPopupName: 'Paskirties lango vardas',
59 title: 'Nuoroda',
60 toAnchor: 'Žymė šiame puslapyje',
61 toEmail: 'El.paštas',
62 toUrl: 'Nuoroda',
63 toolbar: 'Įterpti/taisyti nuorodą',
64 type: 'Nuorodos tipas',
65 unlink: 'Panaikinti nuorodą',
66 upload: 'Siųsti'
67} );
diff --git a/sources/plugins/link/lang/lv.js b/sources/plugins/link/lang/lv.js
new file mode 100644
index 0000000..ef8a3f2
--- /dev/null
+++ b/sources/plugins/link/lang/lv.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'lv', {
6 acccessKey: 'Pieejas taustiņš',
7 advanced: 'Izvērstais',
8 advisoryContentType: 'Konsultatīvs satura tips',
9 advisoryTitle: 'Konsultatīvs virsraksts',
10 anchor: {
11 toolbar: 'Ievietot/Labot iezīmi',
12 menu: 'Labot iezīmi',
13 title: 'Iezīmes uzstādījumi',
14 name: 'Iezīmes nosaukums',
15 errorName: 'Lūdzu norādiet iezīmes nosaukumu',
16 remove: 'Noņemt iezīmi'
17 },
18 anchorId: 'Pēc elementa ID',
19 anchorName: 'Pēc iezīmes nosaukuma',
20 charset: 'Pievienotā resursa kodējums',
21 cssClasses: 'Stilu saraksta klases',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-pasta adrese',
25 emailBody: 'Ziņas saturs',
26 emailSubject: 'Ziņas tēma',
27 id: 'ID',
28 info: 'Hipersaites informācija',
29 langCode: 'Valodas kods',
30 langDir: 'Valodas lasīšanas virziens',
31 langDirLTR: 'No kreisās uz labo (LTR)',
32 langDirRTL: 'No labās uz kreiso (RTL)',
33 menu: 'Labot hipersaiti',
34 name: 'Nosaukums',
35 noAnchors: '(Šajā dokumentā nav iezīmju)',
36 noEmail: 'Lūdzu norādi e-pasta adresi',
37 noUrl: 'Lūdzu norādi hipersaiti',
38 other: '<cits>',
39 popupDependent: 'Atkarīgs (Netscape)',
40 popupFeatures: 'Uznirstošā loga nosaukums īpašības',
41 popupFullScreen: 'Pilnā ekrānā (IE)',
42 popupLeft: 'Kreisā koordināte',
43 popupLocationBar: 'Atrašanās vietas josla',
44 popupMenuBar: 'Izvēlnes josla',
45 popupResizable: 'Mērogojams',
46 popupScrollBars: 'Ritjoslas',
47 popupStatusBar: 'Statusa josla',
48 popupToolbar: 'Rīku josla',
49 popupTop: 'Augšējā koordināte',
50 rel: 'Relācija',
51 selectAnchor: 'Izvēlēties iezīmi',
52 styles: 'Stils',
53 tabIndex: 'Ciļņu indekss',
54 target: 'Mērķis',
55 targetFrame: '<ietvars>',
56 targetFrameName: 'Mērķa ietvara nosaukums',
57 targetPopup: '<uznirstošā logā>',
58 targetPopupName: 'Uznirstošā loga nosaukums',
59 title: 'Hipersaite',
60 toAnchor: 'Iezīme šajā lapā',
61 toEmail: 'E-pasts',
62 toUrl: 'Adrese',
63 toolbar: 'Ievietot/Labot hipersaiti',
64 type: 'Hipersaites tips',
65 unlink: 'Noņemt hipersaiti',
66 upload: 'Augšupielādēt'
67} );
diff --git a/sources/plugins/link/lang/mk.js b/sources/plugins/link/lang/mk.js
new file mode 100644
index 0000000..5fb9655
--- /dev/null
+++ b/sources/plugins/link/lang/mk.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'mk', {
6 acccessKey: 'Access Key', // MISSING
7 advanced: 'Advanced', // MISSING
8 advisoryContentType: 'Advisory Content Type', // MISSING
9 advisoryTitle: 'Advisory Title', // MISSING
10 anchor: {
11 toolbar: 'Anchor',
12 menu: 'Edit Anchor',
13 title: 'Anchor Properties',
14 name: 'Anchor Name',
15 errorName: 'Please type the anchor name',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'By Element Id', // MISSING
19 anchorName: 'By Anchor Name', // MISSING
20 charset: 'Linked Resource Charset', // MISSING
21 cssClasses: 'Stylesheet Classes', // MISSING
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail Address', // MISSING
25 emailBody: 'Message Body', // MISSING
26 emailSubject: 'Message Subject', // MISSING
27 id: 'Id',
28 info: 'Link Info', // MISSING
29 langCode: 'Код на јазик',
30 langDir: 'Насока на јазик',
31 langDirLTR: 'Лево кон десно',
32 langDirRTL: 'Десно кон лево',
33 menu: 'Edit Link', // MISSING
34 name: 'Name',
35 noAnchors: '(No anchors available in the document)', // MISSING
36 noEmail: 'Please type the e-mail address', // MISSING
37 noUrl: 'Please type the link URL', // MISSING
38 other: '<other>', // MISSING
39 popupDependent: 'Dependent (Netscape)', // MISSING
40 popupFeatures: 'Popup Window Features', // MISSING
41 popupFullScreen: 'Full Screen (IE)', // MISSING
42 popupLeft: 'Left Position', // MISSING
43 popupLocationBar: 'Location Bar', // MISSING
44 popupMenuBar: 'Menu Bar', // MISSING
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Scroll Bars', // MISSING
47 popupStatusBar: 'Status Bar', // MISSING
48 popupToolbar: 'Toolbar', // MISSING
49 popupTop: 'Top Position', // MISSING
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Select an Anchor', // MISSING
52 styles: 'Стил',
53 tabIndex: 'Tab Index', // MISSING
54 target: 'Target', // MISSING
55 targetFrame: '<frame>', // MISSING
56 targetFrameName: 'Target Frame Name', // MISSING
57 targetPopup: '<popup window>', // MISSING
58 targetPopupName: 'Popup Window Name', // MISSING
59 title: 'Врска',
60 toAnchor: 'Link to anchor in the text', // MISSING
61 toEmail: 'E-mail', // MISSING
62 toUrl: 'URL',
63 toolbar: 'Врска',
64 type: 'Link Type', // MISSING
65 unlink: 'Unlink', // MISSING
66 upload: 'Прикачи'
67} );
diff --git a/sources/plugins/link/lang/mn.js b/sources/plugins/link/lang/mn.js
new file mode 100644
index 0000000..ed159c7
--- /dev/null
+++ b/sources/plugins/link/lang/mn.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'mn', {
6 acccessKey: 'Холбох түлхүүр',
7 advanced: 'Нэмэлт',
8 advisoryContentType: 'Зөвлөлдөх төрлийн агуулга',
9 advisoryTitle: 'Зөвлөлдөх гарчиг',
10 anchor: {
11 toolbar: 'Зангуу',
12 menu: 'Зангууг болосруулах',
13 title: 'Зангуугийн шинж чанар',
14 name: 'Зангуугийн нэр',
15 errorName: 'Зангуугийн нэрийг оруулна уу',
16 remove: 'Зангууг устгах'
17 },
18 anchorId: 'Элемэнтйн Id нэрээр',
19 anchorName: 'Зангуугийн нэрээр',
20 charset: 'Тэмдэгт оноох нөөцөд холбогдсон',
21 cssClasses: 'Stylesheet классууд',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Э-шуудангийн хаяг',
25 emailBody: 'Зурвасны их бие',
26 emailSubject: 'Зурвасны гарчиг',
27 id: 'Id',
28 info: 'Холбоосын тухай мэдээлэл',
29 langCode: 'Хэлний код',
30 langDir: 'Хэлний чиглэл',
31 langDirLTR: 'Зүүнээс баруун (LTR)',
32 langDirRTL: 'Баруунаас зүүн (RTL)',
33 menu: 'Холбоос засварлах',
34 name: 'Нэр',
35 noAnchors: '(Баримт бичиг зангуугүй байна)',
36 noEmail: 'Э-шуудангий хаягаа шивнэ үү',
37 noUrl: 'Холбоосны URL хаягийг шивнэ үү',
38 other: '<other>', // MISSING
39 popupDependent: 'Хамаатай (Netscape)',
40 popupFeatures: 'Popup цонхны онцлог',
41 popupFullScreen: 'Цонх дүүргэх (Internet Explorer)',
42 popupLeft: 'Зүүн байрлал',
43 popupLocationBar: 'Location хэсэг',
44 popupMenuBar: 'Цэсний самбар',
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Скрол хэсэгүүд',
47 popupStatusBar: 'Статус хэсэг',
48 popupToolbar: 'Багажны самбар',
49 popupTop: 'Дээд байрлал',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Нэг зангууг сонгоно уу',
52 styles: 'Загвар',
53 tabIndex: 'Tab индекс',
54 target: 'Байрлал',
55 targetFrame: '<Агуулах хүрээ>',
56 targetFrameName: 'Очих фремын нэр',
57 targetPopup: '<popup цонх>',
58 targetPopupName: 'Popup цонхны нэр',
59 title: 'Холбоос',
60 toAnchor: 'Энэ бичвэр дэх зангуу руу очих холбоос',
61 toEmail: 'Э-захиа',
62 toUrl: 'цахим хуудасны хаяг (URL)',
63 toolbar: 'Холбоос',
64 type: 'Линкийн төрөл',
65 unlink: 'Холбоос авч хаях',
66 upload: 'Хуулах'
67} );
diff --git a/sources/plugins/link/lang/ms.js b/sources/plugins/link/lang/ms.js
new file mode 100644
index 0000000..9a2e499
--- /dev/null
+++ b/sources/plugins/link/lang/ms.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ms', {
6 acccessKey: 'Kunci Akses',
7 advanced: 'Advanced',
8 advisoryContentType: 'Jenis Kandungan Makluman',
9 advisoryTitle: 'Tajuk Makluman',
10 anchor: {
11 toolbar: 'Masukkan/Sunting Pautan',
12 menu: 'Ciri-ciri Pautan',
13 title: 'Ciri-ciri Pautan',
14 name: 'Nama Pautan',
15 errorName: 'Sila taip nama pautan',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'dengan menggunakan ID elemen',
19 anchorName: 'dengan menggunakan nama pautan',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Kelas-kelas Stylesheet',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Alamat E-Mail',
25 emailBody: 'Isi Kandungan Mesej',
26 emailSubject: 'Subjek Mesej',
27 id: 'Id',
28 info: 'Butiran Sambungan',
29 langCode: 'Arah Tulisan',
30 langDir: 'Arah Tulisan',
31 langDirLTR: 'Kiri ke Kanan (LTR)',
32 langDirRTL: 'Kanan ke Kiri (RTL)',
33 menu: 'Sunting Sambungan',
34 name: 'Nama',
35 noAnchors: '(Tiada pautan terdapat dalam dokumen ini)',
36 noEmail: 'Sila taip alamat e-mail',
37 noUrl: 'Sila taip sambungan URL',
38 other: '<lain>',
39 popupDependent: 'Bergantungan (Netscape)',
40 popupFeatures: 'Ciri Tetingkap Popup',
41 popupFullScreen: 'Skrin Penuh (IE)',
42 popupLeft: 'Posisi Kiri',
43 popupLocationBar: 'Bar Lokasi',
44 popupMenuBar: 'Bar Menu',
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Bar-bar skrol',
47 popupStatusBar: 'Bar Status',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Posisi Atas',
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Sila pilih pautan',
52 styles: 'Stail',
53 tabIndex: 'Indeks Tab ',
54 target: 'Sasaran',
55 targetFrame: '<bingkai>',
56 targetFrameName: 'Nama Bingkai Sasaran',
57 targetPopup: '<tetingkap popup>',
58 targetPopupName: 'Nama Tetingkap Popup',
59 title: 'Sambungan',
60 toAnchor: 'Pautan dalam muka surat ini',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Masukkan/Sunting Sambungan',
64 type: 'Jenis Sambungan',
65 unlink: 'Buang Sambungan',
66 upload: 'Muat Naik'
67} );
diff --git a/sources/plugins/link/lang/nb.js b/sources/plugins/link/lang/nb.js
new file mode 100644
index 0000000..7253b4a
--- /dev/null
+++ b/sources/plugins/link/lang/nb.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'nb', {
6 acccessKey: 'Aksessknapp',
7 advanced: 'Avansert',
8 advisoryContentType: 'Type',
9 advisoryTitle: 'Tittel',
10 anchor: {
11 toolbar: 'Anker',
12 menu: 'Rediger anker',
13 title: 'Egenskaper for anker',
14 name: 'Ankernavn',
15 errorName: 'Vennligst skriv inn ankernavnet',
16 remove: 'Fjern anker'
17 },
18 anchorId: 'Element etter ID',
19 anchorName: 'Anker etter navn',
20 charset: 'Lenket tegnsett',
21 cssClasses: 'Stilarkklasser',
22 download: 'Tving nedlasting',
23 displayText: 'Tekst som skal vises',
24 emailAddress: 'E-postadresse',
25 emailBody: 'Melding',
26 emailSubject: 'Meldingsemne',
27 id: 'Id',
28 info: 'Lenkeinfo',
29 langCode: 'Språkkode',
30 langDir: 'Språkretning',
31 langDirLTR: 'Venstre til høyre (LTR)',
32 langDirRTL: 'Høyre til venstre (RTL)',
33 menu: 'Rediger lenke',
34 name: 'Navn',
35 noAnchors: '(Ingen anker i dokumentet)',
36 noEmail: 'Vennligst skriv inn e-postadressen',
37 noUrl: 'Vennligst skriv inn lenkens URL',
38 other: '<annen>',
39 popupDependent: 'Avhenging (Netscape)',
40 popupFeatures: 'Egenskaper for popup-vindu',
41 popupFullScreen: 'Fullskjerm (IE)',
42 popupLeft: 'Venstre posisjon',
43 popupLocationBar: 'Adresselinje',
44 popupMenuBar: 'Menylinje',
45 popupResizable: 'Skalerbar',
46 popupScrollBars: 'Scrollbar',
47 popupStatusBar: 'Statuslinje',
48 popupToolbar: 'Verktøylinje',
49 popupTop: 'Topp-posisjon',
50 rel: 'Relasjon (rel)',
51 selectAnchor: 'Velg et anker',
52 styles: 'Stil',
53 tabIndex: 'Tabindeks',
54 target: 'Mål',
55 targetFrame: '<ramme>',
56 targetFrameName: 'Målramme',
57 targetPopup: '<popup-vindu>',
58 targetPopupName: 'Navn på popup-vindu',
59 title: 'Lenke',
60 toAnchor: 'Lenke til anker i teksten',
61 toEmail: 'E-post',
62 toUrl: 'URL',
63 toolbar: 'Lenke',
64 type: 'Lenketype',
65 unlink: 'Fjern lenke',
66 upload: 'Last opp'
67} );
diff --git a/sources/plugins/link/lang/nl.js b/sources/plugins/link/lang/nl.js
new file mode 100644
index 0000000..12cb509
--- /dev/null
+++ b/sources/plugins/link/lang/nl.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'nl', {
6 acccessKey: 'Toegangstoets',
7 advanced: 'Geavanceerd',
8 advisoryContentType: 'Aanbevolen content-type',
9 advisoryTitle: 'Adviserende titel',
10 anchor: {
11 toolbar: 'Interne link',
12 menu: 'Eigenschappen interne link',
13 title: 'Eigenschappen interne link',
14 name: 'Naam interne link',
15 errorName: 'Geef de naam van de interne link op',
16 remove: 'Interne link verwijderen'
17 },
18 anchorId: 'Op kenmerk interne link',
19 anchorName: 'Op naam interne link',
20 charset: 'Karakterset van gelinkte bron',
21 cssClasses: 'Stylesheet-klassen',
22 download: 'Download forceren',
23 displayText: 'Weergavetekst',
24 emailAddress: 'E-mailadres',
25 emailBody: 'Inhoud bericht',
26 emailSubject: 'Onderwerp bericht',
27 id: 'Id',
28 info: 'Linkomschrijving',
29 langCode: 'Taalcode',
30 langDir: 'Schrijfrichting',
31 langDirLTR: 'Links naar rechts (LTR)',
32 langDirRTL: 'Rechts naar links (RTL)',
33 menu: 'Link wijzigen',
34 name: 'Naam',
35 noAnchors: '(Geen interne links in document gevonden)',
36 noEmail: 'Geef een e-mailadres',
37 noUrl: 'Geef de link van de URL',
38 other: '<ander>',
39 popupDependent: 'Afhankelijk (Netscape)',
40 popupFeatures: 'Instellingen popupvenster',
41 popupFullScreen: 'Volledig scherm (IE)',
42 popupLeft: 'Positie links',
43 popupLocationBar: 'Locatiemenu',
44 popupMenuBar: 'Menubalk',
45 popupResizable: 'Herschaalbaar',
46 popupScrollBars: 'Schuifbalken',
47 popupStatusBar: 'Statusbalk',
48 popupToolbar: 'Werkbalk',
49 popupTop: 'Positie boven',
50 rel: 'Relatie',
51 selectAnchor: 'Kies een interne link',
52 styles: 'Stijl',
53 tabIndex: 'Tabvolgorde',
54 target: 'Doelvenster',
55 targetFrame: '<frame>',
56 targetFrameName: 'Naam doelframe',
57 targetPopup: '<popupvenster>',
58 targetPopupName: 'Naam popupvenster',
59 title: 'Link',
60 toAnchor: 'Interne link in pagina',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Link invoegen/wijzigen',
64 type: 'Linktype',
65 unlink: 'Link verwijderen',
66 upload: 'Upload'
67} );
diff --git a/sources/plugins/link/lang/no.js b/sources/plugins/link/lang/no.js
new file mode 100644
index 0000000..bdd7fc6
--- /dev/null
+++ b/sources/plugins/link/lang/no.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'no', {
6 acccessKey: 'Aksessknapp',
7 advanced: 'Avansert',
8 advisoryContentType: 'Type',
9 advisoryTitle: 'Tittel',
10 anchor: {
11 toolbar: 'Sett inn/Rediger anker',
12 menu: 'Egenskaper for anker',
13 title: 'Egenskaper for anker',
14 name: 'Ankernavn',
15 errorName: 'Vennligst skriv inn ankernavnet',
16 remove: 'Fjern anker'
17 },
18 anchorId: 'Element etter ID',
19 anchorName: 'Anker etter navn',
20 charset: 'Lenket tegnsett',
21 cssClasses: 'Stilarkklasser',
22 download: 'Force Download', // MISSING
23 displayText: 'Tekst som skal vises',
24 emailAddress: 'E-postadresse',
25 emailBody: 'Melding',
26 emailSubject: 'Meldingsemne',
27 id: 'Id',
28 info: 'Lenkeinfo',
29 langCode: 'Språkkode',
30 langDir: 'Språkretning',
31 langDirLTR: 'Venstre til høyre (VTH)',
32 langDirRTL: 'Høyre til venstre (HTV)',
33 menu: 'Rediger lenke',
34 name: 'Navn',
35 noAnchors: '(Ingen anker i dokumentet)',
36 noEmail: 'Vennligst skriv inn e-postadressen',
37 noUrl: 'Vennligst skriv inn lenkens URL',
38 other: '<annen>',
39 popupDependent: 'Avhenging (Netscape)',
40 popupFeatures: 'Egenskaper for popup-vindu',
41 popupFullScreen: 'Fullskjerm (IE)',
42 popupLeft: 'Venstre posisjon',
43 popupLocationBar: 'Adresselinje',
44 popupMenuBar: 'Menylinje',
45 popupResizable: 'Skalerbar',
46 popupScrollBars: 'Scrollbar',
47 popupStatusBar: 'Statuslinje',
48 popupToolbar: 'Verktøylinje',
49 popupTop: 'Topp-posisjon',
50 rel: 'Relasjon (rel)',
51 selectAnchor: 'Velg et anker',
52 styles: 'Stil',
53 tabIndex: 'Tabindeks',
54 target: 'Mål',
55 targetFrame: '<ramme>',
56 targetFrameName: 'Målramme',
57 targetPopup: '<popup-vindu>',
58 targetPopupName: 'Navn på popup-vindu',
59 title: 'Lenke',
60 toAnchor: 'Lenke til anker i teksten',
61 toEmail: 'E-post',
62 toUrl: 'URL',
63 toolbar: 'Sett inn/Rediger lenke',
64 type: 'Lenketype',
65 unlink: 'Fjern lenke',
66 upload: 'Last opp'
67} );
diff --git a/sources/plugins/link/lang/oc.js b/sources/plugins/link/lang/oc.js
new file mode 100644
index 0000000..f9e51cd
--- /dev/null
+++ b/sources/plugins/link/lang/oc.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'oc', {
6 acccessKey: 'Tòca d\'accessibilitat',
7 advanced: 'Avançat',
8 advisoryContentType: 'Tipe de contengut (indicatiu)',
9 advisoryTitle: 'Infobulla',
10 anchor: {
11 toolbar: 'Ancòra',
12 menu: 'Modificar l\'ancòra',
13 title: 'Proprietats de l\'ancòra',
14 name: 'Nom de l\'ancòra',
15 errorName: 'Entratz lo nom de l\'ancòra',
16 remove: 'Suprimir l\'ancòra'
17 },
18 anchorId: 'Per ID d\'element',
19 anchorName: 'Per nom d\'ancòra',
20 charset: 'Encodatge de la ressorsa ligada',
21 cssClasses: 'Classas d\'estil',
22 download: 'Forçar lo telecargament',
23 displayText: 'Afichar lo tèxte',
24 emailAddress: 'Adreça electronica',
25 emailBody: 'Còs del messatge',
26 emailSubject: 'Subjècte del messatge',
27 id: 'Id',
28 info: 'Informacions sul ligam',
29 langCode: 'Còdi de lenga',
30 langDir: 'Sens d\'escritura',
31 langDirLTR: 'Esquèrra a dreita (LTR)',
32 langDirRTL: 'Dreita a esquèrra (RTL)',
33 menu: 'Modificar lo ligam',
34 name: 'Nom',
35 noAnchors: '(Cap d\'ancòra pas disponibla dins aqueste document)',
36 noEmail: 'Entratz l\'adreça electronica',
37 noUrl: 'Entratz l\'URL del ligam',
38 other: '<autre>',
39 popupDependent: 'Dependenta (Netscape)',
40 popupFeatures: 'Caracteristicas de la fenèstra sorgissenta',
41 popupFullScreen: 'Ecran complet (IE)',
42 popupLeft: 'A esquèrra',
43 popupLocationBar: 'Barra d\'adreça',
44 popupMenuBar: 'Barra de menú',
45 popupResizable: 'Redimensionable',
46 popupScrollBars: 'Barras de desfilament',
47 popupStatusBar: 'Barra d\'estat',
48 popupToolbar: 'Barra d\'aisinas',
49 popupTop: 'Amont',
50 rel: 'Relacion',
51 selectAnchor: 'Seleccionar una ancòra',
52 styles: 'Estil',
53 tabIndex: 'Indici de tabulacion',
54 target: 'Cibla',
55 targetFrame: '<quadre>',
56 targetFrameName: 'Nom del quadre afectat',
57 targetPopup: '<fenèstra sorgissenta>',
58 targetPopupName: 'Nom de la fenèstra sorgissenta',
59 title: 'Ligam',
60 toAnchor: 'Ancòra',
61 toEmail: 'Corrièl',
62 toUrl: 'URL',
63 toolbar: 'Ligam',
64 type: 'Tipe de ligam',
65 unlink: 'Suprimir lo ligam',
66 upload: 'Mandar'
67} );
diff --git a/sources/plugins/link/lang/pl.js b/sources/plugins/link/lang/pl.js
new file mode 100644
index 0000000..41858d3
--- /dev/null
+++ b/sources/plugins/link/lang/pl.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'pl', {
6 acccessKey: 'Klawisz dostępu',
7 advanced: 'Zaawansowane',
8 advisoryContentType: 'Typ MIME obiektu docelowego',
9 advisoryTitle: 'Opis obiektu docelowego',
10 anchor: {
11 toolbar: 'Wstaw/edytuj kotwicę',
12 menu: 'Właściwości kotwicy',
13 title: 'Właściwości kotwicy',
14 name: 'Nazwa kotwicy',
15 errorName: 'Wpisz nazwę kotwicy',
16 remove: 'Usuń kotwicę'
17 },
18 anchorId: 'Wg identyfikatora',
19 anchorName: 'Wg nazwy',
20 charset: 'Kodowanie znaków obiektu docelowego',
21 cssClasses: 'Nazwa klasy CSS',
22 download: 'Wymuś pobieranie',
23 displayText: 'Wyświetlany tekst',
24 emailAddress: 'Adres e-mail',
25 emailBody: 'Treść',
26 emailSubject: 'Temat',
27 id: 'Id',
28 info: 'Informacje ',
29 langCode: 'Kod języka',
30 langDir: 'Kierunek tekstu',
31 langDirLTR: 'Od lewej do prawej (LTR)',
32 langDirRTL: 'Od prawej do lewej (RTL)',
33 menu: 'Edytuj odnośnik',
34 name: 'Nazwa',
35 noAnchors: '(W dokumencie nie zdefiniowano żadnych kotwic)',
36 noEmail: 'Podaj adres e-mail',
37 noUrl: 'Podaj adres URL',
38 other: '<inny>',
39 popupDependent: 'Okno zależne (Netscape)',
40 popupFeatures: 'Właściwości wyskakującego okna',
41 popupFullScreen: 'Pełny ekran (IE)',
42 popupLeft: 'Pozycja w poziomie',
43 popupLocationBar: 'Pasek adresu',
44 popupMenuBar: 'Pasek menu',
45 popupResizable: 'Skalowalny',
46 popupScrollBars: 'Paski przewijania',
47 popupStatusBar: 'Pasek statusu',
48 popupToolbar: 'Pasek narzędzi',
49 popupTop: 'Pozycja w pionie',
50 rel: 'Relacja',
51 selectAnchor: 'Wybierz kotwicę',
52 styles: 'Styl',
53 tabIndex: 'Indeks kolejności',
54 target: 'Obiekt docelowy',
55 targetFrame: '<ramka>',
56 targetFrameName: 'Nazwa ramki docelowej',
57 targetPopup: '<wyskakujące okno>',
58 targetPopupName: 'Nazwa wyskakującego okna',
59 title: 'Odnośnik',
60 toAnchor: 'Odnośnik wewnątrz strony (kotwica)',
61 toEmail: 'Adres e-mail',
62 toUrl: 'Adres URL',
63 toolbar: 'Wstaw/edytuj odnośnik',
64 type: 'Typ odnośnika',
65 unlink: 'Usuń odnośnik',
66 upload: 'Wyślij'
67} );
diff --git a/sources/plugins/link/lang/pt-br.js b/sources/plugins/link/lang/pt-br.js
new file mode 100644
index 0000000..0c43149
--- /dev/null
+++ b/sources/plugins/link/lang/pt-br.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'pt-br', {
6 acccessKey: 'Chave de Acesso',
7 advanced: 'Avançado',
8 advisoryContentType: 'Tipo de Conteúdo',
9 advisoryTitle: 'Título',
10 anchor: {
11 toolbar: 'Inserir/Editar Âncora',
12 menu: 'Formatar Âncora',
13 title: 'Formatar Âncora',
14 name: 'Nome da Âncora',
15 errorName: 'Por favor, digite o nome da âncora',
16 remove: 'Remover Âncora'
17 },
18 anchorId: 'Id da âncora',
19 anchorName: 'Nome da âncora',
20 charset: 'Charset do Link',
21 cssClasses: 'Classe de CSS',
22 download: 'Forçar Download',
23 displayText: 'Exibir Texto',
24 emailAddress: 'Endereço E-Mail',
25 emailBody: 'Corpo da Mensagem',
26 emailSubject: 'Assunto da Mensagem',
27 id: 'Id',
28 info: 'Informações',
29 langCode: 'Direção do idioma',
30 langDir: 'Direção do idioma',
31 langDirLTR: 'Esquerda para Direita (LTR)',
32 langDirRTL: 'Direita para Esquerda (RTL)',
33 menu: 'Editar Link',
34 name: 'Nome',
35 noAnchors: '(Não há âncoras no documento)',
36 noEmail: 'Por favor, digite o endereço de e-mail',
37 noUrl: 'Por favor, digite o endereço do Link',
38 other: '<outro>',
39 popupDependent: 'Dependente (Netscape)',
40 popupFeatures: 'Propriedades da Janela Pop-up',
41 popupFullScreen: 'Modo Tela Cheia (IE)',
42 popupLeft: 'Esquerda',
43 popupLocationBar: 'Barra de Endereços',
44 popupMenuBar: 'Barra de Menus',
45 popupResizable: 'Redimensionável',
46 popupScrollBars: 'Barras de Rolagem',
47 popupStatusBar: 'Barra de Status',
48 popupToolbar: 'Barra de Ferramentas',
49 popupTop: 'Topo',
50 rel: 'Tipo de Relação',
51 selectAnchor: 'Selecione uma âncora',
52 styles: 'Estilos',
53 tabIndex: 'Índice de Tabulação',
54 target: 'Destino',
55 targetFrame: '<frame>',
56 targetFrameName: 'Nome do Frame de Destino',
57 targetPopup: '<janela popup>',
58 targetPopupName: 'Nome da Janela Pop-up',
59 title: 'Editar Link',
60 toAnchor: 'Âncora nesta página',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Inserir/Editar Link',
64 type: 'Tipo de hiperlink',
65 unlink: 'Remover Link',
66 upload: 'Enviar ao Servidor'
67} );
diff --git a/sources/plugins/link/lang/pt.js b/sources/plugins/link/lang/pt.js
new file mode 100644
index 0000000..5f45548
--- /dev/null
+++ b/sources/plugins/link/lang/pt.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'pt', {
6 acccessKey: 'Chave de acesso',
7 advanced: 'Avançado',
8 advisoryContentType: 'Tipo de conteúdo',
9 advisoryTitle: 'Título',
10 anchor: {
11 toolbar: ' Inserir/Editar âncora',
12 menu: 'Propriedades da âncora',
13 title: 'Propriedades da âncora',
14 name: 'Nome da âncora',
15 errorName: 'Por favor, introduza o nome da âncora',
16 remove: 'Remover âncora'
17 },
18 anchorId: 'Por ID do elemento',
19 anchorName: 'Por Nome de Referência',
20 charset: 'Fonte de caracteres vinculado',
21 cssClasses: 'Classes de Estilo',
22 download: 'Force Download', // MISSING
23 displayText: 'Mostrar texto',
24 emailAddress: 'Endereço de email',
25 emailBody: 'Corpo da mensagem',
26 emailSubject: 'Título de mensagem',
27 id: 'ID',
28 info: 'Informação da hiperligação',
29 langCode: 'Código de idioma',
30 langDir: 'Orientação de idioma',
31 langDirLTR: 'Esquerda para a Direita (EPD)',
32 langDirRTL: 'Direita para a Esquerda (DPE)',
33 menu: 'Editar hiperligação',
34 name: 'Nome',
35 noAnchors: '(Não existem âncoras no documento)',
36 noEmail: 'Por favor, escreva o endereço de email',
37 noUrl: 'Por favor, introduza o endereço URL',
38 other: '<outro>',
39 popupDependent: 'Dependente (Netscape)',
40 popupFeatures: 'Características de janela flutuante',
41 popupFullScreen: 'Janela completa (IE)',
42 popupLeft: 'Posição esquerda',
43 popupLocationBar: 'Barra de localização',
44 popupMenuBar: 'Barra de menu',
45 popupResizable: 'Redimensionável',
46 popupScrollBars: 'Barras de deslocamento',
47 popupStatusBar: 'Barra de estado',
48 popupToolbar: 'Barra de ferramentas',
49 popupTop: 'Posição topo',
50 rel: 'Relação',
51 selectAnchor: 'Selecionar âncora',
52 styles: 'Estilo',
53 tabIndex: 'Índice de tabulação',
54 target: 'Alvo',
55 targetFrame: '<frame>',
56 targetFrameName: 'Nome da janela de destino',
57 targetPopup: '<janela de popup>',
58 targetPopupName: 'Nome da janela flutuante',
59 title: 'Hiperligação',
60 toAnchor: 'Ligar a âncora no texto',
61 toEmail: 'Email',
62 toUrl: 'URL',
63 toolbar: 'Hiperligação',
64 type: 'Tipo de hiperligação',
65 unlink: 'Eliminar hiperligação',
66 upload: 'Carregar'
67} );
diff --git a/sources/plugins/link/lang/ro.js b/sources/plugins/link/lang/ro.js
new file mode 100644
index 0000000..a5d79a3
--- /dev/null
+++ b/sources/plugins/link/lang/ro.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ro', {
6 acccessKey: 'Tasta de acces',
7 advanced: 'Avansat',
8 advisoryContentType: 'Tipul consultativ al titlului',
9 advisoryTitle: 'Titlul consultativ',
10 anchor: {
11 toolbar: 'Inserează/Editează ancoră',
12 menu: 'Proprietăţi ancoră',
13 title: 'Proprietăţi ancoră',
14 name: 'Numele ancorei',
15 errorName: 'Vă rugăm scrieţi numele ancorei',
16 remove: 'Elimină ancora'
17 },
18 anchorId: 'după Id-ul elementului',
19 anchorName: 'după numele ancorei',
20 charset: 'Setul de caractere al resursei legate',
21 cssClasses: 'Clasele cu stilul paginii (CSS)',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Adresă de e-mail',
25 emailBody: 'Opțiuni Meniu Contextual',
26 emailSubject: 'Subiectul mesajului',
27 id: 'Id',
28 info: 'Informaţii despre link (Legătură web)',
29 langCode: 'Direcţia cuvintelor',
30 langDir: 'Direcţia cuvintelor',
31 langDirLTR: 'stânga-dreapta (LTR)',
32 langDirRTL: 'dreapta-stânga (RTL)',
33 menu: 'Editează Link',
34 name: 'Nume',
35 noAnchors: '(Nicio ancoră disponibilă în document)',
36 noEmail: 'Vă rugăm să scrieţi adresa de e-mail',
37 noUrl: 'Vă rugăm să scrieţi URL-ul',
38 other: '<alt>',
39 popupDependent: 'Dependent (Netscape)',
40 popupFeatures: 'Proprietăţile ferestrei popup',
41 popupFullScreen: 'Tot ecranul (Full Screen)(IE)',
42 popupLeft: 'Poziţia la stânga',
43 popupLocationBar: 'Bara de locaţie',
44 popupMenuBar: 'Bara de meniu',
45 popupResizable: 'Redimensionabil',
46 popupScrollBars: 'Bare de derulare',
47 popupStatusBar: 'Bara de status',
48 popupToolbar: 'Bara de opţiuni',
49 popupTop: 'Poziţia la dreapta',
50 rel: 'Relație',
51 selectAnchor: 'Selectaţi o ancoră',
52 styles: 'Stil',
53 tabIndex: 'Indexul tabului',
54 target: 'Ţintă (Target)',
55 targetFrame: '<frame>',
56 targetFrameName: 'Numele frameului ţintă',
57 targetPopup: '<fereastra popup>',
58 targetPopupName: 'Numele ferestrei popup',
59 title: 'Link (Legătură web)',
60 toAnchor: 'Ancoră în această pagină',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Inserează/Editează link (legătură web)',
64 type: 'Tipul link-ului (al legăturii web)',
65 unlink: 'Înlătură link (legătură web)',
66 upload: 'Încarcă'
67} );
diff --git a/sources/plugins/link/lang/ru.js b/sources/plugins/link/lang/ru.js
new file mode 100644
index 0000000..7f4b775
--- /dev/null
+++ b/sources/plugins/link/lang/ru.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ru', {
6 acccessKey: 'Клавиша доступа',
7 advanced: 'Дополнительно',
8 advisoryContentType: 'Тип содержимого',
9 advisoryTitle: 'Заголовок',
10 anchor: {
11 toolbar: 'Вставить / редактировать якорь',
12 menu: 'Изменить якорь',
13 title: 'Свойства якоря',
14 name: 'Имя якоря',
15 errorName: 'Пожалуйста, введите имя якоря',
16 remove: 'Удалить якорь'
17 },
18 anchorId: 'По идентификатору',
19 anchorName: 'По имени',
20 charset: 'Кодировка ресурса',
21 cssClasses: 'Классы CSS',
22 download: 'Force Download', // MISSING
23 displayText: 'Отображаемый текст',
24 emailAddress: 'Email адрес',
25 emailBody: 'Текст сообщения',
26 emailSubject: 'Тема сообщения',
27 id: 'Идентификатор',
28 info: 'Информация о ссылке',
29 langCode: 'Код языка',
30 langDir: 'Направление текста',
31 langDirLTR: 'Слева направо (LTR)',
32 langDirRTL: 'Справа налево (RTL)',
33 menu: 'Редактировать ссылку',
34 name: 'Имя',
35 noAnchors: '(В документе нет ни одного якоря)',
36 noEmail: 'Пожалуйста, введите email адрес',
37 noUrl: 'Пожалуйста, введите ссылку',
38 other: '<другой>',
39 popupDependent: 'Зависимое (Netscape)',
40 popupFeatures: 'Параметры всплывающего окна',
41 popupFullScreen: 'Полноэкранное (IE)',
42 popupLeft: 'Отступ слева',
43 popupLocationBar: 'Панель адреса',
44 popupMenuBar: 'Панель меню',
45 popupResizable: 'Изменяемый размер',
46 popupScrollBars: 'Полосы прокрутки',
47 popupStatusBar: 'Строка состояния',
48 popupToolbar: 'Панель инструментов',
49 popupTop: 'Отступ сверху',
50 rel: 'Отношение',
51 selectAnchor: 'Выберите якорь',
52 styles: 'Стиль',
53 tabIndex: 'Последовательность перехода',
54 target: 'Цель',
55 targetFrame: '<фрейм>',
56 targetFrameName: 'Имя целевого фрейма',
57 targetPopup: '<всплывающее окно>',
58 targetPopupName: 'Имя всплывающего окна',
59 title: 'Ссылка',
60 toAnchor: 'Ссылка на якорь в тексте',
61 toEmail: 'Email',
62 toUrl: 'Ссылка',
63 toolbar: 'Вставить/Редактировать ссылку',
64 type: 'Тип ссылки',
65 unlink: 'Убрать ссылку',
66 upload: 'Загрузка'
67} );
diff --git a/sources/plugins/link/lang/si.js b/sources/plugins/link/lang/si.js
new file mode 100644
index 0000000..7ad9935
--- /dev/null
+++ b/sources/plugins/link/lang/si.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'si', {
6 acccessKey: 'ප්‍රවේශ යතුර',
7 advanced: 'දීය',
8 advisoryContentType: 'උපදේශාත්මක අන්තර්ගත ආකාරය',
9 advisoryTitle: 'උපදේශාත්මක නාමය',
10 anchor: {
11 toolbar: 'ආධාරය',
12 menu: 'ආධාරය වෙනස් කිරීම',
13 title: 'ආධාරක ',
14 name: 'ආධාරකයේ නාමය',
15 errorName: 'කරුණාකර ආධාරකයේ නාමය ඇතුල් කරන්න',
16 remove: 'ආධාරකය ඉවත් කිරීම'
17 },
18 anchorId: 'By Element Id', // MISSING
19 anchorName: 'By Anchor Name', // MISSING
20 charset: 'Linked Resource Charset', // MISSING
21 cssClasses: 'විලාසපත්‍ර පන්තිය',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail Address', // MISSING
25 emailBody: 'Message Body', // MISSING
26 emailSubject: 'Message Subject', // MISSING
27 id: 'අංකය',
28 info: 'Link Info', // MISSING
29 langCode: 'භාෂා කේතය',
30 langDir: 'භාෂා දිශාව',
31 langDirLTR: 'වමේසිට දකුණුට',
32 langDirRTL: 'දකුණේ සිට වමට',
33 menu: 'Edit Link', // MISSING
34 name: 'නම',
35 noAnchors: '(No anchors available in the document)', // MISSING
36 noEmail: 'Please type the e-mail address', // MISSING
37 noUrl: 'Please type the link URL', // MISSING
38 other: '<other>', // MISSING
39 popupDependent: 'Dependent (Netscape)', // MISSING
40 popupFeatures: 'Popup Window Features', // MISSING
41 popupFullScreen: 'Full Screen (IE)', // MISSING
42 popupLeft: 'Left Position', // MISSING
43 popupLocationBar: 'Location Bar', // MISSING
44 popupMenuBar: 'Menu Bar', // MISSING
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Scroll Bars', // MISSING
47 popupStatusBar: 'Status Bar', // MISSING
48 popupToolbar: 'Toolbar', // MISSING
49 popupTop: 'Top Position', // MISSING
50 rel: 'Relationship', // MISSING
51 selectAnchor: 'Select an Anchor', // MISSING
52 styles: 'විලාසය',
53 tabIndex: 'Tab Index', // MISSING
54 target: 'අරමුණ',
55 targetFrame: '<frame>', // MISSING
56 targetFrameName: 'Target Frame Name', // MISSING
57 targetPopup: '<popup window>', // MISSING
58 targetPopupName: 'Popup Window Name', // MISSING
59 title: 'සබැඳිය',
60 toAnchor: 'Link to anchor in the text', // MISSING
61 toEmail: 'E-mail', // MISSING
62 toUrl: 'URL',
63 toolbar: 'සබැඳිය',
64 type: 'Link Type', // MISSING
65 unlink: 'Unlink', // MISSING
66 upload: 'උඩුගතකිරීම'
67} );
diff --git a/sources/plugins/link/lang/sk.js b/sources/plugins/link/lang/sk.js
new file mode 100644
index 0000000..87b60bd
--- /dev/null
+++ b/sources/plugins/link/lang/sk.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'sk', {
6 acccessKey: 'Prístupový kľúč',
7 advanced: 'Rozšírené',
8 advisoryContentType: 'Pomocný typ obsahu',
9 advisoryTitle: 'Pomocný titulok',
10 anchor: {
11 toolbar: 'Kotva',
12 menu: 'Upraviť kotvu',
13 title: 'Vlastnosti kotvy',
14 name: 'Názov kotvy',
15 errorName: 'Zadajte prosím názov kotvy',
16 remove: 'Odstrániť kotvu'
17 },
18 anchorId: 'Podľa Id objektu',
19 anchorName: 'Podľa mena kotvy',
20 charset: 'Priradená znaková sada',
21 cssClasses: 'Triedy štýlu',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mailová adresa',
25 emailBody: 'Telo správy',
26 emailSubject: 'Predmet správy',
27 id: 'Id',
28 info: 'Informácie o odkaze',
29 langCode: 'Orientácia jazyka',
30 langDir: 'Orientácia jazyka',
31 langDirLTR: 'Zľava doprava (LTR)',
32 langDirRTL: 'Sprava doľava (RTL)',
33 menu: 'Upraviť odkaz',
34 name: 'Názov',
35 noAnchors: '(V dokumente nie sú dostupné žiadne kotvy)',
36 noEmail: 'Zadajte prosím e-mailovú adresu',
37 noUrl: 'Zadajte prosím URL odkazu',
38 other: '<iný>',
39 popupDependent: 'Závislosť (Netscape)',
40 popupFeatures: 'Vlastnosti vyskakovacieho okna',
41 popupFullScreen: 'Celá obrazovka (IE)',
42 popupLeft: 'Ľavý okraj',
43 popupLocationBar: 'Panel umiestnenia (location bar)',
44 popupMenuBar: 'Panel ponuky (menu bar)',
45 popupResizable: 'Meniteľná veľkosť (resizable)',
46 popupScrollBars: 'Posuvníky (scroll bars)',
47 popupStatusBar: 'Stavový riadok (status bar)',
48 popupToolbar: 'Panel nástrojov (toolbar)',
49 popupTop: 'Horný okraj',
50 rel: 'Vzťah (rel)',
51 selectAnchor: 'Vybrať kotvu',
52 styles: 'Štýl',
53 tabIndex: 'Poradie prvku (tab index)',
54 target: 'Cieľ',
55 targetFrame: '<rámec>',
56 targetFrameName: 'Názov rámu cieľa',
57 targetPopup: '<vyskakovacie okno>',
58 targetPopupName: 'Názov vyskakovacieho okna',
59 title: 'Odkaz',
60 toAnchor: 'Odkaz na kotvu v texte',
61 toEmail: 'E-mail',
62 toUrl: 'URL',
63 toolbar: 'Odkaz',
64 type: 'Typ odkazu',
65 unlink: 'Odstrániť odkaz',
66 upload: 'Nahrať'
67} );
diff --git a/sources/plugins/link/lang/sl.js b/sources/plugins/link/lang/sl.js
new file mode 100644
index 0000000..911203f
--- /dev/null
+++ b/sources/plugins/link/lang/sl.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'sl', {
6 acccessKey: 'Tipka za dostop',
7 advanced: 'Napredno',
8 advisoryContentType: 'Predlagana vrsta vsebine',
9 advisoryTitle: 'Predlagani naslov',
10 anchor: {
11 toolbar: 'Sidro',
12 menu: 'Uredi sidro',
13 title: 'Lastnosti sidra',
14 name: 'Ime sidra',
15 errorName: 'Prosimo, vnesite ime sidra',
16 remove: 'Odstrani sidro'
17 },
18 anchorId: 'Po ID-ju elementa',
19 anchorName: 'Po imenu sidra',
20 charset: 'Nabor znakov povezanega vira',
21 cssClasses: 'Razredi slogovne predloge',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-poštni naslov',
25 emailBody: 'Telo sporočila',
26 emailSubject: 'Zadeva sporočila',
27 id: 'Id',
28 info: 'Podatki o povezavi',
29 langCode: 'Koda jezika',
30 langDir: 'Smer jezika',
31 langDirLTR: 'Od leve proti desni (LTR)',
32 langDirRTL: 'Od desne proti levi (RTL)',
33 menu: 'Uredi povezavo',
34 name: 'Ime',
35 noAnchors: '(V tem dokumentu ni sider)',
36 noEmail: 'Vnesite e-poštni naslov',
37 noUrl: 'Vnesite URL povezave',
38 other: '<drugo>',
39 popupDependent: 'Podokno (Netscape)',
40 popupFeatures: 'Značilnosti pojavnega okna',
41 popupFullScreen: 'Celozaslonsko (IE)',
42 popupLeft: 'Lega levo',
43 popupLocationBar: 'Naslovna vrstica',
44 popupMenuBar: 'Menijska vrstica',
45 popupResizable: 'Spremenljive velikosti',
46 popupScrollBars: 'Drsniki',
47 popupStatusBar: 'Vrstica stanja',
48 popupToolbar: 'Orodna vrstica',
49 popupTop: 'Lega na vrhu',
50 rel: 'Odnos',
51 selectAnchor: 'Izberite sidro',
52 styles: 'Slog',
53 tabIndex: 'Številka tabulatorja',
54 target: 'Cilj',
55 targetFrame: '<okvir>',
56 targetFrameName: 'Ime ciljnega okvirja',
57 targetPopup: '<pojavno okno>',
58 targetPopupName: 'Ime pojavnega okna',
59 title: 'Povezava',
60 toAnchor: 'Sidro na tej strani',
61 toEmail: 'E-pošta',
62 toUrl: 'URL',
63 toolbar: 'Vstavi/uredi povezavo',
64 type: 'Vrsta povezave',
65 unlink: 'Odstrani povezavo',
66 upload: 'Naloži'
67} );
diff --git a/sources/plugins/link/lang/sq.js b/sources/plugins/link/lang/sq.js
new file mode 100644
index 0000000..83b2fb7
--- /dev/null
+++ b/sources/plugins/link/lang/sq.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'sq', {
6 acccessKey: 'Sipas ID-së së Elementit',
7 advanced: 'Të përparuara',
8 advisoryContentType: 'Lloji i Përmbajtjes Këshillimore',
9 advisoryTitle: 'Titull',
10 anchor: {
11 toolbar: 'Spirancë',
12 menu: 'Redakto Spirancën',
13 title: 'Anchor Properties', // MISSING
14 name: 'Emri i Spirancës',
15 errorName: 'Ju lutemi shkruani emrin e spirancës',
16 remove: 'Largo Spirancën'
17 },
18 anchorId: 'Sipas ID-së së Elementit',
19 anchorName: 'Sipas Emrit të Spirancës',
20 charset: 'Seti i Karaktereve të Burimeve të Nëdlidhura',
21 cssClasses: 'Klasa stili CSS',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Posta Elektronike',
25 emailBody: 'Trupi i Porosisë',
26 emailSubject: 'Titulli i Porosisë',
27 id: 'Id',
28 info: 'Informacione të Nyjes',
29 langCode: 'Kod gjuhe',
30 langDir: 'Drejtim teksti',
31 langDirLTR: 'Nga e majta në të djathë (LTR)',
32 langDirRTL: 'Nga e djathta në të majtë (RTL)',
33 menu: 'Redakto Nyjen',
34 name: 'Emër',
35 noAnchors: '(Nuk ka asnjë spirancë në dokument)',
36 noEmail: 'Ju lutemi shkruani postën elektronike',
37 noUrl: 'Ju lutemi shkruani URL-në e nyjes',
38 other: '<tjetër>',
39 popupDependent: 'E Varur (Netscape)',
40 popupFeatures: 'Karakteristikat e Dritares së Dialogut',
41 popupFullScreen: 'Ekran i Plotë (IE)',
42 popupLeft: 'Pozita Majtas',
43 popupLocationBar: 'Shiriti i Lokacionit',
44 popupMenuBar: 'Shiriti i Menysë',
45 popupResizable: 'I ndryshueshëm',
46 popupScrollBars: 'Shiritat zvarritës',
47 popupStatusBar: 'Shiriti i Statutit',
48 popupToolbar: 'Shiriti i Mejteve',
49 popupTop: 'Top Pozita',
50 rel: 'Marrëdhëniet',
51 selectAnchor: 'Përzgjidh një Spirancë',
52 styles: 'Stil',
53 tabIndex: 'Indeksi i fletave',
54 target: 'Objektivi',
55 targetFrame: '<frame>',
56 targetFrameName: 'Emri i Kornizës së Synuar',
57 targetPopup: '<popup window>',
58 targetPopupName: 'Emri i Dritares së Dialogut',
59 title: 'Nyja',
60 toAnchor: 'Lidhu me spirancën në tekst',
61 toEmail: 'Posta Elektronike',
62 toUrl: 'URL',
63 toolbar: 'Nyja',
64 type: 'Lloji i Nyjes',
65 unlink: 'Largo Nyjen',
66 upload: 'Ngarko'
67} );
diff --git a/sources/plugins/link/lang/sr-latn.js b/sources/plugins/link/lang/sr-latn.js
new file mode 100644
index 0000000..8f6f6a7
--- /dev/null
+++ b/sources/plugins/link/lang/sr-latn.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'sr-latn', {
6 acccessKey: 'Pristupni taster',
7 advanced: 'Napredni tagovi',
8 advisoryContentType: 'Advisory vrsta sadržaja',
9 advisoryTitle: 'Advisory naslov',
10 anchor: {
11 toolbar: 'Unesi/izmeni sidro',
12 menu: 'Osobine sidra',
13 title: 'Osobine sidra',
14 name: 'Naziv sidra',
15 errorName: 'Unesite naziv sidra',
16 remove: 'Ukloni sidro'
17 },
18 anchorId: 'Po Id-u elementa',
19 anchorName: 'Po nazivu sidra',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Stylesheet klase',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'E-Mail adresa',
25 emailBody: 'Sadržaj poruke',
26 emailSubject: 'Naslov',
27 id: 'Id',
28 info: 'Link Info',
29 langCode: 'Smer jezika',
30 langDir: 'Smer jezika',
31 langDirLTR: 'S leva na desno (LTR)',
32 langDirRTL: 'S desna na levo (RTL)',
33 menu: 'Izmeni link',
34 name: 'Naziv',
35 noAnchors: '(Nema dostupnih sidra)',
36 noEmail: 'Otkucajte adresu elektronske pote',
37 noUrl: 'Unesite URL linka',
38 other: '<остало>',
39 popupDependent: 'Zavisno (Netscape)',
40 popupFeatures: 'Mogućnosti popup prozora',
41 popupFullScreen: 'Prikaz preko celog ekrana (IE)',
42 popupLeft: 'Od leve ivice ekrana (px)',
43 popupLocationBar: 'Lokacija',
44 popupMenuBar: 'Kontekstni meni',
45 popupResizable: 'Promenljive veličine',
46 popupScrollBars: 'Scroll bar',
47 popupStatusBar: 'Statusna linija',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Od vrha ekrana (px)',
50 rel: 'Odnos',
51 selectAnchor: 'Odaberi sidro',
52 styles: 'Stil',
53 tabIndex: 'Tab indeks',
54 target: 'Meta',
55 targetFrame: '<okvir>',
56 targetFrameName: 'Naziv odredišnog frejma',
57 targetPopup: '<popup prozor>',
58 targetPopupName: 'Naziv popup prozora',
59 title: 'Link',
60 toAnchor: 'Sidro na ovoj stranici',
61 toEmail: 'E-Mail',
62 toUrl: 'URL',
63 toolbar: 'Unesi/izmeni link',
64 type: 'Vrsta linka',
65 unlink: 'Ukloni link',
66 upload: 'Pošalji'
67} );
diff --git a/sources/plugins/link/lang/sr.js b/sources/plugins/link/lang/sr.js
new file mode 100644
index 0000000..18689da
--- /dev/null
+++ b/sources/plugins/link/lang/sr.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'sr', {
6 acccessKey: 'Приступни тастер',
7 advanced: 'Напредни тагови',
8 advisoryContentType: 'Advisory врста садржаја',
9 advisoryTitle: 'Advisory наслов',
10 anchor: {
11 toolbar: 'Унеси/измени сидро',
12 menu: 'Особине сидра',
13 title: 'Особине сидра',
14 name: 'Име сидра',
15 errorName: 'Молимо Вас да унесете име сидра',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'Пo Ид-jу елемента',
19 anchorName: 'По називу сидра',
20 charset: 'Linked Resource Charset',
21 cssClasses: 'Stylesheet класе',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Адреса електронске поште',
25 emailBody: 'Садржај поруке',
26 emailSubject: 'Наслов',
27 id: 'Ид',
28 info: 'Линк инфо',
29 langCode: 'Смер језика',
30 langDir: 'Смер језика',
31 langDirLTR: 'С лева на десно (LTR)',
32 langDirRTL: 'С десна на лево (RTL)',
33 menu: 'Промени линк',
34 name: 'Назив',
35 noAnchors: '(Нема доступних сидра)',
36 noEmail: 'Откуцајте адресу електронске поште',
37 noUrl: 'Унесите УРЛ линка',
38 other: '<друго>',
39 popupDependent: 'Зависно (Netscape)',
40 popupFeatures: 'Могућности искачућег прозора',
41 popupFullScreen: 'Приказ преко целог екрана (ИE)',
42 popupLeft: 'Од леве ивице екрана (пиксела)',
43 popupLocationBar: 'Локација',
44 popupMenuBar: 'Контекстни мени',
45 popupResizable: 'Величина се мења',
46 popupScrollBars: 'Скрол бар',
47 popupStatusBar: 'Статусна линија',
48 popupToolbar: 'Toolbar',
49 popupTop: 'Од врха екрана (пиксела)',
50 rel: 'Однос',
51 selectAnchor: 'Одабери сидро',
52 styles: 'Стил',
53 tabIndex: 'Таб индекс',
54 target: 'Meтa',
55 targetFrame: '<оквир>',
56 targetFrameName: 'Назив одредишног фрејма',
57 targetPopup: '<искачући прозор>',
58 targetPopupName: 'Назив искачућег прозора',
59 title: 'Линк',
60 toAnchor: 'Сидро на овој страници',
61 toEmail: 'Eлектронска пошта',
62 toUrl: 'УРЛ',
63 toolbar: 'Унеси/измени линк',
64 type: 'Врста линка',
65 unlink: 'Уклони линк',
66 upload: 'Пошаљи'
67} );
diff --git a/sources/plugins/link/lang/sv.js b/sources/plugins/link/lang/sv.js
new file mode 100644
index 0000000..bc9f4c2
--- /dev/null
+++ b/sources/plugins/link/lang/sv.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'sv', {
6 acccessKey: 'Behörighetsnyckel',
7 advanced: 'Avancerad',
8 advisoryContentType: 'Innehållstyp',
9 advisoryTitle: 'Titel',
10 anchor: {
11 toolbar: 'Infoga/Redigera ankarlänk',
12 menu: 'Egenskaper för ankarlänk',
13 title: 'Egenskaper för ankarlänk',
14 name: 'Ankarnamn',
15 errorName: 'Var god ange ett ankarnamn',
16 remove: 'Radera ankare'
17 },
18 anchorId: 'Efter element-id',
19 anchorName: 'Efter ankarnamn',
20 charset: 'Teckenuppställning',
21 cssClasses: 'Stilmall',
22 download: 'Tvinga nerladdning',
23 displayText: 'Visningstext',
24 emailAddress: 'E-postadress',
25 emailBody: 'Innehåll',
26 emailSubject: 'Ämne',
27 id: 'Id',
28 info: 'Länkinformation',
29 langCode: 'Språkkod',
30 langDir: 'Språkriktning',
31 langDirLTR: 'Vänster till höger (VTH)',
32 langDirRTL: 'Höger till vänster (HTV)',
33 menu: 'Redigera länk',
34 name: 'Namn',
35 noAnchors: '(Inga ankare kunde hittas)',
36 noEmail: 'Var god ange e-postadress',
37 noUrl: 'Var god ange länkens URL',
38 other: '<annan>',
39 popupDependent: 'Beroende (endast Netscape)',
40 popupFeatures: 'Popup-fönstrets egenskaper',
41 popupFullScreen: 'Helskärm (endast IE)',
42 popupLeft: 'Position från vänster',
43 popupLocationBar: 'Adressfält',
44 popupMenuBar: 'Menyfält',
45 popupResizable: 'Skalbart',
46 popupScrollBars: 'Scrolllista',
47 popupStatusBar: 'Statusfält',
48 popupToolbar: 'Verktygsfält',
49 popupTop: 'Position från sidans topp',
50 rel: 'Förhållande',
51 selectAnchor: 'Välj ett ankare',
52 styles: 'Stilmall',
53 tabIndex: 'Tabindex',
54 target: 'Mål',
55 targetFrame: '<ram>',
56 targetFrameName: 'Målets ramnamn',
57 targetPopup: '<popup-fönster>',
58 targetPopupName: 'Popup-fönstrets namn',
59 title: 'Länk',
60 toAnchor: 'Länk till ankare i texten',
61 toEmail: 'E-post',
62 toUrl: 'URL',
63 toolbar: 'Infoga/Redigera länk',
64 type: 'Länktyp',
65 unlink: 'Radera länk',
66 upload: 'Ladda upp'
67} );
diff --git a/sources/plugins/link/lang/th.js b/sources/plugins/link/lang/th.js
new file mode 100644
index 0000000..593838d
--- /dev/null
+++ b/sources/plugins/link/lang/th.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'th', {
6 acccessKey: 'แอคเซส คีย์',
7 advanced: 'ขั้นสูง',
8 advisoryContentType: 'ชนิดของคำเกริ่นนำ',
9 advisoryTitle: 'คำเกริ่นนำ',
10 anchor: {
11 toolbar: 'แทรก/แก้ไข Anchor',
12 menu: 'รายละเอียด Anchor',
13 title: 'รายละเอียด Anchor',
14 name: 'ชื่อ Anchor',
15 errorName: 'กรุณาระบุชื่อของ Anchor',
16 remove: 'Remove Anchor'
17 },
18 anchorId: 'ไอดี',
19 anchorName: 'ชื่อ',
20 charset: 'ลิงค์เชื่อมโยงไปยังชุดตัวอักษร',
21 cssClasses: 'คลาสของไฟล์กำหนดลักษณะการแสดงผล',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'อีเมล์ (E-Mail)',
25 emailBody: 'ข้อความ',
26 emailSubject: 'หัวเรื่อง',
27 id: 'ไอดี',
28 info: 'รายละเอียด',
29 langCode: 'การเขียน-อ่านภาษา',
30 langDir: 'การเขียน-อ่านภาษา',
31 langDirLTR: 'จากซ้ายไปขวา (LTR)',
32 langDirRTL: 'จากขวามาซ้าย (RTL)',
33 menu: 'แก้ไข ลิงค์',
34 name: 'ชื่อ',
35 noAnchors: '(ยังไม่มีจุดเชื่อมโยงภายในหน้าเอกสารนี้)',
36 noEmail: 'กรุณาระบุอีเมล์ (E-mail)',
37 noUrl: 'กรุณาระบุที่อยู่อ้างอิงออนไลน์ (URL)',
38 other: '<อื่น ๆ>',
39 popupDependent: 'แสดงเต็มหน้าจอ (Netscape)',
40 popupFeatures: 'คุณสมบัติของหน้าจอเล็ก (Pop-up)',
41 popupFullScreen: 'แสดงเต็มหน้าจอ (IE5.5++ เท่านั้น)',
42 popupLeft: 'พิกัดซ้าย (Left Position)',
43 popupLocationBar: 'แสดงที่อยู่ของไฟล์',
44 popupMenuBar: 'แสดงแถบเมนู',
45 popupResizable: 'สามารถปรับขนาดได้',
46 popupScrollBars: 'แสดงแถบเลื่อน',
47 popupStatusBar: 'แสดงแถบสถานะ',
48 popupToolbar: 'แสดงแถบเครื่องมือ',
49 popupTop: 'พิกัดบน (Top Position)',
50 rel: 'ความสัมพันธ์',
51 selectAnchor: 'ระบุข้อมูลของจุดเชื่อมโยง (Anchor)',
52 styles: 'ลักษณะการแสดงผล',
53 tabIndex: 'ลำดับของ แท็บ',
54 target: 'การเปิดหน้าลิงค์',
55 targetFrame: '<เปิดในเฟรม>',
56 targetFrameName: 'ชื่อทาร์เก็ตเฟรม',
57 targetPopup: '<เปิดหน้าจอเล็ก (Pop-up)>',
58 targetPopupName: 'ระบุชื่อหน้าจอเล็ก (Pop-up)',
59 title: 'ลิงค์เชื่อมโยงเว็บ อีเมล์ รูปภาพ หรือไฟล์อื่นๆ',
60 toAnchor: 'จุดเชื่อมโยง (Anchor)',
61 toEmail: 'ส่งอีเมล์ (E-Mail)',
62 toUrl: 'ที่อยู่อ้างอิง URL',
63 toolbar: 'แทรก/แก้ไข ลิงค์',
64 type: 'ประเภทของลิงค์',
65 unlink: 'ลบ ลิงค์',
66 upload: 'อัพโหลดไฟล์'
67} );
diff --git a/sources/plugins/link/lang/tr.js b/sources/plugins/link/lang/tr.js
new file mode 100644
index 0000000..424ad7b
--- /dev/null
+++ b/sources/plugins/link/lang/tr.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'tr', {
6 acccessKey: 'Erişim Tuşu',
7 advanced: 'Gelişmiş',
8 advisoryContentType: 'Danışma İçerik Türü',
9 advisoryTitle: 'Danışma Başlığı',
10 anchor: {
11 toolbar: 'Bağlantı Ekle/Düzenle',
12 menu: 'Bağlantı Özellikleri',
13 title: 'Bağlantı Özellikleri',
14 name: 'Bağlantı Adı',
15 errorName: 'Lütfen bağlantı için ad giriniz',
16 remove: 'Bağlantıyı Kaldır'
17 },
18 anchorId: 'Eleman Kimlik Numarası ile',
19 anchorName: 'Bağlantı Adı ile',
20 charset: 'Bağlı Kaynak Karakter Gurubu',
21 cssClasses: 'Biçem Sayfası Sınıfları',
22 download: 'İndirmeye Zorla',
23 displayText: 'Gösterim Metni',
24 emailAddress: 'E-Posta Adresi',
25 emailBody: 'İleti Gövdesi',
26 emailSubject: 'İleti Konusu',
27 id: 'Id',
28 info: 'Link Bilgisi',
29 langCode: 'Dil Yönü',
30 langDir: 'Dil Yönü',
31 langDirLTR: 'Soldan Sağa (LTR)',
32 langDirRTL: 'Sağdan Sola (RTL)',
33 menu: 'Link Düzenle',
34 name: 'Ad',
35 noAnchors: '(Bu belgede hiç çapa yok)',
36 noEmail: 'Lütfen E-posta adresini yazın',
37 noUrl: 'Lütfen Link URL\'sini yazın',
38 other: '<diğer>',
39 popupDependent: 'Bağımlı (Netscape)',
40 popupFeatures: 'Yeni Açılan Pencere Özellikleri',
41 popupFullScreen: 'Tam Ekran (IE)',
42 popupLeft: 'Sola Göre Konum',
43 popupLocationBar: 'Yer Çubuğu',
44 popupMenuBar: 'Menü Çubuğu',
45 popupResizable: 'Resizable',
46 popupScrollBars: 'Kaydırma Çubukları',
47 popupStatusBar: 'Durum Çubuğu',
48 popupToolbar: 'Araç Çubuğu',
49 popupTop: 'Yukarıya Göre Konum',
50 rel: 'İlişki',
51 selectAnchor: 'Bağlantı Seç',
52 styles: 'Biçem',
53 tabIndex: 'Sekme İndeksi',
54 target: 'Hedef',
55 targetFrame: '<çerçeve>',
56 targetFrameName: 'Hedef Çerçeve Adı',
57 targetPopup: '<yeni açılan pencere>',
58 targetPopupName: 'Yeni Açılan Pencere Adı',
59 title: 'Link',
60 toAnchor: 'Bu sayfada çapa',
61 toEmail: 'E-Posta',
62 toUrl: 'URL',
63 toolbar: 'Link Ekle/Düzenle',
64 type: 'Link Türü',
65 unlink: 'Köprü Kaldır',
66 upload: 'Karşıya Yükle'
67} );
diff --git a/sources/plugins/link/lang/tt.js b/sources/plugins/link/lang/tt.js
new file mode 100644
index 0000000..25bd354
--- /dev/null
+++ b/sources/plugins/link/lang/tt.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'tt', {
6 acccessKey: 'Access Key', // MISSING
7 advanced: 'Киңәйтелгән көйләүләр',
8 advisoryContentType: 'Advisory Content Type', // MISSING
9 advisoryTitle: 'Киңәш исем',
10 anchor: {
11 toolbar: 'Якорь',
12 menu: 'Якорьне үзгәртү',
13 title: 'Якорь үзлекләре',
14 name: 'Якорь исеме',
15 errorName: 'Якорьнең исемен языгыз',
16 remove: 'Якорьне бетерү'
17 },
18 anchorId: 'Элемент идентификаторы буенча',
19 anchorName: 'Якорь исеме буенча',
20 charset: 'Linked Resource Charset', // MISSING
21 cssClasses: 'Стильләр класслары',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Электрон почта адресы',
25 emailBody: 'Хат эчтәлеге',
26 emailSubject: 'Хат темасы',
27 id: 'Идентификатор',
28 info: 'Сылталама тасвирламасы',
29 langCode: 'Тел коды',
30 langDir: 'Язылыш юнəлеше',
31 langDirLTR: 'Сулдан уңга язылыш (LTR)',
32 langDirRTL: 'Уңнан сулга язылыш (RTL)',
33 menu: 'Сылталамаyны үзгәртү',
34 name: 'Исем',
35 noAnchors: '(Әлеге документта якорьләр табылмады)',
36 noEmail: 'Электрон почта адресын языгыз',
37 noUrl: 'Сылталаманы языгыз',
38 other: '<бүтән>',
39 popupDependent: 'Бәйле (Netscape)',
40 popupFeatures: 'Popup Window Features', // MISSING
41 popupFullScreen: 'Тулы экран (IE)',
42 popupLeft: 'Left Position', // MISSING
43 popupLocationBar: 'Location Bar', // MISSING
44 popupMenuBar: 'Menu Bar', // MISSING
45 popupResizable: 'Resizable', // MISSING
46 popupScrollBars: 'Scroll Bars', // MISSING
47 popupStatusBar: 'Status Bar', // MISSING
48 popupToolbar: 'Toolbar', // MISSING
49 popupTop: 'Top Position', // MISSING
50 rel: 'Бәйләнеш',
51 selectAnchor: 'Якорьне сайлау',
52 styles: 'Стиль',
53 tabIndex: 'Tab Index', // MISSING
54 target: 'Максат',
55 targetFrame: '<frame>',
56 targetFrameName: 'Target Frame Name', // MISSING
57 targetPopup: '<popup window>',
58 targetPopupName: 'Попап тәрәзәсе исеме',
59 title: 'Сылталама',
60 toAnchor: 'Якорьне текст белән бәйләү',
61 toEmail: 'Электрон почта',
62 toUrl: 'Сылталама',
63 toolbar: 'Сылталама',
64 type: 'Сылталама төре',
65 unlink: 'Сылталаманы бетерү',
66 upload: 'Йөкләү'
67} );
diff --git a/sources/plugins/link/lang/ug.js b/sources/plugins/link/lang/ug.js
new file mode 100644
index 0000000..3cf75b4
--- /dev/null
+++ b/sources/plugins/link/lang/ug.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'ug', {
6 acccessKey: 'زىيارەت كۇنۇپكا',
7 advanced: 'ئالىي',
8 advisoryContentType: 'مەزمۇن تىپى',
9 advisoryTitle: 'ماۋزۇ',
10 anchor: {
11 toolbar: 'لەڭگەرلىك نۇقتا ئۇلانمىسى قىستۇر/تەھرىرلە',
12 menu: 'لەڭگەرلىك نۇقتا ئۇلانما خاسلىقى',
13 title: 'لەڭگەرلىك نۇقتا ئۇلانما خاسلىقى',
14 name: 'لەڭگەرلىك نۇقتا ئاتى',
15 errorName: 'لەڭگەرلىك نۇقتا ئاتىنى كىرگۈزۈڭ',
16 remove: 'لەڭگەرلىك نۇقتا ئۆچۈر'
17 },
18 anchorId: 'لەڭگەرلىك نۇقتا ID سى بويىچە',
19 anchorName: 'لەڭگەرلىك نۇقتا ئاتى بويىچە',
20 charset: 'ھەرپ كودلىنىشى',
21 cssClasses: 'ئۇسلۇب خىلى ئاتى',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'ئادرېس',
25 emailBody: 'مەزمۇن',
26 emailSubject: 'ماۋزۇ',
27 id: 'ID',
28 info: 'ئۇلانما ئۇچۇرى',
29 langCode: 'تىل كودى',
30 langDir: 'تىل يۆنىلىشى',
31 langDirLTR: 'سولدىن ئوڭغا (LTR)',
32 langDirRTL: 'ئوڭدىن سولغا (RTL)',
33 menu: 'ئۇلانما تەھرىر',
34 name: 'ئات',
35 noAnchors: '(بۇ پۈتۈكتە ئىشلەتكىلى بولىدىغان لەڭگەرلىك نۇقتا يوق)',
36 noEmail: 'ئېلخەت ئادرېسىنى كىرگۈزۈڭ',
37 noUrl: 'ئۇلانما ئادرېسىنى كىرگۈزۈڭ',
38 other: '‹باشقا›',
39 popupDependent: 'تەۋە (NS)',
40 popupFeatures: 'قاڭقىش كۆزنەك خاسلىقى',
41 popupFullScreen: 'پۈتۈن ئېكران (IE)',
42 popupLeft: 'سول',
43 popupLocationBar: 'ئادرېس بالداق',
44 popupMenuBar: 'تىزىملىك بالداق',
45 popupResizable: 'چوڭلۇقى ئۆزگەرتىشچان',
46 popupScrollBars: 'دومىلىما سۈرگۈچ',
47 popupStatusBar: 'ھالەت بالداق',
48 popupToolbar: 'قورال بالداق',
49 popupTop: 'ئوڭ',
50 rel: 'باغلىنىش',
51 selectAnchor: 'بىر لەڭگەرلىك نۇقتا تاللاڭ',
52 styles: 'قۇر ئىچىدىكى ئۇسلۇبى',
53 tabIndex: 'Tab تەرتىپى',
54 target: 'نىشان',
55 targetFrame: '‹كاندۇك›',
56 targetFrameName: 'نىشان كاندۇك ئاتى',
57 targetPopup: '‹قاڭقىش كۆزنەك›',
58 targetPopupName: 'قاڭقىش كۆزنەك ئاتى',
59 title: 'ئۇلانما',
60 toAnchor: 'بەت ئىچىدىكى لەڭگەرلىك نۇقتا ئۇلانمىسى',
61 toEmail: 'ئېلخەت',
62 toUrl: 'ئادرېس',
63 toolbar: 'ئۇلانما قىستۇر/تەھرىرلە',
64 type: 'ئۇلانما تىپى',
65 unlink: 'ئۇلانما بىكار قىل',
66 upload: 'يۈكلە'
67} );
diff --git a/sources/plugins/link/lang/uk.js b/sources/plugins/link/lang/uk.js
new file mode 100644
index 0000000..8322d86
--- /dev/null
+++ b/sources/plugins/link/lang/uk.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'uk', {
6 acccessKey: 'Гаряча клавіша',
7 advanced: 'Додаткове',
8 advisoryContentType: 'Тип вмісту',
9 advisoryTitle: 'Заголовок',
10 anchor: {
11 toolbar: 'Вставити/Редагувати якір',
12 menu: 'Властивості якоря',
13 title: 'Властивості якоря',
14 name: 'Ім\'я якоря',
15 errorName: 'Будь ласка, вкажіть ім\'я якоря',
16 remove: 'Прибрати якір'
17 },
18 anchorId: 'За ідентифікатором елементу',
19 anchorName: 'За ім\'ям елементу',
20 charset: 'Кодування',
21 cssClasses: 'Клас CSS',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Адреса ел. пошти',
25 emailBody: 'Тіло повідомлення',
26 emailSubject: 'Тема листа',
27 id: 'Ідентифікатор',
28 info: 'Інформація посилання',
29 langCode: 'Код мови',
30 langDir: 'Напрямок мови',
31 langDirLTR: 'Зліва направо (LTR)',
32 langDirRTL: 'Справа наліво (RTL)',
33 menu: 'Вставити посилання',
34 name: 'Ім\'я',
35 noAnchors: '(В цьому документі немає якорів)',
36 noEmail: 'Будь ласка, вкажіть адрес ел. пошти',
37 noUrl: 'Будь ласка, вкажіть URL посилання',
38 other: '<інший>',
39 popupDependent: 'Залежний (Netscape)',
40 popupFeatures: 'Властивості випливаючого вікна',
41 popupFullScreen: 'Повний екран (IE)',
42 popupLeft: 'Позиція зліва',
43 popupLocationBar: 'Панель локації',
44 popupMenuBar: 'Панель меню',
45 popupResizable: 'Масштабоване',
46 popupScrollBars: 'Стрічки прокрутки',
47 popupStatusBar: 'Рядок статусу',
48 popupToolbar: 'Панель інструментів',
49 popupTop: 'Позиція зверху',
50 rel: 'Зв\'язок',
51 selectAnchor: 'Оберіть якір',
52 styles: 'Стиль CSS',
53 tabIndex: 'Послідовність переходу',
54 target: 'Ціль',
55 targetFrame: '<фрейм>',
56 targetFrameName: 'Ім\'я цільового фрейму',
57 targetPopup: '<випливаюче вікно>',
58 targetPopupName: 'Ім\'я випливаючого вікна',
59 title: 'Посилання',
60 toAnchor: 'Якір на цю сторінку',
61 toEmail: 'Ел. пошта',
62 toUrl: 'URL',
63 toolbar: 'Вставити/Редагувати посилання',
64 type: 'Тип посилання',
65 unlink: 'Видалити посилання',
66 upload: 'Надіслати'
67} );
diff --git a/sources/plugins/link/lang/vi.js b/sources/plugins/link/lang/vi.js
new file mode 100644
index 0000000..d78012d
--- /dev/null
+++ b/sources/plugins/link/lang/vi.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'vi', {
6 acccessKey: 'Phím hỗ trợ truy cập',
7 advanced: 'Mở rộng',
8 advisoryContentType: 'Nội dung hướng dẫn',
9 advisoryTitle: 'Nhan đề hướng dẫn',
10 anchor: {
11 toolbar: 'Chèn/Sửa điểm neo',
12 menu: 'Thuộc tính điểm neo',
13 title: 'Thuộc tính điểm neo',
14 name: 'Tên của điểm neo',
15 errorName: 'Hãy nhập vào tên của điểm neo',
16 remove: 'Xóa neo'
17 },
18 anchorId: 'Theo định danh thành phần',
19 anchorName: 'Theo tên điểm neo',
20 charset: 'Bảng mã của tài nguyên được liên kết đến',
21 cssClasses: 'Lớp Stylesheet',
22 download: 'Force Download', // MISSING
23 displayText: 'Display Text', // MISSING
24 emailAddress: 'Thư điện tử',
25 emailBody: 'Nội dung thông điệp',
26 emailSubject: 'Tiêu đề thông điệp',
27 id: 'Định danh',
28 info: 'Thông tin liên kết',
29 langCode: 'Mã ngôn ngữ',
30 langDir: 'Hướng ngôn ngữ',
31 langDirLTR: 'Trái sang phải (LTR)',
32 langDirRTL: 'Phải sang trái (RTL)',
33 menu: 'Sửa liên kết',
34 name: 'Tên',
35 noAnchors: '(Không có điểm neo nào trong tài liệu)',
36 noEmail: 'Hãy đưa vào địa chỉ thư điện tử',
37 noUrl: 'Hãy đưa vào đường dẫn liên kết (URL)',
38 other: '<khác>',
39 popupDependent: 'Phụ thuộc (Netscape)',
40 popupFeatures: 'Đặc điểm của cửa sổ Popup',
41 popupFullScreen: 'Toàn màn hình (IE)',
42 popupLeft: 'Vị trí bên trái',
43 popupLocationBar: 'Thanh vị trí',
44 popupMenuBar: 'Thanh Menu',
45 popupResizable: 'Có thể thay đổi kích cỡ',
46 popupScrollBars: 'Thanh cuộn',
47 popupStatusBar: 'Thanh trạng thái',
48 popupToolbar: 'Thanh công cụ',
49 popupTop: 'Vị trí phía trên',
50 rel: 'Quan hệ',
51 selectAnchor: 'Chọn một điểm neo',
52 styles: 'Kiểu (style)',
53 tabIndex: 'Chỉ số của Tab',
54 target: 'Đích',
55 targetFrame: '<khung>',
56 targetFrameName: 'Tên khung đích',
57 targetPopup: '<cửa sổ popup>',
58 targetPopupName: 'Tên cửa sổ Popup',
59 title: 'Liên kết',
60 toAnchor: 'Neo trong trang này',
61 toEmail: 'Thư điện tử',
62 toUrl: 'URL',
63 toolbar: 'Chèn/Sửa liên kết',
64 type: 'Kiểu liên kết',
65 unlink: 'Xoá liên kết',
66 upload: 'Tải lên'
67} );
diff --git a/sources/plugins/link/lang/zh-cn.js b/sources/plugins/link/lang/zh-cn.js
new file mode 100644
index 0000000..6da9e96
--- /dev/null
+++ b/sources/plugins/link/lang/zh-cn.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'zh-cn', {
6 acccessKey: '访问键',
7 advanced: '高级',
8 advisoryContentType: '内容类型',
9 advisoryTitle: '标题',
10 anchor: {
11 toolbar: '插入/编辑锚点链接',
12 menu: '锚点链接属性',
13 title: '锚点链接属性',
14 name: '锚点名称',
15 errorName: '请输入锚点名称',
16 remove: '删除锚点'
17 },
18 anchorId: '按锚点 ID',
19 anchorName: '按锚点名称',
20 charset: '字符编码',
21 cssClasses: '样式类名称',
22 download: '强制下载',
23 displayText: '显示文本',
24 emailAddress: '地址',
25 emailBody: '内容',
26 emailSubject: '主题',
27 id: 'ID',
28 info: '超链接信息',
29 langCode: '语言代码',
30 langDir: '语言方向',
31 langDirLTR: '从左到右 (LTR)',
32 langDirRTL: '从右到左 (RTL)',
33 menu: '编辑超链接',
34 name: '名称',
35 noAnchors: '(此文档没有可用的锚点)',
36 noEmail: '请输入电子邮件地址',
37 noUrl: '请输入超链接地址',
38 other: '<其他>',
39 popupDependent: '依附 (NS)',
40 popupFeatures: '弹出窗口属性',
41 popupFullScreen: '全屏 (IE)',
42 popupLeft: '左',
43 popupLocationBar: '地址栏',
44 popupMenuBar: '菜单栏',
45 popupResizable: '可缩放',
46 popupScrollBars: '滚动条',
47 popupStatusBar: '状态栏',
48 popupToolbar: '工具栏',
49 popupTop: '右',
50 rel: '关联',
51 selectAnchor: '选择一个锚点',
52 styles: '行内样式',
53 tabIndex: 'Tab 键次序',
54 target: '目标',
55 targetFrame: '<框架>',
56 targetFrameName: '目标框架名称',
57 targetPopup: '<弹出窗口>',
58 targetPopupName: '弹出窗口名称',
59 title: '超链接',
60 toAnchor: '页内锚点链接',
61 toEmail: '电子邮件',
62 toUrl: '地址',
63 toolbar: '插入/编辑超链接',
64 type: '超链接类型',
65 unlink: '取消超链接',
66 upload: '上传'
67} );
diff --git a/sources/plugins/link/lang/zh.js b/sources/plugins/link/lang/zh.js
new file mode 100644
index 0000000..5ba3d1c
--- /dev/null
+++ b/sources/plugins/link/lang/zh.js
@@ -0,0 +1,67 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'link', 'zh', {
6 acccessKey: '便捷鍵',
7 advanced: '進階',
8 advisoryContentType: '建議內容類型',
9 advisoryTitle: '標題',
10 anchor: {
11 toolbar: '錨點',
12 menu: '編輯錨點',
13 title: '錨點內容',
14 name: '錨點名稱',
15 errorName: '請輸入錨點名稱',
16 remove: '移除錨點'
17 },
18 anchorId: '依元件編號',
19 anchorName: '依錨點名稱',
20 charset: '連結資源的字元集',
21 cssClasses: '樣式表類別',
22 download: 'Force Download', // MISSING
23 displayText: '顯示文字',
24 emailAddress: '電子郵件地址',
25 emailBody: '郵件本文',
26 emailSubject: '郵件主旨',
27 id: 'ID',
28 info: '連結資訊',
29 langCode: '語言碼',
30 langDir: '語言方向',
31 langDirLTR: '由左至右 (LTR)',
32 langDirRTL: '由右至左 (RTL)',
33 menu: '編輯連結',
34 name: '名稱',
35 noAnchors: '(本文件中無可用之錨點)',
36 noEmail: '請輸入電子郵件',
37 noUrl: '請輸入連結 URL',
38 other: '<其他>',
39 popupDependent: '獨立 (Netscape)',
40 popupFeatures: '快顯視窗功能',
41 popupFullScreen: '全螢幕 (IE)',
42 popupLeft: '左側位置',
43 popupLocationBar: '位置列',
44 popupMenuBar: '功能表列',
45 popupResizable: '可調大小',
46 popupScrollBars: '捲軸',
47 popupStatusBar: '狀態列',
48 popupToolbar: '工具列',
49 popupTop: '頂端位置',
50 rel: '關係',
51 selectAnchor: '選取一個錨點',
52 styles: '樣式',
53 tabIndex: '定位順序',
54 target: '目標',
55 targetFrame: '<框架>',
56 targetFrameName: '目標框架名稱',
57 targetPopup: '<快顯視窗>',
58 targetPopupName: '快顯視窗名稱',
59 title: '連結',
60 toAnchor: '文字中的錨點連結',
61 toEmail: '電子郵件',
62 toUrl: '網址',
63 toolbar: '連結',
64 type: '連結類型',
65 unlink: '取消連結',
66 upload: '上傳'
67} );
diff --git a/sources/plugins/link/plugin.js b/sources/plugins/link/plugin.js
new file mode 100644
index 0000000..94d582b
--- /dev/null
+++ b/sources/plugins/link/plugin.js
@@ -0,0 +1,828 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6'use strict';
7
8( function() {
9 CKEDITOR.plugins.add( 'link', {
10 requires: 'dialog,fakeobjects',
11 // jscs:disable maximumLineLength
12 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
13 // jscs:enable maximumLineLength
14 icons: 'anchor,anchor-rtl,link,unlink', // %REMOVE_LINE_CORE%
15 hidpi: true, // %REMOVE_LINE_CORE%
16 onLoad: function() {
17 // Add the CSS styles for anchor placeholders.
18 var iconPath = CKEDITOR.getUrl( this.path + 'images' + ( CKEDITOR.env.hidpi ? '/hidpi' : '' ) + '/anchor.png' ),
19 baseStyle = 'background:url(' + iconPath + ') no-repeat %1 center;border:1px dotted #00f;background-size:16px;';
20
21 var template = '.%2 a.cke_anchor,' +
22 '.%2 a.cke_anchor_empty' +
23 ',.cke_editable.%2 a[name]' +
24 ',.cke_editable.%2 a[data-cke-saved-name]' +
25 '{' +
26 baseStyle +
27 'padding-%1:18px;' +
28 // Show the arrow cursor for the anchor image (FF at least).
29 'cursor:auto;' +
30 '}' +
31 '.%2 img.cke_anchor' +
32 '{' +
33 baseStyle +
34 'width:16px;' +
35 'min-height:15px;' +
36 // The default line-height on IE.
37 'height:1.15em;' +
38 // Opera works better with "middle" (even if not perfect)
39 'vertical-align:text-bottom;' +
40 '}';
41
42 // Styles with contents direction awareness.
43 function cssWithDir( dir ) {
44 return template.replace( /%1/g, dir == 'rtl' ? 'right' : 'left' ).replace( /%2/g, 'cke_contents_' + dir );
45 }
46
47 CKEDITOR.addCss( cssWithDir( 'ltr' ) + cssWithDir( 'rtl' ) );
48 },
49
50 init: function( editor ) {
51 var allowed = 'a[!href]',
52 required = 'a[href]';
53
54 if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'advanced' ) )
55 allowed = allowed.replace( ']', ',accesskey,charset,dir,id,lang,name,rel,tabindex,title,type,download]{*}(*)' );
56 if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'target' ) )
57 allowed = allowed.replace( ']', ',target,onclick]' );
58
59 // Add the link and unlink buttons.
60 editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link', {
61 allowedContent: allowed,
62 requiredContent: required
63 } ) );
64 editor.addCommand( 'anchor', new CKEDITOR.dialogCommand( 'anchor', {
65 allowedContent: 'a[!name,id]',
66 requiredContent: 'a[name]'
67 } ) );
68 editor.addCommand( 'unlink', new CKEDITOR.unlinkCommand() );
69 editor.addCommand( 'removeAnchor', new CKEDITOR.removeAnchorCommand() );
70
71 editor.setKeystroke( CKEDITOR.CTRL + 76 /*L*/, 'link' );
72
73 if ( editor.ui.addButton ) {
74 editor.ui.addButton( 'Link', {
75 label: editor.lang.link.toolbar,
76 command: 'link',
77 toolbar: 'links,10'
78 } );
79 editor.ui.addButton( 'Unlink', {
80 label: editor.lang.link.unlink,
81 command: 'unlink',
82 toolbar: 'links,20'
83 } );
84 editor.ui.addButton( 'Anchor', {
85 label: editor.lang.link.anchor.toolbar,
86 command: 'anchor',
87 toolbar: 'links,30'
88 } );
89 }
90
91 CKEDITOR.dialog.add( 'link', this.path + 'dialogs/link.js' );
92 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' );
93
94 editor.on( 'doubleclick', function( evt ) {
95 var element = CKEDITOR.plugins.link.getSelectedLink( editor ) || evt.data.element;
96
97 if ( !element.isReadOnly() ) {
98 if ( element.is( 'a' ) ) {
99 evt.data.dialog = ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) ? 'anchor' : 'link';
100
101 // Pass the link to be selected along with event data.
102 evt.data.link = element;
103 } else if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) ) {
104 evt.data.dialog = 'anchor';
105 }
106 }
107 }, null, null, 0 );
108
109 // If event was cancelled, link passed in event data will not be selected.
110 editor.on( 'doubleclick', function( evt ) {
111 // Make sure both links and anchors are selected (#11822).
112 if ( evt.data.dialog in { link: 1, anchor: 1 } && evt.data.link )
113 editor.getSelection().selectElement( evt.data.link );
114 }, null, null, 20 );
115
116 // If the "menu" plugin is loaded, register the menu items.
117 if ( editor.addMenuItems ) {
118 editor.addMenuItems( {
119 anchor: {
120 label: editor.lang.link.anchor.menu,
121 command: 'anchor',
122 group: 'anchor',
123 order: 1
124 },
125
126 removeAnchor: {
127 label: editor.lang.link.anchor.remove,
128 command: 'removeAnchor',
129 group: 'anchor',
130 order: 5
131 },
132
133 link: {
134 label: editor.lang.link.menu,
135 command: 'link',
136 group: 'link',
137 order: 1
138 },
139
140 unlink: {
141 label: editor.lang.link.unlink,
142 command: 'unlink',
143 group: 'link',
144 order: 5
145 }
146 } );
147 }
148
149 // If the "contextmenu" plugin is loaded, register the listeners.
150 if ( editor.contextMenu ) {
151 editor.contextMenu.addListener( function( element ) {
152 if ( !element || element.isReadOnly() )
153 return null;
154
155 var anchor = CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element );
156
157 if ( !anchor && !( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) )
158 return null;
159
160 var menu = {};
161
162 if ( anchor.getAttribute( 'href' ) && anchor.getChildCount() )
163 menu = { link: CKEDITOR.TRISTATE_OFF, unlink: CKEDITOR.TRISTATE_OFF };
164
165 if ( anchor && anchor.hasAttribute( 'name' ) )
166 menu.anchor = menu.removeAnchor = CKEDITOR.TRISTATE_OFF;
167
168 return menu;
169 } );
170 }
171
172 this.compiledProtectionFunction = getCompiledProtectionFunction( editor );
173 },
174
175 afterInit: function( editor ) {
176 // Empty anchors upcasting to fake objects.
177 editor.dataProcessor.dataFilter.addRules( {
178 elements: {
179 a: function( element ) {
180 if ( !element.attributes.name )
181 return null;
182
183 if ( !element.children.length )
184 return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' );
185
186 return null;
187 }
188 }
189 } );
190
191 var pathFilters = editor._.elementsPath && editor._.elementsPath.filters;
192 if ( pathFilters ) {
193 pathFilters.push( function( element, name ) {
194 if ( name == 'a' ) {
195 if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) || ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) )
196 return 'anchor';
197 }
198 } );
199 }
200 }
201 } );
202
203 // Loads the parameters in a selected link to the link dialog fields.
204 var javascriptProtocolRegex = /^javascript:/,
205 emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/,
206 emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/i,
207 emailBodyRegex = /body=([^;?:@&=$,\/]*)/i,
208 anchorRegex = /^#(.*)$/,
209 urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/,
210 selectableTargets = /^(_(?:self|top|parent|blank))$/,
211 encodedEmailLinkRegex = /^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/,
212 functionCallProtectedEmailLinkRegex = /^javascript:([^(]+)\(([^)]+)\)$/,
213 popupRegex = /\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/,
214 popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi;
215
216 var advAttrNames = {
217 id: 'advId',
218 dir: 'advLangDir',
219 accessKey: 'advAccessKey',
220 // 'data-cke-saved-name': 'advName',
221 name: 'advName',
222 lang: 'advLangCode',
223 tabindex: 'advTabIndex',
224 title: 'advTitle',
225 type: 'advContentType',
226 'class': 'advCSSClasses',
227 charset: 'advCharset',
228 style: 'advStyles',
229 rel: 'advRel'
230 };
231
232 function unescapeSingleQuote( str ) {
233 return str.replace( /\\'/g, '\'' );
234 }
235
236 function escapeSingleQuote( str ) {
237 return str.replace( /'/g, '\\$&' );
238 }
239
240 function protectEmailAddressAsEncodedString( address ) {
241 var charCode,
242 length = address.length,
243 encodedChars = [];
244
245 for ( var i = 0; i < length; i++ ) {
246 charCode = address.charCodeAt( i );
247 encodedChars.push( charCode );
248 }
249
250 return 'String.fromCharCode(' + encodedChars.join( ',' ) + ')';
251 }
252
253 function protectEmailLinkAsFunction( editor, email ) {
254 var plugin = editor.plugins.link,
255 name = plugin.compiledProtectionFunction.name,
256 params = plugin.compiledProtectionFunction.params,
257 paramName, paramValue, retval;
258
259 retval = [ name, '(' ];
260 for ( var i = 0; i < params.length; i++ ) {
261 paramName = params[ i ].toLowerCase();
262 paramValue = email[ paramName ];
263
264 i > 0 && retval.push( ',' );
265 retval.push( '\'', paramValue ? escapeSingleQuote( encodeURIComponent( email[ paramName ] ) ) : '', '\'' );
266 }
267 retval.push( ')' );
268 return retval.join( '' );
269 }
270
271 function getCompiledProtectionFunction( editor ) {
272 var emailProtection = editor.config.emailProtection || '',
273 compiledProtectionFunction;
274
275 // Compile the protection function pattern.
276 if ( emailProtection && emailProtection != 'encode' ) {
277 compiledProtectionFunction = {};
278
279 emailProtection.replace( /^([^(]+)\(([^)]+)\)$/, function( match, funcName, params ) {
280 compiledProtectionFunction.name = funcName;
281 compiledProtectionFunction.params = [];
282 params.replace( /[^,\s]+/g, function( param ) {
283 compiledProtectionFunction.params.push( param );
284 } );
285 } );
286 }
287
288 return compiledProtectionFunction;
289 }
290
291 /**
292 * Set of Link plugin helpers.
293 *
294 * @class
295 * @singleton
296 */
297 CKEDITOR.plugins.link = {
298 /**
299 * Get the surrounding link element of the current selection.
300 *
301 * CKEDITOR.plugins.link.getSelectedLink( editor );
302 *
303 * // The following selections will all return the link element.
304 *
305 * <a href="#">li^nk</a>
306 * <a href="#">[link]</a>
307 * text[<a href="#">link]</a>
308 * <a href="#">li[nk</a>]
309 * [<b><a href="#">li]nk</a></b>]
310 * [<a href="#"><b>li]nk</b></a>
311 *
312 * @since 3.2.1
313 * @param {CKEDITOR.editor} editor
314 */
315 getSelectedLink: function( editor ) {
316 var selection = editor.getSelection();
317 var selectedElement = selection.getSelectedElement();
318 if ( selectedElement && selectedElement.is( 'a' ) )
319 return selectedElement;
320
321 var range = selection.getRanges()[ 0 ];
322
323 if ( range ) {
324 range.shrink( CKEDITOR.SHRINK_TEXT );
325 return editor.elementPath( range.getCommonAncestor() ).contains( 'a', 1 );
326 }
327 return null;
328 },
329
330 /**
331 * Collects anchors available in the editor (i.e. used by the Link plugin).
332 * Note that the scope of search is different for inline (the "global" document) and
333 * classic (`iframe`-based) editors (the "inner" document).
334 *
335 * @since 4.3.3
336 * @param {CKEDITOR.editor} editor
337 * @returns {CKEDITOR.dom.element[]} An array of anchor elements.
338 */
339 getEditorAnchors: function( editor ) {
340 var editable = editor.editable(),
341
342 // The scope of search for anchors is the entire document for inline editors
343 // and editor's editable for classic editor/divarea (#11359).
344 scope = ( editable.isInline() && !editor.plugins.divarea ) ? editor.document : editable,
345
346 links = scope.getElementsByTag( 'a' ),
347 imgs = scope.getElementsByTag( 'img' ),
348 anchors = [],
349 i = 0,
350 item;
351
352 // Retrieve all anchors within the scope.
353 while ( ( item = links.getItem( i++ ) ) ) {
354 if ( item.data( 'cke-saved-name' ) || item.hasAttribute( 'name' ) ) {
355 anchors.push( {
356 name: item.data( 'cke-saved-name' ) || item.getAttribute( 'name' ),
357 id: item.getAttribute( 'id' )
358 } );
359 }
360 }
361 // Retrieve all "fake anchors" within the scope.
362 i = 0;
363
364 while ( ( item = imgs.getItem( i++ ) ) ) {
365 if ( ( item = this.tryRestoreFakeAnchor( editor, item ) ) ) {
366 anchors.push( {
367 name: item.getAttribute( 'name' ),
368 id: item.getAttribute( 'id' )
369 } );
370 }
371 }
372
373 return anchors;
374 },
375
376 /**
377 * Opera and WebKit do not make it possible to select empty anchors. Fake
378 * elements must be used for them.
379 *
380 * @readonly
381 * @deprecated 4.3.3 It is set to `true` in every browser.
382 * @property {Boolean}
383 */
384 fakeAnchor: true,
385
386 /**
387 * For browsers that do not support CSS3 `a[name]:empty()`. Note that IE9 is included because of #7783.
388 *
389 * @readonly
390 * @deprecated 4.3.3 It is set to `false` in every browser.
391 * @property {Boolean} synAnchorSelector
392 */
393
394 /**
395 * For browsers that have editing issues with an empty anchor.
396 *
397 * @readonly
398 * @deprecated 4.3.3 It is set to `false` in every browser.
399 * @property {Boolean} emptyAnchorFix
400 */
401
402 /**
403 * Returns an element representing a real anchor restored from a fake anchor.
404 *
405 * @param {CKEDITOR.editor} editor
406 * @param {CKEDITOR.dom.element} element
407 * @returns {CKEDITOR.dom.element} Restored anchor element or nothing if the
408 * passed element was not a fake anchor.
409 */
410 tryRestoreFakeAnchor: function( editor, element ) {
411 if ( element && element.data( 'cke-real-element-type' ) && element.data( 'cke-real-element-type' ) == 'anchor' ) {
412 var link = editor.restoreRealElement( element );
413 if ( link.data( 'cke-saved-name' ) )
414 return link;
415 }
416 },
417
418 /**
419 * Parses attributes of the link element and returns an object representing
420 * the current state (data) of the link. This data format is a plain object accepted
421 * e.g. by the Link dialog window and {@link #getLinkAttributes}.
422 *
423 * **Note:** Data model format produced by the parser must be compatible with the Link
424 * plugin dialog because it is passed directly to {@link CKEDITOR.dialog#setupContent}.
425 *
426 * @since 4.4
427 * @param {CKEDITOR.editor} editor
428 * @param {CKEDITOR.dom.element} element
429 * @returns {Object} An object of link data.
430 */
431 parseLinkAttributes: function( editor, element ) {
432 var href = ( element && ( element.data( 'cke-saved-href' ) || element.getAttribute( 'href' ) ) ) || '',
433 compiledProtectionFunction = editor.plugins.link.compiledProtectionFunction,
434 emailProtection = editor.config.emailProtection,
435 javascriptMatch, emailMatch, anchorMatch, urlMatch,
436 retval = {};
437
438 if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) ) {
439 if ( emailProtection == 'encode' ) {
440 href = href.replace( encodedEmailLinkRegex, function( match, protectedAddress, rest ) {
441 // Without it 'undefined' is appended to e-mails without subject and body (#9192).
442 rest = rest || '';
443
444 return 'mailto:' +
445 String.fromCharCode.apply( String, protectedAddress.split( ',' ) ) +
446 unescapeSingleQuote( rest );
447 } );
448 }
449 // Protected email link as function call.
450 else if ( emailProtection ) {
451 href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs ) {
452 if ( funcName == compiledProtectionFunction.name ) {
453 retval.type = 'email';
454 var email = retval.email = {};
455
456 var paramRegex = /[^,\s]+/g,
457 paramQuoteRegex = /(^')|('$)/g,
458 paramsMatch = funcArgs.match( paramRegex ),
459 paramsMatchLength = paramsMatch.length,
460 paramName, paramVal;
461
462 for ( var i = 0; i < paramsMatchLength; i++ ) {
463 paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) );
464 paramName = compiledProtectionFunction.params[ i ].toLowerCase();
465 email[ paramName ] = paramVal;
466 }
467 email.address = [ email.name, email.domain ].join( '@' );
468 }
469 } );
470 }
471 }
472
473 if ( !retval.type ) {
474 if ( ( anchorMatch = href.match( anchorRegex ) ) ) {
475 retval.type = 'anchor';
476 retval.anchor = {};
477 retval.anchor.name = retval.anchor.id = anchorMatch[ 1 ];
478 }
479 // Protected email link as encoded string.
480 else if ( ( emailMatch = href.match( emailRegex ) ) ) {
481 var subjectMatch = href.match( emailSubjectRegex ),
482 bodyMatch = href.match( emailBodyRegex );
483
484 retval.type = 'email';
485 var email = ( retval.email = {} );
486 email.address = emailMatch[ 1 ];
487 subjectMatch && ( email.subject = decodeURIComponent( subjectMatch[ 1 ] ) );
488 bodyMatch && ( email.body = decodeURIComponent( bodyMatch[ 1 ] ) );
489 }
490 // urlRegex matches empty strings, so need to check for href as well.
491 else if ( href && ( urlMatch = href.match( urlRegex ) ) ) {
492 retval.type = 'url';
493 retval.url = {};
494 retval.url.protocol = urlMatch[ 1 ];
495 retval.url.url = urlMatch[ 2 ];
496 }
497 }
498
499 // Load target and popup settings.
500 if ( element ) {
501 var target = element.getAttribute( 'target' );
502
503 // IE BUG: target attribute is an empty string instead of null in IE if it's not set.
504 if ( !target ) {
505 var onclick = element.data( 'cke-pa-onclick' ) || element.getAttribute( 'onclick' ),
506 onclickMatch = onclick && onclick.match( popupRegex );
507
508 if ( onclickMatch ) {
509 retval.target = {
510 type: 'popup',
511 name: onclickMatch[ 1 ]
512 };
513
514 var featureMatch;
515 while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[ 2 ] ) ) ) {
516 // Some values should remain numbers (#7300)
517 if ( ( featureMatch[ 2 ] == 'yes' || featureMatch[ 2 ] == '1' ) && !( featureMatch[ 1 ] in { height: 1, width: 1, top: 1, left: 1 } ) )
518 retval.target[ featureMatch[ 1 ] ] = true;
519 else if ( isFinite( featureMatch[ 2 ] ) )
520 retval.target[ featureMatch[ 1 ] ] = featureMatch[ 2 ];
521 }
522 }
523 } else {
524 retval.target = {
525 type: target.match( selectableTargets ) ? target : 'frame',
526 name: target
527 };
528 }
529
530 var download = element.getAttribute( 'download' );
531 if ( download !== null ) {
532 retval.download = true;
533 }
534
535 var advanced = {};
536
537 for ( var a in advAttrNames ) {
538 var val = element.getAttribute( a );
539
540 if ( val )
541 advanced[ advAttrNames[ a ] ] = val;
542 }
543
544 var advName = element.data( 'cke-saved-name' ) || advanced.advName;
545
546 if ( advName )
547 advanced.advName = advName;
548
549 if ( !CKEDITOR.tools.isEmpty( advanced ) )
550 retval.advanced = advanced;
551 }
552
553 return retval;
554 },
555
556 /**
557 * Converts link data produced by {@link #parseLinkAttributes} into an object which consists
558 * of attributes to be set (with their values) and an array of attributes to be removed.
559 * This method can be used to compose or to update any link element with the given data.
560 *
561 * @since 4.4
562 * @param {CKEDITOR.editor} editor
563 * @param {Object} data Data in {@link #parseLinkAttributes} format.
564 * @returns {Object} An object consisting of two keys, i.e.:
565 *
566 * {
567 * // Attributes to be set.
568 * set: {
569 * href: 'http://foo.bar',
570 * target: 'bang'
571 * },
572 * // Attributes to be removed.
573 * removed: [
574 * 'id', 'style'
575 * ]
576 * }
577 *
578 */
579 getLinkAttributes: function( editor, data ) {
580 var emailProtection = editor.config.emailProtection || '',
581 set = {};
582
583 // Compose the URL.
584 switch ( data.type ) {
585 case 'url':
586 var protocol = ( data.url && data.url.protocol !== undefined ) ? data.url.protocol : 'http://',
587 url = ( data.url && CKEDITOR.tools.trim( data.url.url ) ) || '';
588
589 set[ 'data-cke-saved-href' ] = ( url.indexOf( '/' ) === 0 ) ? url : protocol + url;
590
591 break;
592 case 'anchor':
593 var name = ( data.anchor && data.anchor.name ),
594 id = ( data.anchor && data.anchor.id );
595
596 set[ 'data-cke-saved-href' ] = '#' + ( name || id || '' );
597
598 break;
599 case 'email':
600 var email = data.email,
601 address = email.address,
602 linkHref;
603
604 switch ( emailProtection ) {
605 case '':
606 case 'encode':
607 var subject = encodeURIComponent( email.subject || '' ),
608 body = encodeURIComponent( email.body || '' ),
609 argList = [];
610
611 // Build the e-mail parameters first.
612 subject && argList.push( 'subject=' + subject );
613 body && argList.push( 'body=' + body );
614 argList = argList.length ? '?' + argList.join( '&' ) : '';
615
616 if ( emailProtection == 'encode' ) {
617 linkHref = [
618 'javascript:void(location.href=\'mailto:\'+', // jshint ignore:line
619 protectEmailAddressAsEncodedString( address )
620 ];
621 // parameters are optional.
622 argList && linkHref.push( '+\'', escapeSingleQuote( argList ), '\'' );
623
624 linkHref.push( ')' );
625 } else {
626 linkHref = [ 'mailto:', address, argList ];
627 }
628
629 break;
630 default:
631 // Separating name and domain.
632 var nameAndDomain = address.split( '@', 2 );
633 email.name = nameAndDomain[ 0 ];
634 email.domain = nameAndDomain[ 1 ];
635
636 linkHref = [ 'javascript:', protectEmailLinkAsFunction( editor, email ) ]; // jshint ignore:line
637 }
638
639 set[ 'data-cke-saved-href' ] = linkHref.join( '' );
640 break;
641 }
642
643 // Popups and target.
644 if ( data.target ) {
645 if ( data.target.type == 'popup' ) {
646 var onclickList = [
647 'window.open(this.href, \'', data.target.name || '', '\', \''
648 ],
649 featureList = [
650 'resizable', 'status', 'location', 'toolbar', 'menubar', 'fullscreen', 'scrollbars', 'dependent'
651 ],
652 featureLength = featureList.length,
653 addFeature = function( featureName ) {
654 if ( data.target[ featureName ] )
655 featureList.push( featureName + '=' + data.target[ featureName ] );
656 };
657
658 for ( var i = 0; i < featureLength; i++ )
659 featureList[ i ] = featureList[ i ] + ( data.target[ featureList[ i ] ] ? '=yes' : '=no' );
660
661 addFeature( 'width' );
662 addFeature( 'left' );
663 addFeature( 'height' );
664 addFeature( 'top' );
665
666 onclickList.push( featureList.join( ',' ), '\'); return false;' );
667 set[ 'data-cke-pa-onclick' ] = onclickList.join( '' );
668 }
669 else if ( data.target.type != 'notSet' && data.target.name ) {
670 set.target = data.target.name;
671 }
672 }
673
674 // Force download attribute.
675 if ( data.download ) {
676 set.download = '';
677 }
678
679 // Advanced attributes.
680 if ( data.advanced ) {
681 for ( var a in advAttrNames ) {
682 var val = data.advanced[ advAttrNames[ a ] ];
683
684 if ( val )
685 set[ a ] = val;
686 }
687
688 if ( set.name )
689 set[ 'data-cke-saved-name' ] = set.name;
690 }
691
692 // Browser need the "href" fro copy/paste link to work. (#6641)
693 if ( set[ 'data-cke-saved-href' ] )
694 set.href = set[ 'data-cke-saved-href' ];
695
696 var removed = {
697 target: 1,
698 onclick: 1,
699 'data-cke-pa-onclick': 1,
700 'data-cke-saved-name': 1,
701 'download': 1
702 };
703
704 if ( data.advanced )
705 CKEDITOR.tools.extend( removed, advAttrNames );
706
707 // Remove all attributes which are not currently set.
708 for ( var s in set )
709 delete removed[ s ];
710
711 return {
712 set: set,
713 removed: CKEDITOR.tools.objectKeys( removed )
714 };
715 },
716
717
718 /**
719 * Determines whether an element should have a "Display Text" field in the Link dialog.
720 *
721 * @since 4.5.11
722 * @param {CKEDITOR.dom.element/null} element Selected element, `null` if none selected or if a ranged selection
723 * is made.
724 * @param {CKEDITOR.editor} editor The editor instance for which the check is performed.
725 * @returns {Boolean}
726 */
727 showDisplayTextForElement: function( element, editor ) {
728 var undesiredElements = {
729 img: 1,
730 table: 1,
731 tbody: 1,
732 thead: 1,
733 tfoot: 1,
734 input: 1,
735 select: 1,
736 textarea: 1
737 };
738
739 // Widget duck typing, we don't want to show display text for widgets.
740 if ( editor.widgets && editor.widgets.focused ) {
741 return false;
742 }
743
744 return !element || !element.getName || !element.is( undesiredElements );
745 }
746 };
747
748 // TODO Much probably there's no need to expose these as public objects.
749
750 CKEDITOR.unlinkCommand = function() {};
751 CKEDITOR.unlinkCommand.prototype = {
752 exec: function( editor ) {
753 var style = new CKEDITOR.style( { element: 'a', type: CKEDITOR.STYLE_INLINE, alwaysRemoveElement: 1 } );
754 editor.removeStyle( style );
755 },
756
757 refresh: function( editor, path ) {
758 // Despite our initial hope, document.queryCommandEnabled() does not work
759 // for this in Firefox. So we must detect the state by element paths.
760
761 var element = path.lastElement && path.lastElement.getAscendant( 'a', true );
762
763 if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) && element.getChildCount() )
764 this.setState( CKEDITOR.TRISTATE_OFF );
765 else
766 this.setState( CKEDITOR.TRISTATE_DISABLED );
767 },
768
769 contextSensitive: 1,
770 startDisabled: 1,
771 requiredContent: 'a[href]'
772 };
773
774 CKEDITOR.removeAnchorCommand = function() {};
775 CKEDITOR.removeAnchorCommand.prototype = {
776 exec: function( editor ) {
777 var sel = editor.getSelection(),
778 bms = sel.createBookmarks(),
779 anchor;
780 if ( sel && ( anchor = sel.getSelectedElement() ) && ( !anchor.getChildCount() ? CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, anchor ) : anchor.is( 'a' ) ) )
781 anchor.remove( 1 );
782 else {
783 if ( ( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) ) {
784 if ( anchor.hasAttribute( 'href' ) ) {
785 anchor.removeAttributes( { name: 1, 'data-cke-saved-name': 1 } );
786 anchor.removeClass( 'cke_anchor' );
787 } else {
788 anchor.remove( 1 );
789 }
790 }
791 }
792 sel.selectBookmarks( bms );
793 },
794 requiredContent: 'a[name]'
795 };
796
797 CKEDITOR.tools.extend( CKEDITOR.config, {
798 /**
799 * Whether to show the Advanced tab in the Link dialog window.
800 *
801 * @cfg {Boolean} [linkShowAdvancedTab=true]
802 * @member CKEDITOR.config
803 */
804 linkShowAdvancedTab: true,
805
806 /**
807 * Whether to show the Target tab in the Link dialog window.
808 *
809 * @cfg {Boolean} [linkShowTargetTab=true]
810 * @member CKEDITOR.config
811 */
812 linkShowTargetTab: true
813
814 /**
815 * Whether JavaScript code is allowed as a `href` attribute in an anchor tag.
816 * With this option enabled it is possible to create links like:
817 *
818 * <a href="javascript:alert('Hello world!')">hello world</a>
819 *
820 * By default JavaScript links are not allowed and will not pass
821 * the Link dialog window validation.
822 *
823 * @since 4.4.1
824 * @cfg {Boolean} [linkJavaScriptLinksAllowed=false]
825 * @member CKEDITOR.config
826 */
827 } );
828} )();
diff --git a/sources/plugins/list/icons/bulletedlist-rtl.png b/sources/plugins/list/icons/bulletedlist-rtl.png
new file mode 100644
index 0000000..2fed6b5
--- /dev/null
+++ b/sources/plugins/list/icons/bulletedlist-rtl.png
Binary files differ
diff --git a/sources/plugins/list/icons/bulletedlist.png b/sources/plugins/list/icons/bulletedlist.png
new file mode 100644
index 0000000..8d33138
--- /dev/null
+++ b/sources/plugins/list/icons/bulletedlist.png
Binary files differ
diff --git a/sources/plugins/list/icons/hidpi/bulletedlist-rtl.png b/sources/plugins/list/icons/hidpi/bulletedlist-rtl.png
new file mode 100644
index 0000000..7e08fb3
--- /dev/null
+++ b/sources/plugins/list/icons/hidpi/bulletedlist-rtl.png
Binary files differ
diff --git a/sources/plugins/list/icons/hidpi/bulletedlist.png b/sources/plugins/list/icons/hidpi/bulletedlist.png
new file mode 100644
index 0000000..796923f
--- /dev/null
+++ b/sources/plugins/list/icons/hidpi/bulletedlist.png
Binary files differ
diff --git a/sources/plugins/list/icons/hidpi/numberedlist-rtl.png b/sources/plugins/list/icons/hidpi/numberedlist-rtl.png
new file mode 100644
index 0000000..2ece272
--- /dev/null
+++ b/sources/plugins/list/icons/hidpi/numberedlist-rtl.png
Binary files differ
diff --git a/sources/plugins/list/icons/hidpi/numberedlist.png b/sources/plugins/list/icons/hidpi/numberedlist.png
new file mode 100644
index 0000000..20fe003
--- /dev/null
+++ b/sources/plugins/list/icons/hidpi/numberedlist.png
Binary files differ
diff --git a/sources/plugins/list/icons/numberedlist-rtl.png b/sources/plugins/list/icons/numberedlist-rtl.png
new file mode 100644
index 0000000..3c62d8d
--- /dev/null
+++ b/sources/plugins/list/icons/numberedlist-rtl.png
Binary files differ
diff --git a/sources/plugins/list/icons/numberedlist.png b/sources/plugins/list/icons/numberedlist.png
new file mode 100644
index 0000000..d47e0d5
--- /dev/null
+++ b/sources/plugins/list/icons/numberedlist.png
Binary files differ
diff --git a/sources/plugins/list/lang/af.js b/sources/plugins/list/lang/af.js
new file mode 100644
index 0000000..6b92ff6
--- /dev/null
+++ b/sources/plugins/list/lang/af.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'af', {
6 bulletedlist: 'Ongenommerde lys',
7 numberedlist: 'Genommerde lys'
8} );
diff --git a/sources/plugins/list/lang/ar.js b/sources/plugins/list/lang/ar.js
new file mode 100644
index 0000000..a7a7de7
--- /dev/null
+++ b/sources/plugins/list/lang/ar.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ar', {
6 bulletedlist: 'ادخال/حذف تعداد نقطي',
7 numberedlist: 'ادخال/حذف تعداد رقمي'
8} );
diff --git a/sources/plugins/list/lang/az.js b/sources/plugins/list/lang/az.js
new file mode 100644
index 0000000..5d4e513
--- /dev/null
+++ b/sources/plugins/list/lang/az.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'az', {
6 bulletedlist: 'Markerlənmiş siyahını başlat/sil',
7 numberedlist: 'Nömrələnmiş siyahını başlat/sil'
8} );
diff --git a/sources/plugins/list/lang/bg.js b/sources/plugins/list/lang/bg.js
new file mode 100644
index 0000000..6ac7ab6
--- /dev/null
+++ b/sources/plugins/list/lang/bg.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'bg', {
6 bulletedlist: 'Вмъкване/Премахване на точков списък',
7 numberedlist: 'Вмъкване/Премахване на номериран списък'
8} );
diff --git a/sources/plugins/list/lang/bn.js b/sources/plugins/list/lang/bn.js
new file mode 100644
index 0000000..cf6a85a
--- /dev/null
+++ b/sources/plugins/list/lang/bn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'bn', {
6 bulletedlist: 'বুলেটেড তালিকা প্রবেশ/অপসারন করি',
7 numberedlist: 'সাংখ্যিক লিস্টের লেবেল'
8} );
diff --git a/sources/plugins/list/lang/bs.js b/sources/plugins/list/lang/bs.js
new file mode 100644
index 0000000..76877b5
--- /dev/null
+++ b/sources/plugins/list/lang/bs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'bs', {
6 bulletedlist: 'Lista',
7 numberedlist: 'Numerisana lista'
8} );
diff --git a/sources/plugins/list/lang/ca.js b/sources/plugins/list/lang/ca.js
new file mode 100644
index 0000000..408cf53
--- /dev/null
+++ b/sources/plugins/list/lang/ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ca', {
6 bulletedlist: 'Llista de pics',
7 numberedlist: 'Llista numerada'
8} );
diff --git a/sources/plugins/list/lang/cs.js b/sources/plugins/list/lang/cs.js
new file mode 100644
index 0000000..e04b94d
--- /dev/null
+++ b/sources/plugins/list/lang/cs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'cs', {
6 bulletedlist: 'Odrážky',
7 numberedlist: 'Číslování'
8} );
diff --git a/sources/plugins/list/lang/cy.js b/sources/plugins/list/lang/cy.js
new file mode 100644
index 0000000..c786d4b
--- /dev/null
+++ b/sources/plugins/list/lang/cy.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'cy', {
6 bulletedlist: 'Mewnosod/Tynnu Rhestr Bwled',
7 numberedlist: 'Mewnosod/Tynnu Rhestr Rhifol'
8} );
diff --git a/sources/plugins/list/lang/da.js b/sources/plugins/list/lang/da.js
new file mode 100644
index 0000000..5c90ec9
--- /dev/null
+++ b/sources/plugins/list/lang/da.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'da', {
6 bulletedlist: 'Punktopstilling',
7 numberedlist: 'Talopstilling'
8} );
diff --git a/sources/plugins/list/lang/de-ch.js b/sources/plugins/list/lang/de-ch.js
new file mode 100644
index 0000000..7d72503
--- /dev/null
+++ b/sources/plugins/list/lang/de-ch.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'de-ch', {
6 bulletedlist: 'Liste',
7 numberedlist: 'Nummerierte Liste einfügen/entfernen'
8} );
diff --git a/sources/plugins/list/lang/de.js b/sources/plugins/list/lang/de.js
new file mode 100644
index 0000000..ef4b5f2
--- /dev/null
+++ b/sources/plugins/list/lang/de.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'de', {
6 bulletedlist: 'Liste',
7 numberedlist: 'Nummerierte Liste einfügen/entfernen'
8} );
diff --git a/sources/plugins/list/lang/el.js b/sources/plugins/list/lang/el.js
new file mode 100644
index 0000000..feeebac
--- /dev/null
+++ b/sources/plugins/list/lang/el.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'el', {
6 bulletedlist: 'Εισαγωγή/Απομάκρυνση Λίστας Κουκκίδων',
7 numberedlist: 'Εισαγωγή/Απομάκρυνση Αριθμημένης Λίστας'
8} );
diff --git a/sources/plugins/list/lang/en-au.js b/sources/plugins/list/lang/en-au.js
new file mode 100644
index 0000000..d3bbc2b
--- /dev/null
+++ b/sources/plugins/list/lang/en-au.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'en-au', {
6 bulletedlist: 'Insert/Remove Bulleted List',
7 numberedlist: 'Insert/Remove Numbered List'
8} );
diff --git a/sources/plugins/list/lang/en-ca.js b/sources/plugins/list/lang/en-ca.js
new file mode 100644
index 0000000..80be02f
--- /dev/null
+++ b/sources/plugins/list/lang/en-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'en-ca', {
6 bulletedlist: 'Insert/Remove Bulleted List',
7 numberedlist: 'Insert/Remove Numbered List'
8} );
diff --git a/sources/plugins/list/lang/en-gb.js b/sources/plugins/list/lang/en-gb.js
new file mode 100644
index 0000000..07db96c
--- /dev/null
+++ b/sources/plugins/list/lang/en-gb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'en-gb', {
6 bulletedlist: 'Insert/Remove Bulleted List',
7 numberedlist: 'Insert/Remove Numbered List'
8} );
diff --git a/sources/plugins/list/lang/en.js b/sources/plugins/list/lang/en.js
new file mode 100644
index 0000000..0bdc852
--- /dev/null
+++ b/sources/plugins/list/lang/en.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'en', {
6 bulletedlist: 'Insert/Remove Bulleted List',
7 numberedlist: 'Insert/Remove Numbered List'
8} );
diff --git a/sources/plugins/list/lang/eo.js b/sources/plugins/list/lang/eo.js
new file mode 100644
index 0000000..9242615
--- /dev/null
+++ b/sources/plugins/list/lang/eo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'eo', {
6 bulletedlist: 'Bula Listo',
7 numberedlist: 'Numera Listo'
8} );
diff --git a/sources/plugins/list/lang/es.js b/sources/plugins/list/lang/es.js
new file mode 100644
index 0000000..37f1904
--- /dev/null
+++ b/sources/plugins/list/lang/es.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'es', {
6 bulletedlist: 'Viñetas',
7 numberedlist: 'Numeración'
8} );
diff --git a/sources/plugins/list/lang/et.js b/sources/plugins/list/lang/et.js
new file mode 100644
index 0000000..498c8a5
--- /dev/null
+++ b/sources/plugins/list/lang/et.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'et', {
6 bulletedlist: 'Punktloend',
7 numberedlist: 'Numberloend'
8} );
diff --git a/sources/plugins/list/lang/eu.js b/sources/plugins/list/lang/eu.js
new file mode 100644
index 0000000..254793d
--- /dev/null
+++ b/sources/plugins/list/lang/eu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'eu', {
6 bulletedlist: 'Buletdun Zerrenda',
7 numberedlist: 'Zenbakidun Zerrenda'
8} );
diff --git a/sources/plugins/list/lang/fa.js b/sources/plugins/list/lang/fa.js
new file mode 100644
index 0000000..af3f9dd
--- /dev/null
+++ b/sources/plugins/list/lang/fa.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'fa', {
6 bulletedlist: 'فهرست نقطه​ای',
7 numberedlist: 'فهرست شماره​دار'
8} );
diff --git a/sources/plugins/list/lang/fi.js b/sources/plugins/list/lang/fi.js
new file mode 100644
index 0000000..3874597
--- /dev/null
+++ b/sources/plugins/list/lang/fi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'fi', {
6 bulletedlist: 'Luettelomerkit',
7 numberedlist: 'Numerointi'
8} );
diff --git a/sources/plugins/list/lang/fo.js b/sources/plugins/list/lang/fo.js
new file mode 100644
index 0000000..416c667
--- /dev/null
+++ b/sources/plugins/list/lang/fo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'fo', {
6 bulletedlist: 'Punktmerktur listi',
7 numberedlist: 'Talmerktur listi'
8} );
diff --git a/sources/plugins/list/lang/fr-ca.js b/sources/plugins/list/lang/fr-ca.js
new file mode 100644
index 0000000..e9eb2b7
--- /dev/null
+++ b/sources/plugins/list/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'fr-ca', {
6 bulletedlist: 'Liste à puces',
7 numberedlist: 'Liste numérotée'
8} );
diff --git a/sources/plugins/list/lang/fr.js b/sources/plugins/list/lang/fr.js
new file mode 100644
index 0000000..cb49ec7
--- /dev/null
+++ b/sources/plugins/list/lang/fr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'fr', {
6 bulletedlist: 'Insérer/Supprimer une liste à puces',
7 numberedlist: 'Insérer/Supprimer une liste numérotée'
8} );
diff --git a/sources/plugins/list/lang/gl.js b/sources/plugins/list/lang/gl.js
new file mode 100644
index 0000000..d020a69
--- /dev/null
+++ b/sources/plugins/list/lang/gl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'gl', {
6 bulletedlist: 'Inserir/retirar lista viñeteada',
7 numberedlist: 'Inserir/retirar lista numerada'
8} );
diff --git a/sources/plugins/list/lang/gu.js b/sources/plugins/list/lang/gu.js
new file mode 100644
index 0000000..24a728f
--- /dev/null
+++ b/sources/plugins/list/lang/gu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'gu', {
6 bulletedlist: 'બુલેટ સૂચિ',
7 numberedlist: 'સંખ્યાંકન સૂચિ'
8} );
diff --git a/sources/plugins/list/lang/he.js b/sources/plugins/list/lang/he.js
new file mode 100644
index 0000000..118ddae
--- /dev/null
+++ b/sources/plugins/list/lang/he.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'he', {
6 bulletedlist: 'רשימת נקודות',
7 numberedlist: 'רשימה ממוספרת'
8} );
diff --git a/sources/plugins/list/lang/hi.js b/sources/plugins/list/lang/hi.js
new file mode 100644
index 0000000..a6bbca5
--- /dev/null
+++ b/sources/plugins/list/lang/hi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'hi', {
6 bulletedlist: 'बुलॅट सूची',
7 numberedlist: 'अंकीय सूची'
8} );
diff --git a/sources/plugins/list/lang/hr.js b/sources/plugins/list/lang/hr.js
new file mode 100644
index 0000000..ceb0a4c
--- /dev/null
+++ b/sources/plugins/list/lang/hr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'hr', {
6 bulletedlist: 'Obična lista',
7 numberedlist: 'Brojčana lista'
8} );
diff --git a/sources/plugins/list/lang/hu.js b/sources/plugins/list/lang/hu.js
new file mode 100644
index 0000000..cf2fe96
--- /dev/null
+++ b/sources/plugins/list/lang/hu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'hu', {
6 bulletedlist: 'Felsorolás',
7 numberedlist: 'Számozás'
8} );
diff --git a/sources/plugins/list/lang/id.js b/sources/plugins/list/lang/id.js
new file mode 100644
index 0000000..0b360dc
--- /dev/null
+++ b/sources/plugins/list/lang/id.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'id', {
6 bulletedlist: 'Sisip/Hapus Daftar Bullet',
7 numberedlist: 'Sisip/Hapus Daftar Bernomor'
8} );
diff --git a/sources/plugins/list/lang/is.js b/sources/plugins/list/lang/is.js
new file mode 100644
index 0000000..a23e87e
--- /dev/null
+++ b/sources/plugins/list/lang/is.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'is', {
6 bulletedlist: 'Punktalisti',
7 numberedlist: 'Númeraður listi'
8} );
diff --git a/sources/plugins/list/lang/it.js b/sources/plugins/list/lang/it.js
new file mode 100644
index 0000000..611f6fb
--- /dev/null
+++ b/sources/plugins/list/lang/it.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'it', {
6 bulletedlist: 'Inserisci/Rimuovi Elenco Puntato',
7 numberedlist: 'Inserisci/Rimuovi Elenco Numerato'
8} );
diff --git a/sources/plugins/list/lang/ja.js b/sources/plugins/list/lang/ja.js
new file mode 100644
index 0000000..c2df282
--- /dev/null
+++ b/sources/plugins/list/lang/ja.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ja', {
6 bulletedlist: '番号無しリスト',
7 numberedlist: '番号付きリスト'
8} );
diff --git a/sources/plugins/list/lang/ka.js b/sources/plugins/list/lang/ka.js
new file mode 100644
index 0000000..2053130
--- /dev/null
+++ b/sources/plugins/list/lang/ka.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ka', {
6 bulletedlist: 'ღილიანი სია',
7 numberedlist: 'გადანომრილი სია'
8} );
diff --git a/sources/plugins/list/lang/km.js b/sources/plugins/list/lang/km.js
new file mode 100644
index 0000000..71c0c7b
--- /dev/null
+++ b/sources/plugins/list/lang/km.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'km', {
6 bulletedlist: 'បញ្ចូល / លុប​បញ្ជី​ជា​ចំណុច​មូល',
7 numberedlist: 'បញ្ចូល / លុប​បញ្ជី​ជា​លេខ'
8} );
diff --git a/sources/plugins/list/lang/ko.js b/sources/plugins/list/lang/ko.js
new file mode 100644
index 0000000..48b4fd0
--- /dev/null
+++ b/sources/plugins/list/lang/ko.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ko', {
6 bulletedlist: '순서 없는 목록',
7 numberedlist: '순서 있는 목록'
8} );
diff --git a/sources/plugins/list/lang/ku.js b/sources/plugins/list/lang/ku.js
new file mode 100644
index 0000000..c5d0d9c
--- /dev/null
+++ b/sources/plugins/list/lang/ku.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ku', {
6 bulletedlist: 'دانان/لابردنی خاڵی لیست',
7 numberedlist: 'دانان/لابردنی ژمارەی لیست'
8} );
diff --git a/sources/plugins/list/lang/lt.js b/sources/plugins/list/lang/lt.js
new file mode 100644
index 0000000..0eac62e
--- /dev/null
+++ b/sources/plugins/list/lang/lt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'lt', {
6 bulletedlist: 'Suženklintas sąrašas',
7 numberedlist: 'Numeruotas sąrašas'
8} );
diff --git a/sources/plugins/list/lang/lv.js b/sources/plugins/list/lang/lv.js
new file mode 100644
index 0000000..6738856
--- /dev/null
+++ b/sources/plugins/list/lang/lv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'lv', {
6 bulletedlist: 'Pievienot/Noņemt vienkāršu sarakstu',
7 numberedlist: 'Numurēts saraksts'
8} );
diff --git a/sources/plugins/list/lang/mk.js b/sources/plugins/list/lang/mk.js
new file mode 100644
index 0000000..4054ea2
--- /dev/null
+++ b/sources/plugins/list/lang/mk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'mk', {
6 bulletedlist: 'Insert/Remove Bulleted List', // MISSING
7 numberedlist: 'Insert/Remove Numbered List' // MISSING
8} );
diff --git a/sources/plugins/list/lang/mn.js b/sources/plugins/list/lang/mn.js
new file mode 100644
index 0000000..ef9d4e0
--- /dev/null
+++ b/sources/plugins/list/lang/mn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'mn', {
6 bulletedlist: 'Цэгтэй жагсаалт',
7 numberedlist: 'Дугаарлагдсан жагсаалт'
8} );
diff --git a/sources/plugins/list/lang/ms.js b/sources/plugins/list/lang/ms.js
new file mode 100644
index 0000000..6d51a33
--- /dev/null
+++ b/sources/plugins/list/lang/ms.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ms', {
6 bulletedlist: 'Senarai tidak bernombor',
7 numberedlist: 'Senarai bernombor'
8} );
diff --git a/sources/plugins/list/lang/nb.js b/sources/plugins/list/lang/nb.js
new file mode 100644
index 0000000..0e817c8
--- /dev/null
+++ b/sources/plugins/list/lang/nb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'nb', {
6 bulletedlist: 'Legg til / fjern punktliste',
7 numberedlist: 'Legg til / fjern nummerert liste'
8} );
diff --git a/sources/plugins/list/lang/nl.js b/sources/plugins/list/lang/nl.js
new file mode 100644
index 0000000..65f71e9
--- /dev/null
+++ b/sources/plugins/list/lang/nl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'nl', {
6 bulletedlist: 'Opsomming invoegen',
7 numberedlist: 'Genummerde lijst invoegen'
8} );
diff --git a/sources/plugins/list/lang/no.js b/sources/plugins/list/lang/no.js
new file mode 100644
index 0000000..dc129c5
--- /dev/null
+++ b/sources/plugins/list/lang/no.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'no', {
6 bulletedlist: 'Legg til/Fjern punktmerket liste',
7 numberedlist: 'Legg til/Fjern nummerert liste'
8} );
diff --git a/sources/plugins/list/lang/oc.js b/sources/plugins/list/lang/oc.js
new file mode 100644
index 0000000..4705e9a
--- /dev/null
+++ b/sources/plugins/list/lang/oc.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'oc', {
6 bulletedlist: 'Inserir/Suprimir una lista amb de piuses',
7 numberedlist: 'Inserir/Suprimir una lista numerotada'
8} );
diff --git a/sources/plugins/list/lang/pl.js b/sources/plugins/list/lang/pl.js
new file mode 100644
index 0000000..0a0e552
--- /dev/null
+++ b/sources/plugins/list/lang/pl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'pl', {
6 bulletedlist: 'Lista wypunktowana',
7 numberedlist: 'Lista numerowana'
8} );
diff --git a/sources/plugins/list/lang/pt-br.js b/sources/plugins/list/lang/pt-br.js
new file mode 100644
index 0000000..b0edd8e
--- /dev/null
+++ b/sources/plugins/list/lang/pt-br.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'pt-br', {
6 bulletedlist: 'Lista sem números',
7 numberedlist: 'Lista numerada'
8} );
diff --git a/sources/plugins/list/lang/pt.js b/sources/plugins/list/lang/pt.js
new file mode 100644
index 0000000..52d4348
--- /dev/null
+++ b/sources/plugins/list/lang/pt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'pt', {
6 bulletedlist: 'Marcas',
7 numberedlist: 'Numeração'
8} );
diff --git a/sources/plugins/list/lang/ro.js b/sources/plugins/list/lang/ro.js
new file mode 100644
index 0000000..c229901
--- /dev/null
+++ b/sources/plugins/list/lang/ro.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ro', {
6 bulletedlist: 'Inserează / Elimină Listă cu puncte',
7 numberedlist: 'Inserează / Elimină Listă numerotată'
8} );
diff --git a/sources/plugins/list/lang/ru.js b/sources/plugins/list/lang/ru.js
new file mode 100644
index 0000000..862fa78
--- /dev/null
+++ b/sources/plugins/list/lang/ru.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ru', {
6 bulletedlist: 'Вставить / удалить маркированный список',
7 numberedlist: 'Вставить / удалить нумерованный список'
8} );
diff --git a/sources/plugins/list/lang/si.js b/sources/plugins/list/lang/si.js
new file mode 100644
index 0000000..de2fc4d
--- /dev/null
+++ b/sources/plugins/list/lang/si.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'si', {
6 bulletedlist: 'ඇතුලත් / ඉවත් කිරීම ලඉස්තුව',
7 numberedlist: 'ඇතුලත් / ඉවත් කිරීම අන්න්කිත ලඉස්තුව'
8} );
diff --git a/sources/plugins/list/lang/sk.js b/sources/plugins/list/lang/sk.js
new file mode 100644
index 0000000..11ca0ee
--- /dev/null
+++ b/sources/plugins/list/lang/sk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'sk', {
6 bulletedlist: 'Vložiť/odstrániť zoznam s odrážkami',
7 numberedlist: 'Vložiť/odstrániť číslovaný zoznam'
8} );
diff --git a/sources/plugins/list/lang/sl.js b/sources/plugins/list/lang/sl.js
new file mode 100644
index 0000000..368f9f6
--- /dev/null
+++ b/sources/plugins/list/lang/sl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'sl', {
6 bulletedlist: 'Vstavi/odstrani neoštevilčen seznam',
7 numberedlist: 'Vstavi/odstrani oštevilčen seznam'
8} );
diff --git a/sources/plugins/list/lang/sq.js b/sources/plugins/list/lang/sq.js
new file mode 100644
index 0000000..121b41e
--- /dev/null
+++ b/sources/plugins/list/lang/sq.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'sq', {
6 bulletedlist: 'Vendos/Largo Listën me Pika',
7 numberedlist: 'Vendos/Largo Listën me Numra'
8} );
diff --git a/sources/plugins/list/lang/sr-latn.js b/sources/plugins/list/lang/sr-latn.js
new file mode 100644
index 0000000..134aa69
--- /dev/null
+++ b/sources/plugins/list/lang/sr-latn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'sr-latn', {
6 bulletedlist: 'Nenabrojiva lista',
7 numberedlist: 'Nabrojiva lista'
8} );
diff --git a/sources/plugins/list/lang/sr.js b/sources/plugins/list/lang/sr.js
new file mode 100644
index 0000000..c54ca8a
--- /dev/null
+++ b/sources/plugins/list/lang/sr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'sr', {
6 bulletedlist: 'Ненабројива листа',
7 numberedlist: 'Набројиву листу'
8} );
diff --git a/sources/plugins/list/lang/sv.js b/sources/plugins/list/lang/sv.js
new file mode 100644
index 0000000..3a12793
--- /dev/null
+++ b/sources/plugins/list/lang/sv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'sv', {
6 bulletedlist: 'Infoga/ta bort punktlista',
7 numberedlist: 'Infoga/ta bort numrerad lista'
8} );
diff --git a/sources/plugins/list/lang/th.js b/sources/plugins/list/lang/th.js
new file mode 100644
index 0000000..8a47731
--- /dev/null
+++ b/sources/plugins/list/lang/th.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'th', {
6 bulletedlist: 'ลำดับรายการแบบสัญลักษณ์',
7 numberedlist: 'ลำดับรายการแบบตัวเลข'
8} );
diff --git a/sources/plugins/list/lang/tr.js b/sources/plugins/list/lang/tr.js
new file mode 100644
index 0000000..976e479
--- /dev/null
+++ b/sources/plugins/list/lang/tr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'tr', {
6 bulletedlist: 'Simgeli Liste',
7 numberedlist: 'Numaralı Liste'
8} );
diff --git a/sources/plugins/list/lang/tt.js b/sources/plugins/list/lang/tt.js
new file mode 100644
index 0000000..eb103ab
--- /dev/null
+++ b/sources/plugins/list/lang/tt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'tt', {
6 bulletedlist: 'Маркерлы тезмә өстәү/бетерү',
7 numberedlist: ' Номерланган тезмә өстәү/бетерү'
8} );
diff --git a/sources/plugins/list/lang/ug.js b/sources/plugins/list/lang/ug.js
new file mode 100644
index 0000000..442b92e
--- /dev/null
+++ b/sources/plugins/list/lang/ug.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'ug', {
6 bulletedlist: 'تۈر بەلگە تىزىمى',
7 numberedlist: 'تەرتىپ نومۇر تىزىمى'
8} );
diff --git a/sources/plugins/list/lang/uk.js b/sources/plugins/list/lang/uk.js
new file mode 100644
index 0000000..65a3e1d
--- /dev/null
+++ b/sources/plugins/list/lang/uk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'uk', {
6 bulletedlist: 'Маркірований список',
7 numberedlist: 'Нумерований список'
8} );
diff --git a/sources/plugins/list/lang/vi.js b/sources/plugins/list/lang/vi.js
new file mode 100644
index 0000000..e9e3acc
--- /dev/null
+++ b/sources/plugins/list/lang/vi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'vi', {
6 bulletedlist: 'Chèn/Xoá Danh sách không thứ tự',
7 numberedlist: 'Chèn/Xoá Danh sách có thứ tự'
8} );
diff --git a/sources/plugins/list/lang/zh-cn.js b/sources/plugins/list/lang/zh-cn.js
new file mode 100644
index 0000000..5e0408b
--- /dev/null
+++ b/sources/plugins/list/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'zh-cn', {
6 bulletedlist: '项目列表',
7 numberedlist: '编号列表'
8} );
diff --git a/sources/plugins/list/lang/zh.js b/sources/plugins/list/lang/zh.js
new file mode 100644
index 0000000..3d207d6
--- /dev/null
+++ b/sources/plugins/list/lang/zh.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'list', 'zh', {
6 bulletedlist: '插入/移除項目符號清單',
7 numberedlist: '插入/移除編號清單清單'
8} );
diff --git a/sources/plugins/list/plugin.js b/sources/plugins/list/plugin.js
new file mode 100644
index 0000000..7280cc2
--- /dev/null
+++ b/sources/plugins/list/plugin.js
@@ -0,0 +1,1111 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Insert and remove numbered and bulleted lists.
8 */
9
10( function() {
11 var listNodeNames = { ol: 1, ul: 1 };
12
13 var whitespaces = CKEDITOR.dom.walker.whitespaces(),
14 bookmarks = CKEDITOR.dom.walker.bookmark(),
15 nonEmpty = function( node ) {
16 return !( whitespaces( node ) || bookmarks( node ) );
17 },
18 blockBogus = CKEDITOR.dom.walker.bogus();
19
20 function cleanUpDirection( element ) {
21 var dir, parent, parentDir;
22 if ( ( dir = element.getDirection() ) ) {
23 parent = element.getParent();
24 while ( parent && !( parentDir = parent.getDirection() ) )
25 parent = parent.getParent();
26
27 if ( dir == parentDir )
28 element.removeAttribute( 'dir' );
29 }
30 }
31
32 // Inherit inline styles from another element.
33 function inheritInlineStyles( parent, el ) {
34 var style = parent.getAttribute( 'style' );
35
36 // Put parent styles before child styles.
37 style && el.setAttribute( 'style', style.replace( /([^;])$/, '$1;' ) + ( el.getAttribute( 'style' ) || '' ) );
38 }
39
40 CKEDITOR.plugins.list = {
41 /**
42 * Convert a DOM list tree into a data structure that is easier to
43 * manipulate. This operation should be non-intrusive in the sense that it
44 * does not change the DOM tree, with the exception that it may add some
45 * markers to the list item nodes when database is specified.
46 *
47 * @member CKEDITOR.plugins.list
48 * @todo params
49 */
50 listToArray: function( listNode, database, baseArray, baseIndentLevel, grandparentNode ) {
51 if ( !listNodeNames[ listNode.getName() ] )
52 return [];
53
54 if ( !baseIndentLevel )
55 baseIndentLevel = 0;
56 if ( !baseArray )
57 baseArray = [];
58
59 // Iterate over all list items to and look for inner lists.
60 for ( var i = 0, count = listNode.getChildCount(); i < count; i++ ) {
61 var listItem = listNode.getChild( i );
62
63 // Fixing malformed nested lists by moving it into a previous list item. (#6236)
64 if ( listItem.type == CKEDITOR.NODE_ELEMENT && listItem.getName() in CKEDITOR.dtd.$list )
65 CKEDITOR.plugins.list.listToArray( listItem, database, baseArray, baseIndentLevel + 1 );
66
67 // It may be a text node or some funny stuff.
68 if ( listItem.$.nodeName.toLowerCase() != 'li' )
69 continue;
70
71 var itemObj = { 'parent': listNode, indent: baseIndentLevel, element: listItem, contents: [] };
72 if ( !grandparentNode ) {
73 itemObj.grandparent = listNode.getParent();
74 if ( itemObj.grandparent && itemObj.grandparent.$.nodeName.toLowerCase() == 'li' )
75 itemObj.grandparent = itemObj.grandparent.getParent();
76 } else {
77 itemObj.grandparent = grandparentNode;
78 }
79
80 if ( database )
81 CKEDITOR.dom.element.setMarker( database, listItem, 'listarray_index', baseArray.length );
82 baseArray.push( itemObj );
83
84 for ( var j = 0, itemChildCount = listItem.getChildCount(), child; j < itemChildCount; j++ ) {
85 child = listItem.getChild( j );
86 if ( child.type == CKEDITOR.NODE_ELEMENT && listNodeNames[ child.getName() ] )
87 // Note the recursion here, it pushes inner list items with
88 // +1 indentation in the correct order.
89 CKEDITOR.plugins.list.listToArray( child, database, baseArray, baseIndentLevel + 1, itemObj.grandparent );
90 else
91 itemObj.contents.push( child );
92 }
93 }
94 return baseArray;
95 },
96
97 /**
98 * Convert our internal representation of a list back to a DOM forest.
99 *
100 * @member CKEDITOR.plugins.list
101 * @todo params
102 */
103 arrayToList: function( listArray, database, baseIndex, paragraphMode, dir ) {
104 if ( !baseIndex )
105 baseIndex = 0;
106 if ( !listArray || listArray.length < baseIndex + 1 )
107 return null;
108
109 var i,
110 doc = listArray[ baseIndex ].parent.getDocument(),
111 retval = new CKEDITOR.dom.documentFragment( doc ),
112 rootNode = null,
113 currentIndex = baseIndex,
114 indentLevel = Math.max( listArray[ baseIndex ].indent, 0 ),
115 currentListItem = null,
116 orgDir, block,
117 paragraphName = ( paragraphMode == CKEDITOR.ENTER_P ? 'p' : 'div' );
118
119 while ( 1 ) {
120 var item = listArray[ currentIndex ],
121 itemGrandParent = item.grandparent;
122
123 orgDir = item.element.getDirection( 1 );
124
125 if ( item.indent == indentLevel ) {
126 if ( !rootNode || listArray[ currentIndex ].parent.getName() != rootNode.getName() ) {
127 rootNode = listArray[ currentIndex ].parent.clone( false, 1 );
128 dir && rootNode.setAttribute( 'dir', dir );
129 retval.append( rootNode );
130 }
131 currentListItem = rootNode.append( item.element.clone( 0, 1 ) );
132
133 if ( orgDir != rootNode.getDirection( 1 ) )
134 currentListItem.setAttribute( 'dir', orgDir );
135
136 for ( i = 0; i < item.contents.length; i++ )
137 currentListItem.append( item.contents[ i ].clone( 1, 1 ) );
138 currentIndex++;
139 } else if ( item.indent == Math.max( indentLevel, 0 ) + 1 ) {
140 // Maintain original direction (#6861).
141 var currDir = listArray[ currentIndex - 1 ].element.getDirection( 1 ),
142 listData = CKEDITOR.plugins.list.arrayToList( listArray, null, currentIndex, paragraphMode, currDir != orgDir ? orgDir : null );
143
144 // If the next block is an <li> with another list tree as the first
145 // child, we'll need to append a filler (<br>/NBSP) or the list item
146 // wouldn't be editable. (#6724)
147 if ( !currentListItem.getChildCount() && CKEDITOR.env.needsNbspFiller && doc.$.documentMode <= 7 )
148 currentListItem.append( doc.createText( '\xa0' ) );
149 currentListItem.append( listData.listNode );
150 currentIndex = listData.nextIndex;
151 } else if ( item.indent == -1 && !baseIndex && itemGrandParent ) {
152 if ( listNodeNames[ itemGrandParent.getName() ] ) {
153 currentListItem = item.element.clone( false, true );
154 if ( orgDir != itemGrandParent.getDirection( 1 ) )
155 currentListItem.setAttribute( 'dir', orgDir );
156 } else {
157 currentListItem = new CKEDITOR.dom.documentFragment( doc );
158 }
159
160 // Migrate all children to the new container,
161 // apply the proper text direction.
162 var dirLoose = itemGrandParent.getDirection( 1 ) != orgDir,
163 li = item.element,
164 className = li.getAttribute( 'class' ),
165 style = li.getAttribute( 'style' );
166
167 var needsBlock = currentListItem.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT && ( paragraphMode != CKEDITOR.ENTER_BR || dirLoose || style || className );
168
169 var child,
170 count = item.contents.length,
171 cachedBookmark;
172
173 for ( i = 0; i < count; i++ ) {
174 child = item.contents[ i ];
175
176 // Append bookmark if we can, or cache it and append it when we'll know
177 // what to do with it. Generally - we want to keep it next to its original neighbour.
178 // Exception: if bookmark is the only child it hasn't got any neighbour, so handle it normally
179 // (wrap with block if needed).
180 if ( bookmarks( child ) && count > 1 ) {
181 // If we don't need block, it's simple - append bookmark directly to the current list item.
182 if ( !needsBlock )
183 currentListItem.append( child.clone( 1, 1 ) );
184 else
185 cachedBookmark = child.clone( 1, 1 );
186 }
187 // Block content goes directly to the current list item, without wrapping.
188 else if ( child.type == CKEDITOR.NODE_ELEMENT && child.isBlockBoundary() ) {
189 // Apply direction on content blocks.
190 if ( dirLoose && !child.getDirection() )
191 child.setAttribute( 'dir', orgDir );
192
193 inheritInlineStyles( li, child );
194
195 className && child.addClass( className );
196
197 // Close the block which we started for inline content.
198 block = null;
199 // Append bookmark directly before current child.
200 if ( cachedBookmark ) {
201 currentListItem.append( cachedBookmark );
202 cachedBookmark = null;
203 }
204 // Append this block element to the list item.
205 currentListItem.append( child.clone( 1, 1 ) );
206 }
207 // Some inline content was found - wrap it with block and append that
208 // block to the current list item or append it to the block previously created.
209 else if ( needsBlock ) {
210 // Establish new block to hold text direction and styles.
211 if ( !block ) {
212 block = doc.createElement( paragraphName );
213 currentListItem.append( block );
214 dirLoose && block.setAttribute( 'dir', orgDir );
215 }
216
217 // Copy over styles to new block;
218 style && block.setAttribute( 'style', style );
219 className && block.setAttribute( 'class', className );
220
221 // Append bookmark directly before current child.
222 if ( cachedBookmark ) {
223 block.append( cachedBookmark );
224 cachedBookmark = null;
225 }
226 block.append( child.clone( 1, 1 ) );
227 }
228 // E.g. BR mode - inline content appended directly to the list item.
229 else {
230 currentListItem.append( child.clone( 1, 1 ) );
231 }
232 }
233
234 // No content after bookmark - append it to the block if we had one
235 // or directly to the current list item if we finished directly in the current list item.
236 if ( cachedBookmark ) {
237 ( block || currentListItem ).append( cachedBookmark );
238 cachedBookmark = null;
239 }
240
241 if ( currentListItem.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT && currentIndex != listArray.length - 1 ) {
242 var last;
243
244 // Remove bogus <br> if this browser uses them.
245 if ( CKEDITOR.env.needsBrFiller ) {
246 last = currentListItem.getLast();
247 if ( last && last.type == CKEDITOR.NODE_ELEMENT && last.is( 'br' ) )
248 last.remove();
249 }
250
251 // If the last element is not a block, append <br> to separate merged list items.
252 last = currentListItem.getLast( nonEmpty );
253 if ( !( last && last.type == CKEDITOR.NODE_ELEMENT && last.is( CKEDITOR.dtd.$block ) ) )
254 currentListItem.append( doc.createElement( 'br' ) );
255 }
256
257 var currentListItemName = currentListItem.$.nodeName.toLowerCase();
258 if ( currentListItemName == 'div' || currentListItemName == 'p' ) {
259 currentListItem.appendBogus();
260 }
261 retval.append( currentListItem );
262 rootNode = null;
263 currentIndex++;
264 } else {
265 return null;
266 }
267
268 block = null;
269
270 if ( listArray.length <= currentIndex || Math.max( listArray[ currentIndex ].indent, 0 ) < indentLevel )
271 break;
272 }
273
274 if ( database ) {
275 var currentNode = retval.getFirst();
276
277 while ( currentNode ) {
278 if ( currentNode.type == CKEDITOR.NODE_ELEMENT ) {
279 // Clear marker attributes for the new list tree made of cloned nodes, if any.
280 CKEDITOR.dom.element.clearMarkers( database, currentNode );
281
282 // Clear redundant direction attribute specified on list items.
283 if ( currentNode.getName() in CKEDITOR.dtd.$listItem )
284 cleanUpDirection( currentNode );
285 }
286
287 currentNode = currentNode.getNextSourceNode();
288 }
289 }
290
291 return { listNode: retval, nextIndex: currentIndex };
292 }
293 };
294
295 function changeListType( editor, groupObj, database, listsCreated ) {
296 // This case is easy...
297 // 1. Convert the whole list into a one-dimensional array.
298 // 2. Change the list type by modifying the array.
299 // 3. Recreate the whole list by converting the array to a list.
300 // 4. Replace the original list with the recreated list.
301 var listArray = CKEDITOR.plugins.list.listToArray( groupObj.root, database ),
302 selectedListItems = [];
303
304 for ( var i = 0; i < groupObj.contents.length; i++ ) {
305 var itemNode = groupObj.contents[ i ];
306 itemNode = itemNode.getAscendant( 'li', true );
307 if ( !itemNode || itemNode.getCustomData( 'list_item_processed' ) )
308 continue;
309 selectedListItems.push( itemNode );
310 CKEDITOR.dom.element.setMarker( database, itemNode, 'list_item_processed', true );
311 }
312
313 var root = groupObj.root,
314 doc = root.getDocument(),
315 listNode, newListNode;
316
317 for ( i = 0; i < selectedListItems.length; i++ ) {
318 var listIndex = selectedListItems[ i ].getCustomData( 'listarray_index' );
319 listNode = listArray[ listIndex ].parent;
320
321 // Switch to new list node for this particular item.
322 if ( !listNode.is( this.type ) ) {
323 newListNode = doc.createElement( this.type );
324 // Copy all attributes, except from 'start' and 'type'.
325 listNode.copyAttributes( newListNode, { start: 1, type: 1 } );
326 // The list-style-type property should be ignored.
327 newListNode.removeStyle( 'list-style-type' );
328 listArray[ listIndex ].parent = newListNode;
329 }
330 }
331
332 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode );
333 var child,
334 length = newList.listNode.getChildCount();
335 for ( i = 0; i < length && ( child = newList.listNode.getChild( i ) ); i++ ) {
336 if ( child.getName() == this.type )
337 listsCreated.push( child );
338 }
339 newList.listNode.replace( groupObj.root );
340
341 editor.fire( 'contentDomInvalidated' );
342 }
343
344 function createList( editor, groupObj, listsCreated ) {
345 var contents = groupObj.contents,
346 doc = groupObj.root.getDocument(),
347 listContents = [];
348
349 // It is possible to have the contents returned by DomRangeIterator to be the same as the root.
350 // e.g. when we're running into table cells.
351 // In such a case, enclose the childNodes of contents[0] into a <div>.
352 if ( contents.length == 1 && contents[ 0 ].equals( groupObj.root ) ) {
353 var divBlock = doc.createElement( 'div' );
354 contents[ 0 ].moveChildren && contents[ 0 ].moveChildren( divBlock );
355 contents[ 0 ].append( divBlock );
356 contents[ 0 ] = divBlock;
357 }
358
359 // Calculate the common parent node of all content blocks.
360 var commonParent = groupObj.contents[ 0 ].getParent();
361 for ( var i = 0; i < contents.length; i++ )
362 commonParent = commonParent.getCommonAncestor( contents[ i ].getParent() );
363
364 var useComputedState = editor.config.useComputedState,
365 listDir, explicitDirection;
366
367 useComputedState = useComputedState === undefined || useComputedState;
368
369 // We want to insert things that are in the same tree level only, so calculate the contents again
370 // by expanding the selected blocks to the same tree level.
371 for ( i = 0; i < contents.length; i++ ) {
372 var contentNode = contents[ i ],
373 parentNode;
374 while ( ( parentNode = contentNode.getParent() ) ) {
375 if ( parentNode.equals( commonParent ) ) {
376 listContents.push( contentNode );
377
378 // Determine the lists's direction.
379 if ( !explicitDirection && contentNode.getDirection() )
380 explicitDirection = 1;
381
382 var itemDir = contentNode.getDirection( useComputedState );
383
384 if ( listDir !== null ) {
385 // If at least one LI have a different direction than current listDir, we can't have listDir.
386 if ( listDir && listDir != itemDir )
387 listDir = null;
388 else
389 listDir = itemDir;
390 }
391
392 break;
393 }
394 contentNode = parentNode;
395 }
396 }
397
398 if ( listContents.length < 1 )
399 return;
400
401 // Insert the list to the DOM tree.
402 var insertAnchor = listContents[ listContents.length - 1 ].getNext(),
403 listNode = doc.createElement( this.type );
404
405 listsCreated.push( listNode );
406
407 var contentBlock, listItem;
408
409 while ( listContents.length ) {
410 contentBlock = listContents.shift();
411 listItem = doc.createElement( 'li' );
412
413 // If current block should be preserved, append it to list item instead of
414 // transforming it to <li> element.
415 if ( shouldPreserveBlock( contentBlock ) )
416 contentBlock.appendTo( listItem );
417 else {
418 contentBlock.copyAttributes( listItem );
419 // Remove direction attribute after it was merged into list root. (#7657)
420 if ( listDir && contentBlock.getDirection() ) {
421 listItem.removeStyle( 'direction' );
422 listItem.removeAttribute( 'dir' );
423 }
424 contentBlock.moveChildren( listItem );
425 contentBlock.remove();
426 }
427
428 listItem.appendTo( listNode );
429 }
430
431 // Apply list root dir only if it has been explicitly declared.
432 if ( listDir && explicitDirection )
433 listNode.setAttribute( 'dir', listDir );
434
435 if ( insertAnchor )
436 listNode.insertBefore( insertAnchor );
437 else
438 listNode.appendTo( commonParent );
439 }
440
441 function removeList( editor, groupObj, database ) {
442 // This is very much like the change list type operation.
443 // Except that we're changing the selected items' indent to -1 in the list array.
444 var listArray = CKEDITOR.plugins.list.listToArray( groupObj.root, database ),
445 selectedListItems = [];
446
447 for ( var i = 0; i < groupObj.contents.length; i++ ) {
448 var itemNode = groupObj.contents[ i ];
449 itemNode = itemNode.getAscendant( 'li', true );
450 if ( !itemNode || itemNode.getCustomData( 'list_item_processed' ) )
451 continue;
452 selectedListItems.push( itemNode );
453 CKEDITOR.dom.element.setMarker( database, itemNode, 'list_item_processed', true );
454 }
455
456 var lastListIndex = null;
457 for ( i = 0; i < selectedListItems.length; i++ ) {
458 var listIndex = selectedListItems[ i ].getCustomData( 'listarray_index' );
459 listArray[ listIndex ].indent = -1;
460 lastListIndex = listIndex;
461 }
462
463 // After cutting parts of the list out with indent=-1, we still have to maintain the array list
464 // model's nextItem.indent <= currentItem.indent + 1 invariant. Otherwise the array model of the
465 // list cannot be converted back to a real DOM list.
466 for ( i = lastListIndex + 1; i < listArray.length; i++ ) {
467 if ( listArray[ i ].indent > listArray[ i - 1 ].indent + 1 ) {
468 var indentOffset = listArray[ i - 1 ].indent + 1 - listArray[ i ].indent;
469 var oldIndent = listArray[ i ].indent;
470 while ( listArray[ i ] && listArray[ i ].indent >= oldIndent ) {
471 listArray[ i ].indent += indentOffset;
472 i++;
473 }
474 i--;
475 }
476 }
477
478 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, groupObj.root.getAttribute( 'dir' ) );
479
480 // Compensate <br> before/after the list node if the surrounds are non-blocks.(#3836)
481 var docFragment = newList.listNode,
482 boundaryNode, siblingNode;
483
484 function compensateBrs( isStart ) {
485 if (
486 ( boundaryNode = docFragment[ isStart ? 'getFirst' : 'getLast' ]() ) &&
487 !( boundaryNode.is && boundaryNode.isBlockBoundary() ) &&
488 ( siblingNode = groupObj.root[ isStart ? 'getPrevious' : 'getNext' ]( CKEDITOR.dom.walker.invisible( true ) ) ) &&
489 !( siblingNode.is && siblingNode.isBlockBoundary( { br: 1 } ) )
490 ) {
491 editor.document.createElement( 'br' )[ isStart ? 'insertBefore' : 'insertAfter' ]( boundaryNode );
492 }
493 }
494 compensateBrs( true );
495 compensateBrs();
496
497 docFragment.replace( groupObj.root );
498
499 editor.fire( 'contentDomInvalidated' );
500 }
501
502 var headerTagRegex = /^h[1-6]$/;
503
504 // Checks wheather this block should be element preserved (not transformed to <li>) when creating list.
505 function shouldPreserveBlock( block ) {
506 return (
507 // #5335
508 block.is( 'pre' ) ||
509 // #5271 - this is a header.
510 headerTagRegex.test( block.getName() ) ||
511 // 11083 - this is a non-editable element.
512 block.getAttribute( 'contenteditable' ) == 'false'
513 );
514 }
515
516 function listCommand( name, type ) {
517 this.name = name;
518 this.type = type;
519 this.context = type;
520 this.allowedContent = type + ' li';
521 this.requiredContent = type;
522 }
523
524 var elementType = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT );
525
526 // Merge child nodes with direction preserved. (#7448)
527 function mergeChildren( from, into, refNode, forward ) {
528 var child, itemDir;
529 while ( ( child = from[ forward ? 'getLast' : 'getFirst' ]( elementType ) ) ) {
530 if ( ( itemDir = child.getDirection( 1 ) ) !== into.getDirection( 1 ) )
531 child.setAttribute( 'dir', itemDir );
532
533 child.remove();
534
535 refNode ? child[ forward ? 'insertBefore' : 'insertAfter' ]( refNode ) : into.append( child, forward );
536 }
537 }
538
539 listCommand.prototype = {
540 exec: function( editor ) {
541 // Run state check first of all.
542 this.refresh( editor, editor.elementPath() );
543
544 var config = editor.config,
545 selection = editor.getSelection(),
546 ranges = selection && selection.getRanges();
547
548 // Midas lists rule #1 says we can create a list even in an empty document.
549 // But DOM iterator wouldn't run if the document is really empty.
550 // So create a paragraph if the document is empty and we're going to create a list.
551 if ( this.state == CKEDITOR.TRISTATE_OFF ) {
552 var editable = editor.editable();
553 if ( !editable.getFirst( nonEmpty ) ) {
554 config.enterMode == CKEDITOR.ENTER_BR ? editable.appendBogus() : ranges[ 0 ].fixBlock( 1, config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' );
555
556 selection.selectRanges( ranges );
557 }
558 // Maybe a single range there enclosing the whole list,
559 // turn on the list state manually(#4129).
560 else {
561 var range = ranges.length == 1 && ranges[ 0 ],
562 enclosedNode = range && range.getEnclosedNode();
563 if ( enclosedNode && enclosedNode.is && this.type == enclosedNode.getName() )
564 this.setState( CKEDITOR.TRISTATE_ON );
565 }
566 }
567
568 var bookmarks = selection.createBookmarks( true );
569
570 // Group the blocks up because there are many cases where multiple lists have to be created,
571 // or multiple lists have to be cancelled.
572 var listGroups = [],
573 database = {},
574 rangeIterator = ranges.createIterator(),
575 index = 0;
576
577 while ( ( range = rangeIterator.getNextRange() ) && ++index ) {
578 var boundaryNodes = range.getBoundaryNodes(),
579 startNode = boundaryNodes.startNode,
580 endNode = boundaryNodes.endNode;
581
582 if ( startNode.type == CKEDITOR.NODE_ELEMENT && startNode.getName() == 'td' )
583 range.setStartAt( boundaryNodes.startNode, CKEDITOR.POSITION_AFTER_START );
584
585 if ( endNode.type == CKEDITOR.NODE_ELEMENT && endNode.getName() == 'td' )
586 range.setEndAt( boundaryNodes.endNode, CKEDITOR.POSITION_BEFORE_END );
587
588 var iterator = range.createIterator(),
589 block;
590
591 iterator.forceBrBreak = ( this.state == CKEDITOR.TRISTATE_OFF );
592
593 while ( ( block = iterator.getNextParagraph() ) ) {
594 // Avoid duplicate blocks get processed across ranges.
595 if ( block.getCustomData( 'list_block' ) )
596 continue;
597 else
598 CKEDITOR.dom.element.setMarker( database, block, 'list_block', 1 );
599
600 var path = editor.elementPath( block ),
601 pathElements = path.elements,
602 pathElementsCount = pathElements.length,
603 processedFlag = 0,
604 blockLimit = path.blockLimit,
605 element;
606
607 // First, try to group by a list ancestor.
608 for ( var i = pathElementsCount - 1; i >= 0 && ( element = pathElements[ i ] ); i-- ) {
609 // Don't leak outside block limit (#3940).
610 if ( listNodeNames[ element.getName() ] && blockLimit.contains( element ) ) {
611 // If we've encountered a list inside a block limit
612 // The last group object of the block limit element should
613 // no longer be valid. Since paragraphs after the list
614 // should belong to a different group of paragraphs before
615 // the list. (Bug #1309)
616 blockLimit.removeCustomData( 'list_group_object_' + index );
617
618 var groupObj = element.getCustomData( 'list_group_object' );
619 if ( groupObj )
620 groupObj.contents.push( block );
621 else {
622 groupObj = { root: element, contents: [ block ] };
623 listGroups.push( groupObj );
624 CKEDITOR.dom.element.setMarker( database, element, 'list_group_object', groupObj );
625 }
626 processedFlag = 1;
627 break;
628 }
629 }
630
631 if ( processedFlag )
632 continue;
633
634 // No list ancestor? Group by block limit, but don't mix contents from different ranges.
635 var root = blockLimit;
636 if ( root.getCustomData( 'list_group_object_' + index ) )
637 root.getCustomData( 'list_group_object_' + index ).contents.push( block );
638 else {
639 groupObj = { root: root, contents: [ block ] };
640 CKEDITOR.dom.element.setMarker( database, root, 'list_group_object_' + index, groupObj );
641 listGroups.push( groupObj );
642 }
643 }
644 }
645
646 // Now we have two kinds of list groups, groups rooted at a list, and groups rooted at a block limit element.
647 // We either have to build lists or remove lists, for removing a list does not makes sense when we are looking
648 // at the group that's not rooted at lists. So we have three cases to handle.
649 var listsCreated = [];
650 while ( listGroups.length > 0 ) {
651 groupObj = listGroups.shift();
652 if ( this.state == CKEDITOR.TRISTATE_OFF ) {
653 if ( listNodeNames[ groupObj.root.getName() ] )
654 changeListType.call( this, editor, groupObj, database, listsCreated );
655 else
656 createList.call( this, editor, groupObj, listsCreated );
657 } else if ( this.state == CKEDITOR.TRISTATE_ON && listNodeNames[ groupObj.root.getName() ] ) {
658 removeList.call( this, editor, groupObj, database );
659 }
660 }
661
662 // For all new lists created, merge into adjacent, same type lists.
663 for ( i = 0; i < listsCreated.length; i++ )
664 mergeListSiblings( listsCreated[ i ] );
665
666 // Clean up, restore selection and update toolbar button states.
667 CKEDITOR.dom.element.clearAllMarkers( database );
668 selection.selectBookmarks( bookmarks );
669 editor.focus();
670 },
671
672 refresh: function( editor, path ) {
673 var list = path.contains( listNodeNames, 1 ),
674 limit = path.blockLimit || path.root;
675
676 // 1. Only a single type of list activate.
677 // 2. Do not show list outside of block limit.
678 if ( list && limit.contains( list ) )
679 this.setState( list.is( this.type ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
680 else
681 this.setState( CKEDITOR.TRISTATE_OFF );
682 }
683 };
684
685 // Merge list adjacent, of same type lists.
686 function mergeListSiblings( listNode ) {
687
688 function mergeSibling( rtl ) {
689 var sibling = listNode[ rtl ? 'getPrevious' : 'getNext' ]( nonEmpty );
690 if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT && sibling.is( listNode.getName() ) ) {
691 // Move children order by merge direction.(#3820)
692 mergeChildren( listNode, sibling, null, !rtl );
693
694 listNode.remove();
695 listNode = sibling;
696 }
697 }
698
699 mergeSibling();
700 mergeSibling( 1 );
701 }
702
703 // Check if node is block element that recieves text.
704 function isTextBlock( node ) {
705 return node.type == CKEDITOR.NODE_ELEMENT && ( node.getName() in CKEDITOR.dtd.$block || node.getName() in CKEDITOR.dtd.$listItem ) && CKEDITOR.dtd[ node.getName() ][ '#' ];
706 }
707
708 // Join visually two block lines.
709 function joinNextLineToCursor( editor, cursor, nextCursor ) {
710 editor.fire( 'saveSnapshot' );
711
712 // Merge with previous block's content.
713 nextCursor.enlarge( CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS );
714 var frag = nextCursor.extractContents();
715
716 cursor.trim( false, true );
717 var bm = cursor.createBookmark();
718
719 // Kill original bogus;
720 var currentPath = new CKEDITOR.dom.elementPath( cursor.startContainer ),
721 pathBlock = currentPath.block,
722 currentBlock = currentPath.lastElement.getAscendant( 'li', 1 ) || pathBlock,
723 nextPath = new CKEDITOR.dom.elementPath( nextCursor.startContainer ),
724 nextLi = nextPath.contains( CKEDITOR.dtd.$listItem ),
725 nextList = nextPath.contains( CKEDITOR.dtd.$list ),
726 last;
727
728 // Remove bogus node the current block/pseudo block.
729 if ( pathBlock ) {
730 var bogus = pathBlock.getBogus();
731 bogus && bogus.remove();
732 }
733 else if ( nextList ) {
734 last = nextList.getPrevious( nonEmpty );
735 if ( last && blockBogus( last ) )
736 last.remove();
737 }
738
739 // Kill the tail br in extracted.
740 last = frag.getLast();
741 if ( last && last.type == CKEDITOR.NODE_ELEMENT && last.is( 'br' ) )
742 last.remove();
743
744 // Insert fragment at the range position.
745 var nextNode = cursor.startContainer.getChild( cursor.startOffset );
746 if ( nextNode )
747 frag.insertBefore( nextNode );
748 else
749 cursor.startContainer.append( frag );
750
751 // Move the sub list nested in the next list item.
752 if ( nextLi ) {
753 var sublist = getSubList( nextLi );
754 if ( sublist ) {
755 // If next line is in the sub list of the current list item.
756 if ( currentBlock.contains( nextLi ) ) {
757 mergeChildren( sublist, nextLi.getParent(), nextLi );
758 sublist.remove();
759 }
760 // Migrate the sub list to current list item.
761 else {
762 currentBlock.append( sublist );
763 }
764 }
765 }
766
767 var nextBlock, parent;
768 // Remove any remaining zombies path blocks at the end after line merged.
769 while ( nextCursor.checkStartOfBlock() && nextCursor.checkEndOfBlock() ) {
770 nextPath = nextCursor.startPath();
771 nextBlock = nextPath.block;
772
773 // Abort when nothing to be removed (#10890).
774 if ( !nextBlock )
775 break;
776
777 // Check if also to remove empty list.
778 if ( nextBlock.is( 'li' ) ) {
779 parent = nextBlock.getParent();
780 if ( nextBlock.equals( parent.getLast( nonEmpty ) ) && nextBlock.equals( parent.getFirst( nonEmpty ) ) )
781 nextBlock = parent;
782 }
783
784 nextCursor.moveToPosition( nextBlock, CKEDITOR.POSITION_BEFORE_START );
785 nextBlock.remove();
786 }
787
788 // Check if need to further merge with the list resides after the merged block. (#9080)
789 var walkerRng = nextCursor.clone(), editable = editor.editable();
790 walkerRng.setEndAt( editable, CKEDITOR.POSITION_BEFORE_END );
791 var walker = new CKEDITOR.dom.walker( walkerRng );
792 walker.evaluator = function( node ) {
793 return nonEmpty( node ) && !blockBogus( node );
794 };
795 var next = walker.next();
796 if ( next && next.type == CKEDITOR.NODE_ELEMENT && next.getName() in CKEDITOR.dtd.$list )
797 mergeListSiblings( next );
798
799 cursor.moveToBookmark( bm );
800
801 // Make fresh selection.
802 cursor.select();
803
804 editor.fire( 'saveSnapshot' );
805 }
806
807 function getSubList( li ) {
808 var last = li.getLast( nonEmpty );
809 return last && last.type == CKEDITOR.NODE_ELEMENT && last.getName() in listNodeNames ? last : null;
810 }
811
812 CKEDITOR.plugins.add( 'list', {
813 // jscs:disable maximumLineLength
814 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
815 // jscs:enable maximumLineLength
816 icons: 'bulletedlist,bulletedlist-rtl,numberedlist,numberedlist-rtl', // %REMOVE_LINE_CORE%
817 hidpi: true, // %REMOVE_LINE_CORE%
818 requires: 'indentlist',
819 init: function( editor ) {
820 if ( editor.blockless )
821 return;
822
823 // Register commands.
824 editor.addCommand( 'numberedlist', new listCommand( 'numberedlist', 'ol' ) );
825 editor.addCommand( 'bulletedlist', new listCommand( 'bulletedlist', 'ul' ) );
826
827 // Register the toolbar button.
828 if ( editor.ui.addButton ) {
829 editor.ui.addButton( 'NumberedList', {
830 label: editor.lang.list.numberedlist,
831 command: 'numberedlist',
832 directional: true,
833 toolbar: 'list,10'
834 } );
835 editor.ui.addButton( 'BulletedList', {
836 label: editor.lang.list.bulletedlist,
837 command: 'bulletedlist',
838 directional: true,
839 toolbar: 'list,20'
840 } );
841 }
842
843 // Handled backspace/del key to join list items. (#8248,#9080)
844 editor.on( 'key', function( evt ) {
845 // Use getKey directly in order to ignore modifiers.
846 // Justification: http://dev.ckeditor.com/ticket/11861#comment:13
847 var key = evt.data.domEvent.getKey(), li;
848
849 // DEl/BACKSPACE
850 if ( editor.mode == 'wysiwyg' && key in { 8: 1, 46: 1 } ) {
851 var sel = editor.getSelection(),
852 range = sel.getRanges()[ 0 ],
853 path = range && range.startPath();
854
855 if ( !range || !range.collapsed )
856 return;
857
858 var isBackspace = key == 8;
859 var editable = editor.editable();
860 var walker = new CKEDITOR.dom.walker( range.clone() );
861 walker.evaluator = function( node ) {
862 return nonEmpty( node ) && !blockBogus( node );
863 };
864 // Backspace/Del behavior at the start/end of table is handled in core.
865 walker.guard = function( node, isOut ) {
866 return !( isOut && node.type == CKEDITOR.NODE_ELEMENT && node.is( 'table' ) );
867 };
868
869 var cursor = range.clone();
870
871 if ( isBackspace ) {
872 var previous, joinWith;
873
874 // Join a sub list's first line, with the previous visual line in parent.
875 if (
876 ( previous = path.contains( listNodeNames ) ) &&
877 range.checkBoundaryOfElement( previous, CKEDITOR.START ) &&
878 ( previous = previous.getParent() ) && previous.is( 'li' ) &&
879 ( previous = getSubList( previous ) )
880 ) {
881 joinWith = previous;
882 previous = previous.getPrevious( nonEmpty );
883 // Place cursor before the nested list.
884 cursor.moveToPosition(
885 previous && blockBogus( previous ) ? previous : joinWith,
886 CKEDITOR.POSITION_BEFORE_START );
887 }
888 // Join any line following a list, with the last visual line of the list.
889 else {
890 walker.range.setStartAt( editable, CKEDITOR.POSITION_AFTER_START );
891 walker.range.setEnd( range.startContainer, range.startOffset );
892
893 previous = walker.previous();
894
895 if (
896 previous && previous.type == CKEDITOR.NODE_ELEMENT &&
897 ( previous.getName() in listNodeNames ||
898 previous.is( 'li' ) )
899 ) {
900 if ( !previous.is( 'li' ) ) {
901 walker.range.selectNodeContents( previous );
902 walker.reset();
903 walker.evaluator = isTextBlock;
904 previous = walker.previous();
905 }
906
907 joinWith = previous;
908 // Place cursor at the end of previous block.
909 cursor.moveToElementEditEnd( joinWith );
910
911 // And then just before end of closest block element (#12729).
912 cursor.moveToPosition( cursor.endPath().block, CKEDITOR.POSITION_BEFORE_END );
913 }
914 }
915
916 if ( joinWith ) {
917 joinNextLineToCursor( editor, cursor, range );
918 evt.cancel();
919 }
920 else {
921 var list = path.contains( listNodeNames );
922 // Backspace pressed at the start of list outdents the first list item. (#9129)
923 if ( list && range.checkBoundaryOfElement( list, CKEDITOR.START ) ) {
924 li = list.getFirst( nonEmpty );
925
926 if ( range.checkBoundaryOfElement( li, CKEDITOR.START ) ) {
927 previous = list.getPrevious( nonEmpty );
928
929 // Only if the list item contains a sub list, do nothing but
930 // simply move cursor backward one character.
931 if ( getSubList( li ) ) {
932 if ( previous ) {
933 range.moveToElementEditEnd( previous );
934 range.select();
935 }
936
937 evt.cancel();
938 }
939 else {
940 editor.execCommand( 'outdent' );
941 evt.cancel();
942 }
943 }
944 }
945 }
946
947 } else {
948 var next, nextLine;
949
950 li = path.contains( 'li' );
951
952 if ( li ) {
953 walker.range.setEndAt( editable, CKEDITOR.POSITION_BEFORE_END );
954
955 var last = li.getLast( nonEmpty );
956 var block = last && isTextBlock( last ) ? last : li;
957
958 // Indicate cursor at the visual end of an list item.
959 var isAtEnd = 0;
960
961 next = walker.next();
962
963 // When list item contains a sub list.
964 if (
965 next && next.type == CKEDITOR.NODE_ELEMENT &&
966 next.getName() in listNodeNames &&
967 next.equals( last )
968 ) {
969 isAtEnd = 1;
970
971 // Move to the first item in sub list.
972 next = walker.next();
973 }
974 // Right at the end of list item.
975 else if ( range.checkBoundaryOfElement( block, CKEDITOR.END ) ) {
976 isAtEnd = 2;
977 }
978
979 if ( isAtEnd && next ) {
980 // Put cursor range there.
981 nextLine = range.clone();
982 nextLine.moveToElementEditStart( next );
983
984 // #13409
985 // For the following case and similar
986 //
987 // <ul>
988 // <li>
989 // <p><a href="#one"><em>x^</em></a></p>
990 // <ul>
991 // <li><span>y</span></li>
992 // </ul>
993 // </li>
994 // </ul>
995 if ( isAtEnd == 1 ) {
996 // Move the cursor to <em> if attached to "x" text node.
997 cursor.optimize();
998
999 // Abort if the range is attached directly in <li>, like
1000 //
1001 // <ul>
1002 // <li>
1003 // x^
1004 // <ul>
1005 // <li><span>y</span></li>
1006 // </ul>
1007 // </li>
1008 // </ul>
1009 if ( !cursor.startContainer.equals( li ) ) {
1010 var node = cursor.startContainer,
1011 farthestInlineAscendant;
1012
1013 // Find <a>, which is farthest from <em> but still inline element.
1014 while ( node.is( CKEDITOR.dtd.$inline ) ) {
1015 farthestInlineAscendant = node;
1016 node = node.getParent();
1017 }
1018
1019 // Move the range so it does not contain inline elements.
1020 // It prevents <span> from being included in <em>.
1021 //
1022 // <ul>
1023 // <li>
1024 // <p><a href="#one"><em>x</em></a>^</p>
1025 // <ul>
1026 // <li><span>y</span></li>
1027 // </ul>
1028 // </li>
1029 // </ul>
1030 //
1031 // so instead of
1032 //
1033 // <ul>
1034 // <li>
1035 // <p><a href="#one"><em>x^<span>y</span></em></a></p>
1036 // </li>
1037 // </ul>
1038 //
1039 // pressing DELETE produces
1040 //
1041 // <ul>
1042 // <li>
1043 // <p><a href="#one"><em>x</em></a>^<span>y</span></p>
1044 // </li>
1045 // </ul>
1046 if ( farthestInlineAscendant ) {
1047 cursor.moveToPosition( farthestInlineAscendant, CKEDITOR.POSITION_AFTER_END );
1048 }
1049 }
1050 }
1051
1052 // Moving `cursor` and `next line` only when at the end literally (#12729).
1053 if ( isAtEnd == 2 ) {
1054 cursor.moveToPosition( cursor.endPath().block, CKEDITOR.POSITION_BEFORE_END );
1055
1056 // Next line might be text node not wrapped in block element.
1057 if ( nextLine.endPath().block ) {
1058 nextLine.moveToPosition( nextLine.endPath().block, CKEDITOR.POSITION_AFTER_START );
1059 }
1060 }
1061
1062 joinNextLineToCursor( editor, cursor, nextLine );
1063 evt.cancel();
1064 }
1065 } else {
1066 // Handle Del key pressed before the list.
1067 walker.range.setEndAt( editable, CKEDITOR.POSITION_BEFORE_END );
1068 next = walker.next();
1069
1070 if ( next && next.type == CKEDITOR.NODE_ELEMENT && next.is( listNodeNames ) ) {
1071 // The start <li>
1072 next = next.getFirst( nonEmpty );
1073
1074 // Simply remove the current empty block, move cursor to the
1075 // subsequent list.
1076 if ( path.block && range.checkStartOfBlock() && range.checkEndOfBlock() ) {
1077 path.block.remove();
1078 range.moveToElementEditStart( next );
1079 range.select();
1080 evt.cancel();
1081 }
1082 // Preventing the default (merge behavior), but simply move
1083 // the cursor one character forward if subsequent list item
1084 // contains sub list.
1085 else if ( getSubList( next ) ) {
1086 range.moveToElementEditStart( next );
1087 range.select();
1088 evt.cancel();
1089 }
1090 // Merge the first list item with the current line.
1091 else {
1092 nextLine = range.clone();
1093 nextLine.moveToElementEditStart( next );
1094 joinNextLineToCursor( editor, cursor, nextLine );
1095 evt.cancel();
1096 }
1097 }
1098 }
1099
1100 }
1101
1102 // The backspace/del could potentially put cursor at a bad position,
1103 // being it handled or not, check immediately the selection to have it fixed.
1104 setTimeout( function() {
1105 editor.selectionChange( 1 );
1106 } );
1107 }
1108 } );
1109 }
1110 } );
1111} )();
diff --git a/sources/plugins/listblock/plugin.js b/sources/plugins/listblock/plugin.js
new file mode 100644
index 0000000..21e6b08
--- /dev/null
+++ b/sources/plugins/listblock/plugin.js
@@ -0,0 +1,241 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'listblock', {
7 requires: 'panel',
8
9 onLoad: function() {
10 var list = CKEDITOR.addTemplate( 'panel-list', '<ul role="presentation" class="cke_panel_list">{items}</ul>' ),
11 listItem = CKEDITOR.addTemplate( 'panel-list-item', '<li id="{id}" class="cke_panel_listItem" role=presentation>' +
12 '<a id="{id}_option" _cke_focus=1 hidefocus=true' +
13 ' title="{title}"' +
14 ' href="javascript:void(\'{val}\')" ' +
15 ' {onclick}="CKEDITOR.tools.callFunction({clickFn},\'{val}\'); return false;"' + // #188
16 ' role="option">' +
17 '{text}' +
18 '</a>' +
19 '</li>' ),
20 listGroup = CKEDITOR.addTemplate( 'panel-list-group', '<h1 id="{id}" class="cke_panel_grouptitle" role="presentation" >{label}</h1>' ),
21 reSingleQuote = /\'/g,
22 escapeSingleQuotes = function( str ) {
23 return str.replace( reSingleQuote, '\\\'' );
24 };
25
26 CKEDITOR.ui.panel.prototype.addListBlock = function( name, definition ) {
27 return this.addBlock( name, new CKEDITOR.ui.listBlock( this.getHolderElement(), definition ) );
28 };
29
30 CKEDITOR.ui.listBlock = CKEDITOR.tools.createClass( {
31 base: CKEDITOR.ui.panel.block,
32
33 $: function( blockHolder, blockDefinition ) {
34 blockDefinition = blockDefinition || {};
35
36 var attribs = blockDefinition.attributes || ( blockDefinition.attributes = {} );
37 ( this.multiSelect = !!blockDefinition.multiSelect ) && ( attribs[ 'aria-multiselectable' ] = true );
38 // Provide default role of 'listbox'.
39 !attribs.role && ( attribs.role = 'listbox' );
40
41 // Call the base contructor.
42 this.base.apply( this, arguments );
43
44 // Set the proper a11y attributes.
45 this.element.setAttribute( 'role', attribs.role );
46
47 var keys = this.keys;
48 keys[ 40 ] = 'next'; // ARROW-DOWN
49 keys[ 9 ] = 'next'; // TAB
50 keys[ 38 ] = 'prev'; // ARROW-UP
51 keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB
52 keys[ 32 ] = CKEDITOR.env.ie ? 'mouseup' : 'click'; // SPACE
53 CKEDITOR.env.ie && ( keys[ 13 ] = 'mouseup' ); // Manage ENTER, since onclick is blocked in IE (#8041).
54
55 this._.pendingHtml = [];
56 this._.pendingList = [];
57 this._.items = {};
58 this._.groups = {};
59 },
60
61 _: {
62 close: function() {
63 if ( this._.started ) {
64 var output = list.output( { items: this._.pendingList.join( '' ) } );
65 this._.pendingList = [];
66 this._.pendingHtml.push( output );
67 delete this._.started;
68 }
69 },
70
71 getClick: function() {
72 if ( !this._.click ) {
73 this._.click = CKEDITOR.tools.addFunction( function( value ) {
74 var marked = this.toggle( value );
75 if ( this.onClick )
76 this.onClick( value, marked );
77 }, this );
78 }
79 return this._.click;
80 }
81 },
82
83 proto: {
84 add: function( value, html, title ) {
85 var id = CKEDITOR.tools.getNextId();
86
87 if ( !this._.started ) {
88 this._.started = 1;
89 this._.size = this._.size || 0;
90 }
91
92 this._.items[ value ] = id;
93
94 var data = {
95 id: id,
96 val: escapeSingleQuotes( CKEDITOR.tools.htmlEncodeAttr( value ) ),
97 onclick: CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick',
98 clickFn: this._.getClick(),
99 title: CKEDITOR.tools.htmlEncodeAttr( title || value ),
100 text: html || value
101 };
102
103 this._.pendingList.push( listItem.output( data ) );
104 },
105
106 startGroup: function( title ) {
107 this._.close();
108
109 var id = CKEDITOR.tools.getNextId();
110
111 this._.groups[ title ] = id;
112
113 this._.pendingHtml.push( listGroup.output( { id: id, label: title } ) );
114 },
115
116 commit: function() {
117 this._.close();
118 this.element.appendHtml( this._.pendingHtml.join( '' ) );
119 delete this._.size;
120
121 this._.pendingHtml = [];
122 },
123
124 toggle: function( value ) {
125 var isMarked = this.isMarked( value );
126
127 if ( isMarked )
128 this.unmark( value );
129 else
130 this.mark( value );
131
132 return !isMarked;
133 },
134
135 hideGroup: function( groupTitle ) {
136 var group = this.element.getDocument().getById( this._.groups[ groupTitle ] ),
137 list = group && group.getNext();
138
139 if ( group ) {
140 group.setStyle( 'display', 'none' );
141
142 if ( list && list.getName() == 'ul' )
143 list.setStyle( 'display', 'none' );
144 }
145 },
146
147 hideItem: function( value ) {
148 this.element.getDocument().getById( this._.items[ value ] ).setStyle( 'display', 'none' );
149 },
150
151 showAll: function() {
152 var items = this._.items,
153 groups = this._.groups,
154 doc = this.element.getDocument();
155
156 for ( var value in items ) {
157 doc.getById( items[ value ] ).setStyle( 'display', '' );
158 }
159
160 for ( var title in groups ) {
161 var group = doc.getById( groups[ title ] ),
162 list = group.getNext();
163
164 group.setStyle( 'display', '' );
165
166 if ( list && list.getName() == 'ul' )
167 list.setStyle( 'display', '' );
168 }
169 },
170
171 mark: function( value ) {
172 if ( !this.multiSelect )
173 this.unmarkAll();
174
175 var itemId = this._.items[ value ],
176 item = this.element.getDocument().getById( itemId );
177 item.addClass( 'cke_selected' );
178
179 this.element.getDocument().getById( itemId + '_option' ).setAttribute( 'aria-selected', true );
180 this.onMark && this.onMark( item );
181 },
182
183 unmark: function( value ) {
184 var doc = this.element.getDocument(),
185 itemId = this._.items[ value ],
186 item = doc.getById( itemId );
187
188 item.removeClass( 'cke_selected' );
189 doc.getById( itemId + '_option' ).removeAttribute( 'aria-selected' );
190
191 this.onUnmark && this.onUnmark( item );
192 },
193
194 unmarkAll: function() {
195 var items = this._.items,
196 doc = this.element.getDocument();
197
198 for ( var value in items ) {
199 var itemId = items[ value ];
200
201 doc.getById( itemId ).removeClass( 'cke_selected' );
202 doc.getById( itemId + '_option' ).removeAttribute( 'aria-selected' );
203 }
204
205 this.onUnmark && this.onUnmark();
206 },
207
208 isMarked: function( value ) {
209 return this.element.getDocument().getById( this._.items[ value ] ).hasClass( 'cke_selected' );
210 },
211
212 focus: function( value ) {
213 this._.focusIndex = -1;
214
215 var links = this.element.getElementsByTag( 'a' ),
216 link,
217 selected,
218 i = -1;
219
220 if ( value ) {
221 selected = this.element.getDocument().getById( this._.items[ value ] ).getFirst();
222
223 while ( ( link = links.getItem( ++i ) ) ) {
224 if ( link.equals( selected ) ) {
225 this._.focusIndex = i;
226 break;
227 }
228 }
229 }
230 else {
231 this.element.focus();
232 }
233
234 selected && setTimeout( function() {
235 selected.focus();
236 }, 0 );
237 }
238 }
239 } );
240 }
241} );
diff --git a/sources/plugins/liststyle/dialogs/liststyle.js b/sources/plugins/liststyle/dialogs/liststyle.js
new file mode 100644
index 0000000..4f8f39b
--- /dev/null
+++ b/sources/plugins/liststyle/dialogs/liststyle.js
@@ -0,0 +1,189 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 function getListElement( editor, listTag ) {
8 var range;
9 try {
10 range = editor.getSelection().getRanges()[ 0 ];
11 } catch ( e ) {
12 return null;
13 }
14
15 range.shrink( CKEDITOR.SHRINK_TEXT );
16 return editor.elementPath( range.getCommonAncestor() ).contains( listTag, 1 );
17 }
18
19 var listItem = function( node ) {
20 return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );
21 };
22
23 var mapListStyle = {
24 'a': 'lower-alpha',
25 'A': 'upper-alpha',
26 'i': 'lower-roman',
27 'I': 'upper-roman',
28 '1': 'decimal',
29 'disc': 'disc',
30 'circle': 'circle',
31 'square': 'square'
32 };
33
34 function listStyle( editor, startupPage ) {
35 var lang = editor.lang.liststyle;
36 if ( startupPage == 'bulletedListStyle' ) {
37 return {
38 title: lang.bulletedTitle,
39 minWidth: 300,
40 minHeight: 50,
41 contents: [ {
42 id: 'info',
43 accessKey: 'I',
44 elements: [ {
45 type: 'select',
46 label: lang.type,
47 id: 'type',
48 align: 'center',
49 style: 'width:150px',
50 items: [
51 [ lang.notset, '' ],
52 [ lang.circle, 'circle' ],
53 [ lang.disc, 'disc' ],
54 [ lang.square, 'square' ]
55 ],
56 setup: function( element ) {
57 var value = element.getStyle( 'list-style-type' ) || mapListStyle[ element.getAttribute( 'type' ) ] || element.getAttribute( 'type' ) || '';
58
59 this.setValue( value );
60 },
61 commit: function( element ) {
62 var value = this.getValue();
63 if ( value )
64 element.setStyle( 'list-style-type', value );
65 else
66 element.removeStyle( 'list-style-type' );
67 }
68 } ]
69 } ],
70 onShow: function() {
71 var editor = this.getParentEditor(),
72 element = getListElement( editor, 'ul' );
73
74 element && this.setupContent( element );
75 },
76 onOk: function() {
77 var editor = this.getParentEditor(),
78 element = getListElement( editor, 'ul' );
79
80 element && this.commitContent( element );
81 }
82 };
83 } else if ( startupPage == 'numberedListStyle' ) {
84
85 var listStyleOptions = [
86 [ lang.notset, '' ],
87 [ lang.lowerRoman, 'lower-roman' ],
88 [ lang.upperRoman, 'upper-roman' ],
89 [ lang.lowerAlpha, 'lower-alpha' ],
90 [ lang.upperAlpha, 'upper-alpha' ],
91 [ lang.decimal, 'decimal' ]
92 ];
93
94 if ( !CKEDITOR.env.ie || CKEDITOR.env.version > 7 ) {
95 listStyleOptions.concat( [
96 [ lang.armenian, 'armenian' ],
97 [ lang.decimalLeadingZero, 'decimal-leading-zero' ],
98 [ lang.georgian, 'georgian' ],
99 [ lang.lowerGreek, 'lower-greek' ]
100 ] );
101 }
102
103 return {
104 title: lang.numberedTitle,
105 minWidth: 300,
106 minHeight: 50,
107 contents: [ {
108 id: 'info',
109 accessKey: 'I',
110 elements: [ {
111 type: 'hbox',
112 widths: [ '25%', '75%' ],
113 children: [ {
114 label: lang.start,
115 type: 'text',
116 id: 'start',
117 validate: CKEDITOR.dialog.validate.integer( lang.validateStartNumber ),
118 setup: function( element ) {
119 // List item start number dominates.
120 var value = element.getFirst( listItem ).getAttribute( 'value' ) || element.getAttribute( 'start' ) || 1;
121 value && this.setValue( value );
122 },
123 commit: function( element ) {
124 var firstItem = element.getFirst( listItem );
125 var oldStart = firstItem.getAttribute( 'value' ) || element.getAttribute( 'start' ) || 1;
126
127 // Force start number on list root.
128 element.getFirst( listItem ).removeAttribute( 'value' );
129 var val = parseInt( this.getValue(), 10 );
130 if ( isNaN( val ) )
131 element.removeAttribute( 'start' );
132 else
133 element.setAttribute( 'start', val );
134
135 // Update consequent list item numbering.
136 var nextItem = firstItem,
137 conseq = oldStart,
138 startNumber = isNaN( val ) ? 1 : val;
139 while ( ( nextItem = nextItem.getNext( listItem ) ) && conseq++ ) {
140 if ( nextItem.getAttribute( 'value' ) == conseq )
141 nextItem.setAttribute( 'value', startNumber + conseq - oldStart );
142 }
143 }
144 },
145 {
146 type: 'select',
147 label: lang.type,
148 id: 'type',
149 style: 'width: 100%;',
150 items: listStyleOptions,
151 setup: function( element ) {
152 var value = element.getStyle( 'list-style-type' ) || mapListStyle[ element.getAttribute( 'type' ) ] || element.getAttribute( 'type' ) || '';
153
154 this.setValue( value );
155 },
156 commit: function( element ) {
157 var value = this.getValue();
158 if ( value )
159 element.setStyle( 'list-style-type', value );
160 else
161 element.removeStyle( 'list-style-type' );
162 }
163 } ]
164 } ]
165 } ],
166 onShow: function() {
167 var editor = this.getParentEditor(),
168 element = getListElement( editor, 'ol' );
169
170 element && this.setupContent( element );
171 },
172 onOk: function() {
173 var editor = this.getParentEditor(),
174 element = getListElement( editor, 'ol' );
175
176 element && this.commitContent( element );
177 }
178 };
179 }
180 }
181
182 CKEDITOR.dialog.add( 'numberedListStyle', function( editor ) {
183 return listStyle( editor, 'numberedListStyle' );
184 } );
185
186 CKEDITOR.dialog.add( 'bulletedListStyle', function( editor ) {
187 return listStyle( editor, 'bulletedListStyle' );
188 } );
189} )();
diff --git a/sources/plugins/liststyle/lang/af.js b/sources/plugins/liststyle/lang/af.js
new file mode 100644
index 0000000..71ba760
--- /dev/null
+++ b/sources/plugins/liststyle/lang/af.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'af', {
6 armenian: 'Armeense nommering',
7 bulletedTitle: 'Eienskappe van ongenommerde lys',
8 circle: 'Sirkel',
9 decimal: 'Desimale syfers (1, 2, 3, ens.)',
10 decimalLeadingZero: 'Desimale syfers met voorloopnul (01, 02, 03, ens.)',
11 disc: 'Skyf',
12 georgian: 'Georgiese nommering (an, ban, gan, ens.)',
13 lowerAlpha: 'Kleinletters (a, b, c, d, e, ens.)',
14 lowerGreek: 'Griekse kleinletters (alpha, beta, gamma, ens.)',
15 lowerRoman: 'Romeinse kleinletters (i, ii, iii, iv, v, ens.)',
16 none: 'Geen',
17 notset: '<nie ingestel nie>',
18 numberedTitle: 'Eienskappe van genommerde lys',
19 square: 'Vierkant',
20 start: 'Begin',
21 type: 'Tipe',
22 upperAlpha: 'Hoofletters (A, B, C, D, E, ens.)',
23 upperRoman: 'Romeinse hoofletters (I, II, III, IV, V, ens.)',
24 validateStartNumber: 'Beginnommer van lys moet \'n heelgetal wees.'
25} );
diff --git a/sources/plugins/liststyle/lang/ar.js b/sources/plugins/liststyle/lang/ar.js
new file mode 100644
index 0000000..7d961df
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ar.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ar', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/az.js b/sources/plugins/liststyle/lang/az.js
new file mode 100644
index 0000000..73fc927
--- /dev/null
+++ b/sources/plugins/liststyle/lang/az.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'az', {
6 armenian: 'Erməni nömrələmə',
7 bulletedTitle: 'Markerlənmiş siyahının xüsusiyyətləri',
8 circle: 'Dəirəcik',
9 decimal: 'Rəqəm (1, 2, 3 və s.)',
10 decimalLeadingZero: 'Aparıcı sıfır olan rəqəm (01, 02, 03 və s.)',
11 disc: 'Disk',
12 georgian: 'Gürcü nömrələmə (an, ban, gan, və s.)',
13 lowerAlpha: 'Kiçik hərflər (a, b, c, d, e və s.)',
14 lowerGreek: 'Kiçik Yunan hərfləri (alfa, beta, qamma və s.)',
15 lowerRoman: 'Rum rəqəmləri (i, ii, iii, iv, v və s.)',
16 none: 'Yoxdur',
17 notset: '<seçilməmiş>',
18 numberedTitle: 'Nömrəli siyahının xüsusiyyətləri',
19 square: 'Dördbucaq',
20 start: 'Başlanğıc',
21 type: 'Növ',
22 upperAlpha: 'Böyük hərflər (a, b, c, d, e və s.)',
23 upperRoman: 'Böyük Rum rəqəmləri (I, II, III, IV, V və s.)',
24 validateStartNumber: 'Siyahının başlanğıc nömrəsi tam və müsbət rəqəm olmalıdır.'
25} );
diff --git a/sources/plugins/liststyle/lang/bg.js b/sources/plugins/liststyle/lang/bg.js
new file mode 100644
index 0000000..a119fd4
--- /dev/null
+++ b/sources/plugins/liststyle/lang/bg.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'bg', {
6 armenian: 'Арменско номериране',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Кръг',
9 decimal: 'Числа (1, 2, 3 и др.)',
10 decimalLeadingZero: 'Числа с водеща нула (01, 02, 03 и т.н.)',
11 disc: 'Диск',
12 georgian: 'Грузинско номериране (an, ban, gan, и т.н.)',
13 lowerAlpha: 'Малки букви (а, б, в, г, д и т.н.)',
14 lowerGreek: 'Малки гръцки букви (алфа, бета, гама и т.н.)',
15 lowerRoman: 'Малки римски числа (i, ii, iii, iv, v и т.н.)',
16 none: 'Няма',
17 notset: '<не е указано>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Квадрат',
20 start: 'Старт',
21 type: 'Тип',
22 upperAlpha: 'Големи букви (А, Б, В, Г, Д и т.н.)',
23 upperRoman: 'Големи римски числа (I, II, III, IV, V и т.н.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/bn.js b/sources/plugins/liststyle/lang/bn.js
new file mode 100644
index 0000000..f1b7bf3
--- /dev/null
+++ b/sources/plugins/liststyle/lang/bn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'bn', {
6 armenian: 'আর্মেনিয়ান সংখ্যাক্রমে বিন্যাস',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/bs.js b/sources/plugins/liststyle/lang/bs.js
new file mode 100644
index 0000000..163d1fb
--- /dev/null
+++ b/sources/plugins/liststyle/lang/bs.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'bs', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/ca.js b/sources/plugins/liststyle/lang/ca.js
new file mode 100644
index 0000000..8006ff8
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ca.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ca', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/cs.js b/sources/plugins/liststyle/lang/cs.js
new file mode 100644
index 0000000..c1e9a07
--- /dev/null
+++ b/sources/plugins/liststyle/lang/cs.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'cs', {
6 armenian: 'Arménské',
7 bulletedTitle: 'Vlastnosti odrážek',
8 circle: 'Kroužky',
9 decimal: 'Arabská čísla (1, 2, 3, atd.)',
10 decimalLeadingZero: 'Arabská čísla uvozená nulou (01, 02, 03, atd.)',
11 disc: 'Kolečka',
12 georgian: 'Gruzínské (an, ban, gan, atd.)',
13 lowerAlpha: 'Malá latinka (a, b, c, d, e, atd.)',
14 lowerGreek: 'Malé řecké (alpha, beta, gamma, atd.)',
15 lowerRoman: 'Malé římské (i, ii, iii, iv, v, atd.)',
16 none: 'Nic',
17 notset: '<nenastaveno>',
18 numberedTitle: 'Vlastnosti číslování',
19 square: 'Čtverce',
20 start: 'Počátek',
21 type: 'Typ',
22 upperAlpha: 'Velká latinka (A, B, C, D, E, atd.)',
23 upperRoman: 'Velké římské (I, II, III, IV, V, atd.)',
24 validateStartNumber: 'Číslování musí začínat celým číslem.'
25} );
diff --git a/sources/plugins/liststyle/lang/cy.js b/sources/plugins/liststyle/lang/cy.js
new file mode 100644
index 0000000..97902b5
--- /dev/null
+++ b/sources/plugins/liststyle/lang/cy.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'cy', {
6 armenian: 'Rhifo Armeneg',
7 bulletedTitle: 'Priodweddau Rhestr Fwled',
8 circle: 'Cylch',
9 decimal: 'Degol (1, 2, 3, ayyb.)',
10 decimalLeadingZero: 'Degol â sero arweiniol (01, 02, 03, ayyb.)',
11 disc: 'Disg',
12 georgian: 'Rhifau Sioraidd (an, ban, gan, ayyb.)',
13 lowerAlpha: 'Alffa Is (a, b, c, d, e, ayyb.)',
14 lowerGreek: 'Groeg Is (alpha, beta, gamma, ayyb.)',
15 lowerRoman: 'Rhufeinig Is (i, ii, iii, iv, v, ayyb.)',
16 none: 'Dim',
17 notset: '<heb osod>',
18 numberedTitle: 'Priodweddau Rhestr Rifol',
19 square: 'Sgwâr',
20 start: 'Dechrau',
21 type: 'Math',
22 upperAlpha: 'Alffa Uwch (A, B, C, D, E, ayyb.)',
23 upperRoman: 'Rhufeinig Uwch (I, II, III, IV, V, ayyb.)',
24 validateStartNumber: 'Rhaid bod y rhif cychwynnol yn gyfanrif.'
25} );
diff --git a/sources/plugins/liststyle/lang/da.js b/sources/plugins/liststyle/lang/da.js
new file mode 100644
index 0000000..27c47b5
--- /dev/null
+++ b/sources/plugins/liststyle/lang/da.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'da', {
6 armenian: 'Armensk nummering',
7 bulletedTitle: 'Værdier for cirkelpunktopstilling',
8 circle: 'Cirkel',
9 decimal: 'Decimal (1, 2, 3, osv.)',
10 decimalLeadingZero: 'Decimaler med 0 først (01, 02, 03, etc.)',
11 disc: 'Værdier for diskpunktopstilling',
12 georgian: 'Georgiansk nummering (an, ban, gan, etc.)',
13 lowerAlpha: 'Små alfabet (a, b, c, d, e, etc.)',
14 lowerGreek: 'Små græsk (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Små romerske (i, ii, iii, iv, v, etc.)',
16 none: 'Ingen',
17 notset: '<ikke defineret>',
18 numberedTitle: 'Egenskaber for nummereret liste',
19 square: 'Firkant',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Store alfabet (A, B, C, D, E, etc.)',
23 upperRoman: 'Store romerske (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Den nummererede liste skal starte med et rundt nummer'
25} );
diff --git a/sources/plugins/liststyle/lang/de-ch.js b/sources/plugins/liststyle/lang/de-ch.js
new file mode 100644
index 0000000..47d8634
--- /dev/null
+++ b/sources/plugins/liststyle/lang/de-ch.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'de-ch', {
6 armenian: 'Armenische Nummerierung',
7 bulletedTitle: 'Aufzählungslisteneigenschaften',
8 circle: 'Ring',
9 decimal: 'Dezimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Dezimal mit führender Null (01, 02, 03, usw.)',
11 disc: 'Kreis',
12 georgian: 'Georgische Nummerierung (an, ban, gan, usw.)',
13 lowerAlpha: 'Klein Alpha (a, b, c, d, e, usw.)',
14 lowerGreek: 'Klein griechisch (alpha, beta, gamma, usw.)',
15 lowerRoman: 'Klein römisch (i, ii, iii, iv, v, usw.)',
16 none: 'Keine',
17 notset: '<nicht festgelegt>',
18 numberedTitle: 'Nummerierte Listeneigenschaften',
19 square: 'Quadrat',
20 start: 'Start',
21 type: 'Typ',
22 upperAlpha: 'Gross alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Gross römisch (I, II, III, IV, V, usw.)',
24 validateStartNumber: 'Listenstartnummer muss eine ganze Zahl sein.'
25} );
diff --git a/sources/plugins/liststyle/lang/de.js b/sources/plugins/liststyle/lang/de.js
new file mode 100644
index 0000000..cdbf0b3
--- /dev/null
+++ b/sources/plugins/liststyle/lang/de.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'de', {
6 armenian: 'Armenische Nummerierung',
7 bulletedTitle: 'Aufzählungslisteneigenschaften',
8 circle: 'Ring',
9 decimal: 'Dezimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Dezimal mit führender Null (01, 02, 03, usw.)',
11 disc: 'Kreis',
12 georgian: 'Georgische Nummerierung (an, ban, gan, usw.)',
13 lowerAlpha: 'Klein Alpha (a, b, c, d, e, usw.)',
14 lowerGreek: 'Klein griechisch (alpha, beta, gamma, usw.)',
15 lowerRoman: 'Klein römisch (i, ii, iii, iv, v, usw.)',
16 none: 'Keine',
17 notset: '<nicht festgelegt>',
18 numberedTitle: 'Nummerierte Listeneigenschaften',
19 square: 'Quadrat',
20 start: 'Start',
21 type: 'Typ',
22 upperAlpha: 'Groß alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Groß römisch (I, II, III, IV, V, usw.)',
24 validateStartNumber: 'Listenstartnummer muss eine ganze Zahl sein.'
25} );
diff --git a/sources/plugins/liststyle/lang/el.js b/sources/plugins/liststyle/lang/el.js
new file mode 100644
index 0000000..2bd7ce2
--- /dev/null
+++ b/sources/plugins/liststyle/lang/el.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'el', {
6 armenian: 'Αρμενική αρίθμηση',
7 bulletedTitle: 'Ιδιότητες Λίστας Σημείων',
8 circle: 'Κύκλος',
9 decimal: 'Δεκαδική (1, 2, 3, κτλ)',
10 decimalLeadingZero: 'Δεκαδική με αρχικό μηδεν (01, 02, 03, κτλ)',
11 disc: 'Δίσκος',
12 georgian: 'Γεωργιανή αρίθμηση (ა, ბ, გ, κτλ)',
13 lowerAlpha: 'Μικρά Λατινικά (a, b, c, d, e, κτλ.)',
14 lowerGreek: 'Μικρά Ελληνικά (α, β, γ, κτλ)',
15 lowerRoman: 'Μικρά Ρωμαϊκά (i, ii, iii, iv, v, κτλ)',
16 none: 'Καμία',
17 notset: '<δεν έχει οριστεί>',
18 numberedTitle: 'Ιδιότητες Αριθμημένης Λίστας ',
19 square: 'Τετράγωνο',
20 start: 'Εκκίνηση',
21 type: 'Τύπος',
22 upperAlpha: 'Κεφαλαία Λατινικά (A, B, C, D, E, κτλ)',
23 upperRoman: 'Κεφαλαία Ρωμαϊκά (I, II, III, IV, V, κτλ)',
24 validateStartNumber: 'Ο αριθμός εκκίνησης της αρίθμησης πρέπει να είναι ακέραιος αριθμός.'
25} );
diff --git a/sources/plugins/liststyle/lang/en-au.js b/sources/plugins/liststyle/lang/en-au.js
new file mode 100644
index 0000000..af38b3e
--- /dev/null
+++ b/sources/plugins/liststyle/lang/en-au.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'en-au', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/en-ca.js b/sources/plugins/liststyle/lang/en-ca.js
new file mode 100644
index 0000000..ce76d82
--- /dev/null
+++ b/sources/plugins/liststyle/lang/en-ca.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'en-ca', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/en-gb.js b/sources/plugins/liststyle/lang/en-gb.js
new file mode 100644
index 0000000..7f67124
--- /dev/null
+++ b/sources/plugins/liststyle/lang/en-gb.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'en-gb', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/en.js b/sources/plugins/liststyle/lang/en.js
new file mode 100644
index 0000000..c41b7d7
--- /dev/null
+++ b/sources/plugins/liststyle/lang/en.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'en', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/eo.js b/sources/plugins/liststyle/lang/eo.js
new file mode 100644
index 0000000..b601e76
--- /dev/null
+++ b/sources/plugins/liststyle/lang/eo.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'eo', {
6 armenian: 'Armena nombrado',
7 bulletedTitle: 'Atributoj de Bula Listo',
8 circle: 'Cirklo',
9 decimal: 'Dekumaj Nombroj (1, 2, 3, ktp.)',
10 decimalLeadingZero: 'Dekumaj Nombroj malantaŭ nulo (01, 02, 03, ktp.)',
11 disc: 'Disko',
12 georgian: 'Gruza nombrado (an, ban, gan, ktp.)',
13 lowerAlpha: 'Minusklaj Literoj (a, b, c, d, e, ktp.)',
14 lowerGreek: 'Grekaj Minusklaj Literoj (alpha, beta, gamma, ktp.)',
15 lowerRoman: 'Minusklaj Romanaj Nombroj (i, ii, iii, iv, v, ktp.)',
16 none: 'Neniu',
17 notset: '<Defaŭlta>',
18 numberedTitle: 'Atributoj de Numera Listo',
19 square: 'kvadrato',
20 start: 'Komenco',
21 type: 'Tipo',
22 upperAlpha: 'Majusklaj Literoj (A, B, C, D, E, ktp.)',
23 upperRoman: 'Majusklaj Romanaj Nombroj (I, II, III, IV, V, ktp.)',
24 validateStartNumber: 'La unua listero devas esti entjera nombro.'
25} );
diff --git a/sources/plugins/liststyle/lang/es.js b/sources/plugins/liststyle/lang/es.js
new file mode 100644
index 0000000..75d2920
--- /dev/null
+++ b/sources/plugins/liststyle/lang/es.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'es', {
6 armenian: 'Numeración armenia',
7 bulletedTitle: 'Propiedades de viñetas',
8 circle: 'Círculo',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal con cero inicial (01, 02, 03, etc.)',
11 disc: 'Disco',
12 georgian: 'Numeración georgiana (an, ban, gan, etc.)',
13 lowerAlpha: 'Alfabeto en minúsculas (a, b, c, d, e, etc.)',
14 lowerGreek: 'Letras griegas (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Números romanos en minúsculas (i, ii, iii, iv, v, etc.)',
16 none: 'Ninguno',
17 notset: '<sin establecer>',
18 numberedTitle: 'Propiedades de lista numerada',
19 square: 'Cuadrado',
20 start: 'Inicio',
21 type: 'Tipo',
22 upperAlpha: 'Alfabeto en mayúsculas (A, B, C, D, E, etc.)',
23 upperRoman: 'Números romanos en mayúsculas (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'El Inicio debe ser un número entero.'
25} );
diff --git a/sources/plugins/liststyle/lang/et.js b/sources/plugins/liststyle/lang/et.js
new file mode 100644
index 0000000..d2dfd5e
--- /dev/null
+++ b/sources/plugins/liststyle/lang/et.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'et', {
6 armenian: 'Armeenia numbrid',
7 bulletedTitle: 'Punktloendi omadused',
8 circle: 'Ring',
9 decimal: 'Numbrid (1, 2, 3, jne)',
10 decimalLeadingZero: 'Numbrid algusnulliga (01, 02, 03, jne)',
11 disc: 'Täpp',
12 georgian: 'Gruusia numbrid (an, ban, gan, jne)',
13 lowerAlpha: 'Väiketähed (a, b, c, d, e, jne)',
14 lowerGreek: 'Kreeka väiketähed (alpha, beta, gamma, jne)',
15 lowerRoman: 'Väiksed rooma numbrid (i, ii, iii, iv, v, jne)',
16 none: 'Puudub',
17 notset: '<pole määratud>',
18 numberedTitle: 'Numberloendi omadused',
19 square: 'Ruut',
20 start: 'Algus',
21 type: 'Liik',
22 upperAlpha: 'Suurtähed (A, B, C, D, E, jne)',
23 upperRoman: 'Suured rooma numbrid (I, II, III, IV, V, jne)',
24 validateStartNumber: 'Loendi algusnumber peab olema täisarv.'
25} );
diff --git a/sources/plugins/liststyle/lang/eu.js b/sources/plugins/liststyle/lang/eu.js
new file mode 100644
index 0000000..ef616e5
--- /dev/null
+++ b/sources/plugins/liststyle/lang/eu.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'eu', {
6 armenian: 'Zenbakitze armeniarra',
7 bulletedTitle: 'Buletadun zerrendaren propietateak',
8 circle: 'Zirkulua',
9 decimal: 'Hamartarra (1, 2, 3...)',
10 decimalLeadingZero: 'Aurretik zeroa duen hamartarra (01, 02, 03...)',
11 disc: 'Diskoa',
12 georgian: 'Zenbakitze georgiarra (an, ban, gan...)',
13 lowerAlpha: 'Alfabetoa minuskulaz (a, b, c, d, e...)',
14 lowerGreek: 'Greziera minuskulaz (alpha, beta, gamma...)',
15 lowerRoman: 'Erromatarra minuskulaz (i, ii, iii, iv, v...)',
16 none: 'Bat ere ez',
17 notset: '<ezarri gabea>',
18 numberedTitle: 'Zenbakidun zerrendaren propietateak',
19 square: 'Karratua',
20 start: 'Hasi',
21 type: 'Mota',
22 upperAlpha: 'Alfabetoa maiuskulaz (A, B, C, D, E...)',
23 upperRoman: 'Erromatarra maiuskulaz (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Zerrendaren hasierako zenbakiak zenbaki osoa izan behar du.'
25} );
diff --git a/sources/plugins/liststyle/lang/fa.js b/sources/plugins/liststyle/lang/fa.js
new file mode 100644
index 0000000..7a4517c
--- /dev/null
+++ b/sources/plugins/liststyle/lang/fa.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'fa', {
6 armenian: 'شماره‌گذاری ارمنی',
7 bulletedTitle: 'خصوصیات فهرست نقطه‌ای',
8 circle: 'دایره',
9 decimal: 'ده‌دهی (۱، ۲، ۳، ...)',
10 decimalLeadingZero: 'دهدهی همراه با صفر (۰۱، ۰۲، ۰۳، ...)',
11 disc: 'صفحه گرد',
12 georgian: 'شمارهگذاری گریگورین (an, ban, gan, etc.)',
13 lowerAlpha: 'پانویس الفبایی (a, b, c, d, e, etc.)',
14 lowerGreek: 'پانویس یونانی (alpha, beta, gamma, etc.)',
15 lowerRoman: 'پانویس رومی (i, ii, iii, iv, v, etc.)',
16 none: 'هیچ',
17 notset: '<تنظیم نشده>',
18 numberedTitle: 'ویژگیهای فهرست شمارهدار',
19 square: 'چهارگوش',
20 start: 'شروع',
21 type: 'نوع',
22 upperAlpha: 'بالانویس الفبایی (A, B, C, D, E, etc.)',
23 upperRoman: 'بالانویس رومی (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'فهرست شماره شروع باید یک عدد صحیح باشد.'
25} );
diff --git a/sources/plugins/liststyle/lang/fi.js b/sources/plugins/liststyle/lang/fi.js
new file mode 100644
index 0000000..b0cf1b3
--- /dev/null
+++ b/sources/plugins/liststyle/lang/fi.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'fi', {
6 armenian: 'Armeenialainen numerointi',
7 bulletedTitle: 'Numeroimattoman listan ominaisuudet',
8 circle: 'Ympyrä',
9 decimal: 'Desimaalit (1, 2, 3, jne.)',
10 decimalLeadingZero: 'Desimaalit, alussa nolla (01, 02, 03, jne.)',
11 disc: 'Levy',
12 georgian: 'Georgialainen numerointi (an, ban, gan, etc.)',
13 lowerAlpha: 'Pienet aakkoset (a, b, c, d, e, jne.)',
14 lowerGreek: 'Pienet kreikkalaiset (alpha, beta, gamma, jne.)',
15 lowerRoman: 'Pienet roomalaiset (i, ii, iii, iv, v, jne.)',
16 none: 'Ei mikään',
17 notset: '<ei asetettu>',
18 numberedTitle: 'Numeroidun listan ominaisuudet',
19 square: 'Neliö',
20 start: 'Alku',
21 type: 'Tyyppi',
22 upperAlpha: 'Isot aakkoset (A, B, C, D, E, jne.)',
23 upperRoman: 'Isot roomalaiset (I, II, III, IV, V, jne.)',
24 validateStartNumber: 'Listan ensimmäisen numeron tulee olla kokonaisluku.'
25} );
diff --git a/sources/plugins/liststyle/lang/fo.js b/sources/plugins/liststyle/lang/fo.js
new file mode 100644
index 0000000..922a85c
--- /dev/null
+++ b/sources/plugins/liststyle/lang/fo.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'fo', {
6 armenian: 'Armensk talskipan',
7 bulletedTitle: 'Eginleikar fyri lista við prikkum',
8 circle: 'Sirkul',
9 decimal: 'Vanlig tøl (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Tøl við null frammanfyri (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgisk talskipan (an, ban, gan, osv.)',
13 lowerAlpha: 'Lítlir bókstavir (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grikskt við lítlum (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lítil rómaratøl (i, ii, iii, iv, v, etc.)',
16 none: 'Einki',
17 notset: '<ikki sett>',
18 numberedTitle: 'Eginleikar fyri lista við tølum',
19 square: 'Fýrkantur',
20 start: 'Byrjan',
21 type: 'Slag',
22 upperAlpha: 'Stórir bókstavir (A, B, C, D, E, etc.)',
23 upperRoman: 'Stór rómaratøl (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Byrjunartalið fyri lista má vera eitt heiltal.'
25} );
diff --git a/sources/plugins/liststyle/lang/fr-ca.js b/sources/plugins/liststyle/lang/fr-ca.js
new file mode 100644
index 0000000..06c2af9
--- /dev/null
+++ b/sources/plugins/liststyle/lang/fr-ca.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'fr-ca', {
6 armenian: 'Numération arménienne',
7 bulletedTitle: 'Propriété de liste à puce',
8 circle: 'Cercle',
9 decimal: 'Décimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Décimal avec zéro (01, 02, 03, etc.)',
11 disc: 'Disque',
12 georgian: 'Numération géorgienne (an, ban, gan, etc.)',
13 lowerAlpha: 'Alphabétique minuscule (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grecque minuscule (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Romain minuscule (i, ii, iii, iv, v, etc.)',
16 none: 'Aucun',
17 notset: '<non défini>',
18 numberedTitle: 'Propriété de la liste numérotée',
19 square: 'Carré',
20 start: 'Début',
21 type: 'Type',
22 upperAlpha: 'Alphabétique majuscule (A, B, C, D, E, etc.)',
23 upperRoman: 'Romain Majuscule (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Le numéro de début de liste doit être un entier.'
25} );
diff --git a/sources/plugins/liststyle/lang/fr.js b/sources/plugins/liststyle/lang/fr.js
new file mode 100644
index 0000000..ccb6944
--- /dev/null
+++ b/sources/plugins/liststyle/lang/fr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'fr', {
6 armenian: 'Numération arménienne',
7 bulletedTitle: 'Propriétés de la liste à puces',
8 circle: 'Cercle',
9 decimal: 'Décimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Décimal précédé par un 0 (01, 02, 03, etc.)',
11 disc: 'Disque',
12 georgian: 'Numération géorgienne (an, ban, gan, etc.)',
13 lowerAlpha: 'Lettres minuscules (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grec minuscule (alpha, bêta, gamma, etc.)',
15 lowerRoman: 'Chiffres romains minuscules (i, ii, iii, iv, v, etc.)',
16 none: 'Aucun',
17 notset: '<indéfini>',
18 numberedTitle: 'Propriétés de la liste numérotée',
19 square: 'Carré',
20 start: 'Début',
21 type: 'Type',
22 upperAlpha: 'Lettres majuscules (A, B, C, D, E, etc.)',
23 upperRoman: 'Chiffres romains majuscules (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Le premier élément de la liste doit être un nombre entier.'
25} );
diff --git a/sources/plugins/liststyle/lang/gl.js b/sources/plugins/liststyle/lang/gl.js
new file mode 100644
index 0000000..eeb622d
--- /dev/null
+++ b/sources/plugins/liststyle/lang/gl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'gl', {
6 armenian: 'Numeración armenia',
7 bulletedTitle: 'Propiedades da lista viñeteada',
8 circle: 'Circulo',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal con cero á esquerda (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Numeración xeorxiana (an, ban, gan, etc.)',
13 lowerAlpha: 'Alfabeto en minúsculas (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grego en minúsculas (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Números romanos en minúsculas (i, ii, iii, iv, v, etc.)',
16 none: 'Ningún',
17 notset: '<sen estabelecer>',
18 numberedTitle: 'Propiedades da lista numerada',
19 square: 'Cadrado',
20 start: 'Inicio',
21 type: 'Tipo',
22 upperAlpha: 'Alfabeto en maiúsculas (A, B, C, D, E, etc.)',
23 upperRoman: 'Números romanos en maiúsculas (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'O número de inicio da lista debe ser un número enteiro.'
25} );
diff --git a/sources/plugins/liststyle/lang/gu.js b/sources/plugins/liststyle/lang/gu.js
new file mode 100644
index 0000000..434f218
--- /dev/null
+++ b/sources/plugins/liststyle/lang/gu.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'gu', {
6 armenian: 'અરમેનિયન આંકડા પદ્ધતિ',
7 bulletedTitle: 'બુલેટેડ લીસ્ટના ગુણ',
8 circle: 'વર્તુળ',
9 decimal: 'આંકડા (1, 2, 3, etc.)',
10 decimalLeadingZero: 'સુન્ય આગળ આંકડા (01, 02, 03, etc.)',
11 disc: 'ડિસ્ક',
12 georgian: 'ગેઓર્ગિયન આંકડા પદ્ધતિ (an, ban, gan, etc.)',
13 lowerAlpha: 'આલ્ફા નાના (a, b, c, d, e, etc.)',
14 lowerGreek: 'ગ્રીક નાના (alpha, beta, gamma, etc.)',
15 lowerRoman: 'રોમન નાના (i, ii, iii, iv, v, etc.)',
16 none: 'કસુ ',
17 notset: '<સેટ નથી>',
18 numberedTitle: 'આંકડાના લીસ્ટના ગુણ',
19 square: 'ચોરસ',
20 start: 'શરુ કરવું',
21 type: 'પ્રકાર',
22 upperAlpha: 'આલ્ફા મોટા (A, B, C, D, E, etc.)',
23 upperRoman: 'રોમન મોટા (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'લીસ્ટના સરુઆતનો આંકડો પુરો હોવો જોઈએ.'
25} );
diff --git a/sources/plugins/liststyle/lang/he.js b/sources/plugins/liststyle/lang/he.js
new file mode 100644
index 0000000..93b6106
--- /dev/null
+++ b/sources/plugins/liststyle/lang/he.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'he', {
6 armenian: 'ספרות ארמניות',
7 bulletedTitle: 'תכונות רשימת תבליטים',
8 circle: 'עיגול ריק',
9 decimal: 'ספרות (1, 2, 3 וכו\')',
10 decimalLeadingZero: 'ספרות עם 0 בהתחלה (01, 02, 03 וכו\')',
11 disc: 'עיגול מלא',
12 georgian: 'ספרות גיאורגיות (an, ban, gan וכו\')',
13 lowerAlpha: 'אותיות אנגליות קטנות (a, b, c, d, e וכו\')',
14 lowerGreek: 'אותיות יווניות קטנות (alpha, beta, gamma וכו\')',
15 lowerRoman: 'ספירה רומית באותיות קטנות (i, ii, iii, iv, v וכו\')',
16 none: 'ללא',
17 notset: '<לא נקבע>',
18 numberedTitle: 'תכונות רשימה ממוספרת',
19 square: 'ריבוע',
20 start: 'תחילת מספור',
21 type: 'סוג',
22 upperAlpha: 'אותיות אנגליות גדולות (A, B, C, D, E וכו\')',
23 upperRoman: 'ספירה רומיות באותיות גדולות (I, II, III, IV, V וכו\')',
24 validateStartNumber: 'שדה תחילת המספור חייב להכיל מספר שלם.'
25} );
diff --git a/sources/plugins/liststyle/lang/hi.js b/sources/plugins/liststyle/lang/hi.js
new file mode 100644
index 0000000..0f1ae03
--- /dev/null
+++ b/sources/plugins/liststyle/lang/hi.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'hi', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/hr.js b/sources/plugins/liststyle/lang/hr.js
new file mode 100644
index 0000000..8da2ff3
--- /dev/null
+++ b/sources/plugins/liststyle/lang/hr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'hr', {
6 armenian: 'Armenijska numeracija',
7 bulletedTitle: 'Svojstva liste',
8 circle: 'Krug',
9 decimal: 'Decimalna numeracija (1, 2, 3, itd.)',
10 decimalLeadingZero: 'Decimalna s vodećom nulom (01, 02, 03, itd)',
11 disc: 'Disk',
12 georgian: 'Gruzijska numeracija(an, ban, gan, etc.)',
13 lowerAlpha: 'Znakovi mala slova (a, b, c, d, e, itd.)',
14 lowerGreek: 'Grčka numeracija mala slova (alfa, beta, gama, itd).',
15 lowerRoman: 'Romanska numeracija mala slova (i, ii, iii, iv, v, itd.)',
16 none: 'Bez',
17 notset: '<nije određen>',
18 numberedTitle: 'Svojstva brojčane liste',
19 square: 'Kvadrat',
20 start: 'Početak',
21 type: 'Vrsta',
22 upperAlpha: 'Znakovi velika slova (A, B, C, D, E, itd.)',
23 upperRoman: 'Romanska numeracija velika slova (I, II, III, IV, V, itd.)',
24 validateStartNumber: 'Početak brojčane liste mora biti cijeli broj.'
25} );
diff --git a/sources/plugins/liststyle/lang/hu.js b/sources/plugins/liststyle/lang/hu.js
new file mode 100644
index 0000000..4e3d922
--- /dev/null
+++ b/sources/plugins/liststyle/lang/hu.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'hu', {
6 armenian: 'Örmény számozás',
7 bulletedTitle: 'Pontozott lista tulajdonságai',
8 circle: 'Kör',
9 decimal: 'Arab számozás (1, 2, 3, stb.)',
10 decimalLeadingZero: 'Számozás bevezető nullákkal (01, 02, 03, stb.)',
11 disc: 'Korong',
12 georgian: 'Grúz számozás (an, ban, gan, stb.)',
13 lowerAlpha: 'Kisbetűs (a, b, c, d, e, stb.)',
14 lowerGreek: 'Görög (alpha, beta, gamma, stb.)',
15 lowerRoman: 'Római kisbetűs (i, ii, iii, iv, v, stb.)',
16 none: 'Nincs',
17 notset: '<Nincs beállítva>',
18 numberedTitle: 'Sorszámozott lista tulajdonságai',
19 square: 'Négyzet',
20 start: 'Kezdőszám',
21 type: 'Típus',
22 upperAlpha: 'Nagybetűs (A, B, C, D, E, stb.)',
23 upperRoman: 'Római nagybetűs (I, II, III, IV, V, stb.)',
24 validateStartNumber: 'A kezdőszám nem lehet tört érték.'
25} );
diff --git a/sources/plugins/liststyle/lang/id.js b/sources/plugins/liststyle/lang/id.js
new file mode 100644
index 0000000..36ec1ec
--- /dev/null
+++ b/sources/plugins/liststyle/lang/id.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'id', {
6 armenian: 'Armenian numbering', // MISSING
7 bulletedTitle: 'Bulleted List Properties', // MISSING
8 circle: 'Lingkaran',
9 decimal: 'Desimal (1, 2, 3, dst.)',
10 decimalLeadingZero: 'Desimal diawali angka nol (01, 02, 03, dst.)',
11 disc: 'Cakram',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)', // MISSING
13 lowerAlpha: 'Huruf Kecil (a, b, c, d, e, dst.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)', // MISSING
15 lowerRoman: 'Angka Romawi (i, ii, iii, iv, v, dst.)',
16 none: 'Tidak ada',
17 notset: '<tidak diatur>',
18 numberedTitle: 'Numbered List Properties', // MISSING
19 square: 'Persegi',
20 start: 'Mulai',
21 type: 'Tipe',
22 upperAlpha: 'Huruf Besar (A, B, C, D, E, dst.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)', // MISSING
24 validateStartNumber: 'List start number must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/liststyle/lang/is.js b/sources/plugins/liststyle/lang/is.js
new file mode 100644
index 0000000..a05c5bc
--- /dev/null
+++ b/sources/plugins/liststyle/lang/is.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'is', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/it.js b/sources/plugins/liststyle/lang/it.js
new file mode 100644
index 0000000..6ef919d
--- /dev/null
+++ b/sources/plugins/liststyle/lang/it.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'it', {
6 armenian: 'Numerazione Armena',
7 bulletedTitle: 'Proprietà liste puntate',
8 circle: 'Cerchio',
9 decimal: 'Decimale (1, 2, 3, ecc.)',
10 decimalLeadingZero: 'Decimale preceduto da 0 (01, 02, 03, ecc.)',
11 disc: 'Disco',
12 georgian: 'Numerazione Georgiana (an, ban, gan, ecc.)',
13 lowerAlpha: 'Alfabetico minuscolo (a, b, c, d, e, ecc.)',
14 lowerGreek: 'Greco minuscolo (alpha, beta, gamma, ecc.)',
15 lowerRoman: 'Numerazione Romana minuscola (i, ii, iii, iv, v, ecc.)',
16 none: 'Nessuno',
17 notset: '<non impostato>',
18 numberedTitle: 'Proprietà liste numerate',
19 square: 'Quadrato',
20 start: 'Inizio',
21 type: 'Tipo',
22 upperAlpha: 'Alfabetico maiuscolo (A, B, C, D, E, ecc.)',
23 upperRoman: 'Numerazione Romana maiuscola (I, II, III, IV, V, ecc.)',
24 validateStartNumber: 'Il numero di inizio di una lista numerata deve essere un numero intero.'
25} );
diff --git a/sources/plugins/liststyle/lang/ja.js b/sources/plugins/liststyle/lang/ja.js
new file mode 100644
index 0000000..e55dafc
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ja.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ja', {
6 armenian: 'アルメニア数字',
7 bulletedTitle: '箇条書きのプロパティ',
8 circle: '白丸',
9 decimal: '数字 (1, 2, 3, etc.)',
10 decimalLeadingZero: '0付きの数字 (01, 02, 03, etc.)',
11 disc: '黒丸',
12 georgian: 'グルジア数字 (an, ban, gan, etc.)',
13 lowerAlpha: '小文字アルファベット (a, b, c, d, e, etc.)',
14 lowerGreek: '小文字ギリシャ文字 (alpha, beta, gamma, etc.)',
15 lowerRoman: '小文字ローマ数字 (i, ii, iii, iv, v, etc.)',
16 none: 'なし',
17 notset: '<なし>',
18 numberedTitle: '番号付きリストのプロパティ',
19 square: '四角',
20 start: '開始',
21 type: '種類',
22 upperAlpha: '大文字アルファベット (A, B, C, D, E, etc.)',
23 upperRoman: '大文字ローマ数字 (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'リストの開始番号は数値で入力してください。'
25} );
diff --git a/sources/plugins/liststyle/lang/ka.js b/sources/plugins/liststyle/lang/ka.js
new file mode 100644
index 0000000..0ede82d
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ka.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ka', {
6 armenian: 'სომხური გადანომრვა',
7 bulletedTitle: 'ღილებიანი სიის პარამეტრები',
8 circle: 'წრეწირი',
9 decimal: 'რიცხვებით (1, 2, 3, ..)',
10 decimalLeadingZero: 'ნულით დაწყებული რიცხვებით (01, 02, 03, ..)',
11 disc: 'წრე',
12 georgian: 'ქართული გადანომრვა (ან, ბან, გან, ..)',
13 lowerAlpha: 'პატარა ლათინური ასოებით (a, b, c, d, e, ..)',
14 lowerGreek: 'პატარა ბერძნული ასოებით (ალფა, ბეტა, გამა, ..)',
15 lowerRoman: 'რომაული გადანომრვცა პატარა ციფრებით (i, ii, iii, iv, v, ..)',
16 none: 'არაფერი',
17 notset: '<არაფერი>',
18 numberedTitle: 'გადანომრილი სიის პარამეტრები',
19 square: 'კვადრატი',
20 start: 'საწყისი',
21 type: 'ტიპი',
22 upperAlpha: 'დიდი ლათინური ასოებით (A, B, C, D, E, ..)',
23 upperRoman: 'რომაული გადანომრვა დიდი ციფრებით (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'სიის საწყისი მთელი რიცხვი უნდა იყოს.'
25} );
diff --git a/sources/plugins/liststyle/lang/km.js b/sources/plugins/liststyle/lang/km.js
new file mode 100644
index 0000000..51d7365
--- /dev/null
+++ b/sources/plugins/liststyle/lang/km.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'km', {
6 armenian: 'លេខ​អារមេនី',
7 bulletedTitle: 'លក្ខណៈ​សម្បត្តិ​បញ្ជី​ជា​ចំណុច',
8 circle: 'រង្វង់​មូល',
9 decimal: 'លេខ​ទសភាគ (1, 2, 3, ...)',
10 decimalLeadingZero: 'ទសភាគ​ចាប់​ផ្ដើម​ពី​សូន្យ (01, 02, 03, ...)',
11 disc: 'ថាស',
12 georgian: 'លេខ​ចចជា (an, ban, gan, ...)',
13 lowerAlpha: 'ព្យញ្ជនៈ​តូច (a, b, c, d, e, ...)',
14 lowerGreek: 'លេខ​ក្រិក​តូច (alpha, beta, gamma, ...)',
15 lowerRoman: 'លេខ​រ៉ូម៉ាំង​តូច (i, ii, iii, iv, v, ...)',
16 none: 'គ្មាន',
17 notset: '<not set>',
18 numberedTitle: 'លក្ខណៈ​សម្បត្តិ​បញ្ជី​ជា​លេខ',
19 square: 'ការេ',
20 start: 'ចាប់​ផ្ដើម',
21 type: 'ប្រភេទ',
22 upperAlpha: 'អក្សរ​ធំ (A, B, C, D, E, ...)',
23 upperRoman: 'លេខ​រ៉ូម៉ាំង​ធំ (I, II, III, IV, V, ...)',
24 validateStartNumber: 'លេខ​ចាប់​ផ្ដើម​បញ្ជី ត្រូវ​តែ​ជា​តួ​លេខ​ពិត​ប្រាកដ។'
25} );
diff --git a/sources/plugins/liststyle/lang/ko.js b/sources/plugins/liststyle/lang/ko.js
new file mode 100644
index 0000000..8b88e2d
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ko.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ko', {
6 armenian: '아르메니아 숫자',
7 bulletedTitle: '순서 없는 목록 속성',
8 circle: '원',
9 decimal: '수 (1, 2, 3, 등)',
10 decimalLeadingZero: '0이 붙은 수 (01, 02, 03, 등)',
11 disc: '내림차순',
12 georgian: '그루지야 숫자 (an, ban, gan, 등)',
13 lowerAlpha: '영소문자 (a, b, c, d, e, 등)',
14 lowerGreek: '그리스 소문자 (alpha, beta, gamma, 등)',
15 lowerRoman: '로마 소문자 (i, ii, iii, iv, v, 등)',
16 none: '없음',
17 notset: '<설정 없음>',
18 numberedTitle: '순서 있는 목록 속성',
19 square: '사각',
20 start: '시작',
21 type: '유형',
22 upperAlpha: '영대문자 (A, B, C, D, E, 등)',
23 upperRoman: '로마 대문자 (I, II, III, IV, V, 등)',
24 validateStartNumber: '목록 시작 숫자는 정수여야 합니다.'
25} );
diff --git a/sources/plugins/liststyle/lang/ku.js b/sources/plugins/liststyle/lang/ku.js
new file mode 100644
index 0000000..a3a7b47
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ku.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ku', {
6 armenian: 'ئاراستەی ژمارەی ئەرمەنی',
7 bulletedTitle: 'خاسیەتی لیستی خاڵی',
8 circle: 'بازنه',
9 decimal: 'ژمارە (1, 2, 3, وە هیتر.)',
10 decimalLeadingZero: 'ژمارە سفڕی لەپێشەوه (01, 02, 03, وە هیتر.)',
11 disc: 'پەپکە',
12 georgian: 'ئاراستەی ژمارەی جۆڕجی (an, ban, gan, وە هیتر.)',
13 lowerAlpha: 'ئەلفابێی بچووك (a, b, c, d, e, وە هیتر.)',
14 lowerGreek: 'یۆنانی بچووك (alpha, beta, gamma, وە هیتر.)',
15 lowerRoman: 'ژمارەی ڕۆمی بچووك (i, ii, iii, iv, v, وە هیتر.)',
16 none: 'هیچ',
17 notset: '<دانەندراوه>',
18 numberedTitle: 'خاسیەتی لیستی ژمارەیی',
19 square: 'چووراگۆشە',
20 start: 'دەستپێکردن',
21 type: 'جۆر',
22 upperAlpha: 'ئەلفابێی گەوره (A, B, C, D, E, وە هیتر.)',
23 upperRoman: 'ژمارەی ڕۆمی گەوره (I, II, III, IV, V, وە هیتر.)',
24 validateStartNumber: 'دەستپێکەری لیستی ژمارەیی دەبێت تەنها ژمارە بێت.'
25} );
diff --git a/sources/plugins/liststyle/lang/lt.js b/sources/plugins/liststyle/lang/lt.js
new file mode 100644
index 0000000..6b7c949
--- /dev/null
+++ b/sources/plugins/liststyle/lang/lt.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'lt', {
6 armenian: 'Armėniški skaitmenys',
7 bulletedTitle: 'Ženklelinio sąrašo nustatymai',
8 circle: 'Apskritimas',
9 decimal: 'Dešimtainis (1, 2, 3, t.t)',
10 decimalLeadingZero: 'Dešimtainis su nuliu priekyje (01, 02, 03, t.t)',
11 disc: 'Diskas',
12 georgian: 'Gruziniški skaitmenys (an, ban, gan, t.t)',
13 lowerAlpha: 'Mažosios Alpha (a, b, c, d, e, t.t)',
14 lowerGreek: 'Mažosios Graikų (alpha, beta, gamma, t.t)',
15 lowerRoman: 'Mažosios Romėnų (i, ii, iii, iv, v, t.t)',
16 none: 'Niekas',
17 notset: '<nenurodytas>',
18 numberedTitle: 'Skaitmeninio sąrašo nustatymai',
19 square: 'Kvadratas',
20 start: 'Pradžia',
21 type: 'Rūšis',
22 upperAlpha: 'Didžiosios Alpha (A, B, C, D, E, t.t)',
23 upperRoman: 'Didžiosios Romėnų (I, II, III, IV, V, t.t)',
24 validateStartNumber: 'Sąrašo pradžios skaitmuo turi būti sveikas skaičius.'
25} );
diff --git a/sources/plugins/liststyle/lang/lv.js b/sources/plugins/liststyle/lang/lv.js
new file mode 100644
index 0000000..17b6da7
--- /dev/null
+++ b/sources/plugins/liststyle/lang/lv.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'lv', {
6 armenian: 'Armēņu skaitļi',
7 bulletedTitle: 'Vienkārša saraksta uzstādījumi',
8 circle: 'Aplis',
9 decimal: 'Decimālie (1, 2, 3, utt)',
10 decimalLeadingZero: 'Decimālie ar nulli (01, 02, 03, utt)',
11 disc: 'Disks',
12 georgian: 'Gruzīņu skaitļi (an, ban, gan, utt)',
13 lowerAlpha: 'Mazie alfabēta (a, b, c, d, e, utt)',
14 lowerGreek: 'Mazie grieķu (alfa, beta, gamma, utt)',
15 lowerRoman: 'Mazie romāņu (i, ii, iii, iv, v, utt)',
16 none: 'Nekas',
17 notset: '<nav norādīts>',
18 numberedTitle: 'Numurēta saraksta uzstādījumi',
19 square: 'Kvadrāts',
20 start: 'Sākt',
21 type: 'Tips',
22 upperAlpha: 'Lielie alfabēta (A, B, C, D, E, utt)',
23 upperRoman: 'Lielie romāņu (I, II, III, IV, V, utt)',
24 validateStartNumber: 'Saraksta sākuma numuram jābūt veselam skaitlim'
25} );
diff --git a/sources/plugins/liststyle/lang/mk.js b/sources/plugins/liststyle/lang/mk.js
new file mode 100644
index 0000000..dbb640b
--- /dev/null
+++ b/sources/plugins/liststyle/lang/mk.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'mk', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/mn.js b/sources/plugins/liststyle/lang/mn.js
new file mode 100644
index 0000000..54e884c
--- /dev/null
+++ b/sources/plugins/liststyle/lang/mn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'mn', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Төрөл',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/ms.js b/sources/plugins/liststyle/lang/ms.js
new file mode 100644
index 0000000..297c02c
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ms.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ms', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/nb.js b/sources/plugins/liststyle/lang/nb.js
new file mode 100644
index 0000000..0fe7859
--- /dev/null
+++ b/sources/plugins/liststyle/lang/nb.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'nb', {
6 armenian: 'Armensk nummerering',
7 bulletedTitle: 'Egenskaper for punktliste',
8 circle: 'Sirkel',
9 decimal: 'Tall (1, 2, 3, osv.)',
10 decimalLeadingZero: 'Tall, med førstesiffer null (01, 02, 03, osv.)',
11 disc: 'Disk',
12 georgian: 'Georgisk nummerering (an, ban, gan, osv.)',
13 lowerAlpha: 'Alfabetisk, små (a, b, c, d, e, osv.)',
14 lowerGreek: 'Gresk, små (alpha, beta, gamma, osv.)',
15 lowerRoman: 'Romertall, små (i, ii, iii, iv, v, osv.)',
16 none: 'Ingen',
17 notset: '<ikke satt>',
18 numberedTitle: 'Egenskaper for nummerert liste',
19 square: 'Firkant',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Alfabetisk, store (A, B, C, D, E, osv.)',
23 upperRoman: 'Romertall, store (I, II, III, IV, V, osv.)',
24 validateStartNumber: 'Starten på listen må være et heltall.'
25} );
diff --git a/sources/plugins/liststyle/lang/nl.js b/sources/plugins/liststyle/lang/nl.js
new file mode 100644
index 0000000..88ea3f8
--- /dev/null
+++ b/sources/plugins/liststyle/lang/nl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'nl', {
6 armenian: 'Armeense nummering',
7 bulletedTitle: 'Eigenschappen lijst met opsommingstekens',
8 circle: 'Cirkel',
9 decimal: 'Cijfers (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Cijfers beginnen met nul (01, 02, 03, etc.)',
11 disc: 'Schijf',
12 georgian: 'Georgische nummering (an, ban, gan, etc.)',
13 lowerAlpha: 'Kleine letters (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grieks kleine letters (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Romeins kleine letters (i, ii, iii, iv, v, etc.)',
16 none: 'Geen',
17 notset: '<niet gezet>',
18 numberedTitle: 'Eigenschappen genummerde lijst',
19 square: 'Vierkant',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Hoofdletters (A, B, C, D, E, etc.)',
23 upperRoman: 'Romeinse hoofdletters (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Startnummer van de lijst moet een heel nummer zijn.'
25} );
diff --git a/sources/plugins/liststyle/lang/no.js b/sources/plugins/liststyle/lang/no.js
new file mode 100644
index 0000000..26927e6
--- /dev/null
+++ b/sources/plugins/liststyle/lang/no.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'no', {
6 armenian: 'Armensk nummerering',
7 bulletedTitle: 'Egenskaper for punktmerket liste',
8 circle: 'Sirkel',
9 decimal: 'Tall (1, 2, 3, osv.)',
10 decimalLeadingZero: 'Tall, med førstesiffer null (01, 02, 03, osv.)',
11 disc: 'Disk',
12 georgian: 'Georgisk nummerering (an, ban, gan, osv.)',
13 lowerAlpha: 'Alfabetisk, små (a, b, c, d, e, osv.)',
14 lowerGreek: 'Gresk, små (alpha, beta, gamma, osv.)',
15 lowerRoman: 'Romertall, små (i, ii, iii, iv, v, osv.)',
16 none: 'Ingen',
17 notset: '<ikke satt>',
18 numberedTitle: 'Egenskaper for nummerert liste',
19 square: 'Firkant',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Alfabetisk, store (A, B, C, D, E, osv.)',
23 upperRoman: 'Romertall, store (I, II, III, IV, V, osv.)',
24 validateStartNumber: 'Starten på listen må være et heltall.'
25} );
diff --git a/sources/plugins/liststyle/lang/oc.js b/sources/plugins/liststyle/lang/oc.js
new file mode 100644
index 0000000..eb64753
--- /dev/null
+++ b/sources/plugins/liststyle/lang/oc.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'oc', {
6 armenian: 'Numerotacion armènia',
7 bulletedTitle: 'Proprietats de la lista de piuses',
8 circle: 'Cercle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal precedit per un 0 (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Numeracion georgiana (an, ban, gan, etc.)',
13 lowerAlpha: 'Letras minusculas (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grèc minuscula (alfa, bèta, gamma, etc.)',
15 lowerRoman: 'Chifras romanas minusculas (i, ii, iii, iv, v, etc.)',
16 none: 'Pas cap',
17 notset: '<indefinit>',
18 numberedTitle: 'Proprietats de la lista numerotada',
19 square: 'Carrat',
20 start: 'Començament',
21 type: 'Tipe',
22 upperAlpha: 'Letras majusculas (A, B, C, D, E, etc.)',
23 upperRoman: 'Chifras romanas majusculas (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Lo primièr element de la lista deu èsser un nombre entièr.'
25} );
diff --git a/sources/plugins/liststyle/lang/pl.js b/sources/plugins/liststyle/lang/pl.js
new file mode 100644
index 0000000..37d2cd7
--- /dev/null
+++ b/sources/plugins/liststyle/lang/pl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'pl', {
6 armenian: 'Numerowanie armeńskie',
7 bulletedTitle: 'Właściwości list wypunktowanych',
8 circle: 'Koło',
9 decimal: 'Liczby (1, 2, 3 itd.)',
10 decimalLeadingZero: 'Liczby z początkowym zerem (01, 02, 03 itd.)',
11 disc: 'Okrąg',
12 georgian: 'Numerowanie gruzińskie (an, ban, gan itd.)',
13 lowerAlpha: 'Małe litery (a, b, c, d, e itd.)',
14 lowerGreek: 'Małe litery greckie (alpha, beta, gamma itd.)',
15 lowerRoman: 'Małe cyfry rzymskie (i, ii, iii, iv, v itd.)',
16 none: 'Brak',
17 notset: '<nie ustawiono>',
18 numberedTitle: 'Właściwości list numerowanych',
19 square: 'Kwadrat',
20 start: 'Początek',
21 type: 'Typ punktora',
22 upperAlpha: 'Duże litery (A, B, C, D, E itd.)',
23 upperRoman: 'Duże cyfry rzymskie (I, II, III, IV, V itd.)',
24 validateStartNumber: 'Listę musi rozpoczynać liczba całkowita.'
25} );
diff --git a/sources/plugins/liststyle/lang/pt-br.js b/sources/plugins/liststyle/lang/pt-br.js
new file mode 100644
index 0000000..c5f0296
--- /dev/null
+++ b/sources/plugins/liststyle/lang/pt-br.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'pt-br', {
6 armenian: 'Numeração Armêna',
7 bulletedTitle: 'Propriedades da Lista sem Numeros',
8 circle: 'Círculo',
9 decimal: 'Numeração Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Numeração Decimal com zeros (01, 02, 03, etc.)',
11 disc: 'Disco',
12 georgian: 'Numeração da Geórgia (an, ban, gan, etc.)',
13 lowerAlpha: 'Numeração Alfabética minúscula (a, b, c, d, e, etc.)',
14 lowerGreek: 'Numeração Grega minúscula (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Numeração Romana minúscula (i, ii, iii, iv, v, etc.)',
16 none: 'Nenhum',
17 notset: '<não definido>',
18 numberedTitle: 'Propriedades da Lista Numerada',
19 square: 'Quadrado',
20 start: 'Início',
21 type: 'Tipo',
22 upperAlpha: 'Numeração Alfabética Maiúscula (A, B, C, D, E, etc.)',
23 upperRoman: 'Numeração Romana maiúscula (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'O número inicial da lista deve ser um número inteiro.'
25} );
diff --git a/sources/plugins/liststyle/lang/pt.js b/sources/plugins/liststyle/lang/pt.js
new file mode 100644
index 0000000..7dc1f25
--- /dev/null
+++ b/sources/plugins/liststyle/lang/pt.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'pt', {
6 armenian: 'Numeração armênia',
7 bulletedTitle: 'Propriedades da lista não numerada',
8 circle: 'Círculo',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Zero decimal à esquerda (01, 02, 03, etc.)',
11 disc: 'Disco',
12 georgian: 'Numeração georgiana (an, ban, gan, etc.)',
13 lowerAlpha: 'Minúsculas (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grego em minúsculas (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Romano em minúsculas (i, ii, iii, iv, v, etc.)',
16 none: 'Nenhum',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Quadrado',
20 start: 'Iniciar',
21 type: 'Tipo',
22 upperAlpha: 'Maiúsculas (A, B, C, D, E, etc.)',
23 upperRoman: 'Romanos em maiúscula (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'A lista tem iniciar por um número inteiro'
25} );
diff --git a/sources/plugins/liststyle/lang/ro.js b/sources/plugins/liststyle/lang/ro.js
new file mode 100644
index 0000000..5a8c327
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ro.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ro', {
6 armenian: 'Numerotare armeniană',
7 bulletedTitle: 'Proprietățile listei cu simboluri',
8 circle: 'Cerc',
9 decimal: 'Decimale (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimale cu zero în față (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Numerotare georgiană (an, ban, gan, etc.)',
13 lowerAlpha: 'Litere mici (a, b, c, d, e, etc.)',
14 lowerGreek: 'Litere grecești mici (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Cifre romane mici (i, ii, iii, iv, v, etc.)',
16 none: 'Nimic',
17 notset: '<nesetat>',
18 numberedTitle: 'Proprietățile listei numerotate',
19 square: 'Pătrat',
20 start: 'Start',
21 type: 'Tip',
22 upperAlpha: 'Litere mari (A, B, C, D, E, etc.)',
23 upperRoman: 'Cifre romane mari (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Începutul listei trebuie să fie un număr întreg.'
25} );
diff --git a/sources/plugins/liststyle/lang/ru.js b/sources/plugins/liststyle/lang/ru.js
new file mode 100644
index 0000000..5bfa8c6
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ru.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ru', {
6 armenian: 'Армянская нумерация',
7 bulletedTitle: 'Свойства маркированного списка',
8 circle: 'Круг',
9 decimal: 'Десятичные (1, 2, 3, и т.д.)',
10 decimalLeadingZero: 'Десятичные с ведущим нулём (01, 02, 03, и т.д.)',
11 disc: 'Окружность',
12 georgian: 'Грузинская нумерация (ани, бани, гани, и т.д.)',
13 lowerAlpha: 'Строчные латинские (a, b, c, d, e, и т.д.)',
14 lowerGreek: 'Строчные греческие (альфа, бета, гамма, и т.д.)',
15 lowerRoman: 'Строчные римские (i, ii, iii, iv, v, и т.д.)',
16 none: 'Нет',
17 notset: '<не указано>',
18 numberedTitle: 'Свойства нумерованного списка',
19 square: 'Квадрат',
20 start: 'Начиная с',
21 type: 'Тип',
22 upperAlpha: 'Заглавные латинские (A, B, C, D, E, и т.д.)',
23 upperRoman: 'Заглавные римские (I, II, III, IV, V, и т.д.)',
24 validateStartNumber: 'Первый номер списка должен быть задан обычным целым числом.'
25} );
diff --git a/sources/plugins/liststyle/lang/si.js b/sources/plugins/liststyle/lang/si.js
new file mode 100644
index 0000000..b401a13
--- /dev/null
+++ b/sources/plugins/liststyle/lang/si.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'si', {
6 armenian: 'Armenian numbering', // MISSING
7 bulletedTitle: 'Bulleted List Properties', // MISSING
8 circle: 'Circle', // MISSING
9 decimal: 'Decimal (1, 2, 3, etc.)', // MISSING
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)', // MISSING
11 disc: 'Disc', // MISSING
12 georgian: 'Georgian numbering (an, ban, gan, etc.)', // MISSING
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)', // MISSING
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)', // MISSING
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)', // MISSING
16 none: 'කිසිවක්ම නොවේ',
17 notset: '<යොදා >',
18 numberedTitle: 'Numbered List Properties', // MISSING
19 square: 'Square', // MISSING
20 start: 'Start', // MISSING
21 type: 'වර්ගය',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)', // MISSING
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)', // MISSING
24 validateStartNumber: 'List start number must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/liststyle/lang/sk.js b/sources/plugins/liststyle/lang/sk.js
new file mode 100644
index 0000000..2529c18
--- /dev/null
+++ b/sources/plugins/liststyle/lang/sk.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'sk', {
6 armenian: 'Arménske číslovanie',
7 bulletedTitle: 'Vlastnosti odrážkového zoznamu',
8 circle: 'Kruh',
9 decimal: 'Číselné (1, 2, 3, atď.)',
10 decimalLeadingZero: 'Číselné s nulou (01, 02, 03, atď.)',
11 disc: 'Disk',
12 georgian: 'Gruzínske číslovanie (an, ban, gan, atď.)',
13 lowerAlpha: 'Malé latinské (a, b, c, d, e, atď.)',
14 lowerGreek: 'Malé grécke (alfa, beta, gama, atď.)',
15 lowerRoman: 'Malé rímske (i, ii, iii, iv, v, atď.)',
16 none: 'Nič',
17 notset: '<nenastavené>',
18 numberedTitle: 'Vlastnosti číselného zoznamu',
19 square: 'Štvorec',
20 start: 'Začiatok',
21 type: 'Typ',
22 upperAlpha: 'Veľké latinské (A, B, C, D, E, atď.)',
23 upperRoman: 'Veľké rímske (I, II, III, IV, V, atď.)',
24 validateStartNumber: 'Začiatočné číslo číselného zoznamu musí byť celé číslo.'
25} );
diff --git a/sources/plugins/liststyle/lang/sl.js b/sources/plugins/liststyle/lang/sl.js
new file mode 100644
index 0000000..bd6c27f
--- /dev/null
+++ b/sources/plugins/liststyle/lang/sl.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'sl', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/sq.js b/sources/plugins/liststyle/lang/sq.js
new file mode 100644
index 0000000..6ee94a5
--- /dev/null
+++ b/sources/plugins/liststyle/lang/sq.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'sq', {
6 armenian: 'Numërim armenian',
7 bulletedTitle: 'Karakteristikat e Listës me Pulla',
8 circle: 'Rreth',
9 decimal: 'Decimal (1, 2, 3, etj.)',
10 decimalLeadingZero: 'Decimal me zerro udhëheqëse (01, 02, 03, etj.)',
11 disc: 'Disk',
12 georgian: 'Numërim gjeorgjian (an, ban, gan, etj.)',
13 lowerAlpha: 'Të vogla alfa (a, b, c, d, e, etj.)',
14 lowerGreek: 'Të vogla greke (alpha, beta, gamma, etj.)',
15 lowerRoman: 'Të vogla romake (i, ii, iii, iv, v, etj.)',
16 none: 'Asnjë',
17 notset: '<e pazgjedhur>',
18 numberedTitle: 'Karakteristikat e Listës me Numra',
19 square: 'Katror',
20 start: 'Fillimi',
21 type: 'LLoji',
22 upperAlpha: 'Të mëdha alfa (A, B, C, D, E, etj.)',
23 upperRoman: 'Të mëdha romake (I, II, III, IV, V, etj.)',
24 validateStartNumber: 'Numri i fillimit të listës duhet të është numër i plotë.'
25} );
diff --git a/sources/plugins/liststyle/lang/sr-latn.js b/sources/plugins/liststyle/lang/sr-latn.js
new file mode 100644
index 0000000..75d1cfa
--- /dev/null
+++ b/sources/plugins/liststyle/lang/sr-latn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'sr-latn', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/sr.js b/sources/plugins/liststyle/lang/sr.js
new file mode 100644
index 0000000..f89a441
--- /dev/null
+++ b/sources/plugins/liststyle/lang/sr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'sr', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/sv.js b/sources/plugins/liststyle/lang/sv.js
new file mode 100644
index 0000000..49bbf48
--- /dev/null
+++ b/sources/plugins/liststyle/lang/sv.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'sv', {
6 armenian: 'Armenisk numrering',
7 bulletedTitle: 'Egenskaper för punktlista',
8 circle: 'Cirkel',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal nolla (01, 02, 03, etc.)',
11 disc: 'Disk',
12 georgian: 'Georgisk numrering (an, ban, gan, etc.)',
13 lowerAlpha: 'Alpha gemener (a, b, c, d, e, etc.)',
14 lowerGreek: 'Grekiska gemener (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Romerska gemener (i, ii, iii, iv, v, etc.)',
16 none: 'Ingen',
17 notset: '<ej angiven>',
18 numberedTitle: 'Egenskaper för punktlista',
19 square: 'Fyrkant',
20 start: 'Start',
21 type: 'Typ',
22 upperAlpha: 'Alpha versaler (A, B, C, D, E, etc.)',
23 upperRoman: 'Romerska versaler (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'Listans startnummer måste vara ett heltal.'
25} );
diff --git a/sources/plugins/liststyle/lang/th.js b/sources/plugins/liststyle/lang/th.js
new file mode 100644
index 0000000..d1425e8
--- /dev/null
+++ b/sources/plugins/liststyle/lang/th.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'th', {
6 armenian: 'Armenian numbering',
7 bulletedTitle: 'Bulleted List Properties',
8 circle: 'Circle',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal leading zero (01, 02, 03, etc.)',
11 disc: 'Disc',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)',
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)',
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)',
16 none: 'None',
17 notset: '<not set>',
18 numberedTitle: 'Numbered List Properties',
19 square: 'Square',
20 start: 'Start',
21 type: 'Type',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)',
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'List start number must be a whole number.'
25} );
diff --git a/sources/plugins/liststyle/lang/tr.js b/sources/plugins/liststyle/lang/tr.js
new file mode 100644
index 0000000..f08131e
--- /dev/null
+++ b/sources/plugins/liststyle/lang/tr.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'tr', {
6 armenian: 'Ermenice sayılandırma',
7 bulletedTitle: 'Simgeli Liste Özellikleri',
8 circle: 'Daire',
9 decimal: 'Ondalık (1, 2, 3, vs.)',
10 decimalLeadingZero: 'Başı sıfırlı ondalık (01, 02, 03, vs.)',
11 disc: 'Disk',
12 georgian: 'Gürcüce numaralandırma (an, ban, gan, vs.)',
13 lowerAlpha: 'Küçük Alpha (a, b, c, d, e, vs.)',
14 lowerGreek: 'Küçük Greek (alpha, beta, gamma, vs.)',
15 lowerRoman: 'Küçük Roman (i, ii, iii, iv, v, vs.)',
16 none: 'Yok',
17 notset: '<ayarlanmamış>',
18 numberedTitle: 'Sayılandırılmış Liste Özellikleri',
19 square: 'Kare',
20 start: 'Başla',
21 type: 'Tipi',
22 upperAlpha: 'Büyük Alpha (A, B, C, D, E, vs.)',
23 upperRoman: 'Büyük Roman (I, II, III, IV, V, vs.)',
24 validateStartNumber: 'Liste başlangıcı tam sayı olmalıdır.'
25} );
diff --git a/sources/plugins/liststyle/lang/tt.js b/sources/plugins/liststyle/lang/tt.js
new file mode 100644
index 0000000..13991f4
--- /dev/null
+++ b/sources/plugins/liststyle/lang/tt.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'tt', {
6 armenian: 'Әрмән номерлавы',
7 bulletedTitle: 'Маркерлы тезмә үзлекләре',
8 circle: 'Түгәрәк',
9 decimal: 'Унарлы (1, 2, 3, ...)',
10 decimalLeadingZero: 'Ноль белән башланган унарлы (01, 02, 03, ...)',
11 disc: 'Диск',
12 georgian: 'Georgian numbering (an, ban, gan, etc.)', // MISSING
13 lowerAlpha: 'Lower Alpha (a, b, c, d, e, etc.)', // MISSING
14 lowerGreek: 'Lower Greek (alpha, beta, gamma, etc.)', // MISSING
15 lowerRoman: 'Lower Roman (i, ii, iii, iv, v, etc.)', // MISSING
16 none: 'Һичбер',
17 notset: '<билгеләнмәгән>',
18 numberedTitle: 'Номерлы тезмә үзлекләре',
19 square: 'Шакмак',
20 start: 'Башлау',
21 type: 'Төр',
22 upperAlpha: 'Upper Alpha (A, B, C, D, E, etc.)', // MISSING
23 upperRoman: 'Upper Roman (I, II, III, IV, V, etc.)', // MISSING
24 validateStartNumber: 'List start number must be a whole number.' // MISSING
25} );
diff --git a/sources/plugins/liststyle/lang/ug.js b/sources/plugins/liststyle/lang/ug.js
new file mode 100644
index 0000000..2d4336e
--- /dev/null
+++ b/sources/plugins/liststyle/lang/ug.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'ug', {
6 armenian: 'قەدىمكى ئەرمىنىيە تەرتىپ نومۇرى شەكلى',
7 bulletedTitle: 'تۈر بەلگە تىزىم خاسلىقى',
8 circle: 'بوش چەمبەر',
9 decimal: 'سان (1, 2, 3 قاتارلىق)',
10 decimalLeadingZero: 'نۆلدىن باشلانغان سان بەلگە (01, 02, 03 قاتارلىق)',
11 disc: 'تولدۇرۇلغان چەمبەر',
12 georgian: 'قەدىمكى جورجىيە تەرتىپ نومۇرى شەكلى (an, ban, gan قاتارلىق)',
13 lowerAlpha: 'ئىنگلىزچە كىچىك ھەرپ (a, b, c, d, e قاتارلىق)',
14 lowerGreek: 'گرېكچە كىچىك ھەرپ (alpha, beta, gamma قاتارلىق)',
15 lowerRoman: 'كىچىك ھەرپلىك رىم رەقىمى (i, ii, iii, iv, v قاتارلىق)',
16 none: 'بەلگە يوق',
17 notset: '‹تەڭشەلمىگەن›',
18 numberedTitle: 'تەرتىپ نومۇر تىزىم خاسلىقى',
19 square: 'تولدۇرۇلغان تۆت چاسا',
20 start: 'باشلىنىش نومۇرى',
21 type: 'بەلگە تىپى',
22 upperAlpha: 'ئىنگلىزچە چوڭ ھەرپ (A, B, C, D, E قاتارلىق)',
23 upperRoman: 'چوڭ ھەرپلىك رىم رەقىمى (I, II, III, IV, V قاتارلىق)',
24 validateStartNumber: 'تىزىم باشلىنىش تەرتىپ نومۇرى چوقۇم پۈتۈن سان پىچىمىدا بولۇشى لازىم'
25} );
diff --git a/sources/plugins/liststyle/lang/uk.js b/sources/plugins/liststyle/lang/uk.js
new file mode 100644
index 0000000..7ef2343
--- /dev/null
+++ b/sources/plugins/liststyle/lang/uk.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'uk', {
6 armenian: 'Вірменська нумерація',
7 bulletedTitle: 'Опції маркованого списку',
8 circle: 'Кільце',
9 decimal: 'Десяткові (1, 2, 3 і т.д.)',
10 decimalLeadingZero: 'Десяткові з нулем (01, 02, 03 і т.д.)',
11 disc: 'Кружечок',
12 georgian: 'Грузинська нумерація (an, ban, gan і т.д.)',
13 lowerAlpha: 'Малі лат. букви (a, b, c, d, e і т.д.)',
14 lowerGreek: 'Малі гр. букви (альфа, бета, гамма і т.д.)',
15 lowerRoman: 'Малі римські (i, ii, iii, iv, v і т.д.)',
16 none: 'Нема',
17 notset: '<не вказано>',
18 numberedTitle: 'Опції нумерованого списку',
19 square: 'Квадратик',
20 start: 'Почати з...',
21 type: 'Тип',
22 upperAlpha: 'Великі лат. букви (A, B, C, D, E і т.д.)',
23 upperRoman: 'Великі римські (I, II, III, IV, V і т.д.)',
24 validateStartNumber: 'Початковий номер списку повинен бути цілим числом.'
25} );
diff --git a/sources/plugins/liststyle/lang/vi.js b/sources/plugins/liststyle/lang/vi.js
new file mode 100644
index 0000000..c5ecc44
--- /dev/null
+++ b/sources/plugins/liststyle/lang/vi.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'vi', {
6 armenian: 'Số theo kiểu Armenian',
7 bulletedTitle: 'Thuộc tính danh sách không thứ tự',
8 circle: 'Khuyên tròn',
9 decimal: 'Kiểu số (1, 2, 3 ...)',
10 decimalLeadingZero: 'Kiểu số (01, 02, 03...)',
11 disc: 'Hình đĩa',
12 georgian: 'Số theo kiểu Georgian (an, ban, gan...)',
13 lowerAlpha: 'Kiểu abc thường (a, b, c, d, e...)',
14 lowerGreek: 'Kiểu Hy Lạp (alpha, beta, gamma...)',
15 lowerRoman: 'Số La Mã kiểu thường (i, ii, iii, iv, v...)',
16 none: 'Không gì cả',
17 notset: '<không thiết lập>',
18 numberedTitle: 'Thuộc tính danh sách có thứ tự',
19 square: 'Hình vuông',
20 start: 'Bắt đầu',
21 type: 'Kiểu loại',
22 upperAlpha: 'Kiểu ABC HOA (A, B, C, D, E...)',
23 upperRoman: 'Số La Mã kiểu HOA (I, II, III, IV, V...)',
24 validateStartNumber: 'Số bắt đầu danh sách phải là một số nguyên.'
25} );
diff --git a/sources/plugins/liststyle/lang/zh-cn.js b/sources/plugins/liststyle/lang/zh-cn.js
new file mode 100644
index 0000000..9d274c2
--- /dev/null
+++ b/sources/plugins/liststyle/lang/zh-cn.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'zh-cn', {
6 armenian: '传统的亚美尼亚编号方式',
7 bulletedTitle: '项目列表属性',
8 circle: '空心圆',
9 decimal: '数字 (1, 2, 3, 等)',
10 decimalLeadingZero: '0开头的数字标记(01, 02, 03, 等)',
11 disc: '实心圆',
12 georgian: '传统的乔治亚编号方式(an, ban, gan, 等)',
13 lowerAlpha: '小写英文字母(a, b, c, d, e, 等)',
14 lowerGreek: '小写希腊字母(alpha, beta, gamma, 等)',
15 lowerRoman: '小写罗马数字(i, ii, iii, iv, v, 等)',
16 none: '无标记',
17 notset: '<没有设置>',
18 numberedTitle: '编号列表属性',
19 square: '实心方块',
20 start: '开始序号',
21 type: '标记类型',
22 upperAlpha: '大写英文字母(A, B, C, D, E, 等)',
23 upperRoman: '大写罗马数字(I, II, III, IV, V, 等)',
24 validateStartNumber: '列表开始序号必须为整数格式'
25} );
diff --git a/sources/plugins/liststyle/lang/zh.js b/sources/plugins/liststyle/lang/zh.js
new file mode 100644
index 0000000..e832518
--- /dev/null
+++ b/sources/plugins/liststyle/lang/zh.js
@@ -0,0 +1,25 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'liststyle', 'zh', {
6 armenian: '亞美尼亞數字',
7 bulletedTitle: '項目符號清單屬性',
8 circle: '圓圈',
9 decimal: '小數點 (1, 2, 3, etc.)',
10 decimalLeadingZero: '前綴 0 十位數字 (01, 02, 03, 等)',
11 disc: '圓點',
12 georgian: '喬治王時代數字 (an, ban, gan, 等)',
13 lowerAlpha: '小寫字母 (a, b, c, d, e 等)',
14 lowerGreek: '小寫希臘字母 (alpha, beta, gamma, 等)',
15 lowerRoman: '小寫羅馬數字 (i, ii, iii, iv, v 等)',
16 none: '無',
17 notset: '<未設定>',
18 numberedTitle: '編號清單屬性',
19 square: '方塊',
20 start: '開始',
21 type: '類型',
22 upperAlpha: '大寫字母 (A, B, C, D, E 等)',
23 upperRoman: '大寫羅馬數字 (I, II, III, IV, V 等)',
24 validateStartNumber: '清單起始號碼須為一完整數字。'
25} );
diff --git a/sources/plugins/liststyle/plugin.js b/sources/plugins/liststyle/plugin.js
new file mode 100644
index 0000000..2d94142
--- /dev/null
+++ b/sources/plugins/liststyle/plugin.js
@@ -0,0 +1,75 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 CKEDITOR.plugins.liststyle = {
8 requires: 'dialog,contextmenu',
9 // jscs:disable maximumLineLength
10 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
11 // jscs:enable maximumLineLength
12 init: function( editor ) {
13 if ( editor.blockless )
14 return;
15
16 var def, cmd;
17
18 def = new CKEDITOR.dialogCommand( 'numberedListStyle', {
19 requiredContent: 'ol',
20 allowedContent: 'ol{list-style-type}[start]; li{list-style-type}[value]',
21 contentTransformations: [
22 [ 'ol: listTypeToStyle' ]
23 ]
24 } );
25 cmd = editor.addCommand( 'numberedListStyle', def );
26 editor.addFeature( cmd );
27 CKEDITOR.dialog.add( 'numberedListStyle', this.path + 'dialogs/liststyle.js' );
28
29 def = new CKEDITOR.dialogCommand( 'bulletedListStyle', {
30 requiredContent: 'ul',
31 allowedContent: 'ul{list-style-type}',
32 contentTransformations: [
33 [ 'ul: listTypeToStyle' ]
34 ]
35 } );
36 cmd = editor.addCommand( 'bulletedListStyle', def );
37 editor.addFeature( cmd );
38 CKEDITOR.dialog.add( 'bulletedListStyle', this.path + 'dialogs/liststyle.js' );
39
40 //Register map group;
41 editor.addMenuGroup( 'list', 108 );
42
43 editor.addMenuItems( {
44 numberedlist: {
45 label: editor.lang.liststyle.numberedTitle,
46 group: 'list',
47 command: 'numberedListStyle'
48 },
49 bulletedlist: {
50 label: editor.lang.liststyle.bulletedTitle,
51 group: 'list',
52 command: 'bulletedListStyle'
53 }
54 } );
55
56 editor.contextMenu.addListener( function( element ) {
57 if ( !element || element.isReadOnly() )
58 return null;
59
60 while ( element ) {
61 var name = element.getName();
62 if ( name == 'ol' )
63 return { numberedlist: CKEDITOR.TRISTATE_OFF };
64 else if ( name == 'ul' )
65 return { bulletedlist: CKEDITOR.TRISTATE_OFF };
66
67 element = element.getParent();
68 }
69 return null;
70 } );
71 }
72 };
73
74 CKEDITOR.plugins.add( 'liststyle', CKEDITOR.plugins.liststyle );
75} )();
diff --git a/sources/plugins/magicline/dev/magicline.html b/sources/plugins/magicline/dev/magicline.html
new file mode 100644
index 0000000..077b670
--- /dev/null
+++ b/sources/plugins/magicline/dev/magicline.html
@@ -0,0 +1,594 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Magicline muddy trenches &ndash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link href="../../../samples/old/sample.css" rel="stylesheet">
12 <style>
13 body {
14 margin: 0 0 130px;
15 }
16 #dev {
17 border-top: 1px solid #555;
18 position: fixed;
19 bottom: 0px;
20 left: 0px;
21 right: 0px;
22 height: 110px;
23 background: #B5E5EE;
24 font-size: 15px;
25 }
26 #dev .hl {
27 color: red;
28 }
29 #tr_upper, #tr_lower {
30 padding: 3px 6px;
31 }
32 #tr_upper {
33 background: rgba(255,0,0,.3);
34 }
35 #tr_lower {
36 background: rgba(0,255,0,.3);
37 }
38
39 #dev p {
40 margin: 0;
41 padding: 0;
42 }
43
44 #timeData,
45 #triggerData,
46 #mouseData,
47 #hiddenData {
48 position: absolute;
49 }
50 #timeData {
51 right: 10px;
52 top: 10px;
53 }
54 #hiddenData {
55 right: 10px;
56 top: 40px;
57 }
58 #mouseData {
59 left: 10px;
60 top: 10px;
61 }
62 #dev h2 {
63 top: 10px;
64 left: 10px;
65 }
66 #triggerData {
67 bottom: 10px;
68 left: 10px;
69 }
70 </style>
71</head>
72<body>
73 <h1 class="samples">
74 CKEditor Sample &mdash; magicline muddy trenches
75 </h1>
76
77 <h2>Various cases</h2>
78 <textarea cols="80" id="editor1" name="editor1" rows="10">
79 <div style="padding: 20px; background: gray; width: 300px" class="1">Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim.</div>
80 <div style="background: violet; padding: 30px" class="static">Position static</div>
81 <dl class="2">
82 <dt>Key</dt><dd>Value</dd>
83 </dl>
84 <div>Whatever</div>
85 <hr id="hr">
86 <div style="
87 display: block;
88 cursor: pointer;
89 background: green;
90 height: 50px; width: 50px;" >aasd
91 </div>
92 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
93 <hr>
94 <hr>
95 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
96 <table border="1" class="first">
97 <tbody><tr>
98 <td>
99 Table Cell 1
100 </td>
101 </tr>
102 <tr>
103 <td>
104 Table Cell 2<br>
105 Table Cell 2<br>
106 </td>
107 </tr>
108 </tbody>
109 </table>
110 <div style="border: 1px solid red; padding: 50px">
111 Parent
112 <div style="border: 10px solid green; padding: 10px">Child</div>
113 </div>
114 I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body.
115 I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body.
116 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
117 <table border="1" style="margin: 15px 0 100px" class="outer">
118 <tbody>
119 <tr>
120 <td>Table Cell 1</td>
121 <td>Table Cell 1</td>
122 </tr>
123 <tr>
124 <td>
125 <table border="10" class="inner">
126 <tbody>
127 <tr>
128 <td>Table Cell 1</td>
129 </tr>
130 <tr>
131 <td>Table Cell 2<br> Table Cell 2<br></td>
132 </tr>
133 </tbody>
134 </table>
135 </td>
136 </tr>
137 </tbody>
138 </table>
139 <table border="1" style="margin: 15px" class="third">
140 <tbody><tr>
141 <td>
142 Table Cell 1
143 </td>
144 <td>
145 Table Cell 1
146 </td>
147 <td>
148 Table Cell 1
149 </td>
150 <td>
151 Table Cell 1
152 </td>
153 </tr>
154 <tr>
155 <td>
156 Table Cell 2
157 </td>
158 </tr>
159 </tbody>
160 </table>
161 <table border="1" style="margin: 15px" class="fourth">
162 <tbody><tr>
163 <td>
164 Table Cell 1
165 </td>
166 <td>
167 Table Cell 1
168 </td>
169 <td>
170 Table Cell 1
171 </td>
172 <td>
173 Table Cell 1
174 </td>
175 </tr>
176 <tr>
177 <td>
178 Table Cell 2
179 </td>
180 </tr>
181 </tbody>
182 </table>
183 <ul style="" class="fifth">
184 <li name="ul_first">List item</li>
185 <li name="ul_second">
186 <ol style="">
187 <li name="ol_first">Nested item</li>
188 <li>Nested item</li>
189 <li>Nested item</li>
190 </ol>
191 </li>
192 <li>List item</li>
193 </ul>
194 <table border="1" class="table#123">
195 <tbody>
196 <tr>
197 <td>Table Cell 1</td>
198 </tr>
199 <tr>
200 <td>Table Cell 2<br> Table Cell 2<br></td>
201 </tr>
202 </tbody>
203 </table>
204 <table border="1" align="right" class="aligned">
205 <tbody>
206 <tr>
207 <td>Table Cell 1</td>
208 </tr>
209 <tr>
210 <td>Table Cell 2<br> Table Cell 2<br></td>
211 </tr>
212 </tbody>
213 </table>
214 <table border="1" style="float: right" class="floated">
215 <tbody>
216 <tr>
217 <td>Table Cell 1</td>
218 </tr>
219 <tr>
220 <td>Table Cell 2<br> Table Cell 2<br></td>
221 </tr>
222 </tbody>
223 </table>
224 <table border="1" align=""class="table#124">
225 <tbody>
226 <tr>
227 <td>Table Cell 1</td>
228 </tr>
229 <tr>
230 <td>Table Cell 2<br> Table Cell 2<br></td>
231 </tr>
232 </tbody>
233 </table>
234 <table border="1"class="table#125">
235 <tbody>
236 <tr>
237 <td>Table Cell 1</td>
238 </tr>
239 <tr>
240 <td>Table Cell 2<br> Table Cell 2<br></td>
241 </tr>
242 </tbody>
243 </table>
244 <p> enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas male</p>
245 <table border="1"class="table#126">
246 <tbody>
247 <tr>
248 <td>Table Cell 1</td>
249 </tr>
250 <tr>
251 <td>Table Cell 2<br> Table Cell 2<br></td>
252 </tr>
253 </tbody>
254 </table>
255 <div style="background: orange; margin: 20px">Upper div</div>
256 <table style="background: blue; margin: 20px"><tr><td>Lower table</td></tr></table>
257 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
258 <div><strong>I'm a div. Let me stay here.</strong></div><dl>
259 <dt>Key</dt>
260 <dd>pendisse a pellentesque dui, non felis</dd>
261 <dt>Key</dt>
262 <dd>pendisse a pellentesque dui, non felis</dd>
263 </dl>
264 <div class="11" style="padding: 20px; background: pink; width: 400px">
265 Parent
266 <div class="12" style="padding: 20px; background: orange">
267 <!-- comment -->
268 <!-- another comment -->
269 <div class="13" style="padding: 20px; background: green">
270 Child#2
271 </div>
272 </div>
273 </div>
274 </textarea>
275
276 <h2>Odd case: first (last) element at the very beginning, short editable</h2>
277 <textarea cols="80" id="editor2" name="editor1a" rows="10">
278 <table border="1" style="width: 300px">
279 <tbody>
280 <tr>
281 <td>
282 Test</td>
283 </tr>
284 </tbody>
285 </table>
286 </textarea>
287
288 <h2>Large document, put everywhere</h2>
289 <textarea id="editor3">
290 <p><div class="navbar" align="center" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;"><a accesskey="p" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">previous</a>   <a accesskey="n" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/idl-definitions.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">next</a>   <a accesskey="c" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/Overview.html#contents" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">contents</a>   <a accesskey="i" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/def-index.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">index</a><hr title="Navigation area separator"></div><div class="noprint" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;text-align: right;"><p style="font-family: monospace;font-size: small;">13 November, 2000</p></div><div class="div1" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;"><a id="Range" name="Range"></a><h1 id="Range-h1" class="div1" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 27px;font-weight: normal; background-color: violet">2. Document Object Model Range</h1><dl style="background: green"><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><i>Editors</i></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Peter Sharpe, SoftQuad Software Inc.</dd><dd style="margin-top: 0px;margin-bottom: 0px;">Vidur Apparao, Netscape Communications Corp.</dd><dd style="margin-top: 0px;margin-bottom: 0px;">Lauren Wood, SoftQuad Software Inc.</dd></dl><div class="noprint"><h2 id="table-of-contents" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">Table of contents</h2><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-introduction" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.1. Introduction</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Definitions" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial; background: red">2.2. Definitions and Notation</a><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.2.1. Position</a></li><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Containment" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.2.2. Selection and Partial Selection</a></li><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Notation" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.2.3. Notation</a></li></ul></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Creating" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.3. Creating a Range</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Changing" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.4. Changing a Range's Position</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.5. Comparing Range Boundary-Points</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Deleting-Content" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.6. Deleting Content with a Range</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Extracting" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.7. Extracting Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Cloning" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.8. Cloning Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Inserting" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.9. Inserting Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Surrounding" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.10. Surrounding Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Misc" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.11. Miscellaneous Members</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.12. Range modification under document mutation</a><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Insertions" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.12.1. Insertions</a></li><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Deletions" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.12.2. Deletions</a></li></ul></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Interface" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.13. Formal Description of the Range Interface</a><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline4" style="font-style: italic;"><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">Range</a>, <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-DocumentRange-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DocumentRange</a>, <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">RangeException</a>, <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeExceptionCode" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">RangeExceptionCode</a></li></ul></li></ul></div><div class="div2"><a id="Level-2-Range-introduction" name="Level-2-Range-introduction"></a><h2 id="Level-2-Range-introduction-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.1. Introduction</h2><p>A Range identifies a range of content in a Document, DocumentFragment or Attr. It is contiguous in the sense that it can be characterized as selecting all of the content between a pair of boundary-points.</p><p><b>Note:</b> In a text editor or a word processor, a user can make a selection by pressing down the mouse at one point in a document, moving the mouse to another point, and releasing the mouse. The resulting selection is contiguous and consists of the content between the two points.</p><p>The term 'selecting' does not mean that every Range corresponds to a selection made by a GUI user;however, such a selection can be returned to a DOM user as a Range.</p><p><b>Note:</b> In bidirectional writing (Arabic, Hebrew), a range may correspond to a logical selection that is not necessarily contiguous when displayed. A visually contiguous selection, also used in some cases, may not correspond to a single logical selection, and may therefore have to be represented by more than one range.</p><p>The Range interface provides methods for accessing and manipulating the document tree at a higher level than similar methods in the Node interface. The expectation is that each of the methods provided by the Range interface for the insertion, deletion and copying of content can be directly mapped to a series of Node editing operations enabled by DOM Core. In this sense, the Range operations can be viewed as convenience methods that also enable the implementation to optimize common editing patterns.</p><p>This chapter describes the Range interface, including methods for creating and moving a Range and methods for manipulating content with Ranges.</p><p>The interfaces found within this section are not mandatory. A DOM application may use the <code>hasFeature(feature, version)</code> method of the <code>DOMImplementation</code> interface with parameter values "Range" and "2.0" (respectively) to determine whether or not this module is supported by the implementation. In order to fully support this module, an implementation must also support the "Core" feature defined defined in the DOM Level 2 Core specification [<a class="noxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/references.html#DOMCore" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DOM Level 2 Core</a>]. Please refer to additional information about <a href="http://www.w3.org/TR/DOM-Level-2-Core/introduction.html#ID-Conformance" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>conformance</em></a> in the DOM Level 2 Core specification [<a class="noxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/references.html#DOMCore" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DOM Level 2 Core</a>].</p></div><div class="div2" style="background: blue;"><a id="Level-2-Range-Definitions" name="Level-2-Range-Definitions"></a><h2 id="Level-2-Range-Definitions-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal; background: red">2.2. Definitions and Notation</h2><div style="background: yellow" class="div3"><a id="Level-2-Range-Position" name="Level-2-Range-Position"></a><h3 id="Level-2-Range-Position-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.2.1. Position</h3><p>This chapter refers to two different representations of a document: the text or source form that includes the document markup and the tree representation similar to the one described in the introduction section of the DOM Level 2 Core [<a class="noxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/references.html#DOMCore" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DOM Level 2 Core</a>].</p><p>A Range consists of two <i>boundary-points</i> corresponding to the start and the end of the Range. <a id="td-boundarypoint" name="td-boundarypoint"></a>A boundary-point's position in a Document or DocumentFragment tree can be characterized by a node and an offset. <a id="td-container" name="td-container"></a>The node is called the <i>container</i> of the boundary-point and of its position. <a id="td-ancestor-container" name="td-ancestor-container"></a>The container and its ancestors are the <i>ancestor container</i>s of the boundary-point and of its position.<a id="td-offset" name="td-offset"></a>The offset within the node is called the <i>offset</i> of the boundary-point and its position. If the container is an Attr, Document, DocumentFragment, Element or EntityReference node, the offset is between its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-child" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>child</em></a> nodes. If the container is a CharacterData, Comment or ProcessingInstruction node, the offset is between the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit units</em></a> of the UTF-16 encoded string contained by it.</p><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-points</em></a> of a Range must have a common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> which is either a Document, DocumentFragment or Attr node. That is, the content of a Range must be entirely within the subtree rooted by a single Document, DocumentFragment or Attr Node. <a id="td-root-container" name="td-root-container"></a>This common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> is known as the <i>root container</i> of the Range. <a id="td-context-tree" name="td-context-tree"></a>The tree rooted by the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a> is known as the Range's <i>context tree</i>.</p><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of a Range must be an Element, Comment, ProcessingInstruction, EntityReference, CDATASection, Document, DocumentFragment, Attr, or Text node. None of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a>s of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of a Range can be a DocumentType, Entity or Notation node.</p><p>In terms of the text representation of a document, the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-points</em></a> of a Range can only be on token boundaries. That is, the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the text range cannot be in the middle of a start- or end-tag of an element or within the name of an entity or character reference. A Range locates a contiguous portion of the content of the structure model.</p><p>The relationship between locations in a text representation of the document and in the Node tree interface of the DOM is illustrated in the following diagram:<br></p><div align="center"><hr width="90%" size="2"><img src="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/images/RangeExample.gif" alt="Range Example"><hr width="90%" size="2"><b>Range Example</b><hr width="90%" size="2"></div><p>In this diagram, four different Ranges are illustrated. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-points</em></a> of each Range are labelled with <i>s#</i> (the start of the Range) and <i>e#</i> (the end of the Range), where # is the number of the Range. For Range 2, the start is in the BODY element and is immediately after the H1 element and immediately before the P element, so its position is between the H1 and P children of BODY. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> whose <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is not a CharacterData node is 0 if it is before the first child, 1 if between the first and second child, and so on. So, for the start of the Range 2, the<a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is BODY and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is 1. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> whose <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is a CharacterData node is obtained similarly but using <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit unit</em></a> positions instead. For example, the<a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> labelled s1 of the Range 1 has a Text node (the one containing "Title") as its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> and an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of 2 since it is between the second and third <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit unit</em></a>.</p><p>Notice that the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of Ranges 3 and 4 correspond to the same location in the text representation. An important feature of the Range is that a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of a Range can unambiguously represent every position within the document tree.</p><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>s and <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a>s of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s can be obtained through the following read-only Range attributes:</p><div class="eg"><pre style="margin-left: 2em;"> readonly attribute Node startContainer;readonly attribute long startOffset;readonly attribute Node endContainer;readonly attribute long endOffset;</pre></div><p><a id="td-collapsed" name="td-collapsed"></a>If the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of a Range have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>s and <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a>s, the Range is said to be a <i>collapsed</i> Range. (This is often referred to as an insertion point in a user agent.)</p></div><div class="div3"><a id="Level-2-Range-Containment" name="Level-2-Range-Containment"></a><h3 id="Level-2-Range-Containment-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.2.2. Selection and Partial Selection</h3><p><a id="td-selected" name="td-selected"></a>A node or <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit unit</em></a> unit is said to be <i>selected</i> by a Range if it is between the two <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of the Range, that is, if the position immediately before the node or 16-bit unit is before the end of the Range and the position immediately after the node or 16-bit unit is after the start of the range. For example, in terms of a text representation of the document, an element would be <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selected</em></a>by a Range if its corresponding start-tag was located after the start of the Range and its end-tag was located before the end of the Range. In the examples in the above diagram, the Range 2<a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selects</em></a> the P node and the Range 3 <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selects</em></a> the text node containing the text "Blah xyz."</p><p><a id="td-partially-selected" name="td-partially-selected"></a>A node is said to be <i>partially selected</i> by a Range if it is an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of exactly one <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the Range. For example, consider Range 1 in the above diagram. The element H1 is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by that Range since the start of the Range is within one of its children.</p></div><div class="div3"><a id="Level-2-Range-Notation" name="Level-2-Range-Notation"></a><h3 id="Level-2-Range-Notation-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.2.3. Notation</h3><p>Many of the examples in this chapter are illustrated using a text representation of a document. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of a Range are indicated by displaying the characters (be they markup or data characters) between the two <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s in bold, as in</p><div class="eg"><pre style="margin-left: 2em;"> <FOO>A<b>BC<BAR>DE</b>F</BAR></FOO></pre></div><p>When both <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s are at the same position, they are indicated with a bold caret ('<b>^</b>'), as in</p><div class="eg"><pre style="margin-left: 2em;"> <FOO>A<b>^</b>BC<BAR>DEF</BAR></FOO></pre></div></div></div><div class="div2"><a id="Level-2-Range-Creating" name="Level-2-Range-Creating"></a><h2 id="Level-2-Range-Creating-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.3. Creating a Range</h2><p>A Range is created by calling the <code>createRange()</code> method on the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-DocumentRange-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>DocumentRange</code></a> interface. This interface can be obtained from the object implementing the <code>Document</code> interface using binding-specific casting methods.</p><div class="eg"><pre style="margin-left: 2em;"> interface DocumentRange{Range createRange();}</pre></div><p>The initial state of the Range returned from this method is such that both of its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s are positioned at the beginning of the corresponding Document, before any content. In other words, the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of each <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> is the Document node and the offset within that node is 0.</p><p>Like some objects created using methods in the Document interface (such as Nodes and DocumentFragments), Ranges created via a particular document instance can select only content associated with that Document, or with DocumentFragments and Attrs for which that Document is the <code>ownerDocument</code>. Such Ranges, then, can not be used with other Document instances.</p></div><div class="div2"><a id="Level-2-Range-Changing" name="Level-2-Range-Changing"></a><h2 id="Level-2-Range-Changing-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.4. Changing a Range's Position</h2><p>A Range's position can be specified by setting the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> and <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of each boundary-point with the <code>setStart</code> and <code>setEnd</code> methods.</p><div class="eg"><pre style="margin-left: 2em;"> void setStart(in Node parent, in long offset) raises(RangeException);void setEnd(in Node parent, in long offset) raises(RangeException);</pre></div><p>If one boundary-point of a Range is set to have a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a> other than the current one for the Range, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to the new position. This enforces the restriction that both boundary-points of a Range must have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a>.</p><p>The start position of a Range is guaranteed to never be after the end position. To enforce this restriction, if the start is set to be at a position after the end, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to that position. Similarly, if the end is set to be at a position before the start, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to that position.</p><p>It is also possible to set a Range's position relative to nodes in the tree:</p><div class="eg"><pre style="margin-left: 2em;"> void setStartBefore(in Node node);raises(RangeException);void setStartAfter(in Node node);raises(RangeException);void setEndBefore(in Node node);raises(RangeException);void setEndAfter(in Node node);raises(RangeException);</pre></div><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-parent" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>parent</em></a> of the node becomes the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> and the Range is subject to the same restrictions as given above in the description of <code>setStart()</code>and <code>setEnd()</code>.</p><p>A Range can be <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to either boundary-point:</p><div class="eg"><pre style="margin-left: 2em;"> void collapse(in boolean toStart);</pre></div><p>Passing <code>TRUE</code> as the parameter <code>toStart</code> will <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapse</em></a> the Range to its start, <code>FALSE</code> to its end.</p><p>Testing whether a Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> can be done by examining the <code>collapsed</code> attribute:</p><div class="eg"><pre style="margin-left: 2em;"> readonly attribute boolean collapsed;</pre></div><p>The following methods can be used to make a Range select the contents of a node or the node itself.</p><div class="eg"><pre style="margin-left: 2em;"> void selectNode(in Node n);void selectNodeContents(in Node n);</pre></div><p>The following examples demonstrate the operation of the methods <code>selectNode</code> and <code>selectNodeContents</code>:</p><div class="eg"><pre style="margin-left: 2em;">Before: <b>^</b><BAR><FOO>A<MOO>B</MOO>C</FOO></BAR>After Range.selectNodeContents(FOO): <BAR><FOO><b>A<MOO>B</MOO>C</b></FOO></BAR>(In this case, FOO is the parent of both boundary-points)After Range.selectNode(FOO):<BAR><b><FOO>A<MOO>B</MOO>C</FOO></b></BAR></pre></div></div><div class="div2"><a id="Level-2-Range-Comparing" name="Level-2-Range-Comparing"></a><h2 id="Level-2-Range-Comparing-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.5. Comparing Range Boundary-Points</h2><p>It is possible to compare two Ranges by comparing their boundary-points:</p><div class="eg"><pre style="margin-left: 2em;"> short compareBoundaryPoints(in CompareHow how, in Range sourceRange) raises(RangeException);</pre></div><p>where <code>CompareHow</code> is one of four values: <code>START_TO_START</code>, <code>START_TO_END</code>, <code>END_TO_END</code> and <code>END_TO_START</code>. The return value is -1, 0 or 1 depending on whether the corresponding boundary-point of the Range is before, equal to, or after the corresponding boundary-point of <code>sourceRange</code>. An exception is thrown if the two Ranges have different <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a>s.</p><p>The result of comparing two boundary-points (or positions) is specified below. An informal but not always correct specification is that an boundary-point is before, equal to, or after another if it corresponds to a location in a text representation before, equal to, or after the other's corresponding location.</p><p><a id="td-comparison" name="td-comparison"></a>Let A and B be two boundary-points or positions. Then one of the following holds: A is <i>before</i> B, A is <i>equal to</i> B, or A is <i>after</i> B. Which one holds is specified in the following by examining four cases:</p><p>In the first case the boundary-points have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>. A is <i>before</i> B if its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is less than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B, A is <i>equal to</i> B if its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is equal to the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B, and A is <i>after</i> B if its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is greater than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B.</p><p>In the second case a child node C of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of A is an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of B. In this case, A is <i>before</i> B if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of A is less than or equal to the index of the child node C and A is <i>after</i>B otherwise.</p><p>In the third case a child node C of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of B is an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of A. In this case, A is <i>before</i> B if the index of the child node C is less than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B and A is <i>after</i> B otherwise.</p><p>In the fourth case, none of three other cases hold: the containers of A and B are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-sibling" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>siblings</em></a> or <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-descendant" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>descendants</em></a> of sibling nodes. In this case, A is <i>before</i> B if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of A is before the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of B in a pre-order traversal of the Ranges' <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> and A is <i>after</i> B otherwise.</p><p>Note that because the same location in a text representation of the document can correspond to two different positions in the DOM tree, it is possible for two boundary-points to not compare equal even though they would be equal in the text representation. For this reason, the informal definition above can sometimes be incorrect.</p></div><div class="div2"><a id="Level-2-Range-Deleting-Content" name="Level-2-Range-Deleting-Content"></a><h2 id="Level-2-Range-Deleting-Content-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.6. Deleting Content with a Range</h2><p>One can delete the contents selected by a Range with:</p><div class="eg"><pre style="margin-left: 2em;"> void deleteContents();</pre></div><p><code>deleteContents()</code> deletes all nodes and characters selected by the Range. All other nodes and characters remain in the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> of the Range. Some examples of this deletion operation are:</p><div class="eg"><pre style="margin-left: 2em;">(1) <FOO>A<b>B<MOO>CD</MOO></b>CD</FOO>--><FOO>A<b>^</b>CD</FOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(2) <FOO>A<MOO>B<b>C</MOO>D</b>E</FOO>--><FOO>A<MOO>B</MOO><b>^</b>E</FOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(3) <FOO>X<b>Y<BAR>Z</b>W</BAR>Q</FOO>--><FOO>X<b>^</b><BAR>W</BAR>Q</FOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(4) <FOO><BAR1>A<b>B</BAR1><BAR2/><BAR3>C</b>D</BAR3></FOO>--><FOO><BAR1>A</BAR1><b>^</b><BAR3>D</BAR3></pre></div><p>After <code>deleteContents()</code> is invoked on a Range, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a>. If no node was <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range, then it is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to its original start point, as in example (1). If a node was <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range and was an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the start of the Range and no <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-ancestor" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor</em></a> of the node satisfies these two conditions, then the Range is collapsed to the position immediately after the node, as in examples (2) and (4). If a node was <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range and was an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the end of the Range and no ancestor of the node satisfies these two conditions, then the Range is collapsed to the position immediately before the node, as in examples (3) and (4).</p><p>Note that if deletion of a Range leaves adjacent Text nodes, they are not automatically merged, and empty Text nodes are not automatically removed. Two Text nodes should be joined only if each is the container of one of the boundary-points of a Range whose contents are deleted. To merge adjacent Text nodes, or remove empty text nodes, the <code>normalize()</code> method on the <code>Node</code>interface should be used.</p></div><div class="div2"><a id="Level-2-Range-Extracting" name="Level-2-Range-Extracting"></a><h2 id="Level-2-Range-Extracting-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.7. Extracting Content</h2><p>If the contents of a Range need to be extracted rather than deleted, the following method may be used:</p><div class="eg"><pre style="margin-left: 2em;"> DocumentFragment extractContents();</pre></div><p>The <code>extractContents()</code> method removes nodes from the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> similarly to the <code>deleteContents()</code> method. In addition, it places the deleted contents in a new <code>DocumentFragment</code>. The following examples illustrate the contents of the returned DocumentFragment:</p><div class="eg"><pre style="margin-left: 2em;">(1) <FOO>A<b>B<MOO>CD</MOO></b>CD</FOO>-->B<MOO>CD</MOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(2) <FOO>A<MOO>B<b>C</MOO>D</b>E</FOO>--><MOO>C<MOO>D</pre></div><div class="eg"><pre style="margin-left: 2em;">(3) <FOO>X<b>Y<BAR>Z</b>W</BAR>Q</FOO>-->Y<BAR>Z</BAR></pre></div><div class="eg"><pre style="margin-left: 2em;">(4)<FOO><BAR1>A<b>B</BAR1><BAR2/><BAR3>C</b>D</BAR3></FOO>--><BAR1>B</BAR1><BAR2/><BAR3>C</BAR3></pre></div><p>It is important to note that nodes that are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range are cloned. Since part of such a node's contents must remain in the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> and part of the contents must be moved to the new DocumentFragment, a clone of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> node is included in the new DocumentFragment. Note that cloning does not take place for <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selected</em></a> elements;these nodes are moved to the new DocumentFragment.</p></div><div class="div2"><a id="Level-2-Range-Cloning" name="Level-2-Range-Cloning"></a><h2 id="Level-2-Range-Cloning-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.8. Cloning Content</h2><p>The contents of a Range may be duplicated using the following method:</p><div class="eg"><pre style="margin-left: 2em;"> DocumentFragment cloneContents();</pre></div><p>This method returns a <code>DocumentFragment</code> that is similar to the one returned by the method <code>extractContents()</code>. However, in this case, the original nodes and character data in the Range are not removed from the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a>. Instead, all of the nodes and text content within the returned <code>DocumentFragment</code> are cloned.</p></div><div class="div2"><a id="Level-2-Range-Inserting" name="Level-2-Range-Inserting"></a><h2 id="Level-2-Range-Inserting-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.9. Inserting Content</h2><p>A node may be inserted into a Range using the following method:</p><div class="eg"><pre style="margin-left: 2em;"> void insertNode(in Node n) raises(RangeException);</pre></div><p>The <code>insertNode()</code> method inserts the specified node into the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a>. The node is inserted at the start <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the Range, without modifying it.</p><p>If the start boundary point of the Range is in a <code>Text</code> node, the <code>insertNode</code> operation splits the <code>Text</code> node at the boundary point. If the node to be inserted is also a <code>Text</code> node, the resulting adjacent<code>Text</code> nodes are not normalized automatically;this operation is left to the application.</p><p>The Node passed into this method can be a <code>DocumentFragment</code>. In that case, the contents of the <code>DocumentFragment</code> are inserted at the start <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the Range, but the <code>DocumentFragment</code>itself is not. Note that if the Node represents the root of a sub-tree, the entire sub-tree is inserted.</p><p>The same rules that apply to the <code>insertBefore()</code> method on the Node interface apply here. Specifically, the Node passed in, if it already has a parent, will be removed from its existing position.</p></div><div class="div2"><a id="Level-2-Range-Surrounding" name="Level-2-Range-Surrounding"></a><h2 id="Level-2-Range-Surrounding-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.10. Surrounding Content</h2><p>The insertion of a single node to subsume the content selected by a Range can be performed with:</p><div class="eg"><pre style="margin-left: 2em;"> void surroundContents(in Node newParent);</pre></div><p>The <code>surroundContents()</code> method causes all of the content selected by the Range to be rooted by the specified node. The nodes may not be Attr, Entity, DocumentType, Notation, Document, or DocumentFragment nodes. Calling <code>surroundContents()</code> with the Element node FOO in the following examples yields:</p><div class="eg"><pre style="margin-left: 2em;"> Before: <BAR>A<b>B<MOO>C</MOO>D</b>E</BAR>After surroundContents(FOO):<BAR>A<b><FOO>B<MOO>C</MOO>D</FOO></b>E</BAR></pre></div><p>Another way of describing the effect of this method on the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> is to decompose it in terms of other operations:</p><ol><li>Remove the contents selected by the Range with a call to <code>extractContents()</code>.</li><li>Insert the node <code>newParent</code> where the Range is collapsed (after the extraction) with <code>insertNode().</code></li><li>Insert the entire contents of the extracted DocumentFragment into <code>newParent</code>. Specifically, invoke the <code>appendChild()</code> on <code>newParent</code> passing in the DocumentFragment returned as a result of the call to <code>extractContents()</code></li><li>Select <code>newParent</code> and all of its contents with <code>selectNode()</code>.</li></ol><p>The <code>surroundContents()</code> method raises an exception if the Range <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selects</em></a> a non-Text node. An example of a Range for which <code>surroundContents()</code>raises an exception is:</p><div class="eg"><pre style="margin-left: 2em;"> <FOO>A<b>B<BAR>C</b>D</BAR>E</FOO></pre></div><p>If the node <code>newParent</code> has any children, those children are removed before its insertion. Also, if the node <code>newParent</code> already has a parent, it is removed from the original parent's <code>childNodes</code> list.</p></div><div class="div2"><a id="Level-2-Range-Misc" name="Level-2-Range-Misc"></a><h2 id="Level-2-Range-Misc-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.11. Miscellaneous Members</h2><p>One can clone a Range:</p><div class="eg"><pre style="margin-left: 2em;"> Range cloneRange();</pre></div><p>This creates a new Range which selects exactly the same content as that selected by the Range on which the method <code>cloneRange</code> was invoked. No content is affected by this operation.</p><p>Because the boundary-points of a Range do not necessarily have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>s, use:</p><div class="eg"><pre style="margin-left: 2em;"> readonly attribute Node commonAncestorContainer;</pre></div><p>to get the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of both boundary-points that is furthest down from the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a></p><p>One can get a copy of all the character data selected or partially selected by a Range with:</p><div class="eg"><pre style="margin-left: 2em;"> DOMString toString();</pre></div><p>This does nothing more than simply concatenate all the character data selected by the Range. This includes character data in both <code>Text</code> and <code>CDATASection</code> nodes.</p></div><div class="div2"><a id="Level-2-Range-Mutation" name="Level-2-Range-Mutation"></a><h2 id="Level-2-Range-Mutation-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.12. Range modification under document mutation</h2><p>As a document is modified, the Ranges within the document need to be updated. For example, if one boundary-point of a Range is within a node and that node is removed from the document, then the Range would be invalid unless it is fixed up in some way. This section describes how Ranges are modified under document mutations so that they remain valid.</p><p>There are two general principles which apply to Ranges under document mutation: The first is that all Ranges in a document will remain valid after any mutation operation and the second is that, as much as possible, all Ranges will select the same portion of the document after any mutation operation.</p><p>Any mutation of the document tree which affect Ranges can be considered to be a combination of basic deletion and insertion operations. In fact, it can be convenient to think of those operations as being accomplished using the <code>deleteContents()</code> and <code>insertNode()</code> Range methods and, in the case of Text mutations, the <code>splitText()</code> and <code>normalize()</code> methods.</p><div class="div3"><a id="Level-2-Range-Insertions" name="Level-2-Range-Insertions"></a><h3 id="Level-2-Range-Insertions-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.12.1. Insertions</h3><p>An insertion occurs at a single point, the insertion point, in the document. For any Range in the document tree, consider each boundary-point. The only case in which the boundary-point will be changed after the insertion is when the boundary-point and the insertion point have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the insertion point is strictly less than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the Range's boundary-point. In that case the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the Range's boundary-point will be increased so that it is between the same nodes or characters as it was before the insertion.</p><p>Note that when content is inserted at a boundary-point, it is ambiguous as to where the boundary-point should be repositioned if its relative position is to be maintained. There are two possibilities: at the start or at the end of the newly inserted content. We have chosen that in this case neither the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> nor <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the boundary-point is changed. As a result, the boundary-point will be positioned at the start of the newly inserted content.</p><p><em>Examples:</em></p><p>Suppose the Range selects the following:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd efgh X<b>Y blah i</b>jkl</P></pre></div><p>Consider the insertion of the text "<i>inserted text</i>" at the following positions:</p><div class="eg"><pre style="margin-left: 2em;">1. Before the 'X':<P>Abcd efgh <i>inserted text</i>X<b>Y blah i</b>jkl</P>2. After the 'X':<P>Abcd efgh X<b><i>inserted text</i>Y blah i</b>jkl</P>3. After the 'Y':<P>Abcd efgh X<b>Y<i>inserted text</i> blah i</b>jkl</P>4. After the 'h' in "Y blah":<P>Abcd efgh X<b>Y blah<i>inserted text</i> i</b>jkl</P></pre></div></div><div class="div3"><a id="Level-2-Range-Deletions" name="Level-2-Range-Deletions"></a><h3 id="Level-2-Range-Deletions-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.12.2. Deletions</h3><p>Any deletion from the document tree can be considered as a sequence of <code>deleteContents()</code> operations applied to a minimal set of disjoint Ranges. To specify how a Range is modified under deletions we need only consider what happens to a Range under a single <code>deleteContents()</code>operation of another Range. And, in fact, we need only consider what happens to a single boundary-point of the Range since both boundary-points are modified using the same algorithm.</p><p>If a boundary-point of the original Range is within the content being deleted, then after the deletion it will be at the same position as the resulting boundary-point of the (now <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a>) Range used to delete the contents.</p><p>If a boundary-point is after the content being deleted then it is not affected by the deletion unless its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is also the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of one of the boundary-points of the Range being deleted. If there is such a common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>, then the index of the boundary-point is modified so that the boundary-point maintains its position relative to the content of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>.</p><p>If a boundary-point is before the content being deleted then it is not affected by the deletion at all.</p><p><em>Examples:</em></p><p>In these examples, the Range on which <code>deleteContents()</code>is invoked is indicated by the underline.</p><p><em>Example 1.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <u>efgh T</u><b><u>he</u> Range i</b>jkl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <b>Range i</b>jkl</P></pre></div><p><em>Example 2.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><p>Abcd <u>efgh T<b>he Range i</b>j</u>kl</p></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><p>Abcd <b>^</b>kl</p></pre></div><p><em>Example 3.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>ABCD <u>efgh T</u><b><u>he <EM>R</u>ange</b></EM>ijkl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>ABCD <EM><b>ange</b></EM>ijkl</P></pre></div><p>In this example, the container of the start boundary-point after the deletion is the Text node holding the string "ange".</p><p><em>Example 4.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <u>efgh T</u><b>he Range i</b>jkl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <b>he Range i</b>jkl</P></pre></div><p><em>Example 5.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <u><EM>efgh T<b>he Range i</b>j</EM></u>kl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <b>^</b>kl</P></pre></div></div></div><div class="div2"><a id="Level-2-Range-Interface" name="Level-2-Range-Interface"></a><h2 id="Level-2-Range-Interface-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.13. Formal Description of the Range Interface</h2><p>To summarize, the complete, formal description of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a> interface is given below:</p><dl ><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Interface <i><a id="Level-2-Range-idl" name="Level-2-Range-idl">Range</a></i></b> (introduced in <b class="since">DOM Level 2</b>)</dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><br><b>IDL Definition</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="idl-code" style="font-family: monospace;border-top-width: 1px;border-right-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-color: black;border-right-color: black;border-bottom-color: black;border-left-color: black;border-image: initial;white-space: pre;background-color: rgb(223, 223, 223);"><pre style="margin-left: 2em;">// Introduced in DOM Level 2:interface Range{readonly attribute Node startContainer;// raises(DOMException) on retrieval readonly attribute long startOffset;// raises(DOMException) on retrieval readonly attribute Node endContainer;// raises(DOMException) on retrieval readonly attribute long endOffset;// raises(DOMException) on retrieval readonly attribute boolean collapsed;// raises(DOMException) on retrieval readonly attribute Node commonAncestorContainer;// raises(DOMException) on retrieval void setStart(in Node refNode, in long offset) raises(RangeException, DOMException);void setEnd(in Node refNode, in long offset) raises(RangeException, DOMException);void setStartBefore(in Node refNode) raises(RangeException, DOMException);void setStartAfter(in Node refNode) raises(RangeException, DOMException);void setEndBefore(in Node refNode) raises(RangeException, DOMException);void setEndAfter(in Node refNode) raises(RangeException, DOMException);void collapse(in boolean toStart) raises(DOMException);void selectNode(in Node refNode) raises(RangeException, DOMException);void selectNodeContents(in Node refNode) raises(RangeException, DOMException);// CompareHow const unsigned short START_TO_START=0;const unsigned short START_TO_END=1;const unsigned short END_TO_END=2;const unsigned short END_TO_START=3;short compareBoundaryPoints(in unsigned short how, in Range sourceRange) raises(DOMException);void deleteContents() raises(DOMException);DocumentFragment extractContents() raises(DOMException);DocumentFragment cloneContents() raises(DOMException);void insertNode(in Node newNode) raises(DOMException, RangeException);void surroundContents(in Node newParent) raises(DOMException, RangeException);Range cloneRange() raises(DOMException);DOMString toString() raises(DOMException);void detach() raises(DOMException);};</pre></div><br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Definition group <i><a id="Level2-Range-compareHow" name="Level2-Range-compareHow">CompareHow</a></i></b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><p>Passed as a parameter to the <code>compareBoundaryPoints</code> method.</p><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Defined Constants</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">END_TO_END</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare end boundary-point of <code>sourceRange</code> to end boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">END_TO_START</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare end boundary-point of <code>sourceRange</code> to start boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">START_TO_END</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare start boundary-point of <code>sourceRange</code> to end boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">START_TO_START</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare start boundary-point of <code>sourceRange</code> to start boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd></dl></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Attributes</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-collapsed" name="Level-2-Range-attr-collapsed">collapsed</a></code> of type <code>boolean</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">TRUE if the Range is collapsed<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-commonParent" name="Level-2-Range-attr-commonParent">commonAncestorContainer</a></code> of type <code>Node</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-deepest" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>deepest</em></a> common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the Range's two boundary-points.<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-endParent" name="Level-2-Range-attr-endParent">endContainer</a></code> of type <code>Node</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Node within which the Range ends<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-endOffset" name="Level-2-Range-attr-endOffset">endOffset</a></code> of type <code>long</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Offset within the ending node of the Range.<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-startParent" name="Level-2-Range-attr-startParent">startContainer</a></code> of type <code>Node</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Node within which the Range begins<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-startOffset" name="Level-2-Range-attr-startOffset">startOffset</a></code> of type <code>long</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Offset within the starting node of the Range.<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Methods</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-cloneContents" name="Level2-Range-method-cloneContents">cloneContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Duplicates the contents of a Range<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>DocumentFragment</code></p></td><td><p>A DocumentFragment that contains content equivalent to this Range.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be extracted into the new DocumentFragment.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-clone" name="Level2-Range-method-clone">cloneRange</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Produces a new Range whose boundary-points are equal to the boundary-points of the Range.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a></p></td><td><p>The duplicated Range.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-collapse" name="Level2-Range-method-collapse">collapse</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Collapse a Range onto one of its boundary-points<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">toStart</code> of type <code>boolean</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">If TRUE, collapses the Range onto its start;if FALSE, collapses it onto its end.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-compareBoundaryPoints" name="Level2-Range-method-compareBoundaryPoints">compareBoundaryPoints</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Compare the boundary-points of two Ranges in a document.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">how</code> of type <code>unsigned short</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">A code representing the type of comparison, as defined above.<br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">sourceRange</code> of type <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>Range</code> on which this current <code>Range</code> is compared to.<br></dd></dl></div></div><div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>short</code></p></td><td><p>-1, 0 or 1 depending on whether the corresponding boundary-point of the Range is respectively before, equal to, or after the corresponding boundary-point of<code>sourceRange</code>.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the same Document or DocumentFragment.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-deleteContents" name="Level2-Range-method-deleteContents">deleteContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Removes the contents of a Range from the containing document or document fragment without returning a reference to the removed content.<div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the content of the Range is read-only or any of the nodes that contain any of the content of the Range are read-only.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-detach" name="Level2-Range-method-detach">detach</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Called to indicate that the Range is no longer in use and that the implementation may relinquish any resources associated with this Range. Subsequent calls to any methods or attribute getters on this Range will result in a <code>DOMException</code> being thrown with an error code of <code>INVALID_STATE_ERR</code>.<div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-extractContents" name="Level2-Range-method-extractContents">extractContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Moves the contents of a Range from the containing document or document fragment to a new DocumentFragment.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>DocumentFragment</code></p></td><td><p>A DocumentFragment containing the extracted contents.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the content of the Range is read-only or any of the nodes which contain any of the content of the Range are read-only.</p><p>HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be extracted into the new DocumentFragment.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-insertNode" name="Level2-Range-method-insertNode">insertNode</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Inserts a node into the Document or DocumentFragment at the start of the Range. If the container is a Text node, this will be split at the start of the Range (as if the Text node's splitText method was performed at the insertion point) and the insertion will occur between the two resulting Text nodes. Adjacent Text nodes will not be automatically merged. If the node to be inserted is a DocumentFragment node, the children will be inserted rather than the DocumentFragment node itself.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">newNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The node to insert at the start of the Range<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the start of the Range is read-only.</p><p>WRONG_DOCUMENT_ERR: Raised if <code>newNode</code> and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range were not created from the same document.</p><p>HIERARCHY_REQUEST_ERR: Raised if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range is of a type that does not allow children of the type of <code>newNode</code> or if <code>newNode</code>is an ancestor of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>newNode</code> is an Attr, Entity, Notation, or Document node.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-selectNode" name="Level2-Range-method-selectNode">selectNode</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Select a node and its contents<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The node to select.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code>refNode</code> is an Entity, Notation or DocumentType node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-selectNodeContents" name="Level2-Range-method-selectNodeContents">selectNodeContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Select the contents within a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Node to select from<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code> or an ancestor of <code>refNode</code> is an Entity, Notation or DocumentType node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setEnd" name="Level2-Range-method-setEnd">setEnd</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the attributes describing the end of a Range.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>refNode</code> value. This parameter must be different from <code>null</code>.<br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">offset</code> of type <code>long</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>endOffset</code> value.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code> or an ancestor of <code>refNode</code> is an Entity, Notation, or DocumentType node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INDEX_SIZE_ERR: Raised if <code>offset</code> is negative or greater than the number of child units in <code>refNode</code>. Child units are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit units</em></a> if <code>refNode</code> is a type of CharacterData node (e.g., a Text or Comment node) or a ProcessingInstruction node. Child units are Nodes in all other cases.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setEndAfter" name="Level2-Range-method-setEndAfter">setEndAfter</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the end of a Range to be after a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range ends after <code>refNode</code>.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setEndBefore" name="Level2-Range-method-setEndBefore">setEndBefore</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the end position to be before a node.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range ends before <code>refNode</code><br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document, or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setStart" name="Level2-Range-method-setStart">setStart</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the attributes describing the start of the Range.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>refNode</code> value. This parameter must be different from <code>null</code>.<br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">offset</code> of type <code>long</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>startOffset</code> value.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code> or an ancestor of <code>refNode</code> is an Entity, Notation, or DocumentType node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INDEX_SIZE_ERR: Raised if <code>offset</code> is negative or greater than the number of child units in <code>refNode</code>. Child units are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit units</em></a> if <code>refNode</code> is a type of CharacterData node (e.g., a Text or Comment node) or a ProcessingInstruction node. Child units are Nodes in all other cases.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setStartAfter" name="Level2-Range-method-setStartAfter">setStartAfter</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the start position to be after a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range starts after <code>refNode</code><br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document, or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-setStartBefore" name="Level2-Range-setStartBefore">setStartBefore</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the start position to be before a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range starts before <code>refNode</code><br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document, or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-surroundContents" name="Level2-Range-method-surroundContents">surroundContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Reparents the contents of the Range to the given node and inserts the node at the position of the start of the Range.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">newParent</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The node to surround the contents with.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of either boundary-point of the Range is read-only.</p><p>WRONG_DOCUMENT_ERR: Raised if <code>newParent</code> and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range were not created from the same document.</p><p>HIERARCHY_REQUEST_ERR: Raised if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range is of a type that does not allow children of the type of <code>newParent</code> or if<code>newParent</code> is an ancestor of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> or if <code>node</code> would end up with a child node of a type not allowed by the type of <code>node</code>.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>BAD_BOUNDARYPOINTS_ERR: Raised if the Range <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selects</em></a> a non-text node.</p><p>INVALID_NODE_TYPE_ERR: Raised if <code>node</code> is an Attr, Entity, DocumentType, Notation, Document, or DocumentFragment node.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-toString" name="Level2-Range-method-toString">toString</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Returns the contents of a Range as a string. This string contains only the data characters, not any markup.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMString</code></p></td><td><p>The contents of the Range.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd></dl></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Interface <i><a id="Level-2-DocumentRange-idl" name="Level-2-DocumentRange-idl">DocumentRange</a></i></b> (introduced in <b class="since">DOM Level 2</b>)</dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><br><b>IDL Definition</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="idl-code" style="font-family: monospace;border-top-width: 1px;border-right-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-color: black;border-right-color: black;border-bottom-color: black;border-left-color: black;border-image: initial;white-space: pre;background-color: rgb(223, 223, 223);"><pre style="margin-left: 2em;">// Introduced in DOM Level 2:interface DocumentRange{Range createRange();};</pre></div><br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Methods</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-DocumentRange-method-createRange" name="Level2-DocumentRange-method-createRange">createRange</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">This interface can be obtained from the object implementing the <code>Document</code> interface using binding-specific casting methods.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a></p></td><td><p>The initial state of the Range returned from this method is such that both of its boundary-points are positioned at the beginning of the corresponding Document, before any content. The Range returned can only be used to select content associated with this Document, or with DocumentFragments and Attrs for which this Document is the <code>ownerDocument</code>.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div><div><b>No Exceptions</b></div></div></dd></dl></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Exception <i><a id="RangeException" name="RangeException">RangeException</a></i></b> introduced in <b class="version">DOM Level 2</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><p>Range operations may throw a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a> as specified in their method descriptions.</p><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><br><b>IDL Definition</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="idl-code" style="font-family: monospace;border-top-width: 1px;border-right-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-color: black;border-right-color: black;border-bottom-color: black;border-left-color: black;border-image: initial;white-space: pre;background-color: rgb(223, 223, 223);"><pre style="margin-left: 2em;">// Introduced in DOM Level 2:exception RangeException{unsigned short code;};// RangeExceptionCodeconst unsigned short BAD_BOUNDARYPOINTS_ERR=1;const unsigned short INVALID_NODE_TYPE_ERR=2;</pre></div><br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Definition group <i><a id="RangeExceptionCode" name="RangeExceptionCode">RangeExceptionCode</a></i></b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><p>An integer indicating the type of error generated.</p><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Defined Constants</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">BAD_BOUNDARYPOINTS_ERR</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">If the boundary-points of a Range do not meet specific requirements.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">INVALID_NODE_TYPE_ERR</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">If the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of an boundary-point of a Range is being set to either a node of an invalid type or a node with an ancestor of an invalid type.</dd></dl></dd></dl></dd></dl></dd></dl></div></div><div class="navbar" align="center" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;"><hr title="Navigation area separator"><a accesskey="p" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">previous</a>   <a accesskey="n" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/idl-definitions.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">next</a>   <a accesskey="c" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/Overview.html#contents" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">contents</a>   <a accesskey="i" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/def-index.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">index</a></div></p><dl></dl>
291 </textarea>
292
293 <h2>Deeply nested divs</h2>
294 <textarea name="editor4">
295 <p> </p><h1 id="mainHeader" style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; font-weight: normal; font-size: 26px; color: rgb(7, 130, 193); font-family: Arial, Helvetica, sans-serif; background-color: rgb(226, 226, 226); ">Jobs</h1><div id="node-438" class="node node-type-page" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 18px; color: rgb(85, 85, 85); font-family: Arial, Helvetica, sans-serif; background-color: rgb(226, 226, 226); "><div class="node-inner" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><div class="meta" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "> </div><div class="content" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><div class="contentBox" style="margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; padding-top: 15px; padding-right: 15px; padding-bottom: 1px; padding-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; background-color: rgb(239, 239, 239); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(226, 226, 226); border-right-color: rgb(226, 226, 226); border-bottom-color: rgb(226, 226, 226); border-left-color: rgb(226, 226, 226); position: relative; "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">CKSource is a successful company with thousands of customers all around the world, including top names like IBM and Oracle. Our company is growing fast, with impressive sales results. This strong growth expands our range of opportunities, followed by the growth of our team. Take this chance and&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">join us!</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Working in a&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">successful Open Source project&nbsp;</strong>is certainly a lot of fun. CKEditor is one of the most frequently used text editors out there, and this success means new responsibilities. We are providing a key component for the software that is powering the Web today. It is downloaded daily by thousands of people all around the world and used by hundreds of thousands out there.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We are constantly looking for top-notch, creative, and enthusiastic professionals ready to join our international team.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We offer a work culture where ideas are free to fly and diversity is our everyday life.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">There is no need to relocate. No matter where you are, as long as you love what you do, you are the right person for us!</p><div class="post joboffer" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 0px; padding-bottom: 5px; padding-left: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; border-top-style: solid; border-top-color: rgb(229, 230, 231); " id=""><h2 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; font-size: 15px; color: rgb(0, 0, 0); ">AJD - Advanced JavaScript Developer</h2><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Location:&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Europe and Its Neighbourhood</strong>&nbsp;(from GMT 0 to GMT +2).</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Employment type:&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Full time</strong>.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We are looking for talented people to join our team. Ideal candidates will have:</p><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Several years of experience with professional JavaScript programming, which we consider is;<ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Writing pure, object-oriented JavaScript applications.</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Ability to create complex JavaScript applications based on your own skills only (excluding usage of external libraries such as jQuery, Prototype, Dojo, or MooTools).</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Being aware and able to solving asynchronous issues.</li></ul></li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">In-depth knowledge of core Web standards, like HTML, XML, DOM, and CSS — including their intrinsic implementation differences among browsers (with IE6 also);</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Ability to understand and fix complicated DOM manipulation problems.</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Good (enough) English speaking and writing skills. This is the language used in the company.</li></ul><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">"Wow" candidates will also have (not required though):</p><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with CKEditor or FCKeditor, having possibly collaborated with the project;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with rich text editors;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with HTML5, CSS3 development;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with Test Cases (like YUI Test);</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">A Bachelor's or Master's degree in Computer Science;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Passion for Open Source.</li></ul></div><div class="post" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 0px; padding-bottom: 30px; padding-left: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; border-top-style: solid; border-top-color: rgb(229, 230, 231); " id=""><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; font-size: 14px; ">In return we offer:</h3><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Permanent full time employment contract;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Flexible working hours;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Competitive salary;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Work&nbsp;</strong>from&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">home</strong>&nbsp;(you will forget what a traffic jam is);</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Working with smart and motivated&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">professionals</strong>;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Becoming a&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">part of great team</strong>&nbsp;who delivers worldwide known software.</li></ul><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Let us start talking. Tell us about the projects you have worked on and your role in them; point to your experience and anything you think might make you a perfect candidate. Contact us with your CV at:&nbsp;<a href="" title="jobs at (spam protection) cksource dot com" id="jobmail1" style="color: rgb(24, 157, 225); ">jobs@cksource.com</a>&nbsp;now!</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We are sure you will enjoy it!</p></div><div class="post" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 0px; padding-bottom: 30px; padding-left: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; border-top-style: solid; border-top-color: rgb(229, 230, 231); "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Please note we only accept CV's in English. Your application must include the following note:</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">"I hereby authorize you to process my personal data included in my job application for the needs of the recruitment process (in accordance to the Personal Data Protection Act 29.08.1997 no 133 position 883).”</p></div></div></div></div></div><dl></dl>
296 </textarea>
297
298 <h2>Line custom look</h2>
299 <div id="hood">
300 <h1>
301 <img alt="" src="http://a.cksource.com/c/1/inc/img/demo-little-red.jpg" style="margin-left: 10px; margin-right: 10px; float: left; width: 120px; height: 168px;" />Little Red Riding Hood</h1>
302 <p>
303 &quot;<b>Little Red Riding Hood</b>&quot; is a famous <a href="http://en.wikipedia.org/wiki/Fairy_tale" title="Fairy tale">fairy tale</a> about a young girl&#39;s encounter with a wolf. The story has been changed considerably in its history and subject to numerous modern adaptations and readings.</p>
304 <table align="right" border="1" cellpadding="1" cellspacing="1" style="width: 200px;">
305 <caption>
306 <strong>International Names</strong></caption>
307 <tbody>
308 <tr>
309 <td>
310 Chinese</td>
311 <td>
312 <i>小紅帽</i></td>
313 </tr>
314 <tr>
315 <td>
316 Italian</td>
317 <td>
318 <i>Cappuccetto Rosso</i></td>
319 </tr>
320 <tr>
321 <td>
322 Spanish</td>
323 <td>
324 <i>Caperucita Roja</i></td>
325 </tr>
326 </tbody>
327 </table>
328 <hr>
329 <hr>
330 <p>
331 The version most widely known today is based on the <a href="http://en.wikipedia.org/wiki/Brothers_Grimm" title="Brothers Grimm">Brothers Grimm</a> variant. It is about a girl called Little Red Riding Hood, after the red <a href="http://en.wikipedia.org/wiki/Hood_%28headgear%29" title="Hood (headgear)">hooded</a> <a href="http://en.wikipedia.org/wiki/Cape" title="Cape">cape</a> or <a href="http://en.wikipedia.org/wiki/Cloak" title="Cloak">cloak</a> she wears. The girl walks through the woods to deliver food to her sick grandmother.</p>
332 <p>
333 A wolf wants to eat the girl but is afraid to do so in public. He approaches the girl, and she na&iuml;vely tells him where she is going. He suggests the girl pick some flowers, which she does. In the meantime, he goes to the grandmother&#39;s house and gains entry by pretending to be the girl. He swallows the grandmother whole, and waits for the girl, disguised as the grandmother.</p>
334 <p>
335 When the girl arrives, she notices he looks very strange to be her grandma. In most retellings, this eventually culminates with Little Red Riding Hood saying, &quot;My, what big teeth you have!&quot;<br />
336 To which the wolf replies, &quot;The better to eat you with,&quot; and swallows her whole, too.</p>
337 <p>
338 A <a href="http://en.wikipedia.org/wiki/Hunter" title="Hunter">hunter</a>, however, comes to the rescue and cuts the wolf open. Little Red Riding Hood and her grandmother emerge unharmed. They fill the wolf&#39;s body with heavy stones, which drown him when he falls into a well. Other versions of the story have had the grandmother shut in the closet instead of eaten, and some have Little Red Riding Hood saved by the hunter as the wolf advances on her rather than after she is eaten.</p>
339 <p>
340 The tale makes the clearest contrast between the safe world of the village and the dangers of the <a href="http://en.wikipedia.org/wiki/Enchanted_forest" title="Enchanted forest">forest</a>, conventional antitheses that are essentially medieval, though no written versions are as old as that.</p>
341 </div>
342
343 <h2>Extreme inline editing</h2>
344 <div id="interpret" contenteditable="true" style="left: 123px; outline: 1px solid red; border: 15px solid green; position: relative; top: 30; left: 30px;">
345 <div style="padding: 20px; background: gray; width: 300px" class="1">Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim.</div>
346 <div style="background: violet; padding: 30px;" class="static">
347 Position static
348 <div style="background: green; padding: 30px; border: 14px solid orange">foo</div>
349 </div>
350 <dl class="2">
351 <dt>Key</dt><dd>Value</dd>
352 </dl>
353 <div>Whatever</div>
354 <hr id="hr">
355 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
356 <hr>
357 <hr>
358 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
359 <div style="background: green; padding: 30px; width: 200px">foo</div>
360 </div>
361
362 <h2>Enter mode: BR</h2>
363 <textarea cols="80" id="editor5" name="editor5" rows="10">
364 Foo<br />
365 <hr style="margin: 50px" />
366 <hr style="margin: 50px" />
367 Foo
368 </textarea>
369
370 <div id="dev">
371 <p id="mouseData">
372 <span>Mouse over: <strong id="over"></strong></span>
373 <span style="display: block">Mouse Y-pos.: <span id="my"></span></span>
374 </p>
375 <p id="triggerData">
376 <span id="tr_type"></span>
377 <span id="tr_upper"></span>
378 <span id="tr_lower"></span>
379 <span id="tr_edge"></span>
380 </dl>
381 <p id="timeData">Time: <span id="time"></span></p>
382 <p id="hiddenData">Hidden state: <span id="hid"></span></p>
383 </div>
384 <script>
385
386 'use strict';
387
388 function fixedWidthNumber( text, chars ) {
389 return ( Array( chars ).join( 0 ) + text ).slice( -chars );
390 }
391
392 var DEBUG = {
393 startTimer: function() {
394 DEBUG.timer = new Date().getTime();
395 },
396
397 stopTimer: (function() {
398 var label = CKEDITOR.document.getById( 'time' ),
399 max = 0,
400 count = 0,
401 values = [],
402 mean = 0,
403 time = 0;
404
405 return function() {
406 time = new Date().getTime() - DEBUG.timer;
407 max = Math.max( time, max );
408
409 values.unshift( time );
410 ( 20 in values ) && values.pop();
411 mean = 0;
412
413 for( var i = 0 ; i < values.length ; i++ )
414 mean += values[ i ];
415
416 mean = mean / i;
417
418 label.setText( fixedWidthNumber( time, 3 ) +
419 ' ms, mean: ' + fixedWidthNumber( 0 | mean, 3 ) +
420 ' ms, max: ' + fixedWidthNumber( max, 3 ) +
421 ' ms' )
422 count++;
423 }
424 })(),
425
426 mousePos: (function( y, element )
427 {
428 var my = CKEDITOR.document.getById( 'my' ),
429 over = CKEDITOR.document.getById( 'over' ),
430 name;
431
432 return function( y, element ) {
433 my.setText( y );
434
435 if( element && element.$ && element.type == CKEDITOR.NODE_ELEMENT ) {
436 try {
437 name = element.getName();
438 over.setText( name + '.' + element.getAttribute( 'class' ) );
439 } catch( e ) {}
440 }
441 else
442 over.setText( '-' );
443 }
444 })(),
445
446 showTrigger: (function( trigger )
447 {
448 var tr_type = CKEDITOR.document.getById( 'tr_type' ),
449 tr_upper = CKEDITOR.document.getById( 'tr_upper' ),
450 tr_lower = CKEDITOR.document.getById( 'tr_lower' ),
451 tr_edge = CKEDITOR.document.getById( 'tr_edge' ),
452 tup, tbo, upper, lower;
453
454 return function( trigger ) {
455 tup && tup.removeAttribute('id') && ( tup = null );
456 tbo && tbo.removeAttribute('id') && ( tbo = null );
457
458 if ( !trigger )
459 return tr_type.setText( '-' ) &&
460 tr_upper.setText( '-' ) &&
461 tr_lower.setText( '-' ) &&
462 tr_edge.setText( '-' );
463
464 upper = trigger.upper,
465 lower = trigger.lower;
466
467 tr_type.setText( trigger.type == 2 ? 'EXPAND': 'EDGE' );
468 tr_upper.setText( upper ? upper.getName() + '.' + upper.getAttribute( 'class' ): 'NULL' );
469 tr_lower.setText( lower ? lower.getName() + '.' + lower.getAttribute( 'class' ): 'NULL' );
470 tr_edge.setText( trigger.edge ? [ 'EDGE_TOP', 'EDGE_BOTTOM', 'EDGE_MIDDLE' ][ trigger.edge - 1 ]: 'NULL' );
471
472 upper && ( tup = upper ) && tup.setAttribute( 'id', 'tup' );
473 lower && ( tbo = lower ) && tbo.setAttribute( 'id', 'tbo' );
474 }
475 })(),
476
477 showHidden: (function( state )
478 {
479 var cnt = CKEDITOR.document.getById( 'hid' );
480
481 return function( state ) {
482 cnt[ state ? 'addClass': 'removeClass' ]( 'hl' );
483 cnt.setText( state ? 'enabled': 'disabled' );
484 }
485 })(),
486
487 markElement: function( element ) {
488 if( !isHtml( element ))
489 return;
490
491 DEBUG.marked && DEBUG.marked.setStyles( {
492 'outline': 'none'
493 } );
494
495 DEBUG.marked = element;
496
497 element.setStyles( {
498 'outline': 'red solid 2px'
499 } );
500 },
501
502 // Log functions.
503 log: function() {},
504 logElements: function() {},
505 groupStart: function() {},
506 groupEnd: function() {},
507 logEnd: function() {},
508 logElementsEnd: function() {}
509 };
510
511 var logEnable = {
512 log: function() {
513 var args = [];
514 for( var i = 0; i < arguments.length ; i++ )
515 args.push( arguments[ i ] );
516
517 console.log.apply( console, args );
518 },
519
520 logElements: function( elements, labels, info ) {
521 var log = {},
522 label;
523
524 for ( var i = 0 ; i < elements.length; i++ ) {
525 label = labels ? labels [ i ] : i;
526
527 if( !elements[ i ] ) {
528 log[ label ] = {
529 'name': 'null',
530 'class': 'null'
531 }
532 }
533 else {
534 log[ labels ? labels [ i ]: i ] = {
535 'name': elements[ i ].is ? elements[ i ].getName(): 'null',
536 'class': elements[ i ].is ? elements[ i ].getAttribute( 'class' ): 'null'
537 }
538 }
539 }
540
541 typeof JSON != 'undefined' && DEBUG.log( ( info ? info.toUpperCase() + ' ': '' ) + JSON.stringify( log ) );
542 },
543
544 groupStart: function( label ) {
545 console.group( label );
546 },
547
548 groupEnd: function() {
549 console.groupEnd();
550 },
551
552 logEnd: function() {
553 DEBUG.log.apply( null, arguments );
554 DEBUG.groupEnd();
555 },
556
557 logElementsEnd: function() {
558 DEBUG.logElements.apply( null, arguments );
559 DEBUG.groupEnd();
560 }
561 }
562
563 // Enable console.log debugging with ?debug address parameter.
564 window.location.href.match( /debug$/g ) ? CKEDITOR.tools.extend( DEBUG, logEnable, true ): null;
565
566 // CKEDITOR.addCss('\
567 // #tup { outline: #FEB2B2 solid 2px; box-shadow: 3px 3px 0 #FEB2B2; } \
568 // #tbo { outline: #B2FEB2 solid 2px; box-shadow: 3px 3px 0 #B2FEB2; } \
569 // p { background: pink }\
570 // ');
571
572 CKEDITOR.replace( 'editor1' );
573
574 CKEDITOR.replace( 'editor2', { height: 150 } );
575
576 CKEDITOR.replace( 'editor3', {
577 magicline_everywhere: 1,
578 magicline_holdDistance: .2,
579 language: 'pl'
580 });
581
582 CKEDITOR.replace( 'editor4' );
583
584 CKEDITOR.replace( 'hood', {
585 magicline_color: 'green'
586 });
587
588 CKEDITOR.replace( 'editor5', {
589 enterMode : CKEDITOR.ENTER_BR
590 });
591
592 </script>
593</body>
594</html>
diff --git a/sources/plugins/magicline/images/hidpi/icon-rtl.png b/sources/plugins/magicline/images/hidpi/icon-rtl.png
new file mode 100644
index 0000000..4a8d2bf
--- /dev/null
+++ b/sources/plugins/magicline/images/hidpi/icon-rtl.png
Binary files differ
diff --git a/sources/plugins/magicline/images/hidpi/icon.png b/sources/plugins/magicline/images/hidpi/icon.png
new file mode 100644
index 0000000..b981bb5
--- /dev/null
+++ b/sources/plugins/magicline/images/hidpi/icon.png
Binary files differ
diff --git a/sources/plugins/magicline/images/icon-rtl.png b/sources/plugins/magicline/images/icon-rtl.png
new file mode 100644
index 0000000..55b5b5f
--- /dev/null
+++ b/sources/plugins/magicline/images/icon-rtl.png
Binary files differ
diff --git a/sources/plugins/magicline/images/icon.png b/sources/plugins/magicline/images/icon.png
new file mode 100644
index 0000000..e063433
--- /dev/null
+++ b/sources/plugins/magicline/images/icon.png
Binary files differ
diff --git a/sources/plugins/magicline/lang/af.js b/sources/plugins/magicline/lang/af.js
new file mode 100644
index 0000000..9b9dc2b
--- /dev/null
+++ b/sources/plugins/magicline/lang/af.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'af', {
7 title: 'Voeg paragraaf hier in'
8} );
diff --git a/sources/plugins/magicline/lang/ar.js b/sources/plugins/magicline/lang/ar.js
new file mode 100644
index 0000000..1c411f3
--- /dev/null
+++ b/sources/plugins/magicline/lang/ar.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ar', {
7 title: 'إدراج فقرة هنا'
8} );
diff --git a/sources/plugins/magicline/lang/az.js b/sources/plugins/magicline/lang/az.js
new file mode 100644
index 0000000..02664f1
--- /dev/null
+++ b/sources/plugins/magicline/lang/az.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'az', {
7 title: 'Abzası burada əlavə et'
8} );
diff --git a/sources/plugins/magicline/lang/bg.js b/sources/plugins/magicline/lang/bg.js
new file mode 100644
index 0000000..768af06
--- /dev/null
+++ b/sources/plugins/magicline/lang/bg.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'bg', {
7 title: 'Вмъкнете параграф тук'
8} );
diff --git a/sources/plugins/magicline/lang/ca.js b/sources/plugins/magicline/lang/ca.js
new file mode 100644
index 0000000..dcd9c1a
--- /dev/null
+++ b/sources/plugins/magicline/lang/ca.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ca', {
7 title: 'Insereix el paràgraf aquí'
8} );
diff --git a/sources/plugins/magicline/lang/cs.js b/sources/plugins/magicline/lang/cs.js
new file mode 100644
index 0000000..4705efd
--- /dev/null
+++ b/sources/plugins/magicline/lang/cs.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'cs', {
7 title: 'zde vložit odstavec'
8} );
diff --git a/sources/plugins/magicline/lang/cy.js b/sources/plugins/magicline/lang/cy.js
new file mode 100644
index 0000000..13e1085
--- /dev/null
+++ b/sources/plugins/magicline/lang/cy.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'cy', {
7 title: 'Mewnosod paragraff yma'
8} );
diff --git a/sources/plugins/magicline/lang/da.js b/sources/plugins/magicline/lang/da.js
new file mode 100644
index 0000000..ee4fa17
--- /dev/null
+++ b/sources/plugins/magicline/lang/da.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'da', {
7 title: 'Indsæt afsnit'
8} );
diff --git a/sources/plugins/magicline/lang/de-ch.js b/sources/plugins/magicline/lang/de-ch.js
new file mode 100644
index 0000000..d6bd3b7
--- /dev/null
+++ b/sources/plugins/magicline/lang/de-ch.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'de-ch', {
7 title: 'Absatz hier einfügen'
8} );
diff --git a/sources/plugins/magicline/lang/de.js b/sources/plugins/magicline/lang/de.js
new file mode 100644
index 0000000..189d564
--- /dev/null
+++ b/sources/plugins/magicline/lang/de.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'de', {
7 title: 'Absatz hier einfügen'
8} );
diff --git a/sources/plugins/magicline/lang/el.js b/sources/plugins/magicline/lang/el.js
new file mode 100644
index 0000000..528a554
--- /dev/null
+++ b/sources/plugins/magicline/lang/el.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'el', {
7 title: 'Εισάγετε παράγραφο εδώ'
8} );
diff --git a/sources/plugins/magicline/lang/en-gb.js b/sources/plugins/magicline/lang/en-gb.js
new file mode 100644
index 0000000..e0d3779
--- /dev/null
+++ b/sources/plugins/magicline/lang/en-gb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'en-gb', {
7 title: 'Insert paragraph here'
8} );
diff --git a/sources/plugins/magicline/lang/en.js b/sources/plugins/magicline/lang/en.js
new file mode 100644
index 0000000..37ef2ed
--- /dev/null
+++ b/sources/plugins/magicline/lang/en.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'en', {
7 title: 'Insert paragraph here'
8} );
diff --git a/sources/plugins/magicline/lang/eo.js b/sources/plugins/magicline/lang/eo.js
new file mode 100644
index 0000000..3cf6286
--- /dev/null
+++ b/sources/plugins/magicline/lang/eo.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'eo', {
7 title: 'Enmeti paragrafon ĉi-tien'
8} );
diff --git a/sources/plugins/magicline/lang/es.js b/sources/plugins/magicline/lang/es.js
new file mode 100644
index 0000000..f9a8f52
--- /dev/null
+++ b/sources/plugins/magicline/lang/es.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'es', {
7 title: 'Insertar párrafo aquí'
8} );
diff --git a/sources/plugins/magicline/lang/et.js b/sources/plugins/magicline/lang/et.js
new file mode 100644
index 0000000..9d2fe53
--- /dev/null
+++ b/sources/plugins/magicline/lang/et.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'et', {
7 title: 'Sisesta siia lõigu tekst'
8} );
diff --git a/sources/plugins/magicline/lang/eu.js b/sources/plugins/magicline/lang/eu.js
new file mode 100644
index 0000000..25daf45
--- /dev/null
+++ b/sources/plugins/magicline/lang/eu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'eu', {
7 title: 'Txertatu paragrafoa hemen'
8} );
diff --git a/sources/plugins/magicline/lang/fa.js b/sources/plugins/magicline/lang/fa.js
new file mode 100644
index 0000000..d09ddfc
--- /dev/null
+++ b/sources/plugins/magicline/lang/fa.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fa', {
7 title: 'قرار دادن بند در اینجا'
8} );
diff --git a/sources/plugins/magicline/lang/fi.js b/sources/plugins/magicline/lang/fi.js
new file mode 100644
index 0000000..094bd9d
--- /dev/null
+++ b/sources/plugins/magicline/lang/fi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fi', {
7 title: 'Lisää kappale tähän.'
8} );
diff --git a/sources/plugins/magicline/lang/fr-ca.js b/sources/plugins/magicline/lang/fr-ca.js
new file mode 100644
index 0000000..6319f1c
--- /dev/null
+++ b/sources/plugins/magicline/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fr-ca', {
7 title: 'Insérer le paragraphe ici'
8} );
diff --git a/sources/plugins/magicline/lang/fr.js b/sources/plugins/magicline/lang/fr.js
new file mode 100644
index 0000000..430fc5f
--- /dev/null
+++ b/sources/plugins/magicline/lang/fr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fr', {
7 title: 'Insérer un paragraphe ici'
8} );
diff --git a/sources/plugins/magicline/lang/gl.js b/sources/plugins/magicline/lang/gl.js
new file mode 100644
index 0000000..5aaa968
--- /dev/null
+++ b/sources/plugins/magicline/lang/gl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'gl', {
7 title: 'Inserir aquí o parágrafo'
8} );
diff --git a/sources/plugins/magicline/lang/he.js b/sources/plugins/magicline/lang/he.js
new file mode 100644
index 0000000..9c01d48
--- /dev/null
+++ b/sources/plugins/magicline/lang/he.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'he', {
7 title: 'הכנס פסקה כאן'
8} );
diff --git a/sources/plugins/magicline/lang/hr.js b/sources/plugins/magicline/lang/hr.js
new file mode 100644
index 0000000..1916e65
--- /dev/null
+++ b/sources/plugins/magicline/lang/hr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'hr', {
7 title: 'Ubaci paragraf ovdje'
8} );
diff --git a/sources/plugins/magicline/lang/hu.js b/sources/plugins/magicline/lang/hu.js
new file mode 100644
index 0000000..86650d5
--- /dev/null
+++ b/sources/plugins/magicline/lang/hu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'hu', {
7 title: 'Szúrja be a bekezdést ide'
8} );
diff --git a/sources/plugins/magicline/lang/id.js b/sources/plugins/magicline/lang/id.js
new file mode 100644
index 0000000..3651e37
--- /dev/null
+++ b/sources/plugins/magicline/lang/id.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'id', {
7 title: 'Masukkan paragraf disini'
8} );
diff --git a/sources/plugins/magicline/lang/it.js b/sources/plugins/magicline/lang/it.js
new file mode 100644
index 0000000..9cc27e0
--- /dev/null
+++ b/sources/plugins/magicline/lang/it.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'it', {
7 title: 'Inserisci paragrafo qui'
8} );
diff --git a/sources/plugins/magicline/lang/ja.js b/sources/plugins/magicline/lang/ja.js
new file mode 100644
index 0000000..84d6b74
--- /dev/null
+++ b/sources/plugins/magicline/lang/ja.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ja', {
7 title: 'ここに段落を挿入'
8} );
diff --git a/sources/plugins/magicline/lang/km.js b/sources/plugins/magicline/lang/km.js
new file mode 100644
index 0000000..f670a7e
--- /dev/null
+++ b/sources/plugins/magicline/lang/km.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'km', {
7 title: 'បញ្ចូល​កថាខណ្ឌ​នៅ​ទីនេះ'
8} );
diff --git a/sources/plugins/magicline/lang/ko.js b/sources/plugins/magicline/lang/ko.js
new file mode 100644
index 0000000..0e718f3
--- /dev/null
+++ b/sources/plugins/magicline/lang/ko.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ko', {
7 title: '여기에 단락 삽입'
8} );
diff --git a/sources/plugins/magicline/lang/ku.js b/sources/plugins/magicline/lang/ku.js
new file mode 100644
index 0000000..cc3f3a4
--- /dev/null
+++ b/sources/plugins/magicline/lang/ku.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ku', {
7 title: 'بڕگە لێرە دابنێ'
8} );
diff --git a/sources/plugins/magicline/lang/lv.js b/sources/plugins/magicline/lang/lv.js
new file mode 100644
index 0000000..f96cc44
--- /dev/null
+++ b/sources/plugins/magicline/lang/lv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'lv', {
7 title: 'Ievietot šeit rindkopu'
8} );
diff --git a/sources/plugins/magicline/lang/nb.js b/sources/plugins/magicline/lang/nb.js
new file mode 100644
index 0000000..297f270
--- /dev/null
+++ b/sources/plugins/magicline/lang/nb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'nb', {
7 title: 'Sett inn nytt avsnitt her'
8} );
diff --git a/sources/plugins/magicline/lang/nl.js b/sources/plugins/magicline/lang/nl.js
new file mode 100644
index 0000000..bfe36ff
--- /dev/null
+++ b/sources/plugins/magicline/lang/nl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'nl', {
7 title: 'Hier paragraaf invoeren'
8} );
diff --git a/sources/plugins/magicline/lang/no.js b/sources/plugins/magicline/lang/no.js
new file mode 100644
index 0000000..e78ca76
--- /dev/null
+++ b/sources/plugins/magicline/lang/no.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'no', {
7 title: 'Sett inn nytt avsnitt her'
8} );
diff --git a/sources/plugins/magicline/lang/oc.js b/sources/plugins/magicline/lang/oc.js
new file mode 100644
index 0000000..312f547
--- /dev/null
+++ b/sources/plugins/magicline/lang/oc.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'oc', {
7 title: 'Inserir un paragraf aicí'
8} );
diff --git a/sources/plugins/magicline/lang/pl.js b/sources/plugins/magicline/lang/pl.js
new file mode 100644
index 0000000..324bf1e
--- /dev/null
+++ b/sources/plugins/magicline/lang/pl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'pl', {
7 title: 'Wstaw nowy akapit'
8} );
diff --git a/sources/plugins/magicline/lang/pt-br.js b/sources/plugins/magicline/lang/pt-br.js
new file mode 100644
index 0000000..35f3daa
--- /dev/null
+++ b/sources/plugins/magicline/lang/pt-br.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'pt-br', {
7 title: 'Insera um parágrafo aqui'
8} );
diff --git a/sources/plugins/magicline/lang/pt.js b/sources/plugins/magicline/lang/pt.js
new file mode 100644
index 0000000..c03c48a
--- /dev/null
+++ b/sources/plugins/magicline/lang/pt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'pt', {
7 title: 'Insira aqui o parágrafo'
8} );
diff --git a/sources/plugins/magicline/lang/ru.js b/sources/plugins/magicline/lang/ru.js
new file mode 100644
index 0000000..bc41703
--- /dev/null
+++ b/sources/plugins/magicline/lang/ru.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ru', {
7 title: 'Вставить здесь параграф'
8} );
diff --git a/sources/plugins/magicline/lang/si.js b/sources/plugins/magicline/lang/si.js
new file mode 100644
index 0000000..a5cdbe8
--- /dev/null
+++ b/sources/plugins/magicline/lang/si.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'si', {
7 title: 'චේදය ඇතුලත් කරන්න'
8} );
diff --git a/sources/plugins/magicline/lang/sk.js b/sources/plugins/magicline/lang/sk.js
new file mode 100644
index 0000000..84761b2
--- /dev/null
+++ b/sources/plugins/magicline/lang/sk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sk', {
7 title: 'Odsek vložiť sem'
8} );
diff --git a/sources/plugins/magicline/lang/sl.js b/sources/plugins/magicline/lang/sl.js
new file mode 100644
index 0000000..6d0cf76
--- /dev/null
+++ b/sources/plugins/magicline/lang/sl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sl', {
7 title: 'Vstavite odstavek tukaj'
8} );
diff --git a/sources/plugins/magicline/lang/sq.js b/sources/plugins/magicline/lang/sq.js
new file mode 100644
index 0000000..d405596
--- /dev/null
+++ b/sources/plugins/magicline/lang/sq.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sq', {
7 title: 'Vendos paragraf këtu'
8} );
diff --git a/sources/plugins/magicline/lang/sv.js b/sources/plugins/magicline/lang/sv.js
new file mode 100644
index 0000000..63327fd
--- /dev/null
+++ b/sources/plugins/magicline/lang/sv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sv', {
7 title: 'Infoga paragraf här'
8} );
diff --git a/sources/plugins/magicline/lang/tr.js b/sources/plugins/magicline/lang/tr.js
new file mode 100644
index 0000000..02dd216
--- /dev/null
+++ b/sources/plugins/magicline/lang/tr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'tr', {
7 title: 'Parağrafı buraya ekle'
8} );
diff --git a/sources/plugins/magicline/lang/tt.js b/sources/plugins/magicline/lang/tt.js
new file mode 100644
index 0000000..7de33bf
--- /dev/null
+++ b/sources/plugins/magicline/lang/tt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'tt', {
7 title: 'Бирегә параграф өстәү'
8} );
diff --git a/sources/plugins/magicline/lang/ug.js b/sources/plugins/magicline/lang/ug.js
new file mode 100644
index 0000000..0017fd4
--- /dev/null
+++ b/sources/plugins/magicline/lang/ug.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ug', {
7 title: 'بۇ جايغا ئابزاس قىستۇر'
8} );
diff --git a/sources/plugins/magicline/lang/uk.js b/sources/plugins/magicline/lang/uk.js
new file mode 100644
index 0000000..980f0e0
--- /dev/null
+++ b/sources/plugins/magicline/lang/uk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'uk', {
7 title: 'Вставити абзац'
8} );
diff --git a/sources/plugins/magicline/lang/vi.js b/sources/plugins/magicline/lang/vi.js
new file mode 100644
index 0000000..b302bd0
--- /dev/null
+++ b/sources/plugins/magicline/lang/vi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'vi', {
7 title: 'Chèn đoạn vào đây'
8} );
diff --git a/sources/plugins/magicline/lang/zh-cn.js b/sources/plugins/magicline/lang/zh-cn.js
new file mode 100644
index 0000000..f0a0b3b
--- /dev/null
+++ b/sources/plugins/magicline/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'zh-cn', {
7 title: '在这插入段落'
8} );
diff --git a/sources/plugins/magicline/lang/zh.js b/sources/plugins/magicline/lang/zh.js
new file mode 100644
index 0000000..3ac9f68
--- /dev/null
+++ b/sources/plugins/magicline/lang/zh.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'zh', {
7 title: '在此插入段落'
8} );
diff --git a/sources/plugins/magicline/plugin.js b/sources/plugins/magicline/plugin.js
new file mode 100644
index 0000000..ac4bb78
--- /dev/null
+++ b/sources/plugins/magicline/plugin.js
@@ -0,0 +1,1874 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The [Magic Line](http://ckeditor.com/addon/magicline) plugin that makes it easier to access some document areas that
8 * are difficult to focus.
9 */
10
11'use strict';
12
13( function() {
14 CKEDITOR.plugins.add( 'magicline', {
15 lang: 'af,ar,az,bg,ca,cs,cy,da,de,de-ch,el,en,en-gb,eo,es,et,eu,fa,fi,fr,fr-ca,gl,he,hr,hu,id,it,ja,km,ko,ku,lv,nb,nl,no,oc,pl,pt,pt-br,ru,si,sk,sl,sq,sv,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
16 init: initPlugin
17 } );
18
19 // Activates the box inside of an editor.
20 function initPlugin( editor ) {
21 // Configurables
22 var config = editor.config,
23 triggerOffset = config.magicline_triggerOffset || 30,
24 enterMode = config.enterMode,
25 that = {
26 // Global stuff is being initialized here.
27 editor: editor,
28 enterMode: enterMode,
29 triggerOffset: triggerOffset,
30 holdDistance: 0 | triggerOffset * ( config.magicline_holdDistance || 0.5 ),
31 boxColor: config.magicline_color || '#ff0000',
32 rtl: config.contentsLangDirection == 'rtl',
33 tabuList: [ 'data-cke-hidden-sel' ].concat( config.magicline_tabuList || [] ),
34 triggers: config.magicline_everywhere ? DTD_BLOCK : { table: 1, hr: 1, div: 1, ul: 1, ol: 1, dl: 1, form: 1, blockquote: 1 }
35 },
36 scrollTimeout, checkMouseTimeoutPending, checkMouseTimer;
37
38 // %REMOVE_START%
39 // Internal DEBUG uses tools located in the topmost window.
40
41 // (#9701) Due to security limitations some browsers may throw
42 // errors when accessing window.top object. Do it safely first then.
43 try {
44 that.debug = window.top.DEBUG;
45 }
46 catch ( e ) {}
47
48 that.debug = that.debug || {
49 groupEnd: function() {},
50 groupStart: function() {},
51 log: function() {},
52 logElements: function() {},
53 logElementsEnd: function() {},
54 logEnd: function() {},
55 mousePos: function() {},
56 showHidden: function() {},
57 showTrigger: function() {},
58 startTimer: function() {},
59 stopTimer: function() {}
60 };
61 // %REMOVE_END%
62
63 // Simple irrelevant elements filter.
64 that.isRelevant = function( node ) {
65 return isHtml( node ) && // -> Node must be an existing HTML element.
66 !isLine( that, node ) && // -> Node can be neither the box nor its child.
67 !isFlowBreaker( node ); // -> Node can be neither floated nor positioned nor aligned.
68 };
69
70 editor.on( 'contentDom', addListeners, this );
71
72 function addListeners() {
73 var editable = editor.editable(),
74 doc = editor.document,
75 win = editor.window;
76
77 // Global stuff is being initialized here.
78 extend( that, {
79 editable: editable,
80 inInlineMode: editable.isInline(),
81 doc: doc,
82 win: win,
83 hotNode: null
84 }, true );
85
86 // This is the boundary of the editor. For inline the boundary is editable itself.
87 // For classic (`iframe`-based) editor, the HTML element is a real boundary.
88 that.boundary = that.inInlineMode ? that.editable : that.doc.getDocumentElement();
89
90 // Enabling the box inside of inline editable is pointless.
91 // There's no need to access spaces inside paragraphs, links, spans, etc.
92 if ( editable.is( dtd.$inline ) )
93 return;
94
95 // Handle in-line editing by setting appropriate position.
96 // If current position is static, make it relative and clear top/left coordinates.
97 if ( that.inInlineMode && !isPositioned( editable ) ) {
98 editable.setStyles( {
99 position: 'relative',
100 top: null,
101 left: null
102 } );
103 }
104 // Enable the box. Let it produce children elements, initialize
105 // event handlers and own methods.
106 initLine.call( this, that );
107
108 // Get view dimensions and scroll positions.
109 // At this stage (before any checkMouse call) it is used mostly
110 // by tests. Nevertheless it a crucial thing.
111 updateWindowSize( that );
112
113 // Remove the box before an undo image is created.
114 // This is important. If we didn't do that, the *undo thing* would revert the box into an editor.
115 // Thanks to that, undo doesn't even know about the existence of the box.
116 editable.attachListener( editor, 'beforeUndoImage', function() {
117 that.line.detach();
118 } );
119
120 // Removes the box HTML from editor data string if getData is called.
121 // Thanks to that, an editor never yields data polluted by the box.
122 // Listen with very high priority, so line will be removed before other
123 // listeners will see it.
124 editable.attachListener( editor, 'beforeGetData', function() {
125 // If the box is in editable, remove it.
126 if ( that.line.wrap.getParent() ) {
127 that.line.detach();
128
129 // Restore line in the last listener for 'getData'.
130 editor.once( 'getData', function() {
131 that.line.attach();
132 }, null, null, 1000 );
133 }
134 }, null, null, 0 );
135
136 // Hide the box on mouseout if mouse leaves document.
137 editable.attachListener( that.inInlineMode ? doc : doc.getWindow().getFrame(), 'mouseout', function( event ) {
138 if ( editor.mode != 'wysiwyg' )
139 return;
140
141 // Check for inline-mode editor. If so, check mouse position
142 // and remove the box if mouse outside of an editor.
143 if ( that.inInlineMode ) {
144 var mouse = {
145 x: event.data.$.clientX,
146 y: event.data.$.clientY
147 };
148
149 updateWindowSize( that );
150 updateEditableSize( that, true );
151
152 var size = that.view.editable,
153 scroll = that.view.scroll;
154
155 // If outside of an editor...
156 if ( !inBetween( mouse.x, size.left - scroll.x, size.right - scroll.x ) || !inBetween( mouse.y, size.top - scroll.y, size.bottom - scroll.y ) ) {
157 clearTimeout( checkMouseTimer );
158 checkMouseTimer = null;
159 that.line.detach();
160 }
161 }
162
163 else {
164 clearTimeout( checkMouseTimer );
165 checkMouseTimer = null;
166 that.line.detach();
167 }
168 } );
169
170 // This one deactivates hidden mode of an editor which
171 // prevents the box from being shown.
172 editable.attachListener( editable, 'keyup', function() {
173 that.hiddenMode = 0;
174 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
175 } );
176
177 editable.attachListener( editable, 'keydown', function( event ) {
178 if ( editor.mode != 'wysiwyg' )
179 return;
180
181 var keyStroke = event.data.getKeystroke();
182
183 switch ( keyStroke ) {
184 // Shift pressed
185 case 2228240: // IE
186 case 16:
187 that.hiddenMode = 1;
188 that.line.detach();
189 }
190
191 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
192 } );
193
194 // This method ensures that checkMouse aren't executed
195 // in parallel and no more frequently than specified in timeout function.
196 // In classic (`iframe`-based) editor, document is used as a trigger, to provide magicline
197 // functionality when mouse is below the body (short content, short body).
198 editable.attachListener( that.inInlineMode ? editable : doc, 'mousemove', function( event ) {
199 checkMouseTimeoutPending = true;
200
201 if ( editor.mode != 'wysiwyg' || editor.readOnly || checkMouseTimer )
202 return;
203
204 // IE<9 requires this event-driven object to be created
205 // outside of the setTimeout statement.
206 // Otherwise it loses the event object with its properties.
207 var mouse = {
208 x: event.data.$.clientX,
209 y: event.data.$.clientY
210 };
211
212 checkMouseTimer = setTimeout( function() {
213 checkMouse( mouse );
214 }, 30 ); // balances performance and accessibility
215 } );
216
217 // This one removes box on scroll event.
218 // It is to avoid box displacement.
219 editable.attachListener( win, 'scroll', function() {
220 if ( editor.mode != 'wysiwyg' )
221 return;
222
223 that.line.detach();
224
225 // To figure this out just look at the mouseup
226 // event handler below.
227 if ( env.webkit ) {
228 that.hiddenMode = 1;
229
230 clearTimeout( scrollTimeout );
231 scrollTimeout = setTimeout( function() {
232 // Don't leave hidden mode until mouse remains pressed and
233 // scroll is being used, i.e. when dragging something.
234 if ( !that.mouseDown )
235 that.hiddenMode = 0;
236 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
237 }, 50 );
238
239 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
240 }
241 } );
242
243 // Those event handlers remove the box on mousedown
244 // and don't reveal it until the mouse is released.
245 // It is to prevent box insertion e.g. while scrolling
246 // (w/ scrollbar), selecting and so on.
247 editable.attachListener( env_ie8 ? doc : win, 'mousedown', function() {
248 if ( editor.mode != 'wysiwyg' )
249 return;
250
251 that.line.detach();
252 that.hiddenMode = 1;
253 that.mouseDown = 1;
254
255 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
256 } );
257
258 // Google Chrome doesn't trigger this on the scrollbar (since 2009...)
259 // so it is totally useless to check for scroll finish
260 // see: http://code.google.com/p/chromium/issues/detail?id=14204
261 editable.attachListener( env_ie8 ? doc : win, 'mouseup', function() {
262 that.hiddenMode = 0;
263 that.mouseDown = 0;
264 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
265 } );
266
267 // Editor commands for accessing difficult focus spaces.
268 editor.addCommand( 'accessPreviousSpace', accessFocusSpaceCmd( that ) );
269 editor.addCommand( 'accessNextSpace', accessFocusSpaceCmd( that, true ) );
270
271 editor.setKeystroke( [
272 [ config.magicline_keystrokePrevious, 'accessPreviousSpace' ],
273 [ config.magicline_keystrokeNext, 'accessNextSpace' ]
274 ] );
275
276 // Revert magicline hot node on undo/redo.
277 editor.on( 'loadSnapshot', function() {
278 var elements, element, i;
279
280 for ( var t in { p: 1, br: 1, div: 1 } ) {
281 // document.find is not available in QM (#11149).
282 elements = editor.document.getElementsByTag( t );
283
284 for ( i = elements.count(); i--; ) {
285 if ( ( element = elements.getItem( i ) ).data( 'cke-magicline-hot' ) ) {
286 // Restore hotNode
287 that.hotNode = element;
288 // Restore last access direction
289 that.lastCmdDirection = element.data( 'cke-magicline-dir' ) === 'true' ? true : false;
290
291 return;
292 }
293 }
294 }
295 } );
296
297 // This method handles mousemove mouse for box toggling.
298 // It uses mouse position to determine underlying element, then
299 // it tries to use different trigger type in order to place the box
300 // in correct place. The following procedure is executed periodically.
301 function checkMouse( mouse ) {
302 that.debug.groupStart( 'CheckMouse' ); // %REMOVE_LINE%
303 that.debug.startTimer(); // %REMOVE_LINE%
304
305 that.mouse = mouse;
306 that.trigger = null;
307
308 checkMouseTimer = null;
309 updateWindowSize( that );
310
311 if (
312 checkMouseTimeoutPending && // There must be an event pending.
313 !that.hiddenMode && // Can't be in hidden mode.
314 editor.focusManager.hasFocus && // Editor must have focus.
315 !that.line.mouseNear() && // Mouse pointer can't be close to the box.
316 ( that.element = elementFromMouse( that, true ) ) // There must be valid element.
317 ) {
318 // If trigger exists, and trigger is correct -> show the box.
319 // Don't show the line if trigger is a descendant of some tabu-list element.
320 if ( ( that.trigger = triggerEditable( that ) || triggerEdge( that ) || triggerExpand( that ) ) &&
321 !isInTabu( that, that.trigger.upper || that.trigger.lower ) ) {
322 that.line.attach().place();
323 }
324
325 // Otherwise remove the box
326 else {
327 that.trigger = null;
328 that.line.detach();
329 }
330
331 that.debug.showTrigger( that.trigger ); // %REMOVE_LINE%
332 that.debug.mousePos( mouse.y, that.element ); // %REMOVE_LINE%
333
334 checkMouseTimeoutPending = false;
335 }
336
337 that.debug.stopTimer(); // %REMOVE_LINE%
338 that.debug.groupEnd(); // %REMOVE_LINE%
339 }
340
341 // This one allows testing and debugging. It reveals some
342 // inner methods to the world.
343 this.backdoor = {
344 accessFocusSpace: accessFocusSpace,
345 boxTrigger: boxTrigger,
346 isLine: isLine,
347 getAscendantTrigger: getAscendantTrigger,
348 getNonEmptyNeighbour: getNonEmptyNeighbour,
349 getSize: getSize,
350 that: that,
351 triggerEdge: triggerEdge,
352 triggerEditable: triggerEditable,
353 triggerExpand: triggerExpand
354 };
355 }
356 }
357
358 // Some shorthands for common methods to save bytes
359 var extend = CKEDITOR.tools.extend,
360 newElement = CKEDITOR.dom.element,
361 newElementFromHtml = newElement.createFromHtml,
362 env = CKEDITOR.env,
363 env_ie8 = CKEDITOR.env.ie && CKEDITOR.env.version < 9,
364 dtd = CKEDITOR.dtd,
365
366 // Global object associating enter modes with elements.
367 enterElements = {},
368
369 // Constant values, types and so on.
370 EDGE_TOP = 128,
371 EDGE_BOTTOM = 64,
372 EDGE_MIDDLE = 32,
373 TYPE_EDGE = 16,
374 TYPE_EXPAND = 8,
375 LOOK_TOP = 4,
376 LOOK_BOTTOM = 2,
377 LOOK_NORMAL = 1,
378 WHITE_SPACE = '\u00A0',
379 DTD_LISTITEM = dtd.$listItem,
380 DTD_TABLECONTENT = dtd.$tableContent,
381 DTD_NONACCESSIBLE = extend( {}, dtd.$nonEditable, dtd.$empty ),
382 DTD_BLOCK = dtd.$block,
383
384 // Minimum time that must elapse between two update*Size calls.
385 // It prevents constant getComuptedStyle calls and improves performance.
386 CACHE_TIME = 100,
387
388 // Shared CSS stuff for box elements
389 CSS_COMMON = 'width:0px;height:0px;padding:0px;margin:0px;display:block;' + 'z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;',
390 CSS_TRIANGLE = CSS_COMMON + 'border-color:transparent;display:block;border-style:solid;',
391 TRIANGLE_HTML = '<span>' + WHITE_SPACE + '</span>';
392
393 enterElements[ CKEDITOR.ENTER_BR ] = 'br';
394 enterElements[ CKEDITOR.ENTER_P ] = 'p';
395 enterElements[ CKEDITOR.ENTER_DIV ] = 'div';
396
397 function areSiblings( that, upper, lower ) {
398 return isHtml( upper ) && isHtml( lower ) && lower.equals( upper.getNext( function( node ) {
399 return !( isEmptyTextNode( node ) || isComment( node ) || isFlowBreaker( node ) );
400 } ) );
401 }
402
403 // boxTrigger is an abstract type which describes
404 // the relationship between elements that may result
405 // in showing the box.
406 //
407 // The following type is used by numerous methods
408 // to share information about the hypothetical box placement
409 // and look by referring to boxTrigger properties.
410 function boxTrigger( triggerSetup ) {
411 this.upper = triggerSetup[ 0 ];
412 this.lower = triggerSetup[ 1 ];
413 this.set.apply( this, triggerSetup.slice( 2 ) );
414 }
415
416 boxTrigger.prototype = {
417 set: function( edge, type, look ) {
418 this.properties = edge + type + ( look || LOOK_NORMAL );
419 return this;
420 },
421
422 is: function( property ) {
423 return ( this.properties & property ) == property;
424 }
425 };
426
427 var elementFromMouse = ( function() {
428 function elementFromPoint( doc, mouse ) {
429 var pointedElement = doc.$.elementFromPoint( mouse.x, mouse.y );
430
431 // IE9QM: from times to times it will return an empty object on scroll bar hover. (#12185)
432 return pointedElement && pointedElement.nodeType ?
433 new CKEDITOR.dom.element( pointedElement ) :
434 null;
435 }
436
437 return function( that, ignoreBox, forceMouse ) {
438 if ( !that.mouse )
439 return null;
440
441 var doc = that.doc,
442 lineWrap = that.line.wrap,
443 mouse = forceMouse || that.mouse,
444 // Note: element might be null.
445 element = elementFromPoint( doc, mouse );
446
447 // If ignoreBox is set and element is the box, it means that we
448 // need to hide the box for a while, repeat elementFromPoint
449 // and show it again.
450 if ( ignoreBox && isLine( that, element ) ) {
451 lineWrap.hide();
452 element = elementFromPoint( doc, mouse );
453 lineWrap.show();
454 }
455
456 // Return nothing if:
457 // \-> Element is not HTML.
458 if ( !( element && element.type == CKEDITOR.NODE_ELEMENT && element.$ ) )
459 return null;
460
461 // Also return nothing if:
462 // \-> We're IE<9 and element is out of the top-level element (editable for inline and HTML for classic (`iframe`-based)).
463 // This is due to the bug which allows IE<9 firing mouse events on element
464 // with contenteditable=true while doing selection out (far, away) of the element.
465 // Thus we must always be sure that we stay in editable or HTML.
466 if ( env.ie && env.version < 9 ) {
467 if ( !( that.boundary.equals( element ) || that.boundary.contains( element ) ) )
468 return null;
469 }
470
471 return element;
472 };
473 } )();
474
475 // Gets the closest parent node that belongs to triggers group.
476 function getAscendantTrigger( that ) {
477 var node = that.element,
478 trigger;
479
480 if ( node && isHtml( node ) ) {
481 trigger = node.getAscendant( that.triggers, true );
482
483 // If trigger is an element, neither editable nor editable's ascendant.
484 if ( trigger && that.editable.contains( trigger ) ) {
485 // Check for closest editable limit.
486 // Don't consider trigger as a limit as it may be nested editable (includeSelf=false) (#12009).
487 var limit = getClosestEditableLimit( trigger );
488
489 // Trigger in nested editable area.
490 if ( limit.getAttribute( 'contenteditable' ) == 'true' )
491 return trigger;
492 // Trigger in non-editable area.
493 else if ( limit.is( that.triggers ) )
494 return limit;
495 else
496 return null;
497 } else {
498 return null;
499 }
500 }
501
502 return null;
503 }
504
505 function getMidpoint( that, upper, lower ) {
506 updateSize( that, upper );
507 updateSize( that, lower );
508
509 var upperSizeBottom = upper.size.bottom,
510 lowerSizeTop = lower.size.top;
511
512 return upperSizeBottom && lowerSizeTop ? 0 | ( upperSizeBottom + lowerSizeTop ) / 2 : upperSizeBottom || lowerSizeTop;
513 }
514
515 // Get nearest node (either text or HTML), but:
516 // \-> Omit all empty text nodes (containing white characters only).
517 // \-> Omit BR elements
518 // \-> Omit flow breakers.
519 function getNonEmptyNeighbour( that, node, goBack ) {
520 node = node[ goBack ? 'getPrevious' : 'getNext' ]( function( node ) {
521 return ( isTextNode( node ) && !isEmptyTextNode( node ) ) ||
522 ( isHtml( node ) && !isFlowBreaker( node ) && !isLine( that, node ) );
523 } );
524
525 return node;
526 }
527
528 function inBetween( val, lower, upper ) {
529 return val > lower && val < upper;
530 }
531
532 // Returns the closest ancestor that has contenteditable attribute.
533 // Such ancestor is the limit of (non-)editable DOM branch that element
534 // belongs to. This method omits editor editable.
535 function getClosestEditableLimit( element, includeSelf ) {
536 if ( element.data( 'cke-editable' ) )
537 return null;
538
539 if ( !includeSelf )
540 element = element.getParent();
541
542 while ( element ) {
543 if ( element.data( 'cke-editable' ) )
544 return null;
545
546 if ( element.hasAttribute( 'contenteditable' ) )
547 return element;
548
549 element = element.getParent();
550 }
551
552 return null;
553 }
554
555 // Access space line consists of a few elements (spans):
556 // \-> Line wrapper.
557 // \-> Line.
558 // \-> Line triangles: left triangle (LT), right triangle (RT).
559 // \-> Button handler (BTN).
560 //
561 // +--------------------------------------------------- line.wrap (span) -----+
562 // | +---------------------------------------------------- line (span) -----+ |
563 // | | +- LT \ +- BTN -+ / RT -+ | |
564 // | | | \ | | | / | | |
565 // | | | / | <__| | \ | | |
566 // | | +-----/ +-------+ \-----+ | |
567 // | +----------------------------------------------------------------------+ |
568 // +--------------------------------------------------------------------------+
569 //
570 function initLine( that ) {
571 var doc = that.doc,
572 // This the main box element that holds triangles and the insertion button
573 line = newElementFromHtml( '<span contenteditable="false" style="' + CSS_COMMON + 'position:absolute;border-top:1px dashed ' + that.boxColor + '"></span>', doc ),
574 iconPath = CKEDITOR.getUrl( this.path + 'images/' + ( env.hidpi ? 'hidpi/' : '' ) + 'icon' + ( that.rtl ? '-rtl' : '' ) + '.png' );
575
576 extend( line, {
577
578 attach: function() {
579 // Only if not already attached
580 if ( !this.wrap.getParent() )
581 this.wrap.appendTo( that.editable, true );
582
583 return this;
584 },
585
586 // Looks are as follows: [ LOOK_TOP, LOOK_BOTTOM, LOOK_NORMAL ].
587 lineChildren: [
588 extend(
589 newElementFromHtml(
590 '<span title="' + that.editor.lang.magicline.title +
591 '" contenteditable="false">&#8629;</span>', doc
592 ), {
593 base: CSS_COMMON + 'height:17px;width:17px;' + ( that.rtl ? 'left' : 'right' ) + ':17px;' +
594 'background:url(' + iconPath + ') center no-repeat ' + that.boxColor + ';cursor:pointer;' +
595 ( env.hc ? 'font-size: 15px;line-height:14px;border:1px solid #fff;text-align:center;' : '' ) +
596 ( env.hidpi ? 'background-size: 9px 10px;' : '' ),
597 looks: [
598 'top:-8px; border-radius: 2px;',
599 'top:-17px; border-radius: 2px 2px 0px 0px;',
600 'top:-1px; border-radius: 0px 0px 2px 2px;'
601 ]
602 }
603 ),
604 extend( newElementFromHtml( TRIANGLE_HTML, doc ), {
605 base: CSS_TRIANGLE + 'left:0px;border-left-color:' + that.boxColor + ';',
606 looks: [
607 'border-width:8px 0 8px 8px;top:-8px',
608 'border-width:8px 0 0 8px;top:-8px',
609 'border-width:0 0 8px 8px;top:0px'
610 ]
611 } ),
612 extend( newElementFromHtml( TRIANGLE_HTML, doc ), {
613 base: CSS_TRIANGLE + 'right:0px;border-right-color:' + that.boxColor + ';',
614 looks: [
615 'border-width:8px 8px 8px 0;top:-8px',
616 'border-width:8px 8px 0 0;top:-8px',
617 'border-width:0 8px 8px 0;top:0px'
618 ]
619 } )
620 ],
621
622 detach: function() {
623 // Detach only if already attached.
624 if ( this.wrap.getParent() )
625 this.wrap.remove();
626
627 return this;
628 },
629
630 // Checks whether mouseY is around an element by comparing boundaries and considering
631 // an offset distance.
632 mouseNear: function() {
633 that.debug.groupStart( 'mouseNear' ); // %REMOVE_LINE%
634
635 updateSize( that, this );
636 var offset = that.holdDistance,
637 size = this.size;
638
639 // Determine neighborhood by element dimensions and offsets.
640 if ( size && inBetween( that.mouse.y, size.top - offset, size.bottom + offset ) && inBetween( that.mouse.x, size.left - offset, size.right + offset ) ) {
641 that.debug.logEnd( 'Mouse is near.' ); // %REMOVE_LINE%
642 return true;
643 }
644
645 that.debug.logEnd( 'Mouse isn\'t near.' ); // %REMOVE_LINE%
646 return false;
647 },
648
649 // Adjusts position of the box according to the trigger properties.
650 // If also affects look of the box depending on the type of the trigger.
651 place: function() {
652 var view = that.view,
653 editable = that.editable,
654 trigger = that.trigger,
655 upper = trigger.upper,
656 lower = trigger.lower,
657 any = upper || lower,
658 parent = any.getParent(),
659 styleSet = {};
660
661 // Save recent trigger for further insertion.
662 // It is necessary due to the fact, that that.trigger may
663 // contain different boxTrigger at the moment of insertion
664 // or may be even null.
665 this.trigger = trigger;
666
667 upper && updateSize( that, upper, true );
668 lower && updateSize( that, lower, true );
669 updateSize( that, parent, true );
670
671 // Yeah, that's gonna be useful in inline-mode case.
672 if ( that.inInlineMode )
673 updateEditableSize( that, true );
674
675 // Set X coordinate (left, right, width).
676 if ( parent.equals( editable ) ) {
677 styleSet.left = view.scroll.x;
678 styleSet.right = -view.scroll.x;
679 styleSet.width = '';
680 } else {
681 styleSet.left = any.size.left - any.size.margin.left + view.scroll.x - ( that.inInlineMode ? view.editable.left + view.editable.border.left : 0 );
682 styleSet.width = any.size.outerWidth + any.size.margin.left + any.size.margin.right + view.scroll.x;
683 styleSet.right = '';
684 }
685
686 // Set Y coordinate (top) for trigger consisting of two elements.
687 if ( upper && lower ) {
688 // No margins at all or they're equal. Place box right between.
689 if ( upper.size.margin.bottom === lower.size.margin.top )
690 styleSet.top = 0 | ( upper.size.bottom + upper.size.margin.bottom / 2 );
691 else {
692 // Upper margin < lower margin. Place at lower margin.
693 if ( upper.size.margin.bottom < lower.size.margin.top )
694 styleSet.top = upper.size.bottom + upper.size.margin.bottom;
695 // Upper margin > lower margin. Place at upper margin - lower margin.
696 else
697 styleSet.top = upper.size.bottom + upper.size.margin.bottom - lower.size.margin.top;
698 }
699 }
700 // Set Y coordinate (top) for single-edge trigger.
701 else if ( !upper )
702 styleSet.top = lower.size.top - lower.size.margin.top;
703 else if ( !lower ) {
704 styleSet.top = upper.size.bottom + upper.size.margin.bottom;
705 }
706
707 // Set box button modes if close to the viewport horizontal edge
708 // or look forced by the trigger.
709 if ( trigger.is( LOOK_TOP ) || inBetween( styleSet.top, view.scroll.y - 15, view.scroll.y + 5 ) ) {
710 styleSet.top = that.inInlineMode ? 0 : view.scroll.y;
711 this.look( LOOK_TOP );
712 } else if ( trigger.is( LOOK_BOTTOM ) || inBetween( styleSet.top, view.pane.bottom - 5, view.pane.bottom + 15 ) ) {
713 styleSet.top = that.inInlineMode ? (
714 view.editable.height + view.editable.padding.top + view.editable.padding.bottom
715 ) : (
716 view.pane.bottom - 1
717 );
718
719 this.look( LOOK_BOTTOM );
720 } else {
721 if ( that.inInlineMode )
722 styleSet.top -= view.editable.top + view.editable.border.top;
723
724 this.look( LOOK_NORMAL );
725 }
726
727 if ( that.inInlineMode ) {
728 // 1px bug here...
729 styleSet.top--;
730
731 // Consider the editable to be an element with overflow:scroll
732 // and non-zero scrollTop/scrollLeft value.
733 // For example: divarea editable. (#9383)
734 styleSet.top += view.editable.scroll.top;
735 styleSet.left += view.editable.scroll.left;
736 }
737
738 // Append `px` prefixes.
739 for ( var style in styleSet )
740 styleSet[ style ] = CKEDITOR.tools.cssLength( styleSet[ style ] );
741
742 this.setStyles( styleSet );
743 },
744
745 // Changes look of the box according to current needs.
746 // Three different styles are available: [ LOOK_TOP, LOOK_BOTTOM, LOOK_NORMAL ].
747 look: function( look ) {
748 if ( this.oldLook == look )
749 return;
750
751 for ( var i = this.lineChildren.length, child; i--; )
752 ( child = this.lineChildren[ i ] ).setAttribute( 'style', child.base + child.looks[ 0 | look / 2 ] );
753
754 this.oldLook = look;
755 },
756
757 wrap: new newElement( 'span', that.doc )
758
759 } );
760
761 // Insert children into the box.
762 for ( var i = line.lineChildren.length; i--; )
763 line.lineChildren[ i ].appendTo( line );
764
765 // Set default look of the box.
766 line.look( LOOK_NORMAL );
767
768 // Using that wrapper prevents IE (8,9) from resizing editable area at the moment
769 // of box insertion. This works thanks to the fact, that positioned box is wrapped by
770 // an inline element. So much tricky.
771 line.appendTo( line.wrap );
772
773 // Make the box unselectable.
774 line.unselectable();
775
776 // Handle accessSpace node insertion.
777 line.lineChildren[ 0 ].on( 'mouseup', function( event ) {
778 line.detach();
779
780 accessFocusSpace( that, function( accessNode ) {
781 // Use old trigger that was saved by 'place' method. Look: line.place
782 var trigger = that.line.trigger;
783
784 accessNode[ trigger.is( EDGE_TOP ) ? 'insertBefore' : 'insertAfter' ](
785 trigger.is( EDGE_TOP ) ? trigger.lower : trigger.upper );
786 }, true );
787
788 that.editor.focus();
789
790 if ( !env.ie && that.enterMode != CKEDITOR.ENTER_BR )
791 that.hotNode.scrollIntoView();
792
793 event.data.preventDefault( true );
794 } );
795
796 // Prevents IE9 from displaying the resize box and disables drag'n'drop functionality.
797 line.on( 'mousedown', function( event ) {
798 event.data.preventDefault( true );
799 } );
800
801 that.line = line;
802 }
803
804 // This function allows accessing any focus space according to the insert function:
805 // * For enterMode ENTER_P it creates P element filled with dummy white-space.
806 // * For enterMode ENTER_DIV it creates DIV element filled with dummy white-space.
807 // * For enterMode ENTER_BR it creates BR element or &nbsp; in IE.
808 //
809 // The node is being inserted according to insertFunction. Finally the method
810 // selects the non-breaking space making the node ready for typing.
811 function accessFocusSpace( that, insertFunction, doSave ) {
812 var range = new CKEDITOR.dom.range( that.doc ),
813 editor = that.editor,
814 accessNode;
815
816 // IE requires text node of &nbsp; in ENTER_BR mode.
817 if ( env.ie && that.enterMode == CKEDITOR.ENTER_BR )
818 accessNode = that.doc.createText( WHITE_SPACE );
819
820 // In other cases a regular element is used.
821 else {
822 // Use the enterMode of editable's limit or editor's
823 // enter mode if not in nested editable.
824 var limit = getClosestEditableLimit( that.element, true ),
825
826 // This is an enter mode for the context. We cannot use
827 // editor.activeEnterMode because the focused nested editable will
828 // have a different enterMode as editor but magicline will be inserted
829 // directly into editor's editable.
830 enterMode = limit && limit.data( 'cke-enter-mode' ) || that.enterMode;
831
832 accessNode = new newElement( enterElements[ enterMode ], that.doc );
833
834 if ( !accessNode.is( 'br' ) ) {
835 var dummy = that.doc.createText( WHITE_SPACE );
836 dummy.appendTo( accessNode );
837 }
838 }
839
840 doSave && editor.fire( 'saveSnapshot' );
841
842 insertFunction( accessNode );
843 //dummy.appendTo( accessNode );
844 range.moveToPosition( accessNode, CKEDITOR.POSITION_AFTER_START );
845 editor.getSelection().selectRanges( [ range ] );
846 that.hotNode = accessNode;
847
848 doSave && editor.fire( 'saveSnapshot' );
849 }
850
851 // Access focus space on demand by taking an element under the caret as a reference.
852 // The space is accessed provided the element under the caret is trigger AND:
853 //
854 // 1. First/last-child of its parent:
855 // +----------------------- Parent element -+
856 // | +------------------------------ DIV -+ | <-- Access before
857 // | | Foo^ | |
858 // | | | |
859 // | +------------------------------------+ | <-- Access after
860 // +----------------------------------------+
861 //
862 // OR
863 //
864 // 2. It has a direct sibling element, which is also a trigger:
865 // +-------------------------------- DIV#1 -+
866 // | Foo^ |
867 // | |
868 // +----------------------------------------+
869 // <-- Access here
870 // +-------------------------------- DIV#2 -+
871 // | Bar |
872 // | |
873 // +----------------------------------------+
874 //
875 // OR
876 //
877 // 3. It has a direct sibling, which is a trigger and has a valid neighbour trigger,
878 // but belongs to dtd.$.empty/nonEditable:
879 // +------------------------------------ P -+
880 // | Foo^ |
881 // | |
882 // +----------------------------------------+
883 // +----------------------------------- HR -+
884 // <-- Access here
885 // +-------------------------------- DIV#2 -+
886 // | Bar |
887 // | |
888 // +----------------------------------------+
889 //
890 function accessFocusSpaceCmd( that, insertAfter ) {
891 return {
892 canUndo: true,
893 modes: { wysiwyg: 1 },
894 exec: ( function() {
895
896 // Inserts line (accessNode) at the position by taking target node as a reference.
897 function doAccess( target ) {
898 // Remove old hotNode under certain circumstances.
899 var hotNodeChar = ( env.ie && env.version < 9 ? ' ' : WHITE_SPACE ),
900 removeOld = that.hotNode && // Old hotNode must exist.
901 that.hotNode.getText() == hotNodeChar && // Old hotNode hasn't been changed.
902 that.element.equals( that.hotNode ) && // Caret is inside old hotNode.
903 // Command is executed in the same direction.
904 that.lastCmdDirection === !!insertAfter; // jshint ignore:line
905
906 accessFocusSpace( that, function( accessNode ) {
907 if ( removeOld && that.hotNode )
908 that.hotNode.remove();
909
910 accessNode[ insertAfter ? 'insertAfter' : 'insertBefore' ]( target );
911
912 // Make this element distinguishable. Also remember the direction
913 // it's been inserted into document.
914 accessNode.setAttributes( {
915 'data-cke-magicline-hot': 1,
916 'data-cke-magicline-dir': !!insertAfter
917 } );
918
919 // Save last direction of the command (is insertAfter?).
920 that.lastCmdDirection = !!insertAfter;
921 } );
922
923 if ( !env.ie && that.enterMode != CKEDITOR.ENTER_BR )
924 that.hotNode.scrollIntoView();
925
926 // Detach the line if was visible (previously triggered by mouse).
927 that.line.detach();
928 }
929
930 return function( editor ) {
931 var selected = editor.getSelection().getStartElement(),
932 limit;
933
934 // (#9833) Go down to the closest non-inline element in DOM structure
935 // since inline elements don't participate in in magicline.
936 selected = selected.getAscendant( DTD_BLOCK, 1 );
937
938 // Stop if selected is a child of a tabu-list element.
939 if ( isInTabu( that, selected ) )
940 return;
941
942 // Sometimes it may happen that there's no parent block below selected element
943 // or, for example, getAscendant reaches editable or editable parent.
944 // We must avoid such pathological cases.
945 if ( !selected || selected.equals( that.editable ) || selected.contains( that.editable ) )
946 return;
947
948 // Executing the command directly in nested editable should
949 // access space before/after it.
950 if ( ( limit = getClosestEditableLimit( selected ) ) && limit.getAttribute( 'contenteditable' ) == 'false' )
951 selected = limit;
952
953 // That holds element from mouse. Replace it with the
954 // element under the caret.
955 that.element = selected;
956
957 // (3.) Handle the following cases where selected neighbour
958 // is a trigger inaccessible for the caret AND:
959 // - Is first/last-child
960 // OR
961 // - Has a sibling, which is also a trigger.
962 var neighbor = getNonEmptyNeighbour( that, selected, !insertAfter ),
963 neighborSibling;
964
965 // Check for a neighbour that belongs to triggers.
966 // Consider only non-accessible elements (they cannot have any children)
967 // since they cannot be given a caret inside, to run the command
968 // the regular way (1. & 2.).
969 if (
970 isHtml( neighbor ) && neighbor.is( that.triggers ) && neighbor.is( DTD_NONACCESSIBLE ) &&
971 (
972 // Check whether neighbor is first/last-child.
973 !getNonEmptyNeighbour( that, neighbor, !insertAfter ) ||
974 // Check for a sibling of a neighbour that also is a trigger.
975 (
976 ( neighborSibling = getNonEmptyNeighbour( that, neighbor, !insertAfter ) ) &&
977 isHtml( neighborSibling ) &&
978 neighborSibling.is( that.triggers )
979 )
980 )
981 ) {
982 doAccess( neighbor );
983 return;
984 }
985
986 // Look for possible target element DOWN "selected" DOM branch (towards editable)
987 // that belong to that.triggers
988 var target = getAscendantTrigger( that, selected );
989
990 // No HTML target -> no access.
991 if ( !isHtml( target ) )
992 return;
993
994 // (1.) Target is first/last child -> access.
995 if ( !getNonEmptyNeighbour( that, target, !insertAfter ) ) {
996 doAccess( target );
997 return;
998 }
999
1000 var sibling = getNonEmptyNeighbour( that, target, !insertAfter );
1001
1002 // (2.) Target has a sibling that belongs to that.triggers -> access.
1003 if ( sibling && isHtml( sibling ) && sibling.is( that.triggers ) ) {
1004 doAccess( target );
1005 return;
1006 }
1007 };
1008 } )()
1009 };
1010 }
1011
1012 function isLine( that, node ) {
1013 if ( !( node && node.type == CKEDITOR.NODE_ELEMENT && node.$ ) )
1014 return false;
1015
1016 var line = that.line;
1017
1018 return line.wrap.equals( node ) || line.wrap.contains( node );
1019 }
1020
1021 // Is text node containing white-spaces only?
1022 var isEmptyTextNode = CKEDITOR.dom.walker.whitespaces();
1023
1024 // Is fully visible HTML node?
1025 function isHtml( node ) {
1026 return node && node.type == CKEDITOR.NODE_ELEMENT && node.$; // IE requires that
1027 }
1028
1029 function isFloated( element ) {
1030 if ( !isHtml( element ) )
1031 return false;
1032
1033 var options = { left: 1, right: 1, center: 1 };
1034
1035 return !!( options[ element.getComputedStyle( 'float' ) ] || options[ element.getAttribute( 'align' ) ] );
1036 }
1037
1038 function isFlowBreaker( element ) {
1039 if ( !isHtml( element ) )
1040 return false;
1041
1042 return isPositioned( element ) || isFloated( element );
1043 }
1044
1045 // Isn't node of NODE_COMMENT type?
1046 var isComment = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_COMMENT );
1047
1048 function isPositioned( element ) {
1049 return !!{ absolute: 1, fixed: 1 }[ element.getComputedStyle( 'position' ) ];
1050 }
1051
1052 // Is text node?
1053 function isTextNode( node ) {
1054 return node && node.type == CKEDITOR.NODE_TEXT;
1055 }
1056
1057 function isTrigger( that, element ) {
1058 return isHtml( element ) ? element.is( that.triggers ) : null;
1059 }
1060
1061 function isInTabu( that, element ) {
1062 if ( !element )
1063 return false;
1064
1065 var parents = element.getParents( 1 );
1066
1067 for ( var i = parents.length ; i-- ; ) {
1068 for ( var j = that.tabuList.length ; j-- ; ) {
1069 if ( parents[ i ].hasAttribute( that.tabuList[ j ] ) )
1070 return true;
1071 }
1072 }
1073
1074 return false;
1075 }
1076
1077 // This function checks vertically is there's a relevant child between element's edge
1078 // and the pointer.
1079 // \-> Table contents are omitted.
1080 function isChildBetweenPointerAndEdge( that, parent, edgeBottom ) {
1081 var edgeChild = parent[ edgeBottom ? 'getLast' : 'getFirst' ]( function( node ) {
1082 return that.isRelevant( node ) && !node.is( DTD_TABLECONTENT );
1083 } );
1084
1085 if ( !edgeChild )
1086 return false;
1087
1088 updateSize( that, edgeChild );
1089
1090 return edgeBottom ? edgeChild.size.top > that.mouse.y : edgeChild.size.bottom < that.mouse.y;
1091 }
1092
1093 // This method handles edge cases:
1094 // \-> Mouse is around upper or lower edge of view pane.
1095 // \-> Also scroll position is either minimal or maximal.
1096 // \-> It's OK to show LOOK_TOP(BOTTOM) type line.
1097 //
1098 // This trigger doesn't need additional post-filtering.
1099 //
1100 // +----------------------------- Editable -+ /--
1101 // | +---------------------- First child -+ | | <-- Top edge (first child)
1102 // | | | | |
1103 // | | | | | * Mouse activation area *
1104 // | | | | |
1105 // | | ... | | \-- Top edge + trigger offset
1106 // | . . |
1107 // | |
1108 // | . . |
1109 // | | ... | | /-- Bottom edge - trigger offset
1110 // | | | | |
1111 // | | | | | * Mouse activation area *
1112 // | | | | |
1113 // | +----------------------- Last child -+ | | <-- Bottom edge (last child)
1114 // +----------------------------------------+ \--
1115 //
1116 function triggerEditable( that ) {
1117 that.debug.groupStart( 'triggerEditable' ); // %REMOVE_LINE%
1118
1119 var editable = that.editable,
1120 mouse = that.mouse,
1121 view = that.view,
1122 triggerOffset = that.triggerOffset,
1123 triggerLook;
1124
1125 // Update editable dimensions.
1126 updateEditableSize( that );
1127
1128 // This flag determines whether checking bottom trigger.
1129 var bottomTrigger = mouse.y > (
1130 that.inInlineMode ? (
1131 view.editable.top + view.editable.height / 2
1132 ) : (
1133 // This is to handle case when editable.height / 2 <<< pane.height.
1134 Math.min( view.editable.height, view.pane.height ) / 2
1135 )
1136 ),
1137
1138 // Edge node according to bottomTrigger.
1139 edgeNode = editable[ bottomTrigger ? 'getLast' : 'getFirst' ]( function( node ) {
1140 return !( isEmptyTextNode( node ) || isComment( node ) );
1141 } );
1142
1143 // There's no edge node. Abort.
1144 if ( !edgeNode ) {
1145 that.debug.logEnd( 'ABORT. No edge node found.' ); // %REMOVE_LINE%
1146 return null;
1147 }
1148
1149 // If the edgeNode in editable is ML, get the next one.
1150 if ( isLine( that, edgeNode ) ) {
1151 edgeNode = that.line.wrap[ bottomTrigger ? 'getPrevious' : 'getNext' ]( function( node ) {
1152 return !( isEmptyTextNode( node ) || isComment( node ) );
1153 } );
1154 }
1155
1156 // Exclude bad nodes (no ML needed then):
1157 // \-> Edge node is text.
1158 // \-> Edge node is floated, etc.
1159 //
1160 // Edge node *must be* a valid trigger at this stage as well.
1161 if ( !isHtml( edgeNode ) || isFlowBreaker( edgeNode ) || !isTrigger( that, edgeNode ) ) {
1162 that.debug.logEnd( 'ABORT. Invalid edge node.' ); // %REMOVE_LINE%
1163 return null;
1164 }
1165
1166 // Update size of edge node. Dimensions will be necessary.
1167 updateSize( that, edgeNode );
1168
1169 // Return appropriate trigger according to bottomTrigger.
1170 // \-> Top edge trigger case first.
1171 if ( !bottomTrigger && // Top trigger case.
1172 edgeNode.size.top >= 0 && // Check if the first element is fully visible.
1173 inBetween( mouse.y, 0, edgeNode.size.top + triggerOffset ) ) { // Check if mouse in [0, edgeNode.top + triggerOffset].
1174
1175 // Determine trigger look.
1176 triggerLook = that.inInlineMode || view.scroll.y === 0 ?
1177 LOOK_TOP : LOOK_NORMAL;
1178
1179 that.debug.logEnd( 'SUCCESS. Created box trigger. EDGE_TOP.' ); // %REMOVE_LINE%
1180
1181 return new boxTrigger( [ null, edgeNode,
1182 EDGE_TOP,
1183 TYPE_EDGE,
1184 triggerLook
1185 ] );
1186 }
1187
1188 // \-> Bottom case.
1189 else if ( bottomTrigger &&
1190 edgeNode.size.bottom <= view.pane.height && // Check if the last element is fully visible
1191 inBetween( mouse.y, // Check if mouse in...
1192 edgeNode.size.bottom - triggerOffset, view.pane.height ) ) { // [ edgeNode.bottom - triggerOffset, paneHeight ]
1193
1194 // Determine trigger look.
1195 triggerLook = that.inInlineMode ||
1196 inBetween( edgeNode.size.bottom, view.pane.height - triggerOffset, view.pane.height ) ?
1197 LOOK_BOTTOM : LOOK_NORMAL;
1198
1199 that.debug.logEnd( 'SUCCESS. Created box trigger. EDGE_BOTTOM.' ); // %REMOVE_LINE%
1200
1201 return new boxTrigger( [ edgeNode, null,
1202 EDGE_BOTTOM,
1203 TYPE_EDGE,
1204 triggerLook
1205 ] );
1206 }
1207
1208 that.debug.logEnd( 'ABORT. No trigger created.' ); // %REMOVE_LINE%
1209 return null;
1210 }
1211
1212 // This method covers cases *inside* of an element:
1213 // \-> The pointer is in the top (bottom) area of an element and there's
1214 // HTML node before (after) this element.
1215 // \-> An element being the first or last child of its parent.
1216 //
1217 // +----------------------- Parent element -+
1218 // | +----------------------- Element #1 -+ | /--
1219 // | | | | | * Mouse activation area (as first child) *
1220 // | | | | \--
1221 // | | | | /--
1222 // | | | | | * Mouse activation area (Element #2) *
1223 // | +------------------------------------+ | \--
1224 // | |
1225 // | +----------------------- Element #2 -+ | /--
1226 // | | | | | * Mouse activation area (Element #1) *
1227 // | | | | \--
1228 // | | | |
1229 // | +------------------------------------+ |
1230 // | |
1231 // | Text node is here. |
1232 // | |
1233 // | +----------------------- Element #3 -+ |
1234 // | | | |
1235 // | | | |
1236 // | | | | /--
1237 // | | | | | * Mouse activation area (as last child) *
1238 // | +------------------------------------+ | \--
1239 // +----------------------------------------+
1240 //
1241 function triggerEdge( that ) {
1242 that.debug.groupStart( 'triggerEdge' ); // %REMOVE_LINE%
1243
1244 var mouse = that.mouse,
1245 view = that.view,
1246 triggerOffset = that.triggerOffset;
1247
1248 // Get the ascendant trigger basing on elementFromMouse.
1249 var element = getAscendantTrigger( that );
1250
1251 that.debug.logElements( [ element ], [ 'Ascendant trigger' ], 'First stage' ); // %REMOVE_LINE%
1252
1253 // Abort if there's no appropriate element.
1254 if ( !element ) {
1255 that.debug.logEnd( 'ABORT. No element, element is editable or element contains editable.' ); // %REMOVE_LINE%
1256 return null;
1257 }
1258
1259 // Dimensions will be necessary.
1260 updateSize( that, element );
1261
1262 // If triggerOffset is larger than a half of element's height,
1263 // use an offset of 1/2 of element's height. If the offset wasn't reduced,
1264 // top area would cover most (all) cases.
1265 var fixedOffset = Math.min( triggerOffset,
1266 0 | ( element.size.outerHeight / 2 ) ),
1267
1268 // This variable will hold the trigger to be returned.
1269 triggerSetup = [],
1270 triggerLook,
1271
1272 // This flag determines whether dealing with a bottom trigger.
1273 bottomTrigger;
1274
1275 // \-> Top trigger.
1276 if ( inBetween( mouse.y, element.size.top - 1, element.size.top + fixedOffset ) )
1277 bottomTrigger = false;
1278 // \-> Bottom trigger.
1279 else if ( inBetween( mouse.y, element.size.bottom - fixedOffset, element.size.bottom + 1 ) )
1280 bottomTrigger = true;
1281 // \-> Abort. Not in a valid trigger space.
1282 else {
1283 that.debug.logEnd( 'ABORT. Not around of any edge.' ); // %REMOVE_LINE%
1284 return null;
1285 }
1286
1287 // Reject wrong elements.
1288 // \-> Reject an element which is a flow breaker.
1289 // \-> Reject an element which has a child above/below the mouse pointer.
1290 // \-> Reject an element which belongs to list items.
1291 if (
1292 isFlowBreaker( element ) ||
1293 isChildBetweenPointerAndEdge( that, element, bottomTrigger ) ||
1294 element.getParent().is( DTD_LISTITEM )
1295 ) {
1296 that.debug.logEnd( 'ABORT. element is wrong', element ); // %REMOVE_LINE%
1297 return null;
1298 }
1299
1300 // Get sibling according to bottomTrigger.
1301 var elementSibling = getNonEmptyNeighbour( that, element, !bottomTrigger );
1302
1303 // No sibling element.
1304 // This is a first or last child case.
1305 if ( !elementSibling ) {
1306 // No need to reject the element as it has already been done before.
1307 // Prepare a trigger.
1308
1309 // Determine trigger look.
1310 if ( element.equals( that.editable[ bottomTrigger ? 'getLast' : 'getFirst' ]( that.isRelevant ) ) ) {
1311 updateEditableSize( that );
1312
1313 if (
1314 bottomTrigger && inBetween( mouse.y,
1315 element.size.bottom - fixedOffset, view.pane.height ) &&
1316 inBetween( element.size.bottom, view.pane.height - fixedOffset, view.pane.height )
1317 ) {
1318 triggerLook = LOOK_BOTTOM;
1319 } else if ( inBetween( mouse.y, 0, element.size.top + fixedOffset ) ) {
1320 triggerLook = LOOK_TOP;
1321 }
1322 } else {
1323 triggerLook = LOOK_NORMAL;
1324 }
1325
1326 triggerSetup = [ null, element ][ bottomTrigger ? 'reverse' : 'concat' ]().concat( [
1327 bottomTrigger ? EDGE_BOTTOM : EDGE_TOP,
1328 TYPE_EDGE,
1329 triggerLook,
1330 element.equals( that.editable[ bottomTrigger ? 'getLast' : 'getFirst' ]( that.isRelevant ) ) ?
1331 ( bottomTrigger ? LOOK_BOTTOM : LOOK_TOP ) : LOOK_NORMAL
1332 ] );
1333
1334 that.debug.log( 'Configured edge trigger of ' + ( bottomTrigger ? 'EDGE_BOTTOM' : 'EDGE_TOP' ) ); // %REMOVE_LINE%
1335 }
1336
1337 // Abort. Sibling is a text element.
1338 else if ( isTextNode( elementSibling ) ) {
1339 that.debug.logEnd( 'ABORT. Sibling is non-empty text element' ); // %REMOVE_LINE%
1340 return null;
1341 }
1342
1343 // Check if the sibling is a HTML element.
1344 // If so, create an TYPE_EDGE, EDGE_MIDDLE trigger.
1345 else if ( isHtml( elementSibling ) ) {
1346 // Reject wrong elementSiblings.
1347 // \-> Reject an elementSibling which is a flow breaker.
1348 // \-> Reject an elementSibling which isn't a trigger.
1349 // \-> Reject an elementSibling which belongs to list items.
1350 if (
1351 isFlowBreaker( elementSibling ) ||
1352 !isTrigger( that, elementSibling ) ||
1353 elementSibling.getParent().is( DTD_LISTITEM )
1354 ) {
1355 that.debug.logEnd( 'ABORT. elementSibling is wrong', elementSibling ); // %REMOVE_LINE%
1356 return null;
1357 }
1358
1359 // Prepare a trigger.
1360 triggerSetup = [ elementSibling, element ][ bottomTrigger ? 'reverse' : 'concat' ]().concat( [
1361 EDGE_MIDDLE,
1362 TYPE_EDGE
1363 ] );
1364
1365 that.debug.log( 'Configured edge trigger of EDGE_MIDDLE' ); // %REMOVE_LINE%
1366 }
1367
1368 if ( 0 in triggerSetup ) {
1369 that.debug.logEnd( 'SUCCESS. Returning a trigger.' ); // %REMOVE_LINE%
1370 return new boxTrigger( triggerSetup );
1371 }
1372
1373 that.debug.logEnd( 'ABORT. No trigger generated.' ); // %REMOVE_LINE%
1374 return null;
1375 }
1376
1377 // Checks iteratively up and down in search for elements using elementFromMouse method.
1378 // Useful if between two triggers.
1379 //
1380 // +----------------------- Parent element -+
1381 // | +----------------------- Element #1 -+ |
1382 // | | | |
1383 // | | | |
1384 // | | | |
1385 // | +------------------------------------+ |
1386 // | | /--
1387 // | . | |
1388 // | . +-- Floated -+ | |
1389 // | | | | | | * Mouse activation area *
1390 // | | | IGNORE | | |
1391 // | X | | | | Method searches vertically for sibling elements.
1392 // | | +------------+ | | Start point is X (mouse-y coordinate).
1393 // | | | | Floated elements, comments and empty text nodes are omitted.
1394 // | . | |
1395 // | . | |
1396 // | | \--
1397 // | +----------------------- Element #2 -+ |
1398 // | | | |
1399 // | | | |
1400 // | | | |
1401 // | | | |
1402 // | +------------------------------------+ |
1403 // +----------------------------------------+
1404 //
1405 var triggerExpand = ( function() {
1406 // The heart of the procedure. This method creates triggers that are
1407 // filtered by expandFilter method.
1408 function expandEngine( that ) {
1409 that.debug.groupStart( 'expandEngine' ); // %REMOVE_LINE%
1410
1411 var startElement = that.element,
1412 upper, lower, trigger;
1413
1414 if ( !isHtml( startElement ) || startElement.contains( that.editable ) ) {
1415 that.debug.logEnd( 'ABORT. No start element, or start element contains editable.' ); // %REMOVE_LINE%
1416 return null;
1417 }
1418
1419 // Stop searching if element is in non-editable branch of DOM.
1420 if ( startElement.isReadOnly() )
1421 return null;
1422
1423 trigger = verticalSearch( that,
1424 function( current, startElement ) {
1425 return !startElement.equals( current ); // stop when start element and the current one differ
1426 }, function( that, mouse ) {
1427 return elementFromMouse( that, true, mouse );
1428 }, startElement ),
1429
1430 upper = trigger.upper,
1431 lower = trigger.lower;
1432
1433 that.debug.logElements( [ upper, lower ], [ 'Upper', 'Lower' ], 'Pair found' ); // %REMOVE_LINE%
1434
1435 // Success: two siblings have been found
1436 if ( areSiblings( that, upper, lower ) ) {
1437 that.debug.logEnd( 'SUCCESS. Expand trigger created.' ); // %REMOVE_LINE%
1438 return trigger.set( EDGE_MIDDLE, TYPE_EXPAND );
1439 }
1440
1441 that.debug.logElements( [ startElement, upper, lower ], // %REMOVE_LINE%
1442 [ 'Start', 'Upper', 'Lower' ], 'Post-processing' ); // %REMOVE_LINE%
1443
1444 // Danger. Dragons ahead.
1445 // No siblings have been found during previous phase, post-processing may be necessary.
1446 // We can traverse DOM until a valid pair of elements around the pointer is found.
1447
1448 // Prepare for post-processing:
1449 // 1. Determine if upper and lower are children of startElement.
1450 // 1.1. If so, find their ascendants that are closest to startElement (one level deeper than startElement).
1451 // 1.2. Otherwise use first/last-child of the startElement as upper/lower. Why?:
1452 // a) upper/lower belongs to another branch of the DOM tree.
1453 // b) verticalSearch encountered an edge of the viewport and failed.
1454 // 1.3. Make sure upper and lower still exist. Why?:
1455 // a) Upper and lower may be not belong to the branch of the startElement (may not exist at all) and
1456 // startElement has no children.
1457 // 2. Perform the post-processing.
1458 // 2.1. Gather dimensions of an upper element.
1459 // 2.2. Abort if lower edge of upper is already under the mouse pointer. Why?:
1460 // a) We expect upper to be above and lower below the mouse pointer.
1461 // 3. Perform iterative search while upper != lower.
1462 // 3.1. Find the upper-next element. If there's no such element, break current search. Why?:
1463 // a) There's no point in further search if there are only text nodes ahead.
1464 // 3.2. Calculate the distance between the middle point of ( upper, upperNext ) and mouse-y.
1465 // 3.3. If the distance is shorter than the previous best, save it (save upper, upperNext as well).
1466 // 3.4. If the optimal pair is found, assign it back to the trigger.
1467
1468 // 1.1., 1.2.
1469 if ( upper && startElement.contains( upper ) ) {
1470 while ( !upper.getParent().equals( startElement ) )
1471 upper = upper.getParent();
1472 } else {
1473 upper = startElement.getFirst( function( node ) {
1474 return expandSelector( that, node );
1475 } );
1476 }
1477
1478 if ( lower && startElement.contains( lower ) ) {
1479 while ( !lower.getParent().equals( startElement ) )
1480 lower = lower.getParent();
1481 } else {
1482 lower = startElement.getLast( function( node ) {
1483 return expandSelector( that, node );
1484 } );
1485 }
1486
1487 // 1.3.
1488 if ( !upper || !lower ) {
1489 that.debug.logEnd( 'ABORT. There is no upper or no lower element.' ); // %REMOVE_LINE%
1490 return null;
1491 }
1492
1493 // 2.1.
1494 updateSize( that, upper );
1495 updateSize( that, lower );
1496
1497 if ( !checkMouseBetweenElements( that, upper, lower ) ) {
1498 that.debug.logEnd( 'ABORT. Mouse is already above upper or below lower.' ); // %REMOVE_LINE%
1499 return null;
1500 }
1501
1502 var minDistance = Number.MAX_VALUE,
1503 currentDistance, upperNext, minElement, minElementNext;
1504
1505 while ( lower && !lower.equals( upper ) ) {
1506 // 3.1.
1507 if ( !( upperNext = upper.getNext( that.isRelevant ) ) )
1508 break;
1509
1510 // 3.2.
1511 currentDistance = Math.abs( getMidpoint( that, upper, upperNext ) - that.mouse.y );
1512
1513 // 3.3.
1514 if ( currentDistance < minDistance ) {
1515 minDistance = currentDistance;
1516 minElement = upper;
1517 minElementNext = upperNext;
1518 }
1519
1520 upper = upperNext;
1521 updateSize( that, upper );
1522 }
1523
1524 that.debug.logElements( [ minElement, minElementNext ], // %REMOVE_LINE%
1525 [ 'Min', 'MinNext' ], 'Post-processing results' ); // %REMOVE_LINE%
1526
1527 // 3.4.
1528 if ( !minElement || !minElementNext ) {
1529 that.debug.logEnd( 'ABORT. No Min or MinNext' ); // %REMOVE_LINE%
1530 return null;
1531 }
1532
1533 if ( !checkMouseBetweenElements( that, minElement, minElementNext ) ) {
1534 that.debug.logEnd( 'ABORT. Mouse is already above minElement or below minElementNext.' ); // %REMOVE_LINE%
1535 return null;
1536 }
1537
1538 // An element of minimal distance has been found. Assign it to the trigger.
1539 trigger.upper = minElement;
1540 trigger.lower = minElementNext;
1541
1542 // Success: post-processing revealed a pair of elements.
1543 that.debug.logEnd( 'SUCCESSFUL post-processing. Trigger created.' ); // %REMOVE_LINE%
1544 return trigger.set( EDGE_MIDDLE, TYPE_EXPAND );
1545 }
1546
1547 // This is default element selector used by the engine.
1548 function expandSelector( that, node ) {
1549 return !( isTextNode( node ) ||
1550 isComment( node ) ||
1551 isFlowBreaker( node ) ||
1552 isLine( that, node ) ||
1553 ( node.type == CKEDITOR.NODE_ELEMENT && node.$ && node.is( 'br' ) ) );
1554 }
1555
1556 // This method checks whether mouse-y is between the top edge of upper
1557 // and bottom edge of lower.
1558 //
1559 // NOTE: This method assumes that updateSize has already been called
1560 // for the elements and is up-to-date.
1561 //
1562 // +---------------------------- Upper -+ /--
1563 // | | |
1564 // +------------------------------------+ |
1565 // |
1566 // ... |
1567 // |
1568 // X | * Return true for mouse-y in this range *
1569 // |
1570 // ... |
1571 // |
1572 // +---------------------------- Lower -+ |
1573 // | | |
1574 // +------------------------------------+ \--
1575 //
1576 function checkMouseBetweenElements( that, upper, lower ) {
1577 return inBetween( that.mouse.y, upper.size.top, lower.size.bottom );
1578 }
1579
1580 // A method for trigger filtering. Accepts or rejects trigger pairs
1581 // by their location in DOM etc.
1582 function expandFilter( that, trigger ) {
1583 that.debug.groupStart( 'expandFilter' ); // %REMOVE_LINE%
1584
1585 var upper = trigger.upper,
1586 lower = trigger.lower;
1587
1588 if (
1589 !upper || !lower || // NOT: EDGE_MIDDLE trigger ALWAYS has two elements.
1590 isFlowBreaker( lower ) || isFlowBreaker( upper ) || // NOT: one of the elements is floated or positioned
1591 lower.equals( upper ) || upper.equals( lower ) || // NOT: two trigger elements, one equals another.
1592 lower.contains( upper ) || upper.contains( lower )
1593 ) { // NOT: two trigger elements, one contains another.
1594 that.debug.logEnd( 'REJECTED. No upper or no lower or they contain each other.' ); // %REMOVE_LINE%
1595
1596 return false;
1597 }
1598
1599 // YES: two trigger elements, pure siblings.
1600 else if ( isTrigger( that, upper ) && isTrigger( that, lower ) && areSiblings( that, upper, lower ) ) {
1601 that.debug.logElementsEnd( [ upper, lower ], // %REMOVE_LINE%
1602 [ 'upper', 'lower' ], 'APPROVED EDGE_MIDDLE' ); // %REMOVE_LINE%
1603
1604 return true;
1605 }
1606
1607 that.debug.logElementsEnd( [ upper, lower ], // %REMOVE_LINE%
1608 [ 'upper', 'lower' ], 'Rejected unknown pair' ); // %REMOVE_LINE%
1609
1610 return false;
1611 }
1612
1613 // Simple wrapper for expandEngine and expandFilter.
1614 return function( that ) {
1615 that.debug.groupStart( 'triggerExpand' ); // %REMOVE_LINE%
1616
1617 var trigger = expandEngine( that );
1618
1619 that.debug.groupEnd(); // %REMOVE_LINE%
1620 return trigger && expandFilter( that, trigger ) ? trigger : null;
1621 };
1622 } )();
1623
1624 // Collects dimensions of an element.
1625 var sizePrefixes = [ 'top', 'left', 'right', 'bottom' ];
1626
1627 function getSize( that, element, ignoreScroll, force ) {
1628 var docPosition = element.getDocumentPosition(),
1629 border = {},
1630 margin = {},
1631 padding = {},
1632 box = {};
1633
1634 for ( var i = sizePrefixes.length; i--; ) {
1635 border[ sizePrefixes[ i ] ] = parseInt( getStyle( 'border-' + sizePrefixes[ i ] + '-width' ), 10 ) || 0;
1636 padding[ sizePrefixes[ i ] ] = parseInt( getStyle( 'padding-' + sizePrefixes[ i ] ), 10 ) || 0;
1637 margin[ sizePrefixes[ i ] ] = parseInt( getStyle( 'margin-' + sizePrefixes[ i ] ), 10 ) || 0;
1638 }
1639
1640 // updateWindowSize if forced to do so OR NOT ignoring scroll.
1641 if ( !ignoreScroll || force )
1642 updateWindowSize( that, force );
1643
1644 box.top = docPosition.y - ( ignoreScroll ? 0 : that.view.scroll.y ), box.left = docPosition.x - ( ignoreScroll ? 0 : that.view.scroll.x ),
1645
1646 // w/ borders and paddings.
1647 box.outerWidth = element.$.offsetWidth, box.outerHeight = element.$.offsetHeight,
1648
1649 // w/o borders and paddings.
1650 box.height = box.outerHeight - ( padding.top + padding.bottom + border.top + border.bottom ), box.width = box.outerWidth - ( padding.left + padding.right + border.left + border.right ),
1651
1652 box.bottom = box.top + box.outerHeight, box.right = box.left + box.outerWidth;
1653
1654 if ( that.inInlineMode ) {
1655 box.scroll = {
1656 top: element.$.scrollTop,
1657 left: element.$.scrollLeft
1658 };
1659 }
1660
1661 return extend( {
1662 border: border,
1663 padding: padding,
1664 margin: margin,
1665 ignoreScroll: ignoreScroll
1666 }, box, true );
1667
1668 function getStyle( propertyName ) {
1669 return element.getComputedStyle.call( element, propertyName );
1670 }
1671 }
1672
1673 function updateSize( that, element, ignoreScroll ) {
1674 if ( !isHtml( element ) ) // i.e. an element is hidden
1675 return ( element.size = null ); // -> reset size to make it useless for other methods
1676
1677 if ( !element.size )
1678 element.size = {};
1679
1680 // Abort if there was a similar query performed recently.
1681 // This kind of caching provides great performance improvement.
1682 else if ( element.size.ignoreScroll == ignoreScroll && element.size.date > new Date() - CACHE_TIME ) {
1683 that.debug.log( 'element.size: get from cache' ); // %REMOVE_LINE%
1684 return null;
1685 }
1686
1687 that.debug.log( 'element.size: capture' ); // %REMOVE_LINE%
1688
1689 return extend( element.size, getSize( that, element, ignoreScroll ), {
1690 date: +new Date()
1691 }, true );
1692 }
1693
1694 // Updates that.view.editable object.
1695 // This one must be called separately outside of updateWindowSize
1696 // to prevent cyclic dependency getSize<->updateWindowSize.
1697 // It calls getSize with force flag to avoid getWindowSize cache (look: getSize).
1698 function updateEditableSize( that, ignoreScroll ) {
1699 that.view.editable = getSize( that, that.editable, ignoreScroll, true );
1700 }
1701
1702 function updateWindowSize( that, force ) {
1703 if ( !that.view )
1704 that.view = {};
1705
1706 var view = that.view;
1707
1708 if ( !force && view && view.date > new Date() - CACHE_TIME ) {
1709 that.debug.log( 'win.size: get from cache' ); // %REMOVE_LINE%
1710 return;
1711 }
1712
1713 that.debug.log( 'win.size: capturing' ); // %REMOVE_LINE%
1714
1715 var win = that.win,
1716 scroll = win.getScrollPosition(),
1717 paneSize = win.getViewPaneSize();
1718
1719 extend( that.view, {
1720 scroll: {
1721 x: scroll.x,
1722 y: scroll.y,
1723 width: that.doc.$.documentElement.scrollWidth - paneSize.width,
1724 height: that.doc.$.documentElement.scrollHeight - paneSize.height
1725 },
1726 pane: {
1727 width: paneSize.width,
1728 height: paneSize.height,
1729 bottom: paneSize.height + scroll.y
1730 },
1731 date: +new Date()
1732 }, true );
1733 }
1734
1735 // This method searches document vertically using given
1736 // select criterion until stop criterion is fulfilled.
1737 function verticalSearch( that, stopCondition, selectCriterion, startElement ) {
1738 var upper = startElement,
1739 lower = startElement,
1740 mouseStep = 0,
1741 upperFound = false,
1742 lowerFound = false,
1743 viewPaneHeight = that.view.pane.height,
1744 mouse = that.mouse;
1745
1746 while ( mouse.y + mouseStep < viewPaneHeight && mouse.y - mouseStep > 0 ) {
1747 if ( !upperFound )
1748 upperFound = stopCondition( upper, startElement );
1749
1750 if ( !lowerFound )
1751 lowerFound = stopCondition( lower, startElement );
1752
1753 // Still not found...
1754 if ( !upperFound && mouse.y - mouseStep > 0 )
1755 upper = selectCriterion( that, { x: mouse.x, y: mouse.y - mouseStep } );
1756
1757 if ( !lowerFound && mouse.y + mouseStep < viewPaneHeight )
1758 lower = selectCriterion( that, { x: mouse.x, y: mouse.y + mouseStep } );
1759
1760 if ( upperFound && lowerFound )
1761 break;
1762
1763 // Instead of ++ to reduce the number of invocations by half.
1764 // It's trades off accuracy in some edge cases for improved performance.
1765 mouseStep += 2;
1766 }
1767
1768 return new boxTrigger( [ upper, lower, null, null ] );
1769 }
1770
1771} )();
1772
1773/**
1774 * Sets the default vertical distance between the edge of the element and the mouse pointer that
1775 * causes the magic line to appear. This option accepts a value in pixels, without the unit (for example:
1776 * `15` for 15 pixels).
1777 *
1778 * Read more in the [documentation](#!/guide/dev_magicline)
1779 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1780 *
1781 * // Changes the offset to 15px.
1782 * CKEDITOR.config.magicline_triggerOffset = 15;
1783 *
1784 * @cfg {Number} [magicline_triggerOffset=30]
1785 * @member CKEDITOR.config
1786 * @see CKEDITOR.config#magicline_holdDistance
1787 */
1788
1789/**
1790 * Defines the distance between the mouse pointer and the box within
1791 * which the magic line stays revealed and no other focus space is offered to be accessed.
1792 * This value is relative to {@link #magicline_triggerOffset}.
1793 *
1794 * Read more in the [documentation](#!/guide/dev_magicline)
1795 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1796 *
1797 * // Increases the distance to 80% of CKEDITOR.config.magicline_triggerOffset.
1798 * CKEDITOR.config.magicline_holdDistance = .8;
1799 *
1800 * @cfg {Number} [magicline_holdDistance=0.5]
1801 * @member CKEDITOR.config
1802 * @see CKEDITOR.config#magicline_triggerOffset
1803 */
1804
1805/**
1806 * Defines the default keystroke that accesses the closest unreachable focus space **before**
1807 * the caret (start of the selection). If there is no focus space available, the selection remains unchanged.
1808 *
1809 * Read more in the [documentation](#!/guide/dev_magicline)
1810 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1811 *
1812 * // Changes the default keystroke to "Ctrl + ,".
1813 * CKEDITOR.config.magicline_keystrokePrevious = CKEDITOR.CTRL + 188;
1814 *
1815 * @cfg {Number} [magicline_keystrokePrevious=CKEDITOR.CTRL + CKEDITOR.SHIFT + 51 (CTRL + SHIFT + 3)]
1816 * @member CKEDITOR.config
1817 */
1818CKEDITOR.config.magicline_keystrokePrevious = CKEDITOR.CTRL + CKEDITOR.SHIFT + 51; // CTRL + SHIFT + 3
1819
1820/**
1821 * Defines the default keystroke that accesses the closest unreachable focus space **after**
1822 * the caret (start of the selection). If there is no focus space available, the selection remains unchanged.
1823 *
1824 * Read more in the [documentation](#!/guide/dev_magicline)
1825 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1826 *
1827 * // Changes keystroke to "Ctrl + .".
1828 * CKEDITOR.config.magicline_keystrokeNext = CKEDITOR.CTRL + 190;
1829 *
1830 * @cfg {Number} [magicline_keystrokeNext=CKEDITOR.CTRL + CKEDITOR.SHIFT + 52 (CTRL + SHIFT + 4)]
1831 * @member CKEDITOR.config
1832 */
1833CKEDITOR.config.magicline_keystrokeNext = CKEDITOR.CTRL + CKEDITOR.SHIFT + 52; // CTRL + SHIFT + 4
1834
1835/**
1836 * Defines a list of attributes that, if assigned to some elements, prevent the magic line from being
1837 * used within these elements.
1838 *
1839 * Read more in the [documentation](#!/guide/dev_magicline)
1840 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1841 *
1842 * // Adds the "data-tabu" attribute to the magic line tabu list.
1843 * CKEDITOR.config.magicline_tabuList = [ 'data-tabu' ];
1844 *
1845 * @cfg {Number} [magicline_tabuList=[ 'data-widget-wrapper' ]]
1846 * @member CKEDITOR.config
1847 */
1848
1849/**
1850 * Defines the color of the magic line. The color may be adjusted to enhance readability.
1851 *
1852 * Read more in the [documentation](#!/guide/dev_magicline)
1853 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1854 *
1855 * // Changes magic line color to blue.
1856 * CKEDITOR.config.magicline_color = '#0000FF';
1857 *
1858 * @cfg {String} [magicline_color='#FF0000']
1859 * @member CKEDITOR.config
1860 */
1861
1862/**
1863 * Activates the special all-encompassing mode that considers all focus spaces between
1864 * {@link CKEDITOR.dtd#$block} elements as accessible by the magic line.
1865 *
1866 * Read more in the [documentation](#!/guide/dev_magicline)
1867 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1868 *
1869 * // Enables the greedy "put everywhere" mode.
1870 * CKEDITOR.config.magicline_everywhere = true;
1871 *
1872 * @cfg {Boolean} [magicline_everywhere=false]
1873 * @member CKEDITOR.config
1874 */
diff --git a/sources/plugins/magicline/samples/magicline.html b/sources/plugins/magicline/samples/magicline.html
new file mode 100644
index 0000000..8fff40e
--- /dev/null
+++ b/sources/plugins/magicline/samples/magicline.html
@@ -0,0 +1,209 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Using Magicline plugin &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link rel="stylesheet" href="../../../samples/old/sample.css">
12 <meta name="ckeditor-sample-name" content="Magicline plugin">
13 <meta name="ckeditor-sample-group" content="Plugins">
14 <meta name="ckeditor-sample-description" content="Using the Magicline plugin to access difficult focus spaces.">
15</head>
16<body>
17 <h1 class="samples">
18 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Using Magicline plugin
19 </h1>
20 <div class="warning deprecated">
21 This sample is not maintained anymore. Check out its <a href="http://sdk.ckeditor.com/samples/magicline.html">brand new version in CKEditor SDK</a>.
22 </div>
23 <div class="description">
24 <p>
25 This sample shows the advantages of <strong>Magicline</strong> plugin
26 which is to enhance the editing process. Thanks to this plugin,
27 a number of difficult focus spaces which are inaccessible due to
28 browser issues can now be focused.
29 </p>
30 <p>
31 <strong>Magicline</strong> plugin shows a red line with a handler
32 which, when clicked, inserts a paragraph and allows typing. To see this,
33 focus an editor and move your mouse above the focus space you want
34 to access. The plugin is enabled by default so no additional
35 configuration is necessary.
36 </p>
37 </div>
38 <div>
39 <label for="editor1">
40 Editor 1:
41 </label>
42 <div class="description">
43 <p>
44 This editor uses a default <strong>Magicline</strong> setup.
45 </p>
46 </div>
47 <textarea cols="80" id="editor1" name="editor1" rows="10">
48 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
49 &lt;tbody&gt;
50 &lt;tr&gt;
51 &lt;td&gt;This table&lt;/td&gt;
52 &lt;td&gt;is the&lt;/td&gt;
53 &lt;td&gt;very first&lt;/td&gt;
54 &lt;td&gt;element of the document.&lt;/td&gt;
55 &lt;/tr&gt;
56 &lt;tr&gt;
57 &lt;td&gt;We are still&lt;/td&gt;
58 &lt;td&gt;able to acces&lt;/td&gt;
59 &lt;td&gt;the space before it.&lt;/td&gt;
60 &lt;td&gt;
61 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
62 &lt;tbody&gt;
63 &lt;tr&gt;
64 &lt;td&gt;This table is inside of a cell of another table.&lt;/td&gt;
65 &lt;/tr&gt;
66 &lt;tr&gt;
67 &lt;td&gt;We can type&amp;nbsp;either before or after it though.&lt;/td&gt;
68 &lt;/tr&gt;
69 &lt;/tbody&gt;
70 &lt;/table&gt;
71 &lt;/td&gt;
72 &lt;/tr&gt;
73 &lt;/tbody&gt;
74 &lt;/table&gt;
75
76 &lt;p&gt;Two succesive horizontal lines (&lt;tt&gt;HR&lt;/tt&gt; tags). We can access the space in between:&lt;/p&gt;
77
78 &lt;hr /&gt;
79 &lt;hr /&gt;
80 &lt;ol&gt;
81 &lt;li&gt;This numbered list...&lt;/li&gt;
82 &lt;li&gt;...is a neighbour of a horizontal line...&lt;/li&gt;
83 &lt;li&gt;...and another list.&lt;/li&gt;
84 &lt;/ol&gt;
85
86 &lt;ul&gt;
87 &lt;li&gt;We can type between the lists...&lt;/li&gt;
88 &lt;li&gt;...thanks to &lt;strong&gt;Magicline&lt;/strong&gt;.&lt;/li&gt;
89 &lt;/ul&gt;
90
91 &lt;p&gt;Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.&lt;/p&gt;
92
93 &lt;p&gt;Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.&lt;/p&gt;
94
95 &lt;p&gt;Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.&lt;/p&gt;
96
97 &lt;div style=&quot;border: 2px dashed green; background: #ddd; text-align: center;&quot;&gt;
98 &lt;p&gt;This text is wrapped in a&amp;nbsp;&lt;tt&gt;DIV&lt;/tt&gt;&amp;nbsp;element. We can type after this element though.&lt;/p&gt;
99 &lt;/div&gt;
100 </textarea>
101 <script>
102
103 // This call can be placed at any point after the
104 // <textarea>, or inside a <head><script> in a
105 // window.onload event handler.
106
107 CKEDITOR.replace( 'editor1', {
108 extraPlugins: 'magicline', // Ensure that magicline plugin, which is required for this sample, is loaded.
109 allowedContent: true // Switch off the ACF, so very complex content created to
110 // show magicline's power isn't filtered.
111 } );
112
113 </script>
114 </div>
115 <br>
116 <div>
117 <label for="editor2">
118 Editor 2:
119 </label>
120 <div class="description">
121 <p>
122 This editor is using a blue line.
123 </p>
124<pre class="samples">
125CKEDITOR.replace( 'editor2', {
126 magicline_color: 'blue'
127});</pre>
128 </div>
129 <textarea cols="80" id="editor2" name="editor2" rows="10">
130 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
131 &lt;tbody&gt;
132 &lt;tr&gt;
133 &lt;td&gt;This table&lt;/td&gt;
134 &lt;td&gt;is the&lt;/td&gt;
135 &lt;td&gt;very first&lt;/td&gt;
136 &lt;td&gt;element of the document.&lt;/td&gt;
137 &lt;/tr&gt;
138 &lt;tr&gt;
139 &lt;td&gt;We are still&lt;/td&gt;
140 &lt;td&gt;able to acces&lt;/td&gt;
141 &lt;td&gt;the space before it.&lt;/td&gt;
142 &lt;td&gt;
143 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
144 &lt;tbody&gt;
145 &lt;tr&gt;
146 &lt;td&gt;This table is inside of a cell of another table.&lt;/td&gt;
147 &lt;/tr&gt;
148 &lt;tr&gt;
149 &lt;td&gt;We can type&amp;nbsp;either before or after it though.&lt;/td&gt;
150 &lt;/tr&gt;
151 &lt;/tbody&gt;
152 &lt;/table&gt;
153 &lt;/td&gt;
154 &lt;/tr&gt;
155 &lt;/tbody&gt;
156 &lt;/table&gt;
157
158 &lt;p&gt;Two succesive horizontal lines (&lt;tt&gt;HR&lt;/tt&gt; tags). We can access the space in between:&lt;/p&gt;
159
160 &lt;hr /&gt;
161 &lt;hr /&gt;
162 &lt;ol&gt;
163 &lt;li&gt;This numbered list...&lt;/li&gt;
164 &lt;li&gt;...is a neighbour of a horizontal line...&lt;/li&gt;
165 &lt;li&gt;...and another list.&lt;/li&gt;
166 &lt;/ol&gt;
167
168 &lt;ul&gt;
169 &lt;li&gt;We can type between the lists...&lt;/li&gt;
170 &lt;li&gt;...thanks to &lt;strong&gt;Magicline&lt;/strong&gt;.&lt;/li&gt;
171 &lt;/ul&gt;
172
173 &lt;p&gt;Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.&lt;/p&gt;
174
175 &lt;p&gt;Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.&lt;/p&gt;
176
177 &lt;p&gt;Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.&lt;/p&gt;
178
179 &lt;div style=&quot;border: 2px dashed green; background: #ddd; text-align: center;&quot;&gt;
180 &lt;p&gt;This text is wrapped in a&amp;nbsp;&lt;tt&gt;DIV&lt;/tt&gt;&amp;nbsp;element. We can type after this element though.&lt;/p&gt;
181 &lt;/div&gt;
182 </textarea>
183 <script>
184
185 // This call can be placed at any point after the
186 // <textarea>, or inside a <head><script> in a
187 // window.onload event handler.
188
189 CKEDITOR.replace( 'editor2', {
190 extraPlugins: 'magicline', // Ensure that magicline plugin, which is required for this sample, is loaded.
191 magicline_color: 'blue', // Blue line
192 allowedContent: true // Switch off the ACF, so very complex content created to
193 // show magicline's power isn't filtered.
194 });
195
196 </script>
197 </div>
198 <div id="footer">
199 <hr>
200 <p>
201 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
202 </p>
203 <p id="copy">
204 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
205 Knabben. All rights reserved.
206 </p>
207 </div>
208</body>
209</html>
diff --git a/sources/plugins/maximize/icons/hidpi/maximize.png b/sources/plugins/maximize/icons/hidpi/maximize.png
new file mode 100644
index 0000000..865c582
--- /dev/null
+++ b/sources/plugins/maximize/icons/hidpi/maximize.png
Binary files differ
diff --git a/sources/plugins/maximize/icons/maximize.png b/sources/plugins/maximize/icons/maximize.png
new file mode 100644
index 0000000..ab25547
--- /dev/null
+++ b/sources/plugins/maximize/icons/maximize.png
Binary files differ
diff --git a/sources/plugins/maximize/lang/af.js b/sources/plugins/maximize/lang/af.js
new file mode 100644
index 0000000..5f17e23
--- /dev/null
+++ b/sources/plugins/maximize/lang/af.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'af', {
6 maximize: 'Maksimaliseer',
7 minimize: 'Minimaliseer'
8} );
diff --git a/sources/plugins/maximize/lang/ar.js b/sources/plugins/maximize/lang/ar.js
new file mode 100644
index 0000000..cdfb258
--- /dev/null
+++ b/sources/plugins/maximize/lang/ar.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ar', {
6 maximize: 'تكبير',
7 minimize: 'تصغير'
8} );
diff --git a/sources/plugins/maximize/lang/az.js b/sources/plugins/maximize/lang/az.js
new file mode 100644
index 0000000..d3a92ac
--- /dev/null
+++ b/sources/plugins/maximize/lang/az.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'az', {
6 maximize: 'Aşkarla',
7 minimize: 'Gizlət'
8} );
diff --git a/sources/plugins/maximize/lang/bg.js b/sources/plugins/maximize/lang/bg.js
new file mode 100644
index 0000000..a56e04e
--- /dev/null
+++ b/sources/plugins/maximize/lang/bg.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'bg', {
6 maximize: 'Максимизиране',
7 minimize: 'Минимизиране'
8} );
diff --git a/sources/plugins/maximize/lang/bn.js b/sources/plugins/maximize/lang/bn.js
new file mode 100644
index 0000000..3fd4087
--- /dev/null
+++ b/sources/plugins/maximize/lang/bn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'bn', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/bs.js b/sources/plugins/maximize/lang/bs.js
new file mode 100644
index 0000000..cb49710
--- /dev/null
+++ b/sources/plugins/maximize/lang/bs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'bs', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/ca.js b/sources/plugins/maximize/lang/ca.js
new file mode 100644
index 0000000..fc88615
--- /dev/null
+++ b/sources/plugins/maximize/lang/ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ca', {
6 maximize: 'Maximitza',
7 minimize: 'Minimitza'
8} );
diff --git a/sources/plugins/maximize/lang/cs.js b/sources/plugins/maximize/lang/cs.js
new file mode 100644
index 0000000..2234af2
--- /dev/null
+++ b/sources/plugins/maximize/lang/cs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'cs', {
6 maximize: 'Maximalizovat',
7 minimize: 'Minimalizovat'
8} );
diff --git a/sources/plugins/maximize/lang/cy.js b/sources/plugins/maximize/lang/cy.js
new file mode 100644
index 0000000..c3370b3
--- /dev/null
+++ b/sources/plugins/maximize/lang/cy.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'cy', {
6 maximize: 'Mwyhau',
7 minimize: 'Lleihau'
8} );
diff --git a/sources/plugins/maximize/lang/da.js b/sources/plugins/maximize/lang/da.js
new file mode 100644
index 0000000..8dd2d88
--- /dev/null
+++ b/sources/plugins/maximize/lang/da.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'da', {
6 maximize: 'Maksimér',
7 minimize: 'Minimér'
8} );
diff --git a/sources/plugins/maximize/lang/de-ch.js b/sources/plugins/maximize/lang/de-ch.js
new file mode 100644
index 0000000..440814b
--- /dev/null
+++ b/sources/plugins/maximize/lang/de-ch.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'de-ch', {
6 maximize: 'Maximieren',
7 minimize: 'Minimieren'
8} );
diff --git a/sources/plugins/maximize/lang/de.js b/sources/plugins/maximize/lang/de.js
new file mode 100644
index 0000000..9af6706
--- /dev/null
+++ b/sources/plugins/maximize/lang/de.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'de', {
6 maximize: 'Maximieren',
7 minimize: 'Minimieren'
8} );
diff --git a/sources/plugins/maximize/lang/el.js b/sources/plugins/maximize/lang/el.js
new file mode 100644
index 0000000..7da1b0b
--- /dev/null
+++ b/sources/plugins/maximize/lang/el.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'el', {
6 maximize: 'Μεγιστοποίηση',
7 minimize: 'Ελαχιστοποίηση'
8} );
diff --git a/sources/plugins/maximize/lang/en-au.js b/sources/plugins/maximize/lang/en-au.js
new file mode 100644
index 0000000..de0310d
--- /dev/null
+++ b/sources/plugins/maximize/lang/en-au.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'en-au', {
6 maximize: 'Maximize',
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/en-ca.js b/sources/plugins/maximize/lang/en-ca.js
new file mode 100644
index 0000000..1c48ee0
--- /dev/null
+++ b/sources/plugins/maximize/lang/en-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'en-ca', {
6 maximize: 'Maximize',
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/en-gb.js b/sources/plugins/maximize/lang/en-gb.js
new file mode 100644
index 0000000..433a065
--- /dev/null
+++ b/sources/plugins/maximize/lang/en-gb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'en-gb', {
6 maximize: 'Maximise',
7 minimize: 'Minimise'
8} );
diff --git a/sources/plugins/maximize/lang/en.js b/sources/plugins/maximize/lang/en.js
new file mode 100644
index 0000000..1e45418
--- /dev/null
+++ b/sources/plugins/maximize/lang/en.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'en', {
6 maximize: 'Maximize',
7 minimize: 'Minimize'
8} );
diff --git a/sources/plugins/maximize/lang/eo.js b/sources/plugins/maximize/lang/eo.js
new file mode 100644
index 0000000..852f529
--- /dev/null
+++ b/sources/plugins/maximize/lang/eo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'eo', {
6 maximize: 'Pligrandigi',
7 minimize: 'Malgrandigi'
8} );
diff --git a/sources/plugins/maximize/lang/es.js b/sources/plugins/maximize/lang/es.js
new file mode 100644
index 0000000..411aae5
--- /dev/null
+++ b/sources/plugins/maximize/lang/es.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'es', {
6 maximize: 'Maximizar',
7 minimize: 'Minimizar'
8} );
diff --git a/sources/plugins/maximize/lang/et.js b/sources/plugins/maximize/lang/et.js
new file mode 100644
index 0000000..1682ec9
--- /dev/null
+++ b/sources/plugins/maximize/lang/et.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'et', {
6 maximize: 'Maksimeerimine',
7 minimize: 'Minimeerimine'
8} );
diff --git a/sources/plugins/maximize/lang/eu.js b/sources/plugins/maximize/lang/eu.js
new file mode 100644
index 0000000..a25c164
--- /dev/null
+++ b/sources/plugins/maximize/lang/eu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'eu', {
6 maximize: 'Maximizatu',
7 minimize: 'Minimizatu'
8} );
diff --git a/sources/plugins/maximize/lang/fa.js b/sources/plugins/maximize/lang/fa.js
new file mode 100644
index 0000000..e08e9ea
--- /dev/null
+++ b/sources/plugins/maximize/lang/fa.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'fa', {
6 maximize: 'بیشنه کردن',
7 minimize: 'کمینه کردن'
8} );
diff --git a/sources/plugins/maximize/lang/fi.js b/sources/plugins/maximize/lang/fi.js
new file mode 100644
index 0000000..763eede
--- /dev/null
+++ b/sources/plugins/maximize/lang/fi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'fi', {
6 maximize: 'Suurenna',
7 minimize: 'Pienennä'
8} );
diff --git a/sources/plugins/maximize/lang/fo.js b/sources/plugins/maximize/lang/fo.js
new file mode 100644
index 0000000..635415a
--- /dev/null
+++ b/sources/plugins/maximize/lang/fo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'fo', {
6 maximize: 'Maksimera',
7 minimize: 'Minimera'
8} );
diff --git a/sources/plugins/maximize/lang/fr-ca.js b/sources/plugins/maximize/lang/fr-ca.js
new file mode 100644
index 0000000..59ed278
--- /dev/null
+++ b/sources/plugins/maximize/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'fr-ca', {
6 maximize: 'Maximizer',
7 minimize: 'Minimizer'
8} );
diff --git a/sources/plugins/maximize/lang/fr.js b/sources/plugins/maximize/lang/fr.js
new file mode 100644
index 0000000..cb3d4dd
--- /dev/null
+++ b/sources/plugins/maximize/lang/fr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'fr', {
6 maximize: 'Agrandir',
7 minimize: 'Réduire'
8} );
diff --git a/sources/plugins/maximize/lang/gl.js b/sources/plugins/maximize/lang/gl.js
new file mode 100644
index 0000000..79009f8
--- /dev/null
+++ b/sources/plugins/maximize/lang/gl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'gl', {
6 maximize: 'Maximizar',
7 minimize: 'Minimizar'
8} );
diff --git a/sources/plugins/maximize/lang/gu.js b/sources/plugins/maximize/lang/gu.js
new file mode 100644
index 0000000..bbd4b52
--- /dev/null
+++ b/sources/plugins/maximize/lang/gu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'gu', {
6 maximize: 'મોટું કરવું',
7 minimize: 'નાનું કરવું'
8} );
diff --git a/sources/plugins/maximize/lang/he.js b/sources/plugins/maximize/lang/he.js
new file mode 100644
index 0000000..d46856b
--- /dev/null
+++ b/sources/plugins/maximize/lang/he.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'he', {
6 maximize: 'הגדלה למקסימום',
7 minimize: 'הקטנה למינימום'
8} );
diff --git a/sources/plugins/maximize/lang/hi.js b/sources/plugins/maximize/lang/hi.js
new file mode 100644
index 0000000..76b0c0c
--- /dev/null
+++ b/sources/plugins/maximize/lang/hi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'hi', {
6 maximize: 'मेक्सिमाईज़',
7 minimize: 'मिनिमाईज़'
8} );
diff --git a/sources/plugins/maximize/lang/hr.js b/sources/plugins/maximize/lang/hr.js
new file mode 100644
index 0000000..4b7a7b3
--- /dev/null
+++ b/sources/plugins/maximize/lang/hr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'hr', {
6 maximize: 'Povećaj',
7 minimize: 'Smanji'
8} );
diff --git a/sources/plugins/maximize/lang/hu.js b/sources/plugins/maximize/lang/hu.js
new file mode 100644
index 0000000..3e11e22
--- /dev/null
+++ b/sources/plugins/maximize/lang/hu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'hu', {
6 maximize: 'Teljes méret',
7 minimize: 'Kis méret'
8} );
diff --git a/sources/plugins/maximize/lang/id.js b/sources/plugins/maximize/lang/id.js
new file mode 100644
index 0000000..1a32383
--- /dev/null
+++ b/sources/plugins/maximize/lang/id.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'id', {
6 maximize: 'Memperbesar',
7 minimize: 'Memperkecil'
8} );
diff --git a/sources/plugins/maximize/lang/is.js b/sources/plugins/maximize/lang/is.js
new file mode 100644
index 0000000..dec813f
--- /dev/null
+++ b/sources/plugins/maximize/lang/is.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'is', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/it.js b/sources/plugins/maximize/lang/it.js
new file mode 100644
index 0000000..67a8a29
--- /dev/null
+++ b/sources/plugins/maximize/lang/it.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'it', {
6 maximize: 'Massimizza',
7 minimize: 'Minimizza'
8} );
diff --git a/sources/plugins/maximize/lang/ja.js b/sources/plugins/maximize/lang/ja.js
new file mode 100644
index 0000000..33184da
--- /dev/null
+++ b/sources/plugins/maximize/lang/ja.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ja', {
6 maximize: '最大化',
7 minimize: '最小化'
8} );
diff --git a/sources/plugins/maximize/lang/ka.js b/sources/plugins/maximize/lang/ka.js
new file mode 100644
index 0000000..a90fb04
--- /dev/null
+++ b/sources/plugins/maximize/lang/ka.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ka', {
6 maximize: 'გადიდება',
7 minimize: 'დაპატარავება'
8} );
diff --git a/sources/plugins/maximize/lang/km.js b/sources/plugins/maximize/lang/km.js
new file mode 100644
index 0000000..4cda2db
--- /dev/null
+++ b/sources/plugins/maximize/lang/km.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'km', {
6 maximize: 'ពង្រីក​អតិបរមា',
7 minimize: 'បង្រួម​អប្បបរមា'
8} );
diff --git a/sources/plugins/maximize/lang/ko.js b/sources/plugins/maximize/lang/ko.js
new file mode 100644
index 0000000..f4af9d4
--- /dev/null
+++ b/sources/plugins/maximize/lang/ko.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ko', {
6 maximize: '최대화',
7 minimize: '최소화'
8} );
diff --git a/sources/plugins/maximize/lang/ku.js b/sources/plugins/maximize/lang/ku.js
new file mode 100644
index 0000000..d34e588
--- /dev/null
+++ b/sources/plugins/maximize/lang/ku.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ku', {
6 maximize: 'ئەوپەڕی گەورەیی',
7 minimize: 'ئەوپەڕی بچووکی'
8} );
diff --git a/sources/plugins/maximize/lang/lt.js b/sources/plugins/maximize/lang/lt.js
new file mode 100644
index 0000000..064291b
--- /dev/null
+++ b/sources/plugins/maximize/lang/lt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'lt', {
6 maximize: 'Išdidinti',
7 minimize: 'Sumažinti'
8} );
diff --git a/sources/plugins/maximize/lang/lv.js b/sources/plugins/maximize/lang/lv.js
new file mode 100644
index 0000000..afbbbbe
--- /dev/null
+++ b/sources/plugins/maximize/lang/lv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'lv', {
6 maximize: 'Maksimizēt',
7 minimize: 'Minimizēt'
8} );
diff --git a/sources/plugins/maximize/lang/mk.js b/sources/plugins/maximize/lang/mk.js
new file mode 100644
index 0000000..69fcfe9
--- /dev/null
+++ b/sources/plugins/maximize/lang/mk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'mk', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/mn.js b/sources/plugins/maximize/lang/mn.js
new file mode 100644
index 0000000..6c4a076
--- /dev/null
+++ b/sources/plugins/maximize/lang/mn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'mn', {
6 maximize: 'Дэлгэц дүүргэх',
7 minimize: 'Цонхыг багсгаж харуулах'
8} );
diff --git a/sources/plugins/maximize/lang/ms.js b/sources/plugins/maximize/lang/ms.js
new file mode 100644
index 0000000..0f27d91
--- /dev/null
+++ b/sources/plugins/maximize/lang/ms.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ms', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/nb.js b/sources/plugins/maximize/lang/nb.js
new file mode 100644
index 0000000..a8ec9dd
--- /dev/null
+++ b/sources/plugins/maximize/lang/nb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'nb', {
6 maximize: 'Maksimer',
7 minimize: 'Minimer'
8} );
diff --git a/sources/plugins/maximize/lang/nl.js b/sources/plugins/maximize/lang/nl.js
new file mode 100644
index 0000000..978bda0
--- /dev/null
+++ b/sources/plugins/maximize/lang/nl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'nl', {
6 maximize: 'Maximaliseren',
7 minimize: 'Minimaliseren'
8} );
diff --git a/sources/plugins/maximize/lang/no.js b/sources/plugins/maximize/lang/no.js
new file mode 100644
index 0000000..02afe8a
--- /dev/null
+++ b/sources/plugins/maximize/lang/no.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'no', {
6 maximize: 'Maksimer',
7 minimize: 'Minimer'
8} );
diff --git a/sources/plugins/maximize/lang/oc.js b/sources/plugins/maximize/lang/oc.js
new file mode 100644
index 0000000..cbd94a4
--- /dev/null
+++ b/sources/plugins/maximize/lang/oc.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'oc', {
6 maximize: 'Maximizar',
7 minimize: 'Minimizar'
8} );
diff --git a/sources/plugins/maximize/lang/pl.js b/sources/plugins/maximize/lang/pl.js
new file mode 100644
index 0000000..1bf6d07
--- /dev/null
+++ b/sources/plugins/maximize/lang/pl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'pl', {
6 maximize: 'Maksymalizuj',
7 minimize: 'Minimalizuj'
8} );
diff --git a/sources/plugins/maximize/lang/pt-br.js b/sources/plugins/maximize/lang/pt-br.js
new file mode 100644
index 0000000..e5c2a52
--- /dev/null
+++ b/sources/plugins/maximize/lang/pt-br.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'pt-br', {
6 maximize: 'Maximizar',
7 minimize: 'Minimize'
8} );
diff --git a/sources/plugins/maximize/lang/pt.js b/sources/plugins/maximize/lang/pt.js
new file mode 100644
index 0000000..a379036
--- /dev/null
+++ b/sources/plugins/maximize/lang/pt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'pt', {
6 maximize: 'Maximizar',
7 minimize: 'Minimizar'
8} );
diff --git a/sources/plugins/maximize/lang/ro.js b/sources/plugins/maximize/lang/ro.js
new file mode 100644
index 0000000..0a3ded6
--- /dev/null
+++ b/sources/plugins/maximize/lang/ro.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ro', {
6 maximize: 'Mărește',
7 minimize: 'Micșorează'
8} );
diff --git a/sources/plugins/maximize/lang/ru.js b/sources/plugins/maximize/lang/ru.js
new file mode 100644
index 0000000..30c491a
--- /dev/null
+++ b/sources/plugins/maximize/lang/ru.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ru', {
6 maximize: 'Развернуть',
7 minimize: 'Свернуть'
8} );
diff --git a/sources/plugins/maximize/lang/si.js b/sources/plugins/maximize/lang/si.js
new file mode 100644
index 0000000..a0331ab
--- /dev/null
+++ b/sources/plugins/maximize/lang/si.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'si', {
6 maximize: 'විශාල කිරීම',
7 minimize: 'කුඩා කිරීම'
8} );
diff --git a/sources/plugins/maximize/lang/sk.js b/sources/plugins/maximize/lang/sk.js
new file mode 100644
index 0000000..a9f2515
--- /dev/null
+++ b/sources/plugins/maximize/lang/sk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'sk', {
6 maximize: 'Maximalizovať',
7 minimize: 'Minimalizovať'
8} );
diff --git a/sources/plugins/maximize/lang/sl.js b/sources/plugins/maximize/lang/sl.js
new file mode 100644
index 0000000..73d5e91
--- /dev/null
+++ b/sources/plugins/maximize/lang/sl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'sl', {
6 maximize: 'Maksimiraj',
7 minimize: 'Minimiraj'
8} );
diff --git a/sources/plugins/maximize/lang/sq.js b/sources/plugins/maximize/lang/sq.js
new file mode 100644
index 0000000..e6b5bc3
--- /dev/null
+++ b/sources/plugins/maximize/lang/sq.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'sq', {
6 maximize: 'Zmadho',
7 minimize: 'Zvogëlo'
8} );
diff --git a/sources/plugins/maximize/lang/sr-latn.js b/sources/plugins/maximize/lang/sr-latn.js
new file mode 100644
index 0000000..33dcd9e
--- /dev/null
+++ b/sources/plugins/maximize/lang/sr-latn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'sr-latn', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/sr.js b/sources/plugins/maximize/lang/sr.js
new file mode 100644
index 0000000..f1ef2d1
--- /dev/null
+++ b/sources/plugins/maximize/lang/sr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'sr', {
6 maximize: 'Maximize', // MISSING
7 minimize: 'Minimize' // MISSING
8} );
diff --git a/sources/plugins/maximize/lang/sv.js b/sources/plugins/maximize/lang/sv.js
new file mode 100644
index 0000000..d14fb84
--- /dev/null
+++ b/sources/plugins/maximize/lang/sv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'sv', {
6 maximize: 'Maximera',
7 minimize: 'Minimera'
8} );
diff --git a/sources/plugins/maximize/lang/th.js b/sources/plugins/maximize/lang/th.js
new file mode 100644
index 0000000..df09eef
--- /dev/null
+++ b/sources/plugins/maximize/lang/th.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'th', {
6 maximize: 'ขยายใหญ่',
7 minimize: 'ย่อขนาด'
8} );
diff --git a/sources/plugins/maximize/lang/tr.js b/sources/plugins/maximize/lang/tr.js
new file mode 100644
index 0000000..90724f4
--- /dev/null
+++ b/sources/plugins/maximize/lang/tr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'tr', {
6 maximize: 'Büyült',
7 minimize: 'Küçült'
8} );
diff --git a/sources/plugins/maximize/lang/tt.js b/sources/plugins/maximize/lang/tt.js
new file mode 100644
index 0000000..cc92021
--- /dev/null
+++ b/sources/plugins/maximize/lang/tt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'tt', {
6 maximize: 'Зурайту',
7 minimize: 'Кечерәйтү'
8} );
diff --git a/sources/plugins/maximize/lang/ug.js b/sources/plugins/maximize/lang/ug.js
new file mode 100644
index 0000000..85af046
--- /dev/null
+++ b/sources/plugins/maximize/lang/ug.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'ug', {
6 maximize: 'چوڭايت',
7 minimize: 'كىچىكلەت'
8} );
diff --git a/sources/plugins/maximize/lang/uk.js b/sources/plugins/maximize/lang/uk.js
new file mode 100644
index 0000000..5ca1021
--- /dev/null
+++ b/sources/plugins/maximize/lang/uk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'uk', {
6 maximize: 'Максимізувати',
7 minimize: 'Мінімізувати'
8} );
diff --git a/sources/plugins/maximize/lang/vi.js b/sources/plugins/maximize/lang/vi.js
new file mode 100644
index 0000000..4ab3a6b
--- /dev/null
+++ b/sources/plugins/maximize/lang/vi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'vi', {
6 maximize: 'Phóng to tối đa',
7 minimize: 'Thu nhỏ'
8} );
diff --git a/sources/plugins/maximize/lang/zh-cn.js b/sources/plugins/maximize/lang/zh-cn.js
new file mode 100644
index 0000000..f4ddf72
--- /dev/null
+++ b/sources/plugins/maximize/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'zh-cn', {
6 maximize: '全屏',
7 minimize: '最小化'
8} );
diff --git a/sources/plugins/maximize/lang/zh.js b/sources/plugins/maximize/lang/zh.js
new file mode 100644
index 0000000..6bca434
--- /dev/null
+++ b/sources/plugins/maximize/lang/zh.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'maximize', 'zh', {
6 maximize: '最大化',
7 minimize: '最小化'
8} );
diff --git a/sources/plugins/maximize/plugin.js b/sources/plugins/maximize/plugin.js
new file mode 100644
index 0000000..16967a0
--- /dev/null
+++ b/sources/plugins/maximize/plugin.js
@@ -0,0 +1,314 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 function protectFormStyles( formElement ) {
8 if ( !formElement || formElement.type != CKEDITOR.NODE_ELEMENT || formElement.getName() != 'form' )
9 return [];
10
11 var hijackRecord = [],
12 hijackNames = [ 'style', 'className' ];
13 for ( var i = 0; i < hijackNames.length; i++ ) {
14 var name = hijackNames[ i ];
15 var $node = formElement.$.elements.namedItem( name );
16 if ( $node ) {
17 var hijackNode = new CKEDITOR.dom.element( $node );
18 hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] );
19 hijackNode.remove();
20 }
21 }
22
23 return hijackRecord;
24 }
25
26 function restoreFormStyles( formElement, hijackRecord ) {
27 if ( !formElement || formElement.type != CKEDITOR.NODE_ELEMENT || formElement.getName() != 'form' )
28 return;
29
30 if ( hijackRecord.length > 0 ) {
31 for ( var i = hijackRecord.length - 1; i >= 0; i-- ) {
32 var node = hijackRecord[ i ][ 0 ];
33 var sibling = hijackRecord[ i ][ 1 ];
34 if ( sibling )
35 node.insertBefore( sibling );
36 else
37 node.appendTo( formElement );
38 }
39 }
40 }
41
42 function saveStyles( element, isInsideEditor ) {
43 var data = protectFormStyles( element );
44 var retval = {};
45
46 var $element = element.$;
47
48 if ( !isInsideEditor ) {
49 retval[ 'class' ] = $element.className || '';
50 $element.className = '';
51 }
52
53 retval.inline = $element.style.cssText || '';
54 if ( !isInsideEditor ) // Reset any external styles that might interfere. (#2474)
55 $element.style.cssText = 'position: static; overflow: visible';
56
57 restoreFormStyles( data );
58 return retval;
59 }
60
61 function restoreStyles( element, savedStyles ) {
62 var data = protectFormStyles( element );
63 var $element = element.$;
64 if ( 'class' in savedStyles )
65 $element.className = savedStyles[ 'class' ];
66 if ( 'inline' in savedStyles )
67 $element.style.cssText = savedStyles.inline;
68 restoreFormStyles( data );
69 }
70
71 function refreshCursor( editor ) {
72 if ( editor.editable().isInline() )
73 return;
74
75 // Refresh all editor instances on the page (#5724).
76 var all = CKEDITOR.instances;
77 for ( var i in all ) {
78 var one = all[ i ];
79 if ( one.mode == 'wysiwyg' && !one.readOnly ) {
80 var body = one.document.getBody();
81 // Refresh 'contentEditable' otherwise
82 // DOM lifting breaks design mode. (#5560)
83 body.setAttribute( 'contentEditable', false );
84 body.setAttribute( 'contentEditable', true );
85 }
86 }
87
88 if ( editor.editable().hasFocus ) {
89 editor.toolbox.focus();
90 editor.focus();
91 }
92 }
93
94 CKEDITOR.plugins.add( 'maximize', {
95 // jscs:disable maximumLineLength
96 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
97 // jscs:enable maximumLineLength
98 icons: 'maximize', // %REMOVE_LINE_CORE%
99 hidpi: true, // %REMOVE_LINE_CORE%
100 init: function( editor ) {
101 // Maximize plugin isn't available in inline mode yet.
102 if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE )
103 return;
104
105 var lang = editor.lang;
106 var mainDocument = CKEDITOR.document,
107 mainWindow = mainDocument.getWindow();
108
109 // Saved selection and scroll position for the editing area.
110 var savedSelection, savedScroll;
111
112 // Saved scroll position for the outer window.
113 var outerScroll;
114
115 // Saved resize handler function.
116 function resizeHandler() {
117 var viewPaneSize = mainWindow.getViewPaneSize();
118 editor.resize( viewPaneSize.width, viewPaneSize.height, null, true );
119 }
120
121 // Retain state after mode switches.
122 var savedState = CKEDITOR.TRISTATE_OFF;
123
124 editor.addCommand( 'maximize', {
125 // Disabled on iOS (#8307).
126 modes: { wysiwyg: !CKEDITOR.env.iOS, source: !CKEDITOR.env.iOS },
127 readOnly: 1,
128 editorFocus: false,
129 exec: function() {
130 var container = editor.container.getFirst( function( node ) {
131 return node.type == CKEDITOR.NODE_ELEMENT && node.hasClass( 'cke_inner' );
132 } );
133 var contents = editor.ui.space( 'contents' );
134
135 // Save current selection and scroll position in editing area.
136 if ( editor.mode == 'wysiwyg' ) {
137 var selection = editor.getSelection();
138 savedSelection = selection && selection.getRanges();
139 savedScroll = mainWindow.getScrollPosition();
140 } else {
141 var $textarea = editor.editable().$;
142 savedSelection = !CKEDITOR.env.ie && [ $textarea.selectionStart, $textarea.selectionEnd ];
143 savedScroll = [ $textarea.scrollLeft, $textarea.scrollTop ];
144 }
145
146 // Go fullscreen if the state is off.
147 if ( this.state == CKEDITOR.TRISTATE_OFF ) {
148 // Add event handler for resizing.
149 mainWindow.on( 'resize', resizeHandler );
150
151 // Save the scroll bar position.
152 outerScroll = mainWindow.getScrollPosition();
153
154 // Save and reset the styles for the entire node tree.
155 var currentNode = editor.container;
156 while ( ( currentNode = currentNode.getParent() ) ) {
157 currentNode.setCustomData( 'maximize_saved_styles', saveStyles( currentNode ) );
158 // Show under floatpanels (-1) and context menu (-2).
159 currentNode.setStyle( 'z-index', editor.config.baseFloatZIndex - 5 );
160 }
161 contents.setCustomData( 'maximize_saved_styles', saveStyles( contents, true ) );
162 container.setCustomData( 'maximize_saved_styles', saveStyles( container, true ) );
163
164 // Hide scroll bars.
165 var styles = {
166 overflow: CKEDITOR.env.webkit ? '' : 'hidden', // #6896
167 width: 0,
168 height: 0
169 };
170
171 mainDocument.getDocumentElement().setStyles( styles );
172 !CKEDITOR.env.gecko && mainDocument.getDocumentElement().setStyle( 'position', 'fixed' );
173 !( CKEDITOR.env.gecko && CKEDITOR.env.quirks ) && mainDocument.getBody().setStyles( styles );
174
175 // Scroll to the top left (IE needs some time for it - #4923).
176 CKEDITOR.env.ie ? setTimeout( function() {
177 mainWindow.$.scrollTo( 0, 0 );
178 }, 0 ) : mainWindow.$.scrollTo( 0, 0 );
179
180 // Resize and move to top left.
181 // Special treatment for FF Quirks (#7284)
182 container.setStyle( 'position', CKEDITOR.env.gecko && CKEDITOR.env.quirks ? 'fixed' : 'absolute' );
183 container.$.offsetLeft; // SAFARI BUG: See #2066.
184 container.setStyles( {
185 // Show under floatpanels (-1) and context menu (-2).
186 'z-index': editor.config.baseFloatZIndex - 5,
187 left: '0px',
188 top: '0px'
189 } );
190
191 // Add cke_maximized class before resize handle since that will change things sizes (#5580)
192 container.addClass( 'cke_maximized' );
193
194 resizeHandler();
195
196 // Still not top left? Fix it. (Bug #174)
197 var offset = container.getDocumentPosition();
198 container.setStyles( {
199 left: ( -1 * offset.x ) + 'px',
200 top: ( -1 * offset.y ) + 'px'
201 } );
202
203 // Fixing positioning editor chrome in Firefox break design mode. (#5149)
204 CKEDITOR.env.gecko && refreshCursor( editor );
205 }
206 // Restore from fullscreen if the state is on.
207 else if ( this.state == CKEDITOR.TRISTATE_ON ) {
208 // Remove event handler for resizing.
209 mainWindow.removeListener( 'resize', resizeHandler );
210
211 // Restore CSS styles for the entire node tree.
212 var editorElements = [ contents, container ];
213 for ( var i = 0; i < editorElements.length; i++ ) {
214 restoreStyles( editorElements[ i ], editorElements[ i ].getCustomData( 'maximize_saved_styles' ) );
215 editorElements[ i ].removeCustomData( 'maximize_saved_styles' );
216 }
217
218 currentNode = editor.container;
219 while ( ( currentNode = currentNode.getParent() ) ) {
220 restoreStyles( currentNode, currentNode.getCustomData( 'maximize_saved_styles' ) );
221 currentNode.removeCustomData( 'maximize_saved_styles' );
222 }
223
224 // Restore the window scroll position.
225 CKEDITOR.env.ie ? setTimeout( function() {
226 mainWindow.$.scrollTo( outerScroll.x, outerScroll.y );
227 }, 0 ) : mainWindow.$.scrollTo( outerScroll.x, outerScroll.y );
228
229 // Remove cke_maximized class.
230 container.removeClass( 'cke_maximized' );
231
232 // Webkit requires a re-layout on editor chrome. (#6695)
233 if ( CKEDITOR.env.webkit ) {
234 container.setStyle( 'display', 'inline' );
235 setTimeout( function() {
236 container.setStyle( 'display', 'block' );
237 }, 0 );
238 }
239
240 // Emit a resize event, because this time the size is modified in
241 // restoreStyles.
242 editor.fire( 'resize', {
243 outerHeight: editor.container.$.offsetHeight,
244 contentsHeight: contents.$.offsetHeight,
245 outerWidth: editor.container.$.offsetWidth
246 } );
247 }
248
249 this.toggleState();
250
251 // Toggle button label.
252 var button = this.uiItems[ 0 ];
253 // Only try to change the button if it exists (#6166)
254 if ( button ) {
255 var label = ( this.state == CKEDITOR.TRISTATE_OFF ) ? lang.maximize.maximize : lang.maximize.minimize;
256 var buttonNode = CKEDITOR.document.getById( button._.id );
257 buttonNode.getChild( 1 ).setHtml( label );
258 buttonNode.setAttribute( 'title', label );
259 buttonNode.setAttribute( 'href', 'javascript:void("' + label + '");' ); // jshint ignore:line
260 }
261
262 // Restore selection and scroll position in editing area.
263 if ( editor.mode == 'wysiwyg' ) {
264 if ( savedSelection ) {
265 // Fixing positioning editor chrome in Firefox break design mode. (#5149)
266 CKEDITOR.env.gecko && refreshCursor( editor );
267
268 editor.getSelection().selectRanges( savedSelection );
269 var element = editor.getSelection().getStartElement();
270 element && element.scrollIntoView( true );
271 } else {
272 mainWindow.$.scrollTo( savedScroll.x, savedScroll.y );
273 }
274 } else {
275 if ( savedSelection ) {
276 $textarea.selectionStart = savedSelection[ 0 ];
277 $textarea.selectionEnd = savedSelection[ 1 ];
278 }
279 $textarea.scrollLeft = savedScroll[ 0 ];
280 $textarea.scrollTop = savedScroll[ 1 ];
281 }
282
283 savedSelection = savedScroll = null;
284 savedState = this.state;
285
286 editor.fire( 'maximize', this.state );
287 },
288 canUndo: false
289 } );
290
291 editor.ui.addButton && editor.ui.addButton( 'Maximize', {
292 label: lang.maximize.maximize,
293 command: 'maximize',
294 toolbar: 'tools,10'
295 } );
296
297 // Restore the command state after mode change, unless it has been changed to disabled (#6467)
298 editor.on( 'mode', function() {
299 var command = editor.getCommand( 'maximize' );
300 command.setState( command.state == CKEDITOR.TRISTATE_DISABLED ? CKEDITOR.TRISTATE_DISABLED : savedState );
301 }, null, null, 100 );
302 }
303 } );
304} )();
305
306/**
307 * Event fired when the maximize command is called.
308 * It also indicates whether an editor is maximized or not.
309 *
310 * @event maximize
311 * @member CKEDITOR.editor
312 * @param {CKEDITOR.editor} editor This editor instance.
313 * @param {Number} data Current state of the command. See {@link CKEDITOR#TRISTATE_ON} and {@link CKEDITOR#TRISTATE_OFF}.
314 */
diff --git a/sources/plugins/menu/plugin.js b/sources/plugins/menu/plugin.js
new file mode 100644
index 0000000..1312a62
--- /dev/null
+++ b/sources/plugins/menu/plugin.js
@@ -0,0 +1,572 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'menu', {
7 requires: 'floatpanel',
8
9 beforeInit: function( editor ) {
10 var groups = editor.config.menu_groups.split( ',' ),
11 groupsOrder = editor._.menuGroups = {},
12 menuItems = editor._.menuItems = {};
13
14 for ( var i = 0; i < groups.length; i++ )
15 groupsOrder[ groups[ i ] ] = i + 1;
16
17 /**
18 * Registers an item group to the editor context menu in order to make it
19 * possible to associate it with menu items later.
20 *
21 * @param {String} name Specify a group name.
22 * @param {Number} [order=100] Define the display sequence of this group
23 * inside the menu. A smaller value gets displayed first.
24 * @member CKEDITOR.editor
25 */
26 editor.addMenuGroup = function( name, order ) {
27 groupsOrder[ name ] = order || 100;
28 };
29
30 /**
31 * Adds an item from the specified definition to the editor context menu.
32 *
33 * @method
34 * @param {String} name The menu item name.
35 * @param {Object} definition The menu item definition.
36 * @member CKEDITOR.editor
37 */
38 editor.addMenuItem = function( name, definition ) {
39 if ( groupsOrder[ definition.group ] )
40 menuItems[ name ] = new CKEDITOR.menuItem( this, name, definition );
41 };
42
43 /**
44 * Adds one or more items from the specified definition object to the editor context menu.
45 *
46 * @method
47 * @param {Object} definitions Object where keys are used as itemName and corresponding values as definition for a {@link #addMenuItem} call.
48 * @member CKEDITOR.editor
49 */
50 editor.addMenuItems = function( definitions ) {
51 for ( var itemName in definitions ) {
52 this.addMenuItem( itemName, definitions[ itemName ] );
53 }
54 };
55
56 /**
57 * Retrieves a particular menu item definition from the editor context menu.
58 *
59 * @method
60 * @param {String} name The name of the desired menu item.
61 * @returns {Object}
62 * @member CKEDITOR.editor
63 */
64 editor.getMenuItem = function( name ) {
65 return menuItems[ name ];
66 };
67
68 /**
69 * Removes a particular menu item added before from the editor context menu.
70 *
71 * @since 3.6.1
72 * @method
73 * @param {String} name The name of the desired menu item.
74 * @member CKEDITOR.editor
75 */
76 editor.removeMenuItem = function( name ) {
77 delete menuItems[ name ];
78 };
79 }
80} );
81
82( function() {
83 var menuItemSource = '<span class="cke_menuitem">' +
84 '<a id="{id}"' +
85 ' class="cke_menubutton cke_menubutton__{name} cke_menubutton_{state} {cls}" href="{href}"' +
86 ' title="{title}"' +
87 ' tabindex="-1"' +
88 ' _cke_focus=1' +
89 ' hidefocus="true"' +
90 ' role="{role}"' +
91 ' aria-label="{label}"' +
92 ' aria-describedby="{id}_description"' +
93 ' aria-haspopup="{hasPopup}"' +
94 ' aria-disabled="{disabled}"' +
95 ' {ariaChecked}' +
96 ' draggable="false"';
97
98 // Some browsers don't cancel key events in the keydown but in the
99 // keypress.
100 // TODO: Check if really needed.
101 if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )
102 menuItemSource += ' onkeypress="return false;"';
103
104 // With Firefox, we need to force the button to redraw, otherwise it
105 // will remain in the focus state. Also we some extra help to prevent dragging (#10373).
106 if ( CKEDITOR.env.gecko ) {
107 menuItemSource += ( ' onblur="this.style.cssText = this.style.cssText;"' +
108 ' ondragstart="return false;"' );
109 }
110
111 // #188
112 menuItemSource += ' onmouseover="CKEDITOR.tools.callFunction({hoverFn},{index});"' +
113 ' onmouseout="CKEDITOR.tools.callFunction({moveOutFn},{index});" ' +
114 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) +
115 '="CKEDITOR.tools.callFunction({clickFn},{index}); return false;"' +
116 '>';
117
118 menuItemSource +=
119 //'' +
120 '<span class="cke_menubutton_inner">' +
121 '<span class="cke_menubutton_icon">' +
122 '<span class="cke_button_icon cke_button__{iconName}_icon" style="{iconStyle}"></span>' +
123 '</span>' +
124 '<span class="cke_menubutton_label">' +
125 '{label}' +
126 '</span>' +
127 '{shortcutHtml}' +
128 '{arrowHtml}' +
129 '</span>' +
130 '</a><span id="{id}_description" class="cke_voice_label" aria-hidden="false">{ariaShortcut}</span></span>';
131
132 var menuArrowSource = '<span class="cke_menuarrow">' +
133 '<span>{label}</span>' +
134 '</span>';
135
136 var menuShortcutSource = '<span class="cke_menubutton_label cke_menubutton_shortcut">' +
137 '{shortcut}' +
138 '</span>';
139
140 var menuItemTpl = CKEDITOR.addTemplate( 'menuItem', menuItemSource ),
141 menuArrowTpl = CKEDITOR.addTemplate( 'menuArrow', menuArrowSource ),
142 menuShortcutTpl = CKEDITOR.addTemplate( 'menuShortcut', menuShortcutSource );
143
144 /**
145 * @class
146 * @todo
147 */
148 CKEDITOR.menu = CKEDITOR.tools.createClass( {
149 /**
150 * @constructor
151 */
152 $: function( editor, definition ) {
153 definition = this._.definition = definition || {};
154 this.id = CKEDITOR.tools.getNextId();
155
156 this.editor = editor;
157 this.items = [];
158 this._.listeners = [];
159
160 this._.level = definition.level || 1;
161
162 var panelDefinition = CKEDITOR.tools.extend( {}, definition.panel, {
163 css: [ CKEDITOR.skin.getPath( 'editor' ) ],
164 level: this._.level - 1,
165 block: {}
166 } );
167
168 var attrs = panelDefinition.block.attributes = ( panelDefinition.attributes || {} );
169 // Provide default role of 'menu'.
170 !attrs.role && ( attrs.role = 'menu' );
171 this._.panelDefinition = panelDefinition;
172 },
173
174 _: {
175 onShow: function() {
176 var selection = this.editor.getSelection(),
177 start = selection && selection.getStartElement(),
178 path = this.editor.elementPath(),
179 listeners = this._.listeners;
180
181 this.removeAll();
182 // Call all listeners, filling the list of items to be displayed.
183 for ( var i = 0; i < listeners.length; i++ ) {
184 var listenerItems = listeners[ i ]( start, selection, path );
185
186 if ( listenerItems ) {
187 for ( var itemName in listenerItems ) {
188 var item = this.editor.getMenuItem( itemName );
189
190 if ( item && ( !item.command || this.editor.getCommand( item.command ).state ) ) {
191 item.state = listenerItems[ itemName ];
192 this.add( item );
193 }
194 }
195 }
196 }
197 },
198
199 onClick: function( item ) {
200 this.hide();
201
202 if ( item.onClick )
203 item.onClick();
204 else if ( item.command )
205 this.editor.execCommand( item.command );
206 },
207
208 onEscape: function( keystroke ) {
209 var parent = this.parent;
210 // 1. If it's sub-menu, close it, with focus restored on this.
211 // 2. In case of a top-menu, close it, with focus returned to page.
212 if ( parent )
213 parent._.panel.hideChild( 1 );
214 else if ( keystroke == 27 )
215 this.hide( 1 );
216
217 return false;
218 },
219
220 onHide: function() {
221 this.onHide && this.onHide();
222 },
223
224 showSubMenu: function( index ) {
225 var menu = this._.subMenu,
226 item = this.items[ index ],
227 subItemDefs = item.getItems && item.getItems();
228
229 // If this item has no subitems, we just hide the submenu, if
230 // available, and return back.
231 if ( !subItemDefs ) {
232 // Hide sub menu with focus returned.
233 this._.panel.hideChild( 1 );
234 return;
235 }
236
237 // Create the submenu, if not available, or clean the existing
238 // one.
239 if ( menu )
240 menu.removeAll();
241 else {
242 menu = this._.subMenu = new CKEDITOR.menu( this.editor, CKEDITOR.tools.extend( {}, this._.definition, { level: this._.level + 1 }, true ) );
243 menu.parent = this;
244 menu._.onClick = CKEDITOR.tools.bind( this._.onClick, this );
245 }
246
247 // Add all submenu items to the menu.
248 for ( var subItemName in subItemDefs ) {
249 var subItem = this.editor.getMenuItem( subItemName );
250 if ( subItem ) {
251 subItem.state = subItemDefs[ subItemName ];
252 menu.add( subItem );
253 }
254 }
255
256 // Get the element representing the current item.
257 var element = this._.panel.getBlock( this.id ).element.getDocument().getById( this.id + String( index ) );
258
259 // Show the submenu.
260 // This timeout is needed to give time for the sub-menu get
261 // focus when JAWS is running. (#9844)
262 setTimeout( function() {
263 menu.show( element, 2 );
264 }, 0 );
265 }
266 },
267
268 proto: {
269 /**
270 * Adds an item.
271 *
272 * @param item
273 */
274 add: function( item ) {
275 // Later we may sort the items, but Array#sort is not stable in
276 // some browsers, here we're forcing the original sequence with
277 // 'order' attribute if it hasn't been assigned. (#3868)
278 if ( !item.order )
279 item.order = this.items.length;
280
281 this.items.push( item );
282 },
283
284 /**
285 * Removes all items.
286 */
287 removeAll: function() {
288 this.items = [];
289 },
290
291 /**
292 * Shows the menu in given location.
293 *
294 * @param {CKEDITOR.dom.element} offsetParent
295 * @param {Number} [corner]
296 * @param {Number} [offsetX]
297 * @param {Number} [offsetY]
298 */
299 show: function( offsetParent, corner, offsetX, offsetY ) {
300 // Not for sub menu.
301 if ( !this.parent ) {
302 this._.onShow();
303 // Don't menu with zero items.
304 if ( !this.items.length )
305 return;
306 }
307
308 corner = corner || ( this.editor.lang.dir == 'rtl' ? 2 : 1 );
309
310 var items = this.items,
311 editor = this.editor,
312 panel = this._.panel,
313 element = this._.element;
314
315 // Create the floating panel for this menu.
316 if ( !panel ) {
317 panel = this._.panel = new CKEDITOR.ui.floatPanel( this.editor, CKEDITOR.document.getBody(), this._.panelDefinition, this._.level );
318
319 panel.onEscape = CKEDITOR.tools.bind( function( keystroke ) {
320 if ( this._.onEscape( keystroke ) === false )
321 return false;
322 }, this );
323
324 panel.onShow = function() {
325 // Menu need CSS resets, compensate class name.
326 var holder = panel._.panel.getHolderElement();
327 holder.getParent().addClass( 'cke' ).addClass( 'cke_reset_all' );
328 };
329
330 panel.onHide = CKEDITOR.tools.bind( function() {
331 this._.onHide && this._.onHide();
332 }, this );
333
334 // Create an autosize block inside the panel.
335 var block = panel.addBlock( this.id, this._.panelDefinition.block );
336 block.autoSize = true;
337
338 var keys = block.keys;
339 keys[ 40 ] = 'next'; // ARROW-DOWN
340 keys[ 9 ] = 'next'; // TAB
341 keys[ 38 ] = 'prev'; // ARROW-UP
342 keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB
343 keys[ ( editor.lang.dir == 'rtl' ? 37 : 39 ) ] = CKEDITOR.env.ie ? 'mouseup' : 'click'; // ARROW-RIGHT/ARROW-LEFT(rtl)
344 keys[ 32 ] = CKEDITOR.env.ie ? 'mouseup' : 'click'; // SPACE
345 CKEDITOR.env.ie && ( keys[ 13 ] = 'mouseup' ); // Manage ENTER, since onclick is blocked in IE (#8041).
346
347 element = this._.element = block.element;
348
349 var elementDoc = element.getDocument();
350 elementDoc.getBody().setStyle( 'overflow', 'hidden' );
351 elementDoc.getElementsByTag( 'html' ).getItem( 0 ).setStyle( 'overflow', 'hidden' );
352
353 this._.itemOverFn = CKEDITOR.tools.addFunction( function( index ) {
354 clearTimeout( this._.showSubTimeout );
355 this._.showSubTimeout = CKEDITOR.tools.setTimeout( this._.showSubMenu, editor.config.menu_subMenuDelay || 400, this, [ index ] );
356 }, this );
357
358 this._.itemOutFn = CKEDITOR.tools.addFunction( function() {
359 clearTimeout( this._.showSubTimeout );
360 }, this );
361
362 this._.itemClickFn = CKEDITOR.tools.addFunction( function( index ) {
363 var item = this.items[ index ];
364
365 if ( item.state == CKEDITOR.TRISTATE_DISABLED ) {
366 this.hide( 1 );
367 return;
368 }
369
370 if ( item.getItems )
371 this._.showSubMenu( index );
372 else
373 this._.onClick( item );
374 }, this );
375 }
376
377 // Put the items in the right order.
378 sortItems( items );
379
380 // Apply the editor mixed direction status to menu.
381 var path = editor.elementPath(),
382 mixedDirCls = ( path && path.direction() != editor.lang.dir ) ? ' cke_mixed_dir_content' : '';
383
384 // Build the HTML that composes the menu and its items.
385 var output = [ '<div class="cke_menu' + mixedDirCls + '" role="presentation">' ];
386
387 var length = items.length,
388 lastGroup = length && items[ 0 ].group;
389
390 for ( var i = 0; i < length; i++ ) {
391 var item = items[ i ];
392 if ( lastGroup != item.group ) {
393 output.push( '<div class="cke_menuseparator" role="separator"></div>' );
394 lastGroup = item.group;
395 }
396
397 item.render( this, i, output );
398 }
399
400 output.push( '</div>' );
401
402 // Inject the HTML inside the panel.
403 element.setHtml( output.join( '' ) );
404
405 CKEDITOR.ui.fire( 'ready', this );
406
407 // Show the panel.
408 if ( this.parent )
409 this.parent._.panel.showAsChild( panel, this.id, offsetParent, corner, offsetX, offsetY );
410 else
411 panel.showBlock( this.id, offsetParent, corner, offsetX, offsetY );
412
413 editor.fire( 'menuShow', [ panel ] );
414 },
415
416 /**
417 * Adds a callback executed on opening the menu. Items
418 * returned by that callback are added to the menu.
419 *
420 * @param {Function} listenerFn
421 * @param {CKEDITOR.dom.element} listenerFn.startElement The selection start anchor element.
422 * @param {CKEDITOR.dom.selection} listenerFn.selection The current selection.
423 * @param {CKEDITOR.dom.elementPath} listenerFn.path The current elements path.
424 * @param listenerFn.return Object (`commandName` => `state`) of items that should be added to the menu.
425 */
426 addListener: function( listenerFn ) {
427 this._.listeners.push( listenerFn );
428 },
429
430 /**
431 * Hides the menu.
432 *
433 * @param {Boolean} [returnFocus]
434 */
435 hide: function( returnFocus ) {
436 this._.onHide && this._.onHide();
437 this._.panel && this._.panel.hide( returnFocus );
438 }
439 }
440 } );
441
442 function sortItems( items ) {
443 items.sort( function( itemA, itemB ) {
444 if ( itemA.group < itemB.group )
445 return -1;
446 else if ( itemA.group > itemB.group )
447 return 1;
448
449 return itemA.order < itemB.order ? -1 : itemA.order > itemB.order ? 1 : 0;
450 } );
451 }
452
453 /**
454 * @class
455 * @todo
456 */
457 CKEDITOR.menuItem = CKEDITOR.tools.createClass( {
458 $: function( editor, name, definition ) {
459 CKEDITOR.tools.extend( this, definition,
460 // Defaults
461 {
462 order: 0,
463 className: 'cke_menubutton__' + name
464 } );
465
466 // Transform the group name into its order number.
467 this.group = editor._.menuGroups[ this.group ];
468
469 this.editor = editor;
470 this.name = name;
471 },
472
473 proto: {
474 render: function( menu, index, output ) {
475 var id = menu.id + String( index ),
476 state = ( typeof this.state == 'undefined' ) ? CKEDITOR.TRISTATE_OFF : this.state,
477 ariaChecked = '',
478 editor = this.editor,
479 keystroke,
480 command,
481 shortcut;
482
483 var stateName = state == CKEDITOR.TRISTATE_ON ? 'on' : state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 'off';
484
485 if ( this.role in { menuitemcheckbox: 1, menuitemradio: 1 } )
486 ariaChecked = ' aria-checked="' + ( state == CKEDITOR.TRISTATE_ON ? 'true' : 'false' ) + '"';
487
488 var hasSubMenu = this.getItems;
489 // ltr: BLACK LEFT-POINTING POINTER
490 // rtl: BLACK RIGHT-POINTING POINTER
491 var arrowLabel = '&#' + ( this.editor.lang.dir == 'rtl' ? '9668' : '9658' ) + ';';
492
493 var iconName = this.name;
494 if ( this.icon && !( /\./ ).test( this.icon ) )
495 iconName = this.icon;
496
497 if ( this.command ) {
498 command = editor.getCommand( this.command );
499 keystroke = editor.getCommandKeystroke( command );
500
501 if ( keystroke ) {
502 shortcut = CKEDITOR.tools.keystrokeToString( editor.lang.common.keyboard, keystroke );
503 }
504 }
505
506 var params = {
507 id: id,
508 name: this.name,
509 iconName: iconName,
510 label: this.label,
511 cls: this.className || '',
512 state: stateName,
513 hasPopup: hasSubMenu ? 'true' : 'false',
514 disabled: state == CKEDITOR.TRISTATE_DISABLED,
515 title: this.label + ( shortcut ? ' (' + shortcut.display + ')' : '' ),
516 ariaShortcut: shortcut ? editor.lang.common.keyboardShortcut + ' ' + shortcut.aria : '',
517 href: 'javascript:void(\'' + ( this.label || '' ).replace( "'" + '' ) + '\')', // jshint ignore:line
518 hoverFn: menu._.itemOverFn,
519 moveOutFn: menu._.itemOutFn,
520 clickFn: menu._.itemClickFn,
521 index: index,
522 iconStyle: CKEDITOR.skin.getIconStyle( iconName, ( this.editor.lang.dir == 'rtl' ), iconName == this.icon ? null : this.icon, this.iconOffset ),
523 shortcutHtml: shortcut ? menuShortcutTpl.output( { shortcut: shortcut.display } ) : '',
524 arrowHtml: hasSubMenu ? menuArrowTpl.output( { label: arrowLabel } ) : '',
525 role: this.role ? this.role : 'menuitem',
526 ariaChecked: ariaChecked
527 };
528
529 menuItemTpl.output( params, output );
530 }
531 }
532 } );
533
534} )();
535
536
537/**
538 * The amount of time, in milliseconds, the editor waits before displaying submenu
539 * options when moving the mouse over options that contain submenus, like the
540 * "Cell Properties" entry for tables.
541 *
542 * // Remove the submenu delay.
543 * config.menu_subMenuDelay = 0;
544 *
545 * @cfg {Number} [menu_subMenuDelay=400]
546 * @member CKEDITOR.config
547 */
548
549/**
550 * Fired when a menu is shown.
551 *
552 * @event menuShow
553 * @member CKEDITOR.editor
554 * @param {CKEDITOR.editor} editor This editor instance.
555 * @param {CKEDITOR.ui.panel[]} data
556 */
557
558/**
559 * A comma separated list of items group names to be displayed in the context
560 * menu. The order of items will reflect the order specified in this list if
561 * no priority was defined in the groups.
562 *
563 * config.menu_groups = 'clipboard,table,anchor,link,image';
564 *
565 * @cfg {String} [menu_groups=see source]
566 * @member CKEDITOR.config
567 */
568CKEDITOR.config.menu_groups = 'clipboard,' +
569 'form,' +
570 'tablecell,tablecellproperties,tablerow,tablecolumn,table,' +
571 'anchor,link,image,flash,' +
572 'checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,div';
diff --git a/sources/plugins/oembed/LICENSE.md b/sources/plugins/oembed/LICENSE.md
new file mode 100644
index 0000000..be0064f
--- /dev/null
+++ b/sources/plugins/oembed/LICENSE.md
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) Ingo Herbote
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/sources/plugins/oembed/README.md b/sources/plugins/oembed/README.md
new file mode 100644
index 0000000..64c729c
--- /dev/null
+++ b/sources/plugins/oembed/README.md
@@ -0,0 +1,201 @@
1CKEditor-oEmbed-Plugin
2======================
3
4oEmbed Plugin for CKEditor
5
6This Plugin allows to insert embedded content (such as photos, videos, audio, and other rich media) via the OEmbed API. You only have to provide the url to the site (It works also when the url is shortened) you want to embed and the plugin does the rest.
7
8This Plugin uses the jquery-oembed-all Plugin located at https://github.com/starfishmod/jquery-oembed-all.
9
10####Demo
11
12http://w8tcha.github.com/CKEditor-oEmbed-Plugin/
13
14####Currently Supported Sites...
15
16###Video
17* Youtube - oembed - YQL
18* Blip - oEmbed
19* Hulu - oEmbed
20* Vimeo - oEmbed
21* National film board of Canada - oEmbed
22* Qik - oEmbed
23* Dotsub - oEmbed
24* Clikthrough - oEmbed
25* Kino Map - oEmbed
26* Funny Or Die - Embedded
27* College Humour - Embedded
28* Metacafe - Embedded
29* embedr - Embedded
30* 5min - oEmbed is XML only - using YQL to translate it
31* ustream.tv - oEmbed is not JSONP enabled - using YQL to translate it
32* viddler - OGP
33* twitvid - Embedded
34* bambuser - Embedded
35* xtranormal - Embedded
36* Gametrailers - Embedded
37* Vzarr - Embedded
38* VHX - oembed
39* bambuser - oembed
40* dailymotion.com - oembed
41* animoto - oembed
42* justin.tv - YQL JSON
43* livestream - OGP
44* scivee - embedded
45* veoh - embedded
46* minoto-video - oembed using YQL
47* TrailerAddict - OGP
48* vodpod - oembed YQL - broken as the oembed has absolute positioning which breaks the display
49* fora.tv -OGP YQL
50* TED - OGP YQL
51* Aniboom - embedded
52* Comedy Central - OGP
53* snotr - embedded
54* zapiks - OGP
55* youku - embedded
56* wistia - Oembed
57
58###Audio
59* Soundcloud - oEmbed
60* HuffDuffer - oEmbed
61* BandCamp - YQL and Embedded
62* podomatic - OGP
63* rdio.com - oEmbed
64* hark.com - OGP
65* chirb.it - YQL and oembed
66* official.fm - YQL and oembed
67* mixcloud - YQL and oembed
68* shoudio - oembed
69* audioboo.fm - OGP
70* Spotify - OGP YQL
71
72###Photo
73* flickr - oEmbed
74* photobucket - oEmbed
75* instagram - oEmbed
76* yfrog - oEmbed
77* 23HQ - oEmbed
78* Smugmug - oEmbed
79* twitpic - OGP YQL
80* 500px.com - OGP
81* visual.ly - YQL Lookup
82* img.ly - Thumbnail view
83* imgur.com - Thumbnail view
84* twitgoo.com - Thumbnail view
85* gravatar - Thumbnail view when using mailto
86* pintrest - YQL - Embedded view of a sort.
87* circuitlab - image view
88* skitch - YQL oembed
89* graphic.ly - OGP
90* dribble - jsonp lookup
91* Lockerz - YQL lookup
92* AsciiArtFarts - YQL Lookup
93* lego cusoo - OGP over YQL
94* plannary - OGP over YQL
95* propic - OGP
96* avairy.com - OGP
97* lomography - ogp
98* weheartit - ogp
99* glogster - ogp
100* chart.ly - embedded
101* twitrpix - OGP
102* chictopia - OGP
103
104###Rich
105* Meetup - oEmbed
106* gigapans - Embedded
107* Slideshare - oEmbed
108* ebay - Embedded
109* scribd - Embedded
110* screenr - Embedded
111* tumblr- JSONP lookup
112* imdb - JSONP lookup via imdbapi.com
113* wikipedia- JSONP lookup
114* github- JSONP lookup (CSS)
115* eventful - OGP
116* myspace - OGP
117* live Journal - JSONP Lookup (CSS)
118* wordpress - oEmbed (wordpress.com, wp.me, blogs.cnn.com, techcrunch.com). I can add other wordpress sites as well.
119* circuitbee -Embedded
120* stack overflow - JSONP Lookup (CSS)
121* Facebook - JSONP Lookup (CSS)
122* Pastebin - Embedded
123* Pastie - YQL lookup
124* kickstarter - Embedded
125* issuu - OGP
126* reelapp.com - Embedded
127* Etsy - OGP over YQL
128* Amazon - Embedded - Requires Affiliate code
129* linkedin - Embedded IFRAME - found a link that works :)
130* Lanyrd - YQL (CSS)
131* twitter - Oembed - status only - but that is ok I think
132* github gist - oembed
133* speakerdeck - yql oembed
134* dipity - yql oembed
135* dailymile - oembed
136* deviantart - oembed
137* Roomshare Japan - oembed
138* mobypictures - oembed
139* prezi - embedded
140* popplet - embedded
141* authorstream - OGP
142* googlecalendar - Iframe
143* cacoo - oembed
144* pearltrees - embedded
145* urtak - oembed - is broken in iframe return atm -seems to be an embed.ly issue??
146* jotform - embedded
147* Urban Dictionary - YQL lookup
148* Ars Technica - YQL Lookup
149* Eventbrite - OGP YQL
150* last.fm OGP YQL
151* Rotten Tomatoes - OGP YQL
152* iFixit - OGP
153* qwiki - OGP
154* brighttalk - Meta info
155* tinychat - OGP
156* tourwrist - embedded
157* bnter - OGP
158* bigthink - OGP
159* wirewax - OGP
160* whosay - OGP
161* timetoast - embedded
162* tripline - OGP
163* jsfiddle - embedded
164
165
166####License
167
168Licensed under the terms of the MIT License.
169
170####Dependencies
171This Plugin requires the following plugins to work: Widget, Dialog.
172
173####Installation
174
175 1. Before you can use the plugin you also need to download & install the widget plugin, if you have it not installed. http://ckeditor.com/addon/widget
176 2. Extract the contents of the file into the "plugins" folder of CKEditor.
177 3. In the CKEditor configuration file (config.js) add the following code:
178
179````js
180config.extraPlugins = 'oembed,widget';
181````
182
1832a. Additionally you can also set the default values vor the Max. Width/Height Values
184
185````js
186config.oembed_maxWidth = '560';
187config.oembed_maxHeight = '315';
188````
189
190and also you can define an css class for the embeded content wrapper (div), by default there is no Class defined
191
192````js
193config.oembed_WrapperClass = 'embededContent';
194````
195
196
1973. and also include the plugin in the toolbar
198
199````js
200toolbar :[ ... ['oembed']...]
201````
diff --git a/sources/plugins/oembed/icons/hidpi/oembed.png b/sources/plugins/oembed/icons/hidpi/oembed.png
new file mode 100644
index 0000000..a568d17
--- /dev/null
+++ b/sources/plugins/oembed/icons/hidpi/oembed.png
Binary files differ
diff --git a/sources/plugins/oembed/icons/oembed.png b/sources/plugins/oembed/icons/oembed.png
new file mode 100644
index 0000000..2ba7cce
--- /dev/null
+++ b/sources/plugins/oembed/icons/oembed.png
Binary files differ
diff --git a/sources/plugins/oembed/lang/de.js b/sources/plugins/oembed/lang/de.js
new file mode 100644
index 0000000..69422ae
--- /dev/null
+++ b/sources/plugins/oembed/lang/de.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'de', {
2 title : "Medien Inhalt einbinden (Bilder, Video, Inhalt)",
3 button : "Medien Inhalt von Verschiedenen Seiten einbinden",
4 pasteUrl : "Fügen Sie eine Url (Gekürzte Urls werden auch erkannt) ein von einer Seite die Unterstützt wird (z.B.: YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, etc.) ...",
5 invalidUrl : "Sie müssem eine korrekte URL an!",
6 noEmbedCode : "Kein embed Code gefunden, oder Seite wird nicht Unterstützt!",
7 url : "URL:",
8 width: "Breite:",
9 height: "Höhe:",
10 widthTitle: "Breite für den eingebundenen Inhalt",
11 heightTitle: "Höhe für den eingebundenen Inhalt",
12 maxWidth: "Max. Breite:",
13 maxHeight: "Max. Höhe:",
14 maxWidthTitle: "Maximale Breite für den eingebundenen Inhalt",
15 maxHeightTitle: "Maximale Höhe für den eingebundenen Inhalt",
16 resizeType: "Größenveränderungsmodus (Nur Video's):",
17 none:'None',
18 noresize: "Keine Veränderung (Standardgröße)",
19 responsive: "Responsive",
20 custom: "Eigene Größe",
21 noVimeo: "Der Eigentümber dieses Videos hat Domain einschränkungen für dieses Video gesetzt das Video kann nicht in die Webseite eingebunden werden.",
22 Error: "Inhalt konnte nicht gefunden werden, bitte Versuchen sie eine Andere URL."
23});
diff --git a/sources/plugins/oembed/lang/en.js b/sources/plugins/oembed/lang/en.js
new file mode 100644
index 0000000..e461f03
--- /dev/null
+++ b/sources/plugins/oembed/lang/en.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'en', {
2 title: "Embed Media Content (Photo, Video, Audio or Rich Content)",
3 button: "Embed Media from External Sites",
4 pasteUrl: "Paste a URL (shorted URLs are also supported) from one of the supported sites (e.g. YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, etc.).",
5 invalidUrl: "Please provide a valid URL.",
6 noEmbedCode: "No embed code found, or site is not supported.",
7 url: "URL:",
8 width: "Width:",
9 height: "Height:",
10 widthTitle: "Width for the embeded content",
11 heightTitle: "Height for the embeded content",
12 maxWidth: "Max. Width:",
13 maxHeight: "Max. Height:",
14 maxWidthTitle: "Maximum Width for the embeded Content",
15 maxHeightTitle: "Maximum Height for the embeded Content",
16 none:'None',
17 resizeType: "Resize Type (videos only):",
18 noresize: "No Resize (use default)",
19 responsive: "Responsive Resize",
20 custom: "Specific Resize",
21 noVimeo: "The owner of this video has set domain restrictions and you will not be able to embed it on your website.",
22 Error: "Media Content could not been retrieved, please try a different URL."
23});
diff --git a/sources/plugins/oembed/lang/fr.js b/sources/plugins/oembed/lang/fr.js
new file mode 100644
index 0000000..c1e0650
--- /dev/null
+++ b/sources/plugins/oembed/lang/fr.js
@@ -0,0 +1,25 @@
1// French Translation by https://github.com/wissim
2
3CKEDITOR.plugins.setLang('oembed', 'fr', {
4 title : "Intégrer des contenus multimédia externes. (Photo, Video, Audio, ...)",
5 button : "Insérer des contenus multimédia provenant de nombreux sites.",
6 pasteUrl : "Coller l'URL de partage que vous voulez publier. De nombreux services sont pris en charge tels que : (YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, etc.). Vous pouvez aussi utiliser les URLs courtes.",
7 invalidUrl : "Merci de fournir une URL valide !",
8 noEmbedCode : "Aucun code d'intégration trouvé ou le site n'est pas supporté !",
9 url : "URL:",
10 width: "Largeur:",
11 height: "Hauteur:",
12 widthTitle: "Largeur du conteneur.",
13 heightTitle: "Hauteur du conteneur.",
14 maxWidth: "Max. Largeur:",
15 maxHeight: "Max. Hauteur:",
16 maxWidthTitle: "Largeur maximale du conteneur.",
17 maxHeightTitle: "Hauteur maximale du conteneur.",
18 resizeType: "Resize Type (Only Video's):",
19 none:'None',
20 noresize: "No Resize (use default)",
21 responsive: "Responsive Resize",
22 custom: "Specific Resize",
23 noVimeo: "The owner of this video has set domain restrictions and you will not be able to embed it on your website.",
24 Error: "Media Content could not been retrieved, please try a different URL."
25});
diff --git a/sources/plugins/oembed/lang/nl.js b/sources/plugins/oembed/lang/nl.js
new file mode 100644
index 0000000..94cf8ad
--- /dev/null
+++ b/sources/plugins/oembed/lang/nl.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'nl', {
2 title : "Integratie van media-inhoud (foto's, video, content)",
3 button : "Media-inhoud van externe websites",
4 pasteUrl : "Geef een URL van een pagina in dat ondersteund wordt (Bijv.: YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, etc.) ...",
5 invalidUrl : "Gelieve een geldige URL op te geven!",
6 noEmbedCode : "Geen embed code gevonden, of de website wordt niet ondersteund!",
7 url : "URL:",
8 width: "Breedte:",
9 height: "Hoogte:",
10 widthTitle: "Breedte voor de ingevoegde inhoud",
11 heightTitle: "Hoogte voor de ingevoegde inhoud",
12 maxWidth: "Maximale breedte:",
13 maxHeight: "Maximale hoogte:",
14 maxWidthTitle: "Maximum breedte voor de ingevoegde inhoud",
15 maxHeightTitle: "Maximum hoogte voor de ingevoegde inhoud",
16 none:'None',
17 resizeType: "Type formaat aanpassing (enkel video's):",
18 noresize: "Geen formaat aanpassing (gebruik standaard)",
19 responsive: "Responsieve formaat aanpassing",
20 custom: "Specifieke formaat aanpassing",
21 noVimeo: "De eigenaar van deze video heeft restricties ingesteld waardoor je deze video niet kunt invoegen op je eigen website.",
22 Error: "Media inhoud kon niet worden opgehaald, gelieve een andere URL te proberen."
23});
diff --git a/sources/plugins/oembed/lang/pl.js b/sources/plugins/oembed/lang/pl.js
new file mode 100644
index 0000000..a7d7b92
--- /dev/null
+++ b/sources/plugins/oembed/lang/pl.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'pl', {
2 title: "Osadzanie multimediów (zdjęć, filmów, dźwięku, bogatych treści)",
3 button: "Osadzanie multimediów z witryn zewnętrznych",
4 pasteUrl: "Wklej tutaj adres URL (adresy skrócone są również obsługiwane) z jednej z obsługiwanych stron (YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, itp.).",
5 invalidUrl: "Proszę wprowadzić prawidłowy adres URL!",
6 noEmbedCode: "Odnośnik nieprawidłowy lub nieobsługiwany!",
7 url: "URL:",
8 width: "szerokość:",
9 height: "wysokość:",
10 widthTitle: "Szerokość osadzanej zawartości",
11 heightTitle: "Wysokość osadzanej zawartości",
12 maxWidth: "Maks. szerokość:",
13 maxHeight: "Maks. wysokość:",
14 maxWidthTitle: "Maksymalna szerokość osadzanej zawartości",
15 maxHeightTitle: "Maksymalna wysokość osadzanej zawartości",
16 resizeType: "Typ zmiany rozmiaru (tylko nagrania wideo):",
17 none:'None',
18 noresize: "Bez zmiany rozmiaru (domyślne)",
19 responsive: "Responsywna zmiana rozmiaru",
20 custom: "Narzucona zmiana rozmiaru",
21 noVimeo: "Właściciel nagrania wideo nałożył ograniczenia domenowe, nagrania nie można osadzić w witrynie.",
22 Error: "Nie można uzyskać zawartości multimedialnej, proszę spróbować inny adres URL."
23});
diff --git a/sources/plugins/oembed/lang/pt-br.js b/sources/plugins/oembed/lang/pt-br.js
new file mode 100644
index 0000000..6616432
--- /dev/null
+++ b/sources/plugins/oembed/lang/pt-br.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'pt-br', {
2 title: "Conteúdo embed de mídia (foto, vídeo, audio, rich)",
3 button: "Conteúdo embed de mídia de vários sites",
4 pasteUrl: "Cole aqui a URL (inclusive URLs encurtadas) de um dos sites que o plugin suporta (ex. YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, etc.) ...",
5 invalidUrl: "Por favor informe uma URL válida!",
6 noEmbedCode: "Nenhum código embed foi encontrado, ou esse site não está na lista dos sites suportados pelo plugin!",
7 url: "URL:",
8 width: "Largura:",
9 height: "Altura:",
10 widthTitle: "Largura do conteúdo embebed",
11 heightTitle: "Altura do conteúdo embeded",
12 maxWidth: "Largura máx.:",
13 maxHeight: "Altura máx.:",
14 maxWidthTitle: "Largura máxima do conteúdo embeded",
15 maxHeightTitle: "Altura máxima do conteúdo embeded",
16 resizeType: "Tipo de redimensionamento (Somente para video):",
17 none:'None',
18 noresize: "Sem redimensionamento (default)",
19 responsive: "Redimensionamento responsivo",
20 custom: "Redimensionamento específico",
21 noVimeo: "O dono desse vídeo tem restrições de domínio a você não poderá utilizá-lo em seu site.",
22 Error: "Esse conteúdo de mídia não foi encontrado, por favor tente uma URL diferente."
23});
diff --git a/sources/plugins/oembed/lang/ru.js b/sources/plugins/oembed/lang/ru.js
new file mode 100644
index 0000000..f2a1e53
--- /dev/null
+++ b/sources/plugins/oembed/lang/ru.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'ru', {
2 title: "Внедрить медиа-контент (видео, аудио, фото и т.д.)",
3 button: "Внедрить медиа-контент с различных сайтов",
4 pasteUrl: "Вставьте ссылку на страницу с медиа-контентом (например YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, и т.д.)",
5 invalidUrl: "Вы ввели некорректный URL",
6 noEmbedCode: "Не обнаружен код для вставки. Возможно, вы ввели ссылку с неподдерживаемого сайта.",
7 url: "URL:",
8 width: "Ширина:",
9 height: "Высота:",
10 widthTitle: "Ширина внедряемого медиа-контента",
11 heightTitle: "Высота внедряемого медиа-контента",
12 maxWidth: "Макс. ширина:",
13 maxHeight: "Макс. высота:",
14 maxWidthTitle: "Максимальная ширина внедряемого медиа-контента",
15 maxHeightTitle: "Максимальная высота внедряемого медиа-контента",
16 resizeType: "Изменение размера (только для видео):",
17 none:'None',
18 noresize: "Без изменения (стандартный размер)",
19 responsive: "Задать максимальный размер",
20 custom: "Задать конкретный размер",
21 noVimeo: "Владелец этого видео установил ограничения на домен, и вы не можете его встроить на ваш сайт.",
22 Error: "Невозможно получить медиа-контент. Попробуйте другой URL."
23});
diff --git a/sources/plugins/oembed/lang/tr.js b/sources/plugins/oembed/lang/tr.js
new file mode 100644
index 0000000..f027106
--- /dev/null
+++ b/sources/plugins/oembed/lang/tr.js
@@ -0,0 +1,23 @@
1CKEDITOR.plugins.setLang('oembed', 'tr', {
2 title: "Medya içeriği ekle (Fotoğraf, Video, Ses Dosyası, Zengin Medya İçeriği)",
3 button: "Farklı sitelerden medya içeriği ekle",
4 pasteUrl: "Desteklenen sitelerden bir URL ekleyin (Kısaltılmış URL de olabilir) (örnek: YouTube, Flickr, Qik, Vimeo, Hulu, Viddler, MyOpera, etc.)...",
5 invalidUrl: "Lütfen geçerli bir URL adresi tanımlayın!",
6 noEmbedCode: "Embed kodu bulunamadı veya site desteklenmiyor!",
7 url: "URL:",
8 width: "Genişlik:",
9 height: "Yükseklik:",
10 widthTitle: "Eklenecek içerik için genişlik",
11 heightTitle: "Eklenecek içerik için yükseklik",
12 maxWidth: "Max. genişlik:",
13 maxHeight: "Max. yükseklik:",
14 maxWidthTitle: "Eklenecek içerik için max. genişlik",
15 maxHeightTitle: "Eklenecek içerik için max. yükseklik",
16 resizeType: "Boyutlandır (sadece videolarda geçerli):",
17 none:'None',
18 noresize: "Boyutlandırma yapma (default kullan)",
19 responsive: "Esnek (Responsive) boyutlandırma",
20 custom: "Özel boyutlandırma",
21 noVimeo: "Bu videonun sahibi alan adı kısıtlaması ayarlamış, web sitenizde bu video çalışmayacaktır.",
22 Error: "Medya içeriği alınamadı, farklı bir URL deneyin."
23});
diff --git a/sources/plugins/oembed/libs/jquery.oembed.min.js b/sources/plugins/oembed/libs/jquery.oembed.min.js
new file mode 100644
index 0000000..e5bd1c5
--- /dev/null
+++ b/sources/plugins/oembed/libs/jquery.oembed.min.js
@@ -0,0 +1 @@
(function(n){function r(){var n=window.location.protocol;return n==="file:"?"http://":"//"}function f(n,t){return t=t?t:"",n?f(--n,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random()*60))+t):t}function s(n,t){var i=n.apiendpoint,u="",r;i+=i.indexOf("?")<=0?"?":"&";i=i.replace("#","%23");n.maxWidth!==null&&(typeof n.params.maxwidth=="undefined"||n.params.maxwidth===null)&&(n.params.maxwidth=n.maxWidth);n.maxHeight!==null&&(typeof n.params.maxheight=="undefined"||n.params.maxheight===null)&&(n.params.maxheight=n.maxHeight);for(r in n.params)r!=n.callbackparameter&&n.params[r]!==null&&(u+="&"+escape(r)+"="+n.params[r]);return i+="format="+n.format+"&url="+escape(t)+u,n.dataType!="json"&&(i+="&"+n.callbackparameter+"=?"),i}function u(i,r,u){n("#jqoembeddata").data(r,i.code);t.beforeEmbed.call(u,i);t.onEmbed.call(u,i);t.afterEmbed.call(u,i)}function e(i,e,o){var p,a,tt,v;if(n("#jqoembeddata").data(e)!=undefined&&o.embedtag.tag!="iframe")a={code:n("#jqoembeddata").data(e)},u(a,e,i);else if(o.yql){var w=o.yql.from||"htmlstring",g=o.yql.url?o.yql.url(e):e,nt="SELECT * FROM "+w+' WHERE url="'+g+'" and '+(/html/.test(w)?"xpath":"itemPath")+"='"+(o.yql.xpath||"/")+"'";w=="html"&&(nt+=" and compat='html5'");v=n.extend({url:r()+"query.yahooapis.com/v1/public/yql",dataType:"jsonp",data:{q:nt,format:"json",env:"store://datatables.org/alltableswithkeys",callback:"?"},success:function(t){var s,f,c,r,h,l;if(o.yql.xpath&&o.yql.xpath=="//meta|//title|//link"){for(f={},t.query.results==null&&(t.query.results={meta:[]}),r=0,h=t.query.results.meta.length;r<h;r++)(c=t.query.results.meta[r].name||t.query.results.meta[r].property||null,c!=null)&&(f[c.toLowerCase()]=t.query.results.meta[r].content);if(f.hasOwnProperty("title")&&f.hasOwnProperty("og:title")||t.query.results.title!=null&&(f.title=t.query.results.title),!f.hasOwnProperty("og:image")&&t.query.results.hasOwnProperty("link"))for(r=0,h=t.query.results.link.length;r<h;r++)t.query.results.link[r].hasOwnProperty("rel")&&t.query.results.link[r].rel=="apple-touch-icon"&&(f["og:image"]=t.query.results.link[r].href.charAt(0)=="/"?g.match(/^(([a-z]+:)?(\/\/)?[^\/]+\/).*$/)[1]+t.query.results.link[r].href:t.query.results.link[r].href);s=o.yql.datareturn(f)}else s=o.yql.datareturn?o.yql.datareturn(t.query.results):t.query.results.result;s!==!1&&(l=n.extend({},s),l.code=s,u(l,e,i))},error:function(){t.onError.call(i,e,o)}},t.ajaxOptions||{});n.ajax(v)}else if(o.templateRegex)if(o.embedtag.tag!==""){var it=o.embedtag.flashvars||"",b=o.embedtag.tag||"embed",h=o.embedtag.width||"auto",rt=o.embedtag.nocache||0,c=o.embedtag.height||"auto",y=e.replace(o.templateRegex,o.apiendpoint);if(o.nocache||(y+="&jqoemcache="+f(5)),o.apikey&&(y=y.replace("_APIKEY_",t.apikeys[o.name])),t.maxHeight&&t.maxWidth)if(t.useResponsiveResize){var l=0,k=h,d=c;h>t.maxWidth&&(l=t.maxWidth/h,k=t.maxWidth,d=c*l,c=c*l,h=h*l);c>t.maxHeight&&(l=t.maxHeight/c,d=t.maxHeight,k=h*l,h=h*l);c=d;h=k}else c=t.maxHeight,h=t.maxWidth;p=n("<"+b+"/>").attr("src",y).attr("width",h).attr("height",c).attr("allowfullscreen",o.embedtag.allowfullscreen||"true").attr("allowscriptaccess",o.embedtag.allowfullscreen||"always").css("max-height",t.maxHeight||"auto").css("max-width",t.maxWidth||"auto");b=="embed"&&p.attr("type",o.embedtag.type||"application/x-shockwave-flash").attr("flashvars",e.replace(o.templateRegex,it));b=="iframe"&&p.attr("scrolling",o.embedtag.scrolling||"no").attr("frameborder",o.embedtag.frameborder||"0");a={code:p};u(a,e,i)}else o.apiendpoint?(o.apikey&&(o.apiendpoint=o.apiendpoint.replace("_APIKEY_",t.apikeys[o.name])),v=n.extend({url:e.replace(o.templateRegex,o.apiendpoint),dataType:"jsonp",success:function(t){var r=n.extend({},t);r.code=o.templateData(t);u(r,e,i)},error:function(){t.onError.call(i,e,o)}},t.ajaxOptions||{}),n.ajax(v)):(a={code:e.replace(o.templateRegex,o.template)},u(a,e,i));else tt=s(o,e),v=n.extend({url:tt,dataType:o.dataType||"jsonp",success:function(t){var r=n.extend({},t);switch(r.type){case"file":case"photo":r.code=n.fn.oembed.getPhotoCode(e,r);break;case"link":r.code=r.provider_name=="Flickr"?n.fn.oembed.getPhotoCode(e,r):n.fn.oembed.getGenericCode(e,r);break;case"video":case"rich":r.code=n.fn.oembed.getRichCode(e,r);break;default:r.code=n.fn.oembed.getGenericCode(e,r)}u(r,e,i)},error:function(){t.onError.call(i,e,o)}},t.ajaxOptions||{}),n.ajax(v)}function o(n){if(n===null)return null;var t,i={};for(t in n)t!==null&&(i[t.toLowerCase()]=n[t]);return i}n.fn.oembed=function(i,r,u){t=n.extend(!0,n.fn.oembed.defaults,r);var f=["0rz.tw","1link.in","1url.com","2.gp","2big.at","2tu.us","3.ly","307.to","4ms.me","4sq.com","4url.cc","6url.com","7.ly","a.gg","a.nf","aa.cx","abcurl.net","ad.vu","adf.ly","adjix.com","afx.cc","all.fuseurl.com","alturl.com","amzn.to","ar.gy","arst.ch","atu.ca","azc.cc","b23.ru","b2l.me","bacn.me","bcool.bz","binged.it","bit.ly","bizj.us","bloat.me","bravo.ly","bsa.ly","budurl.com","canurl.com","chilp.it","chzb.gr","cl.lk","cl.ly","clck.ru","cli.gs","cliccami.info","clickthru.ca","clop.in","conta.cc","cort.as","cot.ag","crks.me","ctvr.us","cutt.us","dai.ly","decenturl.com","dfl8.me","digbig.com","http://digg.com/[^/]+$","disq.us","dld.bz","dlvr.it","do.my","doiop.com","dopen.us","easyuri.com","easyurl.net","eepurl.com","eweri.com","fa.by","fav.me","fb.me","fbshare.me","ff.im","fff.to","fire.to","firsturl.de","firsturl.net","flic.kr","flq.us","fly2.ws","fon.gs","freak.to","fuseurl.com","fuzzy.to","fwd4.me","fwib.net","g.ro.lt","gizmo.do","gl.am","go.9nl.com","go.ign.com","go.usa.gov","goo.gl","goshrink.com","gurl.es","hex.io","hiderefer.com","hmm.ph","href.in","hsblinks.com","htxt.it","huff.to","hulu.com","hurl.me","hurl.ws","icanhaz.com","idek.net","ilix.in","is.gd","its.my","ix.lt","j.mp","jijr.com","kl.am","klck.me","korta.nu","krunchd.com","l9k.net","lat.ms","liip.to","liltext.com","linkbee.com","linkbun.ch","liurl.cn","ln-s.net","ln-s.ru","lnk.gd","lnk.ms","lnkd.in","lnkurl.com","lru.jp","lt.tl","lurl.no","macte.ch","mash.to","merky.de","migre.me","miniurl.com","minurl.fr","mke.me","moby.to","moourl.com","mrte.ch","myloc.me","myurl.in","n.pr","nbc.co","nblo.gs","nn.nf","not.my","notlong.com","nsfw.in","nutshellurl.com","nxy.in","nyti.ms","o-x.fr","oc1.us","om.ly","omf.gd","omoikane.net","on.cnn.com","on.mktw.net","onforb.es","orz.se","ow.ly","ping.fm","pli.gs","pnt.me","politi.co","post.ly","pp.gg","profile.to","ptiturl.com","pub.vitrue.com","qlnk.net","qte.me","qu.tc","qy.fi","r.ebay.com","r.im","rb6.me","read.bi","readthis.ca","reallytinyurl.com","redir.ec","redirects.ca","redirx.com","retwt.me","ri.ms","rickroll.it","riz.gd","rt.nu","ru.ly","rubyurl.com","rurl.org","rww.tw","s4c.in","s7y.us","safe.mn","sameurl.com","sdut.us","shar.es","shink.de","shorl.com","short.ie","short.to","shortlinks.co.uk","shorturl.com","shout.to","show.my","shrinkify.com","shrinkr.com","shrt.fr","shrt.st","shrten.com","shrunkin.com","simurl.com","slate.me","smallr.com","smsh.me","smurl.name","sn.im","snipr.com","snipurl.com","snurl.com","sp2.ro","spedr.com","srnk.net","srs.li","starturl.com","stks.co","su.pr","surl.co.uk","surl.hu","t.cn","t.co","t.lh.com","ta.gd","tbd.ly","tcrn.ch","tgr.me","tgr.ph","tighturl.com","tiniuri.com","tiny.cc","tiny.ly","tiny.pl","tinylink.in","tinyuri.ca","tinyurl.com","tk.","tl.gd","tmi.me","tnij.org","tnw.to","tny.com","to.ly","togoto.us","totc.us","toysr.us","tpm.ly","tr.im","tra.kz","trunc.it","twhub.com","twirl.at","twitclicks.com","twitterurl.net","twitterurl.org","twiturl.de","twurl.cc","twurl.nl","u.mavrev.com","u.nu","u76.org","ub0.cc","ulu.lu","updating.me","ur1.ca","url.az","url.co.uk","url.ie","url360.me","url4.eu","urlborg.com","urlbrief.com","urlcover.com","urlcut.com","urlenco.de","urli.nl","urls.im","urlshorteningservicefortwitter.com","urlx.ie","urlzen.com","usat.ly","use.my","vb.ly","vevo.ly","vgn.am","vl.am","vm.lc","w55.de","wapo.st","wapurl.co.uk","wipi.es","wp.me","x.vu","xr.com","xrl.in","xrl.us","xurl.es","xurl.jp","y.ahoo.it","yatuc.com","ye.pe","yep.it","yfrog.com","yhoo.it","yiyd.com","youtu.be","yuarel.com","z0p.de","zi.ma","zi.mu","zipmyurl.com","zud.me","zurl.ws","zz.gd","zzang.kr","›.ws","✩.ws","✿.ws","❥.ws","➔.ws","➞.ws","➡.ws","➨.ws","➯.ws","➹.ws","➽.ws"];return n("#jqoembeddata").length===0&&n('<span id="jqoembeddata"><\/span>').appendTo("body"),this.each(function(){var h=n(this),s=i&&(!i.indexOf("http://")||!i.indexOf("https://"))?i:h.attr("href"),r,c,l,a,v;if(u?t.onEmbed=u:t.onEmbed||(t.onEmbed=function(i){n.fn.oembed.insertCode(this,t.embedMethod,i)}),s!==null&&s!==undefined){for(c=0,l=f.length;c<l;c++)if(a=new RegExp("://"+f[c]+"/","i"),s.match(a)!==null)return v=n.extend({url:"http://api.longurl.org/v2/expand",dataType:"jsonp",data:{url:s,format:"json"},success:function(i){s=i["long-url"];r=n.fn.oembed.getOEmbedProvider(i["long-url"]);r!==null?(r.params=o(t[r.name])||{},r.maxWidth=t.maxWidth,r.maxHeight=t.maxHeight,e(h,s,r)):t.onProviderNotFound.call(h,s)}},t.ajaxOptions||{}),n.ajax(v),h;r=n.fn.oembed.getOEmbedProvider(s);r!==null?(r.params=o(t[r.name])||{},r.maxWidth=t.maxWidth,r.maxHeight=t.maxHeight,e(h,s,r)):t.onProviderNotFound.call(h,s)}return h})};var t;n.fn.oembed.defaults={maxWidth:null,maxHeight:null,useResponsiveResize:!1,includeHandle:!0,embedMethod:"auto",onProviderNotFound:function(){},beforeEmbed:function(){},afterEmbed:function(){},onEmbed:!1,onError:function(){},ajaxOptions:{timeout:2e3}};n.fn.oembed.insertCode=function(i,r,u){if(u!==null){r=="auto"&&i.attr("href")!==null?r="append":r=="auto"&&(r="replace");switch(r){case"replace":i.replaceWith(u.code);break;case"fill":i.html(u.code);break;case"append":i.wrap('<div class="oembedall-container"><\/div>');var f=i.parent();t.includeHandle&&n('<span class="oembedall-closehide">&darr;<\/span>').insertBefore(i).click(function(){var t=encodeURIComponent(n(this).text());n(this).html(t=="%E2%86%91"?"&darr;":"&uarr;");n(this).parent().children().last().toggle()});f.append("<br/>");try{u.code.clone().appendTo(f)}catch(e){f.append(u.code)}}}};n.fn.oembed.getPhotoCode=function(n,t){var i,r=t.title?t.title:"",u;return r+=t.author_name?" - "+t.author_name:"",r+=t.provider_name?" - "+t.provider_name:"",t.url?i='<div><a href="'+n+"\" target='_blank'><img src=\""+t.url+'" alt="'+r+'"/><\/a><\/div>':t.thumbnail_url?(u=t.thumbnail_url.replace("_s","_b"),i='<div><a href="'+n+"\" target='_blank'><img src=\""+u+'" alt="'+r+'"/><\/a><\/div>'):i=t.provider_name=="Flickr"?'<p><a href="'+n+"\" target='_blank'>"+n+"<\/a><\/p>":"<div>Error loading this picture<\/div>",i};n.fn.oembed.getRichCode=function(n,t){return t.html};n.fn.oembed.getGenericCode=function(n,t){var r=t.title!==null?t.title:n,i='<a href="'+n+'">'+r+"<\/a>";return t.html&&(i+="<div>"+t.html+"<\/div>"),i};n.fn.oembed.getOEmbedProvider=function(t){for(var r,u,f,i=0;i<n.fn.oembed.providers.length;i++)for(r=0,u=n.fn.oembed.providers[i].urlschemes.length;r<u;r++)if(f=new RegExp(n.fn.oembed.providers[i].urlschemes[r],"i"),t.match(f)!==null)return n.fn.oembed.providers[i];return null};n.fn.oembed.OEmbedProvider=function(i,r,u,f,e){this.name=i;this.type=r;this.urlschemes=u;this.apiendpoint=f;this.maxWidth=500;this.maxHeight=400;e=e||{};e.useYQL&&(e.yql=e.useYQL=="xml"?{xpath:"//oembed/html",from:"xml",apiendpoint:this.apiendpoint,url:function(n){return this.apiendpoint+"?format=xml&url="+n},datareturn:function(n){return n.html.replace(/.*\[CDATA\[(.*)\]\]>$/,"$1")||""}}:{from:"json",apiendpoint:this.apiendpoint,url:function(n){return this.apiendpoint+"?format=json&url="+n},datareturn:function(i){var f,o,s;if(i.json.type!="video"&&(i.json.url||i.json.thumbnail_url)&&!i.json.html.indexOf("iframe"))return'<img src="'+(i.json.url||i.json.thumbnail_url)+'" />';if(i.json.html.indexOf("iframe")){i.json.html.indexOf("allowfullscreen>")&&(i.json.html=i.json.html.replace("allowfullscreen>",'allowfullscreen="false">'));var e=n.parseHTML(i.json.html),r=e[0].width,u=e[0].height;return t.maxHeight&&t.maxWidth&&(t.useResponsiveResize?(o=r,s=u,r>t.maxWidth&&(f=t.maxWidth/r,o=t.maxWidth,s=u*f,u=u*f,r=r*f),u>t.maxHeight&&(f=t.maxHeight/u,s=t.maxHeight,o=r*f),u=s,r=o):(u=t.maxHeight,r=t.maxWidth)),e[0].width=r,e[0].height=u,e[0].outerHTML}return i.json.html||""}},this.apiendpoint=null);for(var o in e)this[o]=e[o];this.format=this.format||"json";this.callbackparameter=this.callbackparameter||"callback";this.embedtag=this.embedtag||{tag:""}};n.fn.updateOEmbedProvider=function(t,i,r,u,f){for(var o,e=0;e<n.fn.oembed.providers.length;e++)if(n.fn.oembed.providers[e].name===t&&(i!==null&&(n.fn.oembed.providers[e].type=i),r!==null&&(n.fn.oembed.providers[e].urlschemes=r),u!==null&&(n.fn.oembed.providers[e].apiendpoint=u),f!==null)){n.fn.oembed.providers[e].extraSettings=f;for(o in f)f[o]!==null&&(n.fn.oembed.providers[e][o]=f[o])}};n.fn.oembed.providers=[new n.fn.oembed.OEmbedProvider("youtube","video",["youtube\\.com/watch.+v=[\\w-]+&?","youtu\\.be/[\\w-]+","youtube.com/embed"],r()+"www.youtube.com/embed/$1?wmode=transparent",{templateRegex:/.*(?:v\=|be\/|embed\/)([\w\-]+)&?.*/,embedtag:{tag:"iframe",width:"425",height:"349"}}),new n.fn.oembed.OEmbedProvider("youtubeiframe","video",["youtube.com/embed"],"$1?wmode=transparent",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"425",height:"349"}}),new n.fn.oembed.OEmbedProvider("wistia","video",["wistia.com/m/.+","wistia.com/embed/.+","wi.st/m/.+","wi.st/embed/.+"],"http://fast.wistia.com/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("xtranormal","video",["xtranormal\\.com/watch/.+"],"http://www.xtranormal.com/xtraplayr/$1/$2",{templateRegex:/.*com\/watch\/([\w\-]+)\/([\w\-]+).*/,embedtag:{tag:"iframe",width:"320",height:"269"}}),new n.fn.oembed.OEmbedProvider("scivee","video",["scivee.tv/node/.+"],"http://www.scivee.tv/flash/embedCast.swf?",{templateRegex:/.*tv\/node\/(.+)/,embedtag:{width:"480",height:"400",flashvars:"id=$1&type=3"}}),new n.fn.oembed.OEmbedProvider("veoh","video",["veoh.com/watch/.+"],"http://www.veoh.com/swf/webplayer/WebPlayer.swf?version=AFrontend.5.7.0.1337&permalinkId=$1&player=videodetailsembedded&videoAutoPlay=0&id=anonymous",{templateRegex:/.*watch\/([^\?]+).*/,embedtag:{width:"410",height:"341"}}),new n.fn.oembed.OEmbedProvider("gametrailers","video",["gametrailers\\.com/video/.+"],"http://media.mtvnservices.com/mgid:moses:video:gametrailers.com:$2",{templateRegex:/.*com\/video\/([\w\-]+)\/([\w\-]+).*/,embedtag:{width:"512",height:"288"}}),new n.fn.oembed.OEmbedProvider("funnyordie","video",["funnyordie\\.com/videos/.+"],"http://player.ordienetworks.com/flash/fodplayer.swf?",{templateRegex:/.*videos\/([^\/]+)\/([^\/]+)?/,embedtag:{width:512,height:328,flashvars:"key=$1"}}),new n.fn.oembed.OEmbedProvider("colledgehumour","video",["collegehumor\\.com/video/.+"],"http://www.collegehumor.com/moogaloop/moogaloop.swf?clip_id=$1&use_node_id=true&fullscreen=1",{templateRegex:/.*video\/([^\/]+).*/,embedtag:{width:600,height:338}}),new n.fn.oembed.OEmbedProvider("metacafe","video",["metacafe\\.com/watch/.+"],"http://www.metacafe.com/fplayer/$1/$2.swf",{templateRegex:/.*watch\/(\d+)\/(\w+)\/.*/,embedtag:{width:400,height:345}}),new n.fn.oembed.OEmbedProvider("bambuser","video",["bambuser\\.com/channel/.*/broadcast/.*"],"http://static.bambuser.com/r/player.swf?vid=$1",{templateRegex:/.*bambuser\.com\/channel\/.*\/broadcast\/(\w+).*/,embedtag:{width:512,height:339}}),new n.fn.oembed.OEmbedProvider("twitvid","video",["twitvid\\.com/.+"],"http://www.twitvid.com/embed.php?guid=$1&autoplay=0",{templateRegex:/.*twitvid\.com\/(\w+).*/,embedtag:{tag:"iframe",width:480,height:360}}),new n.fn.oembed.OEmbedProvider("aniboom","video",["aniboom\\.com/animation-video/.+"],"http://api.aniboom.com/e/$1",{templateRegex:/.*animation-video\/(\d+).*/,embedtag:{width:594,height:334}}),new n.fn.oembed.OEmbedProvider("vzaar","video",["vzaar\\.com/videos/.+","vzaar.tv/.+"],"http://view.vzaar.com/$1/player?",{templateRegex:/.*\/(\d+).*/,embedtag:{tag:"iframe",width:576,height:324}}),new n.fn.oembed.OEmbedProvider("snotr","video",["snotr\\.com/video/.+"],"http://www.snotr.com/embed/$1",{templateRegex:/.*\/(\d+).*/,embedtag:{tag:"iframe",width:400,height:330,nocache:1}}),new n.fn.oembed.OEmbedProvider("youku","video",["v.youku.com/v_show/id_.+"],"http://player.youku.com/player.php/sid/$1/v.swf",{templateRegex:/.*id_(.+)\.html.*/,embedtag:{width:480,height:400,nocache:1}}),new n.fn.oembed.OEmbedProvider("tudou","video",["tudou.com/programs/view/.+/"],"http://www.tudou.com/v/$1/v.swf",{templateRegex:/.*view\/(.+)\//,embedtag:{width:480,height:400,nocache:1}}),new n.fn.oembed.OEmbedProvider("embedr","video",["embedr\\.com/playlist/.+"],"http://embedr.com/swf/slider/$1/425/520/default/false/std?",{templateRegex:/.*playlist\/([^\/]+).*/,embedtag:{width:425,height:520}}),new n.fn.oembed.OEmbedProvider("blip","video",["blip\\.tv/.+"],"http://blip.tv/oembed/"),new n.fn.oembed.OEmbedProvider("minoto-video","video",["http://api.minoto-video.com/publishers/.+/videos/.+","http://dashboard.minoto-video.com/main/video/details/.+","http://embed.minoto-video.com/.+"],"http://api.minoto-video.com/services/oembed.json",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("animoto","video",["animoto.com/play/.+"],"http://animoto.com/services/oembed"),new n.fn.oembed.OEmbedProvider("hulu","video",["hulu\\.com/watch/.*"],"http://www.hulu.com/api/oembed.json"),new n.fn.oembed.OEmbedProvider("ustream","video",["ustream\\.tv/recorded/.*"],"http://www.ustream.tv/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("videojug","video",["videojug\\.com/(film|payer|interview).*"],"http://www.videojug.com/oembed.json",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("sapo","video",["videos\\.sapo\\.pt/.*"],"http://videos.sapo.pt/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("vodpod","video",["vodpod.com/watch/.*"],"http://vodpod.com/oembed.js",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("vimeo","video",["www.vimeo.com/groups/.*/videos/.*","www.vimeo.com/.*","vimeo.com/groups/.*/videos/.*","vimeo.com/.*"],"//vimeo.com/api/oembed.json"),new n.fn.oembed.OEmbedProvider("dailymotion","video",["dailymotion\\.com/.+"],"http://www.dailymotion.com/services/oembed"),new n.fn.oembed.OEmbedProvider("5min","video",["www\\.5min\\.com/.+"],"http://api.5min.com/oembed.xml",{useYQL:"xml"}),new n.fn.oembed.OEmbedProvider("National Film Board of Canada","video",["nfb\\.ca/film/.+"],"http://www.nfb.ca/remote/services/oembed/",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("qik","video",["qik\\.com/\\w+"],"http://qik.com/api/oembed.json",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("revision3","video",["revision3\\.com"],"http://revision3.com/api/oembed/"),new n.fn.oembed.OEmbedProvider("dotsub","video",["dotsub\\.com/view/.+"],"http://dotsub.com/services/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("clikthrough","video",["clikthrough\\.com/theater/video/\\d+"],"http://clikthrough.com/services/oembed"),new n.fn.oembed.OEmbedProvider("Kinomap","video",["kinomap\\.com/.+"],"http://www.kinomap.com/oembed"),new n.fn.oembed.OEmbedProvider("VHX","video",["vhx.tv/.+"],"http://vhx.tv/services/oembed.json"),new n.fn.oembed.OEmbedProvider("bambuser","video",["bambuser.com/.+"],"http://api.bambuser.com/oembed/iframe.json"),new n.fn.oembed.OEmbedProvider("justin.tv","video",["justin.tv/.+"],"http://api.justin.tv/api/embed/from_url.json",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("official.fm","rich",["official.fm/.+"],"http://official.fm/services/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("chirbit","rich",["chirb.it/.+"],"http://chirb.it/oembed.json",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("Huffduffer","rich",["huffduffer.com/[-.\\w@]+/\\d+"],"http://huffduffer.com/oembed"),new n.fn.oembed.OEmbedProvider("Spotify","rich",["open.spotify.com/(track|album|user)/"],"https://embed.spotify.com/oembed/"),new n.fn.oembed.OEmbedProvider("shoudio","rich",["shoudio.com/.+","shoud.io/.+"],"http://shoudio.com/api/oembed"),new n.fn.oembed.OEmbedProvider("mixcloud","rich",["mixcloud.com/.+"],r()+"www.mixcloud.com/oembed/",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("rdio.com","rich",["rd.io/.+","rdio.com"],r()+"www.rdio.com/api/oembed/"),new n.fn.oembed.OEmbedProvider("Soundcloud","rich",["soundcloud.com/.+","snd.sc/.+"],r()+"soundcloud.com/oembed",{format:"js"}),new n.fn.oembed.OEmbedProvider("bandcamp","rich",["bandcamp\\.com/album/.+"],null,{yql:{xpath:"//meta[contains(@content, \\'EmbeddedPlayer\\')]",from:"html",datareturn:function(n){return n.meta?'<iframe width="400" height="100" src="'+n.meta.content+'" allowtransparency="true" frameborder="0"><\/iframe>':!1}}}),new n.fn.oembed.OEmbedProvider("deviantart","photo",["deviantart.com/.+","fav.me/.+","deviantart.com/.+"],"http://backend.deviantart.com/oembed",{format:"jsonp"}),new n.fn.oembed.OEmbedProvider("skitch","photo",["skitch.com/.+"],null,{yql:{xpath:"json",from:"json",url:function(n){return"http://skitch.com/oembed/?format=json&url="+n},datareturn:function(t){return n.fn.oembed.getPhotoCode(t.json.url,t.json)}}}),new n.fn.oembed.OEmbedProvider("mobypicture","photo",["mobypicture.com/user/.+/view/.+","moby.to/.+"],"http://api.mobypicture.com/oEmbed"),new n.fn.oembed.OEmbedProvider("flickr","photo",["flickr\\.com/photos/.+"],"http://flickr.com/services/oembed",{callbackparameter:"jsoncallback"}),new n.fn.oembed.OEmbedProvider("photobucket","photo",["photobucket\\.com/(albums|groups)/.+"],r()+"photobucket.com/oembed/"),new n.fn.oembed.OEmbedProvider("instagram","photo",["instagr\\.?am(\\.com)?/.+"],r()+"api.instagram.com/oembed"),new n.fn.oembed.OEmbedProvider("SmugMug","photo",["smugmug.com/[-.\\w@]+/.+"],"http://api.smugmug.com/services/oembed/"),new n.fn.oembed.OEmbedProvider("dribbble","photo",["dribbble.com/shots/.+"],"http://api.dribbble.com/shots/$1?callback=?",{templateRegex:/.*shots\/([\d]+).*/,templateData:function(n){return n.image_teaser_url?'<img src="'+n.image_teaser_url+'"/>':!1}}),new n.fn.oembed.OEmbedProvider("chart.ly","photo",["chart\\.ly/[a-z0-9]{6,8}"],"http://chart.ly/uploads/large_$1.png",{templateRegex:/.*ly\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new n.fn.oembed.OEmbedProvider("circuitlab","photo",["circuitlab.com/circuit/.+"],"https://www.circuitlab.com/circuit/$1/screenshot/540x405/",{templateRegex:/.*circuit\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new n.fn.oembed.OEmbedProvider("23hq","photo",["23hq.com/[-.\\w@]+/photo/.+"],"http://www.23hq.com/23/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("img.ly","photo",["img\\.ly/.+"],"http://img.ly/show/thumb/$1",{templateRegex:/.*ly\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new n.fn.oembed.OEmbedProvider("twitgoo.com","photo",["twitgoo\\.com/.+"],"http://twitgoo.com/show/thumb/$1",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new n.fn.oembed.OEmbedProvider("imgur.com","photo",["imgur\\.com/gallery/.+"],r()+"imgur.com/$1l.jpg",{templateRegex:/.*gallery\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new n.fn.oembed.OEmbedProvider("visual.ly","rich",["visual\\.ly/.+"],null,{yql:{xpath:"//a[@id=\\'gc_article_graphic_image\\']/img",from:"htmlstring"}}),new n.fn.oembed.OEmbedProvider("gravtar","photo",["mailto:.+"],null,{templateRegex:/mailto:([^\/]+).*/,template:function(n,t){return'<img src="http://gravatar.com/avatar/'+t.md5()+'.jpg" alt="on Gravtar" class="jqoaImg">'}}),new n.fn.oembed.OEmbedProvider("twitter","rich",["twitter.com/.+"],"https://api.twitter.com/1/statuses/oembed.json?id="),new n.fn.oembed.OEmbedProvider("gmep","rich",["gmep.imeducate.com/.*","gmep.org/.*"],"http://gmep.org/oembed.json"),new n.fn.oembed.OEmbedProvider("urtak","rich",["urtak.com/(u|clr)/.+"],"http://oembed.urtak.com/1/oembed"),new n.fn.oembed.OEmbedProvider("cacoo","rich",["cacoo.com/.+"],"http://cacoo.com/oembed.json"),new n.fn.oembed.OEmbedProvider("dailymile","rich",["dailymile.com/people/.*/entries/.*"],"http://api.dailymile.com/oembed"),new n.fn.oembed.OEmbedProvider("dipity","rich",["dipity.com/timeline/.+"],"http://www.dipity.com/oembed/timeline/",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("sketchfab","rich",["sketchfab.com/show/.+"],"http://sketchfab.com/oembed",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("speakerdeck","rich",["speakerdeck.com/.+"],"http://speakerdeck.com/oembed.json",{useYQL:"json"}),new n.fn.oembed.OEmbedProvider("popplet","rich",["popplet.com/app/.*"],"http://popplet.com/app/Popplet_Alpha.swf?page_id=$1&em=1",{templateRegex:/.*#\/([^\/]+).*/,embedtag:{width:460,height:460}}),new n.fn.oembed.OEmbedProvider("pearltrees","rich",["pearltrees.com/.*"],"http://cdn.pearltrees.com/s/embed/getApp?",{templateRegex:/.*N-f=1_(\d+).*N-p=(\d+).*/,embedtag:{width:460,height:460,flashvars:"lang=en_US&amp;embedId=pt-embed-$1-693&amp;treeId=$1&amp;pearlId=$2&amp;treeTitle=Diagrams%2FVisualization&amp;site=www.pearltrees.com%2FF"}}),new n.fn.oembed.OEmbedProvider("prezi","rich",["prezi.com/.*"],"http://prezi.com/bin/preziloader.swf?",{templateRegex:/.*com\/([^\/]+)\/.*/,embedtag:{width:550,height:400,flashvars:"prezi_id=$1&amp;lock_to_path=0&amp;color=ffffff&amp;autoplay=no&amp;autohide_ctrls=0"}}),new n.fn.oembed.OEmbedProvider("tourwrist","rich",["tourwrist.com/tours/.+"],null,{templateRegex:/.*tours.([\d]+).*/,template:function(n,t){return setTimeout(function(){loadEmbeds&&loadEmbeds()},2e3),"<div id='"+t+"' class='tourwrist-tour-embed direct'><\/div> <script type='text/javascript' src='http://tourwrist.com/tour_embed.js'><\/script>"}}),new n.fn.oembed.OEmbedProvider("meetup","rich",["meetup\\.(com|ps)/.+"],r()+"api.meetup.com/oembed"),new n.fn.oembed.OEmbedProvider("ebay","rich",["ebay\\.*"],r()+"togo.ebay.com/togo/togo.swf?2008013100",{templateRegex:/.*\/([^\/]+)\/(\d{10,13}).*/,embedtag:{width:355,height:300,flashvars:"base=http://togo.ebay.com/togo/&lang=en-us&mode=normal&itemid=$2&query=$1"}}),new n.fn.oembed.OEmbedProvider("wikipedia","rich",["wikipedia.org/wiki/.+"],"http://$1.wikipedia.org/w/api.php?action=parse&page=$2&format=json&section=0&callback=?",{templateRegex:/.*\/\/([\w]+).*\/wiki\/([^\/]+).*/,templateData:function(n){if(!n.parse)return!1;var t=n.parse.text["*"].replace(/href="\/wiki/g,'href="http://en.wikipedia.org/wiki');return'<div id="content"><h3><a class="nav-link" href="http://en.wikipedia.org/wiki/'+n.parse.displaytitle+'">'+n.parse.displaytitle+"<\/a><\/h3>"+t+"<\/div>"}}),new n.fn.oembed.OEmbedProvider("imdb","rich",["imdb.com/title/.+"],"http://www.imdbapi.com/?i=$1&callback=?",{templateRegex:/.*\/title\/([^\/]+).*/,templateData:function(n){return n.Title?'<div id="content"><h3><a class="nav-link" href="http://imdb.com/title/'+n.ID+'/">'+n.Title+"<\/a> ("+n.Year+")<\/h3><p>Starring: "+n.Actors+'<\/p><div id="photo-wrap" style="margin: auto;width:600px;height:450px;"><img class="photo" id="photo-display" src="'+n.Poster+'" alt="'+n.Title+'"><\/div> <div id="view-photo-caption">'+n.Plot+"<\/div><\/div>":!1}}),new n.fn.oembed.OEmbedProvider("livejournal","rich",["livejournal.com/"],"http://ljpic.seacrow.com/json/$2$4?jsonp=?",{templateRegex:/(http:\/\/(((?!users).)+)\.livejournal\.com|.*users\.livejournal\.com\/([^\/]+)).*/,templateData:function(n){return!!n.username&&'<div><img src="'+n.image+'" align="left" style="margin-right: 1em;" /><span class="oembedall-ljuser"><a href="http://'+n.username+'.livejournal.com/profile"><img src="http://www.livejournal.com/img/userinfo.gif" alt="[info]" width="17" height="17" /><\/a><a href="http://'+n.username+'.livejournal.com/">'+n.username+"<\/a><\/span><br />"+n.name+"<\/div>"}}),new n.fn.oembed.OEmbedProvider("circuitbee","rich",["circuitbee\\.com/circuit/view/.+"],"http://c.circuitbee.com/build/r/schematic-embed.html?id=$1",{templateRegex:/.*circuit\/view\/(\d+).*/,embedtag:{tag:"iframe",width:"500",height:"350"}}),new n.fn.oembed.OEmbedProvider("googlecalendar","rich",["www.google.com/calendar/embed?.+"],"$1",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"800",height:"600"}}),new n.fn.oembed.OEmbedProvider("jsfiddle","rich",["jsfiddle.net/[^/]+/?"],"http://jsfiddle.net/$1/embedded/result,js,resources,html,css/?",{templateRegex:/.*net\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"300"}}),new n.fn.oembed.OEmbedProvider("jsbin","rich",["jsbin.com/.+"],"http://jsbin.com/$1/?",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"300"}}),new n.fn.oembed.OEmbedProvider("jotform","rich",["form.jotform.co/form/.+"],"$1?",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"100%",height:"507"}}),new n.fn.oembed.OEmbedProvider("reelapp","rich",["reelapp\\.com/.+"],"http://www.reelapp.com/$1/embed",{templateRegex:/.*com\/(\S{6}).*/,embedtag:{tag:"iframe",width:"400",height:"338"}}),new n.fn.oembed.OEmbedProvider("linkedin","rich",["linkedin.com/pub/.+"],"https://www.linkedin.com/cws/member/public_profile?public_profile_url=$1&format=inline&isFramed=true",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"368px",height:"auto"}}),new n.fn.oembed.OEmbedProvider("timetoast","rich",["timetoast.com/timelines/[0-9]+"],"http://www.timetoast.com/flash/TimelineViewer.swf?passedTimelines=$1",{templateRegex:/.*timelines\/([0-9]*)/,embedtag:{width:550,height:400,nocache:1}}),new n.fn.oembed.OEmbedProvider("pastebin","rich",["pastebin\\.com/[\\S]{8}"],"http://pastebin.com/embed_iframe.php?i=$1",{templateRegex:/.*\/(\S{8}).*/,embedtag:{tag:"iframe",width:"100%",height:"auto"}}),new n.fn.oembed.OEmbedProvider("mixlr","rich",["mixlr.com/.+"],"http://mixlr.com/embed/$1?autoplay=ae",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"auto"}}),new n.fn.oembed.OEmbedProvider("pastie","rich",["pastie\\.org/pastes/.+"],null,{yql:{xpath:'//pre[@class="textmate-source"]'}}),new n.fn.oembed.OEmbedProvider("github","rich",["gist.github.com/.+"],"https://github.com/api/oembed"),new n.fn.oembed.OEmbedProvider("github","rich",["github.com/[-.\\w@]+/[-.\\w@]+"],"https://api.github.com/repos/$1/$2?callback=?",{templateRegex:/.*\/([^\/]+)\/([^\/]+).*/,templateData:function(n){return n.data.html_url?'<div class="oembedall-githubrepos"><ul class="oembedall-repo-stats"><li>'+n.data.language+'<\/li><li class="oembedall-watchers"><a title="Watchers" href="'+n.data.html_url+'/watchers">&#x25c9; '+n.data.watchers+'<\/a><\/li><li class="oembedall-forks"><a title="Forks" href="'+n.data.html_url+'/network">&#x0265; '+n.data.forks+'<\/a><\/li><\/ul><h3><a href="'+n.data.html_url+'">'+n.data.name+'<\/a><\/h3><div class="oembedall-body"><p class="oembedall-description">'+n.data.description+'<\/p><p class="oembedall-updated-at">Last updated: '+n.data.pushed_at+"<\/p><\/div><\/div>":!1}}),new n.fn.oembed.OEmbedProvider("facebook","rich",["facebook.com/(people/[^\\/]+/\\d+|[^\\/]+$)"],"https://graph.facebook.com/$2$3/?callback=?",{templateRegex:/.*facebook.com\/(people\/[^\/]+\/(\d+).*|([^\/]+$))/,templateData:function(n){if(!n.id)return!1;var t='<div class="oembedall-facebook1"><div class="oembedall-facebook2"><a href="http://www.facebook.com/">facebook<\/a> ';return t+=n.from?'<a href="http://www.facebook.com/'+n.from.id+'">'+n.from.name+"<\/a>":n.link?'<a href="'+n.link+'">'+n.name+"<\/a>":n.username?'<a href="http://www.facebook.com/'+n.username+'">'+n.name+"<\/a>":'<a href="http://www.facebook.com/'+n.id+'">'+n.name+"<\/a>",t+='<\/div><div class="oembedall-facebookBody"><div class="contents">',t+=n.picture?'<a href="'+n.link+'"><img src="'+n.picture+'"><\/a>':'<img src="https://graph.facebook.com/'+n.id+'/picture">',n.from&&(t+='<a href="'+n.link+'">'+n.name+"<\/a>"),n.founded&&(t+="Founded: <strong>"+n.founded+"<\/strong><br>"),n.category&&(t+="Category: <strong>"+n.category+"<\/strong><br>"),n.website&&(t+='Website: <strong><a href="'+n.website+'">'+n.website+"<\/a><\/strong><br>"),n.gender&&(t+="Gender: <strong>"+n.gender+"<\/strong><br>"),n.description&&(t+=n.description+"<br>"),t+"<\/div><\/div>"}}),new n.fn.oembed.OEmbedProvider("stackoverflow","rich",["stackoverflow.com/questions/[\\d]+"],"http://api.stackoverflow.com/1.1/questions/$1?body=true&jsonp=?",{templateRegex:/.*questions\/([\d]+).*/,templateData:function(t){if(!t.questions)return!1;var r=t.questions[0],f=n(r.body).text(),u='<div class="oembedall-stoqembed"><div class="oembedall-statscontainer"><div class="oembedall-statsarrow"><\/div><div class="oembedall-stats"><div class="oembedall-vote"><div class="oembedall-votes"><span class="oembedall-vote-count-post"><strong>'+(r.up_vote_count-r.down_vote_count)+'<\/strong><\/span><div class="oembedall-viewcount">vote(s)<\/div><\/div><\/div><div class="oembedall-status"><strong>'+r.answer_count+'<\/strong>answer<\/div><\/div><div class="oembedall-views">'+r.view_count+' view(s)<\/div><\/div><div class="oembedall-summary"><h3><a class="oembedall-question-hyperlink" href="http://stackoverflow.com/questions/'+r.question_id+'/">'+r.title+'<\/a><\/h3><div class="oembedall-excerpt">'+f.substring(0,100)+'...<\/div><div class="oembedall-tags">';for(i in r.tags)u+='<a title="" class="oembedall-post-tag" href="http://stackoverflow.com/questions/tagged/'+r.tags[i]+'">'+r.tags[i]+"<\/a>";return u+('<\/div><div class="oembedall-fr"><div class="oembedall-user-info"><div class="oembedall-user-gravatar32"><a href="http://stackoverflow.com/users/'+r.owner.user_id+"/"+r.owner.display_name+'"><img width="32" height="32" alt="" src="http://www.gravatar.com/avatar/'+r.owner.email_hash+'?s=32&amp;d=identicon&amp;r=PG"><\/a><\/div><div class="oembedall-user-details"><a href="http://stackoverflow.com/users/'+r.owner.user_id+"/"+r.owner.display_name+'">'+r.owner.display_name+'<\/a><br><span title="reputation score" class="oembedall-reputation-score">'+r.owner.reputation+"<\/span><\/div><\/div><\/div><\/div><\/div>")}}),new n.fn.oembed.OEmbedProvider("wordpress","rich",["wordpress\\.com/.+","blogs\\.cnn\\.com/.+","techcrunch\\.com/.+","wp\\.me/.+"],"http://public-api.wordpress.com/oembed/1.0/?for=jquery-oembed-all"),new n.fn.oembed.OEmbedProvider("screenr","rich",["screenr.com"],"http://www.screenr.com/embed/$1",{templateRegex:/.*\/([^\/]+).*/,embedtag:{tag:"iframe",width:"650",height:396}}),new n.fn.oembed.OEmbedProvider("gigpans","rich",["gigapan\\.org/[-.\\w@]+/\\d+"],"http://gigapan.org/gigapans/$1/options/nosnapshots/iframe/flash.html",{templateRegex:/.*\/(\d+)\/?.*/,embedtag:{tag:"iframe",width:"100%",height:400}}),new n.fn.oembed.OEmbedProvider("scribd","rich",["scribd\\.com/.+"],r()+"www.scribd.com/embeds/$1/content?start_page=1&view_mode=list",{templateRegex:/.*doc\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:600}}),new n.fn.oembed.OEmbedProvider("kickstarter","rich",["kickstarter\\.com/projects/.+"],"$1/widget/card.html",{templateRegex:/([^\?]+).*/,embedtag:{tag:"iframe",width:"220",height:380}}),new n.fn.oembed.OEmbedProvider("amazon","rich",["amzn.com/B+","amazon.com.*/(B\\S+)($|\\/.*)"],r()+"rcm.amazon.com/e/cm?t=_APIKEY_&o=1&p=8&l=as1&asins=$1&ref=qf_br_asin_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr",{apikey:!0,templateRegex:/.*\/(B[0-9A-Z]+)($|\/.*)/,embedtag:{tag:"iframe",width:"120px",height:"240px"}}),new n.fn.oembed.OEmbedProvider("slideshare","rich",["slideshare.net"],r()+"www.slideshare.net/api/oembed/2",{format:"jsonp"}),new n.fn.oembed.OEmbedProvider("roomsharejp","rich",["roomshare\\.jp/(en/)?post/.*"],"http://roomshare.jp/oembed.json"),new n.fn.oembed.OEmbedProvider("lanyard","rich",["lanyrd.com/\\d+/.+"],null,{yql:{xpath:'(//div[@class="primary"])[1]',from:"htmlstring",datareturn:function(n){return n.result?'<div class="oembedall-lanyard">'+n.result+"<\/div>":!1}}}),new n.fn.oembed.OEmbedProvider("asciiartfarts","rich",["asciiartfarts.com/\\d+.html"],null,{yql:{xpath:"//pre/font",from:"htmlstring",datareturn:function(n){return n.result?'<pre style="background-color:000;">'+n.result+"<\/div>":!1}}}),new n.fn.oembed.OEmbedProvider("opengraph","rich",[".*"],null,{yql:{xpath:"//meta|//title|//link",from:"html",datareturn:function(i){var r,u,f;return(!i["og:title"]&&i.title&&i.description&&(i["og:title"]=i.title),!i["og:title"]&&!i.title)?!1:(r=n("<p/>"),i["og:video"]?(u=n('<embed src="'+i["og:video"]+'"/>'),u.attr("type",i["og:video:type"]||"application/x-shockwave-flash").css("max-height",t.maxHeight||"auto").css("max-width",t.maxWidth||"auto"),i["og:video:width"]&&u.attr("width",i["og:video:width"]),i["og:video:height"]&&u.attr("height",i["og:video:height"]),r.append(u)):i["og:image"]&&(f=n('<img src="'+i["og:image"]+'">'),f.css("max-height",t.maxHeight||"auto").css("max-width",t.maxWidth||"auto"),i["og:image:width"]&&f.attr("width",i["og:image:width"]),i["og:image:height"]&&f.attr("height",i["og:image:height"]),r.append(f)),i["og:title"]&&r.append("<b>"+i["og:title"]+"<\/b><br/>"),i["og:description"]?r.append(i["og:description"]+"<br/>"):i.description&&r.append(i.description+"<br/>"),r)}}})]})(jQuery);String.prototype.md5=function(){var u=function(n,t){var i=(n&65535)+(t&65535),r=(n>>16)+(t>>16)+(i>>16);return r<<16|i&65535},e=function(n,t){return n<<t|n>>>32-t},f=function(n,t,i,r,f,o){return u(e(u(u(t,n),u(r,o)),f),i)},n=function(n,t,i,r,u,e,o){return f(t&i|~t&r,n,t,u,e,o)},t=function(n,t,i,r,u,e,o){return f(t&r|i&~r,n,t,u,e,o)},i=function(n,t,i,r,u,e,o){return f(t^i^r,n,t,u,e,o)},r=function(n,t,i,r,u,e,o){return f(i^(t|~r),n,t,u,e,o)},o=function(f){for(var l,a,v,y,p=f.length,e=1732584193,o=-271733879,s=-1732584194,h=271733878,c=0;c<p;c+=16)l=e,a=o,v=s,y=h,e=n(e,o,s,h,f[c+0],7,-680876936),h=n(h,e,o,s,f[c+1],12,-389564586),s=n(s,h,e,o,f[c+2],17,606105819),o=n(o,s,h,e,f[c+3],22,-1044525330),e=n(e,o,s,h,f[c+4],7,-176418897),h=n(h,e,o,s,f[c+5],12,1200080426),s=n(s,h,e,o,f[c+6],17,-1473231341),o=n(o,s,h,e,f[c+7],22,-45705983),e=n(e,o,s,h,f[c+8],7,1770035416),h=n(h,e,o,s,f[c+9],12,-1958414417),s=n(s,h,e,o,f[c+10],17,-42063),o=n(o,s,h,e,f[c+11],22,-1990404162),e=n(e,o,s,h,f[c+12],7,1804603682),h=n(h,e,o,s,f[c+13],12,-40341101),s=n(s,h,e,o,f[c+14],17,-1502002290),o=n(o,s,h,e,f[c+15],22,1236535329),e=t(e,o,s,h,f[c+1],5,-165796510),h=t(h,e,o,s,f[c+6],9,-1069501632),s=t(s,h,e,o,f[c+11],14,643717713),o=t(o,s,h,e,f[c+0],20,-373897302),e=t(e,o,s,h,f[c+5],5,-701558691),h=t(h,e,o,s,f[c+10],9,38016083),s=t(s,h,e,o,f[c+15],14,-660478335),o=t(o,s,h,e,f[c+4],20,-405537848),e=t(e,o,s,h,f[c+9],5,568446438),h=t(h,e,o,s,f[c+14],9,-1019803690),s=t(s,h,e,o,f[c+3],14,-187363961),o=t(o,s,h,e,f[c+8],20,1163531501),e=t(e,o,s,h,f[c+13],5,-1444681467),h=t(h,e,o,s,f[c+2],9,-51403784),s=t(s,h,e,o,f[c+7],14,1735328473),o=t(o,s,h,e,f[c+12],20,-1926607734),e=i(e,o,s,h,f[c+5],4,-378558),h=i(h,e,o,s,f[c+8],11,-2022574463),s=i(s,h,e,o,f[c+11],16,1839030562),o=i(o,s,h,e,f[c+14],23,-35309556),e=i(e,o,s,h,f[c+1],4,-1530992060),h=i(h,e,o,s,f[c+4],11,1272893353),s=i(s,h,e,o,f[c+7],16,-155497632),o=i(o,s,h,e,f[c+10],23,-1094730640),e=i(e,o,s,h,f[c+13],4,681279174),h=i(h,e,o,s,f[c+0],11,-358537222),s=i(s,h,e,o,f[c+3],16,-722521979),o=i(o,s,h,e,f[c+6],23,76029189),e=i(e,o,s,h,f[c+9],4,-640364487),h=i(h,e,o,s,f[c+12],11,-421815835),s=i(s,h,e,o,f[c+15],16,530742520),o=i(o,s,h,e,f[c+2],23,-995338651),e=r(e,o,s,h,f[c+0],6,-198630844),h=r(h,e,o,s,f[c+7],10,1126891415),s=r(s,h,e,o,f[c+14],15,-1416354905),o=r(o,s,h,e,f[c+5],21,-57434055),e=r(e,o,s,h,f[c+12],6,1700485571),h=r(h,e,o,s,f[c+3],10,-1894986606),s=r(s,h,e,o,f[c+10],15,-1051523),o=r(o,s,h,e,f[c+1],21,-2054922799),e=r(e,o,s,h,f[c+8],6,1873313359),h=r(h,e,o,s,f[c+15],10,-30611744),s=r(s,h,e,o,f[c+6],15,-1560198380),o=r(o,s,h,e,f[c+13],21,1309151649),e=r(e,o,s,h,f[c+4],6,-145523070),h=r(h,e,o,s,f[c+11],10,-1120210379),s=r(s,h,e,o,f[c+2],15,718787259),o=r(o,s,h,e,f[c+9],21,-343485551),e=u(e,l),o=u(o,a),s=u(s,v),h=u(h,y);return[e,o,s,h]},s=function(n){for(var i="0123456789abcdef",r="",u=n.length*4,t=0;t<u;t++)r+=i.charAt(n[t>>2]>>t%4*8+4&15)+i.charAt(n[t>>2]>>t%4*8&15);return r},h=function(n){for(var u=(n.length+8>>6)+1,i=[],e=u*16,t,f=n.length,r=0;r<e;r++)i.push(0);for(t=0;t<f;t++)i[t>>2]|=(n.charCodeAt(t)&255)<<t%4*8;return i[t>>2]|=128<<t%4*8,i[u*16-2]=f*8,i};return s(o(h(this)))};
diff --git a/sources/plugins/oembed/plugin.js b/sources/plugins/oembed/plugin.js
new file mode 100644
index 0000000..9ad1ead
--- /dev/null
+++ b/sources/plugins/oembed/plugin.js
@@ -0,0 +1,446 @@
1/**
2* oEmbed Plugin plugin
3* Licensed under the MIT license
4* jQuery Embed Plugin: http://code.google.com/p/jquery-oembed/ (MIT License)
5* Plugin for: http://ckeditor.com/license (GPL/LGPL/MPL: http://ckeditor.com/license)
6*/
7
8(function() {
9 CKEDITOR.plugins.add('oembed', {
10 icons: 'oembed',
11 hidpi: true,
12 requires: 'widget,dialog',
13 lang: 'de,en,fr,nl,pl,pt-br,ru,tr', // %REMOVE_LINE_CORE%
14 version: 1.17,
15 init: function(editor) {
16 // Load jquery?
17 loadjQueryLibaries();
18
19 CKEDITOR.tools.extend(CKEDITOR.editor.prototype, {
20 oEmbed: function(url, maxWidth, maxHeight, responsiveResize) {
21
22 if (url.length < 1 || url.indexOf('http') < 0) {
23 alert(editor.lang.oembed.invalidUrl);
24 return false;
25 }
26
27 function embed() {
28 if (maxWidth == null || maxWidth == 'undefined') {
29 maxWidth = null;
30 }
31
32 if (maxHeight == null || maxHeight == 'undefined') {
33 maxHeight = null;
34 }
35
36 if (responsiveResize == null || responsiveResize == 'undefined') {
37 responsiveResize = false;
38 }
39
40 embedCode(url, editor, false, maxWidth, maxHeight, responsiveResize);
41 }
42
43 if (typeof(jQuery.fn.oembed) === 'undefined') {
44 CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('oembed') + 'libs/jquery.oembed.min.js'), function() {
45 embed();
46 });
47 } else {
48 embed();
49 }
50
51 return true;
52 }
53 });
54
55 editor.widgets.add('oembed', {
56 draggable: false,
57 mask: true,
58 dialog: 'oembed',
59 allowedContent: {
60 div: {
61 styles: 'text-align,float',
62 attributes: '*',
63 classes: editor.config.oembed_WrapperClass != null ? editor.config.oembed_WrapperClass : "embeddedContent"
64 },
65 'div(embeddedContent,oembed-provider-*) iframe': {
66 attributes: '*'
67 },
68 'div(embeddedContent,oembed-provider-*) blockquote': {
69 attributes: '*'
70 },
71 'div(embeddedContent,oembed-provider-*) script': {
72 attributes: '*'
73 }
74 },
75 template:
76 '<div class="' + (editor.config.oembed_WrapperClass != null ? editor.config.oembed_WrapperClass : "embeddedContent") + '">' +
77 '</div>',
78 upcast: function(element) {
79 return element.name == 'div' && element.hasClass(editor.config.oembed_WrapperClass != null ? editor.config.oembed_WrapperClass : "embeddedContent");
80 },
81 init: function() {
82 var data = {
83 oembed: this.element.data('oembed') || '',
84 resizeType: this.element.data('resizeType') || 'noresize',
85 maxWidth: this.element.data('maxWidth') || 560,
86 maxHeight: this.element.data('maxHeight') || 315,
87 align: this.element.data('align') || 'none',
88 oembed_provider: this.element.data('oembed_provider') || ''
89 };
90
91 this.setData(data);
92 this.element.addClass('oembed-provider-' + data.oembed_provider);
93
94 this.on('dialog', function(evt) {
95 evt.data.widget = this;
96 }, this);
97 }
98 });
99
100 editor.ui.addButton('oembed', {
101 label: editor.lang.oembed.button,
102 command: 'oembed',
103 toolbar: 'insert,10',
104 icon: this.path + "icons/" + (CKEDITOR.env.hidpi ? "hidpi/" : "") + "oembed.png"
105 });
106
107 var resizeTypeChanged = function() {
108 var dialog = this.getDialog(),
109 resizetype = this.getValue(),
110 maxSizeBox = dialog.getContentElement('general', 'maxSizeBox').getElement(),
111 sizeBox = dialog.getContentElement('general', 'sizeBox').getElement();
112
113 if (resizetype == 'noresize') {
114 maxSizeBox.hide();
115
116 sizeBox.hide();
117 } else if (resizetype == "custom") {
118 maxSizeBox.hide();
119
120 sizeBox.show();
121 } else {
122 maxSizeBox.show();
123
124 sizeBox.hide();
125 }
126
127 };
128
129 String.prototype.beginsWith = function(string) {
130 return (this.indexOf(string) === 0);
131 };
132
133 function loadjQueryLibaries() {
134 if (typeof(jQuery) === 'undefined') {
135 CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
136 jQuery.noConflict();
137 if (typeof(jQuery.fn.oembed) === 'undefined') {
138 CKEDITOR.scriptLoader.load(
139 CKEDITOR.getUrl(CKEDITOR.plugins.getPath('oembed') + 'libs/jquery.oembed.min.js')
140 );
141 }
142 });
143
144 } else if (typeof(jQuery.fn.oembed) === 'undefined') {
145 CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('oembed') + 'libs/jquery.oembed.min.js'));
146 }
147 }
148
149 function embedCode(url, instance, maxWidth, maxHeight, responsiveResize, resizeType, align, widget) {
150 jQuery('body').oembed(url, {
151 onEmbed: function(e) {
152 var elementAdded = false,
153 provider = jQuery.fn.oembed.getOEmbedProvider(url);
154
155 widget.element.data('resizeType', resizeType);
156 if (resizeType == "responsive" || resizeType == "custom") {
157 widget.element.data('maxWidth', maxWidth);
158 widget.element.data('maxHeight', maxHeight);
159 }
160
161 widget.element.data('align', align);
162
163 // TODO handle align
164 if (align == 'center') {
165 if (!widget.inline)
166 widget.element.setStyle('text-align', 'center');
167
168 widget.element.removeStyle('float');
169 } else {
170 if (!widget.inline)
171 widget.element.removeStyle('text-align');
172
173 if (align == 'none')
174 widget.element.removeStyle('float');
175 else
176 widget.element.setStyle('float', align);
177 }
178
179 if (typeof e.code === 'string') {
180 if (widget.element.$.firstChild) {
181 widget.element.$.removeChild(widget.element.$.firstChild);
182 }
183
184 widget.element.appendHtml(e.code);
185 widget.element.data('oembed', url);
186 widget.element.data('oembed_provider', provider.name);
187 widget.element.addClass('oembed-provider-' + provider.name);
188
189 elementAdded = true;
190 } else if (typeof e.code[0].outerHTML === 'string') {
191
192 if (widget.element.$.firstChild) {
193 widget.element.$.removeChild(widget.element.$.firstChild);
194 }
195
196 widget.element.appendHtml(e.code[0].outerHTML);
197 widget.element.data('oembed', url);
198 widget.element.data('oembed_provider', provider.name);
199 widget.element.addClass('oembed-provider-' + provider.name);
200
201 elementAdded = true;
202 } else {
203 alert(editor.lang.oembed.noEmbedCode);
204 }
205 },
206 onError: function(externalUrl) {
207 if (externalUrl.indexOf("vimeo.com") > 0) {
208 alert(editor.lang.oembed.noVimeo);
209 } else {
210 alert(editor.lang.oembed.Error);
211 }
212
213 },
214 maxHeight: maxHeight,
215 maxWidth: maxWidth,
216 useResponsiveResize: responsiveResize,
217 embedMethod: 'editor'
218 });
219 }
220
221 CKEDITOR.dialog.add('oembed', function(editor) {
222 return {
223 title: editor.lang.oembed.title,
224 minWidth: CKEDITOR.env.ie && CKEDITOR.env.quirks ? 568 : 550,
225 minHeight: 155,
226 onShow: function() {
227 var data = {
228 oembed: this.widget.element.data('oembed') || '',
229 resizeType: this.widget.element.data('resizeType') || 'noresize',
230 maxWidth: this.widget.element.data('maxWidth'),
231 maxHeight: this.widget.element.data('maxHeight'),
232 align: this.widget.element.data('align') || 'none'
233 };
234
235 this.widget.setData(data);
236
237 this.getContentElement('general', 'resizeType').setValue(data.resizeType);
238
239 this.getContentElement('general', 'align').setValue(data.align);
240
241 var resizetype = this.getContentElement('general', 'resizeType').getValue(),
242 maxSizeBox = this.getContentElement('general', 'maxSizeBox').getElement(),
243 sizeBox = this.getContentElement('general', 'sizeBox').getElement();
244
245 if (resizetype == 'noresize') {
246 maxSizeBox.hide();
247 sizeBox.hide();
248 } else if (resizetype == "custom") {
249 maxSizeBox.hide();
250
251 sizeBox.show();
252 } else {
253 maxSizeBox.show();
254
255 sizeBox.hide();
256 }
257 },
258
259 onOk: function() {
260 },
261 contents: [
262 {
263 label: editor.lang.common.generalTab,
264 id: 'general',
265 elements: [
266 {
267 type: 'html',
268 id: 'oembedHeader',
269 html: '<div style="white-space:normal;width:500px;padding-bottom:10px">' + editor.lang.oembed.pasteUrl + '</div>'
270 }, {
271 type: 'text',
272 id: 'embedCode',
273 focus: function() {
274 this.getElement().focus();
275 },
276 label: editor.lang.oembed.url,
277 title: editor.lang.oembed.pasteUrl,
278 setup: function(widget) {
279 if (widget.data.oembed) {
280 this.setValue(widget.data.oembed);
281 }
282 },
283 commit: function(widget) {
284 var dialog = CKEDITOR.dialog.getCurrent(),
285 inputCode = dialog.getValueOf('general', 'embedCode').replace(/\s/g, ""),
286 resizeType = dialog.getContentElement('general', 'resizeType').
287 getValue(),
288 align = dialog.getContentElement('general', 'align').
289 getValue(),
290 maxWidth = null,
291 maxHeight = null,
292 responsiveResize = false,
293 editorInstance = dialog.getParentEditor();
294
295 if (inputCode.length < 1 || inputCode.indexOf('http') < 0) {
296 alert(editor.lang.oembed.invalidUrl);
297 return false;
298 }
299
300 if (resizeType == "noresize") {
301 responsiveResize = false;
302 maxWidth = null;
303 maxHeight = null;
304 } else if (resizeType == "responsive") {
305 maxWidth = dialog.getContentElement('general', 'maxWidth').
306 getInputElement().
307 getValue();
308 maxHeight = dialog.getContentElement('general', 'maxHeight').
309 getInputElement().
310 getValue();
311
312 responsiveResize = true;
313 } else if (resizeType == "custom") {
314 maxWidth = dialog.getContentElement('general', 'width').
315 getInputElement().
316 getValue();
317 maxHeight = dialog.getContentElement('general', 'height').
318 getInputElement().
319 getValue();
320
321 responsiveResize = false;
322 }
323
324 embedCode(inputCode, editorInstance, maxWidth, maxHeight, responsiveResize, resizeType, align, widget);
325
326 widget.setData('oembed', inputCode);
327 widget.setData('resizeType', resizeType);
328 widget.setData('align', align);
329 widget.setData('maxWidth', maxWidth);
330 widget.setData('maxHeight', maxHeight);
331 }
332 }, {
333 type: 'hbox',
334 widths: ['50%', '50%'],
335 children: [
336 {
337 id: 'resizeType',
338 type: 'select',
339 label: editor.lang.oembed.resizeType,
340 'default': 'noresize',
341 setup: function(widget) {
342 if (widget.data.resizeType) {
343 this.setValue(widget.data.resizeType);
344 }
345 },
346 items: [
347 [editor.lang.oembed.noresize, 'noresize'],
348 [editor.lang.oembed.responsive, 'responsive'],
349 [editor.lang.oembed.custom, 'custom']
350 ],
351 onChange: resizeTypeChanged
352 }, {
353 type: 'hbox',
354 id: 'maxSizeBox',
355 widths: ['120px', '120px'],
356 style: 'float:left;position:absolute;left:58%;width:200px',
357 children: [
358 {
359 type: 'text',
360 width: '100px',
361 id: 'maxWidth',
362 'default': editor.config.oembed_maxWidth != null ? editor.config.oembed_maxWidth : '560',
363 label: editor.lang.oembed.maxWidth,
364 title: editor.lang.oembed.maxWidthTitle,
365 setup: function(widget) {
366 if (widget.data.maxWidth) {
367 this.setValue(widget.data.maxWidth);
368 }
369 }
370 }, {
371 type: 'text',
372 id: 'maxHeight',
373 width: '120px',
374 'default': editor.config.oembed_maxHeight != null ? editor.config.oembed_maxHeight : '315',
375 label: editor.lang.oembed.maxHeight,
376 title: editor.lang.oembed.maxHeightTitle,
377 setup: function(widget) {
378 if (widget.data.maxHeight) {
379 this.setValue(widget.data.maxHeight);
380 }
381 }
382 }
383 ]
384 }, {
385 type: 'hbox',
386 id: 'sizeBox',
387 widths: ['120px', '120px'],
388 style: 'float:left;position:absolute;left:58%;width:200px',
389 children: [
390 {
391 type: 'text',
392 id: 'width',
393 width: '100px',
394 'default': editor.config.oembed_maxWidth != null ? editor.config.oembed_maxWidth : '560',
395 label: editor.lang.oembed.width,
396 title: editor.lang.oembed.widthTitle,
397 setup: function(widget) {
398 if (widget.data.maxWidth) {
399 this.setValue(widget.data.maxWidth);
400 }
401 }
402 }, {
403 type: 'text',
404 id: 'height',
405 width: '120px',
406 'default': editor.config.oembed_maxHeight != null ? editor.config.oembed_maxHeight : '315',
407 label: editor.lang.oembed.height,
408 title: editor.lang.oembed.heightTitle,
409 setup: function(widget) {
410 if (widget.data.maxHeight) {
411 this.setValue(widget.data.maxHeight);
412 }
413 }
414 }
415 ]
416 }
417 ]
418 }, {
419 type: 'hbox',
420 id: 'alignment',
421 children: [
422 {
423 id: 'align',
424 type: 'radio',
425 items: [
426 [editor.lang.oembed.none, 'none'],
427 [editor.lang.common.alignLeft, 'left'],
428 [editor.lang.common.alignCenter, 'center'],
429 [editor.lang.common.alignRight, 'right']
430 ],
431 label: editor.lang.common.align,
432 setup: function(widget) {
433 this.setValue(widget.data.align);
434 }
435 }
436 ]
437 }
438 ]
439 }
440 ]
441 };
442 });
443 }
444 });
445 }
446)();
diff --git a/sources/plugins/panel/plugin.js b/sources/plugins/panel/plugin.js
new file mode 100644
index 0000000..b64c540
--- /dev/null
+++ b/sources/plugins/panel/plugin.js
@@ -0,0 +1,403 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 CKEDITOR.plugins.add( 'panel', {
8 beforeInit: function( editor ) {
9 editor.ui.addHandler( CKEDITOR.UI_PANEL, CKEDITOR.ui.panel.handler );
10 }
11 } );
12
13 /**
14 * Panel UI element.
15 *
16 * @readonly
17 * @property {String} [='panel']
18 * @member CKEDITOR
19 */
20 CKEDITOR.UI_PANEL = 'panel';
21
22 /**
23 * @class
24 * @constructor Creates a panel class instance.
25 * @param {CKEDITOR.dom.document} document
26 * @param {Object} definition
27 */
28 CKEDITOR.ui.panel = function( document, definition ) {
29 // Copy all definition properties to this object.
30 if ( definition )
31 CKEDITOR.tools.extend( this, definition );
32
33 // Set defaults.
34 CKEDITOR.tools.extend( this, {
35 className: '',
36 css: []
37 } );
38
39 this.id = CKEDITOR.tools.getNextId();
40 this.document = document;
41 this.isFramed = this.forceIFrame || this.css.length;
42
43 this._ = {
44 blocks: {}
45 };
46 };
47
48 /**
49 * Represents panel handler object.
50 *
51 * @class
52 * @singleton
53 * @extends CKEDITOR.ui.handlerDefinition
54 */
55 CKEDITOR.ui.panel.handler = {
56 /**
57 * Transforms a panel definition in a {@link CKEDITOR.ui.panel} instance.
58 *
59 * @param {Object} definition
60 * @returns {CKEDITOR.ui.panel}
61 */
62 create: function( definition ) {
63 return new CKEDITOR.ui.panel( definition );
64 }
65 };
66
67 var panelTpl = CKEDITOR.addTemplate( 'panel', '<div lang="{langCode}" id="{id}" dir={dir}' +
68 ' class="cke cke_reset_all {editorId} cke_panel cke_panel {cls} cke_{dir}"' +
69 ' style="z-index:{z-index}" role="presentation">' +
70 '{frame}' +
71 '</div>' );
72
73 var frameTpl = CKEDITOR.addTemplate( 'panel-frame', '<iframe id="{id}" class="cke_panel_frame" role="presentation" frameborder="0" src="{src}"></iframe>' );
74
75 var frameDocTpl = CKEDITOR.addTemplate( 'panel-frame-inner', '<!DOCTYPE html>' +
76 '<html class="cke_panel_container {env}" dir="{dir}" lang="{langCode}">' +
77 '<head>{css}</head>' +
78 '<body class="cke_{dir}"' +
79 ' style="margin:0;padding:0" onload="{onload}"></body>' +
80 '<\/html>' );
81
82 /** @class CKEDITOR.ui.panel */
83 CKEDITOR.ui.panel.prototype = {
84 /**
85 * Renders the combo.
86 *
87 * @param {CKEDITOR.editor} editor The editor instance which this button is
88 * to be used by.
89 * @param {Array} [output] The output array to which append the HTML relative
90 * to this button.
91 */
92 render: function( editor, output ) {
93 this.getHolderElement = function() {
94 var holder = this._.holder;
95
96 if ( !holder ) {
97 if ( this.isFramed ) {
98 var iframe = this.document.getById( this.id + '_frame' ),
99 parentDiv = iframe.getParent(),
100 doc = iframe.getFrameDocument();
101
102 // Make it scrollable on iOS. (#8308)
103 CKEDITOR.env.iOS && parentDiv.setStyles( {
104 'overflow': 'scroll',
105 '-webkit-overflow-scrolling': 'touch'
106 } );
107
108 var onLoad = CKEDITOR.tools.addFunction( CKEDITOR.tools.bind( function() {
109 this.isLoaded = true;
110 if ( this.onLoad )
111 this.onLoad();
112 }, this ) );
113
114 doc.write( frameDocTpl.output( CKEDITOR.tools.extend( {
115 css: CKEDITOR.tools.buildStyleHtml( this.css ),
116 onload: 'window.parent.CKEDITOR.tools.callFunction(' + onLoad + ');'
117 }, data ) ) );
118
119 var win = doc.getWindow();
120
121 // Register the CKEDITOR global.
122 win.$.CKEDITOR = CKEDITOR;
123
124 // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (#4534).
125 doc.on( 'keydown', function( evt ) {
126 var keystroke = evt.data.getKeystroke(),
127 dir = this.document.getById( this.id ).getAttribute( 'dir' );
128
129 // Delegate key processing to block.
130 if ( this._.onKeyDown && this._.onKeyDown( keystroke ) === false ) {
131 evt.data.preventDefault();
132 return;
133 }
134
135 // ESC/ARROW-LEFT(ltr) OR ARROW-RIGHT(rtl)
136 if ( keystroke == 27 || keystroke == ( dir == 'rtl' ? 39 : 37 ) ) {
137 if ( this.onEscape && this.onEscape( keystroke ) === false )
138 evt.data.preventDefault();
139 }
140 }, this );
141
142 holder = doc.getBody();
143 holder.unselectable();
144 CKEDITOR.env.air && CKEDITOR.tools.callFunction( onLoad );
145 } else {
146 holder = this.document.getById( this.id );
147 }
148
149 this._.holder = holder;
150 }
151
152 return holder;
153 };
154
155 var data = {
156 editorId: editor.id,
157 id: this.id,
158 langCode: editor.langCode,
159 dir: editor.lang.dir,
160 cls: this.className,
161 frame: '',
162 env: CKEDITOR.env.cssClass,
163 'z-index': editor.config.baseFloatZIndex + 1
164 };
165
166 if ( this.isFramed ) {
167 // With IE, the custom domain has to be taken care at first,
168 // for other browers, the 'src' attribute should be left empty to
169 // trigger iframe's 'load' event.
170 var src =
171 CKEDITOR.env.air ? 'javascript:void(0)' : // jshint ignore:line
172 CKEDITOR.env.ie ? 'javascript:void(function(){' + encodeURIComponent( // jshint ignore:line
173 'document.open();' +
174 // In IE, the document domain must be set any time we call document.open().
175 '(' + CKEDITOR.tools.fixDomain + ')();' +
176 'document.close();'
177 ) + '}())' :
178 '';
179
180 data.frame = frameTpl.output( {
181 id: this.id + '_frame',
182 src: src
183 } );
184 }
185
186 var html = panelTpl.output( data );
187
188 if ( output )
189 output.push( html );
190
191 return html;
192 },
193
194 /**
195 * @todo
196 */
197 addBlock: function( name, block ) {
198 block = this._.blocks[ name ] = block instanceof CKEDITOR.ui.panel.block ? block : new CKEDITOR.ui.panel.block( this.getHolderElement(), block );
199
200 if ( !this._.currentBlock )
201 this.showBlock( name );
202
203 return block;
204 },
205
206 /**
207 * @todo
208 */
209 getBlock: function( name ) {
210 return this._.blocks[ name ];
211 },
212
213 /**
214 * @todo
215 */
216 showBlock: function( name ) {
217 var blocks = this._.blocks,
218 block = blocks[ name ],
219 current = this._.currentBlock;
220
221 // ARIA role works better in IE on the body element, while on the iframe
222 // for FF. (#8864)
223 var holder = !this.forceIFrame || CKEDITOR.env.ie ? this._.holder : this.document.getById( this.id + '_frame' );
224
225 if ( current )
226 current.hide();
227
228 this._.currentBlock = block;
229
230 CKEDITOR.fire( 'ariaWidget', holder );
231
232 // Reset the focus index, so it will always go into the first one.
233 block._.focusIndex = -1;
234
235 this._.onKeyDown = block.onKeyDown && CKEDITOR.tools.bind( block.onKeyDown, block );
236
237 block.show();
238
239 return block;
240 },
241
242 /**
243 * @todo
244 */
245 destroy: function() {
246 this.element && this.element.remove();
247 }
248 };
249
250 /**
251 * @class
252 *
253 * @todo class and all methods
254 */
255 CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass( {
256 /**
257 * Creates a block class instances.
258 *
259 * @constructor
260 * @todo
261 */
262 $: function( blockHolder, blockDefinition ) {
263 this.element = blockHolder.append( blockHolder.getDocument().createElement( 'div', {
264 attributes: {
265 'tabindex': -1,
266 'class': 'cke_panel_block'
267 },
268 styles: {
269 display: 'none'
270 }
271 } ) );
272
273 // Copy all definition properties to this object.
274 if ( blockDefinition )
275 CKEDITOR.tools.extend( this, blockDefinition );
276
277 // Set the a11y attributes of this element ...
278 this.element.setAttributes( {
279 'role': this.attributes.role || 'presentation',
280 'aria-label': this.attributes[ 'aria-label' ],
281 'title': this.attributes.title || this.attributes[ 'aria-label' ]
282 } );
283
284 this.keys = {};
285
286 this._.focusIndex = -1;
287
288 // Disable context menu for panels.
289 this.element.disableContextMenu();
290 },
291
292 _: {
293
294 /**
295 * Mark the item specified by the index as current activated.
296 */
297 markItem: function( index ) {
298 if ( index == -1 )
299 return;
300 var links = this.element.getElementsByTag( 'a' );
301 var item = links.getItem( this._.focusIndex = index );
302
303 // Safari need focus on the iframe window first(#3389), but we need
304 // lock the blur to avoid hiding the panel.
305 if ( CKEDITOR.env.webkit )
306 item.getDocument().getWindow().focus();
307 item.focus();
308
309 this.onMark && this.onMark( item );
310 }
311 },
312
313 proto: {
314 show: function() {
315 this.element.setStyle( 'display', '' );
316 },
317
318 hide: function() {
319 if ( !this.onHide || this.onHide.call( this ) !== true )
320 this.element.setStyle( 'display', 'none' );
321 },
322
323 onKeyDown: function( keystroke, noCycle ) {
324 var keyAction = this.keys[ keystroke ];
325 switch ( keyAction ) {
326 // Move forward.
327 case 'next':
328 var index = this._.focusIndex,
329 links = this.element.getElementsByTag( 'a' ),
330 link;
331
332 while ( ( link = links.getItem( ++index ) ) ) {
333 // Move the focus only if the element is marked with
334 // the _cke_focus and it it's visible (check if it has
335 // width).
336 if ( link.getAttribute( '_cke_focus' ) && link.$.offsetWidth ) {
337 this._.focusIndex = index;
338 link.focus();
339 break;
340 }
341 }
342
343 // If no link was found, cycle and restart from the top. (#11125)
344 if ( !link && !noCycle ) {
345 this._.focusIndex = -1;
346 return this.onKeyDown( keystroke, 1 );
347 }
348
349 return false;
350
351 // Move backward.
352 case 'prev':
353 index = this._.focusIndex;
354 links = this.element.getElementsByTag( 'a' );
355
356 while ( index > 0 && ( link = links.getItem( --index ) ) ) {
357 // Move the focus only if the element is marked with
358 // the _cke_focus and it it's visible (check if it has
359 // width).
360 if ( link.getAttribute( '_cke_focus' ) && link.$.offsetWidth ) {
361 this._.focusIndex = index;
362 link.focus();
363 break;
364 }
365
366 // Make sure link is null when the loop ends and nothing was
367 // found (#11125).
368 link = null;
369 }
370
371 // If no link was found, cycle and restart from the bottom. (#11125)
372 if ( !link && !noCycle ) {
373 this._.focusIndex = links.count();
374 return this.onKeyDown( keystroke, 1 );
375 }
376
377 return false;
378
379 case 'click':
380 case 'mouseup':
381 index = this._.focusIndex;
382 link = index >= 0 && this.element.getElementsByTag( 'a' ).getItem( index );
383
384 if ( link )
385 link.$[ keyAction ] ? link.$[ keyAction ]() : link.$[ 'on' + keyAction ]();
386
387 return false;
388 }
389
390 return true;
391 }
392 }
393 } );
394
395} )();
396
397/**
398 * Fired when a panel is added to the document.
399 *
400 * @event ariaWidget
401 * @member CKEDITOR
402 * @param {Object} data The element wrapping the panel.
403 */
diff --git a/sources/plugins/popup/plugin.js b/sources/plugins/popup/plugin.js
new file mode 100644
index 0000000..352d239
--- /dev/null
+++ b/sources/plugins/popup/plugin.js
@@ -0,0 +1,65 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'popup' );
7
8CKEDITOR.tools.extend( CKEDITOR.editor.prototype, {
9 /**
10 * Opens Browser in a popup. The `width` and `height` parameters accept
11 * numbers (pixels) or percent (of screen size) values.
12 *
13 * @member CKEDITOR.editor
14 * @param {String} url The url of the external file browser.
15 * @param {Number/String} [width='80%'] Popup window width.
16 * @param {Number/String} [height='70%'] Popup window height.
17 * @param {String} [options='location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes']
18 * Popup window features.
19 */
20 popup: function( url, width, height, options ) {
21 width = width || '80%';
22 height = height || '70%';
23
24 if ( typeof width == 'string' && width.length > 1 && width.substr( width.length - 1, 1 ) == '%' )
25 width = parseInt( window.screen.width * parseInt( width, 10 ) / 100, 10 );
26
27 if ( typeof height == 'string' && height.length > 1 && height.substr( height.length - 1, 1 ) == '%' )
28 height = parseInt( window.screen.height * parseInt( height, 10 ) / 100, 10 );
29
30 if ( width < 640 )
31 width = 640;
32
33 if ( height < 420 )
34 height = 420;
35
36 var top = parseInt( ( window.screen.height - height ) / 2, 10 ),
37 left = parseInt( ( window.screen.width - width ) / 2, 10 );
38
39 options = ( options || 'location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes' ) + ',width=' + width +
40 ',height=' + height +
41 ',top=' + top +
42 ',left=' + left;
43
44 var popupWindow = window.open( '', null, options, true );
45
46 // Blocked by a popup blocker.
47 if ( !popupWindow )
48 return false;
49
50 try {
51 // Chrome is problematic with moveTo/resizeTo, but it's not really needed here (#8855).
52 var ua = navigator.userAgent.toLowerCase();
53 if ( ua.indexOf( ' chrome/' ) == -1 ) {
54 popupWindow.moveTo( left, top );
55 popupWindow.resizeTo( width, height );
56 }
57 popupWindow.focus();
58 popupWindow.location.href = url;
59 } catch ( e ) {
60 popupWindow = window.open( url, null, options, true );
61 }
62
63 return true;
64 }
65} );
diff --git a/sources/plugins/removeformat/icons/hidpi/removeformat.png b/sources/plugins/removeformat/icons/hidpi/removeformat.png
new file mode 100644
index 0000000..0695878
--- /dev/null
+++ b/sources/plugins/removeformat/icons/hidpi/removeformat.png
Binary files differ
diff --git a/sources/plugins/removeformat/icons/removeformat.png b/sources/plugins/removeformat/icons/removeformat.png
new file mode 100644
index 0000000..f4597bf
--- /dev/null
+++ b/sources/plugins/removeformat/icons/removeformat.png
Binary files differ
diff --git a/sources/plugins/removeformat/lang/af.js b/sources/plugins/removeformat/lang/af.js
new file mode 100644
index 0000000..4904945
--- /dev/null
+++ b/sources/plugins/removeformat/lang/af.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'af', {
6 toolbar: 'Verwyder opmaak'
7} );
diff --git a/sources/plugins/removeformat/lang/ar.js b/sources/plugins/removeformat/lang/ar.js
new file mode 100644
index 0000000..661e851
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ar.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ar', {
6 toolbar: 'إزالة التنسيقات'
7} );
diff --git a/sources/plugins/removeformat/lang/az.js b/sources/plugins/removeformat/lang/az.js
new file mode 100644
index 0000000..948837e
--- /dev/null
+++ b/sources/plugins/removeformat/lang/az.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'az', {
6 toolbar: 'Formatı sil'
7} );
diff --git a/sources/plugins/removeformat/lang/bg.js b/sources/plugins/removeformat/lang/bg.js
new file mode 100644
index 0000000..a96dc60
--- /dev/null
+++ b/sources/plugins/removeformat/lang/bg.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'bg', {
6 toolbar: 'Премахване на форматирането'
7} );
diff --git a/sources/plugins/removeformat/lang/bn.js b/sources/plugins/removeformat/lang/bn.js
new file mode 100644
index 0000000..0c59c81
--- /dev/null
+++ b/sources/plugins/removeformat/lang/bn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'bn', {
6 toolbar: 'ধরন-প্রকৃতি অপসারণ করি'
7} );
diff --git a/sources/plugins/removeformat/lang/bs.js b/sources/plugins/removeformat/lang/bs.js
new file mode 100644
index 0000000..83fd723
--- /dev/null
+++ b/sources/plugins/removeformat/lang/bs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'bs', {
6 toolbar: 'Poništi format'
7} );
diff --git a/sources/plugins/removeformat/lang/ca.js b/sources/plugins/removeformat/lang/ca.js
new file mode 100644
index 0000000..01ead3b
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ca', {
6 toolbar: 'Elimina Format'
7} );
diff --git a/sources/plugins/removeformat/lang/cs.js b/sources/plugins/removeformat/lang/cs.js
new file mode 100644
index 0000000..cab8cfc
--- /dev/null
+++ b/sources/plugins/removeformat/lang/cs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'cs', {
6 toolbar: 'Odstranit formátování'
7} );
diff --git a/sources/plugins/removeformat/lang/cy.js b/sources/plugins/removeformat/lang/cy.js
new file mode 100644
index 0000000..7908104
--- /dev/null
+++ b/sources/plugins/removeformat/lang/cy.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'cy', {
6 toolbar: 'Tynnu Fformat'
7} );
diff --git a/sources/plugins/removeformat/lang/da.js b/sources/plugins/removeformat/lang/da.js
new file mode 100644
index 0000000..6f35909
--- /dev/null
+++ b/sources/plugins/removeformat/lang/da.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'da', {
6 toolbar: 'Fjern formatering'
7} );
diff --git a/sources/plugins/removeformat/lang/de-ch.js b/sources/plugins/removeformat/lang/de-ch.js
new file mode 100644
index 0000000..37d1ccd
--- /dev/null
+++ b/sources/plugins/removeformat/lang/de-ch.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'de-ch', {
6 toolbar: 'Formatierung entfernen'
7} );
diff --git a/sources/plugins/removeformat/lang/de.js b/sources/plugins/removeformat/lang/de.js
new file mode 100644
index 0000000..5d8901b
--- /dev/null
+++ b/sources/plugins/removeformat/lang/de.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'de', {
6 toolbar: 'Formatierung entfernen'
7} );
diff --git a/sources/plugins/removeformat/lang/el.js b/sources/plugins/removeformat/lang/el.js
new file mode 100644
index 0000000..e0da8c6
--- /dev/null
+++ b/sources/plugins/removeformat/lang/el.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'el', {
6 toolbar: 'Εκκαθάριση Μορφοποίησης'
7} );
diff --git a/sources/plugins/removeformat/lang/en-au.js b/sources/plugins/removeformat/lang/en-au.js
new file mode 100644
index 0000000..4d98f6d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/en-au.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'en-au', {
6 toolbar: 'Remove Format'
7} );
diff --git a/sources/plugins/removeformat/lang/en-ca.js b/sources/plugins/removeformat/lang/en-ca.js
new file mode 100644
index 0000000..998eb01
--- /dev/null
+++ b/sources/plugins/removeformat/lang/en-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'en-ca', {
6 toolbar: 'Remove Format'
7} );
diff --git a/sources/plugins/removeformat/lang/en-gb.js b/sources/plugins/removeformat/lang/en-gb.js
new file mode 100644
index 0000000..f40ca18
--- /dev/null
+++ b/sources/plugins/removeformat/lang/en-gb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'en-gb', {
6 toolbar: 'Remove Format'
7} );
diff --git a/sources/plugins/removeformat/lang/en.js b/sources/plugins/removeformat/lang/en.js
new file mode 100644
index 0000000..ed26343
--- /dev/null
+++ b/sources/plugins/removeformat/lang/en.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'en', {
6 toolbar: 'Remove Format'
7} );
diff --git a/sources/plugins/removeformat/lang/eo.js b/sources/plugins/removeformat/lang/eo.js
new file mode 100644
index 0000000..bb25f96
--- /dev/null
+++ b/sources/plugins/removeformat/lang/eo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'eo', {
6 toolbar: 'Forigi Formaton'
7} );
diff --git a/sources/plugins/removeformat/lang/es.js b/sources/plugins/removeformat/lang/es.js
new file mode 100644
index 0000000..d097bdb
--- /dev/null
+++ b/sources/plugins/removeformat/lang/es.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'es', {
6 toolbar: 'Eliminar Formato'
7} );
diff --git a/sources/plugins/removeformat/lang/et.js b/sources/plugins/removeformat/lang/et.js
new file mode 100644
index 0000000..823749d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/et.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'et', {
6 toolbar: 'Vormingu eemaldamine'
7} );
diff --git a/sources/plugins/removeformat/lang/eu.js b/sources/plugins/removeformat/lang/eu.js
new file mode 100644
index 0000000..bc487f7
--- /dev/null
+++ b/sources/plugins/removeformat/lang/eu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'eu', {
6 toolbar: 'Kendu formatua'
7} );
diff --git a/sources/plugins/removeformat/lang/fa.js b/sources/plugins/removeformat/lang/fa.js
new file mode 100644
index 0000000..8fc6b93
--- /dev/null
+++ b/sources/plugins/removeformat/lang/fa.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'fa', {
6 toolbar: 'برداشتن فرمت'
7} );
diff --git a/sources/plugins/removeformat/lang/fi.js b/sources/plugins/removeformat/lang/fi.js
new file mode 100644
index 0000000..c61a093
--- /dev/null
+++ b/sources/plugins/removeformat/lang/fi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'fi', {
6 toolbar: 'Poista muotoilu'
7} );
diff --git a/sources/plugins/removeformat/lang/fo.js b/sources/plugins/removeformat/lang/fo.js
new file mode 100644
index 0000000..b80c158
--- /dev/null
+++ b/sources/plugins/removeformat/lang/fo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'fo', {
6 toolbar: 'Strika sniðgeving'
7} );
diff --git a/sources/plugins/removeformat/lang/fr-ca.js b/sources/plugins/removeformat/lang/fr-ca.js
new file mode 100644
index 0000000..fe3534d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/fr-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'fr-ca', {
6 toolbar: 'Supprimer le formatage'
7} );
diff --git a/sources/plugins/removeformat/lang/fr.js b/sources/plugins/removeformat/lang/fr.js
new file mode 100644
index 0000000..e18fd83
--- /dev/null
+++ b/sources/plugins/removeformat/lang/fr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'fr', {
6 toolbar: 'Supprimer la mise en forme'
7} );
diff --git a/sources/plugins/removeformat/lang/gl.js b/sources/plugins/removeformat/lang/gl.js
new file mode 100644
index 0000000..8190cca
--- /dev/null
+++ b/sources/plugins/removeformat/lang/gl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'gl', {
6 toolbar: 'Retirar o formato'
7} );
diff --git a/sources/plugins/removeformat/lang/gu.js b/sources/plugins/removeformat/lang/gu.js
new file mode 100644
index 0000000..621ad9d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/gu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'gu', {
6 toolbar: 'ફૉર્મટ કાઢવું'
7} );
diff --git a/sources/plugins/removeformat/lang/he.js b/sources/plugins/removeformat/lang/he.js
new file mode 100644
index 0000000..bcdc1bd
--- /dev/null
+++ b/sources/plugins/removeformat/lang/he.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'he', {
6 toolbar: 'הסרת העיצוב'
7} );
diff --git a/sources/plugins/removeformat/lang/hi.js b/sources/plugins/removeformat/lang/hi.js
new file mode 100644
index 0000000..ab15f5d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/hi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'hi', {
6 toolbar: 'फ़ॉर्मैट हटायें'
7} );
diff --git a/sources/plugins/removeformat/lang/hr.js b/sources/plugins/removeformat/lang/hr.js
new file mode 100644
index 0000000..c061400
--- /dev/null
+++ b/sources/plugins/removeformat/lang/hr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'hr', {
6 toolbar: 'Ukloni formatiranje'
7} );
diff --git a/sources/plugins/removeformat/lang/hu.js b/sources/plugins/removeformat/lang/hu.js
new file mode 100644
index 0000000..fe1c099
--- /dev/null
+++ b/sources/plugins/removeformat/lang/hu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'hu', {
6 toolbar: 'Formázás eltávolítása'
7} );
diff --git a/sources/plugins/removeformat/lang/id.js b/sources/plugins/removeformat/lang/id.js
new file mode 100644
index 0000000..e7eded0
--- /dev/null
+++ b/sources/plugins/removeformat/lang/id.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'id', {
6 toolbar: 'Hapus Format'
7} );
diff --git a/sources/plugins/removeformat/lang/is.js b/sources/plugins/removeformat/lang/is.js
new file mode 100644
index 0000000..98b9b4d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/is.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'is', {
6 toolbar: 'Fjarlægja snið'
7} );
diff --git a/sources/plugins/removeformat/lang/it.js b/sources/plugins/removeformat/lang/it.js
new file mode 100644
index 0000000..0ea8fb9
--- /dev/null
+++ b/sources/plugins/removeformat/lang/it.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'it', {
6 toolbar: 'Elimina formattazione'
7} );
diff --git a/sources/plugins/removeformat/lang/ja.js b/sources/plugins/removeformat/lang/ja.js
new file mode 100644
index 0000000..ca0970f
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ja.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ja', {
6 toolbar: '書式を解除'
7} );
diff --git a/sources/plugins/removeformat/lang/ka.js b/sources/plugins/removeformat/lang/ka.js
new file mode 100644
index 0000000..b624c5d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ka.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ka', {
6 toolbar: 'ფორმატირების მოხსნა'
7} );
diff --git a/sources/plugins/removeformat/lang/km.js b/sources/plugins/removeformat/lang/km.js
new file mode 100644
index 0000000..cacd321
--- /dev/null
+++ b/sources/plugins/removeformat/lang/km.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'km', {
6 toolbar: 'ជម្រះ​ទ្រង់​ទ្រាយ'
7} );
diff --git a/sources/plugins/removeformat/lang/ko.js b/sources/plugins/removeformat/lang/ko.js
new file mode 100644
index 0000000..a594ccc
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ko.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ko', {
6 toolbar: '형식 지우기'
7} );
diff --git a/sources/plugins/removeformat/lang/ku.js b/sources/plugins/removeformat/lang/ku.js
new file mode 100644
index 0000000..51ae15a
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ku.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ku', {
6 toolbar: 'لابردنی داڕشتەکە'
7} );
diff --git a/sources/plugins/removeformat/lang/lt.js b/sources/plugins/removeformat/lang/lt.js
new file mode 100644
index 0000000..1e7f2df
--- /dev/null
+++ b/sources/plugins/removeformat/lang/lt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'lt', {
6 toolbar: 'Panaikinti formatą'
7} );
diff --git a/sources/plugins/removeformat/lang/lv.js b/sources/plugins/removeformat/lang/lv.js
new file mode 100644
index 0000000..f382171
--- /dev/null
+++ b/sources/plugins/removeformat/lang/lv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'lv', {
6 toolbar: 'Noņemt stilus'
7} );
diff --git a/sources/plugins/removeformat/lang/mk.js b/sources/plugins/removeformat/lang/mk.js
new file mode 100644
index 0000000..be04ba4
--- /dev/null
+++ b/sources/plugins/removeformat/lang/mk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'mk', {
6 toolbar: 'Remove Format' // MISSING
7} );
diff --git a/sources/plugins/removeformat/lang/mn.js b/sources/plugins/removeformat/lang/mn.js
new file mode 100644
index 0000000..378a898
--- /dev/null
+++ b/sources/plugins/removeformat/lang/mn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'mn', {
6 toolbar: 'Параргафын загварыг авч хаях'
7} );
diff --git a/sources/plugins/removeformat/lang/ms.js b/sources/plugins/removeformat/lang/ms.js
new file mode 100644
index 0000000..ee81ba1
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ms.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ms', {
6 toolbar: 'Buang Format'
7} );
diff --git a/sources/plugins/removeformat/lang/nb.js b/sources/plugins/removeformat/lang/nb.js
new file mode 100644
index 0000000..19f093d
--- /dev/null
+++ b/sources/plugins/removeformat/lang/nb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'nb', {
6 toolbar: 'Fjern formatering'
7} );
diff --git a/sources/plugins/removeformat/lang/nl.js b/sources/plugins/removeformat/lang/nl.js
new file mode 100644
index 0000000..46be61b
--- /dev/null
+++ b/sources/plugins/removeformat/lang/nl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'nl', {
6 toolbar: 'Opmaak verwijderen'
7} );
diff --git a/sources/plugins/removeformat/lang/no.js b/sources/plugins/removeformat/lang/no.js
new file mode 100644
index 0000000..84d38af
--- /dev/null
+++ b/sources/plugins/removeformat/lang/no.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'no', {
6 toolbar: 'Fjern formatering'
7} );
diff --git a/sources/plugins/removeformat/lang/oc.js b/sources/plugins/removeformat/lang/oc.js
new file mode 100644
index 0000000..7dda966
--- /dev/null
+++ b/sources/plugins/removeformat/lang/oc.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'oc', {
6 toolbar: 'Suprimir la mesa en forma'
7} );
diff --git a/sources/plugins/removeformat/lang/pl.js b/sources/plugins/removeformat/lang/pl.js
new file mode 100644
index 0000000..41e7034
--- /dev/null
+++ b/sources/plugins/removeformat/lang/pl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'pl', {
6 toolbar: 'Usuń formatowanie'
7} );
diff --git a/sources/plugins/removeformat/lang/pt-br.js b/sources/plugins/removeformat/lang/pt-br.js
new file mode 100644
index 0000000..61b44c0
--- /dev/null
+++ b/sources/plugins/removeformat/lang/pt-br.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'pt-br', {
6 toolbar: 'Remover Formatação'
7} );
diff --git a/sources/plugins/removeformat/lang/pt.js b/sources/plugins/removeformat/lang/pt.js
new file mode 100644
index 0000000..b54dbce
--- /dev/null
+++ b/sources/plugins/removeformat/lang/pt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'pt', {
6 toolbar: 'Limpar formatação'
7} );
diff --git a/sources/plugins/removeformat/lang/ro.js b/sources/plugins/removeformat/lang/ro.js
new file mode 100644
index 0000000..649bced
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ro.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ro', {
6 toolbar: 'Înlătură formatarea'
7} );
diff --git a/sources/plugins/removeformat/lang/ru.js b/sources/plugins/removeformat/lang/ru.js
new file mode 100644
index 0000000..ea05d6e
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ru.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ru', {
6 toolbar: 'Убрать форматирование'
7} );
diff --git a/sources/plugins/removeformat/lang/si.js b/sources/plugins/removeformat/lang/si.js
new file mode 100644
index 0000000..db5d715
--- /dev/null
+++ b/sources/plugins/removeformat/lang/si.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'si', {
6 toolbar: 'සැකසීම වෙනස් කරන්න'
7} );
diff --git a/sources/plugins/removeformat/lang/sk.js b/sources/plugins/removeformat/lang/sk.js
new file mode 100644
index 0000000..625c8d6
--- /dev/null
+++ b/sources/plugins/removeformat/lang/sk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'sk', {
6 toolbar: 'Odstrániť formátovanie'
7} );
diff --git a/sources/plugins/removeformat/lang/sl.js b/sources/plugins/removeformat/lang/sl.js
new file mode 100644
index 0000000..895c1e7
--- /dev/null
+++ b/sources/plugins/removeformat/lang/sl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'sl', {
6 toolbar: 'Odstrani oblikovanje'
7} );
diff --git a/sources/plugins/removeformat/lang/sq.js b/sources/plugins/removeformat/lang/sq.js
new file mode 100644
index 0000000..45f455a
--- /dev/null
+++ b/sources/plugins/removeformat/lang/sq.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'sq', {
6 toolbar: 'Largo Formatin'
7} );
diff --git a/sources/plugins/removeformat/lang/sr-latn.js b/sources/plugins/removeformat/lang/sr-latn.js
new file mode 100644
index 0000000..51f34a7
--- /dev/null
+++ b/sources/plugins/removeformat/lang/sr-latn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'sr-latn', {
6 toolbar: 'Ukloni formatiranje'
7} );
diff --git a/sources/plugins/removeformat/lang/sr.js b/sources/plugins/removeformat/lang/sr.js
new file mode 100644
index 0000000..c6080dd
--- /dev/null
+++ b/sources/plugins/removeformat/lang/sr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'sr', {
6 toolbar: 'Уклони форматирање'
7} );
diff --git a/sources/plugins/removeformat/lang/sv.js b/sources/plugins/removeformat/lang/sv.js
new file mode 100644
index 0000000..2dd7edc
--- /dev/null
+++ b/sources/plugins/removeformat/lang/sv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'sv', {
6 toolbar: 'Radera formatering'
7} );
diff --git a/sources/plugins/removeformat/lang/th.js b/sources/plugins/removeformat/lang/th.js
new file mode 100644
index 0000000..0bc74e2
--- /dev/null
+++ b/sources/plugins/removeformat/lang/th.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'th', {
6 toolbar: 'ล้างรูปแบบ'
7} );
diff --git a/sources/plugins/removeformat/lang/tr.js b/sources/plugins/removeformat/lang/tr.js
new file mode 100644
index 0000000..2c961c5
--- /dev/null
+++ b/sources/plugins/removeformat/lang/tr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'tr', {
6 toolbar: 'Biçimi Kaldır'
7} );
diff --git a/sources/plugins/removeformat/lang/tt.js b/sources/plugins/removeformat/lang/tt.js
new file mode 100644
index 0000000..b3afbda
--- /dev/null
+++ b/sources/plugins/removeformat/lang/tt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'tt', {
6 toolbar: 'Форматлауны бетерү'
7} );
diff --git a/sources/plugins/removeformat/lang/ug.js b/sources/plugins/removeformat/lang/ug.js
new file mode 100644
index 0000000..07e5daf
--- /dev/null
+++ b/sources/plugins/removeformat/lang/ug.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'ug', {
6 toolbar: 'پىچىمنى چىقىرىۋەت'
7} );
diff --git a/sources/plugins/removeformat/lang/uk.js b/sources/plugins/removeformat/lang/uk.js
new file mode 100644
index 0000000..7ef1f1c
--- /dev/null
+++ b/sources/plugins/removeformat/lang/uk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'uk', {
6 toolbar: 'Видалити форматування'
7} );
diff --git a/sources/plugins/removeformat/lang/vi.js b/sources/plugins/removeformat/lang/vi.js
new file mode 100644
index 0000000..38316bf
--- /dev/null
+++ b/sources/plugins/removeformat/lang/vi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'vi', {
6 toolbar: 'Xoá định dạng'
7} );
diff --git a/sources/plugins/removeformat/lang/zh-cn.js b/sources/plugins/removeformat/lang/zh-cn.js
new file mode 100644
index 0000000..ec833f1
--- /dev/null
+++ b/sources/plugins/removeformat/lang/zh-cn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'zh-cn', {
6 toolbar: '清除格式'
7} );
diff --git a/sources/plugins/removeformat/lang/zh.js b/sources/plugins/removeformat/lang/zh.js
new file mode 100644
index 0000000..dd23488
--- /dev/null
+++ b/sources/plugins/removeformat/lang/zh.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'removeformat', 'zh', {
6 toolbar: '移除格式'
7} );
diff --git a/sources/plugins/removeformat/plugin.js b/sources/plugins/removeformat/plugin.js
new file mode 100644
index 0000000..20f7ecb
--- /dev/null
+++ b/sources/plugins/removeformat/plugin.js
@@ -0,0 +1,193 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'removeformat', {
7 // jscs:disable maximumLineLength
8 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
9 // jscs:enable maximumLineLength
10 icons: 'removeformat', // %REMOVE_LINE_CORE%
11 hidpi: true, // %REMOVE_LINE_CORE%
12 init: function( editor ) {
13 editor.addCommand( 'removeFormat', CKEDITOR.plugins.removeformat.commands.removeformat );
14 editor.ui.addButton && editor.ui.addButton( 'RemoveFormat', {
15 label: editor.lang.removeformat.toolbar,
16 command: 'removeFormat',
17 toolbar: 'cleanup,10'
18 } );
19 }
20} );
21
22CKEDITOR.plugins.removeformat = {
23 commands: {
24 removeformat: {
25 exec: function( editor ) {
26 var tagsRegex = editor._.removeFormatRegex || ( editor._.removeFormatRegex = new RegExp( '^(?:' + editor.config.removeFormatTags.replace( /,/g, '|' ) + ')$', 'i' ) );
27
28 var removeAttributes = editor._.removeAttributes || ( editor._.removeAttributes = editor.config.removeFormatAttributes.split( ',' ) ),
29 filter = CKEDITOR.plugins.removeformat.filter,
30 ranges = editor.getSelection().getRanges(),
31 iterator = ranges.createIterator(),
32 isElement = function( element ) {
33 return element.type == CKEDITOR.NODE_ELEMENT;
34 },
35 range;
36
37 while ( ( range = iterator.getNextRange() ) ) {
38 if ( !range.collapsed )
39 range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
40
41 // Bookmark the range so we can re-select it after processing.
42 var bookmark = range.createBookmark(),
43 // The style will be applied within the bookmark boundaries.
44 startNode = bookmark.startNode,
45 endNode = bookmark.endNode,
46 currentNode;
47
48 // We need to check the selection boundaries (bookmark spans) to break
49 // the code in a way that we can properly remove partially selected nodes.
50 // For example, removing a <b> style from
51 // <b>This is [some text</b> to show <b>the] problem</b>
52 // ... where [ and ] represent the selection, must result:
53 // <b>This is </b>[some text to show the]<b> problem</b>
54 // The strategy is simple, we just break the partial nodes before the
55 // removal logic, having something that could be represented this way:
56 // <b>This is </b>[<b>some text</b> to show <b>the</b>]<b> problem</b>
57
58 var breakParent = function( node ) {
59 // Let's start checking the start boundary.
60 var path = editor.elementPath( node ),
61 pathElements = path.elements;
62
63 for ( var i = 1, pathElement; pathElement = pathElements[ i ]; i++ ) {
64 if ( pathElement.equals( path.block ) || pathElement.equals( path.blockLimit ) )
65 break;
66
67 // If this element can be removed (even partially).
68 if ( tagsRegex.test( pathElement.getName() ) && filter( editor, pathElement ) )
69 node.breakParent( pathElement );
70 }
71 };
72
73 breakParent( startNode );
74 if ( endNode ) {
75 breakParent( endNode );
76
77 // Navigate through all nodes between the bookmarks.
78 currentNode = startNode.getNextSourceNode( true, CKEDITOR.NODE_ELEMENT );
79
80 while ( currentNode ) {
81 // If we have reached the end of the selection, stop looping.
82 if ( currentNode.equals( endNode ) )
83 break;
84
85 if ( currentNode.isReadOnly() ) {
86 // In case of non-editable we're skipping to the next sibling *elmenet*.
87
88 // We need to be aware that endNode can be nested within current non-editable.
89 // This condition tests if currentNode (non-editable) contains endNode. If it does
90 // then we should break the filtering
91 if ( currentNode.getPosition( endNode ) & CKEDITOR.POSITION_CONTAINS ) {
92 break;
93 }
94
95 currentNode = currentNode.getNext( isElement );
96 continue;
97 }
98
99 // Cache the next node to be processed. Do it now, because
100 // currentNode may be removed.
101 var nextNode = currentNode.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT ),
102 isFakeElement = currentNode.getName() == 'img' && currentNode.data( 'cke-realelement' );
103
104 // This node must not be a fake element, and must not be read-only.
105 if ( !isFakeElement && filter( editor, currentNode ) ) {
106 // Remove elements nodes that match with this style rules.
107 if ( tagsRegex.test( currentNode.getName() ) )
108 currentNode.remove( 1 );
109 else {
110 currentNode.removeAttributes( removeAttributes );
111 editor.fire( 'removeFormatCleanup', currentNode );
112 }
113 }
114
115 currentNode = nextNode;
116 }
117 }
118
119 range.moveToBookmark( bookmark );
120 }
121
122 // The selection path may not changed, but we should force a selection
123 // change event to refresh command states, due to the above attribution change. (#9238)
124 editor.forceNextSelectionCheck();
125 editor.getSelection().selectRanges( ranges );
126 }
127 }
128 },
129
130 // Perform the remove format filters on the passed element.
131 // @param {CKEDITOR.editor} editor
132 // @param {CKEDITOR.dom.element} element
133 filter: function( editor, element ) {
134 // If editor#addRemoveFotmatFilter hasn't been executed yet value is not initialized.
135 var filters = editor._.removeFormatFilters || [];
136 for ( var i = 0; i < filters.length; i++ ) {
137 if ( filters[ i ]( element ) === false )
138 return false;
139 }
140 return true;
141 }
142};
143
144/**
145 * Add to a collection of functions to decide whether a specific
146 * element should be considered as formatting element and thus
147 * could be removed during `removeFormat` command.
148 *
149 * **Note:** Only available with the existence of `removeformat` plugin.
150 *
151 * // Don't remove empty span.
152 * editor.addRemoveFormatFilter( function( element ) {
153 * return !( element.is( 'span' ) && CKEDITOR.tools.isEmpty( element.getAttributes() ) );
154 * } );
155 *
156 * @since 3.3
157 * @member CKEDITOR.editor
158 * @param {Function} func The function to be called, which will be passed a {CKEDITOR.dom.element} element to test.
159 */
160CKEDITOR.editor.prototype.addRemoveFormatFilter = function( func ) {
161 if ( !this._.removeFormatFilters )
162 this._.removeFormatFilters = [];
163
164 this._.removeFormatFilters.push( func );
165};
166
167/**
168 * A comma separated list of elements to be removed when executing the `remove
169 * format` command. Note that only inline elements are allowed.
170 *
171 * @cfg
172 * @member CKEDITOR.config
173 */
174CKEDITOR.config.removeFormatTags = 'b,big,cite,code,del,dfn,em,font,i,ins,kbd,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var';
175
176/**
177 * A comma separated list of elements attributes to be removed when executing
178 * the `remove format` command.
179 *
180 * @cfg
181 * @member CKEDITOR.config
182 */
183CKEDITOR.config.removeFormatAttributes = 'class,style,lang,width,height,align,hspace,valign';
184
185/**
186 * Fired after an element was cleaned by the removeFormat plugin.
187 *
188 * @event removeFormatCleanup
189 * @member CKEDITOR.editor
190 * @param {CKEDITOR.editor} editor This editor instance.
191 * @param data
192 * @param {CKEDITOR.dom.element} data.element The element that was cleaned up.
193 */
diff --git a/sources/plugins/resize/plugin.js b/sources/plugins/resize/plugin.js
new file mode 100644
index 0000000..095ee12
--- /dev/null
+++ b/sources/plugins/resize/plugin.js
@@ -0,0 +1,187 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'resize', {
7 init: function( editor ) {
8 function dragHandler( evt ) {
9 var dx = evt.data.$.screenX - origin.x,
10 dy = evt.data.$.screenY - origin.y,
11 width = startSize.width,
12 height = startSize.height,
13 internalWidth = width + dx * ( resizeDir == 'rtl' ? -1 : 1 ),
14 internalHeight = height + dy;
15
16 if ( resizeHorizontal )
17 width = Math.max( config.resize_minWidth, Math.min( internalWidth, config.resize_maxWidth ) );
18
19 if ( resizeVertical )
20 height = Math.max( config.resize_minHeight, Math.min( internalHeight, config.resize_maxHeight ) );
21
22 // DO NOT impose fixed size with single direction resize. (#6308)
23 editor.resize( resizeHorizontal ? width : null, height );
24 }
25
26 function dragEndHandler() {
27 CKEDITOR.document.removeListener( 'mousemove', dragHandler );
28 CKEDITOR.document.removeListener( 'mouseup', dragEndHandler );
29
30 if ( editor.document ) {
31 editor.document.removeListener( 'mousemove', dragHandler );
32 editor.document.removeListener( 'mouseup', dragEndHandler );
33 }
34 }
35
36 var config = editor.config;
37 var spaceId = editor.ui.spaceId( 'resizer' );
38
39 // Resize in the same direction of chrome,
40 // which is identical to dir of editor element. (#6614)
41 var resizeDir = editor.element ? editor.element.getDirection( 1 ) : 'ltr';
42
43 !config.resize_dir && ( config.resize_dir = 'vertical' );
44 ( config.resize_maxWidth === undefined ) && ( config.resize_maxWidth = 3000 );
45 ( config.resize_maxHeight === undefined ) && ( config.resize_maxHeight = 3000 );
46 ( config.resize_minWidth === undefined ) && ( config.resize_minWidth = 750 );
47 ( config.resize_minHeight === undefined ) && ( config.resize_minHeight = 250 );
48
49 if ( config.resize_enabled !== false ) {
50 var container = null,
51 origin, startSize,
52 resizeHorizontal = ( config.resize_dir == 'both' || config.resize_dir == 'horizontal' ) && ( config.resize_minWidth != config.resize_maxWidth ),
53 resizeVertical = ( config.resize_dir == 'both' || config.resize_dir == 'vertical' ) && ( config.resize_minHeight != config.resize_maxHeight );
54
55 var mouseDownFn = CKEDITOR.tools.addFunction( function( $event ) {
56 if ( !container )
57 container = editor.getResizable();
58
59 startSize = { width: container.$.offsetWidth || 0, height: container.$.offsetHeight || 0 };
60 origin = { x: $event.screenX, y: $event.screenY };
61
62 config.resize_minWidth > startSize.width && ( config.resize_minWidth = startSize.width );
63 config.resize_minHeight > startSize.height && ( config.resize_minHeight = startSize.height );
64
65 CKEDITOR.document.on( 'mousemove', dragHandler );
66 CKEDITOR.document.on( 'mouseup', dragEndHandler );
67
68 if ( editor.document ) {
69 editor.document.on( 'mousemove', dragHandler );
70 editor.document.on( 'mouseup', dragEndHandler );
71 }
72
73 $event.preventDefault && $event.preventDefault();
74 } );
75
76 editor.on( 'destroy', function() {
77 CKEDITOR.tools.removeFunction( mouseDownFn );
78 } );
79
80 editor.on( 'uiSpace', function( event ) {
81 if ( event.data.space == 'bottom' ) {
82 var direction = '';
83 if ( resizeHorizontal && !resizeVertical )
84 direction = ' cke_resizer_horizontal';
85 if ( !resizeHorizontal && resizeVertical )
86 direction = ' cke_resizer_vertical';
87
88 var resizerHtml =
89 '<span' +
90 ' id="' + spaceId + '"' +
91 ' class="cke_resizer' + direction + ' cke_resizer_' + resizeDir + '"' +
92 ' title="' + CKEDITOR.tools.htmlEncode( editor.lang.common.resize ) + '"' +
93 ' onmousedown="CKEDITOR.tools.callFunction(' + mouseDownFn + ', event)"' +
94 '>' +
95 // BLACK LOWER RIGHT TRIANGLE (ltr)
96 // BLACK LOWER LEFT TRIANGLE (rtl)
97 ( resizeDir == 'ltr' ? '\u25E2' : '\u25E3' ) +
98 '</span>';
99
100 // Always sticks the corner of botttom space.
101 resizeDir == 'ltr' && direction == 'ltr' ? event.data.html += resizerHtml : event.data.html = resizerHtml + event.data.html;
102 }
103 }, editor, null, 100 );
104
105 // Toggle the visibility of the resizer when an editor is being maximized or minimized.
106 editor.on( 'maximize', function( event ) {
107 editor.ui.space( 'resizer' )[ event.data == CKEDITOR.TRISTATE_ON ? 'hide' : 'show' ]();
108 } );
109 }
110 }
111} );
112
113/**
114 * The minimum editor width, in pixels, when resizing the editor interface by using the resize handle.
115 * Note: It falls back to editor's actual width if it is smaller than the default value.
116 *
117 * Read more in the [documentation](#!/guide/dev_resize)
118 * and see the [SDK sample](http://sdk.ckeditor.com/samples/resize.html).
119 *
120 * config.resize_minWidth = 500;
121 *
122 * @cfg {Number} [resize_minWidth=750]
123 * @member CKEDITOR.config
124 */
125
126/**
127 * The minimum editor height, in pixels, when resizing the editor interface by using the resize handle.
128 * Note: It falls back to editor's actual height if it is smaller than the default value.
129 *
130 * Read more in the [documentation](#!/guide/dev_resize)
131 * and see the [SDK sample](http://sdk.ckeditor.com/samples/resize.html).
132 *
133 * config.resize_minHeight = 600;
134 *
135 * @cfg {Number} [resize_minHeight=250]
136 * @member CKEDITOR.config
137 */
138
139/**
140 * The maximum editor width, in pixels, when resizing the editor interface by using the resize handle.
141 *
142 * Read more in the [documentation](#!/guide/dev_resize)
143 * and see the [SDK sample](http://sdk.ckeditor.com/samples/resize.html).
144 *
145 * config.resize_maxWidth = 750;
146 *
147 * @cfg {Number} [resize_maxWidth=3000]
148 * @member CKEDITOR.config
149 */
150
151/**
152 * The maximum editor height, in pixels, when resizing the editor interface by using the resize handle.
153 *
154 * Read more in the [documentation](#!/guide/dev_resize)
155 * and see the [SDK sample](http://sdk.ckeditor.com/samples/resize.html).
156 *
157 * config.resize_maxHeight = 600;
158 *
159 * @cfg {Number} [resize_maxHeight=3000]
160 * @member CKEDITOR.config
161 */
162
163/**
164 * Whether to enable the resizing feature. If this feature is disabled, the resize handle will not be visible.
165 *
166 * Read more in the [documentation](#!/guide/dev_resize)
167 * and see the [SDK sample](http://sdk.ckeditor.com/samples/resize.html).
168 *
169 * config.resize_enabled = false;
170 *
171 * @cfg {Boolean} [resize_enabled=true]
172 * @member CKEDITOR.config
173 */
174
175/**
176 * The dimensions for which the editor resizing is enabled. Possible values
177 * are `both`, `vertical`, and `horizontal`.
178 *
179 * Read more in the [documentation](#!/guide/dev_resize)
180 * and see the [SDK sample](http://sdk.ckeditor.com/samples/resize.html).
181 *
182 * config.resize_dir = 'both';
183 *
184 * @since 3.3
185 * @cfg {String} [resize_dir='vertical']
186 * @member CKEDITOR.config
187 */
diff --git a/sources/plugins/richcombo/plugin.js b/sources/plugins/richcombo/plugin.js
new file mode 100644
index 0000000..231a7c7
--- /dev/null
+++ b/sources/plugins/richcombo/plugin.js
@@ -0,0 +1,434 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.add( 'richcombo', {
7 requires: 'floatpanel,listblock,button',
8
9 beforeInit: function( editor ) {
10 editor.ui.addHandler( CKEDITOR.UI_RICHCOMBO, CKEDITOR.ui.richCombo.handler );
11 }
12} );
13
14( function() {
15 var template = '<span id="{id}"' +
16 ' class="cke_combo cke_combo__{name} {cls}"' +
17 ' role="presentation">' +
18 '<span id="{id}_label" class="cke_combo_label">{label}</span>' +
19 '<a class="cke_combo_button" title="{title}" tabindex="-1"' +
20 ( CKEDITOR.env.gecko && !CKEDITOR.env.hc ? '' : ' href="javascript:void(\'{titleJs}\')"' ) +
21 ' hidefocus="true"' +
22 ' role="button"' +
23 ' aria-labelledby="{id}_label"' +
24 ' aria-haspopup="true"';
25
26 // Some browsers don't cancel key events in the keydown but in the
27 // keypress.
28 // TODO: Check if really needed.
29 if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )
30 template += ' onkeypress="return false;"';
31
32 // With Firefox, we need to force the button to redraw, otherwise it
33 // will remain in the focus state.
34 if ( CKEDITOR.env.gecko )
35 template += ' onblur="this.style.cssText = this.style.cssText;"';
36
37 template +=
38 ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event,this);"' +
39 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' +
40 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188
41 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' +
42 '<span id="{id}_text" class="cke_combo_text cke_combo_inlinelabel">{label}</span>' +
43 '<span class="cke_combo_open">' +
44 '<span class="cke_combo_arrow">' +
45 // BLACK DOWN-POINTING TRIANGLE
46 ( CKEDITOR.env.hc ? '&#9660;' : CKEDITOR.env.air ? '&nbsp;' : '' ) +
47 '</span>' +
48 '</span>' +
49 '</a>' +
50 '</span>';
51
52 var rcomboTpl = CKEDITOR.addTemplate( 'combo', template );
53
54 /**
55 * Button UI element.
56 *
57 * @readonly
58 * @property {String} [='richcombo']
59 * @member CKEDITOR
60 */
61 CKEDITOR.UI_RICHCOMBO = 'richcombo';
62
63 /**
64 * @class
65 * @todo
66 */
67 CKEDITOR.ui.richCombo = CKEDITOR.tools.createClass( {
68 $: function( definition ) {
69 // Copy all definition properties to this object.
70 CKEDITOR.tools.extend( this, definition,
71 // Set defaults.
72 {
73 // The combo won't participate in toolbar grouping.
74 canGroup: false,
75 title: definition.label,
76 modes: { wysiwyg: 1 },
77 editorFocus: 1
78 } );
79
80 // We don't want the panel definition in this object.
81 var panelDefinition = this.panel || {};
82 delete this.panel;
83
84 this.id = CKEDITOR.tools.getNextNumber();
85
86 this.document = ( panelDefinition.parent && panelDefinition.parent.getDocument() ) || CKEDITOR.document;
87
88 panelDefinition.className = 'cke_combopanel';
89 panelDefinition.block = {
90 multiSelect: panelDefinition.multiSelect,
91 attributes: panelDefinition.attributes
92 };
93 panelDefinition.toolbarRelated = true;
94
95 this._ = {
96 panelDefinition: panelDefinition,
97 items: {}
98 };
99 },
100
101 proto: {
102 renderHtml: function( editor ) {
103 var output = [];
104 this.render( editor, output );
105 return output.join( '' );
106 },
107
108 /**
109 * Renders the combo.
110 *
111 * @param {CKEDITOR.editor} editor The editor instance which this button is
112 * to be used by.
113 * @param {Array} output The output array to which append the HTML relative
114 * to this button.
115 */
116 render: function( editor, output ) {
117 var env = CKEDITOR.env;
118
119 var id = 'cke_' + this.id;
120 var clickFn = CKEDITOR.tools.addFunction( function( el ) {
121 // Restore locked selection in Opera.
122 if ( selLocked ) {
123 editor.unlockSelection( 1 );
124 selLocked = 0;
125 }
126 instance.execute( el );
127 }, this );
128
129 var combo = this;
130 var instance = {
131 id: id,
132 combo: this,
133 focus: function() {
134 var element = CKEDITOR.document.getById( id ).getChild( 1 );
135 element.focus();
136 },
137 execute: function( el ) {
138 var _ = combo._;
139
140 if ( _.state == CKEDITOR.TRISTATE_DISABLED )
141 return;
142
143 combo.createPanel( editor );
144
145 if ( _.on ) {
146 _.panel.hide();
147 return;
148 }
149
150 combo.commit();
151 var value = combo.getValue();
152 if ( value )
153 _.list.mark( value );
154 else
155 _.list.unmarkAll();
156
157 _.panel.showBlock( combo.id, new CKEDITOR.dom.element( el ), 4 );
158 },
159 clickFn: clickFn
160 };
161
162 function updateState() {
163 // Don't change state while richcombo is active (#11793).
164 if ( this.getState() == CKEDITOR.TRISTATE_ON )
165 return;
166
167 var state = this.modes[ editor.mode ] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
168
169 if ( editor.readOnly && !this.readOnly )
170 state = CKEDITOR.TRISTATE_DISABLED;
171
172 this.setState( state );
173 this.setValue( '' );
174
175 // Let plugin to disable button.
176 if ( state != CKEDITOR.TRISTATE_DISABLED && this.refresh )
177 this.refresh();
178 }
179
180 // Update status when activeFilter, mode, selection or readOnly changes.
181 editor.on( 'activeFilterChange', updateState, this );
182 editor.on( 'mode', updateState, this );
183 editor.on( 'selectionChange', updateState, this );
184 // If this combo is sensitive to readOnly state, update it accordingly.
185 !this.readOnly && editor.on( 'readOnly', updateState, this );
186
187 var keyDownFn = CKEDITOR.tools.addFunction( function( ev, element ) {
188 ev = new CKEDITOR.dom.event( ev );
189
190 var keystroke = ev.getKeystroke();
191
192 // ARROW-DOWN
193 // This call is duplicated in plugins/toolbar/plugin.js in itemKeystroke().
194 // Move focus to the first element after drop down was opened by the arrow down key.
195 if ( keystroke == 40 ) {
196 editor.once( 'panelShow', function( evt ) {
197 evt.data._.panel._.currentBlock.onKeyDown( 40 );
198 } );
199 }
200
201 switch ( keystroke ) {
202 case 13: // ENTER
203 case 32: // SPACE
204 case 40: // ARROW-DOWN
205 // Show panel
206 CKEDITOR.tools.callFunction( clickFn, element );
207 break;
208 default:
209 // Delegate the default behavior to toolbar button key handling.
210 instance.onkey( instance, keystroke );
211 }
212
213 // Avoid subsequent focus grab on editor document.
214 ev.preventDefault();
215 } );
216
217 var focusFn = CKEDITOR.tools.addFunction( function() {
218 instance.onfocus && instance.onfocus();
219 } );
220
221 var selLocked = 0;
222
223 // For clean up
224 instance.keyDownFn = keyDownFn;
225
226 var params = {
227 id: id,
228 name: this.name || this.command,
229 label: this.label,
230 title: this.title,
231 cls: this.className || '',
232 titleJs: env.gecko && !env.hc ? '' : ( this.title || '' ).replace( "'", '' ),
233 keydownFn: keyDownFn,
234 focusFn: focusFn,
235 clickFn: clickFn
236 };
237
238 rcomboTpl.output( params, output );
239
240 if ( this.onRender )
241 this.onRender();
242
243 return instance;
244 },
245
246 createPanel: function( editor ) {
247 if ( this._.panel )
248 return;
249
250 var panelDefinition = this._.panelDefinition,
251 panelBlockDefinition = this._.panelDefinition.block,
252 panelParentElement = panelDefinition.parent || CKEDITOR.document.getBody(),
253 namedPanelCls = 'cke_combopanel__' + this.name,
254 panel = new CKEDITOR.ui.floatPanel( editor, panelParentElement, panelDefinition ),
255 list = panel.addListBlock( this.id, panelBlockDefinition ),
256 me = this;
257
258 panel.onShow = function() {
259 this.element.addClass( namedPanelCls );
260
261 me.setState( CKEDITOR.TRISTATE_ON );
262
263 me._.on = 1;
264
265 me.editorFocus && !editor.focusManager.hasFocus && editor.focus();
266
267 if ( me.onOpen )
268 me.onOpen();
269
270 // The "panelShow" event is fired assinchronously, after the
271 // onShow method call.
272 editor.once( 'panelShow', function() {
273 list.focus( !list.multiSelect && me.getValue() );
274 } );
275 };
276
277 panel.onHide = function( preventOnClose ) {
278 this.element.removeClass( namedPanelCls );
279
280 me.setState( me.modes && me.modes[ editor.mode ] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED );
281
282 me._.on = 0;
283
284 if ( !preventOnClose && me.onClose )
285 me.onClose();
286 };
287
288 panel.onEscape = function() {
289 // Hide drop-down with focus returned.
290 panel.hide( 1 );
291 };
292
293 list.onClick = function( value, marked ) {
294
295 if ( me.onClick )
296 me.onClick.call( me, value, marked );
297
298 panel.hide();
299 };
300
301 this._.panel = panel;
302 this._.list = list;
303
304 panel.getBlock( this.id ).onHide = function() {
305 me._.on = 0;
306 me.setState( CKEDITOR.TRISTATE_OFF );
307 };
308
309 if ( this.init )
310 this.init();
311 },
312
313 setValue: function( value, text ) {
314 this._.value = value;
315
316 var textElement = this.document.getById( 'cke_' + this.id + '_text' );
317 if ( textElement ) {
318 if ( !( value || text ) ) {
319 text = this.label;
320 textElement.addClass( 'cke_combo_inlinelabel' );
321 } else {
322 textElement.removeClass( 'cke_combo_inlinelabel' );
323 }
324
325 textElement.setText( typeof text != 'undefined' ? text : value );
326 }
327 },
328
329 getValue: function() {
330 return this._.value || '';
331 },
332
333 unmarkAll: function() {
334 this._.list.unmarkAll();
335 },
336
337 mark: function( value ) {
338 this._.list.mark( value );
339 },
340
341 hideItem: function( value ) {
342 this._.list.hideItem( value );
343 },
344
345 hideGroup: function( groupTitle ) {
346 this._.list.hideGroup( groupTitle );
347 },
348
349 showAll: function() {
350 this._.list.showAll();
351 },
352
353 add: function( value, html, text ) {
354 this._.items[ value ] = text || value;
355 this._.list.add( value, html, text );
356 },
357
358 startGroup: function( title ) {
359 this._.list.startGroup( title );
360 },
361
362 commit: function() {
363 if ( !this._.committed ) {
364 this._.list.commit();
365 this._.committed = 1;
366 CKEDITOR.ui.fire( 'ready', this );
367 }
368 this._.committed = 1;
369 },
370
371 setState: function( state ) {
372 if ( this._.state == state )
373 return;
374
375 var el = this.document.getById( 'cke_' + this.id );
376 el.setState( state, 'cke_combo' );
377
378 state == CKEDITOR.TRISTATE_DISABLED ?
379 el.setAttribute( 'aria-disabled', true ) :
380 el.removeAttribute( 'aria-disabled' );
381
382 this._.state = state;
383 },
384
385 getState: function() {
386 return this._.state;
387 },
388
389 enable: function() {
390 if ( this._.state == CKEDITOR.TRISTATE_DISABLED )
391 this.setState( this._.lastState );
392 },
393
394 disable: function() {
395 if ( this._.state != CKEDITOR.TRISTATE_DISABLED ) {
396 this._.lastState = this._.state;
397 this.setState( CKEDITOR.TRISTATE_DISABLED );
398 }
399 }
400 },
401
402 /**
403 * Represents richCombo handler object.
404 *
405 * @class CKEDITOR.ui.richCombo.handler
406 * @singleton
407 * @extends CKEDITOR.ui.handlerDefinition
408 */
409 statics: {
410 handler: {
411 /**
412 * Transforms a richCombo definition in a {@link CKEDITOR.ui.richCombo} instance.
413 *
414 * @param {Object} definition
415 * @returns {CKEDITOR.ui.richCombo}
416 */
417 create: function( definition ) {
418 return new CKEDITOR.ui.richCombo( definition );
419 }
420 }
421 }
422 } );
423
424 /**
425 * @param {String} name
426 * @param {Object} definition
427 * @member CKEDITOR.ui
428 * @todo
429 */
430 CKEDITOR.ui.prototype.addRichCombo = function( name, definition ) {
431 this.add( name, CKEDITOR.UI_RICHCOMBO, definition );
432 };
433
434} )();
diff --git a/sources/plugins/showborders/plugin.js b/sources/plugins/showborders/plugin.js
new file mode 100644
index 0000000..7dbfb59
--- /dev/null
+++ b/sources/plugins/showborders/plugin.js
@@ -0,0 +1,174 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The "show border" plugin. The command display visible outline
8 * border line around all table elements if table doesn't have a none-zero 'border' attribute specified.
9 */
10
11( function() {
12 var commandDefinition = {
13 preserveState: true,
14 editorFocus: false,
15 readOnly: 1,
16
17 exec: function( editor ) {
18 this.toggleState();
19 this.refresh( editor );
20 },
21
22 refresh: function( editor ) {
23 if ( editor.document ) {
24 var funcName = ( this.state == CKEDITOR.TRISTATE_ON ) ? 'attachClass' : 'removeClass';
25 editor.editable()[ funcName ]( 'cke_show_borders' );
26 }
27 }
28 };
29
30 var showBorderClassName = 'cke_show_border';
31
32 CKEDITOR.plugins.add( 'showborders', {
33 modes: { 'wysiwyg': 1 },
34
35 onLoad: function() {
36 var cssStyleText,
37 cssTemplate =
38 // TODO: For IE6, we don't have child selector support,
39 // where nested table cells could be incorrect.
40 ( CKEDITOR.env.ie6Compat ? [
41 '.%1 table.%2,',
42 '.%1 table.%2 td, .%1 table.%2 th',
43 '{',
44 'border : #d3d3d3 1px dotted',
45 '}'
46 ] : [
47 '.%1 table.%2,',
48 '.%1 table.%2 > tr > td, .%1 table.%2 > tr > th,',
49 '.%1 table.%2 > tbody > tr > td, .%1 table.%2 > tbody > tr > th,',
50 '.%1 table.%2 > thead > tr > td, .%1 table.%2 > thead > tr > th,',
51 '.%1 table.%2 > tfoot > tr > td, .%1 table.%2 > tfoot > tr > th',
52 '{',
53 'border : #d3d3d3 1px dotted',
54 '}'
55 ] ).join( '' );
56
57 cssStyleText = cssTemplate.replace( /%2/g, showBorderClassName ).replace( /%1/g, 'cke_show_borders ' );
58
59 CKEDITOR.addCss( cssStyleText );
60 },
61
62 init: function( editor ) {
63
64 var command = editor.addCommand( 'showborders', commandDefinition );
65 command.canUndo = false;
66
67 if ( editor.config.startupShowBorders !== false )
68 command.setState( CKEDITOR.TRISTATE_ON );
69
70 // Refresh the command on setData.
71 editor.on( 'mode', function() {
72 if ( command.state != CKEDITOR.TRISTATE_DISABLED )
73 command.refresh( editor );
74 }, null, null, 100 );
75
76 // Refresh the command on wysiwyg frame reloads.
77 editor.on( 'contentDom', function() {
78 if ( command.state != CKEDITOR.TRISTATE_DISABLED )
79 command.refresh( editor );
80 } );
81
82 editor.on( 'removeFormatCleanup', function( evt ) {
83 var element = evt.data;
84 if ( editor.getCommand( 'showborders' ).state == CKEDITOR.TRISTATE_ON && element.is( 'table' ) && ( !element.hasAttribute( 'border' ) || parseInt( element.getAttribute( 'border' ), 10 ) <= 0 ) )
85 element.addClass( showBorderClassName );
86 } );
87 },
88
89 afterInit: function( editor ) {
90 var dataProcessor = editor.dataProcessor,
91 dataFilter = dataProcessor && dataProcessor.dataFilter,
92 htmlFilter = dataProcessor && dataProcessor.htmlFilter;
93
94 if ( dataFilter ) {
95 dataFilter.addRules( {
96 elements: {
97 'table': function( element ) {
98 var attributes = element.attributes,
99 cssClass = attributes[ 'class' ],
100 border = parseInt( attributes.border, 10 );
101
102 if ( ( !border || border <= 0 ) && ( !cssClass || cssClass.indexOf( showBorderClassName ) == -1 ) )
103 attributes[ 'class' ] = ( cssClass || '' ) + ' ' + showBorderClassName;
104 }
105 }
106 } );
107 }
108
109 if ( htmlFilter ) {
110 htmlFilter.addRules( {
111 elements: {
112 'table': function( table ) {
113 var attributes = table.attributes,
114 cssClass = attributes[ 'class' ];
115
116 cssClass && ( attributes[ 'class' ] = cssClass.replace( showBorderClassName, '' ).replace( /\s{2}/, ' ' ).replace( /^\s+|\s+$/, '' ) );
117 }
118 }
119 } );
120 }
121 }
122 } );
123
124 // Table dialog must be aware of it.
125 CKEDITOR.on( 'dialogDefinition', function( ev ) {
126 var dialogName = ev.data.name;
127
128 if ( dialogName == 'table' || dialogName == 'tableProperties' ) {
129 var dialogDefinition = ev.data.definition,
130 infoTab = dialogDefinition.getContents( 'info' ),
131 borderField = infoTab.get( 'txtBorder' ),
132 originalCommit = borderField.commit;
133
134 borderField.commit = CKEDITOR.tools.override( originalCommit, function( org ) {
135 return function( data, selectedTable ) {
136 org.apply( this, arguments );
137 var value = parseInt( this.getValue(), 10 );
138 selectedTable[ ( !value || value <= 0 ) ? 'addClass' : 'removeClass' ]( showBorderClassName );
139 };
140 } );
141
142 var advTab = dialogDefinition.getContents( 'advanced' ),
143 classField = advTab && advTab.get( 'advCSSClasses' );
144
145 if ( classField ) {
146 classField.setup = CKEDITOR.tools.override( classField.setup, function( originalSetup ) {
147 return function() {
148 originalSetup.apply( this, arguments );
149 this.setValue( this.getValue().replace( /cke_show_border/, '' ) );
150 };
151 } );
152
153 classField.commit = CKEDITOR.tools.override( classField.commit, function( originalCommit ) {
154 return function( data, element ) {
155 originalCommit.apply( this, arguments );
156
157 if ( !parseInt( element.getAttribute( 'border' ), 10 ) )
158 element.addClass( 'cke_show_border' );
159 };
160 } );
161 }
162 }
163 } );
164
165} )();
166
167/**
168 * Whether to automatically enable the "show borders" command when the editor loads.
169 *
170 * config.startupShowBorders = false;
171 *
172 * @cfg {Boolean} [startupShowBorders=true]
173 * @member CKEDITOR.config
174 */
diff --git a/sources/plugins/sourcearea/icons/hidpi/source-rtl.png b/sources/plugins/sourcearea/icons/hidpi/source-rtl.png
new file mode 100644
index 0000000..c95da32
--- /dev/null
+++ b/sources/plugins/sourcearea/icons/hidpi/source-rtl.png
Binary files differ
diff --git a/sources/plugins/sourcearea/icons/hidpi/source.png b/sources/plugins/sourcearea/icons/hidpi/source.png
new file mode 100644
index 0000000..2f3eae1
--- /dev/null
+++ b/sources/plugins/sourcearea/icons/hidpi/source.png
Binary files differ
diff --git a/sources/plugins/sourcearea/icons/source-rtl.png b/sources/plugins/sourcearea/icons/source-rtl.png
new file mode 100644
index 0000000..5353eee
--- /dev/null
+++ b/sources/plugins/sourcearea/icons/source-rtl.png
Binary files differ
diff --git a/sources/plugins/sourcearea/icons/source.png b/sources/plugins/sourcearea/icons/source.png
new file mode 100644
index 0000000..0783e85
--- /dev/null
+++ b/sources/plugins/sourcearea/icons/source.png
Binary files differ
diff --git a/sources/plugins/sourcearea/lang/af.js b/sources/plugins/sourcearea/lang/af.js
new file mode 100644
index 0000000..a5a499e
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/af.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'af', {
6 toolbar: 'Bron'
7} );
diff --git a/sources/plugins/sourcearea/lang/ar.js b/sources/plugins/sourcearea/lang/ar.js
new file mode 100644
index 0000000..40808ac
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ar.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ar', {
6 toolbar: 'المصدر'
7} );
diff --git a/sources/plugins/sourcearea/lang/az.js b/sources/plugins/sourcearea/lang/az.js
new file mode 100644
index 0000000..9aeff4b
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/az.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'az', {
6 toolbar: 'HTML mənbəyini göstər'
7} );
diff --git a/sources/plugins/sourcearea/lang/bg.js b/sources/plugins/sourcearea/lang/bg.js
new file mode 100644
index 0000000..4902635
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/bg.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'bg', {
6 toolbar: 'Изходен код'
7} );
diff --git a/sources/plugins/sourcearea/lang/bn.js b/sources/plugins/sourcearea/lang/bn.js
new file mode 100644
index 0000000..b050458
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/bn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'bn', {
6 toolbar: 'উৎস'
7} );
diff --git a/sources/plugins/sourcearea/lang/bs.js b/sources/plugins/sourcearea/lang/bs.js
new file mode 100644
index 0000000..c0b5e09
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/bs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'bs', {
6 toolbar: 'HTML kôd'
7} );
diff --git a/sources/plugins/sourcearea/lang/ca.js b/sources/plugins/sourcearea/lang/ca.js
new file mode 100644
index 0000000..c958e9b
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ca', {
6 toolbar: 'Codi font'
7} );
diff --git a/sources/plugins/sourcearea/lang/cs.js b/sources/plugins/sourcearea/lang/cs.js
new file mode 100644
index 0000000..dccf574
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/cs.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'cs', {
6 toolbar: 'Zdroj'
7} );
diff --git a/sources/plugins/sourcearea/lang/cy.js b/sources/plugins/sourcearea/lang/cy.js
new file mode 100644
index 0000000..b8ce201
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/cy.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'cy', {
6 toolbar: 'HTML'
7} );
diff --git a/sources/plugins/sourcearea/lang/da.js b/sources/plugins/sourcearea/lang/da.js
new file mode 100644
index 0000000..bf02c14
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/da.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'da', {
6 toolbar: 'Kilde'
7} );
diff --git a/sources/plugins/sourcearea/lang/de-ch.js b/sources/plugins/sourcearea/lang/de-ch.js
new file mode 100644
index 0000000..c039623
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/de-ch.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'de-ch', {
6 toolbar: 'Quellcode'
7} );
diff --git a/sources/plugins/sourcearea/lang/de.js b/sources/plugins/sourcearea/lang/de.js
new file mode 100644
index 0000000..dfa995f
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/de.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'de', {
6 toolbar: 'Quellcode'
7} );
diff --git a/sources/plugins/sourcearea/lang/el.js b/sources/plugins/sourcearea/lang/el.js
new file mode 100644
index 0000000..0a8d8a8
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/el.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'el', {
6 toolbar: 'Κώδικας'
7} );
diff --git a/sources/plugins/sourcearea/lang/en-au.js b/sources/plugins/sourcearea/lang/en-au.js
new file mode 100644
index 0000000..10e7843
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/en-au.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'en-au', {
6 toolbar: 'Source'
7} );
diff --git a/sources/plugins/sourcearea/lang/en-ca.js b/sources/plugins/sourcearea/lang/en-ca.js
new file mode 100644
index 0000000..f5e61da
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/en-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'en-ca', {
6 toolbar: 'Source'
7} );
diff --git a/sources/plugins/sourcearea/lang/en-gb.js b/sources/plugins/sourcearea/lang/en-gb.js
new file mode 100644
index 0000000..5d876aa
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/en-gb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'en-gb', {
6 toolbar: 'Source'
7} );
diff --git a/sources/plugins/sourcearea/lang/en.js b/sources/plugins/sourcearea/lang/en.js
new file mode 100644
index 0000000..90a24e9
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/en.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'en', {
6 toolbar: 'Source'
7} );
diff --git a/sources/plugins/sourcearea/lang/eo.js b/sources/plugins/sourcearea/lang/eo.js
new file mode 100644
index 0000000..613de63
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/eo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'eo', {
6 toolbar: 'Fonto'
7} );
diff --git a/sources/plugins/sourcearea/lang/es.js b/sources/plugins/sourcearea/lang/es.js
new file mode 100644
index 0000000..014a967
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/es.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'es', {
6 toolbar: 'Fuente HTML'
7} );
diff --git a/sources/plugins/sourcearea/lang/et.js b/sources/plugins/sourcearea/lang/et.js
new file mode 100644
index 0000000..9a73ece
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/et.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'et', {
6 toolbar: 'Lähtekood'
7} );
diff --git a/sources/plugins/sourcearea/lang/eu.js b/sources/plugins/sourcearea/lang/eu.js
new file mode 100644
index 0000000..350b3e2
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/eu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'eu', {
6 toolbar: 'Iturburua'
7} );
diff --git a/sources/plugins/sourcearea/lang/fa.js b/sources/plugins/sourcearea/lang/fa.js
new file mode 100644
index 0000000..40757c0
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/fa.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'fa', {
6 toolbar: 'منبع'
7} );
diff --git a/sources/plugins/sourcearea/lang/fi.js b/sources/plugins/sourcearea/lang/fi.js
new file mode 100644
index 0000000..fba260e
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/fi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'fi', {
6 toolbar: 'Koodi'
7} );
diff --git a/sources/plugins/sourcearea/lang/fo.js b/sources/plugins/sourcearea/lang/fo.js
new file mode 100644
index 0000000..f384c40
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/fo.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'fo', {
6 toolbar: 'Kelda'
7} );
diff --git a/sources/plugins/sourcearea/lang/fr-ca.js b/sources/plugins/sourcearea/lang/fr-ca.js
new file mode 100644
index 0000000..707686f
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/fr-ca.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'fr-ca', {
6 toolbar: 'Source'
7} );
diff --git a/sources/plugins/sourcearea/lang/fr.js b/sources/plugins/sourcearea/lang/fr.js
new file mode 100644
index 0000000..57d4f5f
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/fr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'fr', {
6 toolbar: 'Source'
7} );
diff --git a/sources/plugins/sourcearea/lang/gl.js b/sources/plugins/sourcearea/lang/gl.js
new file mode 100644
index 0000000..c68a1da
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/gl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'gl', {
6 toolbar: 'Orixe'
7} );
diff --git a/sources/plugins/sourcearea/lang/gu.js b/sources/plugins/sourcearea/lang/gu.js
new file mode 100644
index 0000000..a1c9b66
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/gu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'gu', {
6 toolbar: 'મૂળ કે પ્રાથમિક દસ્તાવેજ'
7} );
diff --git a/sources/plugins/sourcearea/lang/he.js b/sources/plugins/sourcearea/lang/he.js
new file mode 100644
index 0000000..8b0f28d
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/he.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'he', {
6 toolbar: 'מקור'
7} );
diff --git a/sources/plugins/sourcearea/lang/hi.js b/sources/plugins/sourcearea/lang/hi.js
new file mode 100644
index 0000000..0d8cc1b
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/hi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'hi', {
6 toolbar: 'सोर्स'
7} );
diff --git a/sources/plugins/sourcearea/lang/hr.js b/sources/plugins/sourcearea/lang/hr.js
new file mode 100644
index 0000000..dca2202
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/hr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'hr', {
6 toolbar: 'Kôd'
7} );
diff --git a/sources/plugins/sourcearea/lang/hu.js b/sources/plugins/sourcearea/lang/hu.js
new file mode 100644
index 0000000..9628fe4
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/hu.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'hu', {
6 toolbar: 'Forráskód'
7} );
diff --git a/sources/plugins/sourcearea/lang/id.js b/sources/plugins/sourcearea/lang/id.js
new file mode 100644
index 0000000..f8e25c5
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/id.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'id', {
6 toolbar: 'Sumber'
7} );
diff --git a/sources/plugins/sourcearea/lang/is.js b/sources/plugins/sourcearea/lang/is.js
new file mode 100644
index 0000000..a90207d
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/is.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'is', {
6 toolbar: 'Kóði'
7} );
diff --git a/sources/plugins/sourcearea/lang/it.js b/sources/plugins/sourcearea/lang/it.js
new file mode 100644
index 0000000..b445a21
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/it.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'it', {
6 toolbar: 'Sorgente'
7} );
diff --git a/sources/plugins/sourcearea/lang/ja.js b/sources/plugins/sourcearea/lang/ja.js
new file mode 100644
index 0000000..3f026b6
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ja.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ja', {
6 toolbar: 'ソース'
7} );
diff --git a/sources/plugins/sourcearea/lang/ka.js b/sources/plugins/sourcearea/lang/ka.js
new file mode 100644
index 0000000..f06b130
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ka.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ka', {
6 toolbar: 'კოდები'
7} );
diff --git a/sources/plugins/sourcearea/lang/km.js b/sources/plugins/sourcearea/lang/km.js
new file mode 100644
index 0000000..9cd4769
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/km.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'km', {
6 toolbar: 'អក្សរ​កូដ'
7} );
diff --git a/sources/plugins/sourcearea/lang/ko.js b/sources/plugins/sourcearea/lang/ko.js
new file mode 100644
index 0000000..26fe7ff
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ko.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ko', {
6 toolbar: '소스'
7} );
diff --git a/sources/plugins/sourcearea/lang/ku.js b/sources/plugins/sourcearea/lang/ku.js
new file mode 100644
index 0000000..a3f1263
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ku.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ku', {
6 toolbar: 'سەرچاوە'
7} );
diff --git a/sources/plugins/sourcearea/lang/lt.js b/sources/plugins/sourcearea/lang/lt.js
new file mode 100644
index 0000000..c3304dc
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/lt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'lt', {
6 toolbar: 'Šaltinis'
7} );
diff --git a/sources/plugins/sourcearea/lang/lv.js b/sources/plugins/sourcearea/lang/lv.js
new file mode 100644
index 0000000..c3ef246
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/lv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'lv', {
6 toolbar: 'HTML kods'
7} );
diff --git a/sources/plugins/sourcearea/lang/mk.js b/sources/plugins/sourcearea/lang/mk.js
new file mode 100644
index 0000000..eeccabd
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/mk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'mk', {
6 toolbar: 'Source' // MISSING
7} );
diff --git a/sources/plugins/sourcearea/lang/mn.js b/sources/plugins/sourcearea/lang/mn.js
new file mode 100644
index 0000000..a7c1288
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/mn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'mn', {
6 toolbar: 'Код'
7} );
diff --git a/sources/plugins/sourcearea/lang/ms.js b/sources/plugins/sourcearea/lang/ms.js
new file mode 100644
index 0000000..f09ac53
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ms.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ms', {
6 toolbar: 'Sumber'
7} );
diff --git a/sources/plugins/sourcearea/lang/nb.js b/sources/plugins/sourcearea/lang/nb.js
new file mode 100644
index 0000000..87b75a8
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/nb.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'nb', {
6 toolbar: 'Kilde'
7} );
diff --git a/sources/plugins/sourcearea/lang/nl.js b/sources/plugins/sourcearea/lang/nl.js
new file mode 100644
index 0000000..dc61f34
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/nl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'nl', {
6 toolbar: 'Broncode'
7} );
diff --git a/sources/plugins/sourcearea/lang/no.js b/sources/plugins/sourcearea/lang/no.js
new file mode 100644
index 0000000..86f386d
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/no.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'no', {
6 toolbar: 'Kilde'
7} );
diff --git a/sources/plugins/sourcearea/lang/oc.js b/sources/plugins/sourcearea/lang/oc.js
new file mode 100644
index 0000000..90f418f
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/oc.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'oc', {
6 toolbar: 'Font'
7} );
diff --git a/sources/plugins/sourcearea/lang/pl.js b/sources/plugins/sourcearea/lang/pl.js
new file mode 100644
index 0000000..48734a8
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/pl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'pl', {
6 toolbar: 'Źródło dokumentu'
7} );
diff --git a/sources/plugins/sourcearea/lang/pt-br.js b/sources/plugins/sourcearea/lang/pt-br.js
new file mode 100644
index 0000000..54e3ce1
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/pt-br.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'pt-br', {
6 toolbar: 'Código-Fonte'
7} );
diff --git a/sources/plugins/sourcearea/lang/pt.js b/sources/plugins/sourcearea/lang/pt.js
new file mode 100644
index 0000000..7fd6c23
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/pt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'pt', {
6 toolbar: 'Fonte'
7} );
diff --git a/sources/plugins/sourcearea/lang/ro.js b/sources/plugins/sourcearea/lang/ro.js
new file mode 100644
index 0000000..5eb00c4
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ro.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ro', {
6 toolbar: 'Sursa'
7} );
diff --git a/sources/plugins/sourcearea/lang/ru.js b/sources/plugins/sourcearea/lang/ru.js
new file mode 100644
index 0000000..304695c
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ru.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ru', {
6 toolbar: 'Источник'
7} );
diff --git a/sources/plugins/sourcearea/lang/si.js b/sources/plugins/sourcearea/lang/si.js
new file mode 100644
index 0000000..22996eb
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/si.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'si', {
6 toolbar: 'මුලාශ්‍රය'
7} );
diff --git a/sources/plugins/sourcearea/lang/sk.js b/sources/plugins/sourcearea/lang/sk.js
new file mode 100644
index 0000000..aed1c61
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/sk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'sk', {
6 toolbar: 'Zdroj'
7} );
diff --git a/sources/plugins/sourcearea/lang/sl.js b/sources/plugins/sourcearea/lang/sl.js
new file mode 100644
index 0000000..b9a2b5f
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/sl.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'sl', {
6 toolbar: 'Izvorna koda'
7} );
diff --git a/sources/plugins/sourcearea/lang/sq.js b/sources/plugins/sourcearea/lang/sq.js
new file mode 100644
index 0000000..f4512ce
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/sq.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'sq', {
6 toolbar: 'Burimi'
7} );
diff --git a/sources/plugins/sourcearea/lang/sr-latn.js b/sources/plugins/sourcearea/lang/sr-latn.js
new file mode 100644
index 0000000..0d8ebd7
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/sr-latn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'sr-latn', {
6 toolbar: 'Kôd'
7} );
diff --git a/sources/plugins/sourcearea/lang/sr.js b/sources/plugins/sourcearea/lang/sr.js
new file mode 100644
index 0000000..a872556
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/sr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'sr', {
6 toolbar: 'Kôд'
7} );
diff --git a/sources/plugins/sourcearea/lang/sv.js b/sources/plugins/sourcearea/lang/sv.js
new file mode 100644
index 0000000..a05d49d
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/sv.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'sv', {
6 toolbar: 'Källa'
7} );
diff --git a/sources/plugins/sourcearea/lang/th.js b/sources/plugins/sourcearea/lang/th.js
new file mode 100644
index 0000000..4afb9bc
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/th.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'th', {
6 toolbar: 'ดูรหัส HTML'
7} );
diff --git a/sources/plugins/sourcearea/lang/tr.js b/sources/plugins/sourcearea/lang/tr.js
new file mode 100644
index 0000000..7a9f70a
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/tr.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'tr', {
6 toolbar: 'Kaynak'
7} );
diff --git a/sources/plugins/sourcearea/lang/tt.js b/sources/plugins/sourcearea/lang/tt.js
new file mode 100644
index 0000000..ca05df1
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/tt.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'tt', {
6 toolbar: 'Чыганак'
7} );
diff --git a/sources/plugins/sourcearea/lang/ug.js b/sources/plugins/sourcearea/lang/ug.js
new file mode 100644
index 0000000..791c596
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/ug.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'ug', {
6 toolbar: 'مەنبە'
7} );
diff --git a/sources/plugins/sourcearea/lang/uk.js b/sources/plugins/sourcearea/lang/uk.js
new file mode 100644
index 0000000..905af47
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/uk.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'uk', {
6 toolbar: 'Джерело'
7} );
diff --git a/sources/plugins/sourcearea/lang/vi.js b/sources/plugins/sourcearea/lang/vi.js
new file mode 100644
index 0000000..df7eb93
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/vi.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'vi', {
6 toolbar: 'Mã HTML'
7} );
diff --git a/sources/plugins/sourcearea/lang/zh-cn.js b/sources/plugins/sourcearea/lang/zh-cn.js
new file mode 100644
index 0000000..a98c869
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/zh-cn.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'zh-cn', {
6 toolbar: '源码'
7} );
diff --git a/sources/plugins/sourcearea/lang/zh.js b/sources/plugins/sourcearea/lang/zh.js
new file mode 100644
index 0000000..043dd11
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/zh.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'sourcearea', 'zh', {
6 toolbar: '原始碼'
7} );
diff --git a/sources/plugins/sourcearea/plugin.js b/sources/plugins/sourcearea/plugin.js
new file mode 100644
index 0000000..837bc30
--- /dev/null
+++ b/sources/plugins/sourcearea/plugin.js
@@ -0,0 +1,168 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The Source Editing Area plugin. It registers the "source" editing
8 * mode, which displays raw HTML data being edited in the editor.
9 */
10
11( function() {
12 CKEDITOR.plugins.add( 'sourcearea', {
13 // jscs:disable maximumLineLength
14 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
15 // jscs:enable maximumLineLength
16 icons: 'source,source-rtl', // %REMOVE_LINE_CORE%
17 hidpi: true, // %REMOVE_LINE_CORE%
18 init: function( editor ) {
19 // Source mode in inline editors is only available through the "sourcedialog" plugin.
20 if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE )
21 return;
22
23 var sourcearea = CKEDITOR.plugins.sourcearea;
24
25 editor.addMode( 'source', function( callback ) {
26 var contentsSpace = editor.ui.space( 'contents' ),
27 textarea = contentsSpace.getDocument().createElement( 'textarea' );
28
29 textarea.setStyles(
30 CKEDITOR.tools.extend( {
31 // IE7 has overflow the <textarea> from wrapping table cell.
32 width: CKEDITOR.env.ie7Compat ? '99%' : '100%',
33 height: '100%',
34 resize: 'none',
35 outline: 'none',
36 'text-align': 'left'
37 },
38 CKEDITOR.tools.cssVendorPrefix( 'tab-size', editor.config.sourceAreaTabSize || 4 ) ) );
39
40 // Make sure that source code is always displayed LTR,
41 // regardless of editor language (#10105).
42 textarea.setAttribute( 'dir', 'ltr' );
43
44 textarea.addClass( 'cke_source' ).addClass( 'cke_reset' ).addClass( 'cke_enable_context_menu' );
45
46 editor.ui.space( 'contents' ).append( textarea );
47
48 var editable = editor.editable( new sourceEditable( editor, textarea ) );
49
50 // Fill the textarea with the current editor data.
51 editable.setData( editor.getData( 1 ) );
52
53 // Having to make <textarea> fixed sized to conquer the following bugs:
54 // 1. The textarea height/width='100%' doesn't constraint to the 'td' in IE6/7.
55 // 2. Unexpected vertical-scrolling behavior happens whenever focus is moving out of editor
56 // if text content within it has overflowed. (#4762)
57 if ( CKEDITOR.env.ie ) {
58 editable.attachListener( editor, 'resize', onResize, editable );
59 editable.attachListener( CKEDITOR.document.getWindow(), 'resize', onResize, editable );
60 CKEDITOR.tools.setTimeout( onResize, 0, editable );
61 }
62
63 editor.fire( 'ariaWidget', this );
64
65 callback();
66 } );
67
68 editor.addCommand( 'source', sourcearea.commands.source );
69
70 if ( editor.ui.addButton ) {
71 editor.ui.addButton( 'Source', {
72 label: editor.lang.sourcearea.toolbar,
73 command: 'source',
74 toolbar: 'mode,10'
75 } );
76 }
77
78 editor.on( 'mode', function() {
79 editor.getCommand( 'source' ).setState( editor.mode == 'source' ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
80 } );
81
82 var needsFocusHack = CKEDITOR.env.ie && CKEDITOR.env.version == 9;
83
84 function onResize() {
85 // We have to do something with focus on IE9, because if sourcearea had focus
86 // before being resized, the caret ends somewhere in the editor UI (#11839).
87 var wasActive = needsFocusHack && this.equals( CKEDITOR.document.getActive() );
88
89 // Holder rectange size is stretched by textarea,
90 // so hide it just for a moment.
91 this.hide();
92 this.setStyle( 'height', this.getParent().$.clientHeight + 'px' );
93 this.setStyle( 'width', this.getParent().$.clientWidth + 'px' );
94 // When we have proper holder size, show textarea again.
95 this.show();
96
97 if ( wasActive )
98 this.focus();
99 }
100 }
101 } );
102
103 var sourceEditable = CKEDITOR.tools.createClass( {
104 base: CKEDITOR.editable,
105 proto: {
106 setData: function( data ) {
107 this.setValue( data );
108 this.status = 'ready';
109 this.editor.fire( 'dataReady' );
110 },
111
112 getData: function() {
113 return this.getValue();
114 },
115
116 // Insertions are not supported in source editable.
117 insertHtml: function() {},
118 insertElement: function() {},
119 insertText: function() {},
120
121 // Read-only support for textarea.
122 setReadOnly: function( isReadOnly ) {
123 this[ ( isReadOnly ? 'set' : 'remove' ) + 'Attribute' ]( 'readOnly', 'readonly' );
124 },
125
126 detach: function() {
127 sourceEditable.baseProto.detach.call( this );
128 this.clearCustomData();
129 this.remove();
130 }
131 }
132 } );
133} )();
134
135CKEDITOR.plugins.sourcearea = {
136 commands: {
137 source: {
138 modes: { wysiwyg: 1, source: 1 },
139 editorFocus: false,
140 readOnly: 1,
141 exec: function( editor ) {
142 if ( editor.mode == 'wysiwyg' )
143 editor.fire( 'saveSnapshot' );
144 editor.getCommand( 'source' ).setState( CKEDITOR.TRISTATE_DISABLED );
145 editor.setMode( editor.mode == 'source' ? 'wysiwyg' : 'source' );
146 },
147
148 canUndo: false
149 }
150 }
151};
152
153/**
154 * Controls the `tab-size` CSS property of the source editing area. Use it to set the width
155 * of the tab character in the source view. Enter an integer to denote the number of spaces
156 * that the tab will contain.
157 *
158 * **Note:** Works only with {@link #dataIndentationChars}
159 * set to `'\t'`. Please consider that not all browsers support the `tab-size` CSS
160 * property yet.
161 *
162 * // Set tab-size to 10 characters.
163 * config.sourceAreaTabSize = 10;
164 *
165 * @cfg {Number} [sourceAreaTabSize=4]
166 * @member CKEDITOR.config
167 * @see CKEDITOR.config#dataIndentationChars
168 */
diff --git a/sources/plugins/tab/plugin.js b/sources/plugins/tab/plugin.js
new file mode 100644
index 0000000..98acb2e
--- /dev/null
+++ b/sources/plugins/tab/plugin.js
@@ -0,0 +1,302 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6( function() {
7 var meta = {
8 editorFocus: false,
9 modes: { wysiwyg: 1, source: 1 }
10 };
11
12 var blurCommand = {
13 exec: function( editor ) {
14 editor.container.focusNext( true, editor.tabIndex );
15 }
16 };
17
18 var blurBackCommand = {
19 exec: function( editor ) {
20 editor.container.focusPrevious( true, editor.tabIndex );
21 }
22 };
23
24 function selectNextCellCommand( backward ) {
25 return {
26 editorFocus: false,
27 canUndo: false,
28 modes: { wysiwyg: 1 },
29 exec: function( editor ) {
30 if ( editor.editable().hasFocus ) {
31 var sel = editor.getSelection(),
32 path = new CKEDITOR.dom.elementPath( sel.getCommonAncestor(), sel.root ),
33 cell;
34
35 if ( ( cell = path.contains( { td: 1, th: 1 }, 1 ) ) ) {
36 var resultRange = editor.createRange(),
37 next = CKEDITOR.tools.tryThese( function() {
38 var row = cell.getParent(),
39 next = row.$.cells[ cell.$.cellIndex + ( backward ? -1 : 1 ) ];
40
41 // Invalid any empty value.
42 next.parentNode.parentNode;
43 return next;
44 }, function() {
45 var row = cell.getParent(),
46 table = row.getAscendant( 'table' ),
47 nextRow = table.$.rows[ row.$.rowIndex + ( backward ? -1 : 1 ) ];
48
49 return nextRow.cells[ backward ? nextRow.cells.length - 1 : 0 ];
50 } );
51
52 // Clone one more row at the end of table and select the first newly established cell.
53 if ( !( next || backward ) ) {
54 var table = cell.getAscendant( 'table' ).$,
55 cells = cell.getParent().$.cells;
56
57 var newRow = new CKEDITOR.dom.element( table.insertRow( -1 ), editor.document );
58
59 for ( var i = 0, count = cells.length; i < count; i++ ) {
60 var newCell = newRow.append( new CKEDITOR.dom.element( cells[ i ], editor.document ).clone( false, false ) );
61 newCell.appendBogus();
62 }
63
64 resultRange.moveToElementEditStart( newRow );
65 } else if ( next ) {
66 next = new CKEDITOR.dom.element( next );
67 resultRange.moveToElementEditStart( next );
68 // Avoid selecting empty block makes the cursor blind.
69 if ( !( resultRange.checkStartOfBlock() && resultRange.checkEndOfBlock() ) )
70 resultRange.selectNodeContents( next );
71 } else {
72 return true;
73 }
74
75 resultRange.select( true );
76 return true;
77 }
78 }
79
80 return false;
81 }
82 };
83 }
84
85 CKEDITOR.plugins.add( 'tab', {
86 init: function( editor ) {
87 var tabTools = editor.config.enableTabKeyTools !== false,
88 tabSpaces = editor.config.tabSpaces || 0,
89 tabText = '';
90
91 while ( tabSpaces-- )
92 tabText += '\xa0';
93
94 if ( tabText ) {
95 editor.on( 'key', function( ev ) {
96 // TAB.
97 if ( ev.data.keyCode == 9 ) {
98 editor.insertText( tabText );
99 ev.cancel();
100 }
101 } );
102 }
103
104 if ( tabTools ) {
105 editor.on( 'key', function( ev ) {
106 if ( ev.data.keyCode == 9 && editor.execCommand( 'selectNextCell' ) || // TAB
107 ev.data.keyCode == ( CKEDITOR.SHIFT + 9 ) && editor.execCommand( 'selectPreviousCell' ) ) // SHIFT+TAB
108 ev.cancel();
109 } );
110 }
111
112 editor.addCommand( 'blur', CKEDITOR.tools.extend( blurCommand, meta ) );
113 editor.addCommand( 'blurBack', CKEDITOR.tools.extend( blurBackCommand, meta ) );
114 editor.addCommand( 'selectNextCell', selectNextCellCommand() );
115 editor.addCommand( 'selectPreviousCell', selectNextCellCommand( true ) );
116 }
117 } );
118} )();
119
120/**
121 * Moves the UI focus to the element following this element in the tabindex order.
122 *
123 * var element = CKEDITOR.document.getById( 'example' );
124 * element.focusNext();
125 *
126 * @param {Boolean} [ignoreChildren=false]
127 * @param {Number} [indexToUse]
128 * @member CKEDITOR.dom.element
129 */
130CKEDITOR.dom.element.prototype.focusNext = function( ignoreChildren, indexToUse ) {
131 var curTabIndex = ( indexToUse === undefined ? this.getTabIndex() : indexToUse ),
132 passedCurrent, enteredCurrent, elected, electedTabIndex, element, elementTabIndex;
133
134 if ( curTabIndex <= 0 ) {
135 // If this element has tabindex <= 0 then we must simply look for any
136 // element following it containing tabindex=0.
137
138 element = this.getNextSourceNode( ignoreChildren, CKEDITOR.NODE_ELEMENT );
139
140 while ( element ) {
141 if ( element.isVisible() && element.getTabIndex() === 0 ) {
142 elected = element;
143 break;
144 }
145
146 element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT );
147 }
148 } else {
149 // If this element has tabindex > 0 then we must look for:
150 // 1. An element following this element with the same tabindex.
151 // 2. The first element in source other with the lowest tabindex
152 // that is higher than this element tabindex.
153 // 3. The first element with tabindex=0.
154
155 element = this.getDocument().getBody().getFirst();
156
157 while ( ( element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) ) {
158 if ( !passedCurrent ) {
159 if ( !enteredCurrent && element.equals( this ) ) {
160 enteredCurrent = true;
161
162 // Ignore this element, if required.
163 if ( ignoreChildren ) {
164 if ( !( element = element.getNextSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) )
165 break;
166 passedCurrent = 1;
167 }
168 } else if ( enteredCurrent && !this.contains( element ) ) {
169 passedCurrent = 1;
170 }
171 }
172
173 if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 )
174 continue;
175
176 if ( passedCurrent && elementTabIndex == curTabIndex ) {
177 elected = element;
178 break;
179 }
180
181 if ( elementTabIndex > curTabIndex && ( !elected || !electedTabIndex || elementTabIndex < electedTabIndex ) ) {
182 elected = element;
183 electedTabIndex = elementTabIndex;
184 } else if ( !elected && elementTabIndex === 0 ) {
185 elected = element;
186 electedTabIndex = elementTabIndex;
187 }
188 }
189 }
190
191 if ( elected )
192 elected.focus();
193};
194
195/**
196 * Moves the UI focus to the element before this element in the tabindex order.
197 *
198 * var element = CKEDITOR.document.getById( 'example' );
199 * element.focusPrevious();
200 *
201 * @param {Boolean} [ignoreChildren=false]
202 * @param {Number} [indexToUse]
203 * @member CKEDITOR.dom.element
204 */
205CKEDITOR.dom.element.prototype.focusPrevious = function( ignoreChildren, indexToUse ) {
206 var curTabIndex = ( indexToUse === undefined ? this.getTabIndex() : indexToUse ),
207 passedCurrent, enteredCurrent, elected,
208 electedTabIndex = 0,
209 elementTabIndex;
210
211 var element = this.getDocument().getBody().getLast();
212
213 while ( ( element = element.getPreviousSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) ) {
214 if ( !passedCurrent ) {
215 if ( !enteredCurrent && element.equals( this ) ) {
216 enteredCurrent = true;
217
218 // Ignore this element, if required.
219 if ( ignoreChildren ) {
220 if ( !( element = element.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) )
221 break;
222 passedCurrent = 1;
223 }
224 } else if ( enteredCurrent && !this.contains( element ) ) {
225 passedCurrent = 1;
226 }
227 }
228
229 if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 )
230 continue;
231
232 if ( curTabIndex <= 0 ) {
233 // If this element has tabindex <= 0 then we must look for:
234 // 1. An element before this one containing tabindex=0.
235 // 2. The last element with the highest tabindex.
236
237 if ( passedCurrent && elementTabIndex === 0 ) {
238 elected = element;
239 break;
240 }
241
242 if ( elementTabIndex > electedTabIndex ) {
243 elected = element;
244 electedTabIndex = elementTabIndex;
245 }
246 } else {
247 // If this element has tabindex > 0 we must look for:
248 // 1. An element preceeding this one, with the same tabindex.
249 // 2. The last element in source other with the highest tabindex
250 // that is lower than this element tabindex.
251
252 if ( passedCurrent && elementTabIndex == curTabIndex ) {
253 elected = element;
254 break;
255 }
256
257 if ( elementTabIndex < curTabIndex && ( !elected || elementTabIndex > electedTabIndex ) ) {
258 elected = element;
259 electedTabIndex = elementTabIndex;
260 }
261 }
262 }
263
264 if ( elected )
265 elected.focus();
266};
267
268/**
269 * Intructs the editor to add a number of spaces (`&nbsp;`) to the text when
270 * hitting the <kbd>Tab</kbd> key. If set to zero, the <kbd>Tab</kbd> key will be used to move the
271 * cursor focus to the next element in the page, out of the editor focus.
272 *
273 * config.tabSpaces = 4;
274 *
275 * @cfg {Number} [tabSpaces=0]
276 * @member CKEDITOR.config
277 */
278
279/**
280 * Allow context-sensitive <kbd>Tab</kbd> key behaviors, including the following scenarios:
281 *
282 * When selection is anchored inside **table cells**:
283 *
284 * * If <kbd>Tab</kbd> is pressed, select the content of the "next" cell. If in the last
285 * cell in the table, add a new row to it and focus its first cell.
286 * * If <kbd>Shift+Tab</kbd> is pressed, select the content of the "previous" cell.
287 * Do nothing when it is in the first cell.
288 *
289 * Example:
290 *
291 * config.enableTabKeyTools = false;
292 *
293 * @cfg {Boolean} [enableTabKeyTools=true]
294 * @member CKEDITOR.config
295 */
296
297// If the <kbd>Tab</kbd> key is not supposed to be enabled for navigation, the following
298// settings could be used alternatively:
299// config.keystrokes.push(
300// [ CKEDITOR.ALT + 38 /*Arrow Up*/, 'selectPreviousCell' ],
301// [ CKEDITOR.ALT + 40 /*Arrow Down*/, 'selectNextCell' ]
302// );
diff --git a/sources/plugins/toolbar/lang/af.js b/sources/plugins/toolbar/lang/af.js
new file mode 100644
index 0000000..8a3b1cd
--- /dev/null
+++ b/sources/plugins/toolbar/lang/af.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'af', {
6 toolbarCollapse: 'Verklein werkbalk',
7 toolbarExpand: 'Vergroot werkbalk',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Knipbord/Undo',
11 editing: 'Verander',
12 forms: 'Vorms',
13 basicstyles: 'Eenvoudige Styl',
14 paragraph: 'Paragraaf',
15 links: 'Skakels',
16 insert: 'Toevoeg',
17 styles: 'Style',
18 colors: 'Kleure',
19 tools: 'Gereedskap'
20 },
21 toolbars: 'Werkbalke'
22} );
diff --git a/sources/plugins/toolbar/lang/ar.js b/sources/plugins/toolbar/lang/ar.js
new file mode 100644
index 0000000..8cef5e7
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ar.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ar', {
6 toolbarCollapse: 'تقليص شريط الأدوت',
7 toolbarExpand: 'تمديد شريط الأدوات',
8 toolbarGroups: {
9 document: 'مستند',
10 clipboard: 'الحافظة/الرجوع',
11 editing: 'تحرير',
12 forms: 'نماذج',
13 basicstyles: 'نمط بسيط',
14 paragraph: 'فقرة',
15 links: 'روابط',
16 insert: 'إدراج',
17 styles: 'أنماط',
18 colors: 'ألوان',
19 tools: 'أدوات'
20 },
21 toolbars: 'أشرطة أدوات المحرر'
22} );
diff --git a/sources/plugins/toolbar/lang/az.js b/sources/plugins/toolbar/lang/az.js
new file mode 100644
index 0000000..25c4a53
--- /dev/null
+++ b/sources/plugins/toolbar/lang/az.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'az', {
6 toolbarCollapse: 'Paneli gizlət',
7 toolbarExpand: 'Paneli göstər',
8 toolbarGroups: {
9 document: 'Mətn',
10 clipboard: 'Mübadilə buferi/İmtina et',
11 editing: 'Redaktə edilməsi',
12 forms: 'Formalar',
13 basicstyles: 'Əsas üslublar',
14 paragraph: 'Abzas',
15 links: 'Link',
16 insert: 'Əlavə et',
17 styles: 'Üslublar',
18 colors: 'Rənqlər',
19 tools: 'Alətləri'
20 },
21 toolbars: 'Redaktorun panelləri'
22} );
diff --git a/sources/plugins/toolbar/lang/bg.js b/sources/plugins/toolbar/lang/bg.js
new file mode 100644
index 0000000..0fb4384
--- /dev/null
+++ b/sources/plugins/toolbar/lang/bg.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'bg', {
6 toolbarCollapse: 'Свиване на лентата с инструменти',
7 toolbarExpand: 'Разширяване на лентата с инструменти',
8 toolbarGroups: {
9 document: 'Документ',
10 clipboard: 'Клипборд/Отмяна',
11 editing: 'Промяна',
12 forms: 'Форми',
13 basicstyles: 'Базови стилове',
14 paragraph: 'Параграф',
15 links: 'Връзки',
16 insert: 'Вмъкване',
17 styles: 'Стилове',
18 colors: 'Цветове',
19 tools: 'Инструменти'
20 },
21 toolbars: 'Ленти с инструменти'
22} );
diff --git a/sources/plugins/toolbar/lang/bn.js b/sources/plugins/toolbar/lang/bn.js
new file mode 100644
index 0000000..dc9697e
--- /dev/null
+++ b/sources/plugins/toolbar/lang/bn.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'bn', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/bs.js b/sources/plugins/toolbar/lang/bs.js
new file mode 100644
index 0000000..00f46d0
--- /dev/null
+++ b/sources/plugins/toolbar/lang/bs.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'bs', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/ca.js b/sources/plugins/toolbar/lang/ca.js
new file mode 100644
index 0000000..82e4413
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ca.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ca', {
6 toolbarCollapse: 'Redueix la barra d\'eines',
7 toolbarExpand: 'Amplia la barra d\'eines',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor de barra d\'eines'
22} );
diff --git a/sources/plugins/toolbar/lang/cs.js b/sources/plugins/toolbar/lang/cs.js
new file mode 100644
index 0000000..f8e650f
--- /dev/null
+++ b/sources/plugins/toolbar/lang/cs.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'cs', {
6 toolbarCollapse: 'Skrýt panel nástrojů',
7 toolbarExpand: 'Zobrazit panel nástrojů',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Schránka/Zpět',
11 editing: 'Úpravy',
12 forms: 'Formuláře',
13 basicstyles: 'Základní styly',
14 paragraph: 'Odstavec',
15 links: 'Odkazy',
16 insert: 'Vložit',
17 styles: 'Styly',
18 colors: 'Barvy',
19 tools: 'Nástroje'
20 },
21 toolbars: 'Panely nástrojů editoru'
22} );
diff --git a/sources/plugins/toolbar/lang/cy.js b/sources/plugins/toolbar/lang/cy.js
new file mode 100644
index 0000000..faebd1b
--- /dev/null
+++ b/sources/plugins/toolbar/lang/cy.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'cy', {
6 toolbarCollapse: 'Cyfangu\'r Bar Offer',
7 toolbarExpand: 'Ehangu\'r Bar Offer',
8 toolbarGroups: {
9 document: 'Dogfen',
10 clipboard: 'Clipfwrdd/Dadwneud',
11 editing: 'Golygu',
12 forms: 'Ffurflenni',
13 basicstyles: 'Arddulliau Sylfaenol',
14 paragraph: 'Paragraff',
15 links: 'Dolenni',
16 insert: 'Mewnosod',
17 styles: 'Arddulliau',
18 colors: 'Lliwiau',
19 tools: 'Offer'
20 },
21 toolbars: 'Bariau offer y golygydd'
22} );
diff --git a/sources/plugins/toolbar/lang/da.js b/sources/plugins/toolbar/lang/da.js
new file mode 100644
index 0000000..750bc64
--- /dev/null
+++ b/sources/plugins/toolbar/lang/da.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'da', {
6 toolbarCollapse: 'Sammenklap værktøjslinje',
7 toolbarExpand: 'Udvid værktøjslinje',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Udklipsholder/Fortryd',
11 editing: 'Redigering',
12 forms: 'Formularer',
13 basicstyles: 'Basis styles',
14 paragraph: 'Paragraf',
15 links: 'Links',
16 insert: 'Indsæt',
17 styles: 'Typografier',
18 colors: 'Farver',
19 tools: 'Værktøjer'
20 },
21 toolbars: 'Editors værktøjslinjer'
22} );
diff --git a/sources/plugins/toolbar/lang/de-ch.js b/sources/plugins/toolbar/lang/de-ch.js
new file mode 100644
index 0000000..399aa63
--- /dev/null
+++ b/sources/plugins/toolbar/lang/de-ch.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'de-ch', {
6 toolbarCollapse: 'Werkzeugleiste einklappen',
7 toolbarExpand: 'Werkzeugleiste ausklappen',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Zwischenablage/Rückgängig',
11 editing: 'Editieren',
12 forms: 'Formulare',
13 basicstyles: 'Grundstile',
14 paragraph: 'Absatz',
15 links: 'Links',
16 insert: 'Einfügen',
17 styles: 'Stile',
18 colors: 'Farben',
19 tools: 'Werkzeuge'
20 },
21 toolbars: 'Editor Werkzeugleisten'
22} );
diff --git a/sources/plugins/toolbar/lang/de.js b/sources/plugins/toolbar/lang/de.js
new file mode 100644
index 0000000..fab73aa
--- /dev/null
+++ b/sources/plugins/toolbar/lang/de.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'de', {
6 toolbarCollapse: 'Werkzeugleiste einklappen',
7 toolbarExpand: 'Werkzeugleiste ausklappen',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Zwischenablage/Rückgängig',
11 editing: 'Editieren',
12 forms: 'Formulare',
13 basicstyles: 'Grundstile',
14 paragraph: 'Absatz',
15 links: 'Links',
16 insert: 'Einfügen',
17 styles: 'Stile',
18 colors: 'Farben',
19 tools: 'Werkzeuge'
20 },
21 toolbars: 'Editor Werkzeugleisten'
22} );
diff --git a/sources/plugins/toolbar/lang/el.js b/sources/plugins/toolbar/lang/el.js
new file mode 100644
index 0000000..ce46898
--- /dev/null
+++ b/sources/plugins/toolbar/lang/el.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'el', {
6 toolbarCollapse: 'Σύμπτυξη Εργαλειοθήκης',
7 toolbarExpand: 'Ανάπτυξη Εργαλειοθήκης',
8 toolbarGroups: {
9 document: 'Έγγραφο',
10 clipboard: 'Πρόχειρο/Αναίρεση',
11 editing: 'Επεξεργασία',
12 forms: 'Φόρμες',
13 basicstyles: 'Βασικά Στυλ',
14 paragraph: 'Παράγραφος',
15 links: 'Σύνδεσμοι',
16 insert: 'Εισαγωγή',
17 styles: 'Στυλ',
18 colors: 'Χρώματα',
19 tools: 'Εργαλεία'
20 },
21 toolbars: 'Εργαλειοθήκες επεξεργαστή'
22} );
diff --git a/sources/plugins/toolbar/lang/en-au.js b/sources/plugins/toolbar/lang/en-au.js
new file mode 100644
index 0000000..8517e62
--- /dev/null
+++ b/sources/plugins/toolbar/lang/en-au.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'en-au', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars'
22} );
diff --git a/sources/plugins/toolbar/lang/en-ca.js b/sources/plugins/toolbar/lang/en-ca.js
new file mode 100644
index 0000000..fb2049a
--- /dev/null
+++ b/sources/plugins/toolbar/lang/en-ca.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'en-ca', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/en-gb.js b/sources/plugins/toolbar/lang/en-gb.js
new file mode 100644
index 0000000..df7198e
--- /dev/null
+++ b/sources/plugins/toolbar/lang/en-gb.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'en-gb', {
6 toolbarCollapse: 'Collapse Toolbar',
7 toolbarExpand: 'Expand Toolbar',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars'
22} );
diff --git a/sources/plugins/toolbar/lang/en.js b/sources/plugins/toolbar/lang/en.js
new file mode 100644
index 0000000..263ac0e
--- /dev/null
+++ b/sources/plugins/toolbar/lang/en.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'en', {
6 toolbarCollapse: 'Collapse Toolbar',
7 toolbarExpand: 'Expand Toolbar',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars'
22} );
diff --git a/sources/plugins/toolbar/lang/eo.js b/sources/plugins/toolbar/lang/eo.js
new file mode 100644
index 0000000..902a613
--- /dev/null
+++ b/sources/plugins/toolbar/lang/eo.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'eo', {
6 toolbarCollapse: 'Faldi la ilbreton',
7 toolbarExpand: 'Malfaldi la ilbreton',
8 toolbarGroups: {
9 document: 'Dokumento',
10 clipboard: 'Poŝo/Malfari',
11 editing: 'Redaktado',
12 forms: 'Formularoj',
13 basicstyles: 'Bazaj stiloj',
14 paragraph: 'Paragrafo',
15 links: 'Ligiloj',
16 insert: 'Enmeti',
17 styles: 'Stiloj',
18 colors: 'Koloroj',
19 tools: 'Iloj'
20 },
21 toolbars: 'Ilobretoj de la redaktilo'
22} );
diff --git a/sources/plugins/toolbar/lang/es.js b/sources/plugins/toolbar/lang/es.js
new file mode 100644
index 0000000..bf5b457
--- /dev/null
+++ b/sources/plugins/toolbar/lang/es.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'es', {
6 toolbarCollapse: 'Contraer barra de herramientas',
7 toolbarExpand: 'Expandir barra de herramientas',
8 toolbarGroups: {
9 document: 'Documento',
10 clipboard: 'Portapapeles/Deshacer',
11 editing: 'Edición',
12 forms: 'Formularios',
13 basicstyles: 'Estilos básicos',
14 paragraph: 'Párrafo',
15 links: 'Enlaces',
16 insert: 'Insertar',
17 styles: 'Estilos',
18 colors: 'Colores',
19 tools: 'Herramientas'
20 },
21 toolbars: 'Barras de herramientas del editor'
22} );
diff --git a/sources/plugins/toolbar/lang/et.js b/sources/plugins/toolbar/lang/et.js
new file mode 100644
index 0000000..b83473f
--- /dev/null
+++ b/sources/plugins/toolbar/lang/et.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'et', {
6 toolbarCollapse: 'Tööriistariba peitmine',
7 toolbarExpand: 'Tööriistariba näitamine',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Lõikelaud/tagasivõtmine',
11 editing: 'Muutmine',
12 forms: 'Vormid',
13 basicstyles: 'Põhistiilid',
14 paragraph: 'Lõik',
15 links: 'Lingid',
16 insert: 'Sisesta',
17 styles: 'Stiilid',
18 colors: 'Värvid',
19 tools: 'Tööriistad'
20 },
21 toolbars: 'Redaktori tööriistaribad'
22} );
diff --git a/sources/plugins/toolbar/lang/eu.js b/sources/plugins/toolbar/lang/eu.js
new file mode 100644
index 0000000..831d285
--- /dev/null
+++ b/sources/plugins/toolbar/lang/eu.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'eu', {
6 toolbarCollapse: 'Tolestu tresna-barra',
7 toolbarExpand: 'Zabaldu tresna-barra',
8 toolbarGroups: {
9 document: 'Dokumentua',
10 clipboard: 'Arbela/Desegin',
11 editing: 'Editatu',
12 forms: 'Formularioak',
13 basicstyles: 'Oinarrizko estiloak',
14 paragraph: 'Paragrafoa',
15 links: 'Estekak',
16 insert: 'Txertatu',
17 styles: 'Estiloak',
18 colors: 'Koloreak',
19 tools: 'Tresnak'
20 },
21 toolbars: 'Editorearen tresna-barrak'
22} );
diff --git a/sources/plugins/toolbar/lang/fa.js b/sources/plugins/toolbar/lang/fa.js
new file mode 100644
index 0000000..2d1bc5d
--- /dev/null
+++ b/sources/plugins/toolbar/lang/fa.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'fa', {
6 toolbarCollapse: 'بستن نوار ابزار',
7 toolbarExpand: 'بازکردن نوار ابزار',
8 toolbarGroups: {
9 document: 'سند',
10 clipboard: 'حافظه موقت/برگشت',
11 editing: 'در حال ویرایش',
12 forms: 'فرم​ها',
13 basicstyles: 'سبک‌های پایه',
14 paragraph: 'بند',
15 links: 'پیوندها',
16 insert: 'ورود',
17 styles: 'سبک‌ها',
18 colors: 'رنگ​ها',
19 tools: 'ابزارها'
20 },
21 toolbars: 'نوار ابزارهای ویرایش‌گر'
22} );
diff --git a/sources/plugins/toolbar/lang/fi.js b/sources/plugins/toolbar/lang/fi.js
new file mode 100644
index 0000000..9e12ad4
--- /dev/null
+++ b/sources/plugins/toolbar/lang/fi.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'fi', {
6 toolbarCollapse: 'Kutista työkalupalkki',
7 toolbarExpand: 'Laajenna työkalupalkki',
8 toolbarGroups: {
9 document: 'Dokumentti',
10 clipboard: 'Leikepöytä/Kumoa',
11 editing: 'Muokkaus',
12 forms: 'Lomakkeet',
13 basicstyles: 'Perustyylit',
14 paragraph: 'Kappale',
15 links: 'Linkit',
16 insert: 'Lisää',
17 styles: 'Tyylit',
18 colors: 'Värit',
19 tools: 'Työkalut'
20 },
21 toolbars: 'Editorin työkalupalkit'
22} );
diff --git a/sources/plugins/toolbar/lang/fo.js b/sources/plugins/toolbar/lang/fo.js
new file mode 100644
index 0000000..4628b5d
--- /dev/null
+++ b/sources/plugins/toolbar/lang/fo.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'fo', {
6 toolbarCollapse: 'Lat Toolbar aftur',
7 toolbarExpand: 'Vís Toolbar',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editering',
12 forms: 'Formar',
13 basicstyles: 'Grundleggjandi Styles',
14 paragraph: 'Reglubrot',
15 links: 'Leinkjur',
16 insert: 'Set inn',
17 styles: 'Styles',
18 colors: 'Litir',
19 tools: 'Tól'
20 },
21 toolbars: 'Editor toolbars'
22} );
diff --git a/sources/plugins/toolbar/lang/fr-ca.js b/sources/plugins/toolbar/lang/fr-ca.js
new file mode 100644
index 0000000..4aae863
--- /dev/null
+++ b/sources/plugins/toolbar/lang/fr-ca.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'fr-ca', {
6 toolbarCollapse: 'Enrouler la barre d\'outils',
7 toolbarExpand: 'Dérouler la barre d\'outils',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Presse papier/Annuler',
11 editing: 'Édition',
12 forms: 'Formulaires',
13 basicstyles: 'Styles de base',
14 paragraph: 'Paragraphe',
15 links: 'Liens',
16 insert: 'Insérer',
17 styles: 'Styles',
18 colors: 'Couleurs',
19 tools: 'Outils'
20 },
21 toolbars: 'Barre d\'outils de l\'éditeur'
22} );
diff --git a/sources/plugins/toolbar/lang/fr.js b/sources/plugins/toolbar/lang/fr.js
new file mode 100644
index 0000000..9861866
--- /dev/null
+++ b/sources/plugins/toolbar/lang/fr.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'fr', {
6 toolbarCollapse: 'Enrouler la barre d\'outils',
7 toolbarExpand: 'Dérouler la barre d\'outils',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Presse-papier/Défaire',
11 editing: 'Édition',
12 forms: 'Formulaires',
13 basicstyles: 'Styles de base',
14 paragraph: 'Paragraphe',
15 links: 'Liens',
16 insert: 'Insérer',
17 styles: 'Styles',
18 colors: 'Couleurs',
19 tools: 'Outils'
20 },
21 toolbars: 'Barres d\'outils de l\'éditeur'
22} );
diff --git a/sources/plugins/toolbar/lang/gl.js b/sources/plugins/toolbar/lang/gl.js
new file mode 100644
index 0000000..f81c10a
--- /dev/null
+++ b/sources/plugins/toolbar/lang/gl.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'gl', {
6 toolbarCollapse: 'Contraer a barra de ferramentas',
7 toolbarExpand: 'Expandir a barra de ferramentas',
8 toolbarGroups: {
9 document: 'Documento',
10 clipboard: 'Portapapeis/desfacer',
11 editing: 'Edición',
12 forms: 'Formularios',
13 basicstyles: 'Estilos básicos',
14 paragraph: 'Paragrafo',
15 links: 'Ligazóns',
16 insert: 'Inserir',
17 styles: 'Estilos',
18 colors: 'Cores',
19 tools: 'Ferramentas'
20 },
21 toolbars: 'Barras de ferramentas do editor'
22} );
diff --git a/sources/plugins/toolbar/lang/gu.js b/sources/plugins/toolbar/lang/gu.js
new file mode 100644
index 0000000..f34879b
--- /dev/null
+++ b/sources/plugins/toolbar/lang/gu.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'gu', {
6 toolbarCollapse: 'ટૂલબાર નાનું કરવું',
7 toolbarExpand: 'ટૂલબાર મોટું કરવું',
8 toolbarGroups: {
9 document: 'દસ્તાવેજ',
10 clipboard: 'ક્લિપબોર્ડ/અન',
11 editing: 'એડીટ કરવું',
12 forms: 'ફોર્મ',
13 basicstyles: 'બેસિક્ સ્ટાઇલ',
14 paragraph: 'ફકરો',
15 links: 'લીંક',
16 insert: 'ઉમેરવું',
17 styles: 'સ્ટાઇલ',
18 colors: 'રંગ',
19 tools: 'ટૂલ્સ'
20 },
21 toolbars: 'એડીટર ટૂલ બાર'
22} );
diff --git a/sources/plugins/toolbar/lang/he.js b/sources/plugins/toolbar/lang/he.js
new file mode 100644
index 0000000..8e6f343
--- /dev/null
+++ b/sources/plugins/toolbar/lang/he.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'he', {
6 toolbarCollapse: 'מזעור סרגל כלים',
7 toolbarExpand: 'הרחבת סרגל כלים',
8 toolbarGroups: {
9 document: 'מסמך',
10 clipboard: 'לוח הגזירים (Clipboard)/צעד אחרון',
11 editing: 'עריכה',
12 forms: 'טפסים',
13 basicstyles: 'עיצוב בסיסי',
14 paragraph: 'פסקה',
15 links: 'קישורים',
16 insert: 'הכנסה',
17 styles: 'עיצוב',
18 colors: 'צבעים',
19 tools: 'כלים'
20 },
21 toolbars: 'סרגלי כלים של העורך'
22} );
diff --git a/sources/plugins/toolbar/lang/hi.js b/sources/plugins/toolbar/lang/hi.js
new file mode 100644
index 0000000..7693fa1
--- /dev/null
+++ b/sources/plugins/toolbar/lang/hi.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'hi', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'एडिटर टूलबार'
22} );
diff --git a/sources/plugins/toolbar/lang/hr.js b/sources/plugins/toolbar/lang/hr.js
new file mode 100644
index 0000000..1928251
--- /dev/null
+++ b/sources/plugins/toolbar/lang/hr.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'hr', {
6 toolbarCollapse: 'Smanji alatnu traku',
7 toolbarExpand: 'Proširi alatnu traku',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Međuspremnik/Poništi',
11 editing: 'Uređivanje',
12 forms: 'Forme',
13 basicstyles: 'Osnovni stilovi',
14 paragraph: 'Paragraf',
15 links: 'Veze',
16 insert: 'Umetni',
17 styles: 'Stilovi',
18 colors: 'Boje',
19 tools: 'Alatke'
20 },
21 toolbars: 'Alatne trake uređivača teksta'
22} );
diff --git a/sources/plugins/toolbar/lang/hu.js b/sources/plugins/toolbar/lang/hu.js
new file mode 100644
index 0000000..fb67175
--- /dev/null
+++ b/sources/plugins/toolbar/lang/hu.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'hu', {
6 toolbarCollapse: 'Eszköztár összecsukása',
7 toolbarExpand: 'Eszköztár szétnyitása',
8 toolbarGroups: {
9 document: 'Dokumentum',
10 clipboard: 'Vágólap/Visszavonás',
11 editing: 'Szerkesztés',
12 forms: 'Űrlapok',
13 basicstyles: 'Alapstílusok',
14 paragraph: 'Bekezdés',
15 links: 'Hivatkozások',
16 insert: 'Beszúrás',
17 styles: 'Stílusok',
18 colors: 'Színek',
19 tools: 'Eszközök'
20 },
21 toolbars: 'Szerkesztő Eszköztár'
22} );
diff --git a/sources/plugins/toolbar/lang/id.js b/sources/plugins/toolbar/lang/id.js
new file mode 100644
index 0000000..c993a72
--- /dev/null
+++ b/sources/plugins/toolbar/lang/id.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'id', {
6 toolbarCollapse: 'Ciutkan Toolbar',
7 toolbarExpand: 'Bentangkan Toolbar',
8 toolbarGroups: {
9 document: 'Dokumen',
10 clipboard: 'Papan klip / Kembalikan perlakuan',
11 editing: 'Sunting',
12 forms: 'Formulir',
13 basicstyles: 'Gaya Dasar',
14 paragraph: 'Paragraf',
15 links: 'Tautan',
16 insert: 'Sisip',
17 styles: 'Gaya',
18 colors: 'Warna',
19 tools: 'Alat'
20 },
21 toolbars: 'Toolbar Penyunting'
22} );
diff --git a/sources/plugins/toolbar/lang/is.js b/sources/plugins/toolbar/lang/is.js
new file mode 100644
index 0000000..a5fc159
--- /dev/null
+++ b/sources/plugins/toolbar/lang/is.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'is', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/it.js b/sources/plugins/toolbar/lang/it.js
new file mode 100644
index 0000000..42099cd
--- /dev/null
+++ b/sources/plugins/toolbar/lang/it.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'it', {
6 toolbarCollapse: 'Minimizza Toolbar',
7 toolbarExpand: 'Espandi Toolbar',
8 toolbarGroups: {
9 document: 'Documento',
10 clipboard: 'Copia negli appunti/Annulla',
11 editing: 'Modifica',
12 forms: 'Form',
13 basicstyles: 'Stili di base',
14 paragraph: 'Paragrafo',
15 links: 'Link',
16 insert: 'Inserisci',
17 styles: 'Stili',
18 colors: 'Colori',
19 tools: 'Strumenti'
20 },
21 toolbars: 'Editor toolbar'
22} );
diff --git a/sources/plugins/toolbar/lang/ja.js b/sources/plugins/toolbar/lang/ja.js
new file mode 100644
index 0000000..49bfcd0
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ja.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ja', {
6 toolbarCollapse: 'ツールバーを閉じる',
7 toolbarExpand: 'ツールバーを開く',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: '編集ツールバー'
22} );
diff --git a/sources/plugins/toolbar/lang/ka.js b/sources/plugins/toolbar/lang/ka.js
new file mode 100644
index 0000000..f1a46cb
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ka.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ka', {
6 toolbarCollapse: 'ხელსაწყოთა ზოლის შეწევა',
7 toolbarExpand: 'ხელსაწყოთა ზოლის გამოწევა',
8 toolbarGroups: {
9 document: 'დოკუმენტი',
10 clipboard: 'Clipboard/გაუქმება',
11 editing: 'რედაქტირება',
12 forms: 'ფორმები',
13 basicstyles: 'ძირითადი სტილები',
14 paragraph: 'აბზაცი',
15 links: 'ბმულები',
16 insert: 'ჩასმა',
17 styles: 'სტილები',
18 colors: 'ფერები',
19 tools: 'ხელსაწყოები'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/km.js b/sources/plugins/toolbar/lang/km.js
new file mode 100644
index 0000000..3b0eb05
--- /dev/null
+++ b/sources/plugins/toolbar/lang/km.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'km', {
6 toolbarCollapse: 'បង្រួម​របារ​ឧបករណ៍',
7 toolbarExpand: 'ពង្រីក​របារ​ឧបករណ៍',
8 toolbarGroups: {
9 document: 'ឯកសារ',
10 clipboard: 'Clipboard/មិន​ធ្វើ​វិញ',
11 editing: 'ការ​កែ​សម្រួល',
12 forms: 'បែបបទ',
13 basicstyles: 'រចនាបថ​មូលដ្ឋាន',
14 paragraph: 'កថាខណ្ឌ',
15 links: 'តំណ',
16 insert: 'បញ្ចូល',
17 styles: 'រចនាបថ',
18 colors: 'ពណ៌',
19 tools: 'ឧបករណ៍'
20 },
21 toolbars: 'របារ​ឧបករណ៍​កែ​សម្រួល'
22} );
diff --git a/sources/plugins/toolbar/lang/ko.js b/sources/plugins/toolbar/lang/ko.js
new file mode 100644
index 0000000..dc5a674
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ko.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ko', {
6 toolbarCollapse: '툴바 줄이기',
7 toolbarExpand: '툴바 확장',
8 toolbarGroups: {
9 document: '문서',
10 clipboard: '클립보드/실행 취소',
11 editing: '편집',
12 forms: '폼',
13 basicstyles: '기본 스타일',
14 paragraph: '단락',
15 links: '링크',
16 insert: '삽입',
17 styles: '스타일',
18 colors: '색상',
19 tools: '도구'
20 },
21 toolbars: '에디터 툴바'
22} );
diff --git a/sources/plugins/toolbar/lang/ku.js b/sources/plugins/toolbar/lang/ku.js
new file mode 100644
index 0000000..02f8f91
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ku.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ku', {
6 toolbarCollapse: 'شاردنەوی هێڵی تووڵامراز',
7 toolbarExpand: 'نیشاندانی هێڵی تووڵامراز',
8 toolbarGroups: {
9 document: 'پەڕه',
10 clipboard: 'بڕین/پووچکردنەوە',
11 editing: 'چاکسازی',
12 forms: 'داڕشتە',
13 basicstyles: 'شێوازی بنچینەیی',
14 paragraph: 'بڕگە',
15 links: 'بەستەر',
16 insert: 'خستنە ناو',
17 styles: 'شێواز',
18 colors: 'ڕەنگەکان',
19 tools: 'ئامرازەکان'
20 },
21 toolbars: 'تووڵامرازی دەسکاریکەر'
22} );
diff --git a/sources/plugins/toolbar/lang/lt.js b/sources/plugins/toolbar/lang/lt.js
new file mode 100644
index 0000000..b705d6f
--- /dev/null
+++ b/sources/plugins/toolbar/lang/lt.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'lt', {
6 toolbarCollapse: 'Apjungti įrankių juostą',
7 toolbarExpand: 'Išplėsti įrankių juostą',
8 toolbarGroups: {
9 document: 'Dokumentas',
10 clipboard: 'Atmintinė/Atgal',
11 editing: 'Redagavimas',
12 forms: 'Formos',
13 basicstyles: 'Pagrindiniai stiliai',
14 paragraph: 'Paragrafas',
15 links: 'Nuorodos',
16 insert: 'Įterpti',
17 styles: 'Stiliai',
18 colors: 'Spalvos',
19 tools: 'Įrankiai'
20 },
21 toolbars: 'Redaktoriaus įrankiai'
22} );
diff --git a/sources/plugins/toolbar/lang/lv.js b/sources/plugins/toolbar/lang/lv.js
new file mode 100644
index 0000000..20dd345
--- /dev/null
+++ b/sources/plugins/toolbar/lang/lv.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'lv', {
6 toolbarCollapse: 'Aizvērt rīkjoslu',
7 toolbarExpand: 'Atvērt rīkjoslu',
8 toolbarGroups: {
9 document: 'Dokuments',
10 clipboard: 'Starpliktuve/Atcelt',
11 editing: 'Labošana',
12 forms: 'Formas',
13 basicstyles: 'Pamata stili',
14 paragraph: 'Paragrāfs',
15 links: 'Saites',
16 insert: 'Ievietot',
17 styles: 'Stili',
18 colors: 'Krāsas',
19 tools: 'Rīki'
20 },
21 toolbars: 'Redaktora rīkjoslas'
22} );
diff --git a/sources/plugins/toolbar/lang/mk.js b/sources/plugins/toolbar/lang/mk.js
new file mode 100644
index 0000000..e85581d
--- /dev/null
+++ b/sources/plugins/toolbar/lang/mk.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'mk', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/mn.js b/sources/plugins/toolbar/lang/mn.js
new file mode 100644
index 0000000..5aeb46b
--- /dev/null
+++ b/sources/plugins/toolbar/lang/mn.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'mn', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Холбоосууд',
16 insert: 'Оруулах',
17 styles: 'Загварууд',
18 colors: 'Онгөнүүд',
19 tools: 'Хэрэгслүүд'
20 },
21 toolbars: 'Болосруулагчийн хэрэгслийн самбар'
22} );
diff --git a/sources/plugins/toolbar/lang/ms.js b/sources/plugins/toolbar/lang/ms.js
new file mode 100644
index 0000000..7b78dc6
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ms.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ms', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/nb.js b/sources/plugins/toolbar/lang/nb.js
new file mode 100644
index 0000000..830143a
--- /dev/null
+++ b/sources/plugins/toolbar/lang/nb.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'nb', {
6 toolbarCollapse: 'Skjul verktøylinje',
7 toolbarExpand: 'Vis verktøylinje',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Utklippstavle/Angre',
11 editing: 'Redigering',
12 forms: 'Skjema',
13 basicstyles: 'Basisstiler',
14 paragraph: 'Avsnitt',
15 links: 'Lenker',
16 insert: 'Innsetting',
17 styles: 'Stiler',
18 colors: 'Farger',
19 tools: 'Verktøy'
20 },
21 toolbars: 'Verktøylinjer for editor'
22} );
diff --git a/sources/plugins/toolbar/lang/nl.js b/sources/plugins/toolbar/lang/nl.js
new file mode 100644
index 0000000..84ac147
--- /dev/null
+++ b/sources/plugins/toolbar/lang/nl.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'nl', {
6 toolbarCollapse: 'Werkbalk inklappen',
7 toolbarExpand: 'Werkbalk uitklappen',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Klembord/Ongedaan maken',
11 editing: 'Bewerken',
12 forms: 'Formulieren',
13 basicstyles: 'Basisstijlen',
14 paragraph: 'Paragraaf',
15 links: 'Links',
16 insert: 'Invoegen',
17 styles: 'Stijlen',
18 colors: 'Kleuren',
19 tools: 'Toepassingen'
20 },
21 toolbars: 'Werkbalken'
22} );
diff --git a/sources/plugins/toolbar/lang/no.js b/sources/plugins/toolbar/lang/no.js
new file mode 100644
index 0000000..c1a3445
--- /dev/null
+++ b/sources/plugins/toolbar/lang/no.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'no', {
6 toolbarCollapse: 'Skjul verktøylinje',
7 toolbarExpand: 'Vis verktøylinje',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Utklippstavle/Angre',
11 editing: 'Redigering',
12 forms: 'Skjema',
13 basicstyles: 'Basisstiler',
14 paragraph: 'Avsnitt',
15 links: 'Lenker',
16 insert: 'Innsetting',
17 styles: 'Stiler',
18 colors: 'Farger',
19 tools: 'Verktøy'
20 },
21 toolbars: 'Verktøylinjer for editor'
22} );
diff --git a/sources/plugins/toolbar/lang/oc.js b/sources/plugins/toolbar/lang/oc.js
new file mode 100644
index 0000000..bfd8044
--- /dev/null
+++ b/sources/plugins/toolbar/lang/oc.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'oc', {
6 toolbarCollapse: 'Enrotlar la barra d\'aisinas',
7 toolbarExpand: 'Desenrotlar la barra d\'aisinas',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Quichapapièr/Desfar',
11 editing: 'Edicion',
12 forms: 'Formularis',
13 basicstyles: 'Estils de basa',
14 paragraph: 'Paragraf',
15 links: 'Ligams',
16 insert: 'Inserir',
17 styles: 'Estils',
18 colors: 'Colors',
19 tools: 'Aisinas'
20 },
21 toolbars: 'Barras d\'aisinas de l\'editor'
22} );
diff --git a/sources/plugins/toolbar/lang/pl.js b/sources/plugins/toolbar/lang/pl.js
new file mode 100644
index 0000000..07571c9
--- /dev/null
+++ b/sources/plugins/toolbar/lang/pl.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'pl', {
6 toolbarCollapse: 'Zwiń pasek narzędzi',
7 toolbarExpand: 'Rozwiń pasek narzędzi',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Schowek/Wstecz',
11 editing: 'Edycja',
12 forms: 'Formularze',
13 basicstyles: 'Style podstawowe',
14 paragraph: 'Akapit',
15 links: 'Hiperłącza',
16 insert: 'Wstawianie',
17 styles: 'Style',
18 colors: 'Kolory',
19 tools: 'Narzędzia'
20 },
21 toolbars: 'Paski narzędzi edytora'
22} );
diff --git a/sources/plugins/toolbar/lang/pt-br.js b/sources/plugins/toolbar/lang/pt-br.js
new file mode 100644
index 0000000..c897bef
--- /dev/null
+++ b/sources/plugins/toolbar/lang/pt-br.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'pt-br', {
6 toolbarCollapse: 'Diminuir Barra de Ferramentas',
7 toolbarExpand: 'Aumentar Barra de Ferramentas',
8 toolbarGroups: {
9 document: 'Documento',
10 clipboard: 'Clipboard/Desfazer',
11 editing: 'Edição',
12 forms: 'Formulários',
13 basicstyles: 'Estilos Básicos',
14 paragraph: 'Paragrafo',
15 links: 'Links',
16 insert: 'Inserir',
17 styles: 'Estilos',
18 colors: 'Cores',
19 tools: 'Ferramentas'
20 },
21 toolbars: 'Barra de Ferramentas do Editor'
22} );
diff --git a/sources/plugins/toolbar/lang/pt.js b/sources/plugins/toolbar/lang/pt.js
new file mode 100644
index 0000000..d684ede
--- /dev/null
+++ b/sources/plugins/toolbar/lang/pt.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'pt', {
6 toolbarCollapse: 'Ocultar barra de ferramentas',
7 toolbarExpand: 'Expandir barra de ferramentas',
8 toolbarGroups: {
9 document: 'Documento',
10 clipboard: 'Área de transferência/Anular',
11 editing: 'Edição',
12 forms: 'Formulários',
13 basicstyles: 'Estilos básicos',
14 paragraph: 'Parágrafo',
15 links: 'Hiperligações',
16 insert: 'Inserir',
17 styles: 'Estilos',
18 colors: 'Cores',
19 tools: 'Ferramentas'
20 },
21 toolbars: 'Editor de barras de ferramentas'
22} );
diff --git a/sources/plugins/toolbar/lang/ro.js b/sources/plugins/toolbar/lang/ro.js
new file mode 100644
index 0000000..cb1b1e1
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ro.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ro', {
6 toolbarCollapse: 'Micșorează Bara',
7 toolbarExpand: 'Mărește Bara',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Editează bara de unelte'
22} );
diff --git a/sources/plugins/toolbar/lang/ru.js b/sources/plugins/toolbar/lang/ru.js
new file mode 100644
index 0000000..88f9462
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ru.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ru', {
6 toolbarCollapse: 'Свернуть панель инструментов',
7 toolbarExpand: 'Развернуть панель инструментов',
8 toolbarGroups: {
9 document: 'Документ',
10 clipboard: 'Буфер обмена / Отмена действий',
11 editing: 'Корректировка',
12 forms: 'Формы',
13 basicstyles: 'Простые стили',
14 paragraph: 'Абзац',
15 links: 'Ссылки',
16 insert: 'Вставка',
17 styles: 'Стили',
18 colors: 'Цвета',
19 tools: 'Инструменты'
20 },
21 toolbars: 'Панели инструментов редактора'
22} );
diff --git a/sources/plugins/toolbar/lang/si.js b/sources/plugins/toolbar/lang/si.js
new file mode 100644
index 0000000..b57a088
--- /dev/null
+++ b/sources/plugins/toolbar/lang/si.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'si', {
6 toolbarCollapse: 'මෙවලම් තීරුව හැකුලුම.',
7 toolbarExpand: 'මෙවලම් තීරුව දීගහැරුම',
8 toolbarGroups: {
9 document: 'ලිපිය',
10 clipboard: 'ඇමිණුම වෙනස් කිරීම',
11 editing: 'සංස්කරණය',
12 forms: 'පෝරමය',
13 basicstyles: 'මුලික විලාසය',
14 paragraph: 'චේදය',
15 links: 'සබැඳිය',
16 insert: 'ඇතුලත් කිරීම',
17 styles: 'විලාසය',
18 colors: 'වර්ණය',
19 tools: 'මෙවලම්'
20 },
21 toolbars: 'සංස්කරණ මෙවලම් තීරුව'
22} );
diff --git a/sources/plugins/toolbar/lang/sk.js b/sources/plugins/toolbar/lang/sk.js
new file mode 100644
index 0000000..fc9f3db
--- /dev/null
+++ b/sources/plugins/toolbar/lang/sk.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'sk', {
6 toolbarCollapse: 'Zbaliť lištu nástrojov',
7 toolbarExpand: 'Rozbaliť lištu nástrojov',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Schránka pre kopírovanie/Späť',
11 editing: 'Upravovanie',
12 forms: 'Formuláre',
13 basicstyles: 'Základné štýly',
14 paragraph: 'Odsek',
15 links: 'Odkazy',
16 insert: 'Vložiť',
17 styles: 'Štýly',
18 colors: 'Farby',
19 tools: 'Nástroje'
20 },
21 toolbars: 'Lišty nástrojov editora'
22} );
diff --git a/sources/plugins/toolbar/lang/sl.js b/sources/plugins/toolbar/lang/sl.js
new file mode 100644
index 0000000..b17eee4
--- /dev/null
+++ b/sources/plugins/toolbar/lang/sl.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'sl', {
6 toolbarCollapse: 'Skrči orodno vrstico',
7 toolbarExpand: 'Razširi orodno vrstico',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Odložišče/Razveljavi',
11 editing: 'Urejanje',
12 forms: 'Obrazci',
13 basicstyles: 'Osnovni slogi',
14 paragraph: 'Odstavek',
15 links: 'Povezave',
16 insert: 'Vstavi',
17 styles: 'Slogi',
18 colors: 'Barve',
19 tools: 'Orodja'
20 },
21 toolbars: 'Orodne vrstice urejevalnika'
22} );
diff --git a/sources/plugins/toolbar/lang/sq.js b/sources/plugins/toolbar/lang/sq.js
new file mode 100644
index 0000000..0ca8add
--- /dev/null
+++ b/sources/plugins/toolbar/lang/sq.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'sq', {
6 toolbarCollapse: 'Zvogëlo Shiritin',
7 toolbarExpand: 'Zgjero Shiritin',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Tabela Punës/Ribëje',
11 editing: 'Duke Redaktuar',
12 forms: 'Formular',
13 basicstyles: 'Stili Bazë',
14 paragraph: 'Paragraf',
15 links: 'Nyjet',
16 insert: 'Shto',
17 styles: 'Stil',
18 colors: 'Ngjyrat',
19 tools: 'Mjetet'
20 },
21 toolbars: 'Shiritet e Redaktuesit'
22} );
diff --git a/sources/plugins/toolbar/lang/sr-latn.js b/sources/plugins/toolbar/lang/sr-latn.js
new file mode 100644
index 0000000..d746aac
--- /dev/null
+++ b/sources/plugins/toolbar/lang/sr-latn.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'sr-latn', {
6 toolbarCollapse: 'Suzi alatnu traku',
7 toolbarExpand: 'Proširi alatnu traku',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Alatne trake'
22} );
diff --git a/sources/plugins/toolbar/lang/sr.js b/sources/plugins/toolbar/lang/sr.js
new file mode 100644
index 0000000..d02f20f
--- /dev/null
+++ b/sources/plugins/toolbar/lang/sr.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'sr', {
6 toolbarCollapse: 'Склопи алатну траку',
7 toolbarExpand: 'Прошири алатну траку',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'Едитор алатне траке'
22} );
diff --git a/sources/plugins/toolbar/lang/sv.js b/sources/plugins/toolbar/lang/sv.js
new file mode 100644
index 0000000..0a45e88
--- /dev/null
+++ b/sources/plugins/toolbar/lang/sv.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'sv', {
6 toolbarCollapse: 'Dölj verktygsfält',
7 toolbarExpand: 'Visa verktygsfält',
8 toolbarGroups: {
9 document: 'Dokument',
10 clipboard: 'Urklipp/ångra',
11 editing: 'Redigering',
12 forms: 'Formulär',
13 basicstyles: 'Basstilar',
14 paragraph: 'Paragraf',
15 links: 'Länkar',
16 insert: 'Infoga',
17 styles: 'Stilar',
18 colors: 'Färger',
19 tools: 'Verktyg'
20 },
21 toolbars: 'Editorns verktygsfält'
22} );
diff --git a/sources/plugins/toolbar/lang/th.js b/sources/plugins/toolbar/lang/th.js
new file mode 100644
index 0000000..c4ae55e
--- /dev/null
+++ b/sources/plugins/toolbar/lang/th.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'th', {
6 toolbarCollapse: 'ซ่อนแถบเครื่องมือ',
7 toolbarExpand: 'เปิดแถบเครื่องมือ',
8 toolbarGroups: {
9 document: 'Document',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Editing',
12 forms: 'Forms',
13 basicstyles: 'Basic Styles',
14 paragraph: 'Paragraph',
15 links: 'Links',
16 insert: 'Insert',
17 styles: 'Styles',
18 colors: 'Colors',
19 tools: 'Tools'
20 },
21 toolbars: 'แถบเครื่องมือช่วยพิมพ์ข้อความ'
22} );
diff --git a/sources/plugins/toolbar/lang/tr.js b/sources/plugins/toolbar/lang/tr.js
new file mode 100644
index 0000000..cf7f944
--- /dev/null
+++ b/sources/plugins/toolbar/lang/tr.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'tr', {
6 toolbarCollapse: 'Araç çubuklarını topla',
7 toolbarExpand: 'Araç çubuklarını aç',
8 toolbarGroups: {
9 document: 'Belge',
10 clipboard: 'Pano/Geri al',
11 editing: 'Düzenleme',
12 forms: 'Formlar',
13 basicstyles: 'Temel Stiller',
14 paragraph: 'Paragraf',
15 links: 'Bağlantılar',
16 insert: 'Ekle',
17 styles: 'Stiller',
18 colors: 'Renkler',
19 tools: 'Araçlar'
20 },
21 toolbars: 'Araç çubukları Editörü'
22} );
diff --git a/sources/plugins/toolbar/lang/tt.js b/sources/plugins/toolbar/lang/tt.js
new file mode 100644
index 0000000..8eb0542
--- /dev/null
+++ b/sources/plugins/toolbar/lang/tt.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'tt', {
6 toolbarCollapse: 'Collapse Toolbar', // MISSING
7 toolbarExpand: 'Expand Toolbar', // MISSING
8 toolbarGroups: {
9 document: 'Документ',
10 clipboard: 'Алмашу буферы/Кайтару',
11 editing: 'Төзәтү',
12 forms: 'Формалар',
13 basicstyles: 'Төп стильләр',
14 paragraph: 'Параграф',
15 links: 'Сылталамалар',
16 insert: 'Өстәү',
17 styles: 'Стильләр',
18 colors: 'Төсләр',
19 tools: 'Кораллар'
20 },
21 toolbars: 'Editor toolbars' // MISSING
22} );
diff --git a/sources/plugins/toolbar/lang/ug.js b/sources/plugins/toolbar/lang/ug.js
new file mode 100644
index 0000000..95c7c1b
--- /dev/null
+++ b/sources/plugins/toolbar/lang/ug.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'ug', {
6 toolbarCollapse: 'قورال بالداقنى قاتلا',
7 toolbarExpand: 'قورال بالداقنى ياي',
8 toolbarGroups: {
9 document: 'پۈتۈك',
10 clipboard: 'چاپلاش تاختىسى/يېنىۋال',
11 editing: 'تەھرىر',
12 forms: 'جەدۋەل',
13 basicstyles: 'ئاساسىي ئۇسلۇب',
14 paragraph: 'ئابزاس',
15 links: 'ئۇلانما',
16 insert: 'قىستۇر',
17 styles: 'ئۇسلۇب',
18 colors: 'رەڭ',
19 tools: 'قورال'
20 },
21 toolbars: 'قورال بالداق'
22} );
diff --git a/sources/plugins/toolbar/lang/uk.js b/sources/plugins/toolbar/lang/uk.js
new file mode 100644
index 0000000..3f1f1c7
--- /dev/null
+++ b/sources/plugins/toolbar/lang/uk.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'uk', {
6 toolbarCollapse: 'Згорнути панель інструментів',
7 toolbarExpand: 'Розгорнути панель інструментів',
8 toolbarGroups: {
9 document: 'Документ',
10 clipboard: 'Буфер обміну / Скасувати',
11 editing: 'Редагування',
12 forms: 'Форми',
13 basicstyles: 'Основний Стиль',
14 paragraph: 'Параграф',
15 links: 'Посилання',
16 insert: 'Вставити',
17 styles: 'Стилі',
18 colors: 'Кольори',
19 tools: 'Інструменти'
20 },
21 toolbars: 'Панель інструментів редактора'
22} );
diff --git a/sources/plugins/toolbar/lang/vi.js b/sources/plugins/toolbar/lang/vi.js
new file mode 100644
index 0000000..8ff76fd
--- /dev/null
+++ b/sources/plugins/toolbar/lang/vi.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'vi', {
6 toolbarCollapse: 'Thu gọn thanh công cụ',
7 toolbarExpand: 'Mở rộng thnah công cụ',
8 toolbarGroups: {
9 document: 'Tài liệu',
10 clipboard: 'Clipboard/Undo',
11 editing: 'Chỉnh sửa',
12 forms: 'Bảng biểu',
13 basicstyles: 'Kiểu cơ bản',
14 paragraph: 'Đoạn',
15 links: 'Liên kết',
16 insert: 'Chèn',
17 styles: 'Kiểu',
18 colors: 'Màu sắc',
19 tools: 'Công cụ'
20 },
21 toolbars: 'Thanh công cụ'
22} );
diff --git a/sources/plugins/toolbar/lang/zh-cn.js b/sources/plugins/toolbar/lang/zh-cn.js
new file mode 100644
index 0000000..6c3a5ed
--- /dev/null
+++ b/sources/plugins/toolbar/lang/zh-cn.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'zh-cn', {
6 toolbarCollapse: '折叠工具栏',
7 toolbarExpand: '展开工具栏',
8 toolbarGroups: {
9 document: '文档',
10 clipboard: '剪贴板/撤销',
11 editing: '编辑',
12 forms: '表单',
13 basicstyles: '基本格式',
14 paragraph: '段落',
15 links: '链接',
16 insert: '插入',
17 styles: '样式',
18 colors: '颜色',
19 tools: '工具'
20 },
21 toolbars: '工具栏'
22} );
diff --git a/sources/plugins/toolbar/lang/zh.js b/sources/plugins/toolbar/lang/zh.js
new file mode 100644
index 0000000..0a9f5de
--- /dev/null
+++ b/sources/plugins/toolbar/lang/zh.js
@@ -0,0 +1,22 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'toolbar', 'zh', {
6 toolbarCollapse: '摺疊工具列',
7 toolbarExpand: '展開工具列',
8 toolbarGroups: {
9 document: '文件',
10 clipboard: '剪貼簿/復原',
11 editing: '編輯選項',
12 forms: '格式',
13 basicstyles: '基本樣式',
14 paragraph: '段落',
15 links: '連結',
16 insert: '插入',
17 styles: '樣式',
18 colors: '顏色',
19 tools: '工具'
20 },
21 toolbars: '編輯器工具列'
22} );
diff --git a/sources/plugins/toolbar/plugin.js b/sources/plugins/toolbar/plugin.js
new file mode 100644
index 0000000..b267b51
--- /dev/null
+++ b/sources/plugins/toolbar/plugin.js
@@ -0,0 +1,806 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The "toolbar" plugin. Renders the default toolbar interface in
8 * the editor.
9 */
10
11( function() {
12 var toolbox = function() {
13 this.toolbars = [];
14 this.focusCommandExecuted = false;
15 };
16
17 toolbox.prototype.focus = function() {
18 for ( var t = 0, toolbar; toolbar = this.toolbars[ t++ ]; ) {
19 for ( var i = 0, item; item = toolbar.items[ i++ ]; ) {
20 if ( item.focus ) {
21 item.focus();
22 return;
23 }
24 }
25 }
26 };
27
28 var commands = {
29 toolbarFocus: {
30 modes: { wysiwyg: 1, source: 1 },
31 readOnly: 1,
32
33 exec: function( editor ) {
34 if ( editor.toolbox ) {
35 editor.toolbox.focusCommandExecuted = true;
36
37 // Make the first button focus accessible for IE. (#3417)
38 // Adobe AIR instead need while of delay.
39 if ( CKEDITOR.env.ie || CKEDITOR.env.air ) {
40 setTimeout( function() {
41 editor.toolbox.focus();
42 }, 100 );
43 } else {
44 editor.toolbox.focus();
45 }
46 }
47 }
48 }
49 };
50
51 CKEDITOR.plugins.add( 'toolbar', {
52 requires: 'button',
53 // jscs:disable maximumLineLength
54 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,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%
55 // jscs:enable maximumLineLength
56
57 init: function( editor ) {
58 var endFlag;
59
60 var itemKeystroke = function( item, keystroke ) {
61 var next, toolbar;
62 var rtl = editor.lang.dir == 'rtl',
63 toolbarGroupCycling = editor.config.toolbarGroupCycling,
64 // Picking right/left key codes.
65 rightKeyCode = rtl ? 37 : 39,
66 leftKeyCode = rtl ? 39 : 37;
67
68 toolbarGroupCycling = toolbarGroupCycling === undefined || toolbarGroupCycling;
69
70 switch ( keystroke ) {
71 case 9: // TAB
72 case CKEDITOR.SHIFT + 9: // SHIFT + TAB
73 // Cycle through the toolbars, starting from the one
74 // closest to the current item.
75 while ( !toolbar || !toolbar.items.length ) {
76 if ( keystroke == 9 ) {
77 toolbar = ( ( toolbar ? toolbar.next : item.toolbar.next ) || editor.toolbox.toolbars[ 0 ] );
78 } else {
79 toolbar = ( ( toolbar ? toolbar.previous : item.toolbar.previous ) || editor.toolbox.toolbars[ editor.toolbox.toolbars.length - 1 ] );
80 }
81
82 // Look for the first item that accepts focus.
83 if ( toolbar.items.length ) {
84 item = toolbar.items[ endFlag ? ( toolbar.items.length - 1 ) : 0 ];
85 while ( item && !item.focus ) {
86 item = endFlag ? item.previous : item.next;
87
88 if ( !item )
89 toolbar = 0;
90 }
91 }
92 }
93
94 if ( item )
95 item.focus();
96
97 return false;
98
99 case rightKeyCode:
100 next = item;
101 do {
102 // Look for the next item in the toolbar.
103 next = next.next;
104
105 // If it's the last item, cycle to the first one.
106 if ( !next && toolbarGroupCycling ) next = item.toolbar.items[ 0 ];
107 }
108 while ( next && !next.focus );
109
110 // If available, just focus it, otherwise focus the
111 // first one.
112 if ( next )
113 next.focus();
114 else
115 // Send a TAB.
116 itemKeystroke( item, 9 );
117
118 return false;
119 case 40: // DOWN-ARROW
120 if ( item.button && item.button.hasArrow ) {
121 // Note: code is duplicated in plugins\richcombo\plugin.js in keyDownFn().
122 editor.once( 'panelShow', function( evt ) {
123 evt.data._.panel._.currentBlock.onKeyDown( 40 );
124 } );
125 item.execute();
126 } else {
127 // Send left arrow key.
128 itemKeystroke( item, keystroke == 40 ? rightKeyCode : leftKeyCode );
129 }
130 return false;
131 case leftKeyCode:
132 case 38: // UP-ARROW
133 next = item;
134 do {
135 // Look for the previous item in the toolbar.
136 next = next.previous;
137
138 // If it's the first item, cycle to the last one.
139 if ( !next && toolbarGroupCycling ) next = item.toolbar.items[ item.toolbar.items.length - 1 ];
140 }
141 while ( next && !next.focus );
142
143 // If available, just focus it, otherwise focus the
144 // last one.
145 if ( next )
146 next.focus();
147 else {
148 endFlag = 1;
149 // Send a SHIFT + TAB.
150 itemKeystroke( item, CKEDITOR.SHIFT + 9 );
151 endFlag = 0;
152 }
153
154 return false;
155
156 case 27: // ESC
157 editor.focus();
158 return false;
159
160 case 13: // ENTER
161 case 32: // SPACE
162 item.execute();
163 return false;
164 }
165 return true;
166 };
167
168 editor.on( 'uiSpace', function( event ) {
169 if ( event.data.space != editor.config.toolbarLocation )
170 return;
171
172 // Create toolbar only once.
173 event.removeListener();
174
175 editor.toolbox = new toolbox();
176
177 var labelId = CKEDITOR.tools.getNextId();
178
179 var output = [
180 '<span id="', labelId, '" class="cke_voice_label">', editor.lang.toolbar.toolbars, '</span>',
181 '<span id="' + editor.ui.spaceId( 'toolbox' ) + '" class="cke_toolbox" role="group" aria-labelledby="', labelId, '" onmousedown="return false;">'
182 ];
183
184 var expanded = editor.config.toolbarStartupExpanded !== false,
185 groupStarted, pendingSeparator;
186
187 // If the toolbar collapser will be available, we'll have
188 // an additional container for all toolbars.
189 if ( editor.config.toolbarCanCollapse && editor.elementMode != CKEDITOR.ELEMENT_MODE_INLINE )
190 output.push( '<span class="cke_toolbox_main"' + ( expanded ? '>' : ' style="display:none">' ) );
191
192 var toolbars = editor.toolbox.toolbars,
193 toolbar = getToolbarConfig( editor ),
194 toolbarLength = toolbar.length;
195
196 for ( var r = 0; r < toolbarLength; r++ ) {
197 var toolbarId,
198 toolbarObj = 0,
199 toolbarName,
200 row = toolbar[ r ],
201 lastToolbarInRow = row !== '/' && ( toolbar[ r + 1 ] === '/' || r == toolbarLength - 1 ),
202 items;
203
204 // It's better to check if the row object is really
205 // available because it's a common mistake to leave
206 // an extra comma in the toolbar definition
207 // settings, which leads on the editor not loading
208 // at all in IE. (#3983)
209 if ( !row )
210 continue;
211
212 if ( groupStarted ) {
213 output.push( '</span>' );
214 groupStarted = 0;
215 pendingSeparator = 0;
216 }
217
218 if ( row === '/' ) {
219 output.push( '<span class="cke_toolbar_break"></span>' );
220 continue;
221 }
222
223 items = row.items || row;
224
225 // Create all items defined for this toolbar.
226 for ( var i = 0; i < items.length; i++ ) {
227 var item = items[ i ],
228 canGroup;
229
230 if ( item ) {
231 if ( item.type == CKEDITOR.UI_SEPARATOR ) {
232 // Do not add the separator immediately. Just save
233 // it be included if we already have something in
234 // the toolbar and if a new item is to be added (later).
235 pendingSeparator = groupStarted && item;
236 continue;
237 }
238
239 canGroup = item.canGroup !== false;
240
241 // Initialize the toolbar first, if needed.
242 if ( !toolbarObj ) {
243 // Create the basic toolbar object.
244 toolbarId = CKEDITOR.tools.getNextId();
245 toolbarObj = { id: toolbarId, items: [] };
246 toolbarName = row.name && ( editor.lang.toolbar.toolbarGroups[ row.name ] || row.name );
247
248 // Output the toolbar opener.
249 output.push( '<span id="', toolbarId, '" class="cke_toolbar' + ( lastToolbarInRow ? ' cke_toolbar_last"' : '"' ),
250 ( toolbarName ? ' aria-labelledby="' + toolbarId + '_label"' : '' ), ' role="toolbar">' );
251
252 // If a toolbar name is available, send the voice label.
253 toolbarName && output.push( '<span id="', toolbarId, '_label" class="cke_voice_label">', toolbarName, '</span>' );
254
255 output.push( '<span class="cke_toolbar_start"></span>' );
256
257 // Add the toolbar to the "editor.toolbox.toolbars"
258 // array.
259 var index = toolbars.push( toolbarObj ) - 1;
260
261 // Create the next/previous reference.
262 if ( index > 0 ) {
263 toolbarObj.previous = toolbars[ index - 1 ];
264 toolbarObj.previous.next = toolbarObj;
265 }
266 }
267
268 if ( canGroup ) {
269 if ( !groupStarted ) {
270 output.push( '<span class="cke_toolgroup" role="presentation">' );
271 groupStarted = 1;
272 }
273 } else if ( groupStarted ) {
274 output.push( '</span>' );
275 groupStarted = 0;
276 }
277
278 function addItem( item ) { // jshint ignore:line
279 var itemObj = item.render( editor, output );
280 index = toolbarObj.items.push( itemObj ) - 1;
281
282 if ( index > 0 ) {
283 itemObj.previous = toolbarObj.items[ index - 1 ];
284 itemObj.previous.next = itemObj;
285 }
286
287 itemObj.toolbar = toolbarObj;
288 itemObj.onkey = itemKeystroke;
289
290 // Fix for #3052:
291 // Prevent JAWS from focusing the toolbar after document load.
292 itemObj.onfocus = function() {
293 if ( !editor.toolbox.focusCommandExecuted )
294 editor.focus();
295 };
296 }
297
298 if ( pendingSeparator ) {
299 addItem( pendingSeparator );
300 pendingSeparator = 0;
301 }
302
303 addItem( item );
304 }
305 }
306
307 if ( groupStarted ) {
308 output.push( '</span>' );
309 groupStarted = 0;
310 pendingSeparator = 0;
311 }
312
313 if ( toolbarObj )
314 output.push( '<span class="cke_toolbar_end"></span></span>' );
315 }
316
317 if ( editor.config.toolbarCanCollapse )
318 output.push( '</span>' );
319
320 // Not toolbar collapser for inline mode.
321 if ( editor.config.toolbarCanCollapse && editor.elementMode != CKEDITOR.ELEMENT_MODE_INLINE ) {
322 var collapserFn = CKEDITOR.tools.addFunction( function() {
323 editor.execCommand( 'toolbarCollapse' );
324 } );
325
326 editor.on( 'destroy', function() {
327 CKEDITOR.tools.removeFunction( collapserFn );
328 } );
329
330 editor.addCommand( 'toolbarCollapse', {
331 readOnly: 1,
332 exec: function( editor ) {
333 var collapser = editor.ui.space( 'toolbar_collapser' ),
334 toolbox = collapser.getPrevious(),
335 contents = editor.ui.space( 'contents' ),
336 toolboxContainer = toolbox.getParent(),
337 contentHeight = parseInt( contents.$.style.height, 10 ),
338 previousHeight = toolboxContainer.$.offsetHeight,
339 minClass = 'cke_toolbox_collapser_min',
340 collapsed = collapser.hasClass( minClass );
341
342 if ( !collapsed ) {
343 toolbox.hide();
344 collapser.addClass( minClass );
345 collapser.setAttribute( 'title', editor.lang.toolbar.toolbarExpand );
346 } else {
347 toolbox.show();
348 collapser.removeClass( minClass );
349 collapser.setAttribute( 'title', editor.lang.toolbar.toolbarCollapse );
350 }
351
352 // Update collapser symbol.
353 collapser.getFirst().setText( collapsed ? '\u25B2' : // BLACK UP-POINTING TRIANGLE
354 '\u25C0' ); // BLACK LEFT-POINTING TRIANGLE
355
356 var dy = toolboxContainer.$.offsetHeight - previousHeight;
357 contents.setStyle( 'height', ( contentHeight - dy ) + 'px' );
358
359 editor.fire( 'resize', {
360 outerHeight: editor.container.$.offsetHeight,
361 contentsHeight: contents.$.offsetHeight,
362 outerWidth: editor.container.$.offsetWidth
363 } );
364 },
365
366 modes: { wysiwyg: 1, source: 1 }
367 } );
368
369 editor.setKeystroke( CKEDITOR.ALT + ( CKEDITOR.env.ie || CKEDITOR.env.webkit ? 189 : 109 ) /*-*/, 'toolbarCollapse' );
370
371 output.push( '<a title="' + ( expanded ? editor.lang.toolbar.toolbarCollapse : editor.lang.toolbar.toolbarExpand ) +
372 '" id="' + editor.ui.spaceId( 'toolbar_collapser' ) +
373 '" tabIndex="-1" class="cke_toolbox_collapser' );
374
375 if ( !expanded )
376 output.push( ' cke_toolbox_collapser_min' );
377
378 output.push( '" onclick="CKEDITOR.tools.callFunction(' + collapserFn + ')">', '<span class="cke_arrow">&#9650;</span>', // BLACK UP-POINTING TRIANGLE
379 '</a>' );
380 }
381
382 output.push( '</span>' );
383 event.data.html += output.join( '' );
384 } );
385
386 editor.on( 'destroy', function() {
387 if ( this.toolbox ) {
388 var toolbars,
389 index = 0,
390 i, items, instance;
391 toolbars = this.toolbox.toolbars;
392 for ( ; index < toolbars.length; index++ ) {
393 items = toolbars[ index ].items;
394 for ( i = 0; i < items.length; i++ ) {
395 instance = items[ i ];
396 if ( instance.clickFn )
397 CKEDITOR.tools.removeFunction( instance.clickFn );
398 if ( instance.keyDownFn )
399 CKEDITOR.tools.removeFunction( instance.keyDownFn );
400 }
401 }
402 }
403 } );
404
405 // Manage editor focus when navigating the toolbar.
406 editor.on( 'uiReady', function() {
407 var toolbox = editor.ui.space( 'toolbox' );
408 toolbox && editor.focusManager.add( toolbox, 1 );
409 } );
410
411 editor.addCommand( 'toolbarFocus', commands.toolbarFocus );
412 editor.setKeystroke( CKEDITOR.ALT + 121 /*F10*/, 'toolbarFocus' );
413
414 editor.ui.add( '-', CKEDITOR.UI_SEPARATOR, {} );
415 editor.ui.addHandler( CKEDITOR.UI_SEPARATOR, {
416 create: function() {
417 return {
418 render: function( editor, output ) {
419 output.push( '<span class="cke_toolbar_separator" role="separator"></span>' );
420 return {};
421 }
422 };
423 }
424 } );
425 }
426 } );
427
428 function getToolbarConfig( editor ) {
429 var removeButtons = editor.config.removeButtons;
430
431 removeButtons = removeButtons && removeButtons.split( ',' );
432
433 function buildToolbarConfig() {
434
435 // Object containing all toolbar groups used by ui items.
436 var lookup = getItemDefinedGroups();
437
438 // Take the base for the new toolbar, which is basically a toolbar
439 // definition without items.
440 var toolbar = CKEDITOR.tools.clone( editor.config.toolbarGroups ) || getPrivateToolbarGroups( editor );
441
442 // Fill the toolbar groups with the available ui items.
443 for ( var i = 0; i < toolbar.length; i++ ) {
444 var toolbarGroup = toolbar[ i ];
445
446 // Skip toolbar break.
447 if ( toolbarGroup == '/' )
448 continue;
449 // Handle simply group name item.
450 else if ( typeof toolbarGroup == 'string' )
451 toolbarGroup = toolbar[ i ] = { name: toolbarGroup };
452
453 var items, subGroups = toolbarGroup.groups;
454
455 // Look for items that match sub groups.
456 if ( subGroups ) {
457 for ( var j = 0, sub; j < subGroups.length; j++ ) {
458 sub = subGroups[ j ];
459
460 // If any ui item is registered for this subgroup.
461 items = lookup[ sub ];
462 items && fillGroup( toolbarGroup, items );
463 }
464 }
465
466 // Add the main group items as well.
467 items = lookup[ toolbarGroup.name ];
468 items && fillGroup( toolbarGroup, items );
469 }
470
471 return toolbar;
472 }
473
474 // Returns an object containing all toolbar groups used by ui items.
475 function getItemDefinedGroups() {
476 var groups = {},
477 itemName, item, itemToolbar, group, order;
478
479 for ( itemName in editor.ui.items ) {
480 item = editor.ui.items[ itemName ];
481 itemToolbar = item.toolbar || 'others';
482 if ( itemToolbar ) {
483 // Break the toolbar property into its parts: "group_name[,order]".
484 itemToolbar = itemToolbar.split( ',' );
485 group = itemToolbar[ 0 ];
486 order = parseInt( itemToolbar[ 1 ] || -1, 10 );
487
488 // Initialize the group, if necessary.
489 groups[ group ] || ( groups[ group ] = [] );
490
491 // Push the data used to build the toolbar later.
492 groups[ group ].push( { name: itemName, order: order } );
493 }
494 }
495
496 // Put the items in the right order.
497 for ( group in groups ) {
498 groups[ group ] = groups[ group ].sort( function( a, b ) {
499 return a.order == b.order ? 0 :
500 b.order < 0 ? -1 :
501 a.order < 0 ? 1 :
502 a.order < b.order ? -1 :
503 1;
504 } );
505 }
506
507 return groups;
508 }
509
510 function fillGroup( toolbarGroup, uiItems ) {
511 if ( uiItems.length ) {
512 if ( toolbarGroup.items )
513 toolbarGroup.items.push( editor.ui.create( '-' ) );
514 else
515 toolbarGroup.items = [];
516
517 var item, name;
518 while ( ( item = uiItems.shift() ) ) {
519 name = typeof item == 'string' ? item : item.name;
520
521 // Ignore items that are configured to be removed.
522 if ( !removeButtons || CKEDITOR.tools.indexOf( removeButtons, name ) == -1 ) {
523 item = editor.ui.create( name );
524
525 if ( !item )
526 continue;
527
528 if ( !editor.addFeature( item ) )
529 continue;
530
531 toolbarGroup.items.push( item );
532 }
533 }
534 }
535 }
536
537 function populateToolbarConfig( config ) {
538 var toolbar = [],
539 i, group, newGroup;
540
541 for ( i = 0; i < config.length; ++i ) {
542 group = config[ i ];
543 newGroup = {};
544
545 if ( group == '/' )
546 toolbar.push( group );
547 else if ( CKEDITOR.tools.isArray( group ) ) {
548 fillGroup( newGroup, CKEDITOR.tools.clone( group ) );
549 toolbar.push( newGroup );
550 }
551 else if ( group.items ) {
552 fillGroup( newGroup, CKEDITOR.tools.clone( group.items ) );
553 newGroup.name = group.name;
554 toolbar.push( newGroup );
555 }
556 }
557
558 return toolbar;
559 }
560
561 var toolbar = editor.config.toolbar;
562
563 // If it is a string, return the relative "toolbar_name" config.
564 if ( typeof toolbar == 'string' )
565 toolbar = editor.config[ 'toolbar_' + toolbar ];
566
567 return ( editor.toolbar = toolbar ? populateToolbarConfig( toolbar ) : buildToolbarConfig() );
568 }
569
570 /**
571 * Adds a toolbar group. See {@link CKEDITOR.config#toolbarGroups} for more details.
572 *
573 * **Note:** This method will not modify toolbar groups set explicitly by
574 * {@link CKEDITOR.config#toolbarGroups}. It will only extend the default setting.
575 *
576 * @param {String} name Toolbar group name.
577 * @param {Number/String} previous The name of the toolbar group after which this one
578 * should be added or `0` if this group should be the first one.
579 * @param {String} [subgroupOf] The name of the parent group.
580 * @member CKEDITOR.ui
581 */
582 CKEDITOR.ui.prototype.addToolbarGroup = function( name, previous, subgroupOf ) {
583 // The toolbarGroups from the privates is the one we gonna use for automatic toolbar creation.
584 var toolbarGroups = getPrivateToolbarGroups( this.editor ),
585 atStart = previous === 0,
586 newGroup = { name: name };
587
588 if ( subgroupOf ) {
589 // Transform the subgroupOf name in the real subgroup object.
590 subgroupOf = CKEDITOR.tools.search( toolbarGroups, function( group ) {
591 return group.name == subgroupOf;
592 } );
593
594 if ( subgroupOf ) {
595 !subgroupOf.groups && ( subgroupOf.groups = [] ) ;
596
597 if ( previous ) {
598 // Search the "previous" item and add the new one after it.
599 previous = CKEDITOR.tools.indexOf( subgroupOf.groups, previous );
600 if ( previous >= 0 ) {
601 subgroupOf.groups.splice( previous + 1, 0, name );
602 return;
603 }
604 }
605
606 // If no previous found.
607
608 if ( atStart )
609 subgroupOf.groups.splice( 0, 0, name );
610 else
611 subgroupOf.groups.push( name );
612 return;
613 } else {
614 // Ignore "previous" if subgroupOf has not been found.
615 previous = null;
616 }
617 }
618
619 if ( previous ) {
620 // Transform the "previous" name into its index.
621 previous = CKEDITOR.tools.indexOf( toolbarGroups, function( group ) {
622 return group.name == previous;
623 } );
624 }
625
626 if ( atStart )
627 toolbarGroups.splice( 0, 0, name );
628 else if ( typeof previous == 'number' )
629 toolbarGroups.splice( previous + 1, 0, newGroup );
630 else
631 toolbarGroups.push( name );
632 };
633
634 function getPrivateToolbarGroups( editor ) {
635 return editor._.toolbarGroups || ( editor._.toolbarGroups = [
636 { name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
637 { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
638 { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
639 { name: 'forms' },
640 '/',
641 { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
642 { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
643 { name: 'links' },
644 { name: 'insert' },
645 '/',
646 { name: 'styles' },
647 { name: 'colors' },
648 { name: 'tools' },
649 { name: 'others' },
650 { name: 'about' }
651 ] );
652 }
653} )();
654
655/**
656 * Separator UI element.
657 *
658 * @readonly
659 * @property {String} [='separator']
660 * @member CKEDITOR
661 */
662CKEDITOR.UI_SEPARATOR = 'separator';
663
664/**
665 * The part of the user interface where the toolbar will be rendered. For the default
666 * editor implementation, the recommended options are `'top'` and `'bottom'`.
667 *
668 * Please note that this option is only applicable to [classic](#!/guide/dev_framed)
669 * (`iframe`-based) editor. In case of [inline](#!/guide/dev_inline) editor the toolbar
670 * position is set dynamically depending on the position of the editable element on the screen.
671 *
672 * Read more in the [documentation](#!/guide/dev_toolbarlocation)
673 * and see the [SDK sample](http://sdk.ckeditor.com/samples/toolbarlocation.html).
674 *
675 * config.toolbarLocation = 'bottom';
676 *
677 * @cfg
678 * @member CKEDITOR.config
679 */
680CKEDITOR.config.toolbarLocation = 'top';
681
682/**
683 * The toolbox (alias toolbar) definition. It is a toolbar name or an array of
684 * toolbars (strips), each one being also an array, containing a list of UI items.
685 *
686 * If set to `null`, the toolbar will be generated automatically using all available buttons
687 * and {@link #toolbarGroups} as a toolbar groups layout.
688 *
689 * In CKEditor 4.5+ you can generate your toolbar customization code by using the [visual
690 * toolbar configurator](http://docs.ckeditor.com/#!/guide/dev_toolbar).
691 *
692 * // Defines a toolbar with only one strip containing the "Source" button, a
693 * // separator, and the "Bold" and "Italic" buttons.
694 * config.toolbar = [
695 * [ 'Source', '-', 'Bold', 'Italic' ]
696 * ];
697 *
698 * // Similar to the example above, defines a "Basic" toolbar with only one strip containing three buttons.
699 * // Note that this setting is composed by "toolbar_" added to the toolbar name, which in this case is called "Basic".
700 * // This second part of the setting name can be anything. You must use this name in the CKEDITOR.config.toolbar setting
701 * // in order to instruct the editor which `toolbar_(name)` setting should be used.
702 * config.toolbar_Basic = [
703 * [ 'Source', '-', 'Bold', 'Italic' ]
704 * ];
705 * // Load toolbar_Name where Name = Basic.
706 * config.toolbar = 'Basic';
707 *
708 * @cfg {Array/String} [toolbar=null]
709 * @member CKEDITOR.config
710 */
711
712/**
713 * The toolbar groups definition.
714 *
715 * If the toolbar layout is not explicitly defined by the {@link #toolbar} setting, then
716 * this setting is used to group all defined buttons (see {@link CKEDITOR.ui#addButton}).
717 * Buttons are associated with toolbar groups by the `toolbar` property in their definition objects.
718 *
719 * New groups may be dynamically added during the editor and plugin initialization by
720 * {@link CKEDITOR.ui#addToolbarGroup}. This is only possible if the default setting was used.
721 *
722 * // Default setting.
723 * config.toolbarGroups = [
724 * { name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
725 * { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
726 * { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
727 * { name: 'forms' },
728 * '/',
729 * { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
730 * { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
731 * { name: 'links' },
732 * { name: 'insert' },
733 * '/',
734 * { name: 'styles' },
735 * { name: 'colors' },
736 * { name: 'tools' },
737 * { name: 'others' },
738 * { name: 'about' }
739 * ];
740 *
741 * @cfg {Array} [toolbarGroups=see example]
742 * @member CKEDITOR.config
743 */
744
745/**
746 * Whether the toolbar can be collapsed by the user. If disabled, the Collapse Toolbar
747 * button will not be displayed.
748 *
749 * config.toolbarCanCollapse = true;
750 *
751 * @cfg {Boolean} [toolbarCanCollapse=false]
752 * @member CKEDITOR.config
753 */
754
755/**
756 * Whether the toolbar must start expanded when the editor is loaded.
757 *
758 * Setting this option to `false` will affect the toolbar only when
759 * {@link #toolbarCanCollapse} is set to `true`:
760 *
761 * config.toolbarCanCollapse = true;
762 * config.toolbarStartupExpanded = false;
763 *
764 * @cfg {Boolean} [toolbarStartupExpanded=true]
765 * @member CKEDITOR.config
766 */
767
768/**
769 * When enabled, causes the *Arrow* keys navigation to cycle within the current
770 * toolbar group. Otherwise the *Arrow* keys will move through all items available in
771 * the toolbar. The *Tab* key will still be used to quickly jump among the
772 * toolbar groups.
773 *
774 * config.toolbarGroupCycling = false;
775 *
776 * @since 3.6
777 * @cfg {Boolean} [toolbarGroupCycling=true]
778 * @member CKEDITOR.config
779 */
780
781/**
782 * List of toolbar button names that must not be rendered. This will also work
783 * for non-button toolbar items, like the Font drop-down list.
784 *
785 * config.removeButtons = 'Underline,JustifyCenter';
786 *
787 * This configuration option should not be overused. The recommended way is to use the
788 * {@link CKEDITOR.config#removePlugins} setting to remove features from the editor
789 * or even better, [create a custom editor build](http://ckeditor.com/builder) with
790 * just the features that you will use.
791 * In some cases though, a single plugin may define a set of toolbar buttons and
792 * `removeButtons` may be useful when just a few of them are to be removed.
793 *
794 * @cfg {String} [removeButtons]
795 * @member CKEDITOR.config
796 */
797
798/**
799 * The toolbar definition used by the editor. It is created from the
800 * {@link CKEDITOR.config#toolbar} option if it is set or automatically
801 * based on {@link CKEDITOR.config#toolbarGroups}.
802 *
803 * @readonly
804 * @property {Object} toolbar
805 * @member CKEDITOR.editor
806 */
diff --git a/sources/plugins/toolbar/samples/toolbar.html b/sources/plugins/toolbar/samples/toolbar.html
new file mode 100644
index 0000000..e40d2a1
--- /dev/null
+++ b/sources/plugins/toolbar/samples/toolbar.html
@@ -0,0 +1,235 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Toolbar Configuration &mdash; CKEditor Sample</title>
10 <meta name="ckeditor-sample-name" content="Toolbar Configurations">
11 <meta name="ckeditor-sample-group" content="Advanced Samples">
12 <meta name="ckeditor-sample-description" content="Configuring CKEditor to display full or custom toolbar layout.">
13 <script src="../../../ckeditor.js"></script>
14 <link href="../../../samples/old/sample.css" rel="stylesheet">
15</head>
16<body>
17 <h1 class="samples">
18 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Toolbar Configuration
19 </h1>
20 <div class="warning deprecated">
21 This sample is not maintained anymore. Check out the <a href="../../../samples/toolbarconfigurator/index.html#basic">brand new CKEditor Toolbar Configurator</a>.
22 </div>
23 <div class="description">
24 <p>
25 This sample page demonstrates editor with loaded <a href="#fullToolbar">full toolbar</a> (all registered buttons) and, if
26 current editor's configuration modifies default settings, also editor with <a href="#currentToolbar">modified toolbar</a>.
27 </p>
28
29 <p>Since CKEditor 4 there are two ways to configure toolbar buttons.</p>
30
31 <h2 class="samples">By <a href="http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-toolbar">config.toolbar</a></h2>
32
33 <p>
34 You can explicitly define which buttons are displayed in which groups and in which order.
35 This is the more precise setting, but less flexible. If newly added plugin adds its
36 own button you'll have to add it manually to your <code>config.toolbar</code> setting as well.
37 </p>
38
39 <p>To add a CKEditor instance with custom toolbar setting, insert the following JavaScript call to your code:</p>
40
41 <pre class="samples">
42CKEDITOR.replace( <em>'textarea_id'</em>, {
43 <strong>toolbar:</strong> [
44 { name: 'document', items: [ 'Source', '-', 'NewPage', 'Preview', '-', 'Templates' ] }, // Defines toolbar group with name (used to create voice label) and items in 3 subgroups.
45 [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ], // Defines toolbar group without name.
46 '/', // Line break - next group will be placed in new line.
47 { name: 'basicstyles', items: [ 'Bold', 'Italic' ] }
48 ]
49});</pre>
50
51 <h2 class="samples">By <a href="http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-toolbarGroups">config.toolbarGroups</a></h2>
52
53 <p>
54 You can define which groups of buttons (like e.g. <code>basicstyles</code>, <code>clipboard</code>
55 and <code>forms</code>) are displayed and in which order. Registered buttons are associated
56 with toolbar groups by <code>toolbar</code> property in their definition.
57 This setting's advantage is that you don't have to modify toolbar configuration
58 when adding/removing plugins which register their own buttons.
59 </p>
60
61 <p>To add a CKEditor instance with custom toolbar groups setting, insert the following JavaScript call to your code:</p>
62
63 <pre class="samples">
64CKEDITOR.replace( <em>'textarea_id'</em>, {
65 <strong>toolbarGroups:</strong> [
66 { name: 'document', groups: [ 'mode', 'document' ] }, // Displays document group with its two subgroups.
67 { name: 'clipboard', groups: [ 'clipboard', 'undo' ] }, // Group's name will be used to create voice label.
68 '/', // Line break - next group will be placed in new line.
69 { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
70 { name: 'links' }
71 ]
72
73 // NOTE: Remember to leave 'toolbar' property with the default value (null).
74});</pre>
75 </div>
76
77 <div id="currentToolbar" style="display: none">
78 <h2 class="samples">Current toolbar configuration</h2>
79 <p>Below you can see editor with current toolbar definition.</p>
80 <textarea cols="80" id="editorCurrent" name="editorCurrent" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
81 <pre id="editorCurrentCfg" class="samples"></pre>
82 </div>
83
84 <div id="fullToolbar">
85 <h2 class="samples">Full toolbar configuration</h2>
86 <p>Below you can see editor with full toolbar, generated automatically by the editor.</p>
87 <p>
88 <strong>Note</strong>: To create editor instance with full toolbar you don't have to set anything.
89 Just leave <code>toolbar</code> and <code>toolbarGroups</code> with the default, <code>null</code> values.
90 </p>
91 <textarea cols="80" id="editorFull" name="editorFull" rows="10">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
92 <pre id="editorFullCfg" class="samples"></pre>
93 </div>
94
95 <script>
96
97(function() {
98 'use strict';
99
100 var buttonsNames;
101
102 CKEDITOR.config.extraPlugins = 'toolbar';
103
104 CKEDITOR.on( 'instanceReady', function( evt ) {
105 var editor = evt.editor,
106 editorCurrent = editor.name == 'editorCurrent',
107 defaultToolbar = !( editor.config.toolbar || editor.config.toolbarGroups || editor.config.removeButtons ),
108 pre = CKEDITOR.document.getById( editor.name + 'Cfg' ),
109 output = '';
110
111 if ( editorCurrent ) {
112 // If default toolbar configuration has been modified, show "current toolbar" section.
113 if ( !defaultToolbar )
114 CKEDITOR.document.getById( 'currentToolbar' ).show();
115 else
116 return;
117 }
118
119 if ( !buttonsNames )
120 buttonsNames = createButtonsNamesHash( editor.ui.items );
121
122 // Toolbar isn't set explicitly, so it was created automatically from toolbarGroups.
123 if ( !editor.config.toolbar ) {
124 output +=
125 '// Toolbar configuration generated automatically by the editor based on config.toolbarGroups.\n' +
126 dumpToolbarConfiguration( editor ) +
127 '\n\n' +
128 '// Toolbar groups configuration.\n' +
129 dumpToolbarConfiguration( editor, true )
130 }
131 // Toolbar groups doesn't count in this case - print only toolbar.
132 else {
133 output += '// Toolbar configuration.\n' +
134 dumpToolbarConfiguration( editor );
135 }
136
137 // Recreate to avoid old IE from loosing whitespaces on filling <pre> content.
138 var preOutput = pre.getOuterHtml().replace( /(?=<\/)/, output );
139 CKEDITOR.dom.element.createFromHtml( preOutput ).replace( pre );
140 } );
141
142 CKEDITOR.replace( 'editorCurrent', { height: 100 } );
143 CKEDITOR.replace( 'editorFull', {
144 // Reset toolbar settings, so full toolbar will be generated automatically.
145 toolbar: null,
146 toolbarGroups: null,
147 removeButtons: null,
148 height: 100
149 } );
150
151 function dumpToolbarConfiguration( editor, printGroups ) {
152 var output = [],
153 toolbar = editor.toolbar;
154
155 for ( var i = 0; i < toolbar.length; ++i ) {
156 var group = dumpToolbarGroup( toolbar[ i ], printGroups );
157 if ( group )
158 output.push( group );
159 }
160
161 return 'config.toolbar' + ( printGroups ? 'Groups' : '' ) + ' = [\n\t' + output.join( ',\n\t' ) + '\n];';
162 }
163
164 function dumpToolbarGroup( group, printGroups ) {
165 var output = [];
166
167 if ( typeof group == 'string' )
168 return '\'' + group + '\'';
169 if ( CKEDITOR.tools.isArray( group ) )
170 return dumpToolbarItems( group );
171 // Skip group when printing entire toolbar configuration and there are no items in this group.
172 if ( !printGroups && !group.items )
173 return;
174
175 if ( group.name )
176 output.push( 'name: \'' + group.name + '\'' );
177
178 if ( group.groups )
179 output.push( 'groups: ' + dumpToolbarItems( group.groups ) );
180
181 if ( !printGroups )
182 output.push( 'items: ' + dumpToolbarItems( group.items ) );
183
184 return '{ ' + output.join( ', ' ) + ' }';
185 }
186
187 function dumpToolbarItems( items ) {
188 if ( typeof items == 'string' )
189 return '\'' + items + '\'';
190
191 var names = [],
192 i, item;
193
194 for ( var i = 0; i < items.length; ++i ) {
195 item = items[ i ];
196 if ( typeof item == 'string' )
197 names.push( item );
198 else {
199 if ( item.type == CKEDITOR.UI_SEPARATOR )
200 names.push( '-' );
201 else
202 names.push( buttonsNames[ item.name ] );
203 }
204 }
205
206 return '[ \'' + names.join( '\', \'' ) + '\' ]';
207 }
208
209 // Creates { 'lowercased': 'LowerCased' } buttons names hash.
210 function createButtonsNamesHash( items ) {
211 var hash = {},
212 name;
213
214 for ( name in items ) {
215 hash[ items[ name ].name ] = name;
216 }
217
218 return hash;
219 }
220
221})();
222 </script>
223
224 <div id="footer">
225 <hr>
226 <p>
227 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
228 </p>
229 <p id="copy">
230 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
231 Knabben. All rights reserved.
232 </p>
233 </div>
234</body>
235</html>
diff --git a/sources/plugins/widget/dev/assets/contents.css b/sources/plugins/widget/dev/assets/contents.css
new file mode 100644
index 0000000..2cff316
--- /dev/null
+++ b/sources/plugins/widget/dev/assets/contents.css
@@ -0,0 +1,23 @@
1.mediumBorder {
2 border-width: 2px;
3}
4.thickBorder {
5 border-width: 5px;
6}
7img.thickBorder, img.mediumBorder {
8 border-style: solid;
9 border-color: #CCC;
10}
11.important.soMuch {
12 margin: 25px;
13 padding: 25px;
14 background: red;
15 border: none;
16}
17
18span.redMarker {
19 background-color: red;
20}
21.invisible {
22 opacity: 0.1;
23}
diff --git a/sources/plugins/widget/dev/assets/sample.jpg b/sources/plugins/widget/dev/assets/sample.jpg
new file mode 100644
index 0000000..a4a77fa
--- /dev/null
+++ b/sources/plugins/widget/dev/assets/sample.jpg
Binary files differ
diff --git a/sources/plugins/widget/dev/assets/simplebox/contents.css b/sources/plugins/widget/dev/assets/simplebox/contents.css
new file mode 100644
index 0000000..ddf3675
--- /dev/null
+++ b/sources/plugins/widget/dev/assets/simplebox/contents.css
@@ -0,0 +1,36 @@
1.simplebox {
2 padding: 8px;
3 margin: 10px;
4 background: #eee;
5 border-radius: 8px;
6 border: 1px solid #ddd;
7 box-shadow: 0 1px 1px #fff inset, 0 -1px 0px #ccc inset;
8}
9.simplebox-title, .simplebox-content {
10 box-shadow: 0 1px 1px #ddd inset;
11 border: 1px solid #cccccc;
12 border-radius: 5px;
13 background: #fff;
14}
15.simplebox-title {
16 margin: 0 0 8px;
17 padding: 5px 8px;
18}
19.simplebox-content {
20 padding: 0 8px;
21}
22.simplebox-content::after {
23 content: '';
24 display: block;
25 clear: both;
26}
27.simplebox.align-right {
28 float: right;
29}
30.simplebox.align-left {
31 float: left;
32}
33.simplebox.align-center {
34 margin-left: auto;
35 margin-right: auto;
36}
diff --git a/sources/plugins/widget/dev/assets/simplebox/dialogs/simplebox.js b/sources/plugins/widget/dev/assets/simplebox/dialogs/simplebox.js
new file mode 100644
index 0000000..45a150c
--- /dev/null
+++ b/sources/plugins/widget/dev/assets/simplebox/dialogs/simplebox.js
@@ -0,0 +1,51 @@
1// Note: This automatic widget to dialog window binding (the fact that every field is set up from the widget
2// and is committed to the widget) is only possible when the dialog is opened by the Widgets System
3// (i.e. the widgetDef.dialog property is set).
4// When you are opening the dialog window by yourself, you need to take care of this by yourself too.
5
6CKEDITOR.dialog.add( 'simplebox', function( editor ) {
7 return {
8 title: 'Edit Simple Box',
9 minWidth: 200,
10 minHeight: 100,
11 contents: [
12 {
13 id: 'info',
14 elements: [
15 {
16 id: 'align',
17 type: 'select',
18 label: 'Align',
19 items: [
20 [ editor.lang.common.notSet, '' ],
21 [ editor.lang.common.alignLeft, 'left' ],
22 [ editor.lang.common.alignRight, 'right' ],
23 [ editor.lang.common.alignCenter, 'center' ]
24 ],
25 // When setting up this field, set its value to the "align" value from widget data.
26 // Note: Align values used in the widget need to be the same as those defined in the "items" array above.
27 setup: function( widget ) {
28 this.setValue( widget.data.align );
29 },
30 // When committing (saving) this field, set its value to the widget data.
31 commit: function( widget ) {
32 widget.setData( 'align', this.getValue() );
33 }
34 },
35 {
36 id: 'width',
37 type: 'text',
38 label: 'Width',
39 width: '50px',
40 setup: function( widget ) {
41 this.setValue( widget.data.width );
42 },
43 commit: function( widget ) {
44 widget.setData( 'width', this.getValue() );
45 }
46 }
47 ]
48 }
49 ]
50 };
51} );
diff --git a/sources/plugins/widget/dev/assets/simplebox/icons/simplebox.png b/sources/plugins/widget/dev/assets/simplebox/icons/simplebox.png
new file mode 100644
index 0000000..6a5e313
--- /dev/null
+++ b/sources/plugins/widget/dev/assets/simplebox/icons/simplebox.png
Binary files differ
diff --git a/sources/plugins/widget/dev/assets/simplebox/plugin.js b/sources/plugins/widget/dev/assets/simplebox/plugin.js
new file mode 100644
index 0000000..43dbad5
--- /dev/null
+++ b/sources/plugins/widget/dev/assets/simplebox/plugin.js
@@ -0,0 +1,114 @@
1'use strict';
2
3// Register the plugin within the editor.
4CKEDITOR.plugins.add( 'simplebox', {
5 // This plugin requires the Widgets System defined in the 'widget' plugin.
6 requires: 'widget',
7
8 // Register the icon used for the toolbar button. It must be the same
9 // as the name of the widget.
10 icons: 'simplebox',
11
12 // The plugin initialization logic goes inside this method.
13 init: function( editor ) {
14 // Register the editing dialog.
15 CKEDITOR.dialog.add( 'simplebox', this.path + 'dialogs/simplebox.js' );
16
17 // Register the simplebox widget.
18 editor.widgets.add( 'simplebox', {
19 // Allow all HTML elements, classes, and styles that this widget requires.
20 // Read more about the Advanced Content Filter here:
21 // * http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
22 // * http://docs.ckeditor.com/#!/guide/plugin_sdk_integration_with_acf
23 allowedContent:
24 'div(!simplebox,align-left,align-right,align-center){width};' +
25 'div(!simplebox-content); h2(!simplebox-title)',
26
27 // Minimum HTML which is required by this widget to work.
28 requiredContent: 'div(simplebox)',
29
30 // Define two nested editable areas.
31 editables: {
32 title: {
33 // Define CSS selector used for finding the element inside widget element.
34 selector: '.simplebox-title',
35 // Define content allowed in this nested editable. Its content will be
36 // filtered accordingly and the toolbar will be adjusted when this editable
37 // is focused.
38 allowedContent: 'br strong em'
39 },
40 content: {
41 selector: '.simplebox-content'
42 }
43 },
44
45 // Define the template of a new Simple Box widget.
46 // The template will be used when creating new instances of the Simple Box widget.
47 template:
48 '<div class="simplebox">' +
49 '<h2 class="simplebox-title">Title</h2>' +
50 '<div class="simplebox-content"><p>Content...</p></div>' +
51 '</div>',
52
53 // Define the label for a widget toolbar button which will be automatically
54 // created by the Widgets System. This button will insert a new widget instance
55 // created from the template defined above, or will edit selected widget
56 // (see second part of this tutorial to learn about editing widgets).
57 //
58 // Note: In order to be able to translate your widget you should use the
59 // editor.lang.simplebox.* property. A string was used directly here to simplify this tutorial.
60 button: 'Create a simple box',
61
62 // Set the widget dialog window name. This enables the automatic widget-dialog binding.
63 // This dialog window will be opened when creating a new widget or editing an existing one.
64 dialog: 'simplebox',
65
66 // Check the elements that need to be converted to widgets.
67 //
68 // Note: The "element" argument is an instance of http://docs.ckeditor.com/#!/api/CKEDITOR.htmlParser.element
69 // so it is not a real DOM element yet. This is caused by the fact that upcasting is performed
70 // during data processing which is done on DOM represented by JavaScript objects.
71 upcast: function( element ) {
72 // Return "true" (that element needs to converted to a Simple Box widget)
73 // for all <div> elements with a "simplebox" class.
74 return element.name == 'div' && element.hasClass( 'simplebox' );
75 },
76
77 // When a widget is being initialized, we need to read the data ("align" and "width")
78 // from DOM and set it by using the widget.setData() method.
79 // More code which needs to be executed when DOM is available may go here.
80 init: function() {
81 var width = this.element.getStyle( 'width' );
82 if ( width )
83 this.setData( 'width', width );
84
85 if ( this.element.hasClass( 'align-left' ) )
86 this.setData( 'align', 'left' );
87 if ( this.element.hasClass( 'align-right' ) )
88 this.setData( 'align', 'right' );
89 if ( this.element.hasClass( 'align-center' ) )
90 this.setData( 'align', 'center' );
91 },
92
93 // Listen on the widget#data event which is fired every time the widget data changes
94 // and updates the widget's view.
95 // Data may be changed by using the widget.setData() method, which we use in the
96 // Simple Box dialog window.
97 data: function() {
98 // Check whether "width" widget data is set and remove or set "width" CSS style.
99 // The style is set on widget main element (div.simplebox).
100 if ( !this.data.width )
101 this.element.removeStyle( 'width' );
102 else
103 this.element.setStyle( 'width', this.data.width );
104
105 // Brutally remove all align classes and set a new one if "align" widget data is set.
106 this.element.removeClass( 'align-left' );
107 this.element.removeClass( 'align-right' );
108 this.element.removeClass( 'align-center' );
109 if ( this.data.align )
110 this.element.addClass( 'align-' + this.data.align );
111 }
112 } );
113 }
114} );
diff --git a/sources/plugins/widget/dev/console.js b/sources/plugins/widget/dev/console.js
new file mode 100644
index 0000000..78db0d0
--- /dev/null
+++ b/sources/plugins/widget/dev/console.js
@@ -0,0 +1,131 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/* global CKCONSOLE */
7
8'use strict';
9
10( function() {
11
12 CKCONSOLE.add( 'widget', {
13 panels: [
14 {
15 type: 'box',
16 content: '<ul class="ckconsole_list ckconsole_value" data-value="instances"></ul>',
17
18 refresh: function( editor ) {
19 var instances = obj2Array( editor.widgets.instances );
20
21 return {
22 header: 'Instances (' + instances.length + ')',
23 instances: generateInstancesList( instances )
24 };
25 },
26
27 refreshOn: function( editor, refresh ) {
28 editor.widgets.on( 'instanceCreated', function( evt ) {
29 refresh();
30
31 evt.data.on( 'data', refresh );
32 } );
33
34 editor.widgets.on( 'instanceDestroyed', refresh );
35 }
36 },
37
38 {
39 type: 'box',
40 content:
41 '<ul class="ckconsole_list">' +
42 '<li>focused: <span class="ckconsole_value" data-value="focused"></span></li>' +
43 '<li>selected: <span class="ckconsole_value" data-value="selected"></span></li>' +
44 '</ul>',
45
46 refresh: function( editor ) {
47 var focused = editor.widgets.focused,
48 selected = editor.widgets.selected,
49 selectedIds = [];
50
51 for ( var i = 0; i < selected.length; ++i )
52 selectedIds.push( selected[ i ].id );
53
54 return {
55 header: 'Focus &amp; selection',
56 focused: focused ? 'id: ' + focused.id : '-',
57 selected: selectedIds.length ? 'id: ' + selectedIds.join( ', id: ' ) : '-'
58 };
59 },
60
61 refreshOn: function( editor, refresh ) {
62 editor.on( 'selectionCheck', refresh, null, null, 999 );
63 }
64 },
65
66 {
67 type: 'log',
68
69 on: function( editor, log, logFn ) {
70 // Add all listeners with high priorities to log
71 // messages in the correct order when one event depends on another.
72 // E.g. selectionChange triggers widget selection - if this listener
73 // for selectionChange will be executed later than that one, then order
74 // will be incorrect.
75
76 editor.on( 'selectionChange', function( evt ) {
77 var msg = 'selection change',
78 sel = evt.data.selection,
79 el = sel.getSelectedElement(),
80 widget;
81
82 if ( el && ( widget = editor.widgets.getByElement( el, true ) ) )
83 msg += ' (id: ' + widget.id + ')';
84
85 log( msg );
86 }, null, null, 1 );
87
88 editor.widgets.on( 'instanceDestroyed', function( evt ) {
89 log( 'instance destroyed (id: ' + evt.data.id + ')' );
90 }, null, null, 1 );
91
92 editor.widgets.on( 'instanceCreated', function( evt ) {
93 log( 'instance created (id: ' + evt.data.id + ')' );
94 }, null, null, 1 );
95
96 editor.widgets.on( 'widgetFocused', function( evt ) {
97 log( 'widget focused (id: ' + evt.data.widget.id + ')' );
98 }, null, null, 1 );
99
100 editor.widgets.on( 'widgetBlurred', function( evt ) {
101 log( 'widget blurred (id: ' + evt.data.widget.id + ')' );
102 }, null, null, 1 );
103
104 editor.widgets.on( 'checkWidgets', logFn( 'checking widgets' ), null, null, 1 );
105 editor.widgets.on( 'checkSelection', logFn( 'checking selection' ), null, null, 1 );
106 }
107 }
108 ]
109 } );
110
111 function generateInstancesList( instances ) {
112 var html = '',
113 instance;
114
115 for ( var i = 0; i < instances.length; ++i ) {
116 instance = instances[ i ];
117 html += itemTpl.output( { id: instance.id, name: instance.name, data: JSON.stringify( instance.data ) } );
118 }
119 return html;
120 }
121
122 function obj2Array( obj ) {
123 var arr = [];
124 for ( var id in obj )
125 arr.push( obj[ id ] );
126
127 return arr;
128 }
129
130 var itemTpl = new CKEDITOR.template( '<li>id: <code>{id}</code>, name: <code>{name}</code>, data: <code>{data}</code></li>' );
131} )();
diff --git a/sources/plugins/widget/dev/nestedwidgets.html b/sources/plugins/widget/dev/nestedwidgets.html
new file mode 100644
index 0000000..0686d2c
--- /dev/null
+++ b/sources/plugins/widget/dev/nestedwidgets.html
@@ -0,0 +1,134 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Nested widgets &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <script src="../../../dev/console/console.js"></script>
12 <script src="../../../dev/console/focusconsole.js"></script>
13 <script src="console.js"></script>
14 <link rel="stylesheet" href="../../../samples/old/sample.css">
15 <link rel="stylesheet" href="../../../contents.css">
16 <link rel="stylesheet" href="assets/simplebox/contents.css">
17</head>
18<body>
19 <h1 class="samples">Nested widgets</h1>
20
21 <h2>Classic (iframe-based) Sample</h2>
22 <textarea cols="80" id="editor1" name="editor1" rows="10">
23 <h1>Simple Box Sample</h1>
24
25 <div class="simplebox align-right" style="width: 60%">
26 <h2 class="simplebox-title">Title</h2>
27 <div class="simplebox-content">
28 <p><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on [[July 20, 1969, at 20:18 UTC]]. Armstrong became the first to step onto the lunar surface 6 hours later on [[July 21 at 02:56 UTC]].</p>
29
30 <figure class="image" style="float: right">
31 <img alt="The Eagle" src="assets/sample.jpg" width="150" />
32 <figcaption>The Eagle in lunar orbit</figcaption>
33 </figure>
34
35 <ul>
36 <li>Foo!</li>
37 <li>Bar!</li>
38 </ul>
39
40 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci ut nisi adipiscing ultrices. Sed pellentesque iaculis malesuada. Pellentesque scelerisque, purus non porta dictum, neque urna bibendum dolor, eget tristique ipsum metus fringilla dolor. Nullam sed accumsan sapien. Vestibulum in placerat magna. Sed justo lacus, volutpat rhoncus odio luctus, ornare adipiscing mauris. Vivamus erat sem, egestas et lectus eget, varius cursus odio. Duis posuere lacus sit amet urna bibendum, id iaculis eros ultrices. Vestibulum a ultrices ante.</p>
41 </div>
42 </div>
43
44 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci ut nisi adipiscing ultrices. Sed pellentesque iaculis malesuada. Pellentesque scelerisque, purus non porta dictum, neque urna bibendum dolor, eget tristique ipsum metus fringilla dolor. Nullam sed accumsan sapien. Vestibulum in placerat magna. Sed justo lacus, volutpat rhoncus odio luctus, ornare adipiscing mauris. Vivamus erat sem, egestas et lectus eget, varius cursus odio. Duis posuere lacus sit amet urna bibendum, id iaculis eros ultrices. Vestibulum a ultrices ante.</p>
45
46 <p>Pellentesque vitae eleifend nisl, non accumsan tellus. Maecenas nec libero non tellus tincidunt mollis porttitor sed arcu. Donec ultricies nulla vitae eros lacinia, vel congue sem auctor. Vivamus convallis, urna ac tincidunt malesuada, lectus erat convallis metus, a hendrerit massa augue accumsan magna. Nulla mattis tellus elit, nec congue magna scelerisque eget. Aliquam posuere nisi augue, posuere sodales nisi iaculis eu. Donec fermentum urna id nibh sagittis fermentum sit amet sed enim. Aliquam neque elit, pretium elementum nunc a, faucibus accumsan lorem. Etiam pulvinar odio et hendrerit tincidunt. Suspendisse tempus eros lacus, in convallis velit mollis ut. Aenean congue, justo eleifend ultricies malesuada, nunc nunc molestie mauris, eget placerat libero eros vel nisi. Quisque diam arcu, mollis ac laoreet vitae, varius et sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis in vehicula sapien. Nunc feugiat porta elit nec volutpat.</p>
47
48 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci ut nisi adipiscing ultrices. Sed pellentesque iaculis malesuada. Pellentesque scelerisque, purus non porta dictum, neque urna bibendum dolor, eget tristique ipsum metus fringilla dolor. Nullam sed accumsan sapien. Vestibulum in placerat magna. Sed justo lacus, volutpat rhoncus odio luctus, ornare adipiscing mauris. Vivamus erat sem, egestas et lectus eget, varius cursus odio. Duis posuere lacus sit amet urna bibendum, id iaculis eros ultrices. Vestibulum a ultrices ante.</p>
49
50 <div class="simplebox align-center" style="width: 750px">
51 <h2 class="simplebox-title">Title</h2>
52 <div class="simplebox-content">
53 <p><img alt="The Eagle" src="assets/sample.jpg" width="150" style="float: left" /><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on [[July 20, 1969, at 20:18 UTC]]. Armstrong became the first to step onto the lunar surface 6 hours later on [[July 21 at 02:56 UTC]].</p>
54
55 <ul>
56 <li>Foo!</li>
57 <li>Bar!</li>
58 </ul>
59 </div>
60 </div>
61
62 <p>Ut eget ipsum a sapien porta ultrices. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus mi lacus, pharetra eu bibendum blandit, tristique sit amet leo. Integer eu nulla nec magna vulputate blandit. Praesent mattis quis ante eget adipiscing. Nulla vel tempus risus, in placerat velit. Mauris sed nibh at elit posuere laoreet. Morbi non sapien sed nunc fringilla imperdiet.</p>
63 </textarea>
64
65 <h2>Inline Sample</h2>
66 <div id="editor2" contenteditable="true">
67 <h1>Simple Box Sample</h1>
68
69 <div class="simplebox align-right" style="width: 60%">
70 <h2 class="simplebox-title">Title</h2>
71 <div class="simplebox-content">
72 <p><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on [[July 20, 1969, at 20:18 UTC]]. Armstrong became the first to step onto the lunar surface 6 hours later on [[July 21 at 02:56 UTC]].</p>
73
74 <figure class="image" style="float: right">
75 <img alt="The Eagle" src="assets/sample.jpg" width="150" />
76 <figcaption>The Eagle in lunar orbit</figcaption>
77 </figure>
78
79 <ul>
80 <li>Foo!</li>
81 <li>Bar!</li>
82 </ul>
83
84 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci ut nisi adipiscing ultrices. Sed pellentesque iaculis malesuada. Pellentesque scelerisque, purus non porta dictum, neque urna bibendum dolor, eget tristique ipsum metus fringilla dolor. Nullam sed accumsan sapien. Vestibulum in placerat magna. Sed justo lacus, volutpat rhoncus odio luctus, ornare adipiscing mauris. Vivamus erat sem, egestas et lectus eget, varius cursus odio. Duis posuere lacus sit amet urna bibendum, id iaculis eros ultrices. Vestibulum a ultrices ante.</p>
85 </div>
86 </div>
87
88 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci ut nisi adipiscing ultrices. Sed pellentesque iaculis malesuada. Pellentesque scelerisque, purus non porta dictum, neque urna bibendum dolor, eget tristique ipsum metus fringilla dolor. Nullam sed accumsan sapien. Vestibulum in placerat magna. Sed justo lacus, volutpat rhoncus odio luctus, ornare adipiscing mauris. Vivamus erat sem, egestas et lectus eget, varius cursus odio. Duis posuere lacus sit amet urna bibendum, id iaculis eros ultrices. Vestibulum a ultrices ante.</p>
89
90 <p>Pellentesque vitae eleifend nisl, non accumsan tellus. Maecenas nec libero non tellus tincidunt mollis porttitor sed arcu. Donec ultricies nulla vitae eros lacinia, vel congue sem auctor. Vivamus convallis, urna ac tincidunt malesuada, lectus erat convallis metus, a hendrerit massa augue accumsan magna. Nulla mattis tellus elit, nec congue magna scelerisque eget. Aliquam posuere nisi augue, posuere sodales nisi iaculis eu. Donec fermentum urna id nibh sagittis fermentum sit amet sed enim. Aliquam neque elit, pretium elementum nunc a, faucibus accumsan lorem. Etiam pulvinar odio et hendrerit tincidunt. Suspendisse tempus eros lacus, in convallis velit mollis ut. Aenean congue, justo eleifend ultricies malesuada, nunc nunc molestie mauris, eget placerat libero eros vel nisi. Quisque diam arcu, mollis ac laoreet vitae, varius et sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis in vehicula sapien. Nunc feugiat porta elit nec volutpat.</p>
91
92 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci ut nisi adipiscing ultrices. Sed pellentesque iaculis malesuada. Pellentesque scelerisque, purus non porta dictum, neque urna bibendum dolor, eget tristique ipsum metus fringilla dolor. Nullam sed accumsan sapien. Vestibulum in placerat magna. Sed justo lacus, volutpat rhoncus odio luctus, ornare adipiscing mauris. Vivamus erat sem, egestas et lectus eget, varius cursus odio. Duis posuere lacus sit amet urna bibendum, id iaculis eros ultrices. Vestibulum a ultrices ante.</p>
93
94 <div class="simplebox align-center" style="width: 750px">
95 <h2 class="simplebox-title">Title</h2>
96 <div class="simplebox-content">
97 <p><img alt="The Eagle" src="assets/sample.jpg" width="150" style="float: left" /><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on [[July 20, 1969, at 20:18 UTC]]. Armstrong became the first to step onto the lunar surface 6 hours later on [[July 21 at 02:56 UTC]].</p>
98
99 <ul>
100 <li>Foo!</li>
101 <li>Bar!</li>
102 </ul>
103 </div>
104 </div>
105
106 <p>Ut eget ipsum a sapien porta ultrices. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus mi lacus, pharetra eu bibendum blandit, tristique sit amet leo. Integer eu nulla nec magna vulputate blandit. Praesent mattis quis ante eget adipiscing. Nulla vel tempus risus, in placerat velit. Mauris sed nibh at elit posuere laoreet. Morbi non sapien sed nunc fringilla imperdiet.</p>
107 </div>
108
109 <script>
110 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
111 CKEDITOR.tools.enableHtml5Elements( document );
112
113 CKEDITOR.plugins.addExternal( 'simplebox', 'plugins/widget/dev/assets/simplebox/' );
114
115 CKEDITOR.replace( 'editor1', {
116 extraPlugins: 'simplebox,placeholder,image2',
117 removePlugins: 'forms,bidi',
118 contentsCss: [ '../../../contents.css', 'assets/simplebox/contents.css' ],
119 height: 500
120 } );
121
122 CKEDITOR.inline( 'editor2', {
123 extraPlugins: 'simplebox,placeholder,image2',
124 removePlugins: 'forms,bidi'
125 } );
126
127 CKCONSOLE.create( 'widget', { editor: 'editor1' } );
128 CKCONSOLE.create( 'focus', { editor: 'editor1' } );
129 CKCONSOLE.create( 'widget', { editor: 'editor2', folded: true } );
130 CKCONSOLE.create( 'focus', { editor: 'editor2', folded: true } );
131
132 </script>
133</body>
134</html>
diff --git a/sources/plugins/widget/dev/widgetstyles.html b/sources/plugins/widget/dev/widgetstyles.html
new file mode 100644
index 0000000..8e54b8d
--- /dev/null
+++ b/sources/plugins/widget/dev/widgetstyles.html
@@ -0,0 +1,144 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Applying styles to widgets &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link rel="stylesheet" href="../../../samples/old/sample.css">
12 <link rel="stylesheet" href="../../../contents.css">
13 <link rel="stylesheet" href="assets/contents.css">
14</head>
15<body>
16 <h1 class="samples">Applying styles to widgets</h1>
17
18 <h2>Classic (iframe-based) Sample</h2>
19 <textarea cols="80" id="editor1" name="editor1" rows="10">
20 <h1>Apollo 11</h1>
21
22 <figure class="image" style="float: right">
23 <img alt="Saturn V" src="../../../samples/assets/sample.jpg" width="150" />
24 <figcaption>Roll out of Saturn V on launch pad</figcaption>
25 </figure>
26
27 <p><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on [[July 20, 1969, at 20:18 UTC]]. Armstrong became the first to step onto the lunar surface 6 hours later on [[July 21 at 02:56 UTC]].</p>
28
29 <p>Armstrong spent about <s>three and a half</s> two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5&nbsp;kg) of lunar material for return to Earth. A third member of the mission, <a href="http://en.wikipedia.org/wiki/Michael_Collins_(astronaut)" title="Michael Collins (astronaut)">Michael Collins</a>, piloted the <a href="http://en.wikipedia.org/wiki/Apollo_Command/Service_Module" title="Apollo Command/Service Module">command</a> spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.</p>
30
31 <h2>Broadcasting and <em>quotes</em> <a id="quotes" name="quotes"></a></h2>
32
33 <p>Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:</p>
34
35 <blockquote>
36 <p>One small step for [a] man, one giant leap for mankind.</p>
37 </blockquote>
38
39 <p><span class="math-tex">\( \left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) \)</span></p>
40
41 <p>Apollo 11 effectively ended the <a href="http://en.wikipedia.org/wiki/Space_Race" title="Space Race">Space Race</a> and fulfilled a national goal proposed in 1961 by the late U.S. President <a href="http://en.wikipedia.org/wiki/John_F._Kennedy" title="John F. Kennedy">John F. Kennedy</a> in a speech before the United States Congress:</p>
42
43 <blockquote>
44 <p>[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.</p>
45 </blockquote>
46
47 <figure class="image" style="float: right">
48 <img alt="The Eagle" src="../../../samples/assets/sample.jpg" width="150" />
49 <figcaption>The Eagle in lunar orbit</figcaption>
50 </figure>
51
52 <h2>Technical details <a id="tech-details" name="tech-details"></a></h2>
53
54 <p>Launched by a <strong>Saturn V</strong> rocket from <a href="http://en.wikipedia.org/wiki/Kennedy_Space_Center" title="Kennedy Space Center">Kennedy Space Center</a> in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of <a href="http://en.wikipedia.org/wiki/NASA" title="NASA">NASA</a>&#39;s Apollo program. The Apollo spacecraft had three parts:</p>
55
56 <ol>
57 <li><strong>Command Module</strong> with a cabin for the three astronauts which was the only part which landed back on Earth</li>
58 <li><strong>Service Module</strong> which supported the Command Module with propulsion, electrical power, oxygen and water</li>
59 <li><strong>Lunar Module</strong> for landing on the Moon.</li>
60 </ol>
61
62 <p>After being sent to the Moon by the Saturn V&#39;s upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the <a href="http://en.wikipedia.org/wiki/Mare_Tranquillitatis" title="Mare Tranquillitatis">Sea of Tranquility</a>. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the <a href="http://en.wikipedia.org/wiki/Pacific_Ocean" title="Pacific Ocean">Pacific Ocean</a> on July 24.</p>
63 </textarea>
64
65 <h2>Inline Sample</h2>
66 <div id="editor2" contenteditable="true">
67 <h1>Apollo 11</h1>
68
69 <figure class="image" style="float: right">
70 <img alt="Saturn V" src="../../../samples/assets/sample.jpg" width="150" />
71 <figcaption>Roll out of Saturn V on launch pad</figcaption>
72 </figure>
73
74 <p><strong>Apollo 11</strong> was the spaceflight that landed the first humans, Americans <a href="http://en.wikipedia.org/wiki/Neil_Armstrong" title="Neil Armstrong">Neil Armstrong</a> and <a href="http://en.wikipedia.org/wiki/Buzz_Aldrin" title="Buzz Aldrin">Buzz Aldrin</a>, on the Moon on [[July 20, 1969, at 20:18 UTC]]. Armstrong became the first to step onto the lunar surface 6 hours later on [[July 21 at 02:56 UTC]].</p>
75
76 <p>Armstrong spent about <s>three and a half</s> two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5&nbsp;kg) of lunar material for return to Earth. A third member of the mission, <a href="http://en.wikipedia.org/wiki/Michael_Collins_(astronaut)" title="Michael Collins (astronaut)">Michael Collins</a>, piloted the <a href="http://en.wikipedia.org/wiki/Apollo_Command/Service_Module" title="Apollo Command/Service Module">command</a> spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.</p>
77
78 <h2>Broadcasting and <em>quotes</em> <a id="quotes" name="quotes"></a></h2>
79
80 <p>Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:</p>
81
82 <blockquote>
83 <p>One small step for [a] man, one giant leap for mankind.</p>
84 </blockquote>
85
86 <p><span class="math-tex">\( \left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) \)</span></p>
87
88 <p>Apollo 11 effectively ended the <a href="http://en.wikipedia.org/wiki/Space_Race" title="Space Race">Space Race</a> and fulfilled a national goal proposed in 1961 by the late U.S. President <a href="http://en.wikipedia.org/wiki/John_F._Kennedy" title="John F. Kennedy">John F. Kennedy</a> in a speech before the United States Congress:</p>
89
90 <blockquote>
91 <p>[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.</p>
92 </blockquote>
93
94 <figure class="image" style="float: right">
95 <img alt="The Eagle" src="../../../samples/assets/sample.jpg" width="150" />
96 <figcaption>The Eagle in lunar orbit</figcaption>
97 </figure>
98
99 <h2>Technical details <a id="tech-details" name="tech-details"></a></h2>
100
101 <p>Launched by a <strong>Saturn V</strong> rocket from <a href="http://en.wikipedia.org/wiki/Kennedy_Space_Center" title="Kennedy Space Center">Kennedy Space Center</a> in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of <a href="http://en.wikipedia.org/wiki/NASA" title="NASA">NASA</a>&#39;s Apollo program. The Apollo spacecraft had three parts:</p>
102
103 <ol>
104 <li><strong>Command Module</strong> with a cabin for the three astronauts which was the only part which landed back on Earth</li>
105 <li><strong>Service Module</strong> which supported the Command Module with propulsion, electrical power, oxygen and water</li>
106 <li><strong>Lunar Module</strong> for landing on the Moon.</li>
107 </ol>
108
109 <p>After being sent to the Moon by the Saturn V&#39;s upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the <a href="http://en.wikipedia.org/wiki/Mare_Tranquillitatis" title="Mare Tranquillitatis">Sea of Tranquility</a>. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the <a href="http://en.wikipedia.org/wiki/Pacific_Ocean" title="Pacific Ocean">Pacific Ocean</a> on July 24.</p>
110 </div>
111
112 <script>
113 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
114 CKEDITOR.tools.enableHtml5Elements( document );
115
116 CKEDITOR.disableAutoInline = true;
117
118 var stylesSet = [
119 { name: 'Medium border', type: 'widget', widget: 'image', attributes: { 'class': 'mediumBorder' } },
120 { name: 'Thick border', type: 'widget', widget: 'image', attributes: { 'class': 'thickBorder' } },
121 { name: 'So important', type: 'widget', widget: 'image', attributes: { 'class': 'important soMuch' } },
122
123 { name: 'Red marker', type: 'widget', widget: 'placeholder', attributes: { 'class': 'redMarker' } },
124 { name: 'Invisible Placeholder', type: 'widget', widget: 'placeholder', attributes: { 'class': 'invisible' } },
125
126 { name: 'Invisible Mathjax', type: 'widget', widget: 'mathjax', attributes: { 'class': 'invisible' } }
127 ];
128
129 CKEDITOR.replace( 'editor1', {
130 extraPlugins: 'placeholder,image2,mathjax',
131 contentsCss: [ '../../../contents.css', 'assets/contents.css' ],
132 stylesSet: stylesSet,
133 height: 300
134 } );
135
136 CKEDITOR.inline( 'editor2', {
137 extraPlugins: 'placeholder,image2,mathjax',
138 stylesSet: stylesSet,
139 height: 300
140 } );
141
142 </script>
143</body>
144</html>
diff --git a/sources/plugins/widget/images/handle.png b/sources/plugins/widget/images/handle.png
new file mode 100644
index 0000000..ba8cda5
--- /dev/null
+++ b/sources/plugins/widget/images/handle.png
Binary files differ
diff --git a/sources/plugins/widget/lang/af.js b/sources/plugins/widget/lang/af.js
new file mode 100644
index 0000000..e37c598
--- /dev/null
+++ b/sources/plugins/widget/lang/af.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'af', {
6 'move': 'Klik en trek on te beweeg',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/ar.js b/sources/plugins/widget/lang/ar.js
new file mode 100644
index 0000000..0a4f8eb
--- /dev/null
+++ b/sources/plugins/widget/lang/ar.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ar', {
6 'move': 'إضغط و إسحب للتحريك',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/az.js b/sources/plugins/widget/lang/az.js
new file mode 100644
index 0000000..24ddaf3
--- /dev/null
+++ b/sources/plugins/widget/lang/az.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'az', {
6 'move': 'Tıklayın və aparın',
7 'label': '%1 vidjet'
8} );
diff --git a/sources/plugins/widget/lang/bg.js b/sources/plugins/widget/lang/bg.js
new file mode 100644
index 0000000..9b51458
--- /dev/null
+++ b/sources/plugins/widget/lang/bg.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'bg', {
6 'move': 'Кликни и влачи, за да преместиш',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/ca.js b/sources/plugins/widget/lang/ca.js
new file mode 100644
index 0000000..f46a4f8
--- /dev/null
+++ b/sources/plugins/widget/lang/ca.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ca', {
6 'move': 'Clicar i arrossegar per moure',
7 'label': '%1 widget'
8} );
diff --git a/sources/plugins/widget/lang/cs.js b/sources/plugins/widget/lang/cs.js
new file mode 100644
index 0000000..5d9590b
--- /dev/null
+++ b/sources/plugins/widget/lang/cs.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'cs', {
6 'move': 'Klepněte a táhněte pro přesunutí',
7 'label': 'Ovládací prvek %1'
8} );
diff --git a/sources/plugins/widget/lang/cy.js b/sources/plugins/widget/lang/cy.js
new file mode 100644
index 0000000..29dc110
--- /dev/null
+++ b/sources/plugins/widget/lang/cy.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'cy', {
6 'move': 'Clcio a llusgo i symud',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/da.js b/sources/plugins/widget/lang/da.js
new file mode 100644
index 0000000..8dfe785
--- /dev/null
+++ b/sources/plugins/widget/lang/da.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'da', {
6 'move': 'Klik og træk for at flytte',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/de-ch.js b/sources/plugins/widget/lang/de-ch.js
new file mode 100644
index 0000000..a95febb
--- /dev/null
+++ b/sources/plugins/widget/lang/de-ch.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'de-ch', {
6 'move': 'Zum Verschieben anwählen und ziehen',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/de.js b/sources/plugins/widget/lang/de.js
new file mode 100644
index 0000000..838ad89
--- /dev/null
+++ b/sources/plugins/widget/lang/de.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'de', {
6 'move': 'Zum Verschieben anwählen und ziehen',
7 'label': '%1 Steuerelement'
8} );
diff --git a/sources/plugins/widget/lang/el.js b/sources/plugins/widget/lang/el.js
new file mode 100644
index 0000000..863604a
--- /dev/null
+++ b/sources/plugins/widget/lang/el.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'el', {
6 'move': 'Κάνετε κλικ και σύρετε το ποντίκι για να μετακινήστε',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/en-gb.js b/sources/plugins/widget/lang/en-gb.js
new file mode 100644
index 0000000..ed09606
--- /dev/null
+++ b/sources/plugins/widget/lang/en-gb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'en-gb', {
6 'move': 'Click and drag to move',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/en.js b/sources/plugins/widget/lang/en.js
new file mode 100644
index 0000000..5967f4d
--- /dev/null
+++ b/sources/plugins/widget/lang/en.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'en', {
6 'move': 'Click and drag to move',
7 'label': '%1 widget'
8} );
diff --git a/sources/plugins/widget/lang/eo.js b/sources/plugins/widget/lang/eo.js
new file mode 100644
index 0000000..f4979ac
--- /dev/null
+++ b/sources/plugins/widget/lang/eo.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'eo', {
6 'move': 'klaki kaj treni por movi',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/es.js b/sources/plugins/widget/lang/es.js
new file mode 100644
index 0000000..d8deb2c
--- /dev/null
+++ b/sources/plugins/widget/lang/es.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'es', {
6 'move': 'Dar clic y arrastrar para mover',
7 'label': 'reproductor %1'
8} );
diff --git a/sources/plugins/widget/lang/eu.js b/sources/plugins/widget/lang/eu.js
new file mode 100644
index 0000000..e128dfe
--- /dev/null
+++ b/sources/plugins/widget/lang/eu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'eu', {
6 'move': 'Klikatu eta arrastatu lekuz aldatzeko',
7 'label': '%1 widget'
8} );
diff --git a/sources/plugins/widget/lang/fa.js b/sources/plugins/widget/lang/fa.js
new file mode 100644
index 0000000..57ea31f
--- /dev/null
+++ b/sources/plugins/widget/lang/fa.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'fa', {
6 'move': 'کلیک و کشیدن برای جابجایی',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/fi.js b/sources/plugins/widget/lang/fi.js
new file mode 100644
index 0000000..759b2cf
--- /dev/null
+++ b/sources/plugins/widget/lang/fi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'fi', {
6 'move': 'Siirrä klikkaamalla ja raahaamalla',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/fr.js b/sources/plugins/widget/lang/fr.js
new file mode 100644
index 0000000..9decbf6
--- /dev/null
+++ b/sources/plugins/widget/lang/fr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'fr', {
6 'move': 'Cliquer et glisser pour déplacer',
7 'label': 'Élément %1'
8} );
diff --git a/sources/plugins/widget/lang/gl.js b/sources/plugins/widget/lang/gl.js
new file mode 100644
index 0000000..ef070b6
--- /dev/null
+++ b/sources/plugins/widget/lang/gl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'gl', {
6 'move': 'Prema e arrastre para mover',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/he.js b/sources/plugins/widget/lang/he.js
new file mode 100644
index 0000000..b8dd2cb
--- /dev/null
+++ b/sources/plugins/widget/lang/he.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'he', {
6 'move': 'לחץ וגרור להזזה',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/hr.js b/sources/plugins/widget/lang/hr.js
new file mode 100644
index 0000000..952d800
--- /dev/null
+++ b/sources/plugins/widget/lang/hr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'hr', {
6 'move': 'Klikni i povuci da pomakneš',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/hu.js b/sources/plugins/widget/lang/hu.js
new file mode 100644
index 0000000..4721305
--- /dev/null
+++ b/sources/plugins/widget/lang/hu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'hu', {
6 'move': 'Kattints és húzd a mozgatáshoz',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/id.js b/sources/plugins/widget/lang/id.js
new file mode 100644
index 0000000..ef19392
--- /dev/null
+++ b/sources/plugins/widget/lang/id.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'id', {
6 'move': 'Tekan dan geser untuk memindahkan',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/it.js b/sources/plugins/widget/lang/it.js
new file mode 100644
index 0000000..59b43f6
--- /dev/null
+++ b/sources/plugins/widget/lang/it.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'it', {
6 'move': 'Fare clic e trascinare per spostare',
7 'label': 'Widget %1'
8} );
diff --git a/sources/plugins/widget/lang/ja.js b/sources/plugins/widget/lang/ja.js
new file mode 100644
index 0000000..a742718
--- /dev/null
+++ b/sources/plugins/widget/lang/ja.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ja', {
6 'move': 'ドラッグして移動',
7 'label': '%1 ウィジェット'
8} );
diff --git a/sources/plugins/widget/lang/km.js b/sources/plugins/widget/lang/km.js
new file mode 100644
index 0000000..6c61c73
--- /dev/null
+++ b/sources/plugins/widget/lang/km.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'km', {
6 'move': 'ចុច​ហើយ​ទាញ​ដើម្បី​ផ្លាស់​ទី',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/ko.js b/sources/plugins/widget/lang/ko.js
new file mode 100644
index 0000000..0107a13
--- /dev/null
+++ b/sources/plugins/widget/lang/ko.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ko', {
6 'move': '움직이려면 클릭 후 드래그 하세요',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/ku.js b/sources/plugins/widget/lang/ku.js
new file mode 100644
index 0000000..2af50cb
--- /dev/null
+++ b/sources/plugins/widget/lang/ku.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ku', {
6 'move': 'کرتەبکە و ڕایبکێشە بۆ جوڵاندن',
7 'label': '%1 ویجێت'
8} );
diff --git a/sources/plugins/widget/lang/lv.js b/sources/plugins/widget/lang/lv.js
new file mode 100644
index 0000000..e5fc3ac
--- /dev/null
+++ b/sources/plugins/widget/lang/lv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'lv', {
6 'move': 'Klikšķina un velc, lai pārvietotu',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/nb.js b/sources/plugins/widget/lang/nb.js
new file mode 100644
index 0000000..af46bc9
--- /dev/null
+++ b/sources/plugins/widget/lang/nb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'nb', {
6 'move': 'Klikk og dra for å flytte',
7 'label': 'Widget %1'
8} );
diff --git a/sources/plugins/widget/lang/nl.js b/sources/plugins/widget/lang/nl.js
new file mode 100644
index 0000000..56b182c
--- /dev/null
+++ b/sources/plugins/widget/lang/nl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'nl', {
6 'move': 'Klik en sleep om te verplaatsen',
7 'label': '%1 widget'
8} );
diff --git a/sources/plugins/widget/lang/no.js b/sources/plugins/widget/lang/no.js
new file mode 100644
index 0000000..b86bd7b
--- /dev/null
+++ b/sources/plugins/widget/lang/no.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'no', {
6 'move': 'Klikk og dra for å flytte',
7 'label': 'Widget %1'
8} );
diff --git a/sources/plugins/widget/lang/oc.js b/sources/plugins/widget/lang/oc.js
new file mode 100644
index 0000000..10ff842
--- /dev/null
+++ b/sources/plugins/widget/lang/oc.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'oc', {
6 'move': 'Clicar e lisar per desplaçar',
7 'label': 'Element %1'
8} );
diff --git a/sources/plugins/widget/lang/pl.js b/sources/plugins/widget/lang/pl.js
new file mode 100644
index 0000000..2d90df8
--- /dev/null
+++ b/sources/plugins/widget/lang/pl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'pl', {
6 'move': 'Kliknij i przeciągnij, by przenieść.',
7 'label': 'Widget %1'
8} );
diff --git a/sources/plugins/widget/lang/pt-br.js b/sources/plugins/widget/lang/pt-br.js
new file mode 100644
index 0000000..9ce9be4
--- /dev/null
+++ b/sources/plugins/widget/lang/pt-br.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'pt-br', {
6 'move': 'Click e arraste para mover',
7 'label': '%1 widget'
8} );
diff --git a/sources/plugins/widget/lang/pt.js b/sources/plugins/widget/lang/pt.js
new file mode 100644
index 0000000..422ef93
--- /dev/null
+++ b/sources/plugins/widget/lang/pt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'pt', {
6 'move': 'Clique e arraste para mover',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/ru.js b/sources/plugins/widget/lang/ru.js
new file mode 100644
index 0000000..d6f36f5
--- /dev/null
+++ b/sources/plugins/widget/lang/ru.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ru', {
6 'move': 'Нажмите и перетащите, чтобы переместить',
7 'label': '%1 виджет'
8} );
diff --git a/sources/plugins/widget/lang/sk.js b/sources/plugins/widget/lang/sk.js
new file mode 100644
index 0000000..05acac4
--- /dev/null
+++ b/sources/plugins/widget/lang/sk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'sk', {
6 'move': 'Kliknite a potiahnite pre presunutie',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/sl.js b/sources/plugins/widget/lang/sl.js
new file mode 100644
index 0000000..96ffd1e
--- /dev/null
+++ b/sources/plugins/widget/lang/sl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'sl', {
6 'move': 'Kliknite in povlecite, da premaknete',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/sq.js b/sources/plugins/widget/lang/sq.js
new file mode 100644
index 0000000..ad46c7d
--- /dev/null
+++ b/sources/plugins/widget/lang/sq.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'sq', {
6 'move': 'Kliko dhe tërhiqe për ta lëvizur',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/sv.js b/sources/plugins/widget/lang/sv.js
new file mode 100644
index 0000000..7faff37
--- /dev/null
+++ b/sources/plugins/widget/lang/sv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'sv', {
6 'move': 'Klicka och drag för att flytta',
7 'label': '%1-widget'
8} );
diff --git a/sources/plugins/widget/lang/tr.js b/sources/plugins/widget/lang/tr.js
new file mode 100644
index 0000000..92fa952
--- /dev/null
+++ b/sources/plugins/widget/lang/tr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'tr', {
6 'move': 'Taşımak için, tıklayın ve sürükleyin',
7 'label': '%1 Grafik Beleşeni'
8} );
diff --git a/sources/plugins/widget/lang/tt.js b/sources/plugins/widget/lang/tt.js
new file mode 100644
index 0000000..30fb31a
--- /dev/null
+++ b/sources/plugins/widget/lang/tt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'tt', {
6 'move': 'Күчереп куер өчен басып шудырыгыз',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/ug.js b/sources/plugins/widget/lang/ug.js
new file mode 100644
index 0000000..fc216c4
--- /dev/null
+++ b/sources/plugins/widget/lang/ug.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'ug', {
6 'move': 'يۆتكەشتە چېكىپ سۆرەڭ',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/uk.js b/sources/plugins/widget/lang/uk.js
new file mode 100644
index 0000000..fab6d5d
--- /dev/null
+++ b/sources/plugins/widget/lang/uk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'uk', {
6 'move': 'Клікніть і потягніть для переміщення',
7 'label': '%1 віджет'
8} );
diff --git a/sources/plugins/widget/lang/vi.js b/sources/plugins/widget/lang/vi.js
new file mode 100644
index 0000000..2bbe246
--- /dev/null
+++ b/sources/plugins/widget/lang/vi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'vi', {
6 'move': 'Nhấp chuột và kéo để di chuyển',
7 'label': '%1 widget' // MISSING
8} );
diff --git a/sources/plugins/widget/lang/zh-cn.js b/sources/plugins/widget/lang/zh-cn.js
new file mode 100644
index 0000000..2381407
--- /dev/null
+++ b/sources/plugins/widget/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'zh-cn', {
6 'move': '点击并拖拽以移动',
7 'label': '%1 小部件'
8} );
diff --git a/sources/plugins/widget/lang/zh.js b/sources/plugins/widget/lang/zh.js
new file mode 100644
index 0000000..b6e945b
--- /dev/null
+++ b/sources/plugins/widget/lang/zh.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5CKEDITOR.plugins.setLang( 'widget', 'zh', {
6 'move': '拖曳以移動',
7 'label': '%1 小工具'
8} );
diff --git a/sources/plugins/widget/plugin.js b/sources/plugins/widget/plugin.js
new file mode 100644
index 0000000..37374ab
--- /dev/null
+++ b/sources/plugins/widget/plugin.js
@@ -0,0 +1,4126 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview [Widget](http://ckeditor.com/addon/widget) plugin.
8 */
9
10'use strict';
11
12( function() {
13 var DRAG_HANDLER_SIZE = 15;
14
15 CKEDITOR.plugins.add( 'widget', {
16 // jscs:disable maximumLineLength
17 lang: 'af,ar,az,bg,ca,cs,cy,da,de,de-ch,el,en,en-gb,eo,es,eu,fa,fi,fr,gl,he,hr,hu,id,it,ja,km,ko,ku,lv,nb,nl,no,oc,pl,pt,pt-br,ru,sk,sl,sq,sv,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
18 // jscs:enable maximumLineLength
19 requires: 'lineutils,clipboard,widgetselection',
20 onLoad: function() {
21 CKEDITOR.addCss(
22 '.cke_widget_wrapper{' +
23 'position:relative;' +
24 'outline:none' +
25 '}' +
26 '.cke_widget_inline{' +
27 'display:inline-block' +
28 '}' +
29 '.cke_widget_wrapper:hover>.cke_widget_element{' +
30 'outline:2px solid yellow;' +
31 'cursor:default' +
32 '}' +
33 '.cke_widget_wrapper:hover .cke_widget_editable{' +
34 'outline:2px solid yellow' +
35 '}' +
36 '.cke_widget_wrapper.cke_widget_focused>.cke_widget_element,' +
37 // We need higher specificity than hover style.
38 '.cke_widget_wrapper .cke_widget_editable.cke_widget_editable_focused{' +
39 'outline:2px solid #ace' +
40 '}' +
41 '.cke_widget_editable{' +
42 'cursor:text' +
43 '}' +
44 '.cke_widget_drag_handler_container{' +
45 'position:absolute;' +
46 'width:' + DRAG_HANDLER_SIZE + 'px;' +
47 'height:0;' +
48 // Initially drag handler should not be visible, until its position will be
49 // calculated (#11177).
50 // We need to hide unpositined handlers, so they don't extend
51 // widget's outline far to the left (#12024).
52 'display:none;' +
53 'opacity:0.75;' +
54 'transition:height 0s 0.2s;' + // Delay hiding drag handler.
55 // Prevent drag handler from being misplaced (#11198).
56 'line-height:0' +
57 '}' +
58 '.cke_widget_wrapper:hover>.cke_widget_drag_handler_container{' +
59 'height:' + DRAG_HANDLER_SIZE + 'px;' +
60 'transition:none' +
61 '}' +
62 '.cke_widget_drag_handler_container:hover{' +
63 'opacity:1' +
64 '}' +
65 'img.cke_widget_drag_handler{' +
66 'cursor:move;' +
67 'width:' + DRAG_HANDLER_SIZE + 'px;' +
68 'height:' + DRAG_HANDLER_SIZE + 'px;' +
69 'display:inline-block' +
70 '}' +
71 '.cke_widget_mask{' +
72 'position:absolute;' +
73 'top:0;' +
74 'left:0;' +
75 'width:100%;' +
76 'height:100%;' +
77 'display:block' +
78 '}' +
79 '.cke_editable.cke_widget_dragging, .cke_editable.cke_widget_dragging *{' +
80 'cursor:move !important' +
81 '}'
82 );
83 },
84
85 beforeInit: function( editor ) {
86 /**
87 * An instance of widget repository. It contains all
88 * {@link CKEDITOR.plugins.widget.repository#registered registered widget definitions} and
89 * {@link CKEDITOR.plugins.widget.repository#instances initialized instances}.
90 *
91 * editor.widgets.add( 'someName', {
92 * // Widget definition...
93 * } );
94 *
95 * editor.widgets.registered.someName; // -> Widget definition
96 *
97 * @since 4.3
98 * @readonly
99 * @property {CKEDITOR.plugins.widget.repository} widgets
100 * @member CKEDITOR.editor
101 */
102 editor.widgets = new Repository( editor );
103 },
104
105 afterInit: function( editor ) {
106 addWidgetButtons( editor );
107 setupContextMenu( editor );
108 }
109 } );
110
111 /**
112 * Widget repository. It keeps track of all {@link #registered registered widget definitions} and
113 * {@link #instances initialized instances}. An instance of the repository is available under
114 * the {@link CKEDITOR.editor#widgets} property.
115 *
116 * @class CKEDITOR.plugins.widget.repository
117 * @mixins CKEDITOR.event
118 * @constructor Creates a widget repository instance. Note that the widget plugin automatically
119 * creates a repository instance which is available under the {@link CKEDITOR.editor#widgets} property.
120 * @param {CKEDITOR.editor} editor The editor instance for which the repository will be created.
121 */
122 function Repository( editor ) {
123 /**
124 * The editor instance for which this repository was created.
125 *
126 * @readonly
127 * @property {CKEDITOR.editor} editor
128 */
129 this.editor = editor;
130
131 /**
132 * A hash of registered widget definitions (definition name => {@link CKEDITOR.plugins.widget.definition}).
133 *
134 * To register a definition use the {@link #add} method.
135 *
136 * @readonly
137 */
138 this.registered = {};
139
140 /**
141 * An object containing initialized widget instances (widget id => {@link CKEDITOR.plugins.widget}).
142 *
143 * @readonly
144 */
145 this.instances = {};
146
147 /**
148 * An array of selected widget instances.
149 *
150 * @readonly
151 * @property {CKEDITOR.plugins.widget[]} selected
152 */
153 this.selected = [];
154
155 /**
156 * The focused widget instance. See also {@link CKEDITOR.plugins.widget#event-focus}
157 * and {@link CKEDITOR.plugins.widget#event-blur} events.
158 *
159 * editor.on( 'selectionChange', function() {
160 * if ( editor.widgets.focused ) {
161 * // Do something when a widget is focused...
162 * }
163 * } );
164 *
165 * @readonly
166 * @property {CKEDITOR.plugins.widget} focused
167 */
168 this.focused = null;
169
170 /**
171 * The widget instance that contains the nested editable which is currently focused.
172 *
173 * @readonly
174 * @property {CKEDITOR.plugins.widget} widgetHoldingFocusedEditable
175 */
176 this.widgetHoldingFocusedEditable = null;
177
178 this._ = {
179 nextId: 0,
180 upcasts: [],
181 upcastCallbacks: [],
182 filters: {}
183 };
184
185 setupWidgetsLifecycle( this );
186 setupSelectionObserver( this );
187 setupMouseObserver( this );
188 setupKeyboardObserver( this );
189 setupDragAndDrop( this );
190 setupNativeCutAndCopy( this );
191 }
192
193 Repository.prototype = {
194 /**
195 * Minimum interval between selection checks.
196 *
197 * @private
198 */
199 MIN_SELECTION_CHECK_INTERVAL: 500,
200
201 /**
202 * Adds a widget definition to the repository. Fires the {@link CKEDITOR.editor#widgetDefinition} event
203 * which allows to modify the widget definition which is going to be registered.
204 *
205 * @param {String} name The name of the widget definition.
206 * @param {CKEDITOR.plugins.widget.definition} widgetDef Widget definition.
207 * @returns {CKEDITOR.plugins.widget.definition}
208 */
209 add: function( name, widgetDef ) {
210 // Create prototyped copy of original widget definition, so we won't modify it.
211 widgetDef = CKEDITOR.tools.prototypedCopy( widgetDef );
212 widgetDef.name = name;
213
214 widgetDef._ = widgetDef._ || {};
215
216 this.editor.fire( 'widgetDefinition', widgetDef );
217
218 if ( widgetDef.template )
219 widgetDef.template = new CKEDITOR.template( widgetDef.template );
220
221 addWidgetCommand( this.editor, widgetDef );
222 addWidgetProcessors( this, widgetDef );
223
224 this.registered[ name ] = widgetDef;
225
226 return widgetDef;
227 },
228
229 /**
230 * Adds a callback for element upcasting. Each callback will be executed
231 * for every element which is later tested by upcast methods. If a callback
232 * returns `false`, the element will not be upcasted.
233 *
234 * // Images with the "banner" class will not be upcasted (e.g. to the image widget).
235 * editor.widgets.addUpcastCallback( function( element ) {
236 * if ( element.name == 'img' && element.hasClass( 'banner' ) )
237 * return false;
238 * } );
239 *
240 * @param {Function} callback
241 * @param {CKEDITOR.htmlParser.element} callback.element
242 */
243 addUpcastCallback: function( callback ) {
244 this._.upcastCallbacks.push( callback );
245 },
246
247 /**
248 * Checks the selection to update widget states (selection and focus).
249 *
250 * This method is triggered by the {@link #event-checkSelection} event.
251 */
252 checkSelection: function() {
253 var sel = this.editor.getSelection(),
254 selectedElement = sel.getSelectedElement(),
255 updater = stateUpdater( this ),
256 widget;
257
258 // Widget is focused so commit and finish checking.
259 if ( selectedElement && ( widget = this.getByElement( selectedElement, true ) ) )
260 return updater.focus( widget ).select( widget ).commit();
261
262 var range = sel.getRanges()[ 0 ];
263
264 // No ranges or collapsed range mean that nothing is selected, so commit and finish checking.
265 if ( !range || range.collapsed )
266 return updater.commit();
267
268 // Range is not empty, so create walker checking for wrappers.
269 var walker = new CKEDITOR.dom.walker( range ),
270 wrapper;
271
272 walker.evaluator = Widget.isDomWidgetWrapper;
273
274 while ( ( wrapper = walker.next() ) )
275 updater.select( this.getByElement( wrapper ) );
276
277 updater.commit();
278 },
279
280 /**
281 * Checks if all widget instances are still present in the DOM.
282 * Destroys those instances that are not present.
283 * Reinitializes widgets on widget wrappers for which widget instances
284 * cannot be found. Takes nested widgets into account, too.
285 *
286 * This method triggers the {@link #event-checkWidgets} event whose listeners
287 * can cancel the method's execution or modify its options.
288 *
289 * @param [options] The options object.
290 * @param {Boolean} [options.initOnlyNew] Initializes widgets only on newly wrapped
291 * widget elements (those which still have the `cke_widget_new` class). When this option is
292 * set to `true`, widgets which were invalidated (e.g. by replacing with a cloned DOM structure)
293 * will not be reinitialized. This makes the check faster.
294 * @param {Boolean} [options.focusInited] If only one widget is initialized by
295 * the method, it will be focused.
296 */
297 checkWidgets: function( options ) {
298 this.fire( 'checkWidgets', CKEDITOR.tools.copy( options || {} ) );
299 },
300
301 /**
302 * Removes the widget from the editor and moves the selection to the closest
303 * editable position if the widget was focused before.
304 *
305 * @param {CKEDITOR.plugins.widget} widget The widget instance to be deleted.
306 */
307 del: function( widget ) {
308 if ( this.focused === widget ) {
309 var editor = widget.editor,
310 range = editor.createRange(),
311 found;
312
313 // If haven't found place for caret on the default side,
314 // try to find it on the other side.
315 if ( !( found = range.moveToClosestEditablePosition( widget.wrapper, true ) ) )
316 found = range.moveToClosestEditablePosition( widget.wrapper, false );
317
318 if ( found )
319 editor.getSelection().selectRanges( [ range ] );
320 }
321
322 widget.wrapper.remove();
323 this.destroy( widget, true );
324 },
325
326 /**
327 * Destroys the widget instance and all its nested widgets (widgets inside its nested editables).
328 *
329 * @param {CKEDITOR.plugins.widget} widget The widget instance to be destroyed.
330 * @param {Boolean} [offline] Whether the widget is offline (detached from the DOM tree) &mdash;
331 * in this case the DOM (attributes, classes, etc.) will not be cleaned up.
332 */
333 destroy: function( widget, offline ) {
334 if ( this.widgetHoldingFocusedEditable === widget )
335 setFocusedEditable( this, widget, null, offline );
336
337 widget.destroy( offline );
338 delete this.instances[ widget.id ];
339 this.fire( 'instanceDestroyed', widget );
340 },
341
342 /**
343 * Destroys all widget instances.
344 *
345 * @param {Boolean} [offline] Whether the widgets are offline (detached from the DOM tree) &mdash;
346 * in this case the DOM (attributes, classes, etc.) will not be cleaned up.
347 * @param {CKEDITOR.dom.element} [container] The container within widgets will be destroyed.
348 * This option will be ignored if the `offline` flag was set to `true`, because in such case
349 * it is not possible to find widgets within the passed block.
350 */
351 destroyAll: function( offline, container ) {
352 var widget,
353 id,
354 instances = this.instances;
355
356 if ( container && !offline ) {
357 var wrappers = container.find( '.cke_widget_wrapper' ),
358 l = wrappers.count(),
359 i = 0;
360
361 // Length is constant, because this is not a live node list.
362 // Note: since querySelectorAll returns nodes in document order,
363 // outer widgets are always placed before their nested widgets and therefore
364 // are destroyed before them.
365 for ( ; i < l; ++i ) {
366 widget = this.getByElement( wrappers.getItem( i ), true );
367 // Widget might not be found, because it could be a nested widget,
368 // which would be destroyed when destroying its parent.
369 if ( widget )
370 this.destroy( widget );
371 }
372
373 return;
374 }
375
376 for ( id in instances ) {
377 widget = instances[ id ];
378 this.destroy( widget, offline );
379 }
380 },
381
382 /**
383 * Finalizes a process of widget creation. This includes:
384 *
385 * * inserting widget element into editor,
386 * * marking widget instance as ready (see {@link CKEDITOR.plugins.widget#event-ready}),
387 * * focusing widget instance.
388 *
389 * This method is used by the default widget's command and is called
390 * after widget's dialog (if set) is closed. It may also be used in a
391 * customized process of widget creation and insertion.
392 *
393 * widget.once( 'edit', function() {
394 * // Finalize creation only of not ready widgets.
395 * if ( widget.isReady() )
396 * return;
397 *
398 * // Cancel edit event to prevent automatic widget insertion.
399 * evt.cancel();
400 *
401 * CustomDialog.open( widget.data, function saveCallback( savedData ) {
402 * // Cache the container, because widget may be destroyed while saving data,
403 * // if this process will require some deep transformations.
404 * var container = widget.wrapper.getParent();
405 *
406 * widget.setData( savedData );
407 *
408 * // Widget will be retrieved from container and inserted into editor.
409 * editor.widgets.finalizeCreation( container );
410 * } );
411 * } );
412 *
413 * @param {CKEDITOR.dom.element/CKEDITOR.dom.documentFragment} container The element
414 * or document fragment which contains widget wrapper. The container is used, so before
415 * finalizing creation the widget can be freely transformed (even destroyed and reinitialized).
416 */
417 finalizeCreation: function( container ) {
418 var wrapper = container.getFirst();
419 if ( wrapper && Widget.isDomWidgetWrapper( wrapper ) ) {
420 this.editor.insertElement( wrapper );
421
422 var widget = this.getByElement( wrapper );
423 // Fire postponed #ready event.
424 widget.ready = true;
425 widget.fire( 'ready' );
426 widget.focus();
427 }
428 },
429
430 /**
431 * Finds a widget instance which contains a given element. The element will be the {@link CKEDITOR.plugins.widget#wrapper wrapper}
432 * of the returned widget or a descendant of this {@link CKEDITOR.plugins.widget#wrapper wrapper}.
433 *
434 * editor.widgets.getByElement( someWidget.wrapper ); // -> someWidget
435 * editor.widgets.getByElement( someWidget.parts.caption ); // -> someWidget
436 *
437 * // Check wrapper only:
438 * editor.widgets.getByElement( someWidget.wrapper, true ); // -> someWidget
439 * editor.widgets.getByElement( someWidget.parts.caption, true ); // -> null
440 *
441 * @param {CKEDITOR.dom.element} element The element to be checked.
442 * @param {Boolean} [checkWrapperOnly] If set to `true`, the method will not check wrappers' descendants.
443 * @returns {CKEDITOR.plugins.widget} The widget instance or `null`.
444 */
445 getByElement: ( function() {
446 var validWrapperElements = { div: 1, span: 1 };
447 function getWidgetId( element ) {
448 return element.is( validWrapperElements ) && element.data( 'cke-widget-id' );
449 }
450
451 return function( element, checkWrapperOnly ) {
452 if ( !element )
453 return null;
454
455 var id = getWidgetId( element );
456
457 // There's no need to check element parents if element is a wrapper.
458 if ( !checkWrapperOnly && !id ) {
459 var limit = this.editor.editable();
460
461 // Try to find a closest ascendant which is a widget wrapper.
462 do {
463 element = element.getParent();
464 } while ( element && !element.equals( limit ) && !( id = getWidgetId( element ) ) );
465 }
466
467 return this.instances[ id ] || null;
468 };
469 } )(),
470
471 /**
472 * Initializes a widget on a given element if the widget has not been initialized on it yet.
473 *
474 * @param {CKEDITOR.dom.element} element The future widget element.
475 * @param {String/CKEDITOR.plugins.widget.definition} [widgetDef] Name of a widget or a widget definition.
476 * The widget definition should be previously registered by using the
477 * {@link CKEDITOR.plugins.widget.repository#add} method.
478 * @param [startupData] Widget startup data (has precedence over default one).
479 * @returns {CKEDITOR.plugins.widget} The widget instance or `null` if a widget could not be initialized on
480 * a given element.
481 */
482 initOn: function( element, widgetDef, startupData ) {
483 if ( !widgetDef )
484 widgetDef = this.registered[ element.data( 'widget' ) ];
485 else if ( typeof widgetDef == 'string' )
486 widgetDef = this.registered[ widgetDef ];
487
488 if ( !widgetDef )
489 return null;
490
491 // Wrap element if still wasn't wrapped (was added during runtime by method that skips dataProcessor).
492 var wrapper = this.wrapElement( element, widgetDef.name );
493
494 if ( wrapper ) {
495 // Check if widget wrapper is new (widget hasn't been initialized on it yet).
496 // This class will be removed by widget constructor to avoid locking snapshot twice.
497 if ( wrapper.hasClass( 'cke_widget_new' ) ) {
498 var widget = new Widget( this, this._.nextId++, element, widgetDef, startupData );
499
500 // Widget could be destroyed when initializing it.
501 if ( widget.isInited() ) {
502 this.instances[ widget.id ] = widget;
503
504 return widget;
505 } else {
506 return null;
507 }
508 }
509
510 // Widget already has been initialized, so try to get widget by element.
511 // Note - it may happen that other instance will returned than the one created above,
512 // if for example widget was destroyed and reinitialized.
513 return this.getByElement( element );
514 }
515
516 // No wrapper means that there's no widget for this element.
517 return null;
518 },
519
520 /**
521 * Initializes widgets on all elements which were wrapped by {@link #wrapElement} and
522 * have not been initialized yet.
523 *
524 * @param {CKEDITOR.dom.element} [container=editor.editable()] The container which will be checked for not
525 * initialized widgets. Defaults to editor's {@link CKEDITOR.editor#editable editable} element.
526 * @returns {CKEDITOR.plugins.widget[]} Array of widget instances which have been initialized.
527 * Note: Only first-level widgets are returned &mdash; without nested widgets.
528 */
529 initOnAll: function( container ) {
530 var newWidgets = ( container || this.editor.editable() ).find( '.cke_widget_new' ),
531 newInstances = [],
532 instance;
533
534 for ( var i = newWidgets.count(); i--; ) {
535 instance = this.initOn( newWidgets.getItem( i ).getFirst( Widget.isDomWidgetElement ) );
536 if ( instance )
537 newInstances.push( instance );
538 }
539
540 return newInstances;
541 },
542
543 /**
544 * Allows to listen to events on specific types of widgets, even if they are not created yet.
545 *
546 * Please note that this method inherits parameters from the {@link CKEDITOR.event#method-on} method with one
547 * extra parameter at the beginning which is the widget name.
548 *
549 * editor.widgets.onWidget( 'image', 'action', function( evt ) {
550 * // Event `action` occurs on `image` widget.
551 * } );
552 *
553 * @since 4.5
554 * @param {String} widgetName
555 * @param {String} eventName
556 * @param {Function} listenerFunction
557 * @param {Object} [scopeObj]
558 * @param {Object} [listenerData]
559 * @param {Number} [priority=10]
560 */
561 onWidget: function( widgetName ) {
562 var args = Array.prototype.slice.call( arguments );
563
564 args.shift();
565
566 for ( var i in this.instances ) {
567 var instance = this.instances[ i ];
568
569 if ( instance.name == widgetName ) {
570 instance.on.apply( instance, args );
571 }
572 }
573
574 this.on( 'instanceCreated', function( evt ) {
575 var widget = evt.data;
576
577 if ( widget.name == widgetName ) {
578 widget.on.apply( widget, args );
579 }
580 } );
581 },
582
583 /**
584 * Parses element classes string and returns an object
585 * whose keys contain class names. Skips all `cke_*` classes.
586 *
587 * This method is used by the {@link CKEDITOR.plugins.widget#getClasses} method and
588 * may be used when overriding that method.
589 *
590 * @since 4.4
591 * @param {String} classes String (value of `class` attribute).
592 * @returns {Object} Object containing classes or `null` if no classes found.
593 */
594 parseElementClasses: function( classes ) {
595 if ( !classes )
596 return null;
597
598 classes = CKEDITOR.tools.trim( classes ).split( /\s+/ );
599
600 var cl,
601 obj = {},
602 hasClasses = 0;
603
604 while ( ( cl = classes.pop() ) ) {
605 if ( cl.indexOf( 'cke_' ) == -1 )
606 obj[ cl ] = hasClasses = 1;
607 }
608
609 return hasClasses ? obj : null;
610 },
611
612 /**
613 * Wraps an element with a widget's non-editable container.
614 *
615 * If this method is called on an {@link CKEDITOR.htmlParser.element}, then it will
616 * also take care of fixing the DOM after wrapping (the wrapper may not be allowed in element's parent).
617 *
618 * @param {CKEDITOR.dom.element/CKEDITOR.htmlParser.element} element The widget element to be wrapped.
619 * @param {String} [widgetName] The name of the widget definition. Defaults to element's `data-widget`
620 * attribute value.
621 * @returns {CKEDITOR.dom.element/CKEDITOR.htmlParser.element} The wrapper element or `null` if
622 * the widget definition of this name is not registered.
623 */
624 wrapElement: function( element, widgetName ) {
625 var wrapper = null,
626 widgetDef,
627 isInline;
628
629 if ( element instanceof CKEDITOR.dom.element ) {
630 widgetName = widgetName || element.data( 'widget' );
631 widgetDef = this.registered[ widgetName ];
632
633 if ( !widgetDef )
634 return null;
635
636 // Do not wrap already wrapped element.
637 wrapper = element.getParent();
638 if ( wrapper && wrapper.type == CKEDITOR.NODE_ELEMENT && wrapper.data( 'cke-widget-wrapper' ) )
639 return wrapper;
640
641 // If attribute isn't already set (e.g. for pasted widget), set it.
642 if ( !element.hasAttribute( 'data-cke-widget-keep-attr' ) )
643 element.data( 'cke-widget-keep-attr', element.data( 'widget' ) ? 1 : 0 );
644
645 element.data( 'widget', widgetName );
646
647 isInline = isWidgetInline( widgetDef, element.getName() );
648
649 wrapper = new CKEDITOR.dom.element( isInline ? 'span' : 'div' );
650 wrapper.setAttributes( getWrapperAttributes( isInline, widgetName ) );
651
652 wrapper.data( 'cke-display-name', widgetDef.pathName ? widgetDef.pathName : element.getName() );
653
654 // Replace element unless it is a detached one.
655 if ( element.getParent( true ) )
656 wrapper.replace( element );
657 element.appendTo( wrapper );
658 }
659 else if ( element instanceof CKEDITOR.htmlParser.element ) {
660 widgetName = widgetName || element.attributes[ 'data-widget' ];
661 widgetDef = this.registered[ widgetName ];
662
663 if ( !widgetDef )
664 return null;
665
666 wrapper = element.parent;
667 if ( wrapper && wrapper.type == CKEDITOR.NODE_ELEMENT && wrapper.attributes[ 'data-cke-widget-wrapper' ] )
668 return wrapper;
669
670 // If attribute isn't already set (e.g. for pasted widget), set it.
671 if ( !( 'data-cke-widget-keep-attr' in element.attributes ) )
672 element.attributes[ 'data-cke-widget-keep-attr' ] = element.attributes[ 'data-widget' ] ? 1 : 0;
673 if ( widgetName )
674 element.attributes[ 'data-widget' ] = widgetName;
675
676 isInline = isWidgetInline( widgetDef, element.name );
677
678 wrapper = new CKEDITOR.htmlParser.element( isInline ? 'span' : 'div', getWrapperAttributes( isInline, widgetName ) );
679 wrapper.attributes[ 'data-cke-display-name' ] = widgetDef.pathName ? widgetDef.pathName : element.name;
680
681 var parent = element.parent,
682 index;
683
684 // Don't detach already detached element.
685 if ( parent ) {
686 index = element.getIndex();
687 element.remove();
688 }
689
690 wrapper.add( element );
691
692 // Insert wrapper fixing DOM (splitting parents if wrapper is not allowed inside them).
693 parent && insertElement( parent, index, wrapper );
694 }
695
696 return wrapper;
697 },
698
699 // Expose for tests.
700 _tests_createEditableFilter: createEditableFilter
701 };
702
703 CKEDITOR.event.implementOn( Repository.prototype );
704
705 /**
706 * An event fired when a widget instance is created, but before it is fully initialized.
707 *
708 * @event instanceCreated
709 * @param {CKEDITOR.plugins.widget} data The widget instance.
710 */
711
712 /**
713 * An event fired when a widget instance was destroyed.
714 *
715 * See also {@link CKEDITOR.plugins.widget#event-destroy}.
716 *
717 * @event instanceDestroyed
718 * @param {CKEDITOR.plugins.widget} data The widget instance.
719 */
720
721 /**
722 * An event fired to trigger the selection check.
723 *
724 * See the {@link #method-checkSelection} method.
725 *
726 * @event checkSelection
727 */
728
729 /**
730 * An event fired by the the {@link #method-checkWidgets} method.
731 *
732 * It can be canceled in order to stop the {@link #method-checkWidgets}
733 * method execution or the event listener can modify the method's options.
734 *
735 * @event checkWidgets
736 * @param [data]
737 * @param {Boolean} [data.initOnlyNew] Initialize widgets only on newly wrapped
738 * widget elements (those which still have the `cke_widget_new` class). When this option is
739 * set to `true`, widgets which were invalidated (e.g. by replacing with a cloned DOM structure)
740 * will not be reinitialized. This makes the check faster.
741 * @param {Boolean} [data.focusInited] If only one widget is initialized by
742 * the method, it will be focused.
743 */
744
745
746 /**
747 * An instance of a widget. Together with {@link CKEDITOR.plugins.widget.repository} these
748 * two classes constitute the core of the Widget System.
749 *
750 * Note that neither the repository nor the widget instances can be created by using their constructors.
751 * A repository instance is automatically set up by the Widget plugin and is accessible under
752 * {@link CKEDITOR.editor#widgets}, while widget instances are created and destroyed by the repository.
753 *
754 * To create a widget, first you need to {@link CKEDITOR.plugins.widget.repository#add register} its
755 * {@link CKEDITOR.plugins.widget.definition definition}:
756 *
757 * editor.widgets.add( 'simplebox', {
758 * upcast: function( element ) {
759 * // Defines which elements will become widgets.
760 * if ( element.hasClass( 'simplebox' ) )
761 * return true;
762 * },
763 * init: function() {
764 * // ...
765 * }
766 * } );
767 *
768 * Once the widget definition is registered, widgets will be automatically
769 * created when loading data:
770 *
771 * editor.setData( '<div class="simplebox">foo</div>', function() {
772 * console.log( editor.widgets.instances ); // -> An object containing one instance.
773 * } );
774 *
775 * It is also possible to create instances during runtime by using a command
776 * (if a {@link CKEDITOR.plugins.widget.definition#template} property was defined):
777 *
778 * // You can execute an automatically defined command to
779 * // insert a new simplebox widget or edit the one currently focused.
780 * editor.execCommand( 'simplebox' );
781 *
782 * Note: Since CKEditor 4.5 widget's `startupData` can be passed as the command argument:
783 *
784 * editor.execCommand( 'simplebox', {
785 * startupData: {
786 * align: 'left'
787 * }
788 * } );
789 *
790 * A widget can also be created in a completely custom way:
791 *
792 * var element = editor.document.createElement( 'div' );
793 * editor.insertElement( element );
794 * var widget = editor.widgets.initOn( element, 'simplebox' );
795 *
796 * @since 4.3
797 * @class CKEDITOR.plugins.widget
798 * @mixins CKEDITOR.event
799 * @extends CKEDITOR.plugins.widget.definition
800 * @constructor Creates an instance of the widget class. Do not use it directly, but instead initialize widgets
801 * by using the {@link CKEDITOR.plugins.widget.repository#initOn} method or by the upcasting system.
802 * @param {CKEDITOR.plugins.widget.repository} widgetsRepo
803 * @param {Number} id Unique ID of this widget instance.
804 * @param {CKEDITOR.dom.element} element The widget element.
805 * @param {CKEDITOR.plugins.widget.definition} widgetDef Widget's registered definition.
806 * @param [startupData] Initial widget data. This data object will overwrite the default data and
807 * the data loaded from the DOM.
808 */
809 function Widget( widgetsRepo, id, element, widgetDef, startupData ) {
810 var editor = widgetsRepo.editor;
811
812 // Extend this widget with widgetDef-specific methods and properties.
813 CKEDITOR.tools.extend( this, widgetDef, {
814 /**
815 * The editor instance.
816 *
817 * @readonly
818 * @property {CKEDITOR.editor}
819 */
820 editor: editor,
821
822 /**
823 * This widget's unique (per editor instance) ID.
824 *
825 * @readonly
826 * @property {Number}
827 */
828 id: id,
829
830 /**
831 * Whether this widget is an inline widget (based on an inline element unless
832 * forced otherwise by {@link CKEDITOR.plugins.widget.definition#inline}).
833 *
834 * **Note:** This option does not allow to turn a block element into an inline widget.
835 * However, it makes it possible to turn an inline element into a block widget or to
836 * force a correct type in case when automatic recognition fails.
837 *
838 * @readonly
839 * @property {Boolean}
840 */
841 inline: element.getParent().getName() == 'span',
842
843 /**
844 * The widget element &mdash; the element on which the widget was initialized.
845 *
846 * @readonly
847 * @property {CKEDITOR.dom.element} element
848 */
849 element: element,
850
851 /**
852 * Widget's data object.
853 *
854 * The data can only be set by using the {@link #setData} method.
855 * Changes made to the data fire the {@link #event-data} event.
856 *
857 * @readonly
858 */
859 data: CKEDITOR.tools.extend( {}, typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults ),
860
861 /**
862 * Indicates if a widget is data-ready. Set to `true` when data from all sources
863 * ({@link CKEDITOR.plugins.widget.definition#defaults}, set in the
864 * {@link #init} method, loaded from the widget's element and startup data coming from the constructor)
865 * are finally loaded. This is immediately followed by the first {@link #event-data}.
866 *
867 * @readonly
868 */
869 dataReady: false,
870
871 /**
872 * Whether a widget instance was initialized. This means that:
873 *
874 * * An instance was created,
875 * * Its properties were set,
876 * * The `init` method was executed.
877 *
878 * **Note**: The first {@link #event-data} event could not be fired yet which
879 * means that the widget's DOM has not been set up yet. Wait for the {@link #event-ready}
880 * event to be notified when a widget is fully initialized and ready.
881 *
882 * **Note**: Use the {@link #isInited} method to check whether a widget is initialized and
883 * has not been destroyed.
884 *
885 * @readonly
886 */
887 inited: false,
888
889 /**
890 * Whether a widget instance is ready. This means that the widget is {@link #inited} and
891 * that its DOM was finally set up.
892 *
893 * **Note:** Use the {@link #isReady} method to check whether a widget is ready and
894 * has not been destroyed.
895 *
896 * @readonly
897 */
898 ready: false,
899
900 // Revert what widgetDef could override (automatic #edit listener).
901 edit: Widget.prototype.edit,
902
903 /**
904 * The nested editable element which is currently focused.
905 *
906 * @readonly
907 * @property {CKEDITOR.plugins.widget.nestedEditable}
908 */
909 focusedEditable: null,
910
911 /**
912 * The widget definition from which this instance was created.
913 *
914 * @readonly
915 * @property {CKEDITOR.plugins.widget.definition} definition
916 */
917 definition: widgetDef,
918
919 /**
920 * Link to the widget repository which created this instance.
921 *
922 * @readonly
923 * @property {CKEDITOR.plugins.widget.repository} repository
924 */
925 repository: widgetsRepo,
926
927 draggable: widgetDef.draggable !== false,
928
929 // WAAARNING: Overwrite widgetDef's priv object, because otherwise violent unicorn's gonna visit you.
930 _: {
931 downcastFn: ( widgetDef.downcast && typeof widgetDef.downcast == 'string' ) ?
932 widgetDef.downcasts[ widgetDef.downcast ] : widgetDef.downcast
933 }
934 }, true );
935
936 /**
937 * An object of widget component elements.
938 *
939 * For every `partName => selector` pair in {@link CKEDITOR.plugins.widget.definition#parts},
940 * one `partName => element` pair is added to this object during the widget initialization.
941 *
942 * @readonly
943 * @property {Object} parts
944 */
945
946 /**
947 * The template which will be used to create a new widget element (when the widget's command is executed).
948 * It will be populated with {@link #defaults default values}.
949 *
950 * @readonly
951 * @property {CKEDITOR.template} template
952 */
953
954 /**
955 * The widget wrapper &mdash; a non-editable `div` or `span` element (depending on {@link #inline})
956 * which is a parent of the {@link #element} and widget compontents like the drag handler and the {@link #mask}.
957 * It is the outermost widget element.
958 *
959 * @readonly
960 * @property {CKEDITOR.dom.element} wrapper
961 */
962
963 widgetsRepo.fire( 'instanceCreated', this );
964
965 setupWidget( this, widgetDef );
966
967 this.init && this.init();
968
969 // Finally mark widget as inited.
970 this.inited = true;
971
972 setupWidgetData( this, startupData );
973
974 // If at some point (e.g. in #data listener) widget hasn't been destroyed
975 // and widget is already attached to document then fire #ready.
976 if ( this.isInited() && editor.editable().contains( this.wrapper ) ) {
977 this.ready = true;
978 this.fire( 'ready' );
979 }
980 }
981
982 Widget.prototype = {
983 /**
984 * Adds a class to the widget element. This method is used by
985 * the {@link #applyStyle} method and should be overridden by widgets
986 * which should handle classes differently (e.g. add them to other elements).
987 *
988 * Since 4.6.0 this method also adds a corresponding class prefixed with {@link #WRAPPER_CLASS_PREFIX}
989 * to the widget wrapper element.
990 *
991 * **Note**: This method should not be used directly. Use the {@link #setData} method to
992 * set the `classes` property. Read more in the {@link #setData} documentation.
993 *
994 * See also: {@link #removeClass}, {@link #hasClass}, {@link #getClasses}.
995 *
996 * @since 4.4
997 * @param {String} className The class name to be added.
998 */
999 addClass: function( className ) {
1000 this.element.addClass( className );
1001 this.wrapper.addClass( Widget.WRAPPER_CLASS_PREFIX + className );
1002 },
1003
1004 /**
1005 * Applies the specified style to the widget. It is highly recommended to use the
1006 * {@link CKEDITOR.editor#applyStyle} or {@link CKEDITOR.style#apply} methods instead of
1007 * using this method directly, because unlike editor's and style's methods, this one
1008 * does not perform any checks.
1009 *
1010 * By default this method handles only classes defined in the style. It clones existing
1011 * classes which are stored in the {@link #property-data widget data}'s `classes` property,
1012 * adds new classes, and calls the {@link #setData} method if at least one new class was added.
1013 * Then, using the {@link #event-data} event listener widget applies modifications passing
1014 * new classes to the {@link #addClass} method.
1015 *
1016 * If you need to handle classes differently than in the default way, you can override the
1017 * {@link #addClass} and related methods. You can also handle other style properties than `classes`
1018 * by overriding this method.
1019 *
1020 * See also: {@link #checkStyleActive}, {@link #removeStyle}.
1021 *
1022 * @since 4.4
1023 * @param {CKEDITOR.style} style The custom widget style to be applied.
1024 */
1025 applyStyle: function( style ) {
1026 applyRemoveStyle( this, style, 1 );
1027 },
1028
1029 /**
1030 * Checks if the specified style is applied to this widget. It is highly recommended to use the
1031 * {@link CKEDITOR.style#checkActive} method instead of using this method directly,
1032 * because unlike style's method, this one does not perform any checks.
1033 *
1034 * By default this method handles only classes defined in the style and passes
1035 * them to the {@link #hasClass} method. You can override these methods to handle classes
1036 * differently or to handle more of the style properties.
1037 *
1038 * See also: {@link #applyStyle}, {@link #removeStyle}.
1039 *
1040 * @since 4.4
1041 * @param {CKEDITOR.style} style The custom widget style to be checked.
1042 * @returns {Boolean} Whether the style is applied to this widget.
1043 */
1044 checkStyleActive: function( style ) {
1045 var classes = getStyleClasses( style ),
1046 cl;
1047
1048 if ( !classes )
1049 return false;
1050
1051 while ( ( cl = classes.pop() ) ) {
1052 if ( !this.hasClass( cl ) )
1053 return false;
1054 }
1055 return true;
1056 },
1057
1058 /**
1059 * Destroys this widget instance.
1060 *
1061 * Use {@link CKEDITOR.plugins.widget.repository#destroy} when possible instead of this method.
1062 *
1063 * This method fires the {#event-destroy} event.
1064 *
1065 * @param {Boolean} [offline] Whether a widget is offline (detached from the DOM tree) &mdash;
1066 * in this case the DOM (attributes, classes, etc.) will not be cleaned up.
1067 */
1068 destroy: function( offline ) {
1069 this.fire( 'destroy' );
1070
1071 if ( this.editables ) {
1072 for ( var name in this.editables )
1073 this.destroyEditable( name, offline );
1074 }
1075
1076 if ( !offline ) {
1077 if ( this.element.data( 'cke-widget-keep-attr' ) == '0' )
1078 this.element.removeAttribute( 'data-widget' );
1079 this.element.removeAttributes( [ 'data-cke-widget-data', 'data-cke-widget-keep-attr' ] );
1080 this.element.removeClass( 'cke_widget_element' );
1081 this.element.replace( this.wrapper );
1082 }
1083
1084 this.wrapper = null;
1085 },
1086
1087 /**
1088 * Destroys a nested editable and all nested widgets.
1089 *
1090 * @param {String} editableName Nested editable name.
1091 * @param {Boolean} [offline] See {@link #method-destroy} method.
1092 */
1093 destroyEditable: function( editableName, offline ) {
1094 var editable = this.editables[ editableName ];
1095
1096 editable.removeListener( 'focus', onEditableFocus );
1097 editable.removeListener( 'blur', onEditableBlur );
1098 this.editor.focusManager.remove( editable );
1099
1100 if ( !offline ) {
1101 this.repository.destroyAll( false, editable );
1102 editable.removeClass( 'cke_widget_editable' );
1103 editable.removeClass( 'cke_widget_editable_focused' );
1104 editable.removeAttributes( [ 'contenteditable', 'data-cke-widget-editable', 'data-cke-enter-mode' ] );
1105 }
1106
1107 delete this.editables[ editableName ];
1108 },
1109
1110 /**
1111 * Starts widget editing.
1112 *
1113 * This method fires the {@link CKEDITOR.plugins.widget#event-edit} event
1114 * which may be canceled in order to prevent it from opening a dialog window.
1115 *
1116 * The dialog window name is obtained from the event's data `dialog` property or
1117 * from {@link CKEDITOR.plugins.widget.definition#dialog}.
1118 *
1119 * @returns {Boolean} Returns `true` if a dialog window was opened.
1120 */
1121 edit: function() {
1122 var evtData = { dialog: this.dialog },
1123 that = this;
1124
1125 // Edit event was blocked or there's no dialog to be automatically opened.
1126 if ( this.fire( 'edit', evtData ) === false || !evtData.dialog )
1127 return false;
1128
1129 this.editor.openDialog( evtData.dialog, function( dialog ) {
1130 var showListener,
1131 okListener;
1132
1133 // Allow to add a custom dialog handler.
1134 if ( that.fire( 'dialog', dialog ) === false )
1135 return;
1136
1137 showListener = dialog.on( 'show', function() {
1138 dialog.setupContent( that );
1139 } );
1140
1141 okListener = dialog.on( 'ok', function() {
1142 // Commit dialog's fields, but prevent from
1143 // firing data event for every field. Fire only one,
1144 // bulk event at the end.
1145 var dataChanged,
1146 dataListener = that.on( 'data', function( evt ) {
1147 dataChanged = 1;
1148 evt.cancel();
1149 }, null, null, 0 );
1150
1151 // Create snapshot preceeding snapshot with changed widget...
1152 // TODO it should not be required, but it is and I found similar
1153 // code in dialog#ok listener in dialog/plugin.js.
1154 that.editor.fire( 'saveSnapshot' );
1155 dialog.commitContent( that );
1156
1157 dataListener.removeListener();
1158 if ( dataChanged ) {
1159 that.fire( 'data', that.data );
1160 that.editor.fire( 'saveSnapshot' );
1161 }
1162 } );
1163
1164 dialog.once( 'hide', function() {
1165 showListener.removeListener();
1166 okListener.removeListener();
1167 } );
1168 } );
1169
1170 return true;
1171 },
1172
1173 /**
1174 * Returns widget element classes parsed to an object. This method
1175 * is used to populate the `classes` property of widget's {@link #property-data}.
1176 *
1177 * This method reuses {@link CKEDITOR.plugins.widget.repository#parseElementClasses}.
1178 * It should be overriden if a widget should handle classes differently (e.g. on other elements).
1179 *
1180 * See also: {@link #removeClass}, {@link #addClass}, {@link #hasClass}.
1181 *
1182 * @since 4.4
1183 * @returns {Object}
1184 */
1185 getClasses: function() {
1186 return this.repository.parseElementClasses( this.element.getAttribute( 'class' ) );
1187 },
1188
1189 /**
1190 * Checks if the widget element has specified class. This method is used by
1191 * the {@link #checkStyleActive} method and should be overriden by widgets
1192 * which should handle classes differently (e.g. on other elements).
1193 *
1194 * See also: {@link #removeClass}, {@link #addClass}, {@link #getClasses}.
1195 *
1196 * @since 4.4
1197 * @param {String} className The class to be checked.
1198 * @param {Boolean} Whether a widget has specified class.
1199 */
1200 hasClass: function( className ) {
1201 return this.element.hasClass( className );
1202 },
1203
1204 /**
1205 * Initializes a nested editable.
1206 *
1207 * **Note**: Only elements from {@link CKEDITOR.dtd#$editable} may become editables.
1208 *
1209 * @param {String} editableName The nested editable name.
1210 * @param {CKEDITOR.plugins.widget.nestedEditable.definition} definition The definition of the nested editable.
1211 * @returns {Boolean} Whether an editable was successfully initialized.
1212 */
1213 initEditable: function( editableName, definition ) {
1214 // Don't fetch just first element which matched selector but look for a correct one. (#13334)
1215 var editable = this._findOneNotNested( definition.selector );
1216
1217 if ( editable && editable.is( CKEDITOR.dtd.$editable ) ) {
1218 editable = new NestedEditable( this.editor, editable, {
1219 filter: createEditableFilter.call( this.repository, this.name, editableName, definition )
1220 } );
1221 this.editables[ editableName ] = editable;
1222
1223 editable.setAttributes( {
1224 contenteditable: 'true',
1225 'data-cke-widget-editable': editableName,
1226 'data-cke-enter-mode': editable.enterMode
1227 } );
1228
1229 if ( editable.filter )
1230 editable.data( 'cke-filter', editable.filter.id );
1231
1232 editable.addClass( 'cke_widget_editable' );
1233 // This class may be left when d&ding widget which
1234 // had focused editable. Clean this class here, not in
1235 // cleanUpWidgetElement for performance and code size reasons.
1236 editable.removeClass( 'cke_widget_editable_focused' );
1237
1238 if ( definition.pathName )
1239 editable.data( 'cke-display-name', definition.pathName );
1240
1241 this.editor.focusManager.add( editable );
1242 editable.on( 'focus', onEditableFocus, this );
1243 CKEDITOR.env.ie && editable.on( 'blur', onEditableBlur, this );
1244
1245 // Finally, process editable's data. This data wasn't processed when loading
1246 // editor's data, becuase they need to be processed separately, with its own filters and settings.
1247 editable._.initialSetData = true;
1248 editable.setData( editable.getHtml() );
1249
1250 return true;
1251 }
1252
1253 return false;
1254 },
1255
1256 /**
1257 * Looks inside wrapper element to find a node that
1258 * matches given selector and is not nested in other widget. (#13334)
1259 *
1260 * @since 4.5
1261 * @private
1262 * @param {String} selector Selector to match.
1263 * @returns {CKEDITOR.dom.element} Matched element or `null` if a node has not been found.
1264 */
1265 _findOneNotNested: function( selector ) {
1266 var matchedElements = this.wrapper.find( selector ),
1267 match,
1268 closestWrapper;
1269
1270 for ( var i = 0; i < matchedElements.count(); i++ ) {
1271 match = matchedElements.getItem( i );
1272 closestWrapper = match.getAscendant( Widget.isDomWidgetWrapper );
1273
1274 // The closest ascendant-wrapper of this match defines to which widget
1275 // this match belongs. If the ascendant is this widget's wrapper
1276 // it means that the match is not nested in other widget.
1277 if ( this.wrapper.equals( closestWrapper ) ) {
1278 return match;
1279 }
1280 }
1281
1282 return null;
1283 },
1284
1285 /**
1286 * Checks if a widget has already been initialized and has not been destroyed yet.
1287 *
1288 * See {@link #inited} for more details.
1289 *
1290 * @returns {Boolean}
1291 */
1292 isInited: function() {
1293 return !!( this.wrapper && this.inited );
1294 },
1295
1296 /**
1297 * Checks if a widget is ready and has not been destroyed yet.
1298 *
1299 * See {@link #property-ready} for more details.
1300 *
1301 * @returns {Boolean}
1302 */
1303 isReady: function() {
1304 return this.isInited() && this.ready;
1305 },
1306
1307 /**
1308 * Focuses a widget by selecting it.
1309 */
1310 focus: function() {
1311 var sel = this.editor.getSelection();
1312
1313 // Fake the selection before focusing editor, to avoid unpreventable viewports scrolling
1314 // on Webkit/Blink/IE which is done because there's no selection or selection was somewhere else than widget.
1315 if ( sel ) {
1316 var isDirty = this.editor.checkDirty();
1317
1318 sel.fake( this.wrapper );
1319
1320 !isDirty && this.editor.resetDirty();
1321 }
1322
1323 // Always focus editor (not only when focusManger.hasFocus is false) (because of #10483).
1324 this.editor.focus();
1325 },
1326
1327 /**
1328 * Removes a class from the widget element. This method is used by
1329 * the {@link #removeStyle} method and should be overriden by widgets
1330 * which should handle classes differently (e.g. on other elements).
1331 *
1332 * **Note**: This method should not be used directly. Use the {@link #setData} method to
1333 * set the `classes` property. Read more in the {@link #setData} documentation.
1334 *
1335 * See also: {@link #hasClass}, {@link #addClass}.
1336 *
1337 * @since 4.4
1338 * @param {String} className The class to be removed.
1339 */
1340 removeClass: function( className ) {
1341 this.element.removeClass( className );
1342 this.wrapper.removeClass( Widget.WRAPPER_CLASS_PREFIX + className );
1343 },
1344
1345 /**
1346 * Removes the specified style from the widget. It is highly recommended to use the
1347 * {@link CKEDITOR.editor#removeStyle} or {@link CKEDITOR.style#remove} methods instead of
1348 * using this method directly, because unlike editor's and style's methods, this one
1349 * does not perform any checks.
1350 *
1351 * Read more about how applying/removing styles works in the {@link #applyStyle} method documentation.
1352 *
1353 * See also {@link #checkStyleActive}, {@link #applyStyle}, {@link #getClasses}.
1354 *
1355 * @since 4.4
1356 * @param {CKEDITOR.style} style The custom widget style to be removed.
1357 */
1358 removeStyle: function( style ) {
1359 applyRemoveStyle( this, style, 0 );
1360 },
1361
1362 /**
1363 * Sets widget value(s) in the {@link #property-data} object.
1364 * If the given value(s) modifies current ones, the {@link #event-data} event is fired.
1365 *
1366 * this.setData( 'align', 'left' );
1367 * this.data.align; // -> 'left'
1368 *
1369 * this.setData( { align: 'right', opened: false } );
1370 * this.data.align; // -> 'right'
1371 * this.data.opened; // -> false
1372 *
1373 * Set values are stored in {@link #element}'s attribute (`data-cke-widget-data`),
1374 * in a JSON string, therefore {@link #property-data} should contain
1375 * only serializable data.
1376 *
1377 * **Note:** A special data property, `classes`, exists. It contains an object with
1378 * classes which were returned by the {@link #getClasses} method during the widget initialization.
1379 * This property is then used by the {@link #applyStyle} and {@link #removeStyle} methods.
1380 * When it is changed (the reference to object must be changed!), the widget updates its classes by
1381 * using the {@link #addClass} and {@link #removeClass} methods.
1382 *
1383 * // Adding a new class.
1384 * var classes = CKEDITOR.tools.clone( widget.data.classes );
1385 * classes.newClass = 1;
1386 * widget.setData( 'classes', classes );
1387 *
1388 * // Removing a class.
1389 * var classes = CKEDITOR.tools.clone( widget.data.classes );
1390 * delete classes.newClass;
1391 * widget.setData( 'classes', classes );
1392 *
1393 * @param {String/Object} keyOrData
1394 * @param {Object} value
1395 * @chainable
1396 */
1397 setData: function( key, value ) {
1398 var data = this.data,
1399 modified = 0;
1400
1401 if ( typeof key == 'string' ) {
1402 if ( data[ key ] !== value ) {
1403 data[ key ] = value;
1404 modified = 1;
1405 }
1406 }
1407 else {
1408 var newData = key;
1409
1410 for ( key in newData ) {
1411 if ( data[ key ] !== newData[ key ] ) {
1412 modified = 1;
1413 data[ key ] = newData[ key ];
1414 }
1415 }
1416 }
1417
1418 // Block firing data event and overwriting data element before setupWidgetData is executed.
1419 if ( modified && this.dataReady ) {
1420 writeDataToElement( this );
1421 this.fire( 'data', data );
1422 }
1423
1424 return this;
1425 },
1426
1427 /**
1428 * Changes the widget's focus state. This method is executed automatically after
1429 * a widget was focused by the {@link #method-focus} method or the selection was moved
1430 * out of the widget.
1431 *
1432 * This is a low-level method which is not integrated with e.g. the undo manager.
1433 * Use the {@link #method-focus} method instead.
1434 *
1435 * @param {Boolean} selected Whether to select or deselect this widget.
1436 * @chainable
1437 */
1438 setFocused: function( focused ) {
1439 this.wrapper[ focused ? 'addClass' : 'removeClass' ]( 'cke_widget_focused' );
1440 this.fire( focused ? 'focus' : 'blur' );
1441 return this;
1442 },
1443
1444 /**
1445 * Changes the widget's select state. This method is executed automatically after
1446 * a widget was selected by the {@link #method-focus} method or the selection
1447 * was moved out of the widget.
1448 *
1449 * This is a low-level method which is not integrated with e.g. the undo manager.
1450 * Use the {@link #method-focus} method instead or simply change the selection.
1451 *
1452 * @param {Boolean} selected Whether to select or deselect this widget.
1453 * @chainable
1454 */
1455 setSelected: function( selected ) {
1456 this.wrapper[ selected ? 'addClass' : 'removeClass' ]( 'cke_widget_selected' );
1457 this.fire( selected ? 'select' : 'deselect' );
1458 return this;
1459 },
1460
1461 /**
1462 * Repositions drag handler according to the widget's element position. Should be called from events, like mouseover.
1463 */
1464 updateDragHandlerPosition: function() {
1465 var editor = this.editor,
1466 domElement = this.element.$,
1467 oldPos = this._.dragHandlerOffset,
1468 newPos = {
1469 x: domElement.offsetLeft,
1470 y: domElement.offsetTop - DRAG_HANDLER_SIZE
1471 };
1472
1473 if ( oldPos && newPos.x == oldPos.x && newPos.y == oldPos.y )
1474 return;
1475
1476 // We need to make sure that dirty state is not changed (#11487).
1477 var initialDirty = editor.checkDirty();
1478
1479 editor.fire( 'lockSnapshot' );
1480 this.dragHandlerContainer.setStyles( {
1481 top: newPos.y + 'px',
1482 left: newPos.x + 'px',
1483 display: 'block'
1484 } );
1485 editor.fire( 'unlockSnapshot' );
1486 !initialDirty && editor.resetDirty();
1487
1488 this._.dragHandlerOffset = newPos;
1489 }
1490 };
1491
1492 CKEDITOR.event.implementOn( Widget.prototype );
1493
1494 /**
1495 * Gets the {@link #isDomNestedEditable nested editable}
1496 * (returned as a {@link CKEDITOR.dom.element}, not as a {@link CKEDITOR.plugins.widget.nestedEditable})
1497 * closest to the `node` or the `node` if it is a nested editable itself.
1498 *
1499 * @since 4.5
1500 * @static
1501 * @param {CKEDITOR.dom.element} guard Stop ancestor search on this node (usually editor's editable).
1502 * @param {CKEDITOR.dom.node} node Start the search from this node.
1503 * @returns {CKEDITOR.dom.element/null} Element or `null` if not found.
1504 */
1505 Widget.getNestedEditable = function( guard, node ) {
1506 if ( !node || node.equals( guard ) )
1507 return null;
1508
1509 if ( Widget.isDomNestedEditable( node ) )
1510 return node;
1511
1512 return Widget.getNestedEditable( guard, node.getParent() );
1513 };
1514
1515 /**
1516 * Checks whether the `node` is a widget's drag handle element.
1517 *
1518 * @since 4.5
1519 * @static
1520 * @param {CKEDITOR.dom.node} node
1521 * @returns {Boolean}
1522 */
1523 Widget.isDomDragHandler = function( node ) {
1524 return node.type == CKEDITOR.NODE_ELEMENT && node.hasAttribute( 'data-cke-widget-drag-handler' );
1525 };
1526
1527 /**
1528 * Checks whether the `node` is a container of the widget's drag handle element.
1529 *
1530 * @since 4.5
1531 * @static
1532 * @param {CKEDITOR.dom.node} node
1533 * @returns {Boolean}
1534 */
1535 Widget.isDomDragHandlerContainer = function( node ) {
1536 return node.type == CKEDITOR.NODE_ELEMENT && node.hasClass( 'cke_widget_drag_handler_container' );
1537 };
1538
1539 /**
1540 * Checks whether the `node` is a {@link CKEDITOR.plugins.widget#editables nested editable}.
1541 * Note that this function only checks whether it is the right element, not whether
1542 * the passed `node` is an instance of {@link CKEDITOR.plugins.widget.nestedEditable}.
1543 *
1544 * @since 4.5
1545 * @static
1546 * @param {CKEDITOR.dom.node} node
1547 * @returns {Boolean}
1548 */
1549 Widget.isDomNestedEditable = function( node ) {
1550 return node.type == CKEDITOR.NODE_ELEMENT && node.hasAttribute( 'data-cke-widget-editable' );
1551 };
1552
1553 /**
1554 * Checks whether the `node` is a {@link CKEDITOR.plugins.widget#element widget element}.
1555 *
1556 * @since 4.5
1557 * @static
1558 * @param {CKEDITOR.dom.node} node
1559 * @returns {Boolean}
1560 */
1561 Widget.isDomWidgetElement = function( node ) {
1562 return node.type == CKEDITOR.NODE_ELEMENT && node.hasAttribute( 'data-widget' );
1563 };
1564
1565 /**
1566 * Checks whether the `node` is a {@link CKEDITOR.plugins.widget#wrapper widget wrapper}.
1567 *
1568 * @since 4.5
1569 * @static
1570 * @param {CKEDITOR.dom.element} node
1571 * @returns {Boolean}
1572 */
1573 Widget.isDomWidgetWrapper = function( node ) {
1574 return node.type == CKEDITOR.NODE_ELEMENT && node.hasAttribute( 'data-cke-widget-wrapper' );
1575 };
1576
1577 /**
1578 * Checks whether the `node` is a {@link CKEDITOR.plugins.widget#element widget element}.
1579 *
1580 * @since 4.5
1581 * @static
1582 * @param {CKEDITOR.htmlParser.node} node
1583 * @returns {Boolean}
1584 */
1585 Widget.isParserWidgetElement = function( node ) {
1586 return node.type == CKEDITOR.NODE_ELEMENT && !!node.attributes[ 'data-widget' ];
1587 };
1588
1589 /**
1590 * Checks whether the `node` is a {@link CKEDITOR.plugins.widget#wrapper widget wrapper}.
1591 *
1592 * @since 4.5
1593 * @static
1594 * @param {CKEDITOR.htmlParser.element} node
1595 * @returns {Boolean}
1596 */
1597 Widget.isParserWidgetWrapper = function( node ) {
1598 return node.type == CKEDITOR.NODE_ELEMENT && !!node.attributes[ 'data-cke-widget-wrapper' ];
1599 };
1600
1601 /**
1602 * Prefix added to wrapper classes. Each class added to the widget element by the {@link #addClass}
1603 * method will also be added to the wrapper prefixed with it.
1604 *
1605 * @since 4.6.0
1606 * @static
1607 * @readonly
1608 * @property {String} [='cke_widget_wrapper_']
1609 */
1610 Widget.WRAPPER_CLASS_PREFIX = 'cke_widget_wrapper_';
1611
1612 /**
1613 * An event fired when a widget is ready (fully initialized). This event is fired after:
1614 *
1615 * * {@link #init} is called,
1616 * * The first {@link #event-data} event is fired,
1617 * * A widget is attached to the document.
1618 *
1619 * Therefore, in case of widget creation with a command which opens a dialog window, this event
1620 * will be delayed after the dialog window is closed and the widget is finally inserted into the document.
1621 *
1622 * **Note**: If your widget does not use automatic dialog window binding (i.e. you open the dialog window manually)
1623 * or another situation in which the widget wrapper is not attached to document at the time when it is
1624 * initialized occurs, you need to take care of firing {@link #event-ready} yourself.
1625 *
1626 * See also {@link #property-ready} and {@link #property-inited} properties, and
1627 * {@link #isReady} and {@link #isInited} methods.
1628 *
1629 * @event ready
1630 */
1631
1632 /**
1633 * An event fired when a widget is about to be destroyed, but before it is
1634 * fully torn down.
1635 *
1636 * @event destroy
1637 */
1638
1639 /**
1640 * An event fired when a widget is focused.
1641 *
1642 * Widget can be focused by executing {@link #method-focus}.
1643 *
1644 * @event focus
1645 */
1646
1647 /**
1648 * An event fired when a widget is blurred.
1649 *
1650 * @event blur
1651 */
1652
1653 /**
1654 * An event fired when a widget is selected.
1655 *
1656 * @event select
1657 */
1658
1659 /**
1660 * An event fired when a widget is deselected.
1661 *
1662 * @event deselect
1663 */
1664
1665 /**
1666 * An event fired by the {@link #method-edit} method. It can be canceled
1667 * in order to stop the default action (opening a dialog window and/or
1668 * {@link CKEDITOR.plugins.widget.repository#finalizeCreation finalizing widget creation}).
1669 *
1670 * @event edit
1671 * @param data
1672 * @param {String} data.dialog Defaults to {@link CKEDITOR.plugins.widget.definition#dialog}
1673 * and can be changed or set by the listener.
1674 */
1675
1676 /**
1677 * An event fired when a dialog window for widget editing is opened.
1678 * This event can be canceled in order to handle the editing dialog in a custom manner.
1679 *
1680 * @event dialog
1681 * @param {CKEDITOR.dialog} data The opened dialog window instance.
1682 */
1683
1684 /**
1685 * An event fired when a key is pressed on a focused widget.
1686 * This event is forwarded from the {@link CKEDITOR.editor#key} event and
1687 * has the ability to block editor keystrokes if it is canceled.
1688 *
1689 * @event key
1690 * @param data
1691 * @param {Number} data.keyCode A number representing the key code (or combination).
1692 */
1693
1694 /**
1695 * An event fired when a widget is double clicked.
1696 *
1697 * **Note:** If a default editing action is executed on double click (i.e. a widget has a
1698 * {@link CKEDITOR.plugins.widget.definition#dialog dialog} defined and the {@link #event-doubleclick} event was not
1699 * canceled), this event will be automatically canceled, so a listener added with the default priority (10)
1700 * will not be executed. Use a listener with low priority (e.g. 5) to be sure that it will be executed.
1701 *
1702 * widget.on( 'doubleclick', function( evt ) {
1703 * console.log( 'widget#doubleclick' );
1704 * }, null, null, 5 );
1705 *
1706 * If your widget handles double click in a special way (so the default editing action is not executed),
1707 * make sure you cancel this event, because otherwise it will be propagated to {@link CKEDITOR.editor#doubleclick}
1708 * and another feature may step in (e.g. a Link dialog window may be opened if your widget was inside a link).
1709 *
1710 * @event doubleclick
1711 * @param data
1712 * @param {CKEDITOR.dom.element} data.element The double-clicked element.
1713 */
1714
1715 /**
1716 * An event fired when the context menu is opened for a widget.
1717 *
1718 * @event contextMenu
1719 * @param data The object containing context menu options to be added
1720 * for this widget. See {@link CKEDITOR.plugins.contextMenu#addListener}.
1721 */
1722
1723 /**
1724 * An event fired when the widget data changed. See the {@link #setData} method and the {@link #property-data} property.
1725 *
1726 * @event data
1727 */
1728
1729
1730
1731 /**
1732 * The wrapper class for editable elements inside widgets.
1733 *
1734 * Do not use directly. Use {@link CKEDITOR.plugins.widget.definition#editables} or
1735 * {@link CKEDITOR.plugins.widget#initEditable}.
1736 *
1737 * @class CKEDITOR.plugins.widget.nestedEditable
1738 * @extends CKEDITOR.dom.element
1739 * @constructor
1740 * @param {CKEDITOR.editor} editor
1741 * @param {CKEDITOR.dom.element} element
1742 * @param config
1743 * @param {CKEDITOR.filter} [config.filter]
1744 */
1745 function NestedEditable( editor, element, config ) {
1746 // Call the base constructor.
1747 CKEDITOR.dom.element.call( this, element.$ );
1748 this.editor = editor;
1749 this._ = {};
1750 var filter = this.filter = config.filter;
1751
1752 // If blockless editable - always use BR mode.
1753 if ( !CKEDITOR.dtd[ this.getName() ].p )
1754 this.enterMode = this.shiftEnterMode = CKEDITOR.ENTER_BR;
1755 else {
1756 this.enterMode = filter ? filter.getAllowedEnterMode( editor.enterMode ) : editor.enterMode;
1757 this.shiftEnterMode = filter ? filter.getAllowedEnterMode( editor.shiftEnterMode, true ) : editor.shiftEnterMode;
1758 }
1759 }
1760
1761 NestedEditable.prototype = CKEDITOR.tools.extend( CKEDITOR.tools.prototypedCopy( CKEDITOR.dom.element.prototype ), {
1762 /**
1763 * Sets the editable data. The data will be passed through the {@link CKEDITOR.editor#dataProcessor}
1764 * and the {@link CKEDITOR.editor#filter}. This ensures that the data was filtered and prepared to be
1765 * edited like the {@link CKEDITOR.editor#method-setData editor data}.
1766 *
1767 * Before content is changed, all nested widgets are destroyed. Afterwards, after new content is loaded,
1768 * all nested widgets are initialized.
1769 *
1770 * @param {String} data
1771 */
1772 setData: function( data ) {
1773 // For performance reasons don't call destroyAll when initializing a nested editable,
1774 // because there are no widgets inside.
1775 if ( !this._.initialSetData ) {
1776 // Destroy all nested widgets before setting data.
1777 this.editor.widgets.destroyAll( false, this );
1778 }
1779 this._.initialSetData = false;
1780
1781 data = this.editor.dataProcessor.toHtml( data, {
1782 context: this.getName(),
1783 filter: this.filter,
1784 enterMode: this.enterMode
1785 } );
1786 this.setHtml( data );
1787
1788 this.editor.widgets.initOnAll( this );
1789 },
1790
1791 /**
1792 * Gets the editable data. Like {@link #setData}, this method will process and filter the data.
1793 *
1794 * @returns {String}
1795 */
1796 getData: function() {
1797 return this.editor.dataProcessor.toDataFormat( this.getHtml(), {
1798 context: this.getName(),
1799 filter: this.filter,
1800 enterMode: this.enterMode
1801 } );
1802 }
1803 } );
1804
1805 /**
1806 * The editor instance.
1807 *
1808 * @readonly
1809 * @property {CKEDITOR.editor} editor
1810 */
1811
1812 /**
1813 * The filter instance if allowed content rules were defined.
1814 *
1815 * @readonly
1816 * @property {CKEDITOR.filter} filter
1817 */
1818
1819 /**
1820 * The enter mode active in this editable.
1821 * It is determined from editable's name (whether it is a blockless editable),
1822 * its allowed content rules (if defined) and the default editor's mode.
1823 *
1824 * @readonly
1825 * @property {Number} enterMode
1826 */
1827
1828 /**
1829 * The shift enter move active in this editable.
1830 *
1831 * @readonly
1832 * @property {Number} shiftEnterMode
1833 */
1834
1835
1836 //
1837 // REPOSITORY helpers -----------------------------------------------------
1838 //
1839
1840 function addWidgetButtons( editor ) {
1841 var widgets = editor.widgets.registered,
1842 widget,
1843 widgetName,
1844 widgetButton;
1845
1846 for ( widgetName in widgets ) {
1847 widget = widgets[ widgetName ];
1848
1849 // Create button if defined.
1850 widgetButton = widget.button;
1851 if ( widgetButton && editor.ui.addButton ) {
1852 editor.ui.addButton( CKEDITOR.tools.capitalize( widget.name, true ), {
1853 label: widgetButton,
1854 command: widget.name,
1855 toolbar: 'insert,10'
1856 } );
1857 }
1858 }
1859 }
1860
1861 // Create a command creating and editing widget.
1862 //
1863 // @param editor
1864 // @param {CKEDITOR.plugins.widget.definition} widgetDef
1865 function addWidgetCommand( editor, widgetDef ) {
1866 editor.addCommand( widgetDef.name, {
1867 exec: function( editor, commandData ) {
1868 var focused = editor.widgets.focused;
1869 // If a widget of the same type is focused, start editing.
1870 if ( focused && focused.name == widgetDef.name )
1871 focused.edit();
1872 // Otherwise...
1873 // ... use insert method is was defined.
1874 else if ( widgetDef.insert )
1875 widgetDef.insert();
1876 // ... or create a brand-new widget from template.
1877 else if ( widgetDef.template ) {
1878 var defaults = typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults,
1879 element = CKEDITOR.dom.element.createFromHtml( widgetDef.template.output( defaults ) ),
1880 instance,
1881 wrapper = editor.widgets.wrapElement( element, widgetDef.name ),
1882 temp = new CKEDITOR.dom.documentFragment( wrapper.getDocument() );
1883
1884 // Append wrapper to a temporary document. This will unify the environment
1885 // in which #data listeners work when creating and editing widget.
1886 temp.append( wrapper );
1887 instance = editor.widgets.initOn( element, widgetDef, commandData && commandData.startupData );
1888
1889 // Instance could be destroyed during initialization.
1890 // In this case finalize creation if some new widget
1891 // was left in temporary document fragment.
1892 if ( !instance ) {
1893 finalizeCreation();
1894 return;
1895 }
1896
1897 // Listen on edit to finalize widget insertion.
1898 //
1899 // * If dialog was set, then insert widget after dialog was successfully saved or destroy this
1900 // temporary instance.
1901 // * If dialog wasn't set and edit wasn't canceled, insert widget.
1902 var editListener = instance.once( 'edit', function( evt ) {
1903 if ( evt.data.dialog ) {
1904 instance.once( 'dialog', function( evt ) {
1905 var dialog = evt.data,
1906 okListener,
1907 cancelListener;
1908
1909 // Finalize creation AFTER (20) new data was set.
1910 okListener = dialog.once( 'ok', finalizeCreation, null, null, 20 );
1911
1912 cancelListener = dialog.once( 'cancel', function( evt ) {
1913 if ( !( evt.data && evt.data.hide === false ) ) {
1914 editor.widgets.destroy( instance, true );
1915 }
1916 } );
1917
1918 dialog.once( 'hide', function() {
1919 okListener.removeListener();
1920 cancelListener.removeListener();
1921 } );
1922 } );
1923 } else {
1924 // Dialog hasn't been set, so insert widget now.
1925 finalizeCreation();
1926 }
1927 }, null, null, 999 );
1928
1929 instance.edit();
1930
1931 // Remove listener in case someone canceled it before this
1932 // listener was executed.
1933 editListener.removeListener();
1934 }
1935
1936 function finalizeCreation() {
1937 editor.widgets.finalizeCreation( temp );
1938 }
1939 },
1940
1941 allowedContent: widgetDef.allowedContent,
1942 requiredContent: widgetDef.requiredContent,
1943 contentForms: widgetDef.contentForms,
1944 contentTransformations: widgetDef.contentTransformations
1945 } );
1946 }
1947
1948 function addWidgetProcessors( widgetsRepo, widgetDef ) {
1949 var upcast = widgetDef.upcast,
1950 upcasts,
1951 priority = widgetDef.upcastPriority || 10;
1952
1953 if ( !upcast )
1954 return;
1955
1956 // Multiple upcasts defined in string.
1957 if ( typeof upcast == 'string' ) {
1958 upcasts = upcast.split( ',' );
1959 while ( upcasts.length ) {
1960 addUpcast( widgetDef.upcasts[ upcasts.pop() ], widgetDef.name, priority );
1961 }
1962 }
1963 // Single rule which is automatically activated.
1964 else {
1965 addUpcast( upcast, widgetDef.name, priority );
1966 }
1967
1968 function addUpcast( upcast, name, priority ) {
1969 // Find index of the first higher (in terms of value) priority upcast.
1970 var index = CKEDITOR.tools.getIndex( widgetsRepo._.upcasts, function( element ) {
1971 return element[ 2 ] > priority;
1972 } );
1973 // Add at the end if it is the highest priority so far.
1974 if ( index < 0 ) {
1975 index = widgetsRepo._.upcasts.length;
1976 }
1977
1978 widgetsRepo._.upcasts.splice( index, 0, [ upcast, name, priority ] );
1979 }
1980 }
1981
1982 function blurWidget( widgetsRepo, widget ) {
1983 widgetsRepo.focused = null;
1984
1985 if ( widget.isInited() ) {
1986 var isDirty = widget.editor.checkDirty();
1987
1988 // Widget could be destroyed in the meantime - e.g. data could be set.
1989 widgetsRepo.fire( 'widgetBlurred', { widget: widget } );
1990 widget.setFocused( false );
1991
1992 !isDirty && widget.editor.resetDirty();
1993 }
1994 }
1995
1996 function checkWidgets( evt ) {
1997 var options = evt.data;
1998
1999 if ( this.editor.mode != 'wysiwyg' )
2000 return;
2001
2002 var editable = this.editor.editable(),
2003 instances = this.instances,
2004 newInstances, i, count, wrapper, notYetInitialized;
2005
2006 if ( !editable )
2007 return;
2008
2009 // Remove widgets which have no corresponding elements in DOM.
2010 for ( i in instances ) {
2011 // #13410 Remove widgets that are ready. This prevents from destroying widgets that are during loading process.
2012 if ( instances[ i ].isReady() && !editable.contains( instances[ i ].wrapper ) )
2013 this.destroy( instances[ i ], true );
2014 }
2015
2016 // Init on all (new) if initOnlyNew option was passed.
2017 if ( options && options.initOnlyNew )
2018 newInstances = this.initOnAll();
2019 else {
2020 var wrappers = editable.find( '.cke_widget_wrapper' );
2021 newInstances = [];
2022
2023 // Create widgets on existing wrappers if they do not exists.
2024 for ( i = 0, count = wrappers.count(); i < count; i++ ) {
2025 wrapper = wrappers.getItem( i );
2026 notYetInitialized = !this.getByElement( wrapper, true );
2027
2028 // Check if:
2029 // * there's no instance for this widget
2030 // * wrapper is not inside some temporary element like copybin (#11088)
2031 // * it was a nested widget's wrapper which has been detached from DOM,
2032 // when nested editable has been initialized (it overwrites its innerHTML
2033 // and initializes nested widgets).
2034 if ( notYetInitialized && !findParent( wrapper, isDomTemp ) && editable.contains( wrapper ) ) {
2035 // Add cke_widget_new class because otherwise
2036 // widget will not be created on such wrapper.
2037 wrapper.addClass( 'cke_widget_new' );
2038 newInstances.push( this.initOn( wrapper.getFirst( Widget.isDomWidgetElement ) ) );
2039 }
2040 }
2041 }
2042
2043 // If only single widget was initialized and focusInited was passed, focus it.
2044 if ( options && options.focusInited && newInstances.length == 1 )
2045 newInstances[ 0 ].focus();
2046 }
2047
2048 // Unwraps widget element and clean up element.
2049 //
2050 // This function is used to clean up pasted widgets.
2051 // It should have similar result to widget#destroy plus
2052 // some additional adjustments, specific for pasting.
2053 //
2054 // @param {CKEDITOR.htmlParser.element} el
2055 function cleanUpWidgetElement( el ) {
2056 var parent = el.parent;
2057 if ( parent.type == CKEDITOR.NODE_ELEMENT && parent.attributes[ 'data-cke-widget-wrapper' ] )
2058 parent.replaceWith( el );
2059 }
2060
2061 // Similar to cleanUpWidgetElement, but works on DOM and finds
2062 // widget elements by its own.
2063 //
2064 // Unlike cleanUpWidgetElement it will wrap element back.
2065 //
2066 // @param {CKEDITOR.dom.element} container
2067 function cleanUpAllWidgetElements( widgetsRepo, container ) {
2068 var wrappers = container.find( '.cke_widget_wrapper' ),
2069 wrapper, element,
2070 i = 0,
2071 l = wrappers.count();
2072
2073 for ( ; i < l; ++i ) {
2074 wrapper = wrappers.getItem( i );
2075 element = wrapper.getFirst( Widget.isDomWidgetElement );
2076 // If wrapper contains widget element - unwrap it and wrap again.
2077 if ( element.type == CKEDITOR.NODE_ELEMENT && element.data( 'widget' ) ) {
2078 element.replace( wrapper );
2079 widgetsRepo.wrapElement( element );
2080 } else {
2081 // Otherwise - something is wrong... clean this up.
2082 wrapper.remove();
2083 }
2084 }
2085 }
2086
2087 // Creates {@link CKEDITOR.filter} instance for given widget, editable and rules.
2088 //
2089 // Once filter for widget-editable pair is created it is cached, so the same instance
2090 // will be returned when method is executed again.
2091 //
2092 // @param {String} widgetName
2093 // @param {String} editableName
2094 // @param {CKEDITOR.plugins.widget.nestedEditableDefinition} editableDefinition The nested editable definition.
2095 // @returns {CKEDITOR.filter} Filter instance or `null` if rules are not defined.
2096 // @context CKEDITOR.plugins.widget.repository
2097 function createEditableFilter( widgetName, editableName, editableDefinition ) {
2098 if ( !editableDefinition.allowedContent )
2099 return null;
2100
2101 var editables = this._.filters[ widgetName ];
2102
2103 if ( !editables )
2104 this._.filters[ widgetName ] = editables = {};
2105
2106 var filter = editables[ editableName ];
2107
2108 if ( !filter )
2109 editables[ editableName ] = filter = new CKEDITOR.filter( editableDefinition.allowedContent );
2110
2111 return filter;
2112 }
2113
2114 // Creates an iterator function which when executed on all
2115 // elements in DOM tree will gather elements that should be wrapped
2116 // and initialized as widgets.
2117 function createUpcastIterator( widgetsRepo ) {
2118 var toBeWrapped = [],
2119 upcasts = widgetsRepo._.upcasts,
2120 upcastCallbacks = widgetsRepo._.upcastCallbacks;
2121
2122 return {
2123 toBeWrapped: toBeWrapped,
2124
2125 iterator: function( element ) {
2126 var upcast, upcasted,
2127 data,
2128 i,
2129 upcastsLength,
2130 upcastCallbacksLength;
2131
2132 // Wrapper found - find widget element, add it to be
2133 // cleaned up (unwrapped) and wrapped and stop iterating in this branch.
2134 if ( 'data-cke-widget-wrapper' in element.attributes ) {
2135 element = element.getFirst( Widget.isParserWidgetElement );
2136
2137 if ( element )
2138 toBeWrapped.push( [ element ] );
2139
2140 // Do not iterate over descendants.
2141 return false;
2142 }
2143 // Widget element found - add it to be cleaned up (just in case)
2144 // and wrapped and stop iterating in this branch.
2145 else if ( 'data-widget' in element.attributes ) {
2146 toBeWrapped.push( [ element ] );
2147
2148 // Do not iterate over descendants.
2149 return false;
2150 }
2151 else if ( ( upcastsLength = upcasts.length ) ) {
2152 // Ignore elements with data-cke-widget-upcasted to avoid multiple upcasts (#11533).
2153 // Do not iterate over descendants.
2154 if ( element.attributes[ 'data-cke-widget-upcasted' ] )
2155 return false;
2156
2157 // Check element with upcast callbacks first.
2158 // If any of them return false abort upcasting.
2159 for ( i = 0, upcastCallbacksLength = upcastCallbacks.length; i < upcastCallbacksLength; ++i ) {
2160 if ( upcastCallbacks[ i ]( element ) === false )
2161 return;
2162 // Return nothing in order to continue iterating over ascendants.
2163 // See http://dev.ckeditor.com/ticket/11186#comment:6
2164 }
2165
2166 for ( i = 0; i < upcastsLength; ++i ) {
2167 upcast = upcasts[ i ];
2168 data = {};
2169
2170 if ( ( upcasted = upcast[ 0 ]( element, data ) ) ) {
2171 // If upcast function returned element, upcast this one.
2172 // It can be e.g. a new element wrapping the original one.
2173 if ( upcasted instanceof CKEDITOR.htmlParser.element )
2174 element = upcasted;
2175
2176 // Set initial data attr with data from upcast method.
2177 element.attributes[ 'data-cke-widget-data' ] = encodeURIComponent( JSON.stringify( data ) );
2178 element.attributes[ 'data-cke-widget-upcasted' ] = 1;
2179
2180 toBeWrapped.push( [ element, upcast[ 1 ] ] );
2181
2182 // Do not iterate over descendants.
2183 return false;
2184 }
2185 }
2186 }
2187 }
2188 };
2189 }
2190
2191 // Finds a first parent that matches query.
2192 //
2193 // @param {CKEDITOR.dom.element} element
2194 // @param {Function} query
2195 function findParent( element, query ) {
2196 var parent = element;
2197
2198 while ( ( parent = parent.getParent() ) ) {
2199 if ( query( parent ) )
2200 return true;
2201 }
2202 return false;
2203 }
2204
2205 function getWrapperAttributes( inlineWidget, name ) {
2206 return {
2207 // tabindex="-1" means that it can receive focus by code.
2208 tabindex: -1,
2209 contenteditable: 'false',
2210 'data-cke-widget-wrapper': 1,
2211 'data-cke-filter': 'off',
2212 // Class cke_widget_new marks widgets which haven't been initialized yet.
2213 'class': 'cke_widget_wrapper cke_widget_new cke_widget_' +
2214 ( inlineWidget ? 'inline' : 'block' ) +
2215 ( name ? ' cke_widget_' + name : '' )
2216 };
2217 }
2218
2219 // Inserts element at given index.
2220 // It will check DTD and split ancestor elements up to the first
2221 // that can contain this element.
2222 //
2223 // @param {CKEDITOR.htmlParser.element} parent
2224 // @param {Number} index
2225 // @param {CKEDITOR.htmlParser.element} element
2226 function insertElement( parent, index, element ) {
2227 // Do not split doc fragment...
2228 if ( parent.type == CKEDITOR.NODE_ELEMENT ) {
2229 var parentAllows = CKEDITOR.dtd[ parent.name ];
2230 // Parent element is known (included in DTD) and cannot contain
2231 // this element.
2232 if ( parentAllows && !parentAllows[ element.name ] ) {
2233 var parent2 = parent.split( index ),
2234 parentParent = parent.parent;
2235
2236 // Element will now be inserted at right parent's index.
2237 index = parent2.getIndex();
2238
2239 // If left part of split is empty - remove it.
2240 if ( !parent.children.length ) {
2241 index -= 1;
2242 parent.remove();
2243 }
2244
2245 // If right part of split is empty - remove it.
2246 if ( !parent2.children.length )
2247 parent2.remove();
2248
2249 // Try inserting as grandpas' children.
2250 return insertElement( parentParent, index, element );
2251 }
2252 }
2253
2254 // Finally we can add this element.
2255 parent.add( element, index );
2256 }
2257
2258 // Checks whether for the given widget definition and element widget should be created in inline or block mode.
2259 //
2260 // See also: {@link CKEDITOR.plugins.widget.definition#inline} and {@link CKEDITOR.plugins.widget#element}.
2261 //
2262 // @param {CKEDITOR.plugins.widget.definition} widgetDef The widget definition.
2263 // @param {String} elementName The name of the widget element.
2264 // @returns {Boolean}
2265 function isWidgetInline( widgetDef, elementName ) {
2266 return typeof widgetDef.inline == 'boolean' ? widgetDef.inline : !!CKEDITOR.dtd.$inline[ elementName ];
2267 }
2268
2269 // @param {CKEDITOR.dom.element}
2270 // @returns {Boolean}
2271 function isDomTemp( element ) {
2272 return element.hasAttribute( 'data-cke-temp' );
2273 }
2274
2275 function onEditableKey( widget, keyCode ) {
2276 var focusedEditable = widget.focusedEditable,
2277 range;
2278
2279 // CTRL+A.
2280 if ( keyCode == CKEDITOR.CTRL + 65 ) {
2281 var bogus = focusedEditable.getBogus();
2282
2283 range = widget.editor.createRange();
2284 range.selectNodeContents( focusedEditable );
2285 // Exclude bogus if exists.
2286 if ( bogus )
2287 range.setEndAt( bogus, CKEDITOR.POSITION_BEFORE_START );
2288
2289 range.select();
2290 // Cancel event - block default.
2291 return false;
2292 }
2293 // DEL or BACKSPACE.
2294 else if ( keyCode == 8 || keyCode == 46 ) {
2295 var ranges = widget.editor.getSelection().getRanges();
2296
2297 range = ranges[ 0 ];
2298
2299 // Block del or backspace if at editable's boundary.
2300 return !( ranges.length == 1 && range.collapsed &&
2301 range.checkBoundaryOfElement( focusedEditable, CKEDITOR[ keyCode == 8 ? 'START' : 'END' ] ) );
2302 }
2303 }
2304
2305 function setFocusedEditable( widgetsRepo, widget, editableElement, offline ) {
2306 var editor = widgetsRepo.editor;
2307
2308 editor.fire( 'lockSnapshot' );
2309
2310 if ( editableElement ) {
2311 var editableName = editableElement.data( 'cke-widget-editable' ),
2312 editableInstance = widget.editables[ editableName ];
2313
2314 widgetsRepo.widgetHoldingFocusedEditable = widget;
2315 widget.focusedEditable = editableInstance;
2316 editableElement.addClass( 'cke_widget_editable_focused' );
2317
2318 if ( editableInstance.filter )
2319 editor.setActiveFilter( editableInstance.filter );
2320 editor.setActiveEnterMode( editableInstance.enterMode, editableInstance.shiftEnterMode );
2321 } else {
2322 if ( !offline )
2323 widget.focusedEditable.removeClass( 'cke_widget_editable_focused' );
2324
2325 widget.focusedEditable = null;
2326 widgetsRepo.widgetHoldingFocusedEditable = null;
2327 editor.setActiveFilter( null );
2328 editor.setActiveEnterMode( null, null );
2329 }
2330
2331 editor.fire( 'unlockSnapshot' );
2332 }
2333
2334 function setupContextMenu( editor ) {
2335 if ( !editor.contextMenu )
2336 return;
2337
2338 editor.contextMenu.addListener( function( element ) {
2339 var widget = editor.widgets.getByElement( element, true );
2340
2341 if ( widget )
2342 return widget.fire( 'contextMenu', {} );
2343 } );
2344 }
2345
2346 // And now we've got two problems - original problem and RegExp.
2347 // Some softeners:
2348 // * FF tends to copy all blocks up to the copybin container.
2349 // * IE tends to copy only the copybin, without its container.
2350 // * We use spans on IE and blockless editors, but divs in other cases.
2351 var pasteReplaceRegex = new RegExp(
2352 '^' +
2353 '(?:<(?:div|span)(?: data-cke-temp="1")?(?: id="cke_copybin")?(?: data-cke-temp="1")?>)?' +
2354 '(?:<(?:div|span)(?: style="[^"]+")?>)?' +
2355 '<span [^>]*data-cke-copybin-start="1"[^>]*>.?</span>([\\s\\S]+)<span [^>]*data-cke-copybin-end="1"[^>]*>.?</span>' +
2356 '(?:</(?:div|span)>)?' +
2357 '(?:</(?:div|span)>)?' +
2358 '$',
2359 // IE8 prefers uppercase when browsers stick to lowercase HTML (#13460).
2360 'i'
2361 );
2362
2363 function pasteReplaceFn( match, wrapperHtml ) {
2364 // Avoid polluting pasted data with any whitspaces,
2365 // what's going to break check whether only one widget was pasted.
2366 return CKEDITOR.tools.trim( wrapperHtml );
2367 }
2368
2369 function setupDragAndDrop( widgetsRepo ) {
2370 var editor = widgetsRepo.editor,
2371 lineutils = CKEDITOR.plugins.lineutils;
2372
2373 // These listeners handle inline and block widgets drag and drop.
2374 // The only thing we need to do to make block widgets custom drag and drop functionality
2375 // is to fire those events with the right properties (like the target which must be the drag handle).
2376 editor.on( 'dragstart', function( evt ) {
2377 var target = evt.data.target;
2378
2379 if ( Widget.isDomDragHandler( target ) ) {
2380 var widget = widgetsRepo.getByElement( target );
2381
2382 evt.data.dataTransfer.setData( 'cke/widget-id', widget.id );
2383
2384 // IE needs focus.
2385 editor.focus();
2386
2387 // and widget need to be focused on drag start (#12172#comment:10).
2388 widget.focus();
2389 }
2390 } );
2391
2392 editor.on( 'drop', function( evt ) {
2393 var dataTransfer = evt.data.dataTransfer,
2394 id = dataTransfer.getData( 'cke/widget-id' ),
2395 transferType = dataTransfer.getTransferType( editor ),
2396 dragRange = editor.createRange(),
2397 sourceWidget;
2398
2399 // Disable cross-editor drag & drop for widgets - #13599.
2400 if ( id !== '' && transferType === CKEDITOR.DATA_TRANSFER_CROSS_EDITORS ) {
2401 evt.cancel();
2402 return;
2403 }
2404
2405 if ( id === '' || transferType != CKEDITOR.DATA_TRANSFER_INTERNAL ) {
2406 return;
2407 }
2408
2409 sourceWidget = widgetsRepo.instances[ id ];
2410 if ( !sourceWidget ) {
2411 return;
2412 }
2413
2414 dragRange.setStartBefore( sourceWidget.wrapper );
2415 dragRange.setEndAfter( sourceWidget.wrapper );
2416 evt.data.dragRange = dragRange;
2417
2418 // [IE8-9] Reset state of the clipboard#fixSplitNodesAfterDrop fix because by setting evt.data.dragRange
2419 // (see above) after drop happened we do not need it. That fix is needed only if dragRange was created
2420 // before drop (before text node was split).
2421 delete CKEDITOR.plugins.clipboard.dragStartContainerChildCount;
2422 delete CKEDITOR.plugins.clipboard.dragEndContainerChildCount;
2423
2424 evt.data.dataTransfer.setData( 'text/html', editor.editable().getHtmlFromRange( dragRange ).getHtml() );
2425 editor.widgets.destroy( sourceWidget, true );
2426 } );
2427
2428 editor.on( 'contentDom', function() {
2429 var editable = editor.editable();
2430
2431 // Register Lineutils's utilities as properties of repo.
2432 CKEDITOR.tools.extend( widgetsRepo, {
2433 finder: new lineutils.finder( editor, {
2434 lookups: {
2435 // Element is block but not list item and not in nested editable.
2436 'default': function( el ) {
2437 if ( el.is( CKEDITOR.dtd.$listItem ) )
2438 return;
2439
2440 if ( !el.is( CKEDITOR.dtd.$block ) )
2441 return;
2442
2443 // Allow drop line inside, but never before or after nested editable (#12006).
2444 if ( Widget.isDomNestedEditable( el ) )
2445 return;
2446
2447 // Do not allow droping inside the widget being dragged (#13397).
2448 if ( widgetsRepo._.draggedWidget.wrapper.contains( el ) ) {
2449 return;
2450 }
2451
2452 // If element is nested editable, make sure widget can be dropped there (#12006).
2453 var nestedEditable = Widget.getNestedEditable( editable, el );
2454 if ( nestedEditable ) {
2455 var draggedWidget = widgetsRepo._.draggedWidget;
2456
2457 // Don't let the widget to be dropped into its own nested editable.
2458 if ( widgetsRepo.getByElement( nestedEditable ) == draggedWidget )
2459 return;
2460
2461 var filter = CKEDITOR.filter.instances[ nestedEditable.data( 'cke-filter' ) ],
2462 draggedRequiredContent = draggedWidget.requiredContent;
2463
2464 // There will be no relation if the filter of nested editable does not allow
2465 // requiredContent of dragged widget.
2466 if ( filter && draggedRequiredContent && !filter.check( draggedRequiredContent ) )
2467 return;
2468 }
2469
2470 return CKEDITOR.LINEUTILS_BEFORE | CKEDITOR.LINEUTILS_AFTER;
2471 }
2472 }
2473 } ),
2474 locator: new lineutils.locator( editor ),
2475 liner: new lineutils.liner( editor, {
2476 lineStyle: {
2477 cursor: 'move !important',
2478 'border-top-color': '#666'
2479 },
2480 tipLeftStyle: {
2481 'border-left-color': '#666'
2482 },
2483 tipRightStyle: {
2484 'border-right-color': '#666'
2485 }
2486 } )
2487 }, true );
2488 } );
2489 }
2490
2491 // Setup mouse observer which will trigger:
2492 // * widget focus on widget click,
2493 // * widget#doubleclick forwarded from editor#doubleclick.
2494 function setupMouseObserver( widgetsRepo ) {
2495 var editor = widgetsRepo.editor;
2496
2497 editor.on( 'contentDom', function() {
2498 var editable = editor.editable(),
2499 evtRoot = editable.isInline() ? editable : editor.document,
2500 widget,
2501 mouseDownOnDragHandler;
2502
2503 editable.attachListener( evtRoot, 'mousedown', function( evt ) {
2504 var target = evt.data.getTarget();
2505
2506 // #10887 Clicking scrollbar in IE8 will invoke event with empty target object.
2507 if ( !target.type )
2508 return false;
2509
2510 widget = widgetsRepo.getByElement( target );
2511 mouseDownOnDragHandler = 0; // Reset.
2512
2513 // Widget was clicked, but not editable nested in it.
2514 if ( widget ) {
2515 // Ignore mousedown on drag and drop handler if the widget is inline.
2516 // Block widgets are handled by Lineutils.
2517 if ( widget.inline && target.type == CKEDITOR.NODE_ELEMENT && target.hasAttribute( 'data-cke-widget-drag-handler' ) ) {
2518 mouseDownOnDragHandler = 1;
2519
2520 // When drag handler is pressed we have to clear current selection if it wasn't already on this widget.
2521 // Otherwise, the selection may be in a fillingChar, which prevents dragging a widget. (#13284, see comment 8 and 9.)
2522 if ( widgetsRepo.focused != widget )
2523 editor.getSelection().removeAllRanges();
2524
2525 return;
2526 }
2527
2528 if ( !Widget.getNestedEditable( widget.wrapper, target ) ) {
2529 evt.data.preventDefault();
2530 if ( !CKEDITOR.env.ie )
2531 widget.focus();
2532 } else {
2533 // Reset widget so mouseup listener is not confused.
2534 widget = null;
2535 }
2536 }
2537 } );
2538
2539 // Focus widget on mouseup if mousedown was fired on drag handler.
2540 // Note: mouseup won't be fired at all if widget was dragged and dropped, so
2541 // this code will be executed only when drag handler was clicked.
2542 editable.attachListener( evtRoot, 'mouseup', function() {
2543 // Check if widget is not destroyed (if widget is destroyed the wrapper will be null).
2544 if ( mouseDownOnDragHandler && widget && widget.wrapper ) {
2545 mouseDownOnDragHandler = 0;
2546 widget.focus();
2547 }
2548 } );
2549
2550 // On IE it is not enough to block mousedown. If widget wrapper (element with
2551 // contenteditable=false attribute) is clicked directly (it is a target),
2552 // then after mouseup/click IE will select that element.
2553 // It is not possible to prevent that default action,
2554 // so we force fake selection after everything happened.
2555 if ( CKEDITOR.env.ie ) {
2556 editable.attachListener( evtRoot, 'mouseup', function() {
2557 setTimeout( function() {
2558 // Check if widget is not destroyed (if widget is destroyed the wrapper will be null) and
2559 // in editable contains widget (it could be dragged and removed).
2560 if ( widget && widget.wrapper && editable.contains( widget.wrapper ) ) {
2561 widget.focus();
2562 widget = null;
2563 }
2564 } );
2565 } );
2566 }
2567 } );
2568
2569 editor.on( 'doubleclick', function( evt ) {
2570 var widget = widgetsRepo.getByElement( evt.data.element );
2571
2572 // Not in widget or in nested editable.
2573 if ( !widget || Widget.getNestedEditable( widget.wrapper, evt.data.element ) )
2574 return;
2575
2576 return widget.fire( 'doubleclick', { element: evt.data.element } );
2577 }, null, null, 1 );
2578 }
2579
2580 // Setup editor#key observer which will forward it
2581 // to focused widget.
2582 function setupKeyboardObserver( widgetsRepo ) {
2583 var editor = widgetsRepo.editor;
2584
2585 editor.on( 'key', function( evt ) {
2586 var focused = widgetsRepo.focused,
2587 widgetHoldingFocusedEditable = widgetsRepo.widgetHoldingFocusedEditable,
2588 ret;
2589
2590 if ( focused )
2591 ret = focused.fire( 'key', { keyCode: evt.data.keyCode } );
2592 else if ( widgetHoldingFocusedEditable )
2593 ret = onEditableKey( widgetHoldingFocusedEditable, evt.data.keyCode );
2594
2595 return ret;
2596 }, null, null, 1 );
2597 }
2598
2599 // Setup copybin on native copy and cut events in order to handle copy and cut commands
2600 // if user accepted security alert on IEs.
2601 // Note: when copying or cutting using keystroke, copySingleWidget will be first executed
2602 // by the keydown listener. Conflict between two calls will be resolved by copy_bin existence check.
2603 function setupNativeCutAndCopy( widgetsRepo ) {
2604 var editor = widgetsRepo.editor;
2605
2606 editor.on( 'contentDom', function() {
2607 var editable = editor.editable();
2608
2609 editable.attachListener( editable, 'copy', eventListener );
2610 editable.attachListener( editable, 'cut', eventListener );
2611 } );
2612
2613 function eventListener( evt ) {
2614 if ( widgetsRepo.focused )
2615 copySingleWidget( widgetsRepo.focused, evt.name == 'cut' );
2616 }
2617 }
2618
2619 // Setup selection observer which will trigger:
2620 // * widget select & focus on selection change,
2621 // * nested editable focus (related properites and classes) on selection change,
2622 // * deselecting and blurring all widgets on data,
2623 // * blurring widget on editor blur.
2624 function setupSelectionObserver( widgetsRepo ) {
2625 var editor = widgetsRepo.editor;
2626
2627 editor.on( 'selectionCheck', function() {
2628 widgetsRepo.fire( 'checkSelection' );
2629 } );
2630
2631 widgetsRepo.on( 'checkSelection', widgetsRepo.checkSelection, widgetsRepo );
2632
2633 editor.on( 'selectionChange', function( evt ) {
2634 var nestedEditable = Widget.getNestedEditable( editor.editable(), evt.data.selection.getStartElement() ),
2635 newWidget = nestedEditable && widgetsRepo.getByElement( nestedEditable ),
2636 oldWidget = widgetsRepo.widgetHoldingFocusedEditable;
2637
2638 if ( oldWidget ) {
2639 if ( oldWidget !== newWidget || !oldWidget.focusedEditable.equals( nestedEditable ) ) {
2640 setFocusedEditable( widgetsRepo, oldWidget, null );
2641
2642 if ( newWidget && nestedEditable )
2643 setFocusedEditable( widgetsRepo, newWidget, nestedEditable );
2644 }
2645 }
2646 // It may happen that there's no widget even if editable was found -
2647 // e.g. if selection was automatically set in editable although widget wasn't initialized yet.
2648 else if ( newWidget && nestedEditable ) {
2649 setFocusedEditable( widgetsRepo, newWidget, nestedEditable );
2650 }
2651 } );
2652
2653 // Invalidate old widgets early - immediately on dataReady.
2654 editor.on( 'dataReady', function() {
2655 // Deselect and blur all widgets.
2656 stateUpdater( widgetsRepo ).commit();
2657 } );
2658
2659 editor.on( 'blur', function() {
2660 var widget;
2661
2662 if ( ( widget = widgetsRepo.focused ) )
2663 blurWidget( widgetsRepo, widget );
2664
2665 if ( ( widget = widgetsRepo.widgetHoldingFocusedEditable ) )
2666 setFocusedEditable( widgetsRepo, widget, null );
2667 } );
2668 }
2669
2670 // Set up actions like:
2671 // * processing in toHtml/toDataFormat,
2672 // * pasting handling,
2673 // * insertion handling,
2674 // * editable reload handling (setData, mode switch, undo/redo),
2675 // * DOM invalidation handling,
2676 // * widgets checks.
2677 function setupWidgetsLifecycle( widgetsRepo ) {
2678 setupWidgetsLifecycleStart( widgetsRepo );
2679 setupWidgetsLifecycleEnd( widgetsRepo );
2680
2681 widgetsRepo.on( 'checkWidgets', checkWidgets );
2682 widgetsRepo.editor.on( 'contentDomInvalidated', widgetsRepo.checkWidgets, widgetsRepo );
2683 }
2684
2685 function setupWidgetsLifecycleEnd( widgetsRepo ) {
2686 var editor = widgetsRepo.editor,
2687 downcastingSessions = {};
2688
2689 // Listen before htmlDP#htmlFilter is applied to cache all widgets, because we'll
2690 // loose data-cke-* attributes.
2691 editor.on( 'toDataFormat', function( evt ) {
2692 // To avoid conflicts between htmlDP#toDF calls done at the same time
2693 // (e.g. nestedEditable#getData called during downcasting some widget)
2694 // mark every toDataFormat event chain with the downcasting session id.
2695 var id = CKEDITOR.tools.getNextNumber(),
2696 toBeDowncasted = [];
2697 evt.data.downcastingSessionId = id;
2698 downcastingSessions[ id ] = toBeDowncasted;
2699
2700 evt.data.dataValue.forEach( function( element ) {
2701 var attrs = element.attributes,
2702 widget, widgetElement;
2703
2704 // Wrapper.
2705 // Perform first part of downcasting (cleanup) and cache widgets,
2706 // because after applying DP's filter all data-cke-* attributes will be gone.
2707 if ( 'data-cke-widget-id' in attrs ) {
2708 widget = widgetsRepo.instances[ attrs[ 'data-cke-widget-id' ] ];
2709 if ( widget ) {
2710 widgetElement = element.getFirst( Widget.isParserWidgetElement );
2711 toBeDowncasted.push( {
2712 wrapper: element,
2713 element: widgetElement,
2714 widget: widget,
2715 editables: {}
2716 } );
2717
2718 // If widget did not have data-cke-widget attribute before upcasting remove it.
2719 if ( widgetElement.attributes[ 'data-cke-widget-keep-attr' ] != '1' )
2720 delete widgetElement.attributes[ 'data-widget' ];
2721 }
2722 }
2723 // Nested editable.
2724 else if ( 'data-cke-widget-editable' in attrs ) {
2725 // Save the reference to this nested editable in the closest widget to be downcasted.
2726 // Nested editables are downcasted in the successive toDataFormat to create an opportunity
2727 // for dataFilter's "excludeNestedEditable" option to do its job (that option relies on
2728 // contenteditable="true" attribute) (#11372).
2729 toBeDowncasted[ toBeDowncasted.length - 1 ].editables[ attrs[ 'data-cke-widget-editable' ] ] = element;
2730
2731 // Don't check children - there won't be next wrapper or nested editable which we
2732 // should process in this session.
2733 return false;
2734 }
2735 }, CKEDITOR.NODE_ELEMENT, true );
2736 }, null, null, 8 );
2737
2738 // Listen after dataProcessor.htmlFilter and ACF were applied
2739 // so wrappers securing widgets' contents are removed after all filtering was done.
2740 editor.on( 'toDataFormat', function( evt ) {
2741 // Ignore some unmarked sessions.
2742 if ( !evt.data.downcastingSessionId )
2743 return;
2744
2745 var toBeDowncasted = downcastingSessions[ evt.data.downcastingSessionId ],
2746 toBe, widget, widgetElement, retElement, editableElement, e;
2747
2748 while ( ( toBe = toBeDowncasted.shift() ) ) {
2749 widget = toBe.widget;
2750 widgetElement = toBe.element;
2751 retElement = widget._.downcastFn && widget._.downcastFn.call( widget, widgetElement );
2752
2753 // Replace nested editables' content with their output data.
2754 for ( e in toBe.editables ) {
2755 editableElement = toBe.editables[ e ];
2756
2757 delete editableElement.attributes.contenteditable;
2758 editableElement.setHtml( widget.editables[ e ].getData() );
2759 }
2760
2761 // Returned element always defaults to widgetElement.
2762 if ( !retElement )
2763 retElement = widgetElement;
2764
2765 toBe.wrapper.replaceWith( retElement );
2766 }
2767 }, null, null, 13 );
2768
2769
2770 editor.on( 'contentDomUnload', function() {
2771 widgetsRepo.destroyAll( true );
2772 } );
2773 }
2774
2775 function setupWidgetsLifecycleStart( widgetsRepo ) {
2776 var editor = widgetsRepo.editor,
2777 processedWidgetOnly,
2778 snapshotLoaded;
2779
2780 // Listen after ACF (so data are filtered),
2781 // but before dataProcessor.dataFilter was applied (so we can secure widgets' internals).
2782 editor.on( 'toHtml', function( evt ) {
2783 var upcastIterator = createUpcastIterator( widgetsRepo ),
2784 toBeWrapped;
2785
2786 evt.data.dataValue.forEach( upcastIterator.iterator, CKEDITOR.NODE_ELEMENT, true );
2787
2788 // Clean up and wrap all queued elements.
2789 while ( ( toBeWrapped = upcastIterator.toBeWrapped.pop() ) ) {
2790 cleanUpWidgetElement( toBeWrapped[ 0 ] );
2791 widgetsRepo.wrapElement( toBeWrapped[ 0 ], toBeWrapped[ 1 ] );
2792 }
2793
2794 // Used to determine whether only widget was pasted.
2795 if ( evt.data.protectedWhitespaces ) {
2796 // Whitespaces are protected by wrapping content with spans. Take the middle node only.
2797 processedWidgetOnly = evt.data.dataValue.children.length == 3 &&
2798 Widget.isParserWidgetWrapper( evt.data.dataValue.children[ 1 ] );
2799 } else {
2800 processedWidgetOnly = evt.data.dataValue.children.length == 1 &&
2801 Widget.isParserWidgetWrapper( evt.data.dataValue.children[ 0 ] );
2802 }
2803 }, null, null, 8 );
2804
2805 editor.on( 'dataReady', function() {
2806 // Clean up all widgets loaded from snapshot.
2807 if ( snapshotLoaded )
2808 cleanUpAllWidgetElements( widgetsRepo, editor.editable() );
2809 snapshotLoaded = 0;
2810
2811 // Some widgets were destroyed on contentDomUnload,
2812 // some on loadSnapshot, but that does not include
2813 // e.g. setHtml on inline editor or widgets removed just
2814 // before setting data.
2815 widgetsRepo.destroyAll( true );
2816 widgetsRepo.initOnAll();
2817 } );
2818
2819 // Set flag so dataReady will know that additional
2820 // cleanup is needed, because snapshot containing widgets was loaded.
2821 editor.on( 'loadSnapshot', function( evt ) {
2822 // Primitive but sufficient check which will prevent from executing
2823 // heavier cleanUpAllWidgetElements if not needed.
2824 if ( ( /data-cke-widget/ ).test( evt.data ) )
2825 snapshotLoaded = 1;
2826
2827 widgetsRepo.destroyAll( true );
2828 }, null, null, 9 );
2829
2830 // Handle pasted single widget.
2831 editor.on( 'paste', function( evt ) {
2832 var data = evt.data;
2833
2834 data.dataValue = data.dataValue.replace( pasteReplaceRegex, pasteReplaceFn );
2835
2836 // If drag'n'drop kind of paste into nested editable (data.range), selection is set AFTER
2837 // data is pasted, which means editor has no chance to change activeFilter's context.
2838 // As a result, pasted data is filtered with default editor's filter instead of NE's and
2839 // funny things get inserted. Changing the filter by analysis of the paste range below (#13186).
2840 if ( data.range ) {
2841 // Check if pasting into nested editable.
2842 var nestedEditable = Widget.getNestedEditable( editor.editable(), data.range.startContainer );
2843
2844 if ( nestedEditable ) {
2845 // Retrieve the filter from NE's data and set it active before editor.insertHtml is done
2846 // in clipboard plugin.
2847 var filter = CKEDITOR.filter.instances[ nestedEditable.data( 'cke-filter' ) ];
2848
2849 if ( filter ) {
2850 editor.setActiveFilter( filter );
2851 }
2852 }
2853 }
2854 } );
2855
2856 // Listen with high priority to check widgets after data was inserted.
2857 editor.on( 'afterInsertHtml', function( evt ) {
2858 if ( evt.data.intoRange ) {
2859 widgetsRepo.checkWidgets( { initOnlyNew: true } );
2860 } else {
2861 editor.fire( 'lockSnapshot' );
2862 // Init only new for performance reason.
2863 // Focus inited if only widget was processed.
2864 widgetsRepo.checkWidgets( { initOnlyNew: true, focusInited: processedWidgetOnly } );
2865
2866 editor.fire( 'unlockSnapshot' );
2867 }
2868 } );
2869 }
2870
2871 // Helper for coordinating which widgets should be
2872 // selected/deselected and which one should be focused/blurred.
2873 function stateUpdater( widgetsRepo ) {
2874 var currentlySelected = widgetsRepo.selected,
2875 toBeSelected = [],
2876 toBeDeselected = currentlySelected.slice( 0 ),
2877 focused = null;
2878
2879 return {
2880 select: function( widget ) {
2881 if ( CKEDITOR.tools.indexOf( currentlySelected, widget ) < 0 )
2882 toBeSelected.push( widget );
2883
2884 var index = CKEDITOR.tools.indexOf( toBeDeselected, widget );
2885 if ( index >= 0 )
2886 toBeDeselected.splice( index, 1 );
2887
2888 return this;
2889 },
2890
2891 focus: function( widget ) {
2892 focused = widget;
2893 return this;
2894 },
2895
2896 commit: function() {
2897 var focusedChanged = widgetsRepo.focused !== focused,
2898 widget, isDirty;
2899
2900 widgetsRepo.editor.fire( 'lockSnapshot' );
2901
2902 if ( focusedChanged && ( widget = widgetsRepo.focused ) )
2903 blurWidget( widgetsRepo, widget );
2904
2905 while ( ( widget = toBeDeselected.pop() ) ) {
2906 currentlySelected.splice( CKEDITOR.tools.indexOf( currentlySelected, widget ), 1 );
2907 // Widget could be destroyed in the meantime - e.g. data could be set.
2908 if ( widget.isInited() ) {
2909 isDirty = widget.editor.checkDirty();
2910
2911 widget.setSelected( false );
2912
2913 !isDirty && widget.editor.resetDirty();
2914 }
2915 }
2916
2917 if ( focusedChanged && focused ) {
2918 isDirty = widgetsRepo.editor.checkDirty();
2919
2920 widgetsRepo.focused = focused;
2921 widgetsRepo.fire( 'widgetFocused', { widget: focused } );
2922 focused.setFocused( true );
2923
2924 !isDirty && widgetsRepo.editor.resetDirty();
2925 }
2926
2927 while ( ( widget = toBeSelected.pop() ) ) {
2928 currentlySelected.push( widget );
2929 widget.setSelected( true );
2930 }
2931
2932 widgetsRepo.editor.fire( 'unlockSnapshot' );
2933 }
2934 };
2935 }
2936
2937
2938 //
2939 // WIDGET helpers ---------------------------------------------------------
2940 //
2941
2942 // LEFT, RIGHT, UP, DOWN, DEL, BACKSPACE - unblock default fake sel handlers.
2943 var keystrokesNotBlockedByWidget = { 37: 1, 38: 1, 39: 1, 40: 1, 8: 1, 46: 1 };
2944
2945 // Applies or removes style's classes from widget.
2946 // @param {CKEDITOR.style} style Custom widget style.
2947 // @param {Boolean} apply Whether to apply or remove style.
2948 function applyRemoveStyle( widget, style, apply ) {
2949 var changed = 0,
2950 classes = getStyleClasses( style ),
2951 updatedClasses = widget.data.classes || {},
2952 cl;
2953
2954 // Ee... Something is wrong with this style.
2955 if ( !classes )
2956 return;
2957
2958 // Clone, because we need to break reference.
2959 updatedClasses = CKEDITOR.tools.clone( updatedClasses );
2960
2961 while ( ( cl = classes.pop() ) ) {
2962 if ( apply ) {
2963 if ( !updatedClasses[ cl ] )
2964 changed = updatedClasses[ cl ] = 1;
2965 } else {
2966 if ( updatedClasses[ cl ] ) {
2967 delete updatedClasses[ cl ];
2968 changed = 1;
2969 }
2970 }
2971 }
2972 if ( changed )
2973 widget.setData( 'classes', updatedClasses );
2974 }
2975
2976 function cancel( evt ) {
2977 evt.cancel();
2978 }
2979
2980 function copySingleWidget( widget, isCut ) {
2981 var editor = widget.editor,
2982 doc = editor.document;
2983
2984 // We're still handling previous copy/cut.
2985 // When keystroke is used to copy/cut this will also prevent
2986 // conflict with copySingleWidget called again for native copy/cut event.
2987 if ( doc.getById( 'cke_copybin' ) )
2988 return;
2989
2990 // [IE] Use span for copybin and its container to avoid bug with expanding editable height by
2991 // absolutely positioned element.
2992 var copybinName = ( editor.blockless || CKEDITOR.env.ie ) ? 'span' : 'div',
2993 copybin = doc.createElement( copybinName ),
2994 copybinContainer = doc.createElement( copybinName ),
2995 // IE8 always jumps to the end of document.
2996 needsScrollHack = CKEDITOR.env.ie && CKEDITOR.env.version < 9;
2997
2998 copybinContainer.setAttributes( {
2999 id: 'cke_copybin',
3000 'data-cke-temp': '1'
3001 } );
3002
3003 // Position copybin element outside current viewport.
3004 copybin.setStyles( {
3005 position: 'absolute',
3006 width: '1px',
3007 height: '1px',
3008 overflow: 'hidden'
3009 } );
3010
3011 copybin.setStyle( editor.config.contentsLangDirection == 'ltr' ? 'left' : 'right', '-5000px' );
3012
3013 var range = editor.createRange();
3014 range.setStartBefore( widget.wrapper );
3015 range.setEndAfter( widget.wrapper );
3016
3017 copybin.setHtml(
3018 '<span data-cke-copybin-start="1">\u200b</span>' +
3019 editor.editable().getHtmlFromRange( range ).getHtml() +
3020 '<span data-cke-copybin-end="1">\u200b</span>' );
3021
3022 // Save snapshot with the current state.
3023 editor.fire( 'saveSnapshot' );
3024
3025 // Ignore copybin.
3026 editor.fire( 'lockSnapshot' );
3027
3028 copybinContainer.append( copybin );
3029 editor.editable().append( copybinContainer );
3030
3031 var listener1 = editor.on( 'selectionChange', cancel, null, null, 0 ),
3032 listener2 = widget.repository.on( 'checkSelection', cancel, null, null, 0 );
3033
3034 if ( needsScrollHack ) {
3035 var docElement = doc.getDocumentElement().$,
3036 scrollTop = docElement.scrollTop;
3037 }
3038
3039 // Once the clone of the widget is inside of copybin, select
3040 // the entire contents. This selection will be copied by the
3041 // native browser's clipboard system.
3042 range = editor.createRange();
3043 range.selectNodeContents( copybin );
3044 range.select();
3045
3046 if ( needsScrollHack )
3047 docElement.scrollTop = scrollTop;
3048
3049 setTimeout( function() {
3050 // [IE] Focus widget before removing copybin to avoid scroll jump.
3051 if ( !isCut )
3052 widget.focus();
3053
3054 copybinContainer.remove();
3055
3056 listener1.removeListener();
3057 listener2.removeListener();
3058
3059 editor.fire( 'unlockSnapshot' );
3060
3061 if ( isCut ) {
3062 widget.repository.del( widget );
3063 editor.fire( 'saveSnapshot' );
3064 }
3065 }, 100 ); // Use 100ms, so Chrome (@Mac) will be able to grab the content.
3066 }
3067
3068 // Extracts classes array from style instance.
3069 function getStyleClasses( style ) {
3070 var attrs = style.getDefinition().attributes,
3071 classes = attrs && attrs[ 'class' ];
3072
3073 return classes ? classes.split( /\s+/ ) : null;
3074 }
3075
3076 // [IE] Force keeping focus because IE sometimes forgets to fire focus on main editable
3077 // when blurring nested editable.
3078 // @context widget
3079 function onEditableBlur() {
3080 var active = CKEDITOR.document.getActive(),
3081 editor = this.editor,
3082 editable = editor.editable();
3083
3084 // If focus stays within editor override blur and set currentActive because it should be
3085 // automatically changed to editable on editable#focus but it is not fired.
3086 if ( ( editable.isInline() ? editable : editor.document.getWindow().getFrame() ).equals( active ) )
3087 editor.focusManager.focus( editable );
3088 }
3089
3090 // Force selectionChange when editable was focused.
3091 // Similar to hack in selection.js#~620.
3092 // @context widget
3093 function onEditableFocus() {
3094 // Gecko does not support 'DOMFocusIn' event on which we unlock selection
3095 // in selection.js to prevent selection locking when entering nested editables.
3096 if ( CKEDITOR.env.gecko )
3097 this.editor.unlockSelection();
3098
3099 // We don't need to force selectionCheck on Webkit, because on Webkit
3100 // we do that on DOMFocusIn in selection.js.
3101 if ( !CKEDITOR.env.webkit ) {
3102 this.editor.forceNextSelectionCheck();
3103 this.editor.selectionChange( 1 );
3104 }
3105 }
3106
3107 // Setup listener on widget#data which will update (remove/add) classes
3108 // by comparing newly set classes with the old ones.
3109 function setupDataClassesListener( widget ) {
3110 // Note: previousClasses and newClasses may be null!
3111 // Tip: for ( cl in null ) is correct.
3112 var previousClasses = null;
3113
3114 widget.on( 'data', function() {
3115 var newClasses = this.data.classes,
3116 cl;
3117
3118 // When setting new classes one need to remember
3119 // that he must break reference.
3120 if ( previousClasses == newClasses )
3121 return;
3122
3123 for ( cl in previousClasses ) {
3124 // Avoid removing and adding classes again.
3125 if ( !( newClasses && newClasses[ cl ] ) )
3126 this.removeClass( cl );
3127 }
3128 for ( cl in newClasses )
3129 this.addClass( cl );
3130
3131 previousClasses = newClasses;
3132 } );
3133 }
3134
3135 // Add a listener to data event that will set/change widget's label (#14539).
3136 function setupA11yListener( widget ) {
3137 // Note, the function gets executed in a context of widget instance.
3138 function getLabelDefault() {
3139 return this.editor.lang.widget.label.replace( /%1/, this.pathName || this.element.getName() );
3140 }
3141
3142 // Setting a listener on data is enough, there's no need to perform it on widget initialization, as
3143 // setupWidgetData fires this event anyway.
3144 widget.on( 'data', function() {
3145 // In some cases widget might get destroyed in an earlier data listener. For instance, image2 plugin, does
3146 // so when changing its internal state.
3147 if ( !widget.wrapper ) {
3148 return;
3149 }
3150
3151 var label = this.getLabel ? this.getLabel() : getLabelDefault.call( this );
3152
3153 widget.wrapper.setAttribute( 'role', 'region' );
3154 widget.wrapper.setAttribute( 'aria-label', label );
3155 }, null, null, 9999 );
3156 }
3157
3158 function setupDragHandler( widget ) {
3159 if ( !widget.draggable )
3160 return;
3161
3162 var editor = widget.editor,
3163 // Use getLast to find wrapper's direct descendant (#12022).
3164 container = widget.wrapper.getLast( Widget.isDomDragHandlerContainer ),
3165 img;
3166
3167 // Reuse drag handler if already exists (#11281).
3168 if ( container )
3169 img = container.findOne( 'img' );
3170 else {
3171 container = new CKEDITOR.dom.element( 'span', editor.document );
3172 container.setAttributes( {
3173 'class': 'cke_reset cke_widget_drag_handler_container',
3174 // Split background and background-image for IE8 which will break on rgba().
3175 style: 'background:rgba(220,220,220,0.5);background-image:url(' + editor.plugins.widget.path + 'images/handle.png)'
3176 } );
3177
3178 img = new CKEDITOR.dom.element( 'img', editor.document );
3179 img.setAttributes( {
3180 'class': 'cke_reset cke_widget_drag_handler',
3181 'data-cke-widget-drag-handler': '1',
3182 src: CKEDITOR.tools.transparentImageData,
3183 width: DRAG_HANDLER_SIZE,
3184 title: editor.lang.widget.move,
3185 height: DRAG_HANDLER_SIZE,
3186 role: 'presentation'
3187 } );
3188 widget.inline && img.setAttribute( 'draggable', 'true' );
3189
3190 container.append( img );
3191 widget.wrapper.append( container );
3192 }
3193
3194 // Preventing page reload when dropped content on widget wrapper (#13015).
3195 // Widget is not editable so by default drop on it isn't allowed what means that
3196 // browser handles it (there's no editable#drop event). If there's no drop event we cannot block
3197 // the drop, so page is reloaded. This listener enables drop on widget wrappers.
3198 widget.wrapper.on( 'dragover', function( evt ) {
3199 evt.data.preventDefault();
3200 } );
3201
3202 widget.wrapper.on( 'mouseenter', widget.updateDragHandlerPosition, widget );
3203 setTimeout( function() {
3204 widget.on( 'data', widget.updateDragHandlerPosition, widget );
3205 }, 50 );
3206
3207 if ( !widget.inline ) {
3208 img.on( 'mousedown', onBlockWidgetDrag, widget );
3209
3210 // On IE8 'dragstart' is propagated to editable, so editor#dragstart is fired twice on block widgets.
3211 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
3212 img.on( 'dragstart', function( evt ) {
3213 evt.data.preventDefault( true );
3214 } );
3215 }
3216 }
3217
3218 widget.dragHandlerContainer = container;
3219 }
3220
3221 function onBlockWidgetDrag( evt ) {
3222 var finder = this.repository.finder,
3223 locator = this.repository.locator,
3224 liner = this.repository.liner,
3225 editor = this.editor,
3226 editable = editor.editable(),
3227 listeners = [],
3228 sorted = [],
3229 locations,
3230 y;
3231
3232 // Mark dragged widget for repository#finder.
3233 this.repository._.draggedWidget = this;
3234
3235 // Harvest all possible relations and display some closest.
3236 var relations = finder.greedySearch(),
3237
3238 buffer = CKEDITOR.tools.eventsBuffer( 50, function() {
3239 locations = locator.locate( relations );
3240
3241 // There's only a single line displayed for D&D.
3242 sorted = locator.sort( y, 1 );
3243
3244 if ( sorted.length ) {
3245 liner.prepare( relations, locations );
3246 liner.placeLine( sorted[ 0 ] );
3247 liner.cleanup();
3248 }
3249 } );
3250
3251 // Let's have the "dragging cursor" over entire editable.
3252 editable.addClass( 'cke_widget_dragging' );
3253
3254 // Cache mouse position so it is re-used in events buffer.
3255 listeners.push( editable.on( 'mousemove', function( evt ) {
3256 y = evt.data.$.clientY;
3257 buffer.input();
3258 } ) );
3259
3260 // Fire drag start as it happens during the native D&D.
3261 editor.fire( 'dragstart', { target: evt.sender } );
3262
3263 function onMouseUp() {
3264 var l;
3265
3266 buffer.reset();
3267
3268 // Stop observing events.
3269 while ( ( l = listeners.pop() ) )
3270 l.removeListener();
3271
3272 onBlockWidgetDrop.call( this, sorted, evt.sender );
3273 }
3274
3275 // Mouseup means "drop". This is when the widget is being detached
3276 // from DOM and placed at range determined by the line (location).
3277 listeners.push( editor.document.once( 'mouseup', onMouseUp, this ) );
3278
3279 // Prevent calling 'onBlockWidgetDrop' twice in the inline editor.
3280 // `removeListener` does not work if it is called at the same time event is fired.
3281 if ( !editable.isInline() ) {
3282 // Mouseup may occur when user hovers the line, which belongs to
3283 // the outer document. This is, of course, a valid listener too.
3284 listeners.push( CKEDITOR.document.once( 'mouseup', onMouseUp, this ) );
3285 }
3286 }
3287
3288 function onBlockWidgetDrop( sorted, dragTarget ) {
3289 var finder = this.repository.finder,
3290 liner = this.repository.liner,
3291 editor = this.editor,
3292 editable = this.editor.editable();
3293
3294 if ( !CKEDITOR.tools.isEmpty( liner.visible ) ) {
3295 // Retrieve range for the closest location.
3296 var dropRange = finder.getRange( sorted[ 0 ] );
3297
3298 // Focus widget (it could lost focus after mousedown+mouseup)
3299 // and save this state as the one where we want to be taken back when undoing.
3300 this.focus();
3301
3302 // Drag range will be set in the drop listener.
3303 editor.fire( 'drop', {
3304 dropRange: dropRange,
3305 target: dropRange.startContainer
3306 } );
3307 }
3308
3309 // Clean-up custom cursor for editable.
3310 editable.removeClass( 'cke_widget_dragging' );
3311
3312 // Clean-up all remaining lines.
3313 liner.hideVisible();
3314
3315 // Clean-up drag & drop.
3316 editor.fire( 'dragend', { target: dragTarget } );
3317 }
3318
3319 function setupEditables( widget ) {
3320 var editableName,
3321 editableDef,
3322 definedEditables = widget.editables;
3323
3324 widget.editables = {};
3325
3326 if ( !widget.editables )
3327 return;
3328
3329 for ( editableName in definedEditables ) {
3330 editableDef = definedEditables[ editableName ];
3331 widget.initEditable( editableName, typeof editableDef == 'string' ? { selector: editableDef } : editableDef );
3332 }
3333 }
3334
3335 function setupMask( widget ) {
3336 if ( !widget.mask )
3337 return;
3338
3339 // Reuse mask if already exists (#11281).
3340 var img = widget.wrapper.findOne( '.cke_widget_mask' );
3341
3342 if ( !img ) {
3343 img = new CKEDITOR.dom.element( 'img', widget.editor.document );
3344 img.setAttributes( {
3345 src: CKEDITOR.tools.transparentImageData,
3346 'class': 'cke_reset cke_widget_mask'
3347 } );
3348 widget.wrapper.append( img );
3349 }
3350
3351 widget.mask = img;
3352 }
3353
3354 // Replace parts object containing:
3355 // partName => selector pairs
3356 // with:
3357 // partName => element pairs
3358 function setupParts( widget ) {
3359 if ( widget.parts ) {
3360 var parts = {},
3361 el, partName;
3362
3363 for ( partName in widget.parts ) {
3364 el = widget.wrapper.findOne( widget.parts[ partName ] );
3365 parts[ partName ] = el;
3366 }
3367 widget.parts = parts;
3368 }
3369 }
3370
3371 function setupWidget( widget, widgetDef ) {
3372 setupWrapper( widget );
3373 setupParts( widget );
3374 setupEditables( widget );
3375 setupMask( widget );
3376 setupDragHandler( widget );
3377 setupDataClassesListener( widget );
3378 setupA11yListener( widget );
3379
3380 // #11145: [IE8] Non-editable content of widget is draggable.
3381 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
3382 widget.wrapper.on( 'dragstart', function( evt ) {
3383 var target = evt.data.getTarget();
3384
3385 // Allow text dragging inside nested editables or dragging inline widget's drag handler.
3386 if ( !Widget.getNestedEditable( widget, target ) && !( widget.inline && Widget.isDomDragHandler( target ) ) )
3387 evt.data.preventDefault();
3388 } );
3389 }
3390
3391 widget.wrapper.removeClass( 'cke_widget_new' );
3392 widget.element.addClass( 'cke_widget_element' );
3393
3394 widget.on( 'key', function( evt ) {
3395 var keyCode = evt.data.keyCode;
3396
3397 // ENTER.
3398 if ( keyCode == 13 ) {
3399 widget.edit();
3400 // CTRL+C or CTRL+X.
3401 } else if ( keyCode == CKEDITOR.CTRL + 67 || keyCode == CKEDITOR.CTRL + 88 ) {
3402 copySingleWidget( widget, keyCode == CKEDITOR.CTRL + 88 );
3403 return; // Do not preventDefault.
3404 } else if ( keyCode in keystrokesNotBlockedByWidget || ( CKEDITOR.CTRL & keyCode ) || ( CKEDITOR.ALT & keyCode ) ) {
3405 // Pass chosen keystrokes to other plugins or default fake sel handlers.
3406 // Pass all CTRL/ALT keystrokes.
3407 return;
3408 }
3409
3410 return false;
3411 }, null, null, 999 );
3412 // Listen with high priority so it's possible
3413 // to overwrite this callback.
3414
3415 widget.on( 'doubleclick', function( evt ) {
3416 if ( widget.edit() ) {
3417 // We have to cancel event if edit method opens a dialog, otherwise
3418 // link plugin may open extra dialog (#12140).
3419 evt.cancel();
3420 }
3421 } );
3422
3423 if ( widgetDef.data )
3424 widget.on( 'data', widgetDef.data );
3425
3426 if ( widgetDef.edit )
3427 widget.on( 'edit', widgetDef.edit );
3428 }
3429
3430 function setupWidgetData( widget, startupData ) {
3431 var widgetDataAttr = widget.element.data( 'cke-widget-data' );
3432
3433 if ( widgetDataAttr )
3434 widget.setData( JSON.parse( decodeURIComponent( widgetDataAttr ) ) );
3435 if ( startupData )
3436 widget.setData( startupData );
3437
3438 // Populate classes if they are not preset.
3439 if ( !widget.data.classes )
3440 widget.setData( 'classes', widget.getClasses() );
3441
3442 // Unblock data and...
3443 widget.dataReady = true;
3444
3445 // Write data to element because this was blocked when data wasn't ready.
3446 writeDataToElement( widget );
3447
3448 // Fire data event first time, because this was blocked when data wasn't ready.
3449 widget.fire( 'data', widget.data );
3450 }
3451
3452 function setupWrapper( widget ) {
3453 // Retrieve widget wrapper. Assign an id to it.
3454 var wrapper = widget.wrapper = widget.element.getParent();
3455 wrapper.setAttribute( 'data-cke-widget-id', widget.id );
3456 }
3457
3458 function writeDataToElement( widget ) {
3459 widget.element.data( 'cke-widget-data', encodeURIComponent( JSON.stringify( widget.data ) ) );
3460 }
3461
3462 //
3463 // WIDGET STYLE HANDLER ---------------------------------------------------
3464 //
3465
3466 ( function() {
3467 // Styles categorized by group. It is used to prevent applying styles for the same group being used together.
3468 var styleGroups = {};
3469
3470 /**
3471 * The class representing a widget style. It is an {@link CKEDITOR#STYLE_OBJECT object} like
3472 * the styles handler for widgets.
3473 *
3474 * **Note:** This custom style handler does not support all methods of the {@link CKEDITOR.style} class.
3475 * Not supported methods: {@link #applyToRange}, {@link #removeFromRange}, {@link #applyToObject}.
3476 *
3477 * @since 4.4
3478 * @class CKEDITOR.style.customHandlers.widget
3479 * @extends CKEDITOR.style
3480 */
3481 CKEDITOR.style.addCustomHandler( {
3482 type: 'widget',
3483
3484 setup: function( styleDefinition ) {
3485 /**
3486 * The name of widget to which this style can be applied.
3487 * It is extracted from style definition's `widget` property.
3488 *
3489 * @property {String} widget
3490 */
3491 this.widget = styleDefinition.widget;
3492
3493 /**
3494 * An array of groups that this style belongs to.
3495 * Styles assigned to the same group cannot be combined.
3496 *
3497 * @since 4.6.2
3498 * @property {Array} group
3499 */
3500 this.group = typeof styleDefinition.group == 'string' ? [ styleDefinition.group ] : styleDefinition.group;
3501
3502 // Store style categorized by its group.
3503 // It is used to prevent enabling two styles from same group.
3504 if ( this.group ) {
3505 saveStyleGroup( this );
3506 }
3507 },
3508
3509 apply: function( editor ) {
3510 var widget;
3511
3512 // Before CKEditor 4.4 wasn't a required argument, so we need to
3513 // handle a case when it wasn't provided.
3514 if ( !( editor instanceof CKEDITOR.editor ) )
3515 return;
3516
3517 // Theoretically we could bypass checkApplicable, get widget from
3518 // widgets.focused and check its name, what would be faster, but then
3519 // this custom style would work differently than the default style
3520 // which checks if it's applicable before applying or removing itself.
3521 if ( this.checkApplicable( editor.elementPath(), editor ) ) {
3522 widget = editor.widgets.focused;
3523
3524 // Remove other styles from the same group.
3525 if ( this.group ) {
3526 this.removeStylesFromSameGroup( editor );
3527 }
3528
3529 widget.applyStyle( this );
3530 }
3531 },
3532
3533 remove: function( editor ) {
3534 // Before CKEditor 4.4 wasn't a required argument, so we need to
3535 // handle a case when it wasn't provided.
3536 if ( !( editor instanceof CKEDITOR.editor ) )
3537 return;
3538
3539 if ( this.checkApplicable( editor.elementPath(), editor ) )
3540 editor.widgets.focused.removeStyle( this );
3541 },
3542
3543 /**
3544 * Removes all styles that belong to the same group as this style. This method will neither add nor remove
3545 * the current style.
3546 * Returns `true` if any style was removed, otherwise returns `false`.
3547 *
3548 * @since 4.6.2
3549 * @param {CKEDITOR.editor} editor
3550 * @returns {Boolean}
3551 */
3552 removeStylesFromSameGroup: function( editor ) {
3553 var stylesFromSameGroup,
3554 path,
3555 removed = false;
3556
3557 // Before CKEditor 4.4 wasn't a required argument, so we need to
3558 // handle a case when it wasn't provided.
3559 if ( !( editor instanceof CKEDITOR.editor ) )
3560 return false;
3561
3562 path = editor.elementPath();
3563 if ( this.checkApplicable( path, editor ) ) {
3564 // Iterate over each group.
3565 for ( var i = 0, l = this.group.length; i < l; i++ ) {
3566 stylesFromSameGroup = styleGroups[ this.widget ][ this.group[ i ] ];
3567 // Iterate over each style from group.
3568 for ( var j = 0; j < stylesFromSameGroup.length; j++ ) {
3569 if ( stylesFromSameGroup[ j ] !== this && stylesFromSameGroup[ j ].checkActive( path, editor ) ) {
3570 editor.widgets.focused.removeStyle( stylesFromSameGroup[ j ] );
3571 removed = true;
3572 }
3573 }
3574 }
3575 }
3576
3577 return removed;
3578 },
3579
3580 checkActive: function( elementPath, editor ) {
3581 return this.checkElementMatch( elementPath.lastElement, 0, editor );
3582 },
3583
3584 checkApplicable: function( elementPath, editor ) {
3585 // Before CKEditor 4.4 wasn't a required argument, so we need to
3586 // handle a case when it wasn't provided.
3587 if ( !( editor instanceof CKEDITOR.editor ) )
3588 return false;
3589
3590 return this.checkElement( elementPath.lastElement );
3591 },
3592
3593 checkElementMatch: checkElementMatch,
3594
3595 checkElementRemovable: checkElementMatch,
3596
3597 /**
3598 * Checks if an element is a {@link CKEDITOR.plugins.widget#wrapper wrapper} of a
3599 * widget whose name matches the {@link #widget widget name} specified in the style definition.
3600 *
3601 * @param {CKEDITOR.dom.element} element
3602 * @returns {Boolean}
3603 */
3604 checkElement: function( element ) {
3605 if ( !Widget.isDomWidgetWrapper( element ) )
3606 return false;
3607
3608 var widgetElement = element.getFirst( Widget.isDomWidgetElement );
3609 return widgetElement && widgetElement.data( 'widget' ) == this.widget;
3610 },
3611
3612 buildPreview: function( label ) {
3613 return label || this._.definition.name;
3614 },
3615
3616 /**
3617 * Returns allowed content rules which should be registered for this style.
3618 * Uses widget's {@link CKEDITOR.plugins.widget.definition#styleableElements} to make a rule
3619 * allowing classes on specified elements or use widget's
3620 * {@link CKEDITOR.plugins.widget.definition#styleToAllowedContentRules} method to transform a style
3621 * into allowed content rules.
3622 *
3623 * @param {CKEDITOR.editor} The editor instance.
3624 * @returns {CKEDITOR.filter.allowedContentRules}
3625 */
3626 toAllowedContentRules: function( editor ) {
3627 if ( !editor )
3628 return null;
3629
3630 var widgetDef = editor.widgets.registered[ this.widget ],
3631 classes,
3632 rule = {};
3633
3634 if ( !widgetDef )
3635 return null;
3636
3637 if ( widgetDef.styleableElements ) {
3638 classes = this.getClassesArray();
3639 if ( !classes )
3640 return null;
3641
3642 rule[ widgetDef.styleableElements ] = {
3643 classes: classes,
3644 propertiesOnly: true
3645 };
3646 return rule;
3647 }
3648 if ( widgetDef.styleToAllowedContentRules )
3649 return widgetDef.styleToAllowedContentRules( this );
3650 return null;
3651 },
3652
3653 /**
3654 * Returns classes defined in the style in form of an array.
3655 *
3656 * @returns {String[]}
3657 */
3658 getClassesArray: function() {
3659 var classes = this._.definition.attributes && this._.definition.attributes[ 'class' ];
3660
3661 return classes ? CKEDITOR.tools.trim( classes ).split( /\s+/ ) : null;
3662 },
3663
3664 /**
3665 * Not implemented.
3666 *
3667 * @method applyToRange
3668 */
3669 applyToRange: notImplemented,
3670
3671 /**
3672 * Not implemented.
3673 *
3674 * @method removeFromRange
3675 */
3676 removeFromRange: notImplemented,
3677
3678 /**
3679 * Not implemented.
3680 *
3681 * @method applyToObject
3682 */
3683 applyToObject: notImplemented
3684 } );
3685
3686 function notImplemented() {}
3687
3688 // @context style
3689 function checkElementMatch( element, fullMatch, editor ) {
3690 // Before CKEditor 4.4 wasn't a required argument, so we need to
3691 // handle a case when it wasn't provided.
3692 if ( !editor )
3693 return false;
3694
3695 if ( !this.checkElement( element ) )
3696 return false;
3697
3698 var widget = editor.widgets.getByElement( element, true );
3699 return widget && widget.checkStyleActive( this );
3700 }
3701
3702 // Save and categorize style by its group.
3703 function saveStyleGroup( style ) {
3704 var widgetName = style.widget,
3705 group;
3706
3707 if ( !styleGroups[ widgetName ] ) {
3708 styleGroups[ widgetName ] = {};
3709 }
3710
3711 for ( var i = 0, l = style.group.length; i < l; i++ ) {
3712 group = style.group[ i ];
3713 if ( !styleGroups[ widgetName ][ group ] ) {
3714 styleGroups[ widgetName ][ group ] = [];
3715 }
3716
3717 styleGroups[ widgetName ][ group ].push( style );
3718 }
3719 }
3720
3721 } )();
3722
3723 //
3724 // EXPOSE PUBLIC API ------------------------------------------------------
3725 //
3726
3727 CKEDITOR.plugins.widget = Widget;
3728 Widget.repository = Repository;
3729 Widget.nestedEditable = NestedEditable;
3730} )();
3731
3732/**
3733 * An event fired when a widget definition is registered by the {@link CKEDITOR.plugins.widget.repository#add} method.
3734 * It is possible to modify the definition being registered.
3735 *
3736 * @event widgetDefinition
3737 * @member CKEDITOR.editor
3738 * @param {CKEDITOR.plugins.widget.definition} data Widget definition.
3739 */
3740
3741/**
3742 * This is an abstract class that describes the definition of a widget.
3743 * It is a type of {@link CKEDITOR.plugins.widget.repository#add} method's second argument.
3744 *
3745 * Widget instances inherit from registered widget definitions, although not in a prototypal way.
3746 * They are simply extended with corresponding widget definitions. Note that not all properties of
3747 * the widget definition become properties of a widget. Some, like {@link #data} or {@link #edit}, become
3748 * widget's events listeners.
3749 *
3750 * @class CKEDITOR.plugins.widget.definition
3751 * @abstract
3752 * @mixins CKEDITOR.feature
3753 */
3754
3755/**
3756 * Widget definition name. It is automatically set when the definition is
3757 * {@link CKEDITOR.plugins.widget.repository#add registered}.
3758 *
3759 * @property {String} name
3760 */
3761
3762/**
3763 * The method executed while initializing a widget, after a widget instance
3764 * is created, but before it is ready. It is executed before the first
3765 * {@link CKEDITOR.plugins.widget#event-data} is fired so it is common to
3766 * use the `init` method to populate widget data with information loaded from
3767 * the DOM, like for exmaple:
3768 *
3769 * init: function() {
3770 * this.setData( 'width', this.element.getStyle( 'width' ) );
3771 *
3772 * if ( this.parts.caption.getStyle( 'display' ) != 'none' )
3773 * this.setData( 'showCaption', true );
3774 * }
3775 *
3776 * @property {Function} init
3777 */
3778
3779/**
3780 * The function to be used to upcast an element to this widget or a
3781 * comma-separated list of upcast methods from the {@link #upcasts} object.
3782 *
3783 * The upcast function **is not** executed in the widget context (because the widget
3784 * does not exist yet) and two arguments are passed:
3785 *
3786 * * `element` ({@link CKEDITOR.htmlParser.element}) &ndash; The element to be checked.
3787 * * `data` (`Object`) &ndash; The object which can be extended with data which will then be passed to the widget.
3788 *
3789 * An element will be upcasted if a function returned `true` or an instance of
3790 * a {@link CKEDITOR.htmlParser.element} if upcasting meant DOM structure changes
3791 * (in this case the widget will be initialized on the returned element).
3792 *
3793 * @property {String/Function} upcast
3794 */
3795
3796/**
3797 * The object containing functions which can be used to upcast this widget.
3798 * Only those pointed by the {@link #upcast} property will be used.
3799 *
3800 * In most cases it is appropriate to use {@link #upcast} directly,
3801 * because majority of widgets need just one method.
3802 * However, in some cases the widget author may want to expose more than one variant
3803 * and then this property may be used.
3804 *
3805 * upcasts: {
3806 * // This function may upcast only figure elements.
3807 * figure: function() {
3808 * // ...
3809 * },
3810 * // This function may upcast only image elements.
3811 * image: function() {
3812 * // ...
3813 * },
3814 * // More variants...
3815 * }
3816 *
3817 * // Then, widget user may choose which upcast methods will be enabled.
3818 * editor.on( 'widgetDefinition', function( evt ) {
3819 * if ( evt.data.name == 'image' )
3820 * evt.data.upcast = 'figure,image'; // Use both methods.
3821 * } );
3822 *
3823 * @property {Object} upcasts
3824 */
3825
3826/**
3827 * The {@link #upcast} method(s) priority. The upcast with a lower priority number will be called before
3828 * the one with a higher number. The default priority is `10`.
3829 *
3830 * @since 4.5
3831 * @property {Number} [upcastPriority=10]
3832 */
3833
3834/**
3835 * The function to be used to downcast this widget or
3836 * a name of the downcast option from the {@link #downcasts} object.
3837 *
3838 * The downcast funciton will be executed in the {@link CKEDITOR.plugins.widget} context
3839 * and with `widgetElement` ({@link CKEDITOR.htmlParser.element}) argument which is
3840 * the widget's main element.
3841 *
3842 * The function may return an instance of the {@link CKEDITOR.htmlParser.node} class if the widget
3843 * needs to be downcasted to a different node than the widget's main element.
3844 *
3845 * @property {String/Function} downcast
3846 */
3847
3848/**
3849 * The object containing functions which can be used to downcast this widget.
3850 * Only the one pointed by the {@link #downcast} property will be used.
3851 *
3852 * In most cases it is appropriate to use {@link #downcast} directly,
3853 * because majority of widgets have just one variant of downcasting (or none at all).
3854 * However, in some cases the widget author may want to expose more than one variant
3855 * and then this property may be used.
3856 *
3857 * downcasts: {
3858 * // This downcast may transform the widget into the figure element.
3859 * figure: function() {
3860 * // ...
3861 * },
3862 * // This downcast may transform the widget into the image element with data-* attributes.
3863 * image: function() {
3864 * // ...
3865 * }
3866 * }
3867 *
3868 * // Then, the widget user may choose one of the downcast options when setting up his editor.
3869 * editor.on( 'widgetDefinition', function( evt ) {
3870 * if ( evt.data.name == 'image' )
3871 * evt.data.downcast = 'figure';
3872 * } );
3873 *
3874 * @property downcasts
3875 */
3876
3877/**
3878 * If set, it will be added as the {@link CKEDITOR.plugins.widget#event-edit} event listener.
3879 * This means that it will be executed when a widget is being edited.
3880 * See the {@link CKEDITOR.plugins.widget#method-edit} method.
3881 *
3882 * @property {Function} edit
3883 */
3884
3885/**
3886 * If set, it will be added as the {@link CKEDITOR.plugins.widget#event-data} event listener.
3887 * This means that it will be executed every time the {@link CKEDITOR.plugins.widget#property-data widget data} changes.
3888 *
3889 * @property {Function} data
3890 */
3891
3892/**
3893 * The method to be executed when the widget's command is executed in order to insert a new widget
3894 * (widget of this type is not focused). If not defined, then the default action will be
3895 * performed which means that:
3896 *
3897 * * An instance of the widget will be created in a detached {@link CKEDITOR.dom.documentFragment document fragment},
3898 * * The {@link CKEDITOR.plugins.widget#method-edit} method will be called to trigger widget editing,
3899 * * The widget element will be inserted into DOM.
3900 *
3901 * @property {Function} insert
3902 */
3903
3904/**
3905 * The name of a dialog window which will be opened on {@link CKEDITOR.plugins.widget#method-edit}.
3906 * If not defined, then the {@link CKEDITOR.plugins.widget#method-edit} method will not perform any action and
3907 * widget's command will insert a new widget without opening a dialog window first.
3908 *
3909 * @property {String} dialog
3910 */
3911
3912/**
3913 * The template which will be used to create a new widget element (when the widget's command is executed).
3914 * This string is populated with {@link #defaults default values} by using the {@link CKEDITOR.template} format.
3915 * Therefore it has to be a valid {@link CKEDITOR.template} argument.
3916 *
3917 * @property {String} template
3918 */
3919
3920/**
3921 * The data object which will be used to populate the data of a newly created widget.
3922 * See {@link CKEDITOR.plugins.widget#property-data}.
3923 *
3924 * defaults: {
3925 * showCaption: true,
3926 * align: 'none'
3927 * }
3928 *
3929 * @property defaults
3930 */
3931
3932/**
3933 * An object containing definitions of widget components (part name => CSS selector).
3934 *
3935 * parts: {
3936 * image: 'img',
3937 * caption: 'div.caption'
3938 * }
3939 *
3940 * @property parts
3941 */
3942
3943/**
3944 * An object containing definitions of nested editables (editable name => {@link CKEDITOR.plugins.widget.nestedEditable.definition}).
3945 * Note that editables *have to* be defined in the same order as they are in DOM / {@link CKEDITOR.plugins.widget.definition#template template}.
3946 * Otherwise errors will occur when nesting widgets inside each other.
3947 *
3948 * editables: {
3949 * header: 'h1',
3950 * content: {
3951 * selector: 'div.content',
3952 * allowedContent: 'p strong em; a[!href]'
3953 * }
3954 * }
3955 *
3956 * @property editables
3957 */
3958
3959/**
3960 * The function used to obtain an accessibility label for the widget. It might be used to make
3961 * the widget labels as precise as possible, since it has access to the widget instance.
3962 *
3963 * If not specified, the default implementation will use the {@link #pathName} or the main
3964 * {@link CKEDITOR.plugins.widget#element element} tag name.
3965 *
3966 * @property {Function} getLabel
3967 */
3968
3969/**
3970 * The widget name displayed in the elements path.
3971 *
3972 * @property {String} pathName
3973 */
3974
3975/**
3976 * If set to `true`, the widget's element will be covered with a transparent mask.
3977 * This will prevent its content from being clickable, which matters in case
3978 * of special elements like embedded Flash or iframes that generate a separate "context".
3979 *
3980 * @property {Boolean} mask
3981 */
3982
3983/**
3984 * If set to `true/false`, it will force the widget to be either an inline or a block widget.
3985 * If not set, the widget type will be determined from the widget element.
3986 *
3987 * Widget type influences whether a block (`div`) or an inline (`span`) element is used
3988 * for the wrapper.
3989 *
3990 * @property {Boolean} inline
3991 */
3992
3993/**
3994 * The label for the widget toolbar button.
3995 *
3996 * editor.widgets.add( 'simplebox', {
3997 * button: 'Create a simple box'
3998 * } );
3999 *
4000 * editor.widgets.add( 'simplebox', {
4001 * button: editor.lang.simplebox.title
4002 * } );
4003 *
4004 * @property {String} button
4005 */
4006
4007/**
4008 * Whether widget should be draggable. Defaults to `true`.
4009 * If set to `false` drag handler will not be displayed when hovering widget.
4010 *
4011 * @property {Boolean} draggable
4012 */
4013
4014/**
4015 * Names of element(s) (separated by spaces) for which the {@link CKEDITOR.filter} should allow classes
4016 * defined in the widget styles. For example if your widget is upcasted from a simple `<div>`
4017 * element, then in order to make it styleable you can set:
4018 *
4019 * editor.widgets.add( 'customWidget', {
4020 * upcast: function( element ) {
4021 * return element.name == 'div';
4022 * },
4023 *
4024 * // ...
4025 *
4026 * styleableElements: 'div'
4027 * } );
4028 *
4029 * Then, when the following style is defined:
4030 *
4031 * {
4032 * name: 'Thick border', type: 'widget', widget: 'customWidget',
4033 * attributes: { 'class': 'thickBorder' }
4034 * }
4035 *
4036 * a rule allowing the `thickBorder` class for `div` elements will be registered in the {@link CKEDITOR.filter}.
4037 *
4038 * If you need to have more freedom when transforming widget style to allowed content rules,
4039 * you can use the {@link #styleToAllowedContentRules} callback.
4040 *
4041 * @since 4.4
4042 * @property {String} styleableElements
4043 */
4044
4045/**
4046 * Function transforming custom widget's {@link CKEDITOR.style} instance into
4047 * {@link CKEDITOR.filter.allowedContentRules}. It may be used when a static
4048 * {@link #styleableElements} property is not enough to inform the {@link CKEDITOR.filter}
4049 * what HTML features should be enabled when allowing the given style.
4050 *
4051 * In most cases, when style's classes just have to be added to element name(s) used by
4052 * the widget element, it is recommended to use simpler {@link #styleableElements} property.
4053 *
4054 * In order to get parsed classes from the style definition you can use
4055 * {@link CKEDITOR.style.customHandlers.widget#getClassesArray}.
4056 *
4057 * For example, if you want to use the [object format of allowed content rules](#!/guide/dev_allowed_content_rules-section-object-format),
4058 * to specify `match` validator, your implementation could look like this:
4059 *
4060 * editor.widgets.add( 'customWidget', {
4061 * // ...
4062 *
4063 * styleToAllowedContentRules: funciton( style ) {
4064 * // Retrieve classes defined in the style.
4065 * var classes = style.getClassesArray();
4066 *
4067 * // Do something crazy - for example return allowed content rules in object format,
4068 * // with custom match property and propertiesOnly flag.
4069 * return {
4070 * h1: {
4071 * match: isWidgetElement,
4072 * propertiesOnly: true,
4073 * classes: classes
4074 * }
4075 * };
4076 * }
4077 * } );
4078 *
4079 * @since 4.4
4080 * @property {Function} styleToAllowedContentRules
4081 * @param {CKEDITOR.style.customHandlers.widget} style The style to be transformed.
4082 * @returns {CKEDITOR.filter.allowedContentRules}
4083 */
4084
4085/**
4086 * This is an abstract class that describes the definition of a widget's nested editable.
4087 * It is a type of values in the {@link CKEDITOR.plugins.widget.definition#editables} object.
4088 *
4089 * In the simplest case the definition is a string which is a CSS selector used to
4090 * find an element that will become a nested editable inside the widget. Note that
4091 * the widget element can be a nested editable, too.
4092 *
4093 * In the more advanced case a definition is an object with a required `selector` property.
4094 *
4095 * editables: {
4096 * header: 'h1',
4097 * content: {
4098 * selector: 'div.content',
4099 * allowedContent: 'p strong em; a[!href]'
4100 * }
4101 * }
4102 *
4103 * @class CKEDITOR.plugins.widget.nestedEditable.definition
4104 * @abstract
4105 */
4106
4107/**
4108 * The CSS selector used to find an element which will become a nested editable.
4109 *
4110 * @property {String} selector
4111 */
4112
4113/**
4114 * The [Advanced Content Filter](#!/guide/dev_advanced_content_filter) rules
4115 * which will be used to limit the content allowed in this nested editable.
4116 * This option is similar to {@link CKEDITOR.config#allowedContent} and one can
4117 * use it to limit the editor features available in the nested editable.
4118 *
4119 * @property {CKEDITOR.filter.allowedContentRules} allowedContent
4120 */
4121
4122/**
4123 * Nested editable name displayed in elements path.
4124 *
4125 * @property {String} pathName
4126 */
diff --git a/sources/plugins/widgetselection/plugin.js b/sources/plugins/widgetselection/plugin.js
new file mode 100644
index 0000000..b7aa6a0
--- /dev/null
+++ b/sources/plugins/widgetselection/plugin.js
@@ -0,0 +1,366 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview A plugin created to handle ticket #11064. While the issue is caused by native WebKit/Blink behaviour,
8 * this plugin can be easily detached or modified when the issue is fixed in the browsers without changing the core.
9 * When Ctrl/Cmd + A is pressed to select all content it does not work due to a bug in
10 * Webkit/Blink if a non-editable element is at the beginning or the end of the content.
11 */
12
13( function() {
14 'use strict';
15
16 CKEDITOR.plugins.add( 'widgetselection', {
17
18 init: function( editor ) {
19 if ( CKEDITOR.env.webkit ) {
20 var widgetselection = CKEDITOR.plugins.widgetselection;
21
22 editor.on( 'contentDom', function( evt ) {
23
24 var editor = evt.editor,
25 doc = editor.document,
26 editable = editor.editable();
27
28 editable.attachListener( doc, 'keydown', function( evt ) {
29 var data = evt.data.$;
30
31 // Ctrl/Cmd + A
32 if ( evt.data.getKey() == 65 && ( CKEDITOR.env.mac && data.metaKey || !CKEDITOR.env.mac && data.ctrlKey ) ) {
33
34 // Defer the call so the selection is already changed by the pressed keys.
35 CKEDITOR.tools.setTimeout( function() {
36
37 // Manage filler elements on keydown. If there is no need
38 // to add fillers, we need to check and clean previously used once.
39 if ( !widgetselection.addFillers( editable ) ) {
40 widgetselection.removeFillers( editable );
41 }
42 }, 0 );
43 }
44 }, null, null, -1 );
45
46 // Check and clean previously used fillers.
47 editor.on( 'selectionCheck', function( evt ) {
48 widgetselection.removeFillers( evt.editor.editable() );
49 } );
50
51 // Remove fillers on paste before data gets inserted into editor.
52 editor.on( 'paste', function( evt ) {
53 evt.data.dataValue = widgetselection.cleanPasteData( evt.data.dataValue );
54 } );
55
56 if ( 'selectall' in editor.plugins ) {
57 widgetselection.addSelectAllIntegration( editor );
58 }
59 } );
60 }
61 }
62 } );
63
64 /**
65 * A set of helper methods for the Widget Selection plugin.
66 *
67 * @property widgetselection
68 * @member CKEDITOR.plugins
69 * @since 4.6.1
70 */
71 CKEDITOR.plugins.widgetselection = {
72
73 /**
74 * The start filler element reference.
75 *
76 * @property {CKEDITOR.dom.element}
77 * @member CKEDITOR.plugins.widgetselection
78 * @private
79 */
80 startFiller: null,
81
82 /**
83 * The end filler element reference.
84 *
85 * @property {CKEDITOR.dom.element}
86 * @member CKEDITOR.plugins.widgetselection
87 * @private
88 */
89 endFiller: null,
90
91 /**
92 * An attribute which identifies the filler element.
93 *
94 * @property {String}
95 * @member CKEDITOR.plugins.widgetselection
96 * @private
97 */
98 fillerAttribute: 'data-cke-filler-webkit',
99
100 /**
101 * The default content of the filler element. Note: The filler needs to have `visible` content.
102 * Unprintable elements or empty content do not help as a workaround.
103 *
104 * @property {String}
105 * @member CKEDITOR.plugins.widgetselection
106 * @private
107 */
108 fillerContent: '&nbsp;',
109
110 /**
111 * Tag name which is used to create fillers.
112 *
113 * @property {String}
114 * @member CKEDITOR.plugins.widgetselection
115 * @private
116 */
117 fillerTagName: 'div',
118
119 /**
120 * Adds a filler before or after a non-editable element at the beginning or the end of the `editable`.
121 *
122 * @param {CKEDITOR.editable} editable
123 * @returns {Boolean}
124 * @member CKEDITOR.plugins.widgetselection
125 */
126 addFillers: function( editable ) {
127 var editor = editable.editor;
128
129 // Whole content should be selected, if not fix the selection manually.
130 if ( !this.isWholeContentSelected( editable ) && editable.getChildCount() > 0 ) {
131
132 var firstChild = editable.getFirst( filterTempElements ),
133 lastChild = editable.getLast( filterTempElements );
134
135 // Check if first element is editable. If not prepend with filler.
136 if ( firstChild && firstChild.type == CKEDITOR.NODE_ELEMENT && !firstChild.isEditable() ) {
137 this.startFiller = this.createFiller();
138 editable.append( this.startFiller, 1 );
139 }
140
141 // Check if last element is editable. If not append filler.
142 if ( lastChild && lastChild.type == CKEDITOR.NODE_ELEMENT && !lastChild.isEditable() ) {
143 this.endFiller = this.createFiller( true );
144 editable.append( this.endFiller, 0 );
145 }
146
147 // Reselect whole content after any filler was added.
148 if ( this.hasFiller( editable ) ) {
149 var rangeAll = editor.createRange();
150 rangeAll.selectNodeContents( editable );
151 rangeAll.select();
152 return true;
153 }
154 }
155 return false;
156 },
157
158 /**
159 * Removes filler elements or updates their references.
160 *
161 * It will **not remove** filler elements if the whole content is selected, as it would break the
162 * selection.
163 *
164 * @param {CKEDITOR.editable} editable
165 * @member CKEDITOR.plugins.widgetselection
166 */
167 removeFillers: function( editable ) {
168 // If startFiller or endFiller exists and not entire content is selected it means the selection
169 // just changed from selected all. We need to remove fillers and set proper selection/content.
170 if ( this.hasFiller( editable ) && !this.isWholeContentSelected( editable ) ) {
171
172 var startFillerContent = editable.findOne( this.fillerTagName + '[' + this.fillerAttribute + '=start]' ),
173 endFillerContent = editable.findOne( this.fillerTagName + '[' + this.fillerAttribute + '=end]' );
174
175 if ( this.startFiller && startFillerContent && this.startFiller.equals( startFillerContent ) ) {
176 this.removeFiller( this.startFiller, editable );
177 } else {
178 // The start filler is still present but it is a different element than previous one. It means the
179 // undo recreating entirely selected content was performed. We need to update filler reference.
180 this.startFiller = startFillerContent;
181 }
182
183 if ( this.endFiller && endFillerContent && this.endFiller.equals( endFillerContent ) ) {
184 this.removeFiller( this.endFiller, editable );
185 } else {
186 // Same as with start filler.
187 this.endFiller = endFillerContent;
188 }
189 }
190 },
191
192 /**
193 * Removes fillers from the paste data.
194 *
195 * @param {String} data
196 * @returns {String}
197 * @member CKEDITOR.plugins.widgetselection
198 * @private
199 */
200 cleanPasteData: function( data ) {
201 if ( data && data.length ) {
202 data = data
203 .replace( this.createFillerRegex(), '' )
204 .replace( this.createFillerRegex( true ), '' );
205 }
206 return data;
207 },
208
209 /**
210 * Checks if the entire content of the given editable is selected.
211 *
212 * @param {CKEDITOR.editable} editable
213 * @returns {Boolean}
214 * @member CKEDITOR.plugins.widgetselection
215 * @private
216 */
217 isWholeContentSelected: function( editable ) {
218
219 var range = editable.editor.getSelection().getRanges()[ 0 ];
220 if ( range ) {
221
222 if ( range && range.collapsed ) {
223 return false;
224
225 } else {
226 var rangeClone = range.clone();
227 rangeClone.enlarge( CKEDITOR.ENLARGE_ELEMENT );
228
229 return !!( rangeClone && editable && rangeClone.startContainer && rangeClone.endContainer &&
230 rangeClone.startOffset === 0 && rangeClone.endOffset === editable.getChildCount() &&
231 rangeClone.startContainer.equals( editable ) && rangeClone.endContainer.equals( editable ) );
232 }
233 }
234 return false;
235 },
236
237 /**
238 * Checks if there is any filler element in the given editable.
239 *
240 * @param {CKEDITOR.editable} editable
241 * @returns {Boolean}
242 * @member CKEDITOR.plugins.widgetselection
243 * @private
244 */
245 hasFiller: function( editable ) {
246 return editable.find( this.fillerTagName + '[' + this.fillerAttribute + ']' ).count() > 0;
247 },
248
249 /**
250 * Creates a filler element.
251 *
252 * @param {Boolean} [onEnd] If filler will be placed on end or beginning of the content.
253 * @returns {CKEDITOR.dom.element}
254 * @member CKEDITOR.plugins.widgetselection
255 * @private
256 */
257 createFiller: function( onEnd ) {
258 var filler = new CKEDITOR.dom.element( this.fillerTagName );
259 filler.setHtml( this.fillerContent );
260 filler.setAttribute( this.fillerAttribute, onEnd ? 'end' : 'start' );
261 filler.setAttribute( 'data-cke-temp', 1 );
262 filler.setStyles( {
263 display: 'block',
264 width: 0,
265 height: 0,
266 padding: 0,
267 border: 0,
268 margin: 0,
269 position: 'absolute',
270 top: 0,
271 left: '-9999px',
272 opacity: 0,
273 overflow: 'hidden'
274 } );
275
276 return filler;
277 },
278
279 /**
280 * Removes the specific filler element from the given editable. If the filler contains any content (typed or pasted),
281 * it replaces the current editable content. If not, the caret is placed before the first or after the last editable
282 * element (depends if the filler was at the beginning or the end).
283 *
284 * @param {CKEDITOR.dom.element} filler
285 * @param {CKEDITOR.editable} editable
286 * @member CKEDITOR.plugins.widgetselection
287 * @private
288 */
289 removeFiller: function( filler, editable ) {
290 if ( filler ) {
291 var editor = editable.editor,
292 currentRange = editable.editor.getSelection().getRanges()[ 0 ],
293 currentPath = currentRange.startPath(),
294 range = editor.createRange(),
295 insertedHtml,
296 fillerOnStart,
297 manuallyHandleCaret;
298
299 if ( currentPath.contains( filler ) ) {
300 insertedHtml = filler.getHtml();
301 manuallyHandleCaret = true;
302 }
303
304 fillerOnStart = filler.getAttribute( this.fillerAttribute ) == 'start';
305 filler.remove();
306 filler = null;
307
308 if ( insertedHtml && insertedHtml.length > 0 && insertedHtml != this.fillerContent ) {
309 editable.insertHtmlIntoRange( insertedHtml, editor.getSelection().getRanges()[ 0 ] );
310 range.setStartAt( editable.getChild( editable.getChildCount() - 1 ), CKEDITOR.POSITION_BEFORE_END );
311 editor.getSelection().selectRanges( [ range ] );
312
313 } else if ( manuallyHandleCaret ) {
314 if ( fillerOnStart ) {
315 range.setStartAt( editable.getFirst().getNext(), CKEDITOR.POSITION_AFTER_START );
316 } else {
317 range.setEndAt( editable.getLast().getPrevious(), CKEDITOR.POSITION_BEFORE_END );
318 }
319 editable.editor.getSelection().selectRanges( [ range ] );
320 }
321 }
322 },
323
324 /**
325 * Creates a regular expression which will match the filler HTML in the text.
326 *
327 * @param {Boolean} [onEnd] Whether a regular expression should be created for the filler at the beginning or
328 * the end of the content.
329 * @returns {RegExp}
330 * @member CKEDITOR.plugins.widgetselection
331 * @private
332 */
333 createFillerRegex: function( onEnd ) {
334 var matcher = this.createFiller( onEnd ).getOuterHtml()
335 .replace( /style="[^"]*"/gi, 'style="[^"]*"' )
336 .replace( />[^<]*</gi, '>[^<]*<' );
337
338 return new RegExp( ( !onEnd ? '^' : '' ) + matcher + ( onEnd ? '$' : '' ) );
339 },
340
341 /**
342 * Adds an integration for the [Select All](http://ckeditor.com/addon/selectall) plugin to the given `editor`.
343 *
344 * @private
345 * @param {CKEDITOR.editor} editor
346 * @member CKEDITOR.plugins.widgetselection
347 */
348 addSelectAllIntegration: function( editor ) {
349 var widgetselection = this;
350
351 editor.editable().attachListener( editor, 'beforeCommandExec', function( evt ) {
352 var editable = editor.editable();
353
354 if ( evt.data.name == 'selectAll' && editable ) {
355 widgetselection.addFillers( editable );
356 }
357 }, null, null, 9999 );
358 }
359 };
360
361
362 function filterTempElements( el ) {
363 return el.getName && !el.hasAttribute( 'data-cke-temp' );
364 }
365
366} )();
diff --git a/sources/plugins/wysiwygarea/plugin.js b/sources/plugins/wysiwygarea/plugin.js
new file mode 100644
index 0000000..962f31e
--- /dev/null
+++ b/sources/plugins/wysiwygarea/plugin.js
@@ -0,0 +1,713 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The WYSIWYG Area plugin. It registers the "wysiwyg" editing
8 * mode, which handles the main editing area space.
9 */
10
11( function() {
12 var framedWysiwyg;
13
14 CKEDITOR.plugins.add( 'wysiwygarea', {
15 init: function( editor ) {
16 if ( editor.config.fullPage ) {
17 editor.addFeature( {
18 allowedContent: 'html head title; style [media,type]; body (*)[id]; meta link [*]',
19 requiredContent: 'body'
20 } );
21 }
22
23 editor.addMode( 'wysiwyg', function( callback ) {
24 var src = 'document.open();' +
25 // In IE, the document domain must be set any time we call document.open().
26 ( CKEDITOR.env.ie ? '(' + CKEDITOR.tools.fixDomain + ')();' : '' ) +
27 'document.close();';
28
29 // With IE, the custom domain has to be taken care at first,
30 // for other browers, the 'src' attribute should be left empty to
31 // trigger iframe's 'load' event.
32 // Microsoft Edge throws "Permission Denied" if treated like an IE (#13441).
33 if ( CKEDITOR.env.air ) {
34 src = 'javascript:void(0)'; // jshint ignore:line
35 } else if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) {
36 src = 'javascript:void(function(){' + encodeURIComponent( src ) + '}())'; // jshint ignore:line
37 } else {
38 src = '';
39 }
40
41 var iframe = CKEDITOR.dom.element.createFromHtml( '<iframe src="' + src + '" frameBorder="0"></iframe>' );
42 iframe.setStyles( { width: '100%', height: '100%' } );
43 iframe.addClass( 'cke_wysiwyg_frame' ).addClass( 'cke_reset' );
44
45 var contentSpace = editor.ui.space( 'contents' );
46 contentSpace.append( iframe );
47
48
49 // Asynchronous iframe loading is only required in IE>8 and Gecko (other reasons probably).
50 // Do not use it on WebKit as it'll break the browser-back navigation.
51 var useOnloadEvent = ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) || CKEDITOR.env.gecko;
52 if ( useOnloadEvent )
53 iframe.on( 'load', onLoad );
54
55 var frameLabel = editor.title,
56 helpLabel = editor.fire( 'ariaEditorHelpLabel', {} ).label;
57
58 if ( frameLabel ) {
59 if ( CKEDITOR.env.ie && helpLabel )
60 frameLabel += ', ' + helpLabel;
61
62 iframe.setAttribute( 'title', frameLabel );
63 }
64
65 if ( helpLabel ) {
66 var labelId = CKEDITOR.tools.getNextId(),
67 desc = CKEDITOR.dom.element.createFromHtml( '<span id="' + labelId + '" class="cke_voice_label">' + helpLabel + '</span>' );
68
69 contentSpace.append( desc, 1 );
70 iframe.setAttribute( 'aria-describedby', labelId );
71 }
72
73 // Remove the ARIA description.
74 editor.on( 'beforeModeUnload', function( evt ) {
75 evt.removeListener();
76 if ( desc )
77 desc.remove();
78 } );
79
80 iframe.setAttributes( {
81 tabIndex: editor.tabIndex,
82 allowTransparency: 'true'
83 } );
84
85 // Execute onLoad manually for all non IE||Gecko browsers.
86 !useOnloadEvent && onLoad();
87
88 editor.fire( 'ariaWidget', iframe );
89
90 function onLoad( evt ) {
91 evt && evt.removeListener();
92 editor.editable( new framedWysiwyg( editor, iframe.$.contentWindow.document.body ) );
93 editor.setData( editor.getData( 1 ), callback );
94 }
95 } );
96 }
97 } );
98
99 /**
100 * Adds the path to a stylesheet file to the exisiting {@link CKEDITOR.config#contentsCss} value.
101 *
102 * **Note:** This method is available only with the `wysiwygarea` plugin and only affects
103 * classic editors based on it (so it does not affect inline editors).
104 *
105 * editor.addContentsCss( 'assets/contents.css' );
106 *
107 * @since 4.4
108 * @param {String} cssPath The path to the stylesheet file which should be added.
109 * @member CKEDITOR.editor
110 */
111 CKEDITOR.editor.prototype.addContentsCss = function( cssPath ) {
112 var cfg = this.config,
113 curContentsCss = cfg.contentsCss;
114
115 // Convert current value into array.
116 if ( !CKEDITOR.tools.isArray( curContentsCss ) )
117 cfg.contentsCss = curContentsCss ? [ curContentsCss ] : [];
118
119 cfg.contentsCss.push( cssPath );
120 };
121
122 function onDomReady( win ) {
123 var editor = this.editor,
124 doc = win.document,
125 body = doc.body;
126
127 // Remove helper scripts from the DOM.
128 var script = doc.getElementById( 'cke_actscrpt' );
129 script && script.parentNode.removeChild( script );
130 script = doc.getElementById( 'cke_shimscrpt' );
131 script && script.parentNode.removeChild( script );
132 script = doc.getElementById( 'cke_basetagscrpt' );
133 script && script.parentNode.removeChild( script );
134
135 body.contentEditable = true;
136
137 if ( CKEDITOR.env.ie ) {
138 // Don't display the focus border.
139 body.hideFocus = true;
140
141 // Disable and re-enable the body to avoid IE from
142 // taking the editing focus at startup. (#141 / #523)
143 body.disabled = true;
144 body.removeAttribute( 'disabled' );
145 }
146
147 delete this._.isLoadingData;
148
149 // Play the magic to alter element reference to the reloaded one.
150 this.$ = body;
151
152 doc = new CKEDITOR.dom.document( doc );
153
154 this.setup();
155 this.fixInitialSelection();
156
157 var editable = this;
158
159 // Without it IE8 has problem with removing selection in nested editable. (#13785)
160 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) {
161 doc.getDocumentElement().addClass( doc.$.compatMode );
162 }
163
164 // Prevent IE/Edge from leaving a new paragraph/div after deleting all contents in body. (#6966, #13142)
165 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_P ) {
166 removeSuperfluousElement( 'p' );
167 } else if ( CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_DIV ) {
168 removeSuperfluousElement( 'div' );
169 }
170
171 // Fix problem with cursor not appearing in Webkit and IE11+ when clicking below the body (#10945, #10906).
172 // Fix for older IEs (8-10 and QM) is placed inside selection.js.
173 if ( CKEDITOR.env.webkit || ( CKEDITOR.env.ie && CKEDITOR.env.version > 10 ) ) {
174 doc.getDocumentElement().on( 'mousedown', function( evt ) {
175 if ( evt.data.getTarget().is( 'html' ) ) {
176 // IE needs this timeout. Webkit does not, but it does not cause problems too.
177 setTimeout( function() {
178 editor.editable().focus();
179 } );
180 }
181 } );
182 }
183
184 // Config props: disableObjectResizing and disableNativeTableHandles handler.
185 objectResizeDisabler( editor );
186
187 // Enable dragging of position:absolute elements in IE.
188 try {
189 editor.document.$.execCommand( '2D-position', false, true );
190 } catch ( e ) {}
191
192 if ( CKEDITOR.env.gecko || CKEDITOR.env.ie && editor.document.$.compatMode == 'CSS1Compat' ) {
193 this.attachListener( this, 'keydown', function( evt ) {
194 var keyCode = evt.data.getKeystroke();
195
196 // PageUp OR PageDown
197 if ( keyCode == 33 || keyCode == 34 ) {
198 // PageUp/PageDown scrolling is broken in document
199 // with standard doctype, manually fix it. (#4736)
200 if ( CKEDITOR.env.ie ) {
201 setTimeout( function() {
202 editor.getSelection().scrollIntoView();
203 }, 0 );
204 }
205 // Page up/down cause editor selection to leak
206 // outside of editable thus we try to intercept
207 // the behavior, while it affects only happen
208 // when editor contents are not overflowed. (#7955)
209 else if ( editor.window.$.innerHeight > this.$.offsetHeight ) {
210 var range = editor.createRange();
211 range[ keyCode == 33 ? 'moveToElementEditStart' : 'moveToElementEditEnd' ]( this );
212 range.select();
213 evt.data.preventDefault();
214 }
215 }
216 } );
217 }
218
219 if ( CKEDITOR.env.ie ) {
220 // [IE] Iframe will still keep the selection when blurred, if
221 // focus is moved onto a non-editing host, e.g. link or button, but
222 // it becomes a problem for the object type selection, since the resizer
223 // handler attached on it will mark other part of the UI, especially
224 // for the dialog. (#8157)
225 // [IE<8 & Opera] Even worse For old IEs, the cursor will not vanish even if
226 // the selection has been moved to another text input in some cases. (#4716)
227 //
228 // Now the range restore is disabled, so we simply force IE to clean
229 // up the selection before blur.
230 this.attachListener( doc, 'blur', function() {
231 // Error proof when the editor is not visible. (#6375)
232 try {
233 doc.$.selection.empty();
234 } catch ( er ) {}
235 } );
236 }
237
238 if ( CKEDITOR.env.iOS ) {
239 // [iOS] If touch is bound to any parent of the iframe blur happens on any touch
240 // event and body becomes the focused element (#10714).
241 this.attachListener( doc, 'touchend', function() {
242 win.focus();
243 } );
244 }
245
246 var title = editor.document.getElementsByTag( 'title' ).getItem( 0 );
247 // document.title is malfunctioning on Chrome, so get value from the element (#12402).
248 title.data( 'cke-title', title.getText() );
249
250 // [IE] JAWS will not recognize the aria label we used on the iframe
251 // unless the frame window title string is used as the voice label,
252 // backup the original one and restore it on output.
253 if ( CKEDITOR.env.ie )
254 editor.document.$.title = this._.docTitle;
255
256 CKEDITOR.tools.setTimeout( function() {
257 // Editable is ready after first setData.
258 if ( this.status == 'unloaded' )
259 this.status = 'ready';
260
261 editor.fire( 'contentDom' );
262
263 if ( this._.isPendingFocus ) {
264 editor.focus();
265 this._.isPendingFocus = false;
266 }
267
268 setTimeout( function() {
269 editor.fire( 'dataReady' );
270 }, 0 );
271 }, 0, this );
272
273 function removeSuperfluousElement( tagName ) {
274 var lockRetain = false;
275
276 // Superfluous elements appear after keydown
277 // and before keyup, so the procedure is as follows:
278 // 1. On first keydown mark all elements with
279 // a specified tag name as non-superfluous.
280 editable.attachListener( editable, 'keydown', function() {
281 var body = doc.getBody(),
282 retained = body.getElementsByTag( tagName );
283
284 if ( !lockRetain ) {
285 for ( var i = 0; i < retained.count(); i++ ) {
286 retained.getItem( i ).setCustomData( 'retain', true );
287 }
288 lockRetain = true;
289 }
290 }, null, null, 1 );
291
292 // 2. On keyup remove all elements that were not marked
293 // as non-superfluous (which means they must have had appeared in the meantime).
294 // Also we should preserve all temporary elements inserted by editor – otherwise we'd likely
295 // leak fake selection's content into editable due to removing hidden selection container (#14831).
296 editable.attachListener( editable, 'keyup', function() {
297 var elements = doc.getElementsByTag( tagName );
298 if ( lockRetain ) {
299 if ( elements.count() == 1 && !elements.getItem( 0 ).getCustomData( 'retain' ) &&
300 !elements.getItem( 0 ).hasAttribute( 'data-cke-temp' ) ) {
301 elements.getItem( 0 ).remove( 1 );
302 }
303 lockRetain = false;
304 }
305 } );
306 }
307 }
308
309 framedWysiwyg = CKEDITOR.tools.createClass( {
310 $: function() {
311 this.base.apply( this, arguments );
312
313 this._.frameLoadedHandler = CKEDITOR.tools.addFunction( function( win ) {
314 // Avoid opening design mode in a frame window thread,
315 // which will cause host page scrolling.(#4397)
316 CKEDITOR.tools.setTimeout( onDomReady, 0, this, win );
317 }, this );
318
319 this._.docTitle = this.getWindow().getFrame().getAttribute( 'title' );
320 },
321
322 base: CKEDITOR.editable,
323
324 proto: {
325 setData: function( data, isSnapshot ) {
326 var editor = this.editor;
327
328 if ( isSnapshot ) {
329 this.setHtml( data );
330 this.fixInitialSelection();
331
332 // Fire dataReady for the consistency with inline editors
333 // and because it makes sense. (#10370)
334 editor.fire( 'dataReady' );
335 }
336 else {
337 this._.isLoadingData = true;
338 editor._.dataStore = { id: 1 };
339
340 var config = editor.config,
341 fullPage = config.fullPage,
342 docType = config.docType;
343
344 // Build the additional stuff to be included into <head>.
345 var headExtra = CKEDITOR.tools.buildStyleHtml( iframeCssFixes() ).replace( /<style>/, '<style data-cke-temp="1">' );
346
347 if ( !fullPage )
348 headExtra += CKEDITOR.tools.buildStyleHtml( editor.config.contentsCss );
349
350 var baseTag = config.baseHref ? '<base href="' + config.baseHref + '" data-cke-temp="1" />' : '';
351
352 if ( fullPage ) {
353 // Search and sweep out the doctype declaration.
354 data = data.replace( /<!DOCTYPE[^>]*>/i, function( match ) {
355 editor.docType = docType = match;
356 return '';
357 } ).replace( /<\?xml\s[^\?]*\?>/i, function( match ) {
358 editor.xmlDeclaration = match;
359 return '';
360 } );
361 }
362
363 // Get the HTML version of the data.
364 data = editor.dataProcessor.toHtml( data );
365
366 if ( fullPage ) {
367 // Check if the <body> tag is available.
368 if ( !( /<body[\s|>]/ ).test( data ) )
369 data = '<body>' + data;
370
371 // Check if the <html> tag is available.
372 if ( !( /<html[\s|>]/ ).test( data ) )
373 data = '<html>' + data + '</html>';
374
375 // Check if the <head> tag is available.
376 if ( !( /<head[\s|>]/ ).test( data ) )
377 data = data.replace( /<html[^>]*>/, '$&<head><title></title></head>' );
378 else if ( !( /<title[\s|>]/ ).test( data ) )
379 data = data.replace( /<head[^>]*>/, '$&<title></title>' );
380
381 // The base must be the first tag in the HEAD, e.g. to get relative
382 // links on styles.
383 baseTag && ( data = data.replace( /<head[^>]*?>/, '$&' + baseTag ) );
384
385 // Inject the extra stuff into <head>.
386 // Attention: do not change it before testing it well. (V2)
387 // This is tricky... if the head ends with <meta ... content type>,
388 // Firefox will break. But, it works if we place our extra stuff as
389 // the last elements in the HEAD.
390 data = data.replace( /<\/head\s*>/, headExtra + '$&' );
391
392 // Add the DOCTYPE back to it.
393 data = docType + data;
394 } else {
395 data = config.docType +
396 '<html dir="' + config.contentsLangDirection + '"' +
397 ' lang="' + ( config.contentsLanguage || editor.langCode ) + '">' +
398 '<head>' +
399 '<title>' + this._.docTitle + '</title>' +
400 baseTag +
401 headExtra +
402 '</head>' +
403 '<body' + ( config.bodyId ? ' id="' + config.bodyId + '"' : '' ) +
404 ( config.bodyClass ? ' class="' + config.bodyClass + '"' : '' ) +
405 '>' +
406 data +
407 '</body>' +
408 '</html>';
409 }
410
411 if ( CKEDITOR.env.gecko ) {
412 // Hack to make Fx put cursor at the start of doc on fresh focus.
413 data = data.replace( /<body/, '<body contenteditable="true" ' );
414
415 // Another hack which is used by onDomReady to remove a leading
416 // <br> which is inserted by Firefox 3.6 when document.write is called.
417 // This additional <br> is present because of contenteditable="true"
418 if ( CKEDITOR.env.version < 20000 )
419 data = data.replace( /<body[^>]*>/, '$&<!-- cke-content-start -->' );
420 }
421
422 // The script that launches the bootstrap logic on 'domReady', so the document
423 // is fully editable even before the editing iframe is fully loaded (#4455).
424 var bootstrapCode =
425 '<script id="cke_actscrpt" type="text/javascript"' + ( CKEDITOR.env.ie ? ' defer="defer" ' : '' ) + '>' +
426 'var wasLoaded=0;' + // It must be always set to 0 as it remains as a window property.
427 'function onload(){' +
428 'if(!wasLoaded)' + // FF3.6 calls onload twice when editor.setData. Stop that.
429 'window.parent.CKEDITOR.tools.callFunction(' + this._.frameLoadedHandler + ',window);' +
430 'wasLoaded=1;' +
431 '}' +
432 ( CKEDITOR.env.ie ? 'onload();' : 'document.addEventListener("DOMContentLoaded", onload, false );' ) +
433 '</script>';
434
435 // For IE<9 add support for HTML5's elements.
436 // Note: this code must not be deferred.
437 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
438 bootstrapCode +=
439 '<script id="cke_shimscrpt">' +
440 'window.parent.CKEDITOR.tools.enableHtml5Elements(document)' +
441 '</script>';
442 }
443
444 // IE<10 needs this hack to properly enable <base href="...">.
445 // See: http://stackoverflow.com/a/13373180/1485219 (#11910).
446 if ( baseTag && CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) {
447 bootstrapCode +=
448 '<script id="cke_basetagscrpt">' +
449 'var baseTag = document.querySelector( "base" );' +
450 'baseTag.href = baseTag.href;' +
451 '</script>';
452 }
453
454 data = data.replace( /(?=\s*<\/(:?head)>)/, bootstrapCode );
455
456 // Current DOM will be deconstructed by document.write, cleanup required.
457 this.clearCustomData();
458 this.clearListeners();
459
460 editor.fire( 'contentDomUnload' );
461
462 var doc = this.getDocument();
463
464 // Work around Firefox bug - error prune when called from XUL (#320),
465 // defer it thanks to the async nature of this method.
466 try {
467 doc.write( data );
468 } catch ( e ) {
469 setTimeout( function() {
470 doc.write( data );
471 }, 0 );
472 }
473 }
474 },
475
476 getData: function( isSnapshot ) {
477 if ( isSnapshot )
478 return this.getHtml();
479 else {
480 var editor = this.editor,
481 config = editor.config,
482 fullPage = config.fullPage,
483 docType = fullPage && editor.docType,
484 xmlDeclaration = fullPage && editor.xmlDeclaration,
485 doc = this.getDocument();
486
487 var data = fullPage ? doc.getDocumentElement().getOuterHtml() : doc.getBody().getHtml();
488
489 // BR at the end of document is bogus node for Mozilla. (#5293).
490 // Prevent BRs from disappearing from the end of the content
491 // while enterMode is ENTER_BR (#10146).
492 if ( CKEDITOR.env.gecko && config.enterMode != CKEDITOR.ENTER_BR )
493 data = data.replace( /<br>(?=\s*(:?$|<\/body>))/, '' );
494
495 data = editor.dataProcessor.toDataFormat( data );
496
497 if ( xmlDeclaration )
498 data = xmlDeclaration + '\n' + data;
499 if ( docType )
500 data = docType + '\n' + data;
501
502 return data;
503 }
504 },
505
506 focus: function() {
507 if ( this._.isLoadingData )
508 this._.isPendingFocus = true;
509 else
510 framedWysiwyg.baseProto.focus.call( this );
511 },
512
513 detach: function() {
514 var editor = this.editor,
515 doc = editor.document,
516 iframe,
517 onResize;
518
519 // Trying to access window's frameElement property on Edge throws an exception
520 // when frame was already removed from DOM. (#13850, #13790)
521 try {
522 iframe = editor.window.getFrame();
523 } catch ( e ) {}
524
525 framedWysiwyg.baseProto.detach.call( this );
526
527 // Memory leak proof.
528 this.clearCustomData();
529 doc.getDocumentElement().clearCustomData();
530 CKEDITOR.tools.removeFunction( this._.frameLoadedHandler );
531
532 // On IE, iframe is returned even after remove() method is called on it.
533 // Checking if parent is present fixes this issue. (#13850)
534 if ( iframe && iframe.getParent() ) {
535 iframe.clearCustomData();
536 onResize = iframe.removeCustomData( 'onResize' );
537 onResize && onResize.removeListener();
538
539 // IE BUG: When destroying editor DOM with the selection remains inside
540 // editing area would break IE7/8's selection system, we have to put the editing
541 // iframe offline first. (#3812 and #5441)
542 iframe.remove();
543 } else {
544 CKEDITOR.warn( 'editor-destroy-iframe' );
545 }
546 }
547 }
548 } );
549
550 function objectResizeDisabler( editor ) {
551 if ( CKEDITOR.env.gecko ) {
552 // FF allows to change resizing preferences by calling execCommand.
553 try {
554 var doc = editor.document.$;
555 doc.execCommand( 'enableObjectResizing', false, !editor.config.disableObjectResizing );
556 doc.execCommand( 'enableInlineTableEditing', false, !editor.config.disableNativeTableHandles );
557 } catch ( e ) {}
558 } else if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 && editor.config.disableObjectResizing ) {
559 // It's possible to prevent resizing up to IE10.
560 blockResizeStart( editor );
561 }
562
563 // Disables resizing by preventing default action on resizestart event.
564 function blockResizeStart() {
565 var lastListeningElement;
566
567 // We'll attach only one listener at a time, instead of adding it to every img, input, hr etc.
568 // Listener will be attached upon selectionChange, we'll also check if there was any element that
569 // got listener before (lastListeningElement) - if so we need to remove previous listener.
570 editor.editable().attachListener( editor, 'selectionChange', function() {
571 var selectedElement = editor.getSelection().getSelectedElement();
572
573 if ( selectedElement ) {
574 if ( lastListeningElement ) {
575 lastListeningElement.detachEvent( 'onresizestart', resizeStartListener );
576 lastListeningElement = null;
577 }
578
579 // IE requires using attachEvent, because it does not work using W3C compilant addEventListener,
580 // tested with IE10.
581 selectedElement.$.attachEvent( 'onresizestart', resizeStartListener );
582 lastListeningElement = selectedElement.$;
583 }
584 } );
585 }
586
587 function resizeStartListener( evt ) {
588 evt.returnValue = false;
589 }
590 }
591
592 function iframeCssFixes() {
593 var css = [];
594
595 // IE>=8 stricts mode doesn't have 'contentEditable' in effect
596 // on element unless it has layout. (#5562)
597 if ( CKEDITOR.document.$.documentMode >= 8 ) {
598 css.push( 'html.CSS1Compat [contenteditable=false]{min-height:0 !important}' );
599
600 var selectors = [];
601
602 for ( var tag in CKEDITOR.dtd.$removeEmpty )
603 selectors.push( 'html.CSS1Compat ' + tag + '[contenteditable=false]' );
604
605 css.push( selectors.join( ',' ) + '{display:inline-block}' );
606 }
607 // Set the HTML style to 100% to have the text cursor in affect (#6341)
608 else if ( CKEDITOR.env.gecko ) {
609 css.push( 'html{height:100% !important}' );
610 css.push( 'img:-moz-broken{-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}' );
611 }
612
613 // #6341: The text cursor must be set on the editor area.
614 // #6632: Avoid having "text" shape of cursor in IE7 scrollbars.
615 css.push( 'html{cursor:text;*cursor:auto}' );
616
617 // Use correct cursor for these elements
618 css.push( 'img,input,textarea{cursor:default}' );
619
620 return css.join( '\n' );
621 }
622} )();
623
624/**
625 * Disables the ability to resize objects (images and tables) in the editing area.
626 *
627 * config.disableObjectResizing = true;
628 *
629 * **Note:** Because of incomplete implementation of editing features in browsers
630 * this option does not work for inline editors (see ticket [#10197](http://dev.ckeditor.com/ticket/10197)),
631 * does not work in Internet Explorer 11+ (see [#9317](http://dev.ckeditor.com/ticket/9317#comment:16) and
632 * [IE11+ issue](https://connect.microsoft.com/IE/feedback/details/742593/please-respect-execcommand-enableobjectresizing-in-contenteditable-elements)).
633 * In Internet Explorer 8-10 this option only blocks resizing, but it is unable to hide the resize handles.
634 *
635 * @cfg
636 * @member CKEDITOR.config
637 */
638CKEDITOR.config.disableObjectResizing = false;
639
640/**
641 * Disables the "table tools" offered natively by the browser (currently
642 * Firefox only) to perform quick table editing operations, like adding or
643 * deleting rows and columns.
644 *
645 * config.disableNativeTableHandles = false;
646 *
647 * @cfg
648 * @member CKEDITOR.config
649 */
650CKEDITOR.config.disableNativeTableHandles = true;
651
652/**
653 * Disables the built-in spell checker if the browser provides one.
654 *
655 * **Note:** Although word suggestions provided natively by the browsers will
656 * not appear in CKEditor's default context menu,
657 * users can always reach the native context menu by holding the
658 * *Ctrl* key when right-clicking if {@link #browserContextMenuOnCtrl}
659 * is enabled or you are simply not using the
660 * [context menu](http://ckeditor.com/addon/contextmenu) plugin.
661 *
662 * config.disableNativeSpellChecker = false;
663 *
664 * @cfg
665 * @member CKEDITOR.config
666 */
667CKEDITOR.config.disableNativeSpellChecker = true;
668
669/**
670 * Language code of the writing language which is used to author the editor
671 * content. This option accepts one single entry value in the format defined in the
672 * [Tags for Identifying Languages (BCP47)](http://www.ietf.org/rfc/bcp/bcp47.txt)
673 * IETF document and is used in the `lang` attribute.
674 *
675 * config.contentsLanguage = 'fr';
676 *
677 * @cfg {String} [contentsLanguage=same value with editor's UI language]
678 * @member CKEDITOR.config
679 */
680
681/**
682 * The base href URL used to resolve relative and absolute URLs in the
683 * editor content.
684 *
685 * config.baseHref = 'http://www.example.com/path/';
686 *
687 * @cfg {String} [baseHref='']
688 * @member CKEDITOR.config
689 */
690
691/**
692 * Whether to automatically create wrapping blocks around inline content inside the document body.
693 * This helps to ensure the integrity of the block *Enter* mode.
694 *
695 * **Note:** This option is deprecated. Changing the default value might introduce unpredictable usability issues and is
696 * highly unrecommended.
697 *
698 * config.autoParagraph = false;
699 *
700 * @deprecated
701 * @since 3.6
702 * @cfg {Boolean} [autoParagraph=true]
703 * @member CKEDITOR.config
704 */
705
706/**
707 * Fired when some elements are added to the document.
708 *
709 * @event ariaWidget
710 * @member CKEDITOR.editor
711 * @param {CKEDITOR.editor} editor This editor instance.
712 * @param {CKEDITOR.dom.element} data The element being added.
713 */
diff --git a/sources/plugins/wysiwygarea/samples/fullpage.html b/sources/plugins/wysiwygarea/samples/fullpage.html
new file mode 100644
index 0000000..bb3193a
--- /dev/null
+++ b/sources/plugins/wysiwygarea/samples/fullpage.html
@@ -0,0 +1,80 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Full Page Editing &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <script src="../../../samples/old/sample.js"></script>
12 <link rel="stylesheet" href="../../../samples/old/sample.css">
13 <meta name="ckeditor-sample-required-plugins" content="sourcearea">
14 <meta name="ckeditor-sample-name" content="Full page support">
15 <meta name="ckeditor-sample-group" content="Plugins">
16 <meta name="ckeditor-sample-description" content="CKEditor inserted with a JavaScript call and used to edit the whole page from &lt;html&gt; to &lt;/html&gt;.">
17</head>
18<body>
19 <h1 class="samples">
20 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Full Page Editing
21 </h1>
22 <div class="warning deprecated">
23 This sample is not maintained anymore. Check out its <a href="http://sdk.ckeditor.com/samples/fullpage.html">brand new version in CKEditor SDK</a>.
24 </div>
25 <div class="description">
26 <p>
27 This sample shows how to configure CKEditor to edit entire HTML pages, from the
28 <code>&lt;html&gt;</code> tag to the <code>&lt;/html&gt;</code> tag.
29 </p>
30 <p>
31 The CKEditor instance below is inserted with a JavaScript call using the following code:
32 </p>
33<pre class="samples">
34CKEDITOR.replace( '<em>textarea_id</em>', {
35 <strong>fullPage: true</strong>,
36 <strong>allowedContent: true</strong>
37});
38</pre>
39 <p>
40 Note that <code><em>textarea_id</em></code> in the code above is the <code>id</code> attribute of
41 the <code>&lt;textarea&gt;</code> element to be replaced.
42 </p>
43 <p>
44 The <code><em>allowedContent</em></code> in the code above is set to <code>true</code> to disable content filtering.
45 Setting this option is not obligatory, but in full page mode there is a strong chance that one may want be able to freely enter any HTML content in source mode without any limitations.
46 </p>
47 </div>
48 <form action="../../../samples/sample_posteddata.php" method="post">
49 <label for="editor1">
50 CKEditor output the entire page including content outside of
51 <code>&lt;body&gt;</code> element, so content like meta and title can be changed:
52 </label>
53 <textarea cols="80" id="editor1" name="editor1" rows="10">
54 &lt;h1&gt;&lt;img align=&quot;right&quot; alt=&quot;Saturn V carrying Apollo 11&quot; src=&quot;../../../samples/old/assets/sample.jpg&quot;/&gt; Apollo 11&lt;/h1&gt; &lt;p&gt;&lt;b&gt;Apollo 11&lt;/b&gt; was the spaceflight that landed the first humans, Americans &lt;a href=&quot;http://en.wikipedia.org/wiki/Neil_Armstrong&quot; title=&quot;Neil Armstrong&quot;&gt;Neil Armstrong&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Buzz_Aldrin&quot; title=&quot;Buzz Aldrin&quot;&gt;Buzz Aldrin&lt;/a&gt;, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.&lt;/p&gt; &lt;p&gt;Armstrong spent about &lt;s&gt;three and a half&lt;/s&gt; two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5&amp;nbsp;kg) of lunar material for return to Earth. A third member of the mission, &lt;a href=&quot;http://en.wikipedia.org/wiki/Michael_Collins_(astronaut)&quot; title=&quot;Michael Collins (astronaut)&quot;&gt;Michael Collins&lt;/a&gt;, piloted the &lt;a href=&quot;http://en.wikipedia.org/wiki/Apollo_Command/Service_Module&quot; title=&quot;Apollo Command/Service Module&quot;&gt;command&lt;/a&gt; spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.&lt;/p&gt; &lt;h2&gt;Broadcasting and &lt;em&gt;quotes&lt;/em&gt; &lt;a id=&quot;quotes&quot; name=&quot;quotes&quot;&gt;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Broadcast on live TV to a world-wide audience, Armstrong stepped onto the lunar surface and described the event as:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;One small step for [a] man, one giant leap for mankind.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Apollo 11 effectively ended the &lt;a href=&quot;http://en.wikipedia.org/wiki/Space_Race&quot; title=&quot;Space Race&quot;&gt;Space Race&lt;/a&gt; and fulfilled a national goal proposed in 1961 by the late U.S. President &lt;a href=&quot;http://en.wikipedia.org/wiki/John_F._Kennedy&quot; title=&quot;John F. Kennedy&quot;&gt;John F. Kennedy&lt;/a&gt; in a speech before the United States Congress:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;[...] before this decade is out, of landing a man on the Moon and returning him safely to the Earth.&lt;/p&gt;&lt;/blockquote&gt; &lt;h2&gt;Technical details &lt;a id=&quot;tech-details&quot; name=&quot;tech-details&quot;&gt;&lt;/a&gt;&lt;/h2&gt; &lt;table align=&quot;right&quot; border=&quot;1&quot; bordercolor=&quot;#ccc&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; style=&quot;border-collapse:collapse;margin:10px 0 10px 15px;&quot;&gt; &lt;caption&gt;&lt;strong&gt;Mission crew&lt;/strong&gt;&lt;/caption&gt; &lt;thead&gt; &lt;tr&gt; &lt;th scope=&quot;col&quot;&gt;Position&lt;/th&gt; &lt;th scope=&quot;col&quot;&gt;Astronaut&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;Commander&lt;/td&gt; &lt;td&gt;Neil A. Armstrong&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Command Module Pilot&lt;/td&gt; &lt;td&gt;Michael Collins&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Lunar Module Pilot&lt;/td&gt; &lt;td&gt;Edwin &amp;quot;Buzz&amp;quot; E. Aldrin, Jr.&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;Launched by a &lt;strong&gt;Saturn V&lt;/strong&gt; rocket from &lt;a href=&quot;http://en.wikipedia.org/wiki/Kennedy_Space_Center&quot; title=&quot;Kennedy Space Center&quot;&gt;Kennedy Space Center&lt;/a&gt; in Merritt Island, Florida on July 16, Apollo 11 was the fifth manned mission of &lt;a href=&quot;http://en.wikipedia.org/wiki/NASA&quot; title=&quot;NASA&quot;&gt;NASA&lt;/a&gt;&amp;#39;s Apollo program. The Apollo spacecraft had three parts:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;Command Module&lt;/strong&gt; with a cabin for the three astronauts which was the only part which landed back on Earth&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Service Module&lt;/strong&gt; which supported the Command Module with propulsion, electrical power, oxygen and water&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Lunar Module&lt;/strong&gt; for landing on the Moon.&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;After being sent to the Moon by the Saturn V&amp;#39;s upper stage, the astronauts separated the spacecraft from it and travelled for three days until they entered into lunar orbit. Armstrong and Aldrin then moved into the Lunar Module and landed in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Mare_Tranquillitatis&quot; title=&quot;Mare Tranquillitatis&quot;&gt;Sea of Tranquility&lt;/a&gt;. They stayed a total of about 21 and a half hours on the lunar surface. After lifting off in the upper part of the Lunar Module and rejoining Collins in the Command Module, they returned to Earth and landed in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Pacific_Ocean&quot; title=&quot;Pacific Ocean&quot;&gt;Pacific Ocean&lt;/a&gt; on July 24.&lt;/p&gt; &lt;hr/&gt; &lt;p style=&quot;text-align: right;&quot;&gt;&lt;small&gt;Source: &lt;a href=&quot;http://en.wikipedia.org/wiki/Apollo_11&quot;&gt;Wikipedia.org&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
55 </textarea>
56 <script>
57
58 CKEDITOR.replace( 'editor1', {
59 fullPage: true,
60 allowedContent: true,
61 extraPlugins: 'wysiwygarea'
62 });
63
64 </script>
65 <p>
66 <input type="submit" value="Submit">
67 </p>
68 </form>
69 <div id="footer">
70 <hr>
71 <p>
72 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
73 </p>
74 <p id="copy">
75 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
76 Knabben. All rights reserved.
77 </p>
78 </div>
79</body>
80</html>