aboutsummaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2017-12-04 18:55:29 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2017-12-04 18:55:29 +0100
commit1794320dcfdfcd19572fb1676294f9853a6bbc20 (patch)
treea4c9e978947d6930d50391747382d7f95a5863e3 /sources
parent7183f6a6a21ad9124e70c997e0168459f377a9f2 (diff)
downloadludivine-ckeditor-component-1794320dcfdfcd19572fb1676294f9853a6bbc20.tar.gz
ludivine-ckeditor-component-1794320dcfdfcd19572fb1676294f9853a6bbc20.tar.zst
ludivine-ckeditor-component-1794320dcfdfcd19572fb1676294f9853a6bbc20.zip
Update to 4.7.3HEAD4.7.3master
Diffstat (limited to 'sources')
-rw-r--r--sources/CHANGES.md141
-rw-r--r--sources/config.js2
-rw-r--r--sources/core/_bootstrap.js6
-rw-r--r--sources/core/ckeditor.js2
-rw-r--r--sources/core/command.js2
-rw-r--r--sources/core/creators/themedui.js12
-rw-r--r--sources/core/dom/document.js2
-rw-r--r--sources/core/dom/domobject.js4
-rw-r--r--sources/core/dom/element.js36
-rw-r--r--sources/core/dom/elementpath.js22
-rw-r--r--sources/core/dom/iterator.js20
-rw-r--r--sources/core/dom/node.js10
-rw-r--r--sources/core/dom/nodelist.js17
-rw-r--r--sources/core/dom/range.js200
-rw-r--r--sources/core/dom/rangelist.js2
-rw-r--r--sources/core/dom/text.js2
-rw-r--r--sources/core/dom/walker.js10
-rw-r--r--sources/core/editable.js121
-rw-r--r--sources/core/editor.js111
-rw-r--r--sources/core/env.js2
-rw-r--r--sources/core/filter.js37
-rw-r--r--sources/core/focusmanager.js18
-rw-r--r--sources/core/htmldataprocessor.js75
-rw-r--r--sources/core/htmlparser.js2
-rw-r--r--sources/core/htmlparser/basicwriter.js2
-rw-r--r--sources/core/htmlparser/element.js6
-rw-r--r--sources/core/htmlparser/fragment.js14
-rw-r--r--sources/core/lang.js2
-rw-r--r--sources/core/loader.js4
-rw-r--r--sources/core/scriptloader.js4
-rw-r--r--sources/core/selection.js403
-rw-r--r--sources/core/skin.js2
-rw-r--r--sources/core/style.js65
-rw-r--r--sources/core/template.js69
-rw-r--r--sources/core/tools.js167
-rw-r--r--sources/lang/af.js12
-rw-r--r--sources/lang/cs.js6
-rw-r--r--sources/lang/de.js2
-rw-r--r--sources/lang/el.js18
-rw-r--r--sources/lang/eo.js6
-rw-r--r--sources/lang/es-mx.js116
-rw-r--r--sources/lang/fr.js10
-rw-r--r--sources/lang/gl.js8
-rw-r--r--sources/lang/hr.js24
-rw-r--r--sources/lang/hu.js24
-rw-r--r--sources/lang/ja.js2
-rw-r--r--sources/lang/ko.js24
-rw-r--r--sources/lang/ku.js22
-rw-r--r--sources/lang/pt.js6
-rw-r--r--sources/lang/uk.js2
-rw-r--r--sources/plugins/a11yhelp/dialogs/a11yhelp.js32
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/af.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ar.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/az.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/bg.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ca.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/cs.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/cy.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/da.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/de-ch.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/de.js7
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/el.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/en-gb.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/en.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/eo.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/es-mx.js145
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/es.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/et.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/eu.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fa.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fi.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fo.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fr-ca.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/fr.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/gl.js7
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/gu.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/he.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/hi.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/hr.js119
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/hu.js7
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/id.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/it.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ja.js9
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/km.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ko.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ku.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/lt.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/lv.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/mk.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/mn.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/nb.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/nl.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/no.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/oc.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/pl.js13
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/pt-br.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/pt.js25
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ro.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ru.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/si.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sk.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sl.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sq.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sr-latn.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sr.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/sv.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/th.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/tr.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/tt.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/ug.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/uk.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/vi.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/zh-cn.js5
-rw-r--r--sources/plugins/a11yhelp/dialogs/lang/zh.js5
-rw-r--r--sources/plugins/a11yhelp/plugin.js2
-rw-r--r--sources/plugins/basicstyles/lang/es-mx.js12
-rw-r--r--sources/plugins/basicstyles/lang/hr.js4
-rw-r--r--sources/plugins/basicstyles/plugin.js2
-rw-r--r--sources/plugins/button/lang/es-mx.js8
-rw-r--r--sources/plugins/button/lang/hr.js8
-rw-r--r--sources/plugins/button/plugin.js10
-rw-r--r--sources/plugins/clipboard/dev/dnd.html2
-rw-r--r--sources/plugins/clipboard/dialogs/paste.js254
-rw-r--r--sources/plugins/clipboard/lang/af.js5
-rw-r--r--sources/plugins/clipboard/lang/ar.js5
-rw-r--r--sources/plugins/clipboard/lang/az.js5
-rw-r--r--sources/plugins/clipboard/lang/bg.js5
-rw-r--r--sources/plugins/clipboard/lang/bn.js5
-rw-r--r--sources/plugins/clipboard/lang/bs.js5
-rw-r--r--sources/plugins/clipboard/lang/ca.js5
-rw-r--r--sources/plugins/clipboard/lang/cs.js5
-rw-r--r--sources/plugins/clipboard/lang/cy.js5
-rw-r--r--sources/plugins/clipboard/lang/da.js5
-rw-r--r--sources/plugins/clipboard/lang/de-ch.js5
-rw-r--r--sources/plugins/clipboard/lang/de.js5
-rw-r--r--sources/plugins/clipboard/lang/el.js5
-rw-r--r--sources/plugins/clipboard/lang/en-au.js5
-rw-r--r--sources/plugins/clipboard/lang/en-ca.js5
-rw-r--r--sources/plugins/clipboard/lang/en-gb.js5
-rw-r--r--sources/plugins/clipboard/lang/en.js5
-rw-r--r--sources/plugins/clipboard/lang/eo.js5
-rw-r--r--sources/plugins/clipboard/lang/es-mx.js12
-rw-r--r--sources/plugins/clipboard/lang/es.js5
-rw-r--r--sources/plugins/clipboard/lang/et.js5
-rw-r--r--sources/plugins/clipboard/lang/eu.js5
-rw-r--r--sources/plugins/clipboard/lang/fa.js5
-rw-r--r--sources/plugins/clipboard/lang/fi.js5
-rw-r--r--sources/plugins/clipboard/lang/fo.js5
-rw-r--r--sources/plugins/clipboard/lang/fr-ca.js5
-rw-r--r--sources/plugins/clipboard/lang/fr.js5
-rw-r--r--sources/plugins/clipboard/lang/gl.js5
-rw-r--r--sources/plugins/clipboard/lang/gu.js5
-rw-r--r--sources/plugins/clipboard/lang/he.js5
-rw-r--r--sources/plugins/clipboard/lang/hi.js5
-rw-r--r--sources/plugins/clipboard/lang/hr.js5
-rw-r--r--sources/plugins/clipboard/lang/hu.js5
-rw-r--r--sources/plugins/clipboard/lang/id.js5
-rw-r--r--sources/plugins/clipboard/lang/is.js5
-rw-r--r--sources/plugins/clipboard/lang/it.js5
-rw-r--r--sources/plugins/clipboard/lang/ja.js5
-rw-r--r--sources/plugins/clipboard/lang/ka.js5
-rw-r--r--sources/plugins/clipboard/lang/km.js5
-rw-r--r--sources/plugins/clipboard/lang/ko.js5
-rw-r--r--sources/plugins/clipboard/lang/ku.js5
-rw-r--r--sources/plugins/clipboard/lang/lt.js5
-rw-r--r--sources/plugins/clipboard/lang/lv.js5
-rw-r--r--sources/plugins/clipboard/lang/mk.js5
-rw-r--r--sources/plugins/clipboard/lang/mn.js5
-rw-r--r--sources/plugins/clipboard/lang/ms.js5
-rw-r--r--sources/plugins/clipboard/lang/nb.js5
-rw-r--r--sources/plugins/clipboard/lang/nl.js5
-rw-r--r--sources/plugins/clipboard/lang/no.js5
-rw-r--r--sources/plugins/clipboard/lang/oc.js5
-rw-r--r--sources/plugins/clipboard/lang/pl.js5
-rw-r--r--sources/plugins/clipboard/lang/pt-br.js5
-rw-r--r--sources/plugins/clipboard/lang/pt.js5
-rw-r--r--sources/plugins/clipboard/lang/ro.js5
-rw-r--r--sources/plugins/clipboard/lang/ru.js5
-rw-r--r--sources/plugins/clipboard/lang/si.js5
-rw-r--r--sources/plugins/clipboard/lang/sk.js5
-rw-r--r--sources/plugins/clipboard/lang/sl.js5
-rw-r--r--sources/plugins/clipboard/lang/sq.js5
-rw-r--r--sources/plugins/clipboard/lang/sr-latn.js5
-rw-r--r--sources/plugins/clipboard/lang/sr.js5
-rw-r--r--sources/plugins/clipboard/lang/sv.js9
-rw-r--r--sources/plugins/clipboard/lang/th.js5
-rw-r--r--sources/plugins/clipboard/lang/tr.js5
-rw-r--r--sources/plugins/clipboard/lang/tt.js5
-rw-r--r--sources/plugins/clipboard/lang/ug.js5
-rw-r--r--sources/plugins/clipboard/lang/uk.js5
-rw-r--r--sources/plugins/clipboard/lang/vi.js5
-rw-r--r--sources/plugins/clipboard/lang/zh-cn.js5
-rw-r--r--sources/plugins/clipboard/lang/zh.js5
-rw-r--r--sources/plugins/clipboard/plugin.js332
-rw-r--r--sources/plugins/colorbutton/lang/az.js48
-rw-r--r--sources/plugins/colorbutton/lang/cs.js14
-rw-r--r--sources/plugins/colorbutton/lang/de.js34
-rw-r--r--sources/plugins/colorbutton/lang/el.js6
-rw-r--r--sources/plugins/colorbutton/lang/eo.js44
-rw-r--r--sources/plugins/colorbutton/lang/es-mx.js75
-rw-r--r--sources/plugins/colorbutton/lang/fr.js44
-rw-r--r--sources/plugins/colorbutton/lang/gl.js44
-rw-r--r--sources/plugins/colorbutton/lang/hr.js44
-rw-r--r--sources/plugins/colorbutton/lang/hu.js44
-rw-r--r--sources/plugins/colorbutton/lang/ja.js44
-rw-r--r--sources/plugins/colorbutton/lang/ko.js44
-rw-r--r--sources/plugins/colorbutton/lang/ku.js22
-rw-r--r--sources/plugins/colorbutton/lang/nb.js44
-rw-r--r--sources/plugins/colorbutton/lang/pt-br.js44
-rw-r--r--sources/plugins/colorbutton/lang/pt.js40
-rw-r--r--sources/plugins/colorbutton/lang/ru.js16
-rw-r--r--sources/plugins/colorbutton/lang/sk.js44
-rw-r--r--sources/plugins/colorbutton/lang/sv.js44
-rw-r--r--sources/plugins/colorbutton/lang/tr.js44
-rw-r--r--sources/plugins/colorbutton/lang/zh-cn.js124
-rw-r--r--sources/plugins/colorbutton/lang/zh.js46
-rw-r--r--sources/plugins/colorbutton/plugin.js134
-rw-r--r--sources/plugins/colordialog/lang/es-mx.js11
-rw-r--r--sources/plugins/colordialog/lang/nb.js4
-rw-r--r--sources/plugins/colordialog/plugin.js2
-rw-r--r--sources/plugins/contextmenu/lang/es-mx.js7
-rw-r--r--sources/plugins/contextmenu/plugin.js27
-rw-r--r--sources/plugins/dialog/plugin.js58
-rw-r--r--sources/plugins/dialogui/plugin.js14
-rw-r--r--sources/plugins/div/dialogs/div.js34
-rw-r--r--sources/plugins/div/lang/es-mx.js19
-rw-r--r--sources/plugins/div/lang/ja.js4
-rw-r--r--sources/plugins/div/lang/pt.js4
-rw-r--r--sources/plugins/div/plugin.js4
-rw-r--r--sources/plugins/elementspath/lang/es-mx.js8
-rw-r--r--sources/plugins/elementspath/lang/hr.js2
-rw-r--r--sources/plugins/elementspath/plugin.js10
-rw-r--r--sources/plugins/enterkey/plugin.js25
-rw-r--r--sources/plugins/fakeobjects/lang/es-mx.js11
-rw-r--r--sources/plugins/fakeobjects/plugin.js28
-rw-r--r--sources/plugins/filebrowser/plugin.js2
-rw-r--r--sources/plugins/floatingspace/plugin.js8
-rw-r--r--sources/plugins/floatpanel/plugin.js48
-rw-r--r--sources/plugins/font/lang/es-mx.js14
-rw-r--r--sources/plugins/font/lang/hr.js2
-rw-r--r--sources/plugins/font/plugin.js6
-rw-r--r--sources/plugins/format/lang/es-mx.js18
-rw-r--r--sources/plugins/format/lang/hr.js20
-rw-r--r--sources/plugins/format/plugin.js4
-rw-r--r--sources/plugins/horizontalrule/lang/es-mx.js7
-rw-r--r--sources/plugins/horizontalrule/plugin.js2
-rw-r--r--sources/plugins/html5audio/dialogs/html5audio.js18
-rw-r--r--sources/plugins/html5audio/lang/de.js1
-rw-r--r--sources/plugins/html5audio/lang/el.js14
-rw-r--r--sources/plugins/html5audio/lang/en.js1
-rw-r--r--sources/plugins/html5audio/lang/es.js1
-rw-r--r--sources/plugins/html5audio/lang/eu.js1
-rw-r--r--sources/plugins/html5audio/lang/fr.js1
-rw-r--r--sources/plugins/html5audio/lang/ru.js1
-rw-r--r--sources/plugins/html5audio/lang/uk.js1
-rw-r--r--sources/plugins/html5audio/lang/uz.js1
-rw-r--r--sources/plugins/html5audio/lang/zh-cn.js14
-rw-r--r--sources/plugins/html5audio/plugin.js14
-rw-r--r--sources/plugins/html5video/dialogs/html5video.js13
-rw-r--r--sources/plugins/html5video/lang/en.js3
-rw-r--r--sources/plugins/html5video/lang/ru.js3
-rw-r--r--sources/plugins/html5video/plugin.js28
-rw-r--r--sources/plugins/htmlwriter/plugin.js4
-rw-r--r--sources/plugins/iframe/dialogs/iframe.js2
-rw-r--r--sources/plugins/iframe/lang/es-mx.js11
-rw-r--r--sources/plugins/iframe/lang/hr.js2
-rw-r--r--sources/plugins/iframe/plugin.js2
-rw-r--r--sources/plugins/image/dialogs/image.js8
-rw-r--r--sources/plugins/image/lang/es-mx.js25
-rw-r--r--sources/plugins/image/lang/hr.js2
-rw-r--r--sources/plugins/image/lang/pt.js8
-rw-r--r--sources/plugins/image/plugin.js8
-rw-r--r--sources/plugins/indent/lang/es-mx.js8
-rw-r--r--sources/plugins/indent/plugin.js2
-rw-r--r--sources/plugins/indentlist/plugin.js27
-rw-r--r--sources/plugins/justify/lang/es-mx.js10
-rw-r--r--sources/plugins/justify/plugin.js41
-rw-r--r--sources/plugins/lineutils/plugin.js10
-rw-r--r--sources/plugins/link/dialogs/anchor.js27
-rw-r--r--sources/plugins/link/dialogs/link.js202
-rw-r--r--sources/plugins/link/lang/eo.js4
-rw-r--r--sources/plugins/link/lang/es-mx.js67
-rw-r--r--sources/plugins/link/lang/fr.js4
-rw-r--r--sources/plugins/link/lang/gl.js4
-rw-r--r--sources/plugins/link/lang/hr.js16
-rw-r--r--sources/plugins/link/lang/hu.js4
-rw-r--r--sources/plugins/link/lang/ja.js4
-rw-r--r--sources/plugins/link/lang/ko.js4
-rw-r--r--sources/plugins/link/lang/ku.js4
-rw-r--r--sources/plugins/link/lang/ru.js2
-rw-r--r--sources/plugins/link/lang/sk.js4
-rw-r--r--sources/plugins/link/lang/zh.js2
-rw-r--r--sources/plugins/link/plugin.js104
-rw-r--r--sources/plugins/list/lang/es-mx.js8
-rw-r--r--sources/plugins/list/plugin.js40
-rw-r--r--sources/plugins/listblock/plugin.js12
-rw-r--r--sources/plugins/liststyle/lang/es-mx.js25
-rw-r--r--sources/plugins/liststyle/plugin.js2
-rw-r--r--sources/plugins/magicline/lang/es-mx.js8
-rw-r--r--sources/plugins/magicline/lang/pt.js2
-rw-r--r--sources/plugins/magicline/plugin.js14
-rw-r--r--sources/plugins/maximize/lang/es-mx.js8
-rw-r--r--sources/plugins/maximize/plugin.js32
-rw-r--r--sources/plugins/menu/plugin.js10
-rw-r--r--sources/plugins/notification/lang/az.js7
-rw-r--r--sources/plugins/notification/lang/ca.js7
-rw-r--r--sources/plugins/notification/lang/cs.js7
-rw-r--r--sources/plugins/notification/lang/da.js7
-rw-r--r--sources/plugins/notification/lang/de-ch.js7
-rw-r--r--sources/plugins/notification/lang/de.js7
-rw-r--r--sources/plugins/notification/lang/en.js7
-rw-r--r--sources/plugins/notification/lang/eo.js7
-rw-r--r--sources/plugins/notification/lang/es-mx.js7
-rw-r--r--sources/plugins/notification/lang/es.js7
-rw-r--r--sources/plugins/notification/lang/eu.js7
-rw-r--r--sources/plugins/notification/lang/fr.js7
-rw-r--r--sources/plugins/notification/lang/gl.js7
-rw-r--r--sources/plugins/notification/lang/hr.js7
-rw-r--r--sources/plugins/notification/lang/hu.js7
-rw-r--r--sources/plugins/notification/lang/id.js7
-rw-r--r--sources/plugins/notification/lang/it.js7
-rw-r--r--sources/plugins/notification/lang/ja.js7
-rw-r--r--sources/plugins/notification/lang/km.js7
-rw-r--r--sources/plugins/notification/lang/ko.js7
-rw-r--r--sources/plugins/notification/lang/ku.js7
-rw-r--r--sources/plugins/notification/lang/nb.js7
-rw-r--r--sources/plugins/notification/lang/nl.js7
-rw-r--r--sources/plugins/notification/lang/oc.js7
-rw-r--r--sources/plugins/notification/lang/pl.js7
-rw-r--r--sources/plugins/notification/lang/pt-br.js7
-rw-r--r--sources/plugins/notification/lang/pt.js7
-rw-r--r--sources/plugins/notification/lang/ru.js7
-rw-r--r--sources/plugins/notification/lang/sk.js7
-rw-r--r--sources/plugins/notification/lang/sv.js7
-rw-r--r--sources/plugins/notification/lang/tr.js7
-rw-r--r--sources/plugins/notification/lang/ug.js7
-rw-r--r--sources/plugins/notification/lang/uk.js7
-rw-r--r--sources/plugins/notification/lang/zh-cn.js7
-rw-r--r--sources/plugins/notification/lang/zh.js7
-rw-r--r--sources/plugins/notification/plugin.js929
-rw-r--r--sources/plugins/panel/plugin.js69
-rw-r--r--sources/plugins/popup/plugin.js2
-rw-r--r--sources/plugins/removeformat/lang/es-mx.js7
-rw-r--r--sources/plugins/removeformat/plugin.js4
-rw-r--r--sources/plugins/resize/plugin.js4
-rw-r--r--sources/plugins/richcombo/plugin.js19
-rw-r--r--sources/plugins/sourcearea/lang/es-mx.js7
-rw-r--r--sources/plugins/sourcearea/plugin.js8
-rw-r--r--sources/plugins/toolbar/lang/es-mx.js22
-rw-r--r--sources/plugins/toolbar/plugin.js12
-rw-r--r--sources/plugins/widget/dev/assets/simplebox/plugin.js2
-rw-r--r--sources/plugins/widget/lang/eo.js2
-rw-r--r--sources/plugins/widget/lang/es-mx.js8
-rw-r--r--sources/plugins/widget/lang/gl.js2
-rw-r--r--sources/plugins/widget/lang/hr.js4
-rw-r--r--sources/plugins/widget/lang/hu.js2
-rw-r--r--sources/plugins/widget/lang/ko.js2
-rw-r--r--sources/plugins/widget/lang/sk.js2
-rw-r--r--sources/plugins/widget/plugin.js91
-rw-r--r--sources/plugins/widgetselection/plugin.js2
-rw-r--r--sources/plugins/wysiwygarea/plugin.js54
-rw-r--r--sources/samples/index.html2
-rw-r--r--sources/samples/old/assets/uilanguages/languages.js1
-rw-r--r--sources/samples/toolbarconfigurator/index.html2
-rw-r--r--sources/samples/toolbarconfigurator/lib/codemirror/codemirror.js16
-rw-r--r--sources/styles.js2
366 files changed, 5178 insertions, 2242 deletions
diff --git a/sources/CHANGES.md b/sources/CHANGES.md
index 1419e55..31a6299 100644
--- a/sources/CHANGES.md
+++ b/sources/CHANGES.md
@@ -1,6 +1,145 @@
1CKEditor 4 Changelog 1CKEditor 4 Changelog
2==================== 2====================
3 3
4## CKEditor 4.7.3
5
6New Features:
7
8* [#568](https://github.com/ckeditor/ckeditor-dev/issues/568): Added possibility to adjust nested editables' filters using the [`CKEDITOR.filter.disallowedContent`](https://docs.ckeditor.com/#!/api/CKEDITOR.filter-property-disallowedContent) property.
9
10Fixed Issues:
11
12* [#554](https://github.com/ckeditor/ckeditor-dev/issues/554): Fixed: [`change`](https://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-change) event not fired when typing the first character after pasting into the editor. Thanks to [Daniel Miller](https://github.com/millerdev)!
13* [#566](https://github.com/ckeditor/ckeditor-dev/issues/566): Fixed: The CSS `border` shorthand property with zero width (`border: 0px solid #000;`) causes the table to have the border attribute set to 1.
14* [#779](https://github.com/ckeditor/ckeditor-dev/issues/779): Fixed: The [Remove Format](https://ckeditor.com/addon/removeformat) plugin removes elements with language definition inserted by the [Language](https://ckeditor.com/addon/language) plugin.
15* [#423](https://github.com/ckeditor/ckeditor-dev/issues/423): Fixed: The [Paste from Word](https://ckeditor.com/addon/pastefromword) plugin pastes paragraphs into the editor even if [`CKEDITOR.config.enterMode`](https://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-enterMode) is set to `CKEDITOR.ENTER_BR`.
16* [#719](https://github.com/ckeditor/ckeditor-dev/issues/719): Fixed: Image inserted using the [Enhanced Image](https://ckeditor.com/addon/image2) plugin can be resized when the editor is in [read-only mode](https://docs.ckeditor.com/#!/guide/dev_readonly).
17* [#577](https://github.com/ckeditor/ckeditor-dev/issues/577): Fixed: The "Delete Columns" command provided by the [Table Tools](https://ckeditor.com/addon/tabletools) plugin throws an error when trying to delete columns.
18* [#867](https://github.com/ckeditor/ckeditor-dev/issues/867): Fixed: Typing into a selected table throws an error.
19* [#817](https://github.com/ckeditor/ckeditor-dev/issues/817): Fixed: The [Save](https://ckeditor.com/addon/save) plugin does not work in [Source Mode](https://ckeditor.com/addon/sourcearea).
20
21Other Changes:
22
23* Updated the [WebSpellChecker](http://ckeditor.com/addon/wsc) plugin:
24 * [#40](https://github.com/WebSpellChecker/ckeditor-plugin-wsc/issues/40): Fixed: IE10 throws an error when spell checking is started.
25* [#800](https://github.com/ckeditor/ckeditor-dev/issues/800): Added the [`CKEDITOR.dom.selection.isCollapsed`](https://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-isCollapsed) method which is a simpler way to check if the selection is collapsed.
26* [#830](https://github.com/ckeditor/ckeditor-dev/issues/830): Added an option to define which dialog tab should be shown by default when creating [`CKEDITOR.dialogCommand`](https://docs.ckeditor.com/#!/api/CKEDITOR.dialogCommand).
27
28## CKEditor 4.7.2
29
30New Features:
31
32* [#455](https://github.com/ckeditor/ckeditor-dev/issues/455): Added [Advanced Content Filter](https://docs.ckeditor.com/#!/guide/dev_acf) integration with the [Justify](http://ckeditor.com/addon/justify) plugin.
33
34Fixed Issues:
35
36* [#663](https://github.com/ckeditor/ckeditor-dev/issues/663): [Chrome] Fixed: Clicking the scrollbar throws an `Uncaught TypeError: element.is is not a function` error.
37* [#694](https://github.com/ckeditor/ckeditor-dev/pull/694): Refactoring in the [Table Selection](http://ckeditor.com/addon/tableselection) plugin:
38 * [#520](https://github.com/ckeditor/ckeditor-dev/issues/520): Fixed: Widgets cannot be properly pasted into a table cell.
39 * [#460](https://github.com/ckeditor/ckeditor-dev/issues/460): Fixed: Editor gone after pasting into an editor within a table.
40* [#579](https://github.com/ckeditor/ckeditor-dev/issues/579): Fixed: Internal `cke_table-faked-selection-table` class is visible in the Stylesheet Classes field of the [Table Properties](http://ckeditor.com/addon/table) dialog.
41* [#545](https://github.com/ckeditor/ckeditor-dev/issues/545): [Edge] Fixed: Error thrown when pressing the [Select All](https://ckeditor.com/addon/selectall) button in [Source Mode](http://ckeditor.com/addon/sourcearea).
42* [#582](https://github.com/ckeditor/ckeditor-dev/issues/582): Fixed: Double slash in the path to stylesheet needed by the [Table Selection](http://ckeditor.com/addon/tableselection) plugin. Thanks to [Marius Dumitru Florea](https://github.com/mflorea)!
43* [#491](https://github.com/ckeditor/ckeditor-dev/issues/491): Fixed: Unnecessary dependency on the [Editor Toolbar](http://ckeditor.com/addon/toolbar) plugin inside the [Notification](http://ckeditor.com/addon/notification) plugin.
44* [#646](https://github.com/ckeditor/ckeditor-dev/issues/646): Fixed: Error thrown into the browser console after opening the [Styles Combo](http://ckeditor.com/addon/stylescombo) plugin menu in the editor without any selection.
45* [#501](https://github.com/ckeditor/ckeditor-dev/issues/501): Fixed: Double click does not open the dialog for modifying anchors inserted via the [Link](http://ckeditor.com/addon/link) plugin.
46* [#9780](https://dev.ckeditor.com/ticket/9780): [IE8-9] Fixed: Clicking inside an empty [read-only](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-readOnly) editor throws an error.
47* [#16820](https://dev.ckeditor.com/ticket/16820): [IE10] Fixed: Clicking below a single horizontal rule throws an error.
48* [#426](https://github.com/ckeditor/ckeditor-dev/issues/426): Fixed: The [`range.cloneContents`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.range-method-cloneContents) method selects the whole element when the selection starts at the beginning of that element.
49* [#644](https://github.com/ckeditor/ckeditor-dev/issues/644): Fixed: The [`range.extractContents`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.range-method-extractContents) method returns an incorrect result when multiple nodes are selected.
50* [#684](https://github.com/ckeditor/ckeditor-dev/issues/684): Fixed: The [`elementPath.contains`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.elementPath-method-contains) method incorrectly excludes the last element instead of root when the `fromTop` parameter is set to `true`.
51
52Other Changes:
53
54* Updated the [SCAYT](http://ckeditor.com/addon/scayt) (Spell Check As You Type) plugin:
55 * [#148](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/148): Fixed: SCAYT leaves underlined word after the CKEditor Replace dialog corrects it.
56* [#751](https://github.com/ckeditor/ckeditor-dev/issues/751): Added the [`CKEDITOR.dom.nodeList.toArray`](https://docs.ckeditor.com/#!/api/CKEDITOR.dom.nodeList-method-toArray) method which returns an array representation of a [node list](https://docs.ckeditor.com/#!/api/CKEDITOR.dom.nodeList).
57
58## CKEditor 4.7.1
59
60New Features:
61
62* Added a new Mexican Spanish localization. Thanks to [David Alexandro Rodriguez](https://www.transifex.com/user/profile/darsco16/)!
63* [#413](https://github.com/ckeditor/ckeditor-dev/issues/413): Added Paste as Plain Text keyboard shortcut to the [Accessibility Help](http://ckeditor.com/addon/a11yhelp) instructions.
64
65Fixed Issues:
66
67* [#515](https://github.com/ckeditor/ckeditor-dev/issues/515): [Chrome] Fixed: Mouse actions on CKEditor scrollbar throw an exception when the [Table Selection](http://ckeditor.com/addon/tableselection) plugin is loaded.
68* [#493](https://github.com/ckeditor/ckeditor-dev/issues/493): Fixed: Selection started from a nested table causes an error in the browser while scrolling down.
69* [#415](https://github.com/ckeditor/ckeditor-dev/issues/415): [Firefox] Fixed: <kbd>Enter</kbd> key breaks the table structure when pressed in a table selection.
70* [#457](https://github.com/ckeditor/ckeditor-dev/issues/457): Fixed: Error thrown when deleting content from the editor with no selection.
71* [#478](https://github.com/ckeditor/ckeditor-dev/issues/478): [Chrome] Fixed: Error thrown by the [Enter Key](http://ckeditor.com/addon/enterkey) plugin when pressing <kbd>Enter</kbd> with no selection.
72* [#424](https://github.com/ckeditor/ckeditor-dev/issues/424): Fixed: Error thrown by [Tab Key Handling](http://ckeditor.com/addon/tab) and [Indent List](http://ckeditor.com/addon/indentlist) plugins when pressing <kbd>Tab</kbd> with no selection in inline editor.
73* [#476](https://github.com/ckeditor/ckeditor-dev/issues/476): Fixed: Anchors inserted with the [Link](http://ckeditor.com/addon/link) plugin on collapsed selection cannot be edited.
74* [#417](https://github.com/ckeditor/ckeditor-dev/issues/417): Fixed: The [Table Resize](http://ckeditor.com/addon/tableresize) plugin throws an error when used with a table with only header or footer rows.
75* [#523](https://github.com/ckeditor/ckeditor-dev/issues/523): Fixed: The [`editor.getCommandKeystroke`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getCommandKeystroke) method does not obtain the correct keystroke.
76* [#534](https://github.com/ckeditor/ckeditor-dev/issues/534): [IE] Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) does not work in Quirks Mode.
77* [#450](https://github.com/ckeditor/ckeditor-dev/issues/450): Fixed: [`CKEDITOR.filter`](http://docs.ckeditor.com/#!/api/CKEDITOR.filter) incorrectly transforms the `margin` CSS property.
78
79## CKEditor 4.7
80
81**Important Notes:**
82
83* [#13793](http://dev.ckeditor.com/ticket/13793): The [`embed_provider`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-embed_provider) configuration option for the [Media Embed](http://ckeditor.com/addon/embed) and [Semantic Media Embed](http://ckeditor.com/addon/embedsemantic) plugins is no longer preset by default.
84* The [UI Color](http://ckeditor.com/addon/uicolor) plugin now uses a custom color picker instead of the `YUI 2.7.0` library which has some known vulnerabilities (it's a security precaution, there was no security issue in CKEditor due to the way it was used).
85
86New Features:
87
88* [#16755](http://dev.ckeditor.com/ticket/16755): Added the [Table Selection](http://ckeditor.com/addon/tableselection) plugin that lets you select and manipulate an arbitrary rectangular table fragment (a few cells, a row or a column).
89* [#16961](http://dev.ckeditor.com/ticket/16961): Added support for pasting from Microsoft Excel.
90* [#13381](http://dev.ckeditor.com/ticket/13381): Dynamic code evaluation call in [`CKEDITOR.template`](http://docs.ckeditor.com/#!/api/CKEDITOR.template) removed. CKEditor can now be used without the `unsafe-eval` Content Security Policy. Thanks to [Caridy Patiño](http://caridy.name)!
91* [#16971](http://dev.ckeditor.com/ticket/16971): Added support for color in the `background` property containing also other styles for table cells in the [Table Tools](http://ckeditor.com/addon/tabletools) plugin.
92* [#16847](http://dev.ckeditor.com/ticket/16847): Added support for parsing and inlining any formatting created using the Microsoft Word style system to the [Paste from Word](http://ckeditor.com/addon/pastefromword) plugin.
93* [#16818](http://dev.ckeditor.com/ticket/16818): Added table cell height parsing in the [Paste from Word](http://ckeditor.com/addon/pastefromword) plugin.
94* [#16850](http://dev.ckeditor.com/ticket/16850): Added a new [`config.enableContextMenu`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-enableContextMenu) configuration option for enabling and disabling the [context menu](http://ckeditor.com/addon/contextmenu).
95* [#16937](http://dev.ckeditor.com/ticket/16937): The `command` parameter in [CKEDITOR.editor.getCommandKeystroke](http://docs.ckeditor.dev/#!/api/CKEDITOR.editor-method-getCommandKeystroke) now also accepts a command name as an argument.
96* [#17010](http://dev.ckeditor.com/ticket/17010): The [`CKEDITOR.dom.range.shrink`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.range-method-shrink) method now allows for skipping bogus `<br>` elements.
97
98Fixed Issues:
99
100* [#16935](http://dev.ckeditor.com/ticket/16935): [Chrome] Fixed: Blurring the editor in [Source Mode](http://ckeditor.com/addon/sourcearea) throws an error.
101* [#16825](http://dev.ckeditor.com/ticket/16825): [Chrome] Fixed: Error thrown when destroying a focused inline editor.
102* [#16857](http://dev.ckeditor.com/ticket/16857): Fixed: <kbd>Ctrl+Shift+V</kbd> blocked by [Copy Formatting](http://ckeditor.com/addon/copyformatting).
103* [#16845](https://dev.ckeditor.com/ticket/16845): [IE] Fixed: Cursor jumps to the top of the scrolled editor after focusing it when the [Copy Formatting](http://ckeditor.com/addon/copyformatting) plugin is enabled.
104* [#16786](http://dev.ckeditor.com/ticket/16786): Fixed: Added missing translations for the [Copy Formatting](http://ckeditor.com/addon/copyformatting) plugin.
105* [#14714](http://dev.ckeditor.com/ticket/14714): [WebKit/Blink] Fixed: Exception thrown on refocusing a blurred inline editor.
106* [#16913](http://dev.ckeditor.com/ticket/16913): [Firefox, IE] Fixed: [Paste as Plain Text](http://ckeditor.com/addon/pastetext) keystroke does not work.
107* [#16968](http://dev.ckeditor.com/ticket/16968): Fixed: [Safari] [Paste as Plain Text](http://ckeditor.com/addon/pastetext) is not handled by the editor.
108* [#16912](http://dev.ckeditor.com/ticket/16912): Fixed: Exception thrown when a single image is pasted using [Paste from Word](http://ckeditor.com/addon/pastefromword).
109* [#16821](http://dev.ckeditor.com/ticket/16821): Fixed: Extraneous `<span>` elements with `height` style stacked when [pasting from Word](http://ckeditor.com/addon/pastefromword).
110* [#16866](http://dev.ckeditor.com/ticket/16866): [IE, Edge] Fixed: Whitespaces not preserved when [pasting from Word](http://ckeditor.com/addon/pastefromword).
111* [#16860](http://dev.ckeditor.com/ticket/16860): Fixed: Paragraphs which only look like lists incorrectly transformed into them when [pasting from Word](http://ckeditor.com/addon/pastefromword).
112* [#16817](http://dev.ckeditor.com/ticket/16817): Fixed: When [pasting from Word](http://ckeditor.com/addon/pastefromword), paragraphs are transformed into lists with some corrupted data.
113* [#16833](http://dev.ckeditor.com/ticket/16833): [IE11] Fixed: Malformed list with headers [pasted from Word](http://ckeditor.com/addon/pastefromword).
114* [#16826](http://dev.ckeditor.com/ticket/16826): [IE] Fixed: Superfluous paragraphs within lists [pasted from Word](http://ckeditor.com/addon/pastefromword).
115* [#12465](http://dev.ckeditor.com/ticket/12465): Fixed: Cannot change the state of checkboxes or radio buttons if the properties dialog was invoked with a double-click.
116* [#13062](http://dev.ckeditor.com/ticket/13062): Fixed: Impossible to unlink when the caret is at the edge of the link.
117* [#13585](http://dev.ckeditor.com/ticket/13585): Fixed: Error when wrapping two adjacent `<div>` elements with a `<div>`.
118* [#16811](http://dev.ckeditor.com/ticket/16811): Fixed: Table alignment is not preserved by the [Paste from Word](http://ckeditor.com/addon/pastefromword) plugin.
119* [#16810](http://dev.ckeditor.com/ticket/16810): Fixed: Vertical align in tables is not supported by the [Paste from Word](http://ckeditor.com/addon/pastefromword) plugin.
120* [#11956](http://dev.ckeditor.com/ticket/11956): [Blink, IE] Fixed: [Link](http://ckeditor.com/addon/link) dialog does not open on a double click on the second word of the link with a background color or other styles.
121* [#10472](http://dev.ckeditor.com/ticket/10472): Fixed: Unable to use [Table Resize](http://ckeditor.com/addon/tableresize) on table header and footer.
122* [#14762](http://dev.ckeditor.com/ticket/14762): Fixed: Hovering over an empty table (without rows or cells) throws an error when the [Table Resize](http://ckeditor.com/addon/tableresize) plugin is active.
123* [#16777](https://dev.ckeditor.com/ticket/16777): [Edge] Fixed: The [Clipboard](http://ckeditor.com/addon/clipboard) plugin does not allow to drop widgets into the editor.
124* [#14894](https://dev.ckeditor.com/ticket/14894): [Chrome] Fixed: The editor scrolls to the top after focusing or when a dialog is opened.
125* [#14769](https://dev.ckeditor.com/ticket/14769): Fixed: URLs with '-' in host are not detected by the [Auto Link](http://ckeditor.com/addon/autolink) plugin.
126* [#16804](https://dev.ckeditor.com/ticket/16804): Fixed: Focus is not on the first menu item when the user opens a context menu or a drop-down list from the editor toolbar.
127* [#14407](https://dev.ckeditor.com/ticket/14407): [IE] Fixed: Non-editable widgets can be edited.
128* [#16927](https://dev.ckeditor.com/ticket/16927): Fixed: An error thrown if a bundle containing the [Color Button](http://ckeditor.com/addon/colorbutton) plugin is run in ES5 strict mode. Thanks to [Igor Rubinovich](https://github.com/IgorRubinovich)!
129* [#16920](http://dev.ckeditor.com/ticket/16920): Fixed: Several plugins not using the [Dialog](http://ckeditor.com/addon/dialog) plugin as a direct dependency.
130* [PR#336](https://github.com/ckeditor/ckeditor-dev/pull/336): Fixed: Typo in [`CKEDITOR.getCss`](http://docs.ckeditor.com/#!/api/CKEDITOR-method-getCss) API documentation. Thanks to [knusperpixel](https://github.com/knusperpixel)!
131* [#17027](http://dev.ckeditor.com/ticket/17027): Fixed: Command event data should be initialized as an empty object.
132* Fixed the behavior of HTML parser when parsing `src`/`srcdoc` attributes of the `<iframe>` element in a CKEditor setup with ACF turned off and without the [Iframe Dialog](http://ckeditor.com/addon/iframe) plugin. The issue was originally reported as a security issue by [Sriramk21](https://twitter.com/sriramk21) from Pegasystems and was later downgraded by the security team into a normal issue due to the requirement of having ACF turned off. Disabling [Advanced Content Filter](http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter) is against [security best practices](http://docs.ckeditor.com/#!/guide/dev_best_practices-section-security), so the problem described above has not been considered a security issue as such.
133
134Other Changes:
135
136* Updated [SCAYT](http://ckeditor.com/addon/scayt) (Spell Check As You Type) and [WebSpellChecker](http://ckeditor.com/addon/wsc) plugins:
137 * Fixed: DOM Exception after clicking "Remove Language" on a selected word with enabled [Language](http://ckeditor.com/addon/language) plugin in SCAYT.
138* [#16958](http://dev.ckeditor.com/ticket/16958): Switched the default MathJax CDN provider for the [Mathematical Formulas](http://ckeditor.com/addon/mathjax) plugin from `cdn.mathjax.org` to [cdnjs](https://cdnjs.com/), due to closing of `cdn.mathjax.org` scheduled for April 30, 2017.
139* [#16954](http://dev.ckeditor.com/ticket/16954): Removed the paste dialog.
140* [#16982](http://dev.ckeditor.com/ticket/16982): Latest Safari now supports enhanced Clipboard API introduced in CKEditor 4.5.0.
141* [#17025](http://dev.ckeditor.com/ticket/17025): Updated [Bender.js](https://github.com/benderjs/benderjs) to 0.4.2.
142
4## CKEditor 4.6.2 143## CKEditor 4.6.2
5 144
6New Features: 145New Features:
@@ -428,7 +567,7 @@ New Features:
428* Notification system: 567* Notification system:
429 * [#11580](http://dev.ckeditor.com/ticket/11580): Introduced the [notification system](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notification). 568 * [#11580](http://dev.ckeditor.com/ticket/11580): Introduced the [notification system](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notification).
430 * [#12810](http://dev.ckeditor.com/ticket/12810): Introduced a [notification aggregator](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notificationAggregator) for the [notification system](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notification) which simplifies displaying progress of many concurrent tasks. 569 * [#12810](http://dev.ckeditor.com/ticket/12810): Introduced a [notification aggregator](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notificationAggregator) for the [notification system](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.notification) which simplifies displaying progress of many concurrent tasks.
431* [#11636](http://dev.ckeditor.com/ticket/11636): Introduced new, UX-focused, methods for getting selected HTML and deleting it &mdash; [`editor.getSelectedHtml()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getSelectedHtml) and [`editor.deleteSelectedHtml()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getSelectedHtml). 570* [#11636](http://dev.ckeditor.com/ticket/11636): Introduced new, UX-focused, methods for getting selected HTML and deleting it &mdash; [`editor.getSelectedHtml()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getSelectedHtml) and [`editor.extractSelectedHtml()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-extractSelectedHtml).
432* [#12416](http://dev.ckeditor.com/ticket/12416): Added the [`widget.definition.upcastPriority`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.definition-property-upcastPriority) property which gives more control over widget upcasting order to the widget author. 571* [#12416](http://dev.ckeditor.com/ticket/12416): Added the [`widget.definition.upcastPriority`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.definition-property-upcastPriority) property which gives more control over widget upcasting order to the widget author.
433* [#12036](http://dev.ckeditor.com/ticket/12036): Initialize the editor in [read-only](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-readOnly) mode when the `<textarea>` element has a `readonly` attribute. 572* [#12036](http://dev.ckeditor.com/ticket/12036): Initialize the editor in [read-only](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-readOnly) mode when the `<textarea>` element has a `readonly` attribute.
434* [#11905](http://dev.ckeditor.com/ticket/11905): The [`resize` event](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-resize) passes the current dimensions in its data. 573* [#11905](http://dev.ckeditor.com/ticket/11905): The [`resize` event](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-resize) passes the current dimensions in its data.
diff --git a/sources/config.js b/sources/config.js
index 62eb407..ee64420 100644
--- a/sources/config.js
+++ b/sources/config.js
@@ -7,7 +7,7 @@ CKEDITOR.editorConfig = function( config ) {
7 7
8 // %REMOVE_START% 8 // %REMOVE_START%
9 // The configuration options below are needed when running CKEditor from source files. 9 // The configuration options below are needed when running CKEditor from source files.
10 config.plugins = 'dialogui,dialog,a11yhelp,dialogadvtab,basicstyles,button,panelbutton,panel,floatpanel,colorbutton,colordialog,menu,contextmenu,div,resize,toolbar,elementspath,enterkey,entities,popup,filebrowser,floatingspace,listblock,richcombo,font,format,horizontalrule,htmlwriter,fakeobjects,iframe,wysiwygarea,image,indent,indentblock,indentlist,justify,link,list,liststyle,magicline,maximize,removeformat,showborders,sourcearea,tab,lineutils,clipboard,widgetselection,widget,oembed,brclear,html5audio,html5video'; 10 config.plugins = 'dialogui,dialog,a11yhelp,dialogadvtab,basicstyles,button,panelbutton,panel,floatpanel,colorbutton,colordialog,menu,contextmenu,div,resize,toolbar,elementspath,enterkey,entities,popup,filebrowser,floatingspace,listblock,richcombo,font,format,horizontalrule,htmlwriter,fakeobjects,iframe,wysiwygarea,image,indent,indentblock,indentlist,justify,link,list,liststyle,magicline,maximize,removeformat,showborders,sourcearea,tab,lineutils,notification,clipboard,widgetselection,widget,oembed,brclear,html5audio,html5video';
11 config.skin = 'moonocolor'; 11 config.skin = 'moonocolor';
12 // %REMOVE_END% 12 // %REMOVE_END%
13 13
diff --git a/sources/core/_bootstrap.js b/sources/core/_bootstrap.js
index 0163912..cc7fb38 100644
--- a/sources/core/_bootstrap.js
+++ b/sources/core/_bootstrap.js
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10( function() { 10( function() {
11 // Disable HC detection in WebKit. (#5429) 11 // Disable HC detection in WebKit. (http://dev.ckeditor.com/ticket/5429)
12 if ( CKEDITOR.env.webkit ) 12 if ( CKEDITOR.env.webkit )
13 CKEDITOR.env.hc = false; 13 CKEDITOR.env.hc = false;
14 else { 14 else {
@@ -19,13 +19,13 @@
19 hcDetect.appendTo( CKEDITOR.document.getHead() ); 19 hcDetect.appendTo( CKEDITOR.document.getHead() );
20 20
21 // Update CKEDITOR.env. 21 // Update CKEDITOR.env.
22 // Catch exception needed sometimes for FF. (#4230) 22 // Catch exception needed sometimes for FF. (http://dev.ckeditor.com/ticket/4230)
23 try { 23 try {
24 var top = hcDetect.getComputedStyle( 'border-top-color' ), 24 var top = hcDetect.getComputedStyle( 'border-top-color' ),
25 right = hcDetect.getComputedStyle( 'border-right-color' ); 25 right = hcDetect.getComputedStyle( 'border-right-color' );
26 26
27 // We need to check if getComputedStyle returned any value, because on FF 27 // We need to check if getComputedStyle returned any value, because on FF
28 // it returnes empty string if CKEditor is loaded in hidden iframe. (#11121) 28 // it returnes empty string if CKEditor is loaded in hidden iframe. (http://dev.ckeditor.com/ticket/11121)
29 CKEDITOR.env.hc = !!( top && top == right ); 29 CKEDITOR.env.hc = !!( top && top == right );
30 } catch ( e ) { 30 } catch ( e ) {
31 CKEDITOR.env.hc = false; 31 CKEDITOR.env.hc = false;
diff --git a/sources/core/ckeditor.js b/sources/core/ckeditor.js
index 2756204..95dd67a 100644
--- a/sources/core/ckeditor.js
+++ b/sources/core/ckeditor.js
@@ -126,7 +126,7 @@ CKEDITOR.remove = function( editor ) {
126 }; 126 };
127 127
128 /** 128 /**
129 * Returns a string will all CSS rules passed to the {@link CKEDITOR#addCss} method. 129 * Returns a string with all CSS rules passed to the {@link CKEDITOR#addCss} method.
130 * 130 *
131 * @returns {String} A string containing CSS rules. 131 * @returns {String} A string containing CSS rules.
132 */ 132 */
diff --git a/sources/core/command.js b/sources/core/command.js
index 0446d24..128cea4 100644
--- a/sources/core/command.js
+++ b/sources/core/command.js
@@ -47,7 +47,7 @@ CKEDITOR.command = function( editor, commandDefinition ) {
47 if ( this.state == CKEDITOR.TRISTATE_DISABLED || !this.checkAllowed() ) 47 if ( this.state == CKEDITOR.TRISTATE_DISABLED || !this.checkAllowed() )
48 return false; 48 return false;
49 49
50 if ( this.editorFocus ) // Give editor focus if necessary (#4355). 50 if ( this.editorFocus ) // Give editor focus if necessary (http://dev.ckeditor.com/ticket/4355).
51 editor.focus(); 51 editor.focus();
52 52
53 if ( this.fire( 'exec' ) === false ) 53 if ( this.fire( 'exec' ) === false )
diff --git a/sources/core/creators/themedui.js b/sources/core/creators/themedui.js
index 04927d0..4e7a93e 100644
--- a/sources/core/creators/themedui.js
+++ b/sources/core/creators/themedui.js
@@ -280,10 +280,10 @@ CKEDITOR.replaceClass = 'ckeditor';
280 outer = container; 280 outer = container;
281 } 281 }
282 282
283 // Set as border box width. (#5353) 283 // Set as border box width. (http://dev.ckeditor.com/ticket/5353)
284 outer.setSize( 'width', width, true ); 284 outer.setSize( 'width', width, true );
285 285
286 // WebKit needs to refresh the iframe size to avoid rendering issues. (1/2) (#8348) 286 // WebKit needs to refresh the iframe size to avoid rendering issues. (1/2) (http://dev.ckeditor.com/ticket/8348)
287 contentsFrame && ( contentsFrame.style.width = '1%' ); 287 contentsFrame && ( contentsFrame.style.width = '1%' );
288 288
289 // Get the height delta between the outer table and the content area. 289 // Get the height delta between the outer table and the content area.
@@ -295,7 +295,7 @@ CKEDITOR.replaceClass = 'ckeditor';
295 295
296 contents.setStyle( 'height', resultContentsHeight + 'px' ); 296 contents.setStyle( 'height', resultContentsHeight + 'px' );
297 297
298 // WebKit needs to refresh the iframe size to avoid rendering issues. (2/2) (#8348) 298 // WebKit needs to refresh the iframe size to avoid rendering issues. (2/2) (http://dev.ckeditor.com/ticket/8348)
299 contentsFrame && ( contentsFrame.style.width = '100%' ); 299 contentsFrame && ( contentsFrame.style.width = '100%' );
300 300
301 // Emit a resize event. 301 // Emit a resize event.
@@ -337,7 +337,7 @@ CKEDITOR.replaceClass = 'ckeditor';
337 // replacement will be done later in the editor creation lifecycle. 337 // replacement will be done later in the editor creation lifecycle.
338 element.setStyle( 'visibility', 'hidden' ); 338 element.setStyle( 'visibility', 'hidden' );
339 339
340 // #8031 Remember if textarea was required and remove the attribute. 340 // http://dev.ckeditor.com/ticket/8031 Remember if textarea was required and remove the attribute.
341 editor._.required = element.hasAttribute( 'required' ); 341 editor._.required = element.hasAttribute( 'required' );
342 element.removeAttribute( 'required' ); 342 element.removeAttribute( 'required' );
343 } 343 }
@@ -422,7 +422,7 @@ CKEDITOR.replaceClass = 'ckeditor';
422 topHtml: topHtml ? '<span id="' + editor.ui.spaceId( 'top' ) + '" class="cke_top cke_reset_all" role="presentation" style="height:auto">' + topHtml + '</span>' : '', 422 topHtml: topHtml ? '<span id="' + editor.ui.spaceId( 'top' ) + '" class="cke_top cke_reset_all" role="presentation" style="height:auto">' + topHtml + '</span>' : '',
423 contentId: editor.ui.spaceId( 'contents' ), 423 contentId: editor.ui.spaceId( 'contents' ),
424 bottomHtml: bottomHtml ? '<span id="' + editor.ui.spaceId( 'bottom' ) + '" class="cke_bottom cke_reset_all" role="presentation">' + bottomHtml + '</span>' : '', 424 bottomHtml: bottomHtml ? '<span id="' + editor.ui.spaceId( 'bottom' ) + '" class="cke_bottom cke_reset_all" role="presentation">' + bottomHtml + '</span>' : '',
425 outerEl: CKEDITOR.env.ie ? 'span' : 'div' // #9571 425 outerEl: CKEDITOR.env.ie ? 'span' : 'div' // http://dev.ckeditor.com/ticket/9571
426 } ) ); 426 } ) );
427 427
428 if ( elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) { 428 if ( elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) {
@@ -451,7 +451,7 @@ CKEDITOR.replaceClass = 'ckeditor';
451 // Disable browser context menu for editor's chrome. 451 // Disable browser context menu for editor's chrome.
452 container.disableContextMenu(); 452 container.disableContextMenu();
453 453
454 // Redirect the focus into editor for webkit. (#5713) 454 // Redirect the focus into editor for webkit. (http://dev.ckeditor.com/ticket/5713)
455 CKEDITOR.env.webkit && container.on( 'focus', function() { 455 CKEDITOR.env.webkit && container.on( 'focus', function() {
456 editor.focus(); 456 editor.focus();
457 } ); 457 } );
diff --git a/sources/core/dom/document.js b/sources/core/dom/document.js
index 51c5b19..ebf0bab 100644
--- a/sources/core/dom/document.js
+++ b/sources/core/dom/document.js
@@ -262,7 +262,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.document.prototype, {
262 * @param {String} html The HTML defining the document content. 262 * @param {String} html The HTML defining the document content.
263 */ 263 */
264 write: function( html ) { 264 write: function( html ) {
265 // Don't leave any history log in IE. (#5657) 265 // Don't leave any history log in IE. (http://dev.ckeditor.com/ticket/5657)
266 this.$.open( 'text/html', 'replace' ); 266 this.$.open( 'text/html', 'replace' );
267 267
268 // Support for custom document.domain in IE. 268 // Support for custom document.domain in IE.
diff --git a/sources/core/dom/domobject.js b/sources/core/dom/domobject.js
index 4c593ff..f4e258a 100644
--- a/sources/core/dom/domobject.js
+++ b/sources/core/dom/domobject.js
@@ -41,7 +41,7 @@ CKEDITOR.dom.domObject.prototype = ( function() {
41 return function( domEvent ) { 41 return function( domEvent ) {
42 // In FF, when reloading the page with the editor focused, it may 42 // In FF, when reloading the page with the editor focused, it may
43 // throw an error because the CKEDITOR global is not anymore 43 // throw an error because the CKEDITOR global is not anymore
44 // available. So, we check it here first. (#2923) 44 // available. So, we check it here first. (http://dev.ckeditor.com/ticket/2923)
45 if ( typeof CKEDITOR != 'undefined' ) 45 if ( typeof CKEDITOR != 'undefined' )
46 domObject.fire( eventName, new CKEDITOR.dom.event( domEvent ) ); 46 domObject.fire( eventName, new CKEDITOR.dom.event( domEvent ) );
47 }; 47 };
@@ -138,7 +138,7 @@ CKEDITOR.dom.domObject.prototype = ( function() {
138 } 138 }
139 139
140 // Remove events from events object so fire() method will not call 140 // Remove events from events object so fire() method will not call
141 // listeners (#11400). 141 // listeners (http://dev.ckeditor.com/ticket/11400).
142 CKEDITOR.event.prototype.removeAllListeners.call( this ); 142 CKEDITOR.event.prototype.removeAllListeners.call( this );
143 } 143 }
144 }; 144 };
diff --git a/sources/core/dom/element.js b/sources/core/dom/element.js
index e02ff17..31451f9 100644
--- a/sources/core/dom/element.js
+++ b/sources/core/dom/element.js
@@ -308,7 +308,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
308 */ 308 */
309 appendText: function( text ) { 309 appendText: function( text ) {
310 // On IE8 it is impossible to append node to script tag, so we use its text. 310 // On IE8 it is impossible to append node to script tag, so we use its text.
311 // On the contrary, on Safari the text property is unpredictable in links. (#13232) 311 // On the contrary, on Safari the text property is unpredictable in links. (http://dev.ckeditor.com/ticket/13232)
312 if ( this.$.text != null && CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) 312 if ( this.$.text != null && CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
313 this.$.text += text; 313 this.$.text += text;
314 else 314 else
@@ -377,7 +377,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
377 377
378 // In case of Internet Explorer, we must check if there is no background-color 378 // In case of Internet Explorer, we must check if there is no background-color
379 // added to the element. In such case, we have to overwrite it to prevent "switching it off" 379 // added to the element. In such case, we have to overwrite it to prevent "switching it off"
380 // by a browser (#14667). 380 // by a browser (http://dev.ckeditor.com/ticket/14667).
381 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { 381 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) {
382 tmpElement = new CKEDITOR.dom.element( 'div' ); 382 tmpElement = new CKEDITOR.dom.element( 'div' );
383 383
@@ -452,7 +452,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
452 */ 452 */
453 getHtml: function() { 453 getHtml: function() {
454 var retval = this.$.innerHTML; 454 var retval = this.$.innerHTML;
455 // Strip <?xml:namespace> tags in IE. (#3341). 455 // Strip <?xml:namespace> tags in IE. (http://dev.ckeditor.com/ticket/3341).
456 return CKEDITOR.env.ie ? retval.replace( /<\?[^>]*>/g, '' ) : retval; 456 return CKEDITOR.env.ie ? retval.replace( /<\?[^>]*>/g, '' ) : retval;
457 }, 457 },
458 458
@@ -467,7 +467,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
467 getOuterHtml: function() { 467 getOuterHtml: function() {
468 if ( this.$.outerHTML ) { 468 if ( this.$.outerHTML ) {
469 // IE includes the <?xml:namespace> tag in the outerHTML of 469 // IE includes the <?xml:namespace> tag in the outerHTML of
470 // namespaced element. So, we must strip it here. (#3341) 470 // namespaced element. So, we must strip it here. (http://dev.ckeditor.com/ticket/3341)
471 return this.$.outerHTML.replace( /<\?[^>]*>/, '' ); 471 return this.$.outerHTML.replace( /<\?[^>]*>/, '' );
472 } 472 }
473 473
@@ -618,7 +618,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
618 return this.$[ name ]; 618 return this.$[ name ];
619 619
620 case 'style': 620 case 'style':
621 // IE does not return inline styles via getAttribute(). See #2947. 621 // IE does not return inline styles via getAttribute(). See http://dev.ckeditor.com/ticket/2947.
622 return this.$.style.cssText; 622 return this.$.style.cssText;
623 623
624 case 'contenteditable': 624 case 'contenteditable':
@@ -679,7 +679,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
679 function( propertyName ) { 679 function( propertyName ) {
680 var style = this.getWindow().$.getComputedStyle( this.$, null ); 680 var style = this.getWindow().$.getComputedStyle( this.$, null );
681 681
682 // Firefox may return null if we call the above on a hidden iframe. (#9117) 682 // Firefox may return null if we call the above on a hidden iframe. (http://dev.ckeditor.com/ticket/9117)
683 return style ? style.getPropertyValue( propertyName ) : ''; 683 return style ? style.getPropertyValue( propertyName ) : '';
684 } : function( propertyName ) { 684 } : function( propertyName ) {
685 return this.$.currentStyle[ CKEDITOR.tools.cssStyleToDomStyle( propertyName ) ]; 685 return this.$.currentStyle[ CKEDITOR.tools.cssStyleToDomStyle( propertyName ) ];
@@ -972,7 +972,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
972 elementWindow, elementWindowFrame; 972 elementWindow, elementWindowFrame;
973 973
974 // Webkit and Opera report non-zero offsetHeight despite that 974 // Webkit and Opera report non-zero offsetHeight despite that
975 // element is inside an invisible iframe. (#4542) 975 // element is inside an invisible iframe. (http://dev.ckeditor.com/ticket/4542)
976 if ( isVisible && CKEDITOR.env.webkit ) { 976 if ( isVisible && CKEDITOR.env.webkit ) {
977 elementWindow = this.getWindow(); 977 elementWindow = this.getWindow();
978 978
@@ -1033,7 +1033,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1033 // attribute, which will be marked as "specified", even if the 1033 // attribute, which will be marked as "specified", even if the
1034 // outerHTML of the element is not displaying the class attribute. 1034 // outerHTML of the element is not displaying the class attribute.
1035 // Note : I was not able to reproduce it outside the editor, 1035 // Note : I was not able to reproduce it outside the editor,
1036 // but I've faced it while working on the TC of #1391. 1036 // but I've faced it while working on the TC of http://dev.ckeditor.com/ticket/1391.
1037 if ( this.getAttribute( 'class' ) ) { 1037 if ( this.getAttribute( 'class' ) ) {
1038 return true; 1038 return true;
1039 } 1039 }
@@ -1057,7 +1057,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1057 var attrs = this.$.attributes, 1057 var attrs = this.$.attributes,
1058 attrsNum = attrs.length; 1058 attrsNum = attrs.length;
1059 1059
1060 // The _moz_dirty attribute might get into the element after pasting (#5455) 1060 // The _moz_dirty attribute might get into the element after pasting (http://dev.ckeditor.com/ticket/5455)
1061 var execludeAttrs = { 'data-cke-expando': 1, _moz_dirty: 1 }; 1061 var execludeAttrs = { 'data-cke-expando': 1, _moz_dirty: 1 };
1062 1062
1063 return attrsNum > 0 && ( attrsNum > 2 || !execludeAttrs[ attrs[ 0 ].nodeName ] || ( attrsNum == 2 && !execludeAttrs[ attrs[ 1 ].nodeName ] ) ); 1063 return attrsNum > 0 && ( attrsNum > 2 || !execludeAttrs[ attrs[ 0 ].nodeName ] || ( attrsNum == 2 && !execludeAttrs[ attrs[ 1 ].nodeName ] ) );
@@ -1164,7 +1164,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1164 function mergeElements( element, sibling, isNext ) { 1164 function mergeElements( element, sibling, isNext ) {
1165 if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT ) { 1165 if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT ) {
1166 // Jumping over bookmark nodes and empty inline elements, e.g. <b><i></i></b>, 1166 // Jumping over bookmark nodes and empty inline elements, e.g. <b><i></i></b>,
1167 // queuing them to be moved later. (#5567) 1167 // queuing them to be moved later. (http://dev.ckeditor.com/ticket/5567)
1168 var pendingNodes = []; 1168 var pendingNodes = [];
1169 1169
1170 while ( sibling.data( 'cke-bookmark' ) || sibling.isEmptyInlineRemoveable() ) { 1170 while ( sibling.data( 'cke-bookmark' ) || sibling.isEmptyInlineRemoveable() ) {
@@ -1194,7 +1194,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1194 } 1194 }
1195 1195
1196 return function( inlineOnly ) { 1196 return function( inlineOnly ) {
1197 // Merge empty links and anchors also. (#5567) 1197 // Merge empty links and anchors also. (http://dev.ckeditor.com/ticket/5567)
1198 if ( !( inlineOnly === false || CKEDITOR.dtd.$removeEmpty[ this.getName() ] || this.is( 'a' ) ) ) { 1198 if ( !( inlineOnly === false || CKEDITOR.dtd.$removeEmpty[ this.getName() ] || this.is( 'a' ) ) ) {
1199 return; 1199 return;
1200 } 1200 }
@@ -1253,7 +1253,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1253 }; 1253 };
1254 } else if ( CKEDITOR.env.ie8Compat && CKEDITOR.env.secure ) { 1254 } else if ( CKEDITOR.env.ie8Compat && CKEDITOR.env.secure ) {
1255 return function( name, value ) { 1255 return function( name, value ) {
1256 // IE8 throws error when setting src attribute to non-ssl value. (#7847) 1256 // IE8 throws error when setting src attribute to non-ssl value. (http://dev.ckeditor.com/ticket/7847)
1257 if ( name == 'src' && value.match( /^http:\/\// ) ) { 1257 if ( name == 'src' && value.match( /^http:\/\// ) ) {
1258 try { 1258 try {
1259 standard.apply( this, arguments ); 1259 standard.apply( this, arguments );
@@ -1501,7 +1501,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1501 clientLeft = $docElem.clientLeft || body.$.clientLeft || 0, 1501 clientLeft = $docElem.clientLeft || body.$.clientLeft || 0,
1502 needAdjustScrollAndBorders = true; 1502 needAdjustScrollAndBorders = true;
1503 1503
1504 // #3804: getBoundingClientRect() works differently on IE and non-IE 1504 // http://dev.ckeditor.com/ticket/3804: getBoundingClientRect() works differently on IE and non-IE
1505 // browsers, regarding scroll positions. 1505 // browsers, regarding scroll positions.
1506 // 1506 //
1507 // On IE, the top position of the <html> element is always 0, no matter 1507 // On IE, the top position of the <html> element is always 0, no matter
@@ -1516,12 +1516,12 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1516 needAdjustScrollAndBorders = ( quirks && inBody ) || ( !quirks && inDocElem ); 1516 needAdjustScrollAndBorders = ( quirks && inBody ) || ( !quirks && inDocElem );
1517 } 1517 }
1518 1518
1519 // #12747. 1519 // http://dev.ckeditor.com/ticket/12747.
1520 if ( needAdjustScrollAndBorders ) { 1520 if ( needAdjustScrollAndBorders ) {
1521 var scrollRelativeLeft, 1521 var scrollRelativeLeft,
1522 scrollRelativeTop; 1522 scrollRelativeTop;
1523 1523
1524 // See #12758 to know more about document.(documentElement|body).scroll(Left|Top) in Webkit. 1524 // See http://dev.ckeditor.com/ticket/12758 to know more about document.(documentElement|body).scroll(Left|Top) in Webkit.
1525 if ( CKEDITOR.env.webkit || ( CKEDITOR.env.ie && CKEDITOR.env.version >= 12 ) ) { 1525 if ( CKEDITOR.env.webkit || ( CKEDITOR.env.ie && CKEDITOR.env.version >= 12 ) ) {
1526 scrollRelativeLeft = body.$.scrollLeft || $docElem.scrollLeft; 1526 scrollRelativeLeft = body.$.scrollLeft || $docElem.scrollLeft;
1527 scrollRelativeTop = body.$.scrollTop || $docElem.scrollTop; 1527 scrollRelativeTop = body.$.scrollTop || $docElem.scrollTop;
@@ -1603,7 +1603,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1603 parent.$.clientHeight && parent.$.clientHeight < parent.$.scrollHeight; 1603 parent.$.clientHeight && parent.$.clientHeight < parent.$.scrollHeight;
1604 1604
1605 // Skip body element, which will report wrong clientHeight when containing 1605 // Skip body element, which will report wrong clientHeight when containing
1606 // floated content. (#9523) 1606 // floated content. (http://dev.ckeditor.com/ticket/9523)
1607 if ( overflowed && !parent.is( 'body' ) ) 1607 if ( overflowed && !parent.is( 'body' ) )
1608 this.scrollIntoParent( parent, alignToTop, 1 ); 1608 this.scrollIntoParent( parent, alignToTop, 1 );
1609 1609
@@ -1677,7 +1677,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1677 } 1677 }
1678 1678
1679 // [WebKit] Reset stored scrollTop value to not break scrollIntoView() method flow. 1679 // [WebKit] Reset stored scrollTop value to not break scrollIntoView() method flow.
1680 // Scrolling breaks when range.select() is used right after element.scrollIntoView(). (#14659) 1680 // Scrolling breaks when range.select() is used right after element.scrollIntoView(). (http://dev.ckeditor.com/ticket/14659)
1681 if ( CKEDITOR.env.webkit ) { 1681 if ( CKEDITOR.env.webkit ) {
1682 var editor = this.getEditor( false ); 1682 var editor = this.getEditor( false );
1683 1683
@@ -1857,7 +1857,7 @@ CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatab
1857 this.getParent( true ) && this.$.parentNode.replaceChild( newNode.$, this.$ ); 1857 this.getParent( true ) && this.$.parentNode.replaceChild( newNode.$, this.$ );
1858 newNode.$[ 'data-cke-expando' ] = this.$[ 'data-cke-expando' ]; 1858 newNode.$[ 'data-cke-expando' ] = this.$[ 'data-cke-expando' ];
1859 this.$ = newNode.$; 1859 this.$ = newNode.$;
1860 // Bust getName's cache. (#8663) 1860 // Bust getName's cache. (http://dev.ckeditor.com/ticket/8663)
1861 delete this.getName; 1861 delete this.getName;
1862 }, 1862 },
1863 1863
diff --git a/sources/core/dom/elementpath.js b/sources/core/dom/elementpath.js
index 1a3aed0..dd50f10 100644
--- a/sources/core/dom/elementpath.js
+++ b/sources/core/dom/elementpath.js
@@ -57,6 +57,11 @@
57 // Backward compact. 57 // Backward compact.
58 root = root || startNode.getDocument().getBody(); 58 root = root || startNode.getDocument().getBody();
59 59
60 // Assign root value if startNode is null (#424)(https://dev.ckeditor.com/ticket/17028).
61 if ( !e ) {
62 e = root;
63 }
64
60 do { 65 do {
61 if ( e.type == CKEDITOR.NODE_ELEMENT ) { 66 if ( e.type == CKEDITOR.NODE_ELEMENT ) {
62 elements.push( e ); 67 elements.push( e );
@@ -84,7 +89,7 @@
84 block = e; 89 block = e;
85 90
86 if ( pathBlockLimitElements[ elementName ] ) { 91 if ( pathBlockLimitElements[ elementName ] ) {
87 // End level DIV is considered as the block, if no block is available. (#525) 92 // End level DIV is considered as the block, if no block is available. (http://dev.ckeditor.com/ticket/525)
88 // But it must NOT be the root element (checked above). 93 // But it must NOT be the root element (checked above).
89 if ( !block && elementName == 'div' && !checkHasBlock( e ) ) 94 if ( !block && elementName == 'div' && !checkHasBlock( e ) )
90 block = e; 95 block = e;
@@ -181,7 +186,9 @@ CKEDITOR.dom.elementPath.prototype = {
181 * @returns {CKEDITOR.dom.element} The first matched dom element or `null`. 186 * @returns {CKEDITOR.dom.element} The first matched dom element or `null`.
182 */ 187 */
183 contains: function( query, excludeRoot, fromTop ) { 188 contains: function( query, excludeRoot, fromTop ) {
184 var evaluator; 189 var i = 0,
190 evaluator;
191
185 if ( typeof query == 'string' ) 192 if ( typeof query == 'string' )
186 evaluator = function( node ) { 193 evaluator = function( node ) {
187 return node.getName() == query; 194 return node.getName() == query;
@@ -203,14 +210,21 @@ CKEDITOR.dom.elementPath.prototype = {
203 210
204 var elements = this.elements, 211 var elements = this.elements,
205 length = elements.length; 212 length = elements.length;
206 excludeRoot && length--; 213
214 if ( excludeRoot ) {
215 if ( !fromTop ) {
216 length -= 1;
217 } else {
218 i += 1;
219 }
220 }
207 221
208 if ( fromTop ) { 222 if ( fromTop ) {
209 elements = Array.prototype.slice.call( elements, 0 ); 223 elements = Array.prototype.slice.call( elements, 0 );
210 elements.reverse(); 224 elements.reverse();
211 } 225 }
212 226
213 for ( var i = 0; i < length; i++ ) { 227 for ( ; i < length; i++ ) {
214 if ( evaluator( elements[ i ] ) ) 228 if ( evaluator( elements[ i ] ) )
215 return elements[ i ]; 229 return elements[ i ];
216 } 230 }
diff --git a/sources/core/dom/iterator.js b/sources/core/dom/iterator.js
index 50056ec..9176e33 100644
--- a/sources/core/dom/iterator.js
+++ b/sources/core/dom/iterator.js
@@ -45,7 +45,7 @@
45 */ 45 */
46 this.forceBrBreak = 0; 46 this.forceBrBreak = 0;
47 47
48 // (#3730). 48 // (http://dev.ckeditor.com/ticket/3730).
49 /** 49 /**
50 * Whether to include `<br>` elements in the enlarged range. Should be 50 * Whether to include `<br>` elements in the enlarged range. Should be
51 * set to `false` when using the iterator in the {@link CKEDITOR#ENTER_BR} mode. 51 * set to `false` when using the iterator in the {@link CKEDITOR#ENTER_BR} mode.
@@ -85,7 +85,7 @@
85 */ 85 */
86 86
87 var beginWhitespaceRegex = /^[\r\n\t ]+$/, 87 var beginWhitespaceRegex = /^[\r\n\t ]+$/,
88 // Ignore bookmark nodes.(#3783) 88 // Ignore bookmark nodes.(http://dev.ckeditor.com/ticket/3783)
89 bookmarkGuard = CKEDITOR.dom.walker.bookmark( false, true ), 89 bookmarkGuard = CKEDITOR.dom.walker.bookmark( false, true ),
90 whitespacesGuard = CKEDITOR.dom.walker.whitespaces( true ), 90 whitespacesGuard = CKEDITOR.dom.walker.whitespaces( true ),
91 skipGuard = function( node ) { 91 skipGuard = function( node ) {
@@ -191,12 +191,12 @@
191 } 191 }
192 192
193 // The range must finish right before the boundary, 193 // The range must finish right before the boundary,
194 // including possibly skipped empty spaces. (#1603) 194 // including possibly skipped empty spaces. (http://dev.ckeditor.com/ticket/1603)
195 if ( range ) { 195 if ( range ) {
196 range.setEndAt( currentNode, CKEDITOR.POSITION_BEFORE_START ); 196 range.setEndAt( currentNode, CKEDITOR.POSITION_BEFORE_START );
197 197
198 // The found boundary must be set as the next one at this 198 // The found boundary must be set as the next one at this
199 // point. (#1717) 199 // point. (http://dev.ckeditor.com/ticket/1717)
200 if ( nodeName != 'br' ) { 200 if ( nodeName != 'br' ) {
201 this._.nextNode = currentNode; 201 this._.nextNode = currentNode;
202 } 202 }
@@ -244,7 +244,7 @@
244 closeRange = 1; 244 closeRange = 1;
245 includeNode = 0; 245 includeNode = 0;
246 isLast = isLast || ( parentNode.equals( lastNode ) ); 246 isLast = isLast || ( parentNode.equals( lastNode ) );
247 // Make sure range includes bookmarks at the end of the block. (#7359) 247 // Make sure range includes bookmarks at the end of the block. (http://dev.ckeditor.com/ticket/7359)
248 range.setEndAt( parentNode, CKEDITOR.POSITION_BEFORE_END ); 248 range.setEndAt( parentNode, CKEDITOR.POSITION_BEFORE_END );
249 break; 249 break;
250 } 250 }
@@ -377,7 +377,7 @@
377 // Here we are checking in guard function whether current element 377 // Here we are checking in guard function whether current element
378 // reach lastNode(default behaviour) and root node to prevent against 378 // reach lastNode(default behaviour) and root node to prevent against
379 // getting out of editor instance root DOM object. 379 // getting out of editor instance root DOM object.
380 // #12484 380 // http://dev.ckeditor.com/ticket/12484
381 function guardFunction( node ) { 381 function guardFunction( node ) {
382 return !( node.equals( lastNode ) || node.equals( rootNode ) ); 382 return !( node.equals( lastNode ) || node.equals( rootNode ) );
383 } 383 }
@@ -397,7 +397,7 @@
397 // Indicate at least one of the range boundaries is inside a preformat block. 397 // Indicate at least one of the range boundaries is inside a preformat block.
398 touchPre, 398 touchPre,
399 399
400 // (#12178) 400 // (http://dev.ckeditor.com/ticket/12178)
401 // Remember if following situation takes place: 401 // Remember if following situation takes place:
402 // * startAtInnerBoundary: <p>foo[</p>... 402 // * startAtInnerBoundary: <p>foo[</p>...
403 // * endAtInnerBoundary: ...<p>]bar</p> 403 // * endAtInnerBoundary: ...<p>]bar</p>
@@ -405,13 +405,13 @@
405 // Note that we test only if path block exist, because we must properly shrink 405 // Note that we test only if path block exist, because we must properly shrink
406 // range containing table and/or table cells. 406 // range containing table and/or table cells.
407 // Note: When range is collapsed there's no way it can be shrinked. 407 // Note: When range is collapsed there's no way it can be shrinked.
408 // By checking if range is collapsed we also prevent #12308. 408 // By checking if range is collapsed we also prevent http://dev.ckeditor.com/ticket/12308.
409 startPath = range.startPath(), 409 startPath = range.startPath(),
410 endPath = range.endPath(), 410 endPath = range.endPath(),
411 startAtInnerBoundary = !range.collapsed && rangeAtInnerBlockBoundary( range, startPath.block ), 411 startAtInnerBoundary = !range.collapsed && rangeAtInnerBlockBoundary( range, startPath.block ),
412 endAtInnerBoundary = !range.collapsed && rangeAtInnerBlockBoundary( range, endPath.block, 1 ); 412 endAtInnerBoundary = !range.collapsed && rangeAtInnerBlockBoundary( range, endPath.block, 1 );
413 413
414 // Shrink the range to exclude harmful "noises" (#4087, #4450, #5435). 414 // Shrink the range to exclude harmful "noises" (http://dev.ckeditor.com/ticket/4087, http://dev.ckeditor.com/ticket/4450, http://dev.ckeditor.com/ticket/5435).
415 range.shrink( CKEDITOR.SHRINK_ELEMENT, true ); 415 range.shrink( CKEDITOR.SHRINK_ELEMENT, true );
416 416
417 if ( startAtInnerBoundary ) 417 if ( startAtInnerBoundary )
@@ -437,7 +437,7 @@
437 437
438 // We may have an empty text node at the end of block due to [3770]. 438 // We may have an empty text node at the end of block due to [3770].
439 // If that node is the lastNode, it would cause our logic to leak to the 439 // If that node is the lastNode, it would cause our logic to leak to the
440 // next block.(#3887) 440 // next block.(http://dev.ckeditor.com/ticket/3887)
441 if ( this._.lastNode && this._.lastNode.type == CKEDITOR.NODE_TEXT && !CKEDITOR.tools.trim( this._.lastNode.getText() ) && this._.lastNode.getParent().isBlockBoundary() ) { 441 if ( this._.lastNode && this._.lastNode.type == CKEDITOR.NODE_TEXT && !CKEDITOR.tools.trim( this._.lastNode.getText() ) && this._.lastNode.getParent().isBlockBoundary() ) {
442 var testRange = this.range.clone(); 442 var testRange = this.range.clone();
443 testRange.moveToPosition( this._.lastNode, CKEDITOR.POSITION_AFTER_END ); 443 testRange.moveToPosition( this._.lastNode, CKEDITOR.POSITION_AFTER_END );
diff --git a/sources/core/dom/node.js b/sources/core/dom/node.js
index 51bba18..69b223e 100644
--- a/sources/core/dom/node.js
+++ b/sources/core/dom/node.js
@@ -200,7 +200,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
200 } 200 }
201 201
202 // IE8 rename HTML5 nodes by adding `:` at the begging of the tag name when the node is cloned, 202 // IE8 rename HTML5 nodes by adding `:` at the begging of the tag name when the node is cloned,
203 // so `<figure>` will be `<:figure>` after 'cloneNode'. We need to fix it (#13101). 203 // so `<figure>` will be `<:figure>` after 'cloneNode'. We need to fix it (http://dev.ckeditor.com/ticket/13101).
204 function renameNodes( node ) { 204 function renameNodes( node ) {
205 if ( node.type != CKEDITOR.NODE_ELEMENT && node.type != CKEDITOR.NODE_DOCUMENT_FRAGMENT ) 205 if ( node.type != CKEDITOR.NODE_ELEMENT && node.type != CKEDITOR.NODE_DOCUMENT_FRAGMENT )
206 return; 206 return;
@@ -804,7 +804,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
804 } else if ( trimmed.length < originalLength ) { 804 } else if ( trimmed.length < originalLength ) {
805 child.split( originalLength - trimmed.length ); 805 child.split( originalLength - trimmed.length );
806 806
807 // IE BUG: child.remove() may raise JavaScript errors here. (#81) 807 // IE BUG: child.remove() may raise JavaScript errors here. (http://dev.ckeditor.com/ticket/81)
808 this.$.removeChild( this.$.firstChild ); 808 this.$.removeChild( this.$.firstChild );
809 } 809 }
810 } 810 }
@@ -829,7 +829,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
829 child.split( trimmed.length ); 829 child.split( trimmed.length );
830 830
831 // IE BUG: child.getNext().remove() may raise JavaScript errors here. 831 // IE BUG: child.getNext().remove() may raise JavaScript errors here.
832 // (#81) 832 // (http://dev.ckeditor.com/ticket/81)
833 this.$.lastChild.parentNode.removeChild( this.$.lastChild ); 833 this.$.lastChild.parentNode.removeChild( this.$.lastChild );
834 } 834 }
835 } 835 }
@@ -840,7 +840,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
840 child = this.$.lastChild; 840 child = this.$.lastChild;
841 841
842 if ( child && child.type == 1 && child.nodeName.toLowerCase() == 'br' ) { 842 if ( child && child.type == 1 && child.nodeName.toLowerCase() == 'br' ) {
843 // Use "eChildNode.parentNode" instead of "node" to avoid IE bug (#324). 843 // Use "eChildNode.parentNode" instead of "node" to avoid IE bug (http://dev.ckeditor.com/ticket/324).
844 child.parentNode.removeChild( child ); 844 child.parentNode.removeChild( child );
845 } 845 }
846 } 846 }
@@ -874,7 +874,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
874 if ( this.type != CKEDITOR.NODE_ELEMENT ) 874 if ( this.type != CKEDITOR.NODE_ELEMENT )
875 element = this.getParent(); 875 element = this.getParent();
876 876
877 // Prevent Edge crash (#13609, #13919). 877 // Prevent Edge crash (http://dev.ckeditor.com/ticket/13609, http://dev.ckeditor.com/ticket/13919).
878 if ( CKEDITOR.env.edge && element && element.is( 'textarea', 'input' ) ) { 878 if ( CKEDITOR.env.edge && element && element.is( 'textarea', 'input' ) ) {
879 checkOnlyAttributes = true; 879 checkOnlyAttributes = true;
880 } 880 }
diff --git a/sources/core/dom/nodelist.js b/sources/core/dom/nodelist.js
index 165a415..07af314 100644
--- a/sources/core/dom/nodelist.js
+++ b/sources/core/dom/nodelist.js
@@ -5,7 +5,7 @@
5 5
6/** 6/**
7 * Represents a list of {@link CKEDITOR.dom.node} objects. 7 * Represents a list of {@link CKEDITOR.dom.node} objects.
8 * It's a wrapper for native nodes list. 8 * It is a wrapper for a native nodes list.
9 * 9 *
10 * var nodeList = CKEDITOR.document.getBody().getChildren(); 10 * var nodeList = CKEDITOR.document.getBody().getChildren();
11 * alert( nodeList.count() ); // number [0;N] 11 * alert( nodeList.count() ); // number [0;N]
@@ -20,7 +20,7 @@ CKEDITOR.dom.nodeList = function( nativeList ) {
20 20
21CKEDITOR.dom.nodeList.prototype = { 21CKEDITOR.dom.nodeList.prototype = {
22 /** 22 /**
23 * Get count of nodes in this list. 23 * Gets the count of nodes in this list.
24 * 24 *
25 * @returns {Number} 25 * @returns {Number}
26 */ 26 */
@@ -29,7 +29,7 @@ CKEDITOR.dom.nodeList.prototype = {
29 }, 29 },
30 30
31 /** 31 /**
32 * Get node from the list. 32 * Gets the node from the list.
33 * 33 *
34 * @returns {CKEDITOR.dom.node} 34 * @returns {CKEDITOR.dom.node}
35 */ 35 */
@@ -39,5 +39,16 @@ CKEDITOR.dom.nodeList.prototype = {
39 39
40 var $node = this.$[ index ]; 40 var $node = this.$[ index ];
41 return $node ? new CKEDITOR.dom.node( $node ) : null; 41 return $node ? new CKEDITOR.dom.node( $node ) : null;
42 },
43
44 /**
45 * Returns a node list as an array.
46 *
47 * @returns {CKEDITOR.dom.node[]}
48 */
49 toArray: function() {
50 return CKEDITOR.tools.array.map( this.$, function( nativeEl ) {
51 return new CKEDITOR.dom.node( nativeEl );
52 } );
42 } 53 }
43}; 54};
diff --git a/sources/core/dom/range.js b/sources/core/dom/range.js
index 6407074..742c24c 100644
--- a/sources/core/dom/range.js
+++ b/sources/core/dom/range.js
@@ -204,9 +204,14 @@ CKEDITOR.dom.range = function( root ) {
204 // This allows us to not think about startNode == endNode case later on. 204 // This allows us to not think about startNode == endNode case later on.
205 // We do that only when cloning, because in other cases we can safely split this text node 205 // We do that only when cloning, because in other cases we can safely split this text node
206 // and hence we can easily handle this case as many others. 206 // and hence we can easily handle this case as many others.
207 if ( isClone && endNode.type == CKEDITOR.NODE_TEXT && startNode.equals( endNode ) ) { 207
208 startNode = range.document.createText( startNode.substring( startOffset, endOffset ) ); 208 // We need to handle situation when selection startNode is type of NODE_ELEMENT (#426).
209 docFrag.append( startNode ); 209 if ( isClone &&
210 endNode.type == CKEDITOR.NODE_TEXT &&
211 ( startNode.equals( endNode ) || ( startNode.type === CKEDITOR.NODE_ELEMENT && startNode.getFirst().equals( endNode ) ) ) ) {
212
213 // Here we should always be inside one text node.
214 docFrag.append( range.document.createText( endNode.substring( startOffset, endOffset ) ) );
210 return; 215 return;
211 } 216 }
212 217
@@ -214,7 +219,7 @@ CKEDITOR.dom.range = function( root ) {
214 // second part. The removal will be handled by the rest of the code. 219 // second part. The removal will be handled by the rest of the code.
215 if ( endNode.type == CKEDITOR.NODE_TEXT ) { 220 if ( endNode.type == CKEDITOR.NODE_TEXT ) {
216 // If Extract or Delete we can split the text node, 221 // If Extract or Delete we can split the text node,
217 // but if Clone (2), then we cannot modify the DOM (#11586) so we mark the text node for cloning. 222 // but if Clone (2), then we cannot modify the DOM (http://dev.ckeditor.com/ticket/11586) so we mark the text node for cloning.
218 if ( !isClone ) { 223 if ( !isClone ) {
219 endNode = endNode.split( endOffset ); 224 endNode = endNode.split( endOffset );
220 } else { 225 } else {
@@ -243,7 +248,7 @@ CKEDITOR.dom.range = function( root ) {
243 // be handled by the rest of the code . 248 // be handled by the rest of the code .
244 if ( startNode.type == CKEDITOR.NODE_TEXT ) { 249 if ( startNode.type == CKEDITOR.NODE_TEXT ) {
245 // If Extract or Delete we can split the text node, 250 // If Extract or Delete we can split the text node,
246 // but if Clone (2), then we cannot modify the DOM (#11586) so we mark 251 // but if Clone (2), then we cannot modify the DOM (http://dev.ckeditor.com/ticket/11586) so we mark
247 // the text node for cloning. 252 // the text node for cloning.
248 if ( !isClone ) { 253 if ( !isClone ) {
249 startNode.split( startOffset ); 254 startNode.split( startOffset );
@@ -373,7 +378,7 @@ CKEDITOR.dom.range = function( root ) {
373 // If we don't do that, in next iterations nodes will be appended to wrong parent. 378 // If we don't do that, in next iterations nodes will be appended to wrong parent.
374 // 379 //
375 // We can just take first child because the algorithm guarantees 380 // We can just take first child because the algorithm guarantees
376 // that this will be the only child on this level. (#13568) 381 // that this will be the only child on this level. (http://dev.ckeditor.com/ticket/13568)
377 levelParent = levelParent.getChild( 0 ); 382 levelParent = levelParent.getChild( 0 );
378 } 383 }
379 } 384 }
@@ -405,7 +410,7 @@ CKEDITOR.dom.range = function( root ) {
405 410
406 // When Extracting, move the removed node to the docFrag. 411 // When Extracting, move the removed node to the docFrag.
407 if ( isExtract ) { 412 if ( isExtract ) {
408 newParent.append( node ); 413 newParent.append( node, toStart );
409 } 414 }
410 } 415 }
411 416
@@ -574,7 +579,7 @@ CKEDITOR.dom.range = function( root ) {
574 // Tolerant bogus br when checking at the end of block. 579 // Tolerant bogus br when checking at the end of block.
575 // Reject any text node unless it's being bookmark 580 // Reject any text node unless it's being bookmark
576 // OR it's spaces. 581 // OR it's spaces.
577 // Reject any element unless it's being invisible empty. (#3883) 582 // Reject any element unless it's being invisible empty. (http://dev.ckeditor.com/ticket/3883)
578 return !checkStart && isBogus( node ) || 583 return !checkStart && isBogus( node ) ||
579 node.type == CKEDITOR.NODE_ELEMENT && 584 node.type == CKEDITOR.NODE_ELEMENT &&
580 node.is( CKEDITOR.dtd.$removeEmpty ); 585 node.is( CKEDITOR.dtd.$removeEmpty );
@@ -1052,7 +1057,7 @@ CKEDITOR.dom.range = function( root ) {
1052 } 1057 }
1053 1058
1054 // Sometimes the endNode will come right before startNode for collapsed 1059 // Sometimes the endNode will come right before startNode for collapsed
1055 // ranges. Fix it. (#3780) 1060 // ranges. Fix it. (http://dev.ckeditor.com/ticket/3780)
1056 if ( startNode.getPosition( endNode ) & CKEDITOR.POSITION_FOLLOWING ) 1061 if ( startNode.getPosition( endNode ) & CKEDITOR.POSITION_FOLLOWING )
1057 startNode = endNode; 1062 startNode = endNode;
1058 1063
@@ -1324,13 +1329,13 @@ CKEDITOR.dom.range = function( root ) {
1324 1329
1325 isWhiteSpace = /[\s\ufeff]$/.test( siblingText ); 1330 isWhiteSpace = /[\s\ufeff]$/.test( siblingText );
1326 } else { 1331 } else {
1327 // #12221 (Chrome) plus #11111 (Safari). 1332 // http://dev.ckeditor.com/ticket/12221 (Chrome) plus http://dev.ckeditor.com/ticket/11111 (Safari).
1328 var offsetWidth0 = CKEDITOR.env.webkit ? 1 : 0; 1333 var offsetWidth0 = CKEDITOR.env.webkit ? 1 : 0;
1329 1334
1330 // If this is a visible element. 1335 // If this is a visible element.
1331 // We need to check for the bookmark attribute because IE insists on 1336 // We need to check for the bookmark attribute because IE insists on
1332 // rendering the display:none nodes we use for bookmarks. (#3363) 1337 // rendering the display:none nodes we use for bookmarks. (http://dev.ckeditor.com/ticket/3363)
1333 // Line-breaks (br) are rendered with zero width, which we don't want to include. (#7041) 1338 // Line-breaks (br) are rendered with zero width, which we don't want to include. (http://dev.ckeditor.com/ticket/7041)
1334 if ( ( sibling.$.offsetWidth > offsetWidth0 || excludeBrs && sibling.is( 'br' ) ) && !sibling.data( 'cke-bookmark' ) ) { 1339 if ( ( sibling.$.offsetWidth > offsetWidth0 || excludeBrs && sibling.is( 'br' ) ) && !sibling.data( 'cke-bookmark' ) ) {
1335 // We'll accept it only if we need 1340 // We'll accept it only if we need
1336 // whitespace, and this is an inline 1341 // whitespace, and this is an inline
@@ -1399,7 +1404,7 @@ CKEDITOR.dom.range = function( root ) {
1399 1404
1400 // Process the end boundary. This is basically the same 1405 // Process the end boundary. This is basically the same
1401 // code used for the start boundary, with small changes to 1406 // code used for the start boundary, with small changes to
1402 // make it work in the oposite side (to the right). This 1407 // make it work in the opposite side (to the right). This
1403 // makes it difficult to reuse the code here. So, fixes to 1408 // makes it difficult to reuse the code here. So, fixes to
1404 // the above code are likely to be replicated here. 1409 // the above code are likely to be replicated here.
1405 1410
@@ -1482,7 +1487,7 @@ CKEDITOR.dom.range = function( root ) {
1482 } 1487 }
1483 } 1488 }
1484 } else { 1489 } else {
1485 // Get the node right after the boudary to be checked 1490 // Get the node right after the boundary to be checked
1486 // first. 1491 // first.
1487 sibling = container.getChild( offset ); 1492 sibling = container.getChild( offset );
1488 1493
@@ -1525,8 +1530,8 @@ CKEDITOR.dom.range = function( root ) {
1525 } else if ( sibling.type == CKEDITOR.NODE_ELEMENT ) { 1530 } else if ( sibling.type == CKEDITOR.NODE_ELEMENT ) {
1526 // If this is a visible element. 1531 // If this is a visible element.
1527 // We need to check for the bookmark attribute because IE insists on 1532 // We need to check for the bookmark attribute because IE insists on
1528 // rendering the display:none nodes we use for bookmarks. (#3363) 1533 // rendering the display:none nodes we use for bookmarks. (http://dev.ckeditor.com/ticket/3363)
1529 // Line-breaks (br) are rendered with zero width, which we don't want to include. (#7041) 1534 // Line-breaks (br) are rendered with zero width, which we don't want to include. (http://dev.ckeditor.com/ticket/7041)
1530 if ( ( sibling.$.offsetWidth > 0 || excludeBrs && sibling.is( 'br' ) ) && !sibling.data( 'cke-bookmark' ) ) { 1535 if ( ( sibling.$.offsetWidth > 0 || excludeBrs && sibling.is( 'br' ) ) && !sibling.data( 'cke-bookmark' ) ) {
1531 // We'll accept it only if we need 1536 // We'll accept it only if we need
1532 // whitespace, and this is an inline 1537 // whitespace, and this is an inline
@@ -1617,7 +1622,7 @@ CKEDITOR.dom.range = function( root ) {
1617 boundaryGuard = function( node ) { 1622 boundaryGuard = function( node ) {
1618 // We should not check contents of non-editable elements. It may happen 1623 // We should not check contents of non-editable elements. It may happen
1619 // that inline widget has display:table child which should not block range#enlarge. 1624 // that inline widget has display:table child which should not block range#enlarge.
1620 // When encoutered non-editable element... 1625 // When encountered non-editable element...
1621 if ( node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'false' ) { 1626 if ( node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'false' ) {
1622 if ( inNonEditable ) { 1627 if ( inNonEditable ) {
1623 // ... in which we already were, reset it (because we're leaving it) and return. 1628 // ... in which we already were, reset it (because we're leaving it) and return.
@@ -1639,7 +1644,7 @@ CKEDITOR.dom.range = function( root ) {
1639 blockBoundary = node; 1644 blockBoundary = node;
1640 return retval; 1645 return retval;
1641 }, 1646 },
1642 // Record the encounted 'tailBr' for later use. 1647 // Record the encountered 'tailBr' for later use.
1643 tailBrGuard = function( node ) { 1648 tailBrGuard = function( node ) {
1644 var retval = boundaryGuard( node ); 1649 var retval = boundaryGuard( node );
1645 if ( !retval && node.is && node.is( 'br' ) ) 1650 if ( !retval && node.is && node.is( 'br' ) )
@@ -1660,7 +1665,7 @@ CKEDITOR.dom.range = function( root ) {
1660 this.setStartAt( blockBoundary, !blockBoundary.is( 'br' ) && ( !enlargeable && this.checkStartOfBlock() || 1665 this.setStartAt( blockBoundary, !blockBoundary.is( 'br' ) && ( !enlargeable && this.checkStartOfBlock() ||
1661 enlargeable && blockBoundary.contains( enlargeable ) ) ? CKEDITOR.POSITION_AFTER_START : CKEDITOR.POSITION_AFTER_END ); 1666 enlargeable && blockBoundary.contains( enlargeable ) ) ? CKEDITOR.POSITION_AFTER_START : CKEDITOR.POSITION_AFTER_END );
1662 1667
1663 // Avoid enlarging the range further when end boundary spans right after the BR. (#7490) 1668 // Avoid enlarging the range further when end boundary spans right after the BR. (http://dev.ckeditor.com/ticket/7490)
1664 if ( unit == CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS ) { 1669 if ( unit == CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS ) {
1665 var theRange = this.clone(); 1670 var theRange = this.clone();
1666 walker = new CKEDITOR.dom.walker( theRange ); 1671 walker = new CKEDITOR.dom.walker( theRange );
@@ -1715,18 +1720,28 @@ CKEDITOR.dom.range = function( root ) {
1715 }, 1720 },
1716 1721
1717 /** 1722 /**
1718 * Descrease the range to make sure that boundaries 1723 * Decreases the range to make sure that boundaries
1719 * always anchor beside text nodes or innermost element. 1724 * always anchor beside text nodes or the innermost element.
1720 * 1725 *
1721 * @param {Number} mode The shrinking mode ({@link CKEDITOR#SHRINK_ELEMENT} or {@link CKEDITOR#SHRINK_TEXT}). 1726 * @param {Number} mode The shrinking mode ({@link CKEDITOR#SHRINK_ELEMENT} or {@link CKEDITOR#SHRINK_TEXT}).
1722 * 1727 *
1723 * * {@link CKEDITOR#SHRINK_ELEMENT} - Shrink the range boundaries to the edge of the innermost element. 1728 * * {@link CKEDITOR#SHRINK_ELEMENT} &ndash; Shrinks the range boundaries to the edge of the innermost element.
1724 * * {@link CKEDITOR#SHRINK_TEXT} - Shrink the range boudaries to anchor by the side of enclosed text 1729 * * {@link CKEDITOR#SHRINK_TEXT} &ndash; Shrinks the range boundaries to anchor by the side of enclosed text
1725 * node, range remains if there's no text nodes on boundaries at all. 1730 * node. The range remains if there are no text nodes available on boundaries.
1726 * 1731 *
1727 * @param {Boolean} selectContents Whether result range anchors at the inner OR outer boundary of the node. 1732 * @param {Boolean} [selectContents=false] Whether the resulting range anchors at the inner OR outer boundary of the node.
1733 * @param {Boolean/Object} [options=true] If this parameter is of a Boolean type, it is treated as
1734 * `options.shrinkOnBlockBoundary`. This parameter was added in 4.7.0.
1735 * @param {Boolean} [options.shrinkOnBlockBoundary=true] Whether the block boundary should be included in
1736 * the shrunk range.
1737 * @param {Boolean} [options.skipBogus=false] Whether bogus `<br>` elements should be ignored while
1738 * `mode` is set to {@link CKEDITOR#SHRINK_TEXT}. This option was added in 4.7.0.
1728 */ 1739 */
1729 shrink: function( mode, selectContents, shrinkOnBlockBoundary ) { 1740 shrink: function( mode, selectContents, options ) {
1741 var shrinkOnBlockBoundary = typeof options === 'boolean' ? options :
1742 ( options && typeof options.shrinkOnBlockBoundary === 'boolean' ? options.shrinkOnBlockBoundary : true ),
1743 skipBogus = options && options.skipBogus;
1744
1730 // Unable to shrink a collapsed range. 1745 // Unable to shrink a collapsed range.
1731 if ( !this.collapsed ) { 1746 if ( !this.collapsed ) {
1732 mode = mode || CKEDITOR.SHRINK_TEXT; 1747 mode = mode || CKEDITOR.SHRINK_TEXT;
@@ -1749,7 +1764,7 @@ CKEDITOR.dom.range = function( root ) {
1749 walkerRange.setStartAfter( startContainer ); 1764 walkerRange.setStartAfter( startContainer );
1750 else { 1765 else {
1751 // Enlarge the range properly to avoid walker making 1766 // Enlarge the range properly to avoid walker making
1752 // DOM changes caused by triming the text nodes later. 1767 // DOM changes caused by trimming the text nodes later.
1753 walkerRange.setStartBefore( startContainer ); 1768 walkerRange.setStartBefore( startContainer );
1754 moveStart = 0; 1769 moveStart = 0;
1755 } 1770 }
@@ -1767,7 +1782,8 @@ CKEDITOR.dom.range = function( root ) {
1767 } 1782 }
1768 1783
1769 var walker = new CKEDITOR.dom.walker( walkerRange ), 1784 var walker = new CKEDITOR.dom.walker( walkerRange ),
1770 isBookmark = CKEDITOR.dom.walker.bookmark(); 1785 isBookmark = CKEDITOR.dom.walker.bookmark(),
1786 isBogus = CKEDITOR.dom.walker.bogus();
1771 1787
1772 walker.evaluator = function( node ) { 1788 walker.evaluator = function( node ) {
1773 return node.type == ( mode == CKEDITOR.SHRINK_ELEMENT ? CKEDITOR.NODE_ELEMENT : CKEDITOR.NODE_TEXT ); 1789 return node.type == ( mode == CKEDITOR.SHRINK_ELEMENT ? CKEDITOR.NODE_ELEMENT : CKEDITOR.NODE_TEXT );
@@ -1775,6 +1791,11 @@ CKEDITOR.dom.range = function( root ) {
1775 1791
1776 var currentElement; 1792 var currentElement;
1777 walker.guard = function( node, movingOut ) { 1793 walker.guard = function( node, movingOut ) {
1794 // Skipping bogus before other cases (http://dev.ckeditor.com/ticket/17010).
1795 if ( skipBogus && isBogus( node ) ) {
1796 return true;
1797 }
1798
1778 if ( isBookmark( node ) ) 1799 if ( isBookmark( node ) )
1779 return true; 1800 return true;
1780 1801
@@ -1816,7 +1837,7 @@ CKEDITOR.dom.range = function( root ) {
1816 1837
1817 /** 1838 /**
1818 * Inserts a node at the start of the range. The range will be expanded 1839 * Inserts a node at the start of the range. The range will be expanded
1819 * the contain the node. 1840 * to contain the node.
1820 * 1841 *
1821 * @param {CKEDITOR.dom.node} node 1842 * @param {CKEDITOR.dom.node} node
1822 */ 1843 */
@@ -1843,7 +1864,7 @@ CKEDITOR.dom.range = function( root ) {
1843 }, 1864 },
1844 1865
1845 /** 1866 /**
1846 * Moves the range to given position according to specified node. 1867 * Moves the range to a given position according to the specified node.
1847 * 1868 *
1848 * // HTML: <p>Foo <b>bar</b></p> 1869 * // HTML: <p>Foo <b>bar</b></p>
1849 * range.moveToPosition( elB, CKEDITOR.POSITION_BEFORE_START ); 1870 * range.moveToPosition( elB, CKEDITOR.POSITION_BEFORE_START );
@@ -1851,7 +1872,7 @@ CKEDITOR.dom.range = function( root ) {
1851 * 1872 *
1852 * See also {@link #setStartAt} and {@link #setEndAt}. 1873 * See also {@link #setStartAt} and {@link #setEndAt}.
1853 * 1874 *
1854 * @param {CKEDITOR.dom.node} node The node according to which position will be set. 1875 * @param {CKEDITOR.dom.node} node The node according to which the position will be set.
1855 * @param {Number} position One of {@link CKEDITOR#POSITION_BEFORE_START}, 1876 * @param {Number} position One of {@link CKEDITOR#POSITION_BEFORE_START},
1856 * {@link CKEDITOR#POSITION_AFTER_START}, {@link CKEDITOR#POSITION_BEFORE_END}, 1877 * {@link CKEDITOR#POSITION_AFTER_START}, {@link CKEDITOR#POSITION_BEFORE_END},
1857 * {@link CKEDITOR#POSITION_AFTER_END}. 1878 * {@link CKEDITOR#POSITION_AFTER_END}.
@@ -2118,7 +2139,7 @@ CKEDITOR.dom.range = function( root ) {
2118 // So even if the initial range was placed before the bogus <br>, after creating the bookmark it 2139 // So even if the initial range was placed before the bogus <br>, after creating the bookmark it
2119 // is placed before the bookmark. 2140 // is placed before the bookmark.
2120 // Fortunately, getBogus() is able to skip the bookmark so it finds the bogus <br> in this case. 2141 // Fortunately, getBogus() is able to skip the bookmark so it finds the bogus <br> in this case.
2121 // We remove incorrectly placed one and add a brand new one. (#13001) 2142 // We remove incorrectly placed one and add a brand new one. (http://dev.ckeditor.com/ticket/13001)
2122 var bogus = fixedBlock.getBogus(); 2143 var bogus = fixedBlock.getBogus();
2123 if ( bogus ) { 2144 if ( bogus ) {
2124 bogus.remove(); 2145 bogus.remove();
@@ -2340,7 +2361,7 @@ CKEDITOR.dom.range = function( root ) {
2340 this.trim( 0, 1 ); 2361 this.trim( 0, 1 );
2341 } 2362 }
2342 2363
2343 // Antecipate the trim() call here, so the walker will not make 2364 // Anticipate the trim() call here, so the walker will not make
2344 // changes to the DOM, which would not get reflected into this 2365 // changes to the DOM, which would not get reflected into this
2345 // range otherwise. 2366 // range otherwise.
2346 this.trim(); 2367 this.trim();
@@ -2379,7 +2400,7 @@ CKEDITOR.dom.range = function( root ) {
2379 this.trim( 1, 0 ); 2400 this.trim( 1, 0 );
2380 } 2401 }
2381 2402
2382 // Antecipate the trim() call here, so the walker will not make 2403 // Anticipate the trim() call here, so the walker will not make
2383 // changes to the DOM, which would not get reflected into this 2404 // changes to the DOM, which would not get reflected into this
2384 // range otherwise. 2405 // range otherwise.
2385 this.trim(); 2406 this.trim();
@@ -2636,7 +2657,7 @@ CKEDITOR.dom.range = function( root ) {
2636 getEnclosedNode: function() { 2657 getEnclosedNode: function() {
2637 var walkerRange = this.clone(); 2658 var walkerRange = this.clone();
2638 2659
2639 // Optimize and analyze the range to avoid DOM destructive nature of walker. (#5780) 2660 // Optimize and analyze the range to avoid DOM destructive nature of walker. (http://dev.ckeditor.com/ticket/5780)
2640 walkerRange.optimize(); 2661 walkerRange.optimize();
2641 if ( walkerRange.startContainer.type != CKEDITOR.NODE_ELEMENT || walkerRange.endContainer.type != CKEDITOR.NODE_ELEMENT ) 2662 if ( walkerRange.startContainer.type != CKEDITOR.NODE_ELEMENT || walkerRange.endContainer.type != CKEDITOR.NODE_ELEMENT )
2642 return null; 2663 return null;
@@ -2703,6 +2724,53 @@ CKEDITOR.dom.range = function( root ) {
2703 getPreviousEditableNode: getNextEditableNode( 1 ), 2724 getPreviousEditableNode: getNextEditableNode( 1 ),
2704 2725
2705 /** 2726 /**
2727 * Returns any table element, like `td`, `tbody`, `table` etc. from a given range. The element
2728 * is returned only if the range is contained within one table (might be a nested
2729 * table, but it cannot be two different tables on the same DOM level).
2730 *
2731 * @private
2732 * @since 4.7
2733 * @param {Object} [tableElements] Mapping of element names that should be considered.
2734 * @returns {CKEDITOR.dom.element/null}
2735 */
2736 _getTableElement: function( tableElements ) {
2737 tableElements = tableElements || {
2738 td: 1,
2739 th: 1,
2740 tr: 1,
2741 tbody: 1,
2742 thead: 1,
2743 tfoot: 1,
2744 table: 1
2745 };
2746
2747 var start = this.startContainer,
2748 end = this.endContainer,
2749 startTable = start.getAscendant( 'table', true ),
2750 endTable = end.getAscendant( 'table', true );
2751
2752 // Super weird edge case in Safari: if there is a table with only one cell inside and that cell
2753 // is selected, then the end boundary of the table is moved into editor's editable.
2754 // That case is also present when selecting the last cell inside nested table.
2755 if ( CKEDITOR.env.safari && startTable && end.equals( this.root ) ) {
2756 return start.getAscendant( tableElements, true );
2757 }
2758
2759 if ( this.getEnclosedNode() ) {
2760 return this.getEnclosedNode().getAscendant( tableElements, true );
2761 }
2762
2763 // Ensure that selection starts and ends in the same table or one of the table is inside the other.
2764 if ( startTable && endTable && ( startTable.equals( endTable ) || startTable.contains( endTable ) ||
2765 endTable.contains( startTable ) ) ) {
2766
2767 return start.getAscendant( tableElements, true );
2768 }
2769
2770 return null;
2771 },
2772
2773 /**
2706 * Scrolls the start of current range into view. 2774 * Scrolls the start of current range into view.
2707 */ 2775 */
2708 scrollIntoView: function() { 2776 scrollIntoView: function() {
@@ -2819,10 +2887,10 @@ CKEDITOR.dom.range = function( root ) {
2819 continue; 2887 continue;
2820 } 2888 }
2821 2889
2822 // It's not enough to get elements from common ancestor, because it migth contain too many matches. 2890 // It's not enough to get elements from common ancestor, because it might contain too many matches.
2823 // We need to ensure that returned items are between boundary points. 2891 // We need to ensure that returned items are between boundary points.
2824 isStartGood = ( curItem.getPosition( boundaries.startNode ) & CKEDITOR.POSITION_FOLLOWING ) || boundaries.startNode.equals( curItem ); 2892 isStartGood = ( curItem.getPosition( boundaries.startNode ) & CKEDITOR.POSITION_FOLLOWING ) || boundaries.startNode.equals( curItem );
2825 isEndGood = ( curItem.getPosition( boundaries.endNode ) & ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IS_CONTAINED ) ); 2893 isEndGood = ( curItem.getPosition( boundaries.endNode ) & ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IS_CONTAINED ) ) || boundaries.endNode.equals( curItem );
2826 2894
2827 if ( isStartGood && isEndGood ) { 2895 if ( isStartGood && isEndGood ) {
2828 ret.push( curItem ); 2896 ret.push( curItem );
@@ -2834,6 +2902,62 @@ CKEDITOR.dom.range = function( root ) {
2834 } 2902 }
2835 }; 2903 };
2836 2904
2905 /**
2906 * Merges every subsequent range in given set, returning a smaller array of ranges.
2907 *
2908 * Note that each range in the returned value will be enlarged with `CKEDITOR.ENLARGE_ELEMENT` value.
2909 *
2910 * @since 4.7.0
2911 * @static
2912 * @param {CKEDITOR.dom.range[]} ranges
2913 * @returns {CKEDITOR.dom.range[]} Set of merged ranges.
2914 * @member CKEDITOR.dom.range
2915 */
2916 CKEDITOR.dom.range.mergeRanges = function( ranges ) {
2917 return CKEDITOR.tools.array.reduce( ranges, function( ret, rng ) {
2918 // Last range ATM.
2919 var lastRange = ret[ ret.length - 1 ],
2920 isContinuation = false;
2921
2922 // Make a clone, we don't want to modify input.
2923 rng = rng.clone();
2924 rng.enlarge( CKEDITOR.ENLARGE_ELEMENT );
2925
2926 if ( lastRange ) {
2927 // The trick is to create a range spanning the gap between the two ranges. Then iterate over
2928 // each node found in this gap. If it contains anything other than whitespace, then it means it
2929 // is not a continuation.
2930 var gapRange = new CKEDITOR.dom.range( rng.root ),
2931 walker = new CKEDITOR.dom.walker( gapRange ),
2932 isWhitespace = CKEDITOR.dom.walker.whitespaces(),
2933 nodeInBetween;
2934
2935 gapRange.setStart( lastRange.endContainer, lastRange.endOffset );
2936 gapRange.setEnd( rng.startContainer, rng.startOffset );
2937
2938 nodeInBetween = walker.next();
2939
2940 while ( isWhitespace( nodeInBetween ) || rng.endContainer.equals( nodeInBetween ) ) {
2941 // We don't care about whitespaces, and range container. Also we skip the endContainer,
2942 // as it will also be provided by the iterator (as it visits it's opening tag).
2943 nodeInBetween = walker.next();
2944 }
2945
2946 // Simply, if anything has been found there's a content in between the two.
2947 isContinuation = !nodeInBetween;
2948 }
2949
2950 if ( isContinuation ) {
2951 // If last range ends, where the current range starts, then let's merge it.
2952 lastRange.setEnd( rng.endContainer, rng.endOffset );
2953 } else {
2954 // In other case just push cur range into the stack.
2955 ret.push( rng );
2956 }
2957
2958 return ret;
2959 }, [] );
2960 };
2837 2961
2838} )(); 2962} )();
2839 2963
diff --git a/sources/core/dom/rangelist.js b/sources/core/dom/rangelist.js
index 250dfd9..15ccb88 100644
--- a/sources/core/dom/rangelist.js
+++ b/sources/core/dom/rangelist.js
@@ -164,7 +164,7 @@
164 }; 164 };
165 165
166 // Update the specified range which has been mangled by previous insertion of 166 // Update the specified range which has been mangled by previous insertion of
167 // range bookmark nodes.(#3256) 167 // range bookmark nodes.(http://dev.ckeditor.com/ticket/3256)
168 function updateDirtyRange( bookmark, dirtyRange, checkEnd ) { 168 function updateDirtyRange( bookmark, dirtyRange, checkEnd ) {
169 var serializable = bookmark.serializable, 169 var serializable = bookmark.serializable,
170 container = dirtyRange[ checkEnd ? 'endContainer' : 'startContainer' ], 170 container = dirtyRange[ checkEnd ? 'endContainer' : 'startContainer' ],
diff --git a/sources/core/dom/text.js b/sources/core/dom/text.js
index ce20ffe..e77a3d9 100644
--- a/sources/core/dom/text.js
+++ b/sources/core/dom/text.js
@@ -106,7 +106,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.text.prototype, {
106 retval.insertAfter( this ); 106 retval.insertAfter( this );
107 } else { 107 } else {
108 // IE BUG: IE8+ does not update the childNodes array in DOM after splitText(), 108 // IE BUG: IE8+ does not update the childNodes array in DOM after splitText(),
109 // we need to make some DOM changes to make it update. (#3436) 109 // we need to make some DOM changes to make it update. (http://dev.ckeditor.com/ticket/3436)
110 var workaround = doc.createText( '' ); 110 var workaround = doc.createText( '' );
111 workaround.insertAfter( retval ); 111 workaround.insertAfter( retval );
112 workaround.remove(); 112 workaround.remove();
diff --git a/sources/core/dom/walker.js b/sources/core/dom/walker.js
index cec4574..8665909 100644
--- a/sources/core/dom/walker.js
+++ b/sources/core/dom/walker.js
@@ -319,7 +319,7 @@
319 */ 319 */
320 CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames ) { 320 CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames ) {
321 // Whether element is in normal page flow. Floated or positioned elements are out of page flow. 321 // Whether element is in normal page flow. Floated or positioned elements are out of page flow.
322 // Don't consider floated or positioned formatting as block boundary, fall back to dtd check in that case. (#6297) 322 // Don't consider floated or positioned formatting as block boundary, fall back to dtd check in that case. (http://dev.ckeditor.com/ticket/6297)
323 var inPageFlow = this.getComputedStyle( 'float' ) == 'none' && !( this.getComputedStyle( 'position' ) in outOfFlowPositions ); 323 var inPageFlow = this.getComputedStyle( 'float' ) == 'none' && !( this.getComputedStyle( 'position' ) in outOfFlowPositions );
324 324
325 if ( inPageFlow && blockBoundaryDisplayMatch[ this.getComputedStyle( 'display' ) ] ) 325 if ( inPageFlow && blockBoundaryDisplayMatch[ this.getComputedStyle( 'display' ) ] )
@@ -388,7 +388,7 @@
388 return function( node ) { 388 return function( node ) {
389 var isWhitespace; 389 var isWhitespace;
390 if ( node && node.type == CKEDITOR.NODE_TEXT ) { 390 if ( node && node.type == CKEDITOR.NODE_TEXT ) {
391 // Whitespace, as well as the Filling Char Sequence text node used in Webkit. (#9384, #13816) 391 // Whitespace, as well as the Filling Char Sequence text node used in Webkit. (http://dev.ckeditor.com/ticket/9384, http://dev.ckeditor.com/ticket/13816)
392 isWhitespace = !CKEDITOR.tools.trim( node.getText() ) || 392 isWhitespace = !CKEDITOR.tools.trim( node.getText() ) ||
393 CKEDITOR.env.webkit && node.getText() == CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE; 393 CKEDITOR.env.webkit && node.getText() == CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE;
394 } 394 }
@@ -406,7 +406,7 @@
406 */ 406 */
407 CKEDITOR.dom.walker.invisible = function( isReject ) { 407 CKEDITOR.dom.walker.invisible = function( isReject ) {
408 var whitespace = CKEDITOR.dom.walker.whitespaces(), 408 var whitespace = CKEDITOR.dom.walker.whitespaces(),
409 // #12221 (Chrome) plus #11111 (Safari). 409 // http://dev.ckeditor.com/ticket/12221 (Chrome) plus http://dev.ckeditor.com/ticket/11111 (Safari).
410 offsetWidth0 = CKEDITOR.env.webkit ? 1 : 0; 410 offsetWidth0 = CKEDITOR.env.webkit ? 1 : 0;
411 411
412 return function( node ) { 412 return function( node ) {
@@ -422,7 +422,7 @@
422 // Nodes that take no spaces in wysiwyg: 422 // Nodes that take no spaces in wysiwyg:
423 // 1. White-spaces but not including NBSP. 423 // 1. White-spaces but not including NBSP.
424 // 2. Empty inline elements, e.g. <b></b>. 424 // 2. Empty inline elements, e.g. <b></b>.
425 // 3. <br> elements (bogus, surrounded by text) (#12423). 425 // 3. <br> elements (bogus, surrounded by text) (http://dev.ckeditor.com/ticket/12423).
426 invisible = node.$.offsetWidth <= offsetWidth0; 426 invisible = node.$.offsetWidth <= offsetWidth0;
427 } 427 }
428 428
@@ -636,7 +636,7 @@
636 * @returns {CKEDITOR.dom.node/Boolean} Bogus node or `false`. 636 * @returns {CKEDITOR.dom.node/Boolean} Bogus node or `false`.
637 */ 637 */
638 CKEDITOR.dom.element.prototype.getBogus = function() { 638 CKEDITOR.dom.element.prototype.getBogus = function() {
639 // Bogus are not always at the end, e.g. <p><a>text<br /></a></p> (#7070). 639 // Bogus are not always at the end, e.g. <p><a>text<br /></a></p> (http://dev.ckeditor.com/ticket/7070).
640 var tail = this; 640 var tail = this;
641 do { 641 do {
642 tail = tail.getPreviousSourceNode(); 642 tail = tail.getPreviousSourceNode();
diff --git a/sources/core/editable.js b/sources/core/editable.js
index c50ec7f..6b3fa9f 100644
--- a/sources/core/editable.js
+++ b/sources/core/editable.js
@@ -76,7 +76,7 @@
76 76
77 // [Edge] Starting from EdgeHTML 14.14393, it does not support `setActive`. We need to use focus which 77 // [Edge] Starting from EdgeHTML 14.14393, it does not support `setActive`. We need to use focus which
78 // causes unexpected scroll. Store scrollTop value so it can be restored after focusing editor. 78 // causes unexpected scroll. Store scrollTop value so it can be restored after focusing editor.
79 // Scroll only happens if the editor is focused for the first time. (#14825) 79 // Scroll only happens if the editor is focused for the first time. (http://dev.ckeditor.com/ticket/14825)
80 if ( CKEDITOR.env.edge && CKEDITOR.env.version > 14 && !this.hasFocus && this.getDocument().equals( CKEDITOR.document ) ) { 80 if ( CKEDITOR.env.edge && CKEDITOR.env.version > 14 && !this.hasFocus && this.getDocument().equals( CKEDITOR.document ) ) {
81 this.editor._.previousScrollTop = this.$.scrollTop; 81 this.editor._.previousScrollTop = this.$.scrollTop;
82 } 82 }
@@ -87,7 +87,15 @@
87 if ( CKEDITOR.env.ie && !( CKEDITOR.env.edge && CKEDITOR.env.version > 14 ) && this.getDocument().equals( CKEDITOR.document ) ) { 87 if ( CKEDITOR.env.ie && !( CKEDITOR.env.edge && CKEDITOR.env.version > 14 ) && this.getDocument().equals( CKEDITOR.document ) ) {
88 this.$.setActive(); 88 this.$.setActive();
89 } else { 89 } else {
90 this.$.focus(); 90 // We have no control over exactly what happens when the native `focus` method is called,
91 // so save the scroll position and restore it later.
92 if ( CKEDITOR.env.chrome ) {
93 var scrollPos = this.$.scrollTop;
94 this.$.focus();
95 this.$.scrollTop = scrollPos;
96 } else {
97 this.$.focus();
98 }
91 } 99 }
92 } catch ( e ) { 100 } catch ( e ) {
93 // IE throws unspecified error when focusing editable after closing dialog opened on nested editable. 101 // IE throws unspecified error when focusing editable after closing dialog opened on nested editable.
@@ -95,7 +103,7 @@
95 throw e; 103 throw e;
96 } 104 }
97 105
98 // Remedy if Safari doens't applies focus properly. (#279) 106 // Remedy if Safari doens't applies focus properly. (http://dev.ckeditor.com/ticket/279)
99 if ( CKEDITOR.env.safari && !this.isInline() ) { 107 if ( CKEDITOR.env.safari && !this.isInline() ) {
100 active = CKEDITOR.document.getActive(); 108 active = CKEDITOR.document.getActive();
101 if ( !active.equals( this.getWindow().getFrame() ) ) 109 if ( !active.equals( this.getWindow().getFrame() ) )
@@ -117,7 +125,7 @@
117 125
118 // The "focusin/focusout" events bubbled, e.g. If there are elements with layout 126 // The "focusin/focusout" events bubbled, e.g. If there are elements with layout
119 // they fire this event when clicking in to edit them but it must be ignored 127 // they fire this event when clicking in to edit them but it must be ignored
120 // to allow edit their contents. (#4682) 128 // to allow edit their contents. (http://dev.ckeditor.com/ticket/4682)
121 fn = isNotBubbling( fn, this ); 129 fn = isNotBubbling( fn, this );
122 args[ 0 ] = name; 130 args[ 0 ] = name;
123 args[ 1 ] = fn; 131 args[ 1 ] = fn;
@@ -252,7 +260,7 @@
252 * @param {String} text 260 * @param {String} text
253 */ 261 */
254 insertText: function( text ) { 262 insertText: function( text ) {
255 // Focus the editor before calling transformPlainTextToHtml. (#12726) 263 // Focus the editor before calling transformPlainTextToHtml. (http://dev.ckeditor.com/ticket/12726)
256 this.editor.focus(); 264 this.editor.focus();
257 this.insertHtml( this.transformPlainTextToHtml( text ), 'text' ); 265 this.insertHtml( this.transformPlainTextToHtml( text ), 'text' );
258 }, 266 },
@@ -350,7 +358,7 @@
350 insertElement: function( element, range ) { 358 insertElement: function( element, range ) {
351 var editor = this.editor; 359 var editor = this.editor;
352 360
353 // Prepare for the insertion. For example - focus editor (#11848). 361 // Prepare for the insertion. For example - focus editor (http://dev.ckeditor.com/ticket/11848).
354 editor.focus(); 362 editor.focus();
355 editor.fire( 'saveSnapshot' ); 363 editor.fire( 'saveSnapshot' );
356 364
@@ -363,12 +371,12 @@
363 range = selection.getRanges()[ 0 ]; 371 range = selection.getRanges()[ 0 ];
364 } 372 }
365 373
366 // Insert element into first range only and ignore the rest (#11183). 374 // Insert element into first range only and ignore the rest (http://dev.ckeditor.com/ticket/11183).
367 if ( this.insertElementIntoRange( element, range ) ) { 375 if ( this.insertElementIntoRange( element, range ) ) {
368 range.moveToPosition( element, CKEDITOR.POSITION_AFTER_END ); 376 range.moveToPosition( element, CKEDITOR.POSITION_AFTER_END );
369 377
370 // If we're inserting a block element, the new cursor position must be 378 // If we're inserting a block element, the new cursor position must be
371 // optimized. (#3100,#5436,#8950) 379 // optimized. (http://dev.ckeditor.com/ticket/3100,http://dev.ckeditor.com/ticket/5436,http://dev.ckeditor.com/ticket/8950)
372 if ( isBlock ) { 380 if ( isBlock ) {
373 // Find next, meaningful element. 381 // Find next, meaningful element.
374 var next = element.getNext( function( node ) { 382 var next = element.getNext( function( node ) {
@@ -456,7 +464,7 @@
456 range.splitElement( current ); 464 range.splitElement( current );
457 465
458 // If we're in an empty block which indicate a new paragraph, 466 // If we're in an empty block which indicate a new paragraph,
459 // simply replace it with the inserting block.(#3664) 467 // simply replace it with the inserting block.(http://dev.ckeditor.com/ticket/3664)
460 else if ( range.checkStartOfBlock() && range.checkEndOfBlock() ) { 468 else if ( range.checkStartOfBlock() && range.checkEndOfBlock() ) {
461 range.setStartBefore( current ); 469 range.setStartBefore( current );
462 range.collapse( true ); 470 range.collapse( true );
@@ -770,7 +778,7 @@
770 range.checkEndOfBlock() && 778 range.checkEndOfBlock() &&
771 path.block && 779 path.block &&
772 !range.root.equals( path.block ) && 780 !range.root.equals( path.block ) &&
773 // Do not remove a block with bookmarks. (#13465) 781 // Do not remove a block with bookmarks. (http://dev.ckeditor.com/ticket/13465)
774 !hasBookmarks( path.block ) ) { 782 !hasBookmarks( path.block ) ) {
775 range.moveToPosition( path.block, CKEDITOR.POSITION_BEFORE_START ); 783 range.moveToPosition( path.block, CKEDITOR.POSITION_BEFORE_START );
776 path.block.remove(); 784 path.block.remove();
@@ -832,7 +840,7 @@
832 840
833 // IE considers control-type element as separate 841 // IE considers control-type element as separate
834 // focus host when selected, avoid destroying the 842 // focus host when selected, avoid destroying the
835 // selection in such case. (#5812) (#8949) 843 // selection in such case. (http://dev.ckeditor.com/ticket/5812) (http://dev.ckeditor.com/ticket/8949)
836 if ( ieSel && ieSel.type == 'Control' ) 844 if ( ieSel && ieSel.type == 'Control' )
837 return; 845 return;
838 846
@@ -884,14 +892,14 @@
884 }, null, null, -1 ); 892 }, null, null, -1 );
885 893
886 if ( CKEDITOR.env.webkit ) { 894 if ( CKEDITOR.env.webkit ) {
887 // [WebKit] Save scrollTop value so it can be used when restoring locked selection. (#14659) 895 // [WebKit] Save scrollTop value so it can be used when restoring locked selection. (http://dev.ckeditor.com/ticket/14659)
888 this.on( 'scroll', function() { 896 this.on( 'scroll', function() {
889 editor._.previousScrollTop = editor.editable().$.scrollTop; 897 editor._.previousScrollTop = editor.editable().$.scrollTop;
890 }, null, null, -1 ); 898 }, null, null, -1 );
891 } 899 }
892 900
893 // [Edge] This is the other part of the workaround for Edge which restores saved 901 // [Edge] This is the other part of the workaround for Edge which restores saved
894 // scrollTop value and removes listener which is not needed anymore. (#14825) 902 // scrollTop value and removes listener which is not needed anymore. (http://dev.ckeditor.com/ticket/14825)
895 if ( CKEDITOR.env.edge && CKEDITOR.env.version > 14 ) { 903 if ( CKEDITOR.env.edge && CKEDITOR.env.version > 14 ) {
896 904
897 var fixScrollOnFocus = function() { 905 var fixScrollOnFocus = function() {
@@ -967,7 +975,7 @@
967 // Pass this configuration to styles system. 975 // Pass this configuration to styles system.
968 this.setCustomData( 'cke_includeReadonly', !editor.config.disableReadonlyStyling ); 976 this.setCustomData( 'cke_includeReadonly', !editor.config.disableReadonlyStyling );
969 977
970 // Prevent the browser opening read-only links. (#6032 & #10912) 978 // Prevent the browser opening read-only links. (http://dev.ckeditor.com/ticket/6032 & http://dev.ckeditor.com/ticket/10912)
971 this.attachListener( this, 'click', function( evt ) { 979 this.attachListener( this, 'click', function( evt ) {
972 evt = evt.data; 980 evt = evt.data;
973 981
@@ -980,7 +988,7 @@
980 var backspaceOrDelete = { 8: 1, 46: 1 }; 988 var backspaceOrDelete = { 8: 1, 46: 1 };
981 989
982 // Override keystrokes which should have deletion behavior 990 // Override keystrokes which should have deletion behavior
983 // on fully selected element . (#4047) (#7645) 991 // on fully selected element . (http://dev.ckeditor.com/ticket/4047) (http://dev.ckeditor.com/ticket/7645)
984 this.attachListener( editor, 'key', function( evt ) { 992 this.attachListener( editor, 'key', function( evt ) {
985 if ( editor.readOnly ) 993 if ( editor.readOnly )
986 return true; 994 return true;
@@ -990,10 +998,15 @@
990 var keyCode = evt.data.domEvent.getKey(), 998 var keyCode = evt.data.domEvent.getKey(),
991 isHandled; 999 isHandled;
992 1000
1001 // Prevent of reading path of empty range (http://dev.ckeditor.com/ticket/13096, #457).
1002 var sel = editor.getSelection();
1003 if ( sel.getRanges().length === 0 ) {
1004 return;
1005 }
1006
993 // Backspace OR Delete. 1007 // Backspace OR Delete.
994 if ( keyCode in backspaceOrDelete ) { 1008 if ( keyCode in backspaceOrDelete ) {
995 var sel = editor.getSelection(), 1009 var selected,
996 selected,
997 range = sel.getRanges()[ 0 ], 1010 range = sel.getRanges()[ 0 ],
998 path = range.startPath(), 1011 path = range.startPath(),
999 block, 1012 block,
@@ -1001,16 +1014,17 @@
1001 next, 1014 next,
1002 rtl = keyCode == 8; 1015 rtl = keyCode == 8;
1003 1016
1017
1004 if ( 1018 if (
1005 // [IE<11] Remove selected image/anchor/etc here to avoid going back in history. (#10055) 1019 // [IE<11] Remove selected image/anchor/etc here to avoid going back in history. (http://dev.ckeditor.com/ticket/10055)
1006 ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 && ( selected = sel.getSelectedElement() ) ) || 1020 ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 && ( selected = sel.getSelectedElement() ) ) ||
1007 // Remove the entire list/table on fully selected content. (#7645) 1021 // Remove the entire list/table on fully selected content. (http://dev.ckeditor.com/ticket/7645)
1008 ( selected = getSelectedTableList( sel ) ) ) { 1022 ( selected = getSelectedTableList( sel ) ) ) {
1009 // Make undo snapshot. 1023 // Make undo snapshot.
1010 editor.fire( 'saveSnapshot' ); 1024 editor.fire( 'saveSnapshot' );
1011 1025
1012 // Delete any element that 'hasLayout' (e.g. hr,table) in IE8 will 1026 // Delete any element that 'hasLayout' (e.g. hr,table) in IE8 will
1013 // break up the selection, safely manage it here. (#4795) 1027 // break up the selection, safely manage it here. (http://dev.ckeditor.com/ticket/4795)
1014 range.moveToPosition( selected, CKEDITOR.POSITION_BEFORE_START ); 1028 range.moveToPosition( selected, CKEDITOR.POSITION_BEFORE_START );
1015 // Remove the control manually. 1029 // Remove the control manually.
1016 selected.remove(); 1030 selected.remove();
@@ -1020,7 +1034,7 @@
1020 1034
1021 isHandled = 1; 1035 isHandled = 1;
1022 } else if ( range.collapsed ) { 1036 } else if ( range.collapsed ) {
1023 // Handle the following special cases: (#6217) 1037 // Handle the following special cases: (http://dev.ckeditor.com/ticket/6217)
1024 // 1. Del/Backspace key before/after table; 1038 // 1. Del/Backspace key before/after table;
1025 // 2. Backspace Key after start of table. 1039 // 2. Backspace Key after start of table.
1026 if ( ( block = path.block ) && 1040 if ( ( block = path.block ) &&
@@ -1095,28 +1109,28 @@
1095 editor.fire( 'doubleclick', data ); 1109 editor.fire( 'doubleclick', data );
1096 } ); 1110 } );
1097 1111
1098 // Prevent automatic submission in IE #6336 1112 // Prevent automatic submission in IE http://dev.ckeditor.com/ticket/6336
1099 CKEDITOR.env.ie && this.attachListener( this, 'click', blockInputClick ); 1113 CKEDITOR.env.ie && this.attachListener( this, 'click', blockInputClick );
1100 1114
1101 // Gecko/Webkit need some help when selecting control type elements. (#3448) 1115 // Gecko/Webkit need some help when selecting control type elements. (http://dev.ckeditor.com/ticket/3448)
1102 // We apply same behavior for IE Edge. (#13386) 1116 // We apply same behavior for IE Edge. (http://dev.ckeditor.com/ticket/13386)
1103 if ( !CKEDITOR.env.ie || CKEDITOR.env.edge ) { 1117 if ( !CKEDITOR.env.ie || CKEDITOR.env.edge ) {
1104 this.attachListener( this, 'mousedown', function( ev ) { 1118 this.attachListener( this, 'mousedown', function( ev ) {
1105 var control = ev.data.getTarget(); 1119 var control = ev.data.getTarget();
1106 // #11727. Note: htmlDP assures that input/textarea/select have contenteditable=false 1120 // http://dev.ckeditor.com/ticket/11727. Note: htmlDP assures that input/textarea/select have contenteditable=false
1107 // attributes. However, they also have data-cke-editable attribute, so isReadOnly() returns false, 1121 // attributes. However, they also have data-cke-editable attribute, so isReadOnly() returns false,
1108 // and therefore those elements are correctly selected by this code. 1122 // and therefore those elements are correctly selected by this code.
1109 if ( control.is( 'img', 'hr', 'input', 'textarea', 'select' ) && !control.isReadOnly() ) { 1123 if ( control.is( 'img', 'hr', 'input', 'textarea', 'select' ) && !control.isReadOnly() ) {
1110 editor.getSelection().selectElement( control ); 1124 editor.getSelection().selectElement( control );
1111 1125
1112 // Prevent focus from stealing from the editable. (#9515) 1126 // Prevent focus from stealing from the editable. (http://dev.ckeditor.com/ticket/9515)
1113 if ( control.is( 'input', 'textarea', 'select' ) ) 1127 if ( control.is( 'input', 'textarea', 'select' ) )
1114 ev.data.preventDefault(); 1128 ev.data.preventDefault();
1115 } 1129 }
1116 } ); 1130 } );
1117 } 1131 }
1118 1132
1119 // For some reason, after click event is done, IE Edge loses focus on the selected element. (#13386) 1133 // For some reason, after click event is done, IE Edge loses focus on the selected element. (http://dev.ckeditor.com/ticket/13386)
1120 if ( CKEDITOR.env.edge ) { 1134 if ( CKEDITOR.env.edge ) {
1121 this.attachListener( this, 'mouseup', function( ev ) { 1135 this.attachListener( this, 'mouseup', function( ev ) {
1122 var selectedElement = ev.data.getTarget(); 1136 var selectedElement = ev.data.getTarget();
@@ -1127,7 +1141,7 @@
1127 } 1141 }
1128 1142
1129 // Prevent right click from selecting an empty block even 1143 // Prevent right click from selecting an empty block even
1130 // when selection is anchored inside it. (#5845) 1144 // when selection is anchored inside it. (http://dev.ckeditor.com/ticket/5845)
1131 if ( CKEDITOR.env.gecko ) { 1145 if ( CKEDITOR.env.gecko ) {
1132 this.attachListener( this, 'mouseup', function( ev ) { 1146 this.attachListener( this, 'mouseup', function( ev ) {
1133 if ( ev.data.$.button == 2 ) { 1147 if ( ev.data.$.button == 2 ) {
@@ -1158,7 +1172,7 @@
1158 } 1172 }
1159 1173
1160 // Prevent Webkit/Blink from going rogue when joining 1174 // Prevent Webkit/Blink from going rogue when joining
1161 // blocks on BACKSPACE/DEL (#11861,#9998). 1175 // blocks on BACKSPACE/DEL (http://dev.ckeditor.com/ticket/11861,http://dev.ckeditor.com/ticket/9998).
1162 if ( CKEDITOR.env.webkit ) { 1176 if ( CKEDITOR.env.webkit ) {
1163 this.attachListener( editor, 'key', function( evt ) { 1177 this.attachListener( editor, 'key', function( evt ) {
1164 if ( editor.readOnly ) { 1178 if ( editor.readOnly ) {
@@ -1172,8 +1186,14 @@
1172 if ( !( key in backspaceOrDelete ) ) 1186 if ( !( key in backspaceOrDelete ) )
1173 return; 1187 return;
1174 1188
1189 // Prevent of reading path of empty range (http://dev.ckeditor.com/ticket/13096, #457).
1190 var sel = editor.getSelection();
1191 if ( sel.getRanges().length === 0 ) {
1192 return;
1193 }
1194
1175 var backspace = key == 8, 1195 var backspace = key == 8,
1176 range = editor.getSelection().getRanges()[ 0 ], 1196 range = sel.getRanges()[ 0 ],
1177 startPath = range.startPath(); 1197 startPath = range.startPath();
1178 1198
1179 if ( range.collapsed ) { 1199 if ( range.collapsed ) {
@@ -1184,7 +1204,7 @@
1184 return; 1204 return;
1185 } 1205 }
1186 1206
1187 // Scroll to the new position of the caret (#11960). 1207 // Scroll to the new position of the caret (http://dev.ckeditor.com/ticket/11960).
1188 editor.getSelection().scrollIntoView(); 1208 editor.getSelection().scrollIntoView();
1189 editor.fire( 'saveSnapshot' ); 1209 editor.fire( 'saveSnapshot' );
1190 1210
@@ -1241,6 +1261,7 @@
1241 * @member CKEDITOR.editor 1261 * @member CKEDITOR.editor
1242 * @param {CKEDITOR.dom.element/CKEDITOR.editable} [elementOrEditable] The 1262 * @param {CKEDITOR.dom.element/CKEDITOR.editable} [elementOrEditable] The
1243 * DOM element to become the editable or a {@link CKEDITOR.editable} object. 1263 * DOM element to become the editable or a {@link CKEDITOR.editable} object.
1264 * @returns {CKEDITOR.dom.element/null} The editor's editable element, or `null` if not available.
1244 */ 1265 */
1245 CKEDITOR.editor.prototype.editable = function( element ) { 1266 CKEDITOR.editor.prototype.editable = function( element ) {
1246 var editable = this._.editable; 1267 var editable = this._.editable;
@@ -1263,7 +1284,7 @@
1263 CKEDITOR.on( 'instanceLoaded', function( evt ) { 1284 CKEDITOR.on( 'instanceLoaded', function( evt ) {
1264 var editor = evt.editor; 1285 var editor = evt.editor;
1265 1286
1266 // and flag that the element was locked by our code so it'll be editable by the editor functions (#6046). 1287 // and flag that the element was locked by our code so it'll be editable by the editor functions (http://dev.ckeditor.com/ticket/6046).
1267 editor.on( 'insertElement', function( evt ) { 1288 editor.on( 'insertElement', function( evt ) {
1268 var element = evt.data; 1289 var element = evt.data;
1269 if ( element.type == CKEDITOR.NODE_ELEMENT && ( element.is( 'input' ) || element.is( 'textarea' ) ) ) { 1290 if ( element.type == CKEDITOR.NODE_ELEMENT && ( element.is( 'input' ) || element.is( 'textarea' ) ) ) {
@@ -1278,9 +1299,9 @@
1278 if ( editor.readOnly ) 1299 if ( editor.readOnly )
1279 return; 1300 return;
1280 1301
1281 // Auto fixing on some document structure weakness to enhance usabilities. (#3190 and #3189) 1302 // Auto fixing on some document structure weakness to enhance usabilities. (http://dev.ckeditor.com/ticket/3190 and http://dev.ckeditor.com/ticket/3189)
1282 var sel = editor.getSelection(); 1303 var sel = editor.getSelection();
1283 // Do it only when selection is not locked. (#8222) 1304 // Do it only when selection is not locked. (http://dev.ckeditor.com/ticket/8222)
1284 if ( sel && !sel.isLocked ) { 1305 if ( sel && !sel.isLocked ) {
1285 var isDirty = editor.checkDirty(); 1306 var isDirty = editor.checkDirty();
1286 1307
@@ -1330,7 +1351,7 @@
1330 } ); 1351 } );
1331 } ); 1352 } );
1332 1353
1333 // #9222: Show text cursor in Gecko. 1354 // http://dev.ckeditor.com/ticket/9222: Show text cursor in Gecko.
1334 // Show default cursor over control elements on all non-IEs. 1355 // Show default cursor over control elements on all non-IEs.
1335 CKEDITOR.addCss( '.cke_editable{cursor:text}.cke_editable img,.cke_editable input,.cke_editable textarea{cursor:default}' ); 1356 CKEDITOR.addCss( '.cke_editable{cursor:text}.cke_editable img,.cke_editable input,.cke_editable textarea{cursor:default}' );
1336 1357
@@ -1347,8 +1368,8 @@
1347 // Matching an empty paragraph at the end of document. 1368 // Matching an empty paragraph at the end of document.
1348 emptyParagraphRegexp = /(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi; 1369 emptyParagraphRegexp = /(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi;
1349 1370
1350 // Auto-fixing block-less content by wrapping paragraph (#3190), prevent 1371 // Auto-fixing block-less content by wrapping paragraph (http://dev.ckeditor.com/ticket/3190), prevent
1351 // non-exitable-block by padding extra br.(#3189) 1372 // non-exitable-block by padding extra br.(http://dev.ckeditor.com/ticket/3189)
1352 // Returns truly value when dom was changed, falsy otherwise. 1373 // Returns truly value when dom was changed, falsy otherwise.
1353 function fixDom( evt ) { 1374 function fixDom( evt ) {
1354 var editor = evt.editor, 1375 var editor = evt.editor,
@@ -1369,7 +1390,7 @@
1369 } 1390 }
1370 1391
1371 // When we're in block enter mode, a new paragraph will be established 1392 // When we're in block enter mode, a new paragraph will be established
1372 // to encapsulate inline contents inside editable. (#3657) 1393 // to encapsulate inline contents inside editable. (http://dev.ckeditor.com/ticket/3657)
1373 // Don't autoparagraph if browser (namely - IE) incorrectly anchored selection 1394 // Don't autoparagraph if browser (namely - IE) incorrectly anchored selection
1374 // inside non-editable content. This happens e.g. if non-editable block is the only 1395 // inside non-editable content. This happens e.g. if non-editable block is the only
1375 // content of editable. 1396 // content of editable.
@@ -1397,7 +1418,7 @@
1397 1418
1398 selectionUpdateNeeded = 1; 1419 selectionUpdateNeeded = 1;
1399 1420
1400 // Cancel this selection change in favor of the next (correct). (#6811) 1421 // Cancel this selection change in favor of the next (correct). (http://dev.ckeditor.com/ticket/6811)
1401 evt.cancel(); 1422 evt.cancel();
1402 } 1423 }
1403 } 1424 }
@@ -1413,13 +1434,13 @@
1413 if ( selection.isFake ) 1434 if ( selection.isFake )
1414 return 0; 1435 return 0;
1415 1436
1416 // Ensure bogus br could help to move cursor (out of styles) to the end of block. (#7041) 1437 // Ensure bogus br could help to move cursor (out of styles) to the end of block. (http://dev.ckeditor.com/ticket/7041)
1417 var pathBlock = path.block || path.blockLimit, 1438 var pathBlock = path.block || path.blockLimit,
1418 lastNode = pathBlock && pathBlock.getLast( isNotEmpty ); 1439 lastNode = pathBlock && pathBlock.getLast( isNotEmpty );
1419 1440
1420 // Check some specialities of the current path block: 1441 // Check some specialities of the current path block:
1421 // 1. It is really displayed as block; (#7221) 1442 // 1. It is really displayed as block; (http://dev.ckeditor.com/ticket/7221)
1422 // 2. It doesn't end with one inner block; (#7467) 1443 // 2. It doesn't end with one inner block; (http://dev.ckeditor.com/ticket/7467)
1423 // 3. It doesn't have bogus br yet. 1444 // 3. It doesn't have bogus br yet.
1424 if ( 1445 if (
1425 pathBlock && pathBlock.isBlockBoundary() && 1446 pathBlock && pathBlock.isBlockBoundary() &&
@@ -1556,7 +1577,7 @@
1556 // Whether in given context (pathBlock, pathBlockLimit and editor settings) 1577 // Whether in given context (pathBlock, pathBlockLimit and editor settings)
1557 // editor should automatically wrap inline contents with blocks. 1578 // editor should automatically wrap inline contents with blocks.
1558 function shouldAutoParagraph( editor, pathBlock, pathBlockLimit ) { 1579 function shouldAutoParagraph( editor, pathBlock, pathBlockLimit ) {
1559 // Check whether pathBlock equals pathBlockLimit to support nested editable (#12162). 1580 // Check whether pathBlock equals pathBlockLimit to support nested editable (http://dev.ckeditor.com/ticket/12162).
1560 return editor.config.autoParagraph !== false && 1581 return editor.config.autoParagraph !== false &&
1561 editor.activeEnterMode != CKEDITOR.ENTER_BR && 1582 editor.activeEnterMode != CKEDITOR.ENTER_BR &&
1562 ( 1583 (
@@ -1623,7 +1644,7 @@
1623 1644
1624 // Select range and stop execution. 1645 // Select range and stop execution.
1625 // If data has been totally emptied after the filtering, 1646 // If data has been totally emptied after the filtering,
1626 // any insertion is pointless (#10339). 1647 // any insertion is pointless (http://dev.ckeditor.com/ticket/10339).
1627 if ( data && processDataForInsertion( that, data ) ) { 1648 if ( data && processDataForInsertion( that, data ) ) {
1628 // DATA INSERTION 1649 // DATA INSERTION
1629 insertDataIntoRange( that ); 1650 insertDataIntoRange( that );
@@ -2008,7 +2029,7 @@
2008 nodeName = node.getName(); 2029 nodeName = node.getName();
2009 2030
2010 // Extract only the list items, when insertion happens 2031 // Extract only the list items, when insertion happens
2011 // inside of a list, reads as rearrange list items. (#7957) 2032 // inside of a list, reads as rearrange list items. (http://dev.ckeditor.com/ticket/7957)
2012 if ( insideOfList && nodeName in CKEDITOR.dtd.$list ) { 2033 if ( insideOfList && nodeName in CKEDITOR.dtd.$list ) {
2013 nodesData = nodesData.concat( extractNodesData( node, that ) ); 2034 nodesData = nodesData.concat( extractNodesData( node, that ) );
2014 continue; 2035 continue;
@@ -2256,7 +2277,7 @@
2256 } 2277 }
2257 2278
2258 // Don't use String.replace because it fails in IE7 if special replacement 2279 // Don't use String.replace because it fails in IE7 if special replacement
2259 // characters ($$, $&, etc.) are in data (#10367). 2280 // characters ($$, $&, etc.) are in data (http://dev.ckeditor.com/ticket/10367).
2260 return wrapper.getOuterHtml().split( '{cke-peak}' ).join( data ); 2281 return wrapper.getOuterHtml().split( '{cke-peak}' ).join( data );
2261 } 2282 }
2262 2283
@@ -2517,7 +2538,7 @@
2517 if ( ( bogus = startBlock.getBogus() ) ) 2538 if ( ( bogus = startBlock.getBogus() ) )
2518 bogus.remove(); 2539 bogus.remove();
2519 2540
2520 // Changing end container to element from text node (#12503). 2541 // Changing end container to element from text node (http://dev.ckeditor.com/ticket/12503).
2521 range.enlarge( CKEDITOR.ENLARGE_INLINE ); 2542 range.enlarge( CKEDITOR.ENLARGE_INLINE );
2522 2543
2523 // Delete range contents. Do NOT merge. Merging is weird. 2544 // Delete range contents. Do NOT merge. Merging is weird.
@@ -2540,7 +2561,7 @@
2540 range = editor.getSelection().getRanges()[ 0 ]; 2561 range = editor.getSelection().getRanges()[ 0 ];
2541 range.collapse( 1 ); 2562 range.collapse( 1 );
2542 2563
2543 // Optimizing range containers from text nodes to elements (#12503). 2564 // Optimizing range containers from text nodes to elements (http://dev.ckeditor.com/ticket/12503).
2544 range.optimize(); 2565 range.optimize();
2545 if ( range.startContainer.getHtml() === '' ) { 2566 if ( range.startContainer.getHtml() === '' ) {
2546 range.startContainer.appendBogus(); 2567 range.startContainer.appendBogus();
@@ -2762,7 +2783,7 @@
2762 while ( ( next = endBookmark.getNext() ) ) { 2783 while ( ( next = endBookmark.getNext() ) ) {
2763 next.insertAfter( startBookmark ); 2784 next.insertAfter( startBookmark );
2764 2785
2765 // Update startBookmark after insertion to avoid the reversal of nodes (#13449). 2786 // Update startBookmark after insertion to avoid the reversal of nodes (http://dev.ckeditor.com/ticket/13449).
2766 startBookmark = next; 2787 startBookmark = next;
2767 } 2788 }
2768 2789
@@ -2913,7 +2934,7 @@
2913 2934
2914 walker.guard = function( node, leaving ) { 2935 walker.guard = function( node, leaving ) {
2915 // Guard may be executed on some node boundaries multiple times, 2936 // Guard may be executed on some node boundaries multiple times,
2916 // what results in creating more than one range for each selected cell. (#12964) 2937 // what results in creating more than one range for each selected cell. (http://dev.ckeditor.com/ticket/12964)
2917 if ( node.type == CKEDITOR.NODE_ELEMENT ) { 2938 if ( node.type == CKEDITOR.NODE_ELEMENT ) {
2918 var key = 'visited_' + ( leaving ? 'out' : 'in' ); 2939 var key = 'visited_' + ( leaving ? 'out' : 'in' );
2919 if ( node.getCustomData( key ) ) { 2940 if ( node.getCustomData( key ) ) {
diff --git a/sources/core/editor.js b/sources/core/editor.js
index 8dfce7f..640cec0 100644
--- a/sources/core/editor.js
+++ b/sources/core/editor.js
@@ -29,7 +29,7 @@
29 // Call the CKEDITOR.event constructor to initialize this instance. 29 // Call the CKEDITOR.event constructor to initialize this instance.
30 CKEDITOR.event.call( this ); 30 CKEDITOR.event.call( this );
31 31
32 // Make a clone of the config object, to avoid having it touched by our code. (#9636) 32 // Make a clone of the config object, to avoid having it touched by our code. (http://dev.ckeditor.com/ticket/9636)
33 instanceConfig = instanceConfig && CKEDITOR.tools.clone( instanceConfig ); 33 instanceConfig = instanceConfig && CKEDITOR.tools.clone( instanceConfig );
34 34
35 // if editor is created off one page element. 35 // if editor is created off one page element.
@@ -223,7 +223,7 @@
223 function updateCommandsContext( editor, path, forceRefresh ) { 223 function updateCommandsContext( editor, path, forceRefresh ) {
224 // Commands cannot be refreshed without a path. In edge cases 224 // Commands cannot be refreshed without a path. In edge cases
225 // it may happen that there's no selection when this function is executed. 225 // it may happen that there's no selection when this function is executed.
226 // For example when active filter is changed in #10877. 226 // For example when active filter is changed in http://dev.ckeditor.com/ticket/10877.
227 if ( !path ) 227 if ( !path )
228 return; 228 return;
229 229
@@ -270,7 +270,7 @@
270 } else { 270 } else {
271 // Load the custom configuration file. 271 // Load the custom configuration file.
272 // To resolve customConfig race conflicts, use scriptLoader#queue 272 // To resolve customConfig race conflicts, use scriptLoader#queue
273 // instead of scriptLoader#load (#6504). 273 // instead of scriptLoader#load (http://dev.ckeditor.com/ticket/6504).
274 CKEDITOR.scriptLoader.queue( customConfig, function() { 274 CKEDITOR.scriptLoader.queue( customConfig, function() {
275 // If the CKEDITOR.editorConfig function has been properly 275 // If the CKEDITOR.editorConfig function has been properly
276 // defined in the custom configuration file, cache it. 276 // defined in the custom configuration file, cache it.
@@ -654,24 +654,49 @@
654 return editor.blockless ? CKEDITOR.ENTER_BR : enterMode; 654 return editor.blockless ? CKEDITOR.ENTER_BR : enterMode;
655 } 655 }
656 656
657 // Create DocumentFragment from specified ranges. For now it handles only tables in Firefox 657 // Create DocumentFragment from specified ranges. For now it handles only tables
658 // and returns DocumentFragment from the 1. range for other cases. (#13884) 658 // and returns DocumentFragment from the 1. range for other cases. (http://dev.ckeditor.com/ticket/13884)
659 function createDocumentFragmentFromRanges( ranges, editable ) { 659 function createDocumentFragmentFromRanges( ranges, editable ) {
660 var docFragment = new CKEDITOR.dom.documentFragment(), 660 var docFragment = new CKEDITOR.dom.documentFragment(),
661 tableClone, 661 tableClone,
662 currentRow, 662 currentRow,
663 currentRowClone; 663 currentRowClone;
664 664
665 // We must handle two cases here:
666 // 1. <tr>[<td>Cell</td>]</tr> (IE9+, Edge, Chrome, Firefox)
667 // 2. <td>[Cell]</td> (IE8-, Safari)
668 function isSelectedCell( range ) {
669 var start = range.startContainer,
670 end = range.endContainer;
671
672 if ( start.is && ( start.is( 'tr' ) ||
673 ( start.is( 'td' ) && start.equals( end ) && range.endOffset === start.getChildCount() ) ) ) {
674 return true;
675 }
676
677 return false;
678 }
679
680 function cloneCell( range ) {
681 var start = range.startContainer;
682
683 if ( start.is( 'tr' ) ) {
684 return range.cloneContents();
685 }
686
687 return start.clone( true );
688 }
689
665 for ( var i = 0; i < ranges.length; i++ ) { 690 for ( var i = 0; i < ranges.length; i++ ) {
666 var range = ranges[ i ], 691 var range = ranges[ i ],
667 container = range.startContainer; 692 container = range.startContainer.getAscendant( 'tr', true );
668 693
669 if ( container.getName && container.getName() == 'tr' ) { 694 if ( isSelectedCell( range ) ) {
670 if ( !tableClone ) { 695 if ( !tableClone ) {
671 tableClone = container.getAscendant( 'table' ).clone(); 696 tableClone = container.getAscendant( 'table' ).clone();
672 tableClone.append( container.getAscendant( 'tbody' ).clone() ); 697 tableClone.append( container.getAscendant( { thead: 1, tbody: 1, tfoot: 1 } ).clone() );
673 docFragment.append( tableClone ); 698 docFragment.append( tableClone );
674 tableClone = tableClone.findOne( 'tbody' ); 699 tableClone = tableClone.findOne( 'thead, tbody, tfoot' );
675 } 700 }
676 701
677 if ( !( currentRow && currentRow.equals( container ) ) ) { 702 if ( !( currentRow && currentRow.equals( container ) ) ) {
@@ -680,7 +705,7 @@
680 tableClone.append( currentRowClone ); 705 tableClone.append( currentRowClone );
681 } 706 }
682 707
683 currentRowClone.append( range.cloneContents() ); 708 currentRowClone.append( cloneCell( range ) );
684 } else { 709 } else {
685 // If there was something else copied with table, 710 // If there was something else copied with table,
686 // append it to DocumentFragment. 711 // append it to DocumentFragment.
@@ -717,7 +742,7 @@
717 // This guarantees that commands added before first editor#mode 742 // This guarantees that commands added before first editor#mode
718 // aren't immediately updated, but waits for editor#mode and that 743 // aren't immediately updated, but waits for editor#mode and that
719 // commands added later are immediately refreshed, even when added 744 // commands added later are immediately refreshed, even when added
720 // before instanceReady. #10103, #10249 745 // before instanceReady. http://dev.ckeditor.com/ticket/10103, http://dev.ckeditor.com/ticket/10249
721 if ( this.mode ) 746 if ( this.mode )
722 updateCommand( this, cmd ); 747 updateCommand( this, cmd );
723 748
@@ -761,7 +786,7 @@
761 } ); 786 } );
762 } 787 }
763 788
764 // Remove 'submit' events registered on form element before destroying.(#3988) 789 // Remove 'submit' events registered on form element before destroying.(http://dev.ckeditor.com/ticket/3988)
765 editor.on( 'destroy', function() { 790 editor.on( 'destroy', function() {
766 form.removeListener( 'submit', onSubmit ); 791 form.removeListener( 'submit', onSubmit );
767 } ); 792 } );
@@ -771,7 +796,7 @@
771 function onSubmit( evt ) { 796 function onSubmit( evt ) {
772 editor.updateElement(); 797 editor.updateElement();
773 798
774 // #8031 If textarea had required attribute and editor is empty fire 'required' event and if 799 // http://dev.ckeditor.com/ticket/8031 If textarea had required attribute and editor is empty fire 'required' event and if
775 // it was cancelled, prevent submitting the form. 800 // it was cancelled, prevent submitting the form.
776 if ( editor._.required && !element.getValue() && editor.fire( 'required' ) === false ) { 801 if ( editor._.required && !element.getValue() && editor.fire( 'required' ) === false ) {
777 // When user press save button event (evt) is undefined (see save plugin). 802 // When user press save button event (evt) is undefined (see save plugin).
@@ -860,10 +885,10 @@
860 * 885 *
861 * editorInstance.execCommand( 'bold' ); 886 * editorInstance.execCommand( 'bold' );
862 * 887 *
863 * @param {String} commandName The indentifier name of the command. 888 * @param {String} commandName The identifier name of the command.
864 * @param {Object} [data] The data to be passed to the command. 889 * @param {Object} [data] The data to be passed to the command. It defaults to
865 * @returns {Boolean} `true` if the command was executed 890 * an empty object starting from 4.7.0.
866 * successfully, otherwise `false`. 891 * @returns {Boolean} `true` if the command was executed successfully, `false` otherwise.
867 * @see CKEDITOR.editor#addCommand 892 * @see CKEDITOR.editor#addCommand
868 */ 893 */
869 execCommand: function( commandName, data ) { 894 execCommand: function( commandName, data ) {
@@ -871,7 +896,7 @@
871 896
872 var eventData = { 897 var eventData = {
873 name: commandName, 898 name: commandName,
874 commandData: data, 899 commandData: data || {},
875 command: command 900 command: command
876 }; 901 };
877 902
@@ -967,7 +992,7 @@
967 } 992 }
968 else { 993 else {
969 // If we don't have a proper element, set data to an empty string, 994 // If we don't have a proper element, set data to an empty string,
970 // as this method is expected to return a string. (#13385) 995 // as this method is expected to return a string. (http://dev.ckeditor.com/ticket/13385)
971 data = ''; 996 data = '';
972 } 997 }
973 } 998 }
@@ -1069,7 +1094,7 @@
1069 this.readOnly = isReadOnly; 1094 this.readOnly = isReadOnly;
1070 1095
1071 // Block or release BACKSPACE key according to current read-only 1096 // Block or release BACKSPACE key according to current read-only
1072 // state to prevent browser's history navigation (#9761). 1097 // state to prevent browser's history navigation (http://dev.ckeditor.com/ticket/9761).
1073 this.keystrokeHandler.blockedKeystrokes[ 8 ] = +isReadOnly; 1098 this.keystrokeHandler.blockedKeystrokes[ 8 ] = +isReadOnly;
1074 1099
1075 this.editable().setReadOnly( isReadOnly ); 1100 this.editable().setReadOnly( isReadOnly );
@@ -1198,17 +1223,20 @@
1198 */ 1223 */
1199 extractSelectedHtml: function( toString, removeEmptyBlock ) { 1224 extractSelectedHtml: function( toString, removeEmptyBlock ) {
1200 var editable = this.editable(), 1225 var editable = this.editable(),
1201 ranges = this.getSelection().getRanges(); 1226 ranges = this.getSelection().getRanges(),
1227 docFragment = new CKEDITOR.dom.documentFragment(),
1228 i;
1202 1229
1203 if ( !editable || ranges.length === 0 ) { 1230 if ( !editable || ranges.length === 0 ) {
1204 return null; 1231 return null;
1205 } 1232 }
1206 1233
1207 var range = ranges[ 0 ], 1234 for ( i = 0; i < ranges.length; i++ ) {
1208 docFragment = editable.extractHtmlFromRange( range, removeEmptyBlock ); 1235 docFragment.append( editable.extractHtmlFromRange( ranges[ i ], removeEmptyBlock ) );
1236 }
1209 1237
1210 if ( !removeEmptyBlock ) { 1238 if ( !removeEmptyBlock ) {
1211 this.getSelection().selectRanges( [ range ] ); 1239 this.getSelection().selectRanges( [ ranges[ 0 ] ] );
1212 } 1240 }
1213 1241
1214 return toString ? docFragment.getHtml() : docFragment; 1242 return toString ? docFragment.getHtml() : docFragment;
@@ -1325,28 +1353,33 @@
1325 1353
1326 /** 1354 /**
1327 * Returns the keystroke that is assigned to a specified {@link CKEDITOR.command}. If no keystroke is assigned, 1355 * Returns the keystroke that is assigned to a specified {@link CKEDITOR.command}. If no keystroke is assigned,
1328 * it returns null. 1356 * it returns `null`.
1357 *
1358 * Since version 4.7.0 this function also accepts a `command` parameter as a string.
1329 * 1359 *
1330 * @since 4.6.0 1360 * @since 4.6.0
1331 * @param {CKEDITOR.command} command 1361 * @param {CKEDITOR.command/String} command The {@link CKEDITOR.command} instance or a string with the command name.
1332 * @returns {Number} The keystroke assigned to the provided command or null if there is no keystroke. 1362 * @returns {Number/null} The keystroke assigned to the provided command or `null` if there is no keystroke.
1333 */ 1363 */
1334 getCommandKeystroke: function( command ) { 1364 getCommandKeystroke: function( command ) {
1335 var commandName = command.name, 1365 var commandInstance = ( typeof command === 'string' ? this.getCommand( command ) : command );
1336 keystrokes = this.keystrokeHandler.keystrokes,
1337 key;
1338 1366
1339 // Some commands have a fake keystroke - for example CUT/COPY/PASTE commands are handled natively. 1367 if ( commandInstance ) {
1340 if ( command.fakeKeystroke ) { 1368 var commandName = CKEDITOR.tools.object.findKey( this.commands, commandInstance ),
1341 return command.fakeKeystroke; 1369 keystrokes = this.keystrokeHandler.keystrokes,
1342 } 1370 key;
1343 1371
1344 for ( key in keystrokes ) { 1372 // Some commands have a fake keystroke - for example CUT/COPY/PASTE commands are handled natively.
1345 if ( keystrokes.hasOwnProperty( key ) && keystrokes[ key ] == commandName ) { 1373 if ( commandInstance.fakeKeystroke ) {
1346 return key; 1374 return commandInstance.fakeKeystroke;
1347 } 1375 }
1348 }
1349 1376
1377 for ( key in keystrokes ) {
1378 if ( keystrokes.hasOwnProperty( key ) && keystrokes[ key ] == commandName ) {
1379 return key;
1380 }
1381 }
1382 }
1350 return null; 1383 return null;
1351 }, 1384 },
1352 1385
@@ -1539,7 +1572,7 @@ CKEDITOR.ELEMENT_MODE_INLINE = 3;
1539 * @member CKEDITOR.config 1572 * @member CKEDITOR.config
1540 */ 1573 */
1541 1574
1542 /** 1575/**
1543 * Customizes the {@link CKEDITOR.editor#title human-readable title} of this editor. This title is displayed in 1576 * Customizes the {@link CKEDITOR.editor#title human-readable title} of this editor. This title is displayed in
1544 * tooltips and impacts various [accessibility aspects](#!/guide/dev_a11y-section-announcing-the-editor-on-the-page), 1577 * tooltips and impacts various [accessibility aspects](#!/guide/dev_a11y-section-announcing-the-editor-on-the-page),
1545 * e.g. it is commonly used by screen readers for distinguishing editor instances and for navigation. 1578 * e.g. it is commonly used by screen readers for distinguishing editor instances and for navigation.
diff --git a/sources/core/env.js b/sources/core/env.js
index 43b608a..cbf089c 100644
--- a/sources/core/env.js
+++ b/sources/core/env.js
@@ -136,7 +136,7 @@ if ( !CKEDITOR.env ) {
136 var domain = document.domain, 136 var domain = document.domain,
137 hostname = window.location.hostname; 137 hostname = window.location.hostname;
138 138
139 return domain != hostname && domain != ( '[' + hostname + ']' ); // IPv6 IP support (#5434) 139 return domain != hostname && domain != ( '[' + hostname + ']' ); // IPv6 IP support (http://dev.ckeditor.com/ticket/5434)
140 }, 140 },
141 141
142 /** 142 /**
diff --git a/sources/core/filter.js b/sources/core/filter.js
index db68530..3e64fc5 100644
--- a/sources/core/filter.js
+++ b/sources/core/filter.js
@@ -158,7 +158,8 @@
158 }, 158 },
159 // Object: element name => array of transformations groups. 159 // Object: element name => array of transformations groups.
160 transformations: {}, 160 transformations: {},
161 cachedTests: {} 161 cachedTests: {},
162 cachedChecks: {}
162 }; 163 };
163 164
164 // Register filter instance. 165 // Register filter instance.
@@ -299,7 +300,7 @@
299 if ( el.attributes[ 'data-cke-filter' ] == 'off' ) 300 if ( el.attributes[ 'data-cke-filter' ] == 'off' )
300 return false; 301 return false;
301 302
302 // (#10260) Don't touch elements like spans with data-cke-* attribute since they're 303 // (http://dev.ckeditor.com/ticket/10260) Don't touch elements like spans with data-cke-* attribute since they're
303 // responsible e.g. for placing markers, bookmarks, odds and stuff. 304 // responsible e.g. for placing markers, bookmarks, odds and stuff.
304 // We love 'em and we don't wanna lose anything during the filtering. 305 // We love 'em and we don't wanna lose anything during the filtering.
305 // '|' is to avoid tricky joints like data-="foo" + cke-="bar". Yes, they're possible. 306 // '|' is to avoid tricky joints like data-="foo" + cke-="bar". Yes, they're possible.
@@ -346,7 +347,7 @@
346 if ( !element.parent ) 347 if ( !element.parent )
347 continue; 348 continue;
348 349
349 // Handle custom elements as inline elements (#12683). 350 // Handle custom elements as inline elements (http://dev.ckeditor.com/ticket/12683).
350 parentDtd = DTD[ element.parent.name ] || DTD.span; 351 parentDtd = DTD[ element.parent.name ] || DTD.span;
351 352
352 switch ( check.check ) { 353 switch ( check.check ) {
@@ -806,6 +807,32 @@
806 } )(), 807 } )(),
807 808
808 /** 809 /**
810 * Returns a clone of this filter instance.
811 *
812 * @since 4.7.3
813 * @returns {CKEDITOR.filter}
814 */
815 clone: function() {
816 var ret = new CKEDITOR.filter(),
817 clone = CKEDITOR.tools.clone;
818
819 // Cloning allowed content related things.
820 ret.allowedContent = clone( this.allowedContent );
821 ret._.allowedRules = clone( this._.allowedRules );
822
823 // Disallowed content rules.
824 ret.disallowedContent = clone( this.disallowedContent );
825 ret._.disallowedRules = clone( this._.disallowedRules );
826
827 ret._.transformations = clone( this._.transformations );
828
829 ret.disabled = this.disabled;
830 ret.editor = this.editor;
831
832 return ret;
833 },
834
835 /**
809 * Destroys the filter instance and removes it from the global {@link CKEDITOR.filter#instances} object. 836 * Destroys the filter instance and removes it from the global {@link CKEDITOR.filter#instances} object.
810 * 837 *
811 * @since 4.4.5 838 * @since 4.4.5
@@ -2201,7 +2228,7 @@
2201 var widths = element.styles.margin.match( /(\-?[\.\d]+\w+)/g ) || [ '0px' ]; 2228 var widths = element.styles.margin.match( /(\-?[\.\d]+\w+)/g ) || [ '0px' ];
2202 switch ( widths.length ) { 2229 switch ( widths.length ) {
2203 case 1: 2230 case 1:
2204 element.styles.margin = widths[0]; 2231 mapStyles( [ 0, 0, 0, 0 ] );
2205 break; 2232 break;
2206 case 2: 2233 case 2:
2207 mapStyles( [ 0, 1, 0, 1 ] ); 2234 mapStyles( [ 0, 1, 0, 1 ] );
@@ -2291,7 +2318,7 @@
2291 * * {@link CKEDITOR.filter.allowedContentRules} &ndash; defined rules will be added 2318 * * {@link CKEDITOR.filter.allowedContentRules} &ndash; defined rules will be added
2292 * to the {@link CKEDITOR.editor#filter}. 2319 * to the {@link CKEDITOR.editor#filter}.
2293 * * `true` &ndash; will disable the filter (data will not be filtered, 2320 * * `true` &ndash; will disable the filter (data will not be filtered,
2294 * all features will be activated). 2321 * all features will be activated). Reading [security best practices](#!/guide/dev_best_practices) before setting `true` is recommended.
2295 * * default &ndash; the filter will be configured by loaded features 2322 * * default &ndash; the filter will be configured by loaded features
2296 * (toolbar items, commands, etc.). 2323 * (toolbar items, commands, etc.).
2297 * 2324 *
diff --git a/sources/core/focusmanager.js b/sources/core/focusmanager.js
index 6fc9969..45c3137 100644
--- a/sources/core/focusmanager.js
+++ b/sources/core/focusmanager.js
@@ -147,34 +147,28 @@
147 * @member CKEDITOR.focusManager 147 * @member CKEDITOR.focusManager
148 */ 148 */
149 blur: function( noDelay ) { 149 blur: function( noDelay ) {
150 if ( this._.locked ) 150 if ( this._.locked ) {
151 return; 151 return;
152 }
152 153
153 function doBlur() { 154 function doBlur() {
154 var editor = this._.editor;
155
156 if ( this.hasFocus ) { 155 if ( this.hasFocus ) {
157 this.hasFocus = false; 156 this.hasFocus = false;
158 157
159 // Blink browsers leave selection in `[contenteditable=true]`
160 // when it's blurred and it's neccessary to remove it manually for inline editor. (#13446)
161 if ( CKEDITOR.env.chrome && editor.editable().isInline() ) {
162 editor.window.$.getSelection().removeAllRanges();
163 }
164
165 var ct = this._.editor.container; 158 var ct = this._.editor.container;
166 ct && ct.removeClass( 'cke_focus' ); 159 ct && ct.removeClass( 'cke_focus' );
167 this._.editor.fire( 'blur' ); 160 this._.editor.fire( 'blur' );
168 } 161 }
169 } 162 }
170 163
171 if ( this._.timer ) 164 if ( this._.timer ) {
172 clearTimeout( this._.timer ); 165 clearTimeout( this._.timer );
166 }
173 167
174 var delay = CKEDITOR.focusManager._.blurDelay; 168 var delay = CKEDITOR.focusManager._.blurDelay;
175 if ( noDelay || !delay ) 169 if ( noDelay || !delay ) {
176 doBlur.call( this ); 170 doBlur.call( this );
177 else { 171 } else {
178 this._.timer = CKEDITOR.tools.setTimeout( function() { 172 this._.timer = CKEDITOR.tools.setTimeout( function() {
179 delete this._.timer; 173 delete this._.timer;
180 doBlur.call( this ); 174 doBlur.call( this );
diff --git a/sources/core/htmldataprocessor.js b/sources/core/htmldataprocessor.js
index 56764be..79e996b 100644
--- a/sources/core/htmldataprocessor.js
+++ b/sources/core/htmldataprocessor.js
@@ -56,7 +56,7 @@
56 // it up and apply the filter. 56 // it up and apply the filter.
57 data = protectSource( data, editor ); 57 data = protectSource( data, editor );
58 58
59 // Protect content of textareas. (#9995) 59 // Protect content of textareas. (http://dev.ckeditor.com/ticket/9995)
60 // Do this before protecting attributes to avoid breaking: 60 // Do this before protecting attributes to avoid breaking:
61 // <textarea><img src="..." /></textarea> 61 // <textarea><img src="..." /></textarea>
62 data = protectElements( data, protectTextareaRegex ); 62 data = protectElements( data, protectTextareaRegex );
@@ -67,23 +67,23 @@
67 data = protectAttributes( data ); 67 data = protectAttributes( data );
68 68
69 // Protect elements than can't be set inside a DIV. E.g. IE removes 69 // Protect elements than can't be set inside a DIV. E.g. IE removes
70 // style tags from innerHTML. (#3710) 70 // style tags from innerHTML. (http://dev.ckeditor.com/ticket/3710)
71 data = protectElements( data, protectElementsRegex ); 71 data = protectElements( data, protectElementsRegex );
72 72
73 // Certain elements has problem to go through DOM operation, protect 73 // Certain elements has problem to go through DOM operation, protect
74 // them by prefixing 'cke' namespace. (#3591) 74 // them by prefixing 'cke' namespace. (http://dev.ckeditor.com/ticket/3591)
75 data = protectElementsNames( data ); 75 data = protectElementsNames( data );
76 76
77 // All none-IE browsers ignore self-closed custom elements, 77 // All none-IE browsers ignore self-closed custom elements,
78 // protecting them into open-close. (#3591) 78 // protecting them into open-close. (http://dev.ckeditor.com/ticket/3591)
79 data = protectSelfClosingElements( data ); 79 data = protectSelfClosingElements( data );
80 80
81 // Compensate one leading line break after <pre> open as browsers 81 // Compensate one leading line break after <pre> open as browsers
82 // eat it up. (#5789) 82 // eat it up. (http://dev.ckeditor.com/ticket/5789)
83 data = protectPreFormatted( data ); 83 data = protectPreFormatted( data );
84 84
85 // There are attributes which may execute JavaScript code inside fixBin. 85 // There are attributes which may execute JavaScript code inside fixBin.
86 // Encode them greedily. They will be unprotected right after getting HTML from fixBin. (#10) 86 // Encode them greedily. They will be unprotected right after getting HTML from fixBin. (http://dev.ckeditor.com/ticket/10)
87 data = protectInsecureAttributes( data ); 87 data = protectInsecureAttributes( data );
88 88
89 var fixBin = evtData.context || editor.editable().getName(), 89 var fixBin = evtData.context || editor.editable().getName(),
@@ -99,7 +99,7 @@
99 // Call the browser to help us fixing a possibly invalid HTML 99 // Call the browser to help us fixing a possibly invalid HTML
100 // structure. 100 // structure.
101 var el = editor.document.createElement( fixBin ); 101 var el = editor.document.createElement( fixBin );
102 // Add fake character to workaround IE comments bug. (#3801) 102 // Add fake character to workaround IE comments bug. (http://dev.ckeditor.com/ticket/3801)
103 el.setHtml( 'a' + data ); 103 el.setHtml( 'a' + data );
104 data = el.getHtml().substr( 1 ); 104 data = el.getHtml().substr( 1 );
105 105
@@ -128,7 +128,7 @@
128 data = CKEDITOR.htmlParser.fragment.fromHtml( data, evtData.context, fixBodyTag ); 128 data = CKEDITOR.htmlParser.fragment.fromHtml( data, evtData.context, fixBodyTag );
129 129
130 // The empty root element needs to be fixed by adding 'p' or 'div' into it. 130 // The empty root element needs to be fixed by adding 'p' or 'div' into it.
131 // This avoids the need to create that element on the first focus (#12630). 131 // This avoids the need to create that element on the first focus (http://dev.ckeditor.com/ticket/12630).
132 if ( fixBodyTag ) { 132 if ( fixBodyTag ) {
133 fixEmptyRoot( data, fixBodyTag ); 133 fixEmptyRoot( data, fixBodyTag );
134 } 134 }
@@ -163,7 +163,7 @@
163 editor.on( 'toDataFormat', function( evt ) { 163 editor.on( 'toDataFormat', function( evt ) {
164 var data = evt.data.dataValue; 164 var data = evt.data.dataValue;
165 165
166 // #10854 - we need to strip leading blockless <br> which FF adds 166 // http://dev.ckeditor.com/ticket/10854 - we need to strip leading blockless <br> which FF adds
167 // automatically when editable contains only non-editable content. 167 // automatically when editable contains only non-editable content.
168 // We do that for every browser (so it's a constant behavior) and 168 // We do that for every browser (so it's a constant behavior) and
169 // not in BR mode, in which chance of valid leading blockless <br> is higher. 169 // not in BR mode, in which chance of valid leading blockless <br> is higher.
@@ -192,7 +192,7 @@
192 data.writeChildrenHtml( writer ); 192 data.writeChildrenHtml( writer );
193 data = writer.getHtml( true ); 193 data = writer.getHtml( true );
194 194
195 // Restore those non-HTML protected source. (#4475,#4880) 195 // Restore those non-HTML protected source. (http://dev.ckeditor.com/ticket/4475,http://dev.ckeditor.com/ticket/4880)
196 data = unprotectRealComments( data ); 196 data = unprotectRealComments( data );
197 data = unprotectSource( data, editor ); 197 data = unprotectSource( data, editor );
198 198
@@ -448,7 +448,7 @@
448 return false; 448 return false;
449 449
450 // 1. For IE version >=8, empty blocks are displayed correctly themself in wysiwiyg; 450 // 1. For IE version >=8, empty blocks are displayed correctly themself in wysiwiyg;
451 // 2. For the rest, at least table cell and list item need no filler space. (#6248) 451 // 2. For the rest, at least table cell and list item need no filler space. (http://dev.ckeditor.com/ticket/6248)
452 if ( !isOutput && !CKEDITOR.env.needsBrFiller && 452 if ( !isOutput && !CKEDITOR.env.needsBrFiller &&
453 ( document.documentMode > 7 || 453 ( document.documentMode > 7 ||
454 block.name in CKEDITOR.dtd.tr || 454 block.name in CKEDITOR.dtd.tr ||
@@ -484,7 +484,7 @@
484 } 484 }
485 485
486 // Regex to scan for &nbsp; at the end of blocks, which are actually placeholders. 486 // Regex to scan for &nbsp; at the end of blocks, which are actually placeholders.
487 // Safari transforms the &nbsp; to \xa0. (#4172) 487 // Safari transforms the &nbsp; to \xa0. (http://dev.ckeditor.com/ticket/4172)
488 var tailNbspRegex = /(?:&nbsp;|\xa0)$/; 488 var tailNbspRegex = /(?:&nbsp;|\xa0)$/;
489 489
490 var protectedSourceMarker = '{cke_protected}'; 490 var protectedSourceMarker = '{cke_protected}';
@@ -563,18 +563,35 @@
563 // active in the editing area (IE|WebKit). 563 // active in the editing area (IE|WebKit).
564 [ ( /^on/ ), 'data-cke-pa-on' ], 564 [ ( /^on/ ), 'data-cke-pa-on' ],
565 565
566 // Prevent iframe's srcdoc attribute from being evaluated in the editable.
567 [ ( /^srcdoc/ ), 'data-cke-pa-srcdoc' ],
568
566 // Don't let some old expando enter editor. Concerns only IE8, 569 // Don't let some old expando enter editor. Concerns only IE8,
567 // but for consistency remove on all browsers. 570 // but for consistency remove on all browsers.
568 [ ( /^data-cke-expando$/ ), '' ] 571 [ ( /^data-cke-expando$/ ), '' ]
569 ] 572 ],
573
574 elements: {
575 // Prevent iframe's src attribute with javascript code or data protocol from being evaluated in the editable.
576 iframe: function( element ) {
577 if ( element.attributes && element.attributes.src ) {
578
579 var src = element.attributes.src.toLowerCase().replace( /[^a-z]/gi, '' );
580 if ( src.indexOf( 'javascript' ) === 0 || src.indexOf( 'data' ) === 0 ) {
581 element.attributes[ 'data-cke-pa-src' ] = element.attributes.src;
582 delete element.attributes.src;
583 }
584 }
585 }
586 }
570 }; 587 };
571 588
572 // Disable form elements editing mode provided by some browsers. (#5746) 589 // Disable form elements editing mode provided by some browsers. (http://dev.ckeditor.com/ticket/5746)
573 function protectReadOnly( element ) { 590 function protectReadOnly( element ) {
574 var attrs = element.attributes; 591 var attrs = element.attributes;
575 592
576 // We should flag that the element was locked by our code so 593 // We should flag that the element was locked by our code so
577 // it'll be editable by the editor functions (#6046). 594 // it'll be editable by the editor functions (http://dev.ckeditor.com/ticket/6046).
578 if ( attrs.contenteditable != 'false' ) 595 if ( attrs.contenteditable != 'false' )
579 attrs[ 'data-cke-editable' ] = attrs.contenteditable ? 'true' : 1; 596 attrs[ 'data-cke-editable' ] = attrs.contenteditable ? 'true' : 1;
580 597
@@ -602,7 +619,7 @@
602 } 619 }
603 }, 620 },
604 621
605 // Remove empty link but not empty anchor. (#3829, #13516) 622 // Remove empty link but not empty anchor. (http://dev.ckeditor.com/ticket/3829, http://dev.ckeditor.com/ticket/13516)
606 a: function( element ) { 623 a: function( element ) {
607 var attrs = element.attributes; 624 var attrs = element.attributes;
608 625
@@ -641,7 +658,7 @@
641 if ( attribs[ 'data-cke-temp' ] ) 658 if ( attribs[ 'data-cke-temp' ] )
642 return false; 659 return false;
643 660
644 // Remove duplicated attributes - #3789. 661 // Remove duplicated attributes - http://dev.ckeditor.com/ticket/3789.
645 var attributeNames = [ 'name', 'href', 'src' ], 662 var attributeNames = [ 'name', 'href', 'src' ],
646 savedAttributeName; 663 savedAttributeName;
647 for ( var i = 0; i < attributeNames.length; i++ ) { 664 for ( var i = 0; i < attributeNames.length; i++ ) {
@@ -653,7 +670,7 @@
653 return element; 670 return element;
654 }, 671 },
655 672
656 // The contents of table should be in correct order (#4809). 673 // The contents of table should be in correct order (http://dev.ckeditor.com/ticket/4809).
657 table: function( element ) { 674 table: function( element ) {
658 // Clone the array as it would become empty during the sort call. 675 // Clone the array as it would become empty during the sort call.
659 var children = element.children.slice( 0 ); 676 var children = element.children.slice( 0 );
@@ -712,7 +729,7 @@
712 title: function( element ) { 729 title: function( element ) {
713 var titleText = element.children[ 0 ]; 730 var titleText = element.children[ 0 ];
714 731
715 // Append text-node to title tag if not present (i.e. non-IEs) (#9882). 732 // Append text-node to title tag if not present (i.e. non-IEs) (http://dev.ckeditor.com/ticket/9882).
716 !titleText && append( element, titleText = new CKEDITOR.htmlParser.text() ); 733 !titleText && append( element, titleText = new CKEDITOR.htmlParser.text() );
717 734
718 // Transfer data-saved title to title tag. 735 // Transfer data-saved title to title tag.
@@ -733,7 +750,7 @@
733 750
734 if ( CKEDITOR.env.ie ) { 751 if ( CKEDITOR.env.ie ) {
735 // IE outputs style attribute in capital letters. We should convert 752 // IE outputs style attribute in capital letters. We should convert
736 // them back to lower case, while not hurting the values (#5930) 753 // them back to lower case, while not hurting the values (http://dev.ckeditor.com/ticket/5930)
737 defaultHtmlFilterRulesForAll.attributes.style = function( value ) { 754 defaultHtmlFilterRulesForAll.attributes.style = function( value ) {
738 return value.replace( /(^|;)([^\:]+)/g, function( match ) { 755 return value.replace( /(^|;)([^\:]+)/g, function( match ) {
739 return match.toLowerCase(); 756 return match.toLowerCase();
@@ -741,7 +758,7 @@
741 }; 758 };
742 } 759 }
743 760
744 // Disable form elements editing mode provided by some browsers. (#5746) 761 // Disable form elements editing mode provided by some browsers. (http://dev.ckeditor.com/ticket/5746)
745 function unprotectReadyOnly( element ) { 762 function unprotectReadyOnly( element ) {
746 var attrs = element.attributes; 763 var attrs = element.attributes;
747 switch ( attrs[ 'data-cke-editable' ] ) { 764 switch ( attrs[ 'data-cke-editable' ] ) {
@@ -773,7 +790,7 @@
773 // 790 //
774 // 'data-x' => '&lt;a href=&quot;X&quot;' 791 // 'data-x' => '&lt;a href=&quot;X&quot;'
775 // 792 //
776 // which, can be easily filtered out (#11508). 793 // which, can be easily filtered out (http://dev.ckeditor.com/ticket/11508).
777 protectAttributeRegex = /([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi, 794 protectAttributeRegex = /([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,
778 protectAttributeNameRegex = /^(href|src|name)$/i; 795 protectAttributeNameRegex = /^(href|src|name)$/i;
779 796
@@ -790,8 +807,8 @@
790 function protectAttributes( html ) { 807 function protectAttributes( html ) {
791 return html.replace( protectElementRegex, function( element, tag, attributes ) { 808 return html.replace( protectElementRegex, function( element, tag, attributes ) {
792 return '<' + tag + attributes.replace( protectAttributeRegex, function( fullAttr, attrName ) { 809 return '<' + tag + attributes.replace( protectAttributeRegex, function( fullAttr, attrName ) {
793 // Avoid corrupting the inline event attributes (#7243). 810 // Avoid corrupting the inline event attributes (http://dev.ckeditor.com/ticket/7243).
794 // We should not rewrite the existed protected attributes, e.g. clipboard content from editor. (#5218) 811 // We should not rewrite the existed protected attributes, e.g. clipboard content from editor. (http://dev.ckeditor.com/ticket/5218)
795 if ( protectAttributeNameRegex.test( attrName ) && attributes.indexOf( 'data-cke-saved-' + attrName ) == -1 ) 812 if ( protectAttributeNameRegex.test( attrName ) && attributes.indexOf( 'data-cke-saved-' + attrName ) == -1 )
796 return ' data-cke-saved-' + fullAttr + ' data-cke-' + CKEDITOR.rnd + '-' + fullAttr; 813 return ' data-cke-saved-' + fullAttr + ' data-cke-' + CKEDITOR.rnd + '-' + fullAttr;
797 814
@@ -880,7 +897,7 @@
880 // <noscript> tags (get lost in IE and messed up in FF). 897 // <noscript> tags (get lost in IE and messed up in FF).
881 /<noscript[\s\S]*?<\/noscript>/gi, 898 /<noscript[\s\S]*?<\/noscript>/gi,
882 899
883 // Avoid meta tags being stripped (#8117). 900 // Avoid meta tags being stripped (http://dev.ckeditor.com/ticket/8117).
884 /<meta[\s\S]*?\/?>/gi 901 /<meta[\s\S]*?\/?>/gi
885 ].concat( protectRegexes ); 902 ].concat( protectRegexes );
886 903
@@ -894,7 +911,7 @@
894 911
895 for ( var i = 0; i < regexes.length; i++ ) { 912 for ( var i = 0; i < regexes.length; i++ ) {
896 data = data.replace( regexes[ i ], function( match ) { 913 data = data.replace( regexes[ i ], function( match ) {
897 match = match.replace( tempRegex, // There could be protected source inside another one. (#3869). 914 match = match.replace( tempRegex, // There could be protected source inside another one. (http://dev.ckeditor.com/ticket/3869).
898 function( $, isComment, id ) { 915 function( $, isComment, id ) {
899 return protectedHtml[ id ]; 916 return protectedHtml[ id ];
900 } ); 917 } );
@@ -912,7 +929,7 @@
912 929
913 // Different protection pattern is used for those that 930 // Different protection pattern is used for those that
914 // live in attributes to avoid from being HTML encoded. 931 // live in attributes to avoid from being HTML encoded.
915 // Why so serious? See #9205, #8216, #7805, #11754, #11846. 932 // Why so serious? See http://dev.ckeditor.com/ticket/9205, http://dev.ckeditor.com/ticket/8216, http://dev.ckeditor.com/ticket/7805, http://dev.ckeditor.com/ticket/11754, http://dev.ckeditor.com/ticket/11846.
916 data = data.replace( /<\w+(?:\s+(?:(?:[^\s=>]+\s*=\s*(?:[^'"\s>]+|'[^']*'|"[^"]*"))|[^\s=\/>]+))+\s*\/?>/g, function( match ) { 933 data = data.replace( /<\w+(?:\s+(?:(?:[^\s=>]+\s*=\s*(?:[^'"\s>]+|'[^']*'|"[^"]*"))|[^\s=\/>]+))+\s*\/?>/g, function( match ) {
917 return match.replace( /<!--\{cke_protected\}([^>]*)-->/g, function( match, data ) { 934 return match.replace( /<!--\{cke_protected\}([^>]*)-->/g, function( match, data ) {
918 store[ store.id ] = decodeURIComponent( data ); 935 store[ store.id ] = decodeURIComponent( data );
@@ -922,7 +939,7 @@
922 939
923 // This RegExp searches for innerText in all the title/iframe/textarea elements. 940 // This RegExp searches for innerText in all the title/iframe/textarea elements.
924 // This is because browser doesn't allow HTML in these elements, that's why we can't 941 // This is because browser doesn't allow HTML in these elements, that's why we can't
925 // nest comments in there. (#11223) 942 // nest comments in there. (http://dev.ckeditor.com/ticket/11223)
926 data = data.replace( /<(title|iframe|textarea)([^>]*)>([\s\S]*?)<\/\1>/g, function( match, tagName, tagAttributes, innerText ) { 943 data = data.replace( /<(title|iframe|textarea)([^>]*)>([\s\S]*?)<\/\1>/g, function( match, tagName, tagAttributes, innerText ) {
927 return '<' + tagName + tagAttributes + '>' + unprotectSource( unprotectRealComments( innerText ), editor ) + '</' + tagName + '>'; 944 return '<' + tagName + tagAttributes + '>' + unprotectSource( unprotectRealComments( innerText ), editor ) + '</' + tagName + '>';
928 } ); 945 } );
@@ -971,7 +988,7 @@
971 * {@link CKEDITOR.htmlParser.fragment} {@link CKEDITOR.htmlParser.element}. 988 * {@link CKEDITOR.htmlParser.fragment} {@link CKEDITOR.htmlParser.element}.
972 * * 5-9: Data is available in the parsed format, but {@link CKEDITOR.htmlDataProcessor#dataFilter} 989 * * 5-9: Data is available in the parsed format, but {@link CKEDITOR.htmlDataProcessor#dataFilter}
973 * is not applied yet. 990 * is not applied yet.
974 * * 6: Data is filtered with the {CKEDITOR.filter content filter}. 991 * * 6: Data is filtered with the {@link CKEDITOR.filter content filter}.
975 * * 10: Data is processed with {@link CKEDITOR.htmlDataProcessor#dataFilter}. 992 * * 10: Data is processed with {@link CKEDITOR.htmlDataProcessor#dataFilter}.
976 * * 10-14: Data is available in the parsed format and {@link CKEDITOR.htmlDataProcessor#dataFilter} 993 * * 10-14: Data is available in the parsed format and {@link CKEDITOR.htmlDataProcessor#dataFilter}
977 * has already been applied. 994 * has already been applied.
diff --git a/sources/core/htmlparser.js b/sources/core/htmlparser.js
index 8c30992..c95257c 100644
--- a/sources/core/htmlparser.js
+++ b/sources/core/htmlparser.js
@@ -163,7 +163,7 @@ CKEDITOR.htmlParser = function() {
163 tagName = tagName.toLowerCase(); 163 tagName = tagName.toLowerCase();
164 164
165 // There are some tag names that can break things, so let's 165 // There are some tag names that can break things, so let's
166 // simply ignore them when parsing. (#5224) 166 // simply ignore them when parsing. (http://dev.ckeditor.com/ticket/5224)
167 if ( /="/.test( tagName ) ) 167 if ( /="/.test( tagName ) )
168 continue; 168 continue;
169 169
diff --git a/sources/core/htmlparser/basicwriter.js b/sources/core/htmlparser/basicwriter.js
index 529fbf1..61447f0 100644
--- a/sources/core/htmlparser/basicwriter.js
+++ b/sources/core/htmlparser/basicwriter.js
@@ -67,7 +67,7 @@ CKEDITOR.htmlParser.basicWriter = CKEDITOR.tools.createClass( {
67 * @param {String} attValue The attribute value. 67 * @param {String} attValue The attribute value.
68 */ 68 */
69 attribute: function( attName, attValue ) { 69 attribute: function( attName, attValue ) {
70 // Browsers don't always escape special character in attribute values. (#4683, #4719). 70 // Browsers don't always escape special character in attribute values. (http://dev.ckeditor.com/ticket/4683, http://dev.ckeditor.com/ticket/4719).
71 if ( typeof attValue == 'string' ) 71 if ( typeof attValue == 'string' )
72 attValue = CKEDITOR.tools.htmlEncodeAttr( attValue ); 72 attValue = CKEDITOR.tools.htmlEncodeAttr( attValue );
73 73
diff --git a/sources/core/htmlparser/element.js b/sources/core/htmlparser/element.js
index 0ed750e..224d3e6 100644
--- a/sources/core/htmlparser/element.js
+++ b/sources/core/htmlparser/element.js
@@ -35,7 +35,7 @@ CKEDITOR.htmlParser.element = function( name, attributes ) {
35 */ 35 */
36 this.children = []; 36 this.children = [];
37 37
38 // Reveal the real semantic of our internal custom tag name (#6639), 38 // Reveal the real semantic of our internal custom tag name (http://dev.ckeditor.com/ticket/6639),
39 // when resolving whether it's block like. 39 // when resolving whether it's block like.
40 var realName = name || '', 40 var realName = name || '',
41 prefixed = realName.match( /^cke:(.*)/ ); 41 prefixed = realName.match( /^cke:(.*)/ );
@@ -543,8 +543,8 @@ CKEDITOR.htmlParser.cssStyle = function() {
543 543
544 if ( !ctx.nonEditable && this.attributes.contenteditable == 'false' ) 544 if ( !ctx.nonEditable && this.attributes.contenteditable == 'false' )
545 changes.push( 'nonEditable', true ); 545 changes.push( 'nonEditable', true );
546 // A context to be given nestedEditable must be nonEditable first (by inheritance) (#11372, #11698). 546 // A context to be given nestedEditable must be nonEditable first (by inheritance) (http://dev.ckeditor.com/ticket/11372, http://dev.ckeditor.com/ticket/11698).
547 // Special case: #11504 - filter starts on <body contenteditable=true>, 547 // Special case: http://dev.ckeditor.com/ticket/11504 - filter starts on <body contenteditable=true>,
548 // so ctx.nonEditable has not been yet set to true. 548 // so ctx.nonEditable has not been yet set to true.
549 else if ( ctx.nonEditable && !ctx.nestedEditable && this.attributes.contenteditable == 'true' ) 549 else if ( ctx.nonEditable && !ctx.nestedEditable && this.attributes.contenteditable == 'true' )
550 changes.push( 'nestedEditable', true ); 550 changes.push( 'nestedEditable', true );
diff --git a/sources/core/htmlparser/fragment.js b/sources/core/htmlparser/fragment.js
index f696a12..7ef915c 100644
--- a/sources/core/htmlparser/fragment.js
+++ b/sources/core/htmlparser/fragment.js
@@ -61,7 +61,7 @@ CKEDITOR.htmlParser.fragment = function() {
61 if ( node.attributes[ 'data-cke-survive' ] ) 61 if ( node.attributes[ 'data-cke-survive' ] )
62 return false; 62 return false;
63 63
64 // Empty link is to be removed when empty but not anchor. (#7894) 64 // Empty link is to be removed when empty but not anchor. (http://dev.ckeditor.com/ticket/7894)
65 return node.name == 'a' && node.attributes.href || CKEDITOR.dtd.$removeEmpty[ node.name ]; 65 return node.name == 'a' && node.attributes.href || CKEDITOR.dtd.$removeEmpty[ node.name ];
66 } 66 }
67 67
@@ -130,7 +130,7 @@ CKEDITOR.htmlParser.fragment = function() {
130 i--; 130 i--;
131 } else { 131 } else {
132 // Some element of the same type cannot be nested, flat them, 132 // Some element of the same type cannot be nested, flat them,
133 // e.g. <a href="#">foo<a href="#">bar</a></a>. (#7894) 133 // e.g. <a href="#">foo<a href="#">bar</a></a>. (http://dev.ckeditor.com/ticket/7894)
134 if ( pendingName == currentNode.name ) 134 if ( pendingName == currentNode.name )
135 addElement( currentNode, currentNode.parent, 1 ), i--; 135 addElement( currentNode, currentNode.parent, 1 ), i--;
136 } 136 }
@@ -143,7 +143,7 @@ CKEDITOR.htmlParser.fragment = function() {
143 addElement( pendingBRs.shift(), currentNode ); 143 addElement( pendingBRs.shift(), currentNode );
144 } 144 }
145 145
146 // Rtrim empty spaces on block end boundary. (#3585) 146 // Rtrim empty spaces on block end boundary. (http://dev.ckeditor.com/ticket/3585)
147 function removeTailWhitespace( element ) { 147 function removeTailWhitespace( element ) {
148 if ( element._.isBlockLike && element.name != 'pre' && element.name != 'textarea' ) { 148 if ( element._.isBlockLike && element.name != 'pre' && element.name != 'textarea' ) {
149 149
@@ -275,10 +275,10 @@ CKEDITOR.htmlParser.fragment = function() {
275 // If the element cannot be child of the current element. 275 // If the element cannot be child of the current element.
276 if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] ) { 276 if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] ) {
277 // Current node doesn't have a close tag, time for a close 277 // Current node doesn't have a close tag, time for a close
278 // as this element isn't fit in. (#7497) 278 // as this element isn't fit in. (http://dev.ckeditor.com/ticket/7497)
279 if ( currentNode.isOptionalClose ) 279 if ( currentNode.isOptionalClose )
280 parser.onTagClose( currentName ); 280 parser.onTagClose( currentName );
281 // Fixing malformed nested lists by moving it into a previous list item. (#3828) 281 // Fixing malformed nested lists by moving it into a previous list item. (http://dev.ckeditor.com/ticket/3828)
282 else if ( tagName in listBlocks && currentName in listBlocks ) { 282 else if ( tagName in listBlocks && currentName in listBlocks ) {
283 var children = currentNode.children, 283 var children = currentNode.children,
284 lastChild = children[ children.length - 1 ]; 284 lastChild = children[ children.length - 1 ];
@@ -291,7 +291,7 @@ CKEDITOR.htmlParser.fragment = function() {
291 currentNode = lastChild; 291 currentNode = lastChild;
292 } 292 }
293 // Establish new list root for orphan list items, but NOT to create 293 // Establish new list root for orphan list items, but NOT to create
294 // new list for the following ones, fix them instead. (#6975) 294 // new list for the following ones, fix them instead. (http://dev.ckeditor.com/ticket/6975)
295 // <dl><dt>foo<dd>bar</dl> 295 // <dl><dt>foo<dd>bar</dl>
296 // <ul><li>foo<li>bar</ul> 296 // <ul><li>foo<li>bar</ul>
297 else if ( tagName in CKEDITOR.dtd.$listItem && 297 else if ( tagName in CKEDITOR.dtd.$listItem &&
@@ -409,7 +409,7 @@ CKEDITOR.htmlParser.fragment = function() {
409 var currentName = currentNode.name, 409 var currentName = currentNode.name,
410 currentDtd = currentName ? ( CKEDITOR.dtd[ currentName ] || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) ) : rootDtd; 410 currentDtd = currentName ? ( CKEDITOR.dtd[ currentName ] || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) ) : rootDtd;
411 411
412 // Fix orphan text in list/table. (#8540) (#8870) 412 // Fix orphan text in list/table. (http://dev.ckeditor.com/ticket/8540) (http://dev.ckeditor.com/ticket/8870)
413 if ( !inTextarea && !currentDtd[ '#' ] && currentName in nonBreakingBlocks ) { 413 if ( !inTextarea && !currentDtd[ '#' ] && currentName in nonBreakingBlocks ) {
414 parser.onTagOpen( structureFixes[ currentName ] || '' ); 414 parser.onTagOpen( structureFixes[ currentName ] || '' );
415 parser.onText( text ); 415 parser.onText( text );
diff --git a/sources/core/lang.js b/sources/core/lang.js
index 8766055..06f3a2a 100644
--- a/sources/core/lang.js
+++ b/sources/core/lang.js
@@ -18,7 +18,7 @@
18 */ 18 */
19 languages: { 19 languages: {
20 af: 1, ar: 1, az: 1, bg: 1, bn: 1, bs: 1, ca: 1, cs: 1, cy: 1, da: 1, de: 1, 'de-ch': 1, el: 1, 20 af: 1, ar: 1, az: 1, bg: 1, bn: 1, bs: 1, ca: 1, cs: 1, cy: 1, da: 1, de: 1, 'de-ch': 1, el: 1,
21 'en-au': 1, 'en-ca': 1, 'en-gb': 1, en: 1, eo: 1, es: 1, et: 1, eu: 1, fa: 1, fi: 1, fo: 1, 21 'en-au': 1, 'en-ca': 1, 'en-gb': 1, en: 1, eo: 1, es: 1, 'es-mx':1, et: 1, eu: 1, fa: 1, fi: 1, fo: 1,
22 'fr-ca': 1, fr: 1, gl: 1, gu: 1, he: 1, hi: 1, hr: 1, hu: 1, id: 1, is: 1, it: 1, ja: 1, ka: 1, 22 'fr-ca': 1, fr: 1, gl: 1, gu: 1, he: 1, hi: 1, hr: 1, hu: 1, id: 1, is: 1, it: 1, ja: 1, ka: 1,
23 km: 1, ko: 1, ku: 1, lt: 1, lv: 1, mk: 1, mn: 1, ms: 1, nb: 1, nl: 1, no: 1, oc: 1, pl: 1, 'pt-br': 1, 23 km: 1, ko: 1, ku: 1, lt: 1, lv: 1, mk: 1, mn: 1, ms: 1, nb: 1, nl: 1, no: 1, oc: 1, pl: 1, 'pt-br': 1,
24 pt: 1, ro: 1, ru: 1, si: 1, sk: 1, sl: 1, sq: 1, 'sr-latn': 1, sr: 1, sv: 1, th: 1, tr: 1, tt: 1, ug: 1, 24 pt: 1, ro: 1, ru: 1, si: 1, sk: 1, sl: 1, sq: 1, 'sr-latn': 1, sr: 1, sv: 1, th: 1, tr: 1, tt: 1, ug: 1,
diff --git a/sources/core/loader.js b/sources/core/loader.js
index 249a8cf..dc02511 100644
--- a/sources/core/loader.js
+++ b/sources/core/loader.js
@@ -142,7 +142,7 @@ if ( !CKEDITOR.loader ) {
142 } 142 }
143 143
144 // We must guarantee the execution order of the scripts, so we 144 // We must guarantee the execution order of the scripts, so we
145 // need to load them one by one. (#4145) 145 // need to load them one by one. (http://dev.ckeditor.com/ticket/4145)
146 // The following if/else block has been taken from the scriptloader core code. 146 // The following if/else block has been taken from the scriptloader core code.
147 if ( typeof script.onreadystatechange !== 'undefined' ) { 147 if ( typeof script.onreadystatechange !== 'undefined' ) {
148 /** @ignore */ 148 /** @ignore */
@@ -156,7 +156,7 @@ if ( !CKEDITOR.loader ) {
156 /** @ignore */ 156 /** @ignore */
157 script.onload = function() { 157 script.onload = function() {
158 // Some browsers, such as Safari, may call the onLoad function 158 // Some browsers, such as Safari, may call the onLoad function
159 // immediately. Which will break the loading sequence. (#3661) 159 // immediately. Which will break the loading sequence. (http://dev.ckeditor.com/ticket/3661)
160 setTimeout( function() { 160 setTimeout( function() {
161 onScriptLoaded( scriptName ); 161 onScriptLoaded( scriptName );
162 }, 0 ); 162 }, 0 );
diff --git a/sources/core/scriptloader.js b/sources/core/scriptloader.js
index a2b9cca..356996f 100644
--- a/sources/core/scriptloader.js
+++ b/sources/core/scriptloader.js
@@ -119,7 +119,7 @@ CKEDITOR.scriptLoader = ( function() {
119 } ); 119 } );
120 120
121 if ( callback ) { 121 if ( callback ) {
122 // The onload or onerror event does not fire in IE8 and IE9 Quirks Mode (#14849). 122 // The onload or onerror event does not fire in IE8 and IE9 Quirks Mode (http://dev.ckeditor.com/ticket/14849).
123 if ( CKEDITOR.env.ie && ( CKEDITOR.env.version <= 8 || CKEDITOR.env.ie9Compat ) ) { 123 if ( CKEDITOR.env.ie && ( CKEDITOR.env.version <= 8 || CKEDITOR.env.ie9Compat ) ) {
124 script.$.onreadystatechange = function() { 124 script.$.onreadystatechange = function() {
125 if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' ) { 125 if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' ) {
@@ -130,7 +130,7 @@ CKEDITOR.scriptLoader = ( function() {
130 } else { 130 } else {
131 script.$.onload = function() { 131 script.$.onload = function() {
132 // Some browsers, such as Safari, may call the onLoad function 132 // Some browsers, such as Safari, may call the onLoad function
133 // immediately. Which will break the loading sequence. (#3661) 133 // immediately. Which will break the loading sequence. (http://dev.ckeditor.com/ticket/3661)
134 setTimeout( function() { 134 setTimeout( function() {
135 onLoad( url, true ); 135 onLoad( url, true );
136 }, 0 ); 136 }, 0 );
diff --git a/sources/core/selection.js b/sources/core/selection.js
index eef28a3..d44db3b 100644
--- a/sources/core/selection.js
+++ b/sources/core/selection.js
@@ -6,9 +6,211 @@
6( function() { 6( function() {
7 var isMSSelection = typeof window.getSelection != 'function', 7 var isMSSelection = typeof window.getSelection != 'function',
8 nextRev = 1, 8 nextRev = 1,
9 // #13816 9 // http://dev.ckeditor.com/ticket/13816
10 fillingCharSequence = CKEDITOR.tools.repeat( '\u200b', 7 ), 10 fillingCharSequence = CKEDITOR.tools.repeat( '\u200b', 7 ),
11 fillingCharSequenceRegExp = new RegExp( fillingCharSequence + '( )?', 'g' ); 11 fillingCharSequenceRegExp = new RegExp( fillingCharSequence + '( )?', 'g' ),
12 isSelectingTable;
13
14 // #### table selection : START
15 // @param {CKEDITOR.dom.range[]} ranges
16 // @param {Boolean} allowPartially Whether a collapsed selection within table is recognized to be a valid selection.
17 // This happens for WebKits on MacOS, when you right click inside the table.
18 function isTableSelection( ranges, allowPartially ) {
19 if ( ranges.length === 0 ) {
20 return false;
21 }
22
23 var node,
24 i;
25
26 function isPartiallySelected( range ) {
27 var startCell = range.startContainer.getAscendant( { td: 1, th: 1 }, true ),
28 endCell = range.endContainer.getAscendant( { td: 1, th: 1 }, true ),
29 trim = CKEDITOR.tools.trim,
30 selected;
31
32 // Check if the selection is inside one cell and we don't have any nested table contents selected.
33 if ( !startCell || !startCell.equals( endCell ) || startCell.findOne( 'td, th, tr, tbody, table' ) ) {
34 return false;
35 }
36
37 selected = range.cloneContents();
38
39 // Empty selection is still partially selected.
40 if ( !selected.getFirst() ) {
41 return true;
42 }
43
44 return trim( selected.getFirst().getText() ) !== trim( startCell.getText() );
45 }
46
47 // Edge case: partially selected text node inside one table cell or cursor inside cell.
48 if ( !allowPartially && ranges.length === 1 &&
49 ( ranges[ 0 ].collapsed || isPartiallySelected( ranges[ 0 ] ) ) ) {
50 return false;
51 }
52
53 for ( i = 0; i < ranges.length; i++ ) {
54 node = ranges[ i ]._getTableElement();
55
56 if ( !node ) {
57 return false;
58 }
59 }
60
61 return true;
62 }
63
64 // After performing fake table selection, the real selection is limited
65 // to the first selected cell. Therefore to check if the real selection
66 // matches the fake selection, we check if the table cell from fake selection's
67 // first range and real selection's range are the same.
68 // Also if the selection is collapsed, we should check if it's placed inside the table
69 // in which the fake selection is or inside nested table. Such selection occurs after right mouse click.
70 function isRealTableSelection( selection, fakeSelection ) {
71 var ranges = selection.getRanges(),
72 fakeRanges = fakeSelection.getRanges(),
73 table = ranges.length && ranges[ 0 ]._getTableElement() &&
74 ranges[ 0 ]._getTableElement().getAscendant( 'table', true ),
75 fakeTable = fakeRanges.length && fakeRanges[ 0 ]._getTableElement() &&
76 fakeRanges[ 0 ]._getTableElement().getAscendant( 'table', true ),
77 isTableRange = ranges.length === 1 && ranges[ 0 ]._getTableElement() &&
78 ranges[ 0 ]._getTableElement().is( 'table' ),
79 isFakeTableRange = fakeRanges.length === 1 && fakeRanges[ 0 ]._getTableElement() &&
80 fakeRanges[ 0 ]._getTableElement().is( 'table' );
81
82 function isValidTableSelection( table, fakeTable, ranges, fakeRanges ) {
83 var isMenuOpen = ranges.length === 1 && ranges[ 0 ].collapsed,
84 // In case of WebKit on MacOS, when checking real selection, we must allow selection to be partial.
85 // Otherwise the check will fail for table selection with opened context menu.
86 isInTable = isTableSelection( ranges, !!CKEDITOR.env.webkit ) && isTableSelection( fakeRanges );
87
88 return isSameTable( table, fakeTable ) && ( isMenuOpen || isInTable );
89 }
90
91 function isSameTable( table, fakeTable ) {
92 if ( !table || !fakeTable ) {
93 return false;
94 }
95
96 return table.equals( fakeTable ) || fakeTable.contains( table );
97 }
98
99 if ( isValidTableSelection( table, fakeTable, ranges, fakeRanges ) ) {
100 // Edge case: when editor contains only table and that table is selected using selectAll command,
101 // then the selection is not properly refreshed and it must be done manually.
102 if ( isTableRange && !isFakeTableRange ) {
103 fakeSelection.selectRanges( ranges );
104 }
105 return true;
106 }
107
108 return false;
109 }
110
111 function getSelectedCells( ranges ) {
112 var cells = [],
113 node,
114 i;
115
116 function getCellsFromElement( element ) {
117 var cells = element.find( 'td, th' ),
118 cellsArray = [],
119 i;
120
121 for ( i = 0; i < cells.count(); i++ ) {
122 cellsArray.push( cells.getItem( i ) );
123 }
124
125 return cellsArray;
126 }
127
128 for ( i = 0; i < ranges.length; i++ ) {
129 node = ranges[ i ]._getTableElement();
130
131 if ( node.is && node.is( { td: 1, th: 1 } ) ) {
132 cells.push( node );
133 } else {
134 cells = cells.concat( getCellsFromElement( node ) );
135 }
136 }
137
138 return cells;
139 }
140
141 // Cells in the same row are separated by tab and the rows are separated by new line, e.g.
142 // Cell 1.1 Cell 1.2
143 // Cell 2.1 Cell 2.2
144 function getTextFromSelectedCells( ranges ) {
145 var cells = getSelectedCells( ranges ),
146 txt = '',
147 currentRow = [],
148 lastRow,
149 i;
150
151 for ( i = 0; i < cells.length; i++ ) {
152 if ( lastRow && !lastRow.equals( cells[ i ].getAscendant( 'tr' ) ) ) {
153 txt += currentRow.join( '\t' ) + '\n';
154 lastRow = cells[ i ].getAscendant( 'tr' );
155 currentRow = [];
156 } else if ( i === 0 ) {
157 lastRow = cells[ i ].getAscendant( 'tr' );
158 }
159
160 currentRow.push( cells[ i ].getText() );
161 }
162
163 txt += currentRow.join( '\t' );
164
165 return txt;
166 }
167
168 function performFakeTableSelection( ranges ) {
169 var editor = this.root.editor,
170 realSelection = editor.getSelection( 1 ),
171 cache;
172
173 // Cleanup after previous selection - e.g. remove hidden sel container.
174 this.reset();
175
176 // Indicate that the table is being fake-selected to prevent infinite loop
177 // inside `selectRanges`.
178 isSelectingTable = true;
179
180 // Cancel selectionchange for the real selection.
181 realSelection.root.once( 'selectionchange', function( evt ) {
182 evt.cancel();
183 }, null, null, 0 );
184
185 // Move real selection to the first selected range.
186 realSelection.selectRanges( [ ranges[ 0 ] ] );
187
188 cache = this._.cache;
189
190 // Caches given ranges.
191 cache.ranges = new CKEDITOR.dom.rangeList( ranges );
192 cache.type = CKEDITOR.SELECTION_TEXT;
193 cache.selectedElement = ranges[ 0 ]._getTableElement();
194
195 // `selectedText` should contain text from all selected data ("plain text table")
196 // to be compatible with Firefox's implementation.
197 cache.selectedText = getTextFromSelectedCells( ranges );
198
199 // Properties that will not be available when isFake.
200 cache.nativeSel = null;
201
202 this.isFake = 1;
203 this.rev = nextRev++;
204
205 // Save this selection, so it can be returned by editor.getSelection().
206 editor._.fakeSelection = this;
207
208 isSelectingTable = false;
209
210 // Fire selectionchange, just like a normal selection.
211 this.root.fire( 'selectionchange' );
212 }
213 // #### table selection : END
12 214
13 // #### checkSelectionChange : START 215 // #### checkSelectionChange : START
14 216
@@ -22,10 +224,9 @@
22 224
23 if ( sel ) { 225 if ( sel ) {
24 realSel = this.getSelection( 1 ); 226 realSel = this.getSelection( 1 );
25 227 // If real (not locked/stored) selection was moved from hidden container
26 // If real (not locked/stored) selection was moved from hidden container, 228 // or is not a table one, then the fake-selection must be invalidated.
27 // then the fake-selection must be invalidated. 229 if ( !realSel || ( !realSel.isHidden() && !isRealTableSelection( realSel, sel ) ) ) {
28 if ( !realSel || !realSel.isHidden() ) {
29 // Remove the cache from fake-selection references in use elsewhere. 230 // Remove the cache from fake-selection references in use elsewhere.
30 sel.reset(); 231 sel.reset();
31 232
@@ -47,7 +248,7 @@
47 248
48 var currentPath = this.elementPath(); 249 var currentPath = this.elementPath();
49 if ( !currentPath.compare( this._.selectionPreviousPath ) ) { 250 if ( !currentPath.compare( this._.selectionPreviousPath ) ) {
50 // Handle case when dialog inserts new element but parent block and path (so also focus context) does not change. (#13362) 251 // Handle case when dialog inserts new element but parent block and path (so also focus context) does not change. (http://dev.ckeditor.com/ticket/13362)
51 var sameBlockParent = this._.selectionPreviousPath && this._.selectionPreviousPath.blockLimit.equals( currentPath.blockLimit ); 252 var sameBlockParent = this._.selectionPreviousPath && this._.selectionPreviousPath.blockLimit.equals( currentPath.blockLimit );
52 // Cache the active element, which we'll eventually lose on Webkit. 253 // Cache the active element, which we'll eventually lose on Webkit.
53 if ( CKEDITOR.env.webkit && !sameBlockParent ) 254 if ( CKEDITOR.env.webkit && !sameBlockParent )
@@ -97,7 +298,7 @@
97 // * is a visible node, 298 // * is a visible node,
98 // * is a non-empty element (this rule will accept elements like <strong></strong> because they 299 // * is a non-empty element (this rule will accept elements like <strong></strong> because they
99 // they were not accepted by the isVisible() check, not not <br> which cannot absorb the caret). 300 // they were not accepted by the isVisible() check, not not <br> which cannot absorb the caret).
100 // See #12621. 301 // See http://dev.ckeditor.com/ticket/12621.
101 function mayAbsorbCaret( node ) { 302 function mayAbsorbCaret( node ) {
102 if ( isVisible( node ) ) 303 if ( isVisible( node ) )
103 return true; 304 return true;
@@ -138,8 +339,8 @@
138 if ( ctxRequiresFix( previous ) || ctxRequiresFix( next, 1 ) ) 339 if ( ctxRequiresFix( previous ) || ctxRequiresFix( next, 1 ) )
139 return true; 340 return true;
140 341
141 // Empty block/inline element is also affected. <span>^</span>, <p>^</p> (#7222) 342 // Empty block/inline element is also affected. <span>^</span>, <p>^</p> (http://dev.ckeditor.com/ticket/7222)
142 // If you found this line confusing check #12655. 343 // If you found this line confusing check http://dev.ckeditor.com/ticket/12655.
143 if ( !( previous || next ) && !( ct.type == CKEDITOR.NODE_ELEMENT && ct.isBlockBoundary() && ct.getBogus() ) ) 344 if ( !( previous || next ) && !( ct.type == CKEDITOR.NODE_ELEMENT && ct.isBlockBoundary() && ct.getBogus() ) )
144 return true; 345 return true;
145 346
@@ -155,7 +356,7 @@
155 return fillingChar; 356 return fillingChar;
156 } 357 }
157 358
158 // Checks if a filling char has been used, eventualy removing it (#1272). 359 // Checks if a filling char has been used, eventually removing it (http://dev.ckeditor.com/ticket/1272).
159 function checkFillingCharSequenceNodeReady( editable ) { 360 function checkFillingCharSequenceNodeReady( editable ) {
160 var fillingChar = editable.getCustomData( 'cke-fillingChar' ); 361 var fillingChar = editable.getCustomData( 'cke-fillingChar' );
161 362
@@ -164,6 +365,7 @@
164 // creating it. 365 // creating it.
165 if ( fillingChar.getCustomData( 'ready' ) ) { 366 if ( fillingChar.getCustomData( 'ready' ) ) {
166 removeFillingCharSequenceNode( editable ); 367 removeFillingCharSequenceNode( editable );
368 editable.editor.fire( 'selectionCheck' );
167 } else { 369 } else {
168 fillingChar.setCustomData( 'ready', 1 ); 370 fillingChar.setCustomData( 'ready', 1 );
169 } 371 }
@@ -175,7 +377,7 @@
175 377
176 if ( fillingChar ) { 378 if ( fillingChar ) {
177 // Text selection position might get mangled by 379 // Text selection position might get mangled by
178 // subsequent dom modification, save it now for restoring. (#8617) 380 // subsequent dom modification, save it now for restoring. (http://dev.ckeditor.com/ticket/8617)
179 if ( keepSelection !== false ) { 381 if ( keepSelection !== false ) {
180 var sel = editable.getDocument().getSelection().getNative(), 382 var sel = editable.getDocument().getSelection().getNative(),
181 // Be error proof. 383 // Be error proof.
@@ -211,11 +413,11 @@
211 } 413 }
212 } 414 }
213 415
214 // #13816 416 // http://dev.ckeditor.com/ticket/13816
215 function removeFillingCharSequenceString( str, nbspAware ) { 417 function removeFillingCharSequenceString( str, nbspAware ) {
216 if ( nbspAware ) { 418 if ( nbspAware ) {
217 return str.replace( fillingCharSequenceRegExp, function( m, p ) { 419 return str.replace( fillingCharSequenceRegExp, function( m, p ) {
218 // #10291 if filling char is followed by a space replace it with NBSP. 420 // http://dev.ckeditor.com/ticket/10291 if filling char is followed by a space replace it with NBSP.
219 return p ? '\xa0' : ''; 421 return p ? '\xa0' : '';
220 } ); 422 } );
221 } else { 423 } else {
@@ -391,7 +593,7 @@
391 ( enclosedNode = range.getEnclosedNode() ) && enclosedNode.type == CKEDITOR.NODE_ELEMENT ) { 593 ( enclosedNode = range.getEnclosedNode() ) && enclosedNode.type == CKEDITOR.NODE_ELEMENT ) {
392 // So far we can't say that enclosed element is non-editable. Before checking, 594 // So far we can't say that enclosed element is non-editable. Before checking,
393 // we'll shrink range (clone). Shrinking will stop on non-editable range, or 595 // we'll shrink range (clone). Shrinking will stop on non-editable range, or
394 // innermost element (#11114). 596 // innermost element (http://dev.ckeditor.com/ticket/11114).
395 clone = range.clone(); 597 clone = range.clone();
396 clone.shrink( CKEDITOR.SHRINK_ELEMENT, true ); 598 clone.shrink( CKEDITOR.SHRINK_ELEMENT, true );
397 599
@@ -525,7 +727,7 @@
525 727
526 // Give the editable an initial selection on first focus, 728 // Give the editable an initial selection on first focus,
527 // put selection at a consistent position at the start 729 // put selection at a consistent position at the start
528 // of the contents. (#9507) 730 // of the contents. (http://dev.ckeditor.com/ticket/9507)
529 if ( CKEDITOR.env.gecko ) { 731 if ( CKEDITOR.env.gecko ) {
530 editable.attachListener( editable, 'focus', function( evt ) { 732 editable.attachListener( editable, 'focus', function( evt ) {
531 evt.removeListener(); 733 evt.removeListener();
@@ -533,7 +735,7 @@
533 if ( restoreSel !== 0 ) { 735 if ( restoreSel !== 0 ) {
534 var nativ = editor.getSelection().getNative(); 736 var nativ = editor.getSelection().getNative();
535 // Do it only if the native selection is at an unwanted 737 // Do it only if the native selection is at an unwanted
536 // place (at the very start of the editable). #10119 738 // place (at the very start of the editable). http://dev.ckeditor.com/ticket/10119
537 if ( nativ && nativ.isCollapsed && nativ.anchorNode == editable.$ ) { 739 if ( nativ && nativ.isCollapsed && nativ.anchorNode == editable.$ ) {
538 var rng = editor.createRange(); 740 var rng = editor.createRange();
539 rng.moveToElementEditStart( editable ); 741 rng.moveToElementEditStart( editable );
@@ -553,7 +755,7 @@
553 755
554 // On Webkit when editor uses divarea, native focus causes editable viewport to scroll 756 // On Webkit when editor uses divarea, native focus causes editable viewport to scroll
555 // to the top (when there is no active selection inside while focusing) so the scroll 757 // to the top (when there is no active selection inside while focusing) so the scroll
556 // position should be restored after focusing back editable area. (#14659) 758 // position should be restored after focusing back editable area. (http://dev.ckeditor.com/ticket/14659)
557 if ( restoreSel && editor._.previousScrollTop != null && editor._.previousScrollTop != editable.$.scrollTop ) { 759 if ( restoreSel && editor._.previousScrollTop != null && editor._.previousScrollTop != editable.$.scrollTop ) {
558 editable.$.scrollTop = editor._.previousScrollTop; 760 editable.$.scrollTop = editor._.previousScrollTop;
559 } 761 }
@@ -605,7 +807,7 @@
605 editable.attachListener( editable, 'mousedown', function( evt ) { 807 editable.attachListener( editable, 'mousedown', function( evt ) {
606 // IE scrolls document to top on right mousedown 808 // IE scrolls document to top on right mousedown
607 // when editor has no focus, remember this scroll 809 // when editor has no focus, remember this scroll
608 // position and revert it before context menu opens. (#5778) 810 // position and revert it before context menu opens. (http://dev.ckeditor.com/ticket/5778)
609 if ( evt.data.$.button == 2 ) { 811 if ( evt.data.$.button == 2 ) {
610 var sel = editor.document.getSelection(); 812 var sel = editor.document.getSelection();
611 if ( !sel || sel.getType() == CKEDITOR.SELECTION_NONE ) 813 if ( !sel || sel.getType() == CKEDITOR.SELECTION_NONE )
@@ -624,7 +826,7 @@
624 826
625 // When content doc is in standards mode, IE doesn't focus the editor when 827 // When content doc is in standards mode, IE doesn't focus the editor when
626 // clicking at the region below body (on html element) content, we emulate 828 // clicking at the region below body (on html element) content, we emulate
627 // the normal behavior on old IEs. (#1659, #7932) 829 // the normal behavior on old IEs. (http://dev.ckeditor.com/ticket/1659, http://dev.ckeditor.com/ticket/7932)
628 if ( doc.$.compatMode != 'BackCompat' ) { 830 if ( doc.$.compatMode != 'BackCompat' ) {
629 if ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) { 831 if ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) {
630 var textRng, 832 var textRng,
@@ -661,7 +863,7 @@
661 html.removeListener( 'mousemove', onHover ); 863 html.removeListener( 'mousemove', onHover );
662 removeListeners(); 864 removeListeners();
663 865
664 // Make it in effect on mouse up. (#9022) 866 // Make it in effect on mouse up. (http://dev.ckeditor.com/ticket/9022)
665 textRng.select(); 867 textRng.select();
666 } 868 }
667 869
@@ -690,7 +892,7 @@
690 if ( CKEDITOR.env.version > 7 && CKEDITOR.env.version < 11 ) { 892 if ( CKEDITOR.env.version > 7 && CKEDITOR.env.version < 11 ) {
691 html.on( 'mousedown', function( evt ) { 893 html.on( 'mousedown', function( evt ) {
692 if ( evt.data.getTarget().is( 'html' ) ) { 894 if ( evt.data.getTarget().is( 'html' ) ) {
693 // Limit the text selection mouse move inside of editable. (#9715) 895 // Limit the text selection mouse move inside of editable. (http://dev.ckeditor.com/ticket/9715)
694 outerDoc.on( 'mouseup', onSelectEnd ); 896 outerDoc.on( 'mouseup', onSelectEnd );
695 html.on( 'mouseup', onSelectEnd ); 897 html.on( 'mouseup', onSelectEnd );
696 } 898 }
@@ -704,6 +906,14 @@
704 // 2. After the accomplish of keyboard and mouse events. 906 // 2. After the accomplish of keyboard and mouse events.
705 editable.attachListener( editable, 'selectionchange', checkSelectionChange, editor ); 907 editable.attachListener( editable, 'selectionchange', checkSelectionChange, editor );
706 editable.attachListener( editable, 'keyup', checkSelectionChangeTimeout, editor ); 908 editable.attachListener( editable, 'keyup', checkSelectionChangeTimeout, editor );
909 // http://dev.ckeditor.com/ticket/14407 - Don't even let anything happen if the selection is in a non-editable element.
910 editable.attachListener( editable, 'keydown', function( evt ) {
911 var sel = this.getSelection( 1 );
912 if ( nonEditableAscendant( sel ) ) {
913 sel.selectElement( nonEditableAscendant( sel ) );
914 evt.data.preventDefault();
915 }
916 }, editor );
707 // Always fire the selection change on focus gain. 917 // Always fire the selection change on focus gain.
708 // On Webkit do this on DOMFocusIn, because the selection is unlocked on it too and 918 // On Webkit do this on DOMFocusIn, because the selection is unlocked on it too and
709 // we need synchronization between those listeners to not lost cached editor._.previousActive property 919 // we need synchronization between those listeners to not lost cached editor._.previousActive property
@@ -713,7 +923,7 @@
713 editor.selectionChange( 1 ); 923 editor.selectionChange( 1 );
714 } ); 924 } );
715 925
716 // #9699: On Webkit&Gecko in inline editor we have to check selection when it was changed 926 // http://dev.ckeditor.com/ticket/9699: On Webkit&Gecko in inline editor we have to check selection when it was changed
717 // by dragging and releasing mouse button outside editable. Dragging (mousedown) 927 // by dragging and releasing mouse button outside editable. Dragging (mousedown)
718 // has to be initialized in editable, but for mouseup we listen on document element. 928 // has to be initialized in editable, but for mouseup we listen on document element.
719 if ( isInline && ( CKEDITOR.env.webkit || CKEDITOR.env.gecko ) ) { 929 if ( isInline && ( CKEDITOR.env.webkit || CKEDITOR.env.gecko ) ) {
@@ -727,11 +937,11 @@
727 mouseDown = 0; 937 mouseDown = 0;
728 } ); 938 } );
729 } 939 }
730 // In all other cases listen on simple mouseup over editable, as we did before #9699. 940 // In all other cases listen on simple mouseup over editable, as we did before http://dev.ckeditor.com/ticket/9699.
731 // 941 //
732 // Use document instead of editable in non-IEs for observing mouseup 942 // Use document instead of editable in non-IEs for observing mouseup
733 // since editable won't fire the event if selection process started within iframe and ended out 943 // since editable won't fire the event if selection process started within iframe and ended out
734 // of the editor (#9851). 944 // of the editor (http://dev.ckeditor.com/ticket/9851).
735 else { 945 else {
736 editable.attachListener( CKEDITOR.env.ie ? editable : doc.getDocumentElement(), 'mouseup', checkSelectionChangeTimeout, editor ); 946 editable.attachListener( CKEDITOR.env.ie ? editable : doc.getDocumentElement(), 'mouseup', checkSelectionChangeTimeout, editor );
737 } 947 }
@@ -753,18 +963,18 @@
753 case 8: // BACKSPACE 963 case 8: // BACKSPACE
754 case 45: // INS 964 case 45: // INS
755 case 46: // DEl 965 case 46: // DEl
756 removeFillingCharSequenceNode( editable ); 966 if ( editable.hasFocus ) {
967 removeFillingCharSequenceNode( editable );
968 }
757 } 969 }
758 970
759 }, null, null, -1 ); 971 }, null, null, -1 );
760 } 972 }
761 973
762 // Automatically select non-editable element when navigating into
763 // it by left/right or backspace/del keys.
764 editable.attachListener( editable, 'keydown', getOnKeyDownListener( editor ), null, null, -1 ); 974 editable.attachListener( editable, 'keydown', getOnKeyDownListener( editor ), null, null, -1 );
765 975
766 function moveRangeToPoint( range, x, y ) { 976 function moveRangeToPoint( range, x, y ) {
767 // Error prune in IE7. (#9034, #9110) 977 // Error prune in IE7. (http://dev.ckeditor.com/ticket/9034, http://dev.ckeditor.com/ticket/9110)
768 try { 978 try {
769 range.moveToPoint( x, y ); 979 range.moveToPoint( x, y );
770 } catch ( e ) {} 980 } catch ( e ) {}
@@ -785,14 +995,27 @@
785 range = sel.createRange(); 995 range = sel.createRange();
786 996
787 // The selection range is reported on host, but actually it should applies to the content doc. 997 // The selection range is reported on host, but actually it should applies to the content doc.
788 if ( sel.type != 'None' && range.parentElement().ownerDocument == doc.$ ) 998 // The parentElement may be null for read only mode in IE10 and below (http://dev.ckeditor.com/ticket/9780).
999 if ( sel.type != 'None' && range.parentElement() && range.parentElement().ownerDocument == doc.$ )
789 range.select(); 1000 range.select();
790 } 1001 }
1002
1003 function nonEditableAscendant( sel ) {
1004 if ( CKEDITOR.env.ie ) {
1005 var range = sel.getRanges()[ 0 ],
1006 ascendant = range ? range.startContainer.getAscendant( function( parent ) {
1007 return parent.type == CKEDITOR.NODE_ELEMENT &&
1008 ( parent.getAttribute( 'contenteditable' ) == 'false' || parent.getAttribute( 'contenteditable' ) == 'true' );
1009 }, true ) : null ;
1010
1011 return range && ascendant.getAttribute( 'contenteditable' ) == 'false' && ascendant;
1012 }
1013 }
791 } ); 1014 } );
792 1015
793 editor.on( 'setData', function() { 1016 editor.on( 'setData', function() {
794 // Invalidate locked selection when unloading DOM. 1017 // Invalidate locked selection when unloading DOM.
795 // (#9521, #5217#comment:32 and #11500#comment:11) 1018 // (http://dev.ckeditor.com/ticket/9521, http://dev.ckeditor.com/ticket/5217#comment:32 and http://dev.ckeditor.com/ticket/11500#comment:11)
796 editor.unlockSelection(); 1019 editor.unlockSelection();
797 1020
798 // Webkit's selection will mess up after the data loading. 1021 // Webkit's selection will mess up after the data loading.
@@ -806,7 +1029,7 @@
806 editor.unlockSelection(); 1029 editor.unlockSelection();
807 } ); 1030 } );
808 1031
809 // IE9 might cease to work if there's an object selection inside the iframe (#7639). 1032 // IE9 might cease to work if there's an object selection inside the iframe (http://dev.ckeditor.com/ticket/7639).
810 if ( CKEDITOR.env.ie9Compat ) 1033 if ( CKEDITOR.env.ie9Compat )
811 editor.on( 'beforeDestroy', clearSelection, null, null, 9 ); 1034 editor.on( 'beforeDestroy', clearSelection, null, null, 9 );
812 1035
@@ -822,7 +1045,7 @@
822 // When loaded data are ready check whether hidden selection container was not loaded. 1045 // When loaded data are ready check whether hidden selection container was not loaded.
823 editor.on( 'loadSnapshot', function() { 1046 editor.on( 'loadSnapshot', function() {
824 var isElement = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT ), 1047 var isElement = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT ),
825 // TODO replace with el.find() which will be introduced in #9764, 1048 // TODO replace with el.find() which will be introduced in http://dev.ckeditor.com/ticket/9764,
826 // because it may happen that hidden sel container won't be the last element. 1049 // because it may happen that hidden sel container won't be the last element.
827 last = editor.editable().getLast( isElement ); 1050 last = editor.editable().getLast( isElement );
828 1051
@@ -869,7 +1092,7 @@
869 } ); 1092 } );
870 1093
871 // On WebKit only, we need a special "filling" char on some situations 1094 // On WebKit only, we need a special "filling" char on some situations
872 // (#1272). Here we set the events that should invalidate that char. 1095 // (http://dev.ckeditor.com/ticket/1272). Here we set the events that should invalidate that char.
873 if ( CKEDITOR.env.webkit ) { 1096 if ( CKEDITOR.env.webkit ) {
874 CKEDITOR.on( 'instanceReady', function( evt ) { 1097 CKEDITOR.on( 'instanceReady', function( evt ) {
875 var editor = evt.editor; 1098 var editor = evt.editor;
@@ -884,7 +1107,7 @@
884 1107
885 // Filter Undo snapshot's HTML to get rid of Filling Char Sequence. 1108 // Filter Undo snapshot's HTML to get rid of Filling Char Sequence.
886 // Note: CKEDITOR.dom.range.createBookmark2() normalizes snapshot's 1109 // Note: CKEDITOR.dom.range.createBookmark2() normalizes snapshot's
887 // bookmarks to anticipate the removal of FCSeq from the snapshot's HTML (#13816). 1110 // bookmarks to anticipate the removal of FCSeq from the snapshot's HTML (http://dev.ckeditor.com/ticket/13816).
888 editor.on( 'getSnapshot', function( evt ) { 1111 editor.on( 'getSnapshot', function( evt ) {
889 if ( evt.data ) { 1112 if ( evt.data ) {
890 evt.data = removeFillingCharSequenceString( evt.data ); 1113 evt.data = removeFillingCharSequenceString( evt.data );
@@ -893,7 +1116,7 @@
893 1116
894 // Filter data to get rid of Filling Char Sequence. Filter on #toDataFormat 1117 // Filter data to get rid of Filling Char Sequence. Filter on #toDataFormat
895 // instead of #getData because once removed, FCSeq may leave an empty element, 1118 // instead of #getData because once removed, FCSeq may leave an empty element,
896 // which should be pruned by the dataProcessor (#13816). 1119 // which should be pruned by the dataProcessor (http://dev.ckeditor.com/ticket/13816).
897 // Note: Used low priority to filter when dataProcessor works on strings, 1120 // Note: Used low priority to filter when dataProcessor works on strings,
898 // not pseudo–DOM. 1121 // not pseudo–DOM.
899 editor.on( 'toDataFormat', function( evt ) { 1122 editor.on( 'toDataFormat', function( evt ) {
@@ -1138,7 +1361,7 @@
1138 1361
1139 // Selection out of concerned range, empty the selection. 1362 // Selection out of concerned range, empty the selection.
1140 // TODO check whether this condition cannot be reverted to its old 1363 // TODO check whether this condition cannot be reverted to its old
1141 // form (commented out) after we closed #10438. 1364 // form (commented out) after we closed http://dev.ckeditor.com/ticket/10438.
1142 //if ( !( rangeParent && ( root.equals( rangeParent ) || root.contains( rangeParent ) ) ) ) { 1365 //if ( !( rangeParent && ( root.equals( rangeParent ) || root.contains( rangeParent ) ) ) ) {
1143 if ( !( 1366 if ( !(
1144 rangeParent && 1367 rangeParent &&
@@ -1180,7 +1403,7 @@
1180 * 1403 *
1181 * var selection = editor.getSelection().getNative(); 1404 * var selection = editor.getSelection().getNative();
1182 * 1405 *
1183 * @returns {Object} The native browser selection object. 1406 * @returns {Object} The native browser selection object or null if this is a fake selection.
1184 */ 1407 */
1185 getNative: function() { 1408 getNative: function() {
1186 if ( this._.cache.nativeSel !== undefined ) 1409 if ( this._.cache.nativeSel !== undefined )
@@ -1272,7 +1495,7 @@
1272 * alert( ranges.length ); 1495 * alert( ranges.length );
1273 * 1496 *
1274 * @method 1497 * @method
1275 * @param {Boolean} [onlyEditables] If set to `true`, this function retrives editable ranges only. 1498 * @param {Boolean} [onlyEditables] If set to `true`, this function retrieves editable ranges only.
1276 * @returns {Array} Range instances that represent the current selection. 1499 * @returns {Array} Range instances that represent the current selection.
1277 */ 1500 */
1278 getRanges: ( function() { 1501 getRanges: ( function() {
@@ -1303,7 +1526,7 @@
1303 index = -1, 1526 index = -1,
1304 position, distance, container; 1527 position, distance, container;
1305 1528
1306 // Binary search over all element childs to test the range to see whether 1529 // Binary search over all element children to test the range to see whether
1307 // range is right on the boundary of one element. 1530 // range is right on the boundary of one element.
1308 while ( startIndex <= endIndex ) { 1531 while ( startIndex <= endIndex ) {
1309 index = Math.floor( ( startIndex + endIndex ) / 2 ); 1532 index = Math.floor( ( startIndex + endIndex ) / 2 );
@@ -1319,8 +1542,8 @@
1319 return { container: parent, offset: getNodeIndex( child ) }; 1542 return { container: parent, offset: getNodeIndex( child ) };
1320 } 1543 }
1321 1544
1322 // All childs are text nodes, 1545 // All children are text nodes,
1323 // or to the right hand of test range are all text nodes. (#6992) 1546 // or to the right hand of test range are all text nodes. (http://dev.ckeditor.com/ticket/6992)
1324 if ( index == -1 || index == siblings.length - 1 && position < 0 ) { 1547 if ( index == -1 || index == siblings.length - 1 && position < 0 ) {
1325 // Adapt test range to embrace the entire parent contents. 1548 // Adapt test range to embrace the entire parent contents.
1326 testRange.moveToElementText( parent ); 1549 testRange.moveToElementText( parent );
@@ -1328,7 +1551,7 @@
1328 1551
1329 // IE report line break as CRLF with range.text but 1552 // IE report line break as CRLF with range.text but
1330 // only LF with textnode.nodeValue, normalize them to avoid 1553 // only LF with textnode.nodeValue, normalize them to avoid
1331 // breaking character counting logic below. (#3949) 1554 // breaking character counting logic below. (http://dev.ckeditor.com/ticket/3949)
1332 distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; 1555 distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
1333 1556
1334 siblings = parent.childNodes; 1557 siblings = parent.childNodes;
@@ -1364,7 +1587,7 @@
1364 1587
1365 // IE report line break as CRLF with range.text but 1588 // IE report line break as CRLF with range.text but
1366 // only LF with textnode.nodeValue, normalize them to avoid 1589 // only LF with textnode.nodeValue, normalize them to avoid
1367 // breaking character counting logic below. (#3949) 1590 // breaking character counting logic below. (http://dev.ckeditor.com/ticket/3949)
1368 distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; 1591 distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
1369 1592
1370 // Actual range anchor right beside test range at the inner boundary of text node. 1593 // Actual range anchor right beside test range at the inner boundary of text node.
@@ -1381,7 +1604,7 @@
1381 } 1604 }
1382 child = sibling; 1605 child = sibling;
1383 } 1606 }
1384 // Measurement in IE could be somtimes wrong because of <select> element. (#4611) 1607 // Measurement in IE could be sometimes wrong because of <select> element. (http://dev.ckeditor.com/ticket/4611)
1385 catch ( e ) { 1608 catch ( e ) {
1386 return { container: parent, offset: getNodeIndex( child ) }; 1609 return { container: parent, offset: getNodeIndex( child ) };
1387 } 1610 }
@@ -1413,7 +1636,7 @@
1413 boundaryInfo = getBoundaryInformation( nativeRange ); 1636 boundaryInfo = getBoundaryInformation( nativeRange );
1414 range.setEnd( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset ); 1637 range.setEnd( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset );
1415 1638
1416 // Correct an invalid IE range case on empty list item. (#5850) 1639 // Correct an invalid IE range case on empty list item. (http://dev.ckeditor.com/ticket/5850)
1417 if ( range.endContainer.getPosition( range.startContainer ) & CKEDITOR.POSITION_PRECEDING && range.endOffset <= range.startContainer.getIndex() ) 1640 if ( range.endContainer.getPosition( range.startContainer ) & CKEDITOR.POSITION_PRECEDING && range.endOffset <= range.startContainer.getIndex() )
1418 range.collapse(); 1641 range.collapse();
1419 1642
@@ -1445,7 +1668,7 @@
1445 } )() : 1668 } )() :
1446 function() { 1669 function() {
1447 // On browsers implementing the W3C range, we simply 1670 // On browsers implementing the W3C range, we simply
1448 // tranform the native ranges in CKEDITOR.dom.range 1671 // transform the native ranges in CKEDITOR.dom.range
1449 // instances. 1672 // instances.
1450 1673
1451 var ranges = [], 1674 var ranges = [],
@@ -1478,7 +1701,7 @@
1478 return ranges; 1701 return ranges;
1479 1702
1480 // Split range into multiple by read-only nodes. 1703 // Split range into multiple by read-only nodes.
1481 // Clone ranges array to avoid changing cached ranges (#11493). 1704 // Clone ranges array to avoid changing cached ranges (http://dev.ckeditor.com/ticket/11493).
1482 return extractEditableRanges( new CKEDITOR.dom.rangeList( ranges.slice() ) ); 1705 return extractEditableRanges( new CKEDITOR.dom.rangeList( ranges.slice() ) );
1483 }; 1706 };
1484 } )(), 1707 } )(),
@@ -1512,11 +1735,11 @@
1512 1735
1513 // Decrease the range content to exclude particial 1736 // Decrease the range content to exclude particial
1514 // selected node on the start which doesn't have 1737 // selected node on the start which doesn't have
1515 // visual impact. ( #3231 ) 1738 // visual impact. ( http://dev.ckeditor.com/ticket/3231 )
1516 while ( 1 ) { 1739 while ( 1 ) {
1517 var startContainer = range.startContainer, 1740 var startContainer = range.startContainer,
1518 startOffset = range.startOffset; 1741 startOffset = range.startOffset;
1519 // Limit the fix only to non-block elements.(#3950) 1742 // Limit the fix only to non-block elements.(http://dev.ckeditor.com/ticket/3950)
1520 if ( startOffset == ( startContainer.getChildCount ? startContainer.getChildCount() : startContainer.getLength() ) && !startContainer.isBlockBoundary() ) 1743 if ( startOffset == ( startContainer.getChildCount ? startContainer.getChildCount() : startContainer.getLength() ) && !startContainer.isBlockBoundary() )
1521 range.setStartAfter( startContainer ); 1744 range.setStartAfter( startContainer );
1522 else 1745 else
@@ -1558,7 +1781,7 @@
1558 * var element = editor.getSelection().getSelectedElement(); 1781 * var element = editor.getSelection().getSelectedElement();
1559 * alert( element.getName() ); 1782 * alert( element.getName() );
1560 * 1783 *
1561 * @returns {CKEDITOR.dom.element} The selected element. Null if no 1784 * @returns {CKEDITOR.dom.element/null} The selected element. `null` if no
1562 * selection is available or the selection type is not {@link CKEDITOR#SELECTION_ELEMENT}. 1785 * selection is available or the selection type is not {@link CKEDITOR#SELECTION_ELEMENT}.
1563 */ 1786 */
1564 getSelectedElement: function() { 1787 getSelectedElement: function() {
@@ -1641,7 +1864,7 @@
1641 1864
1642 if ( restore ) { 1865 if ( restore ) {
1643 var selectedElement = this.getSelectedElement(), 1866 var selectedElement = this.getSelectedElement(),
1644 ranges = !selectedElement && this.getRanges(), 1867 ranges = this.getRanges(),
1645 faked = this.isFake; 1868 faked = this.isFake;
1646 } 1869 }
1647 1870
@@ -1655,7 +1878,10 @@
1655 if ( !( common && common.getAscendant( 'body', 1 ) ) ) 1878 if ( !( common && common.getAscendant( 'body', 1 ) ) )
1656 return; 1879 return;
1657 1880
1658 if ( faked ) 1881 if ( isTableSelection( ranges ) ) {
1882 // Tables have it's own selection method.
1883 performFakeTableSelection.call( this, ranges );
1884 } else if ( faked )
1659 this.fake( selectedElement ); 1885 this.fake( selectedElement );
1660 else if ( selectedElement ) 1886 else if ( selectedElement )
1661 this.selectElement( selectedElement ); 1887 this.selectElement( selectedElement );
@@ -1727,7 +1953,7 @@
1727 // Check if there's a hiddenSelectionContainer in editable at some index. 1953 // Check if there's a hiddenSelectionContainer in editable at some index.
1728 // Some ranges may be anchored after the hiddenSelectionContainer and, 1954 // Some ranges may be anchored after the hiddenSelectionContainer and,
1729 // once the container is removed while resetting the selection, they 1955 // once the container is removed while resetting the selection, they
1730 // may need new endOffset (one element less within the range) (#11021 #11393). 1956 // may need new endOffset (one element less within the range) (http://dev.ckeditor.com/ticket/11021 http://dev.ckeditor.com/ticket/11393).
1731 if ( hadHiddenSelectionContainer ) 1957 if ( hadHiddenSelectionContainer )
1732 fixRangesAfterHiddenSelectionContainer( ranges, this.root ); 1958 fixRangesAfterHiddenSelectionContainer( ranges, this.root );
1733 1959
@@ -1755,6 +1981,15 @@
1755 return; 1981 return;
1756 } 1982 }
1757 1983
1984 // Handle special case - fake selection of table cells.
1985 if ( editor && editor.plugins.tableselection &&
1986 CKEDITOR.plugins.tableselection.isSupportedEnvironment &&
1987 isTableSelection( ranges ) && !isSelectingTable
1988 ) {
1989 performFakeTableSelection.call( this, ranges );
1990 return;
1991 }
1992
1758 if ( isMSSelection ) { 1993 if ( isMSSelection ) {
1759 var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true ), 1994 var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true ),
1760 fillerTextRegex = /\ufeff|\u00a0/, 1995 fillerTextRegex = /\ufeff|\u00a0/,
@@ -1788,7 +2023,7 @@
1788 if ( range.startContainer.type == CKEDITOR.NODE_ELEMENT && range.startContainer.getName() in nonCells || 2023 if ( range.startContainer.type == CKEDITOR.NODE_ELEMENT && range.startContainer.getName() in nonCells ||
1789 range.endContainer.type == CKEDITOR.NODE_ELEMENT && range.endContainer.getName() in nonCells ) { 2024 range.endContainer.type == CKEDITOR.NODE_ELEMENT && range.endContainer.getName() in nonCells ) {
1790 range.shrink( CKEDITOR.NODE_ELEMENT, true ); 2025 range.shrink( CKEDITOR.NODE_ELEMENT, true );
1791 // The range might get collapsed (#7975). Update cached variable. 2026 // The range might get collapsed (http://dev.ckeditor.com/ticket/7975). Update cached variable.
1792 collapsed = range.collapsed; 2027 collapsed = range.collapsed;
1793 } 2028 }
1794 2029
@@ -1830,18 +2065,18 @@
1830 2065
1831 // Append a temporary <span>&#65279;</span> before the selection. 2066 // Append a temporary <span>&#65279;</span> before the selection.
1832 // This is needed to avoid IE destroying selections inside empty 2067 // This is needed to avoid IE destroying selections inside empty
1833 // inline elements, like <b></b> (#253). 2068 // inline elements, like <b></b> (http://dev.ckeditor.com/ticket/253).
1834 // It is also needed when placing the selection right after an inline 2069 // It is also needed when placing the selection right after an inline
1835 // element to avoid the selection moving inside of it. 2070 // element to avoid the selection moving inside of it.
1836 dummySpan = range.document.createElement( 'span' ); 2071 dummySpan = range.document.createElement( 'span' );
1837 dummySpan.setHtml( '&#65279;' ); // Zero Width No-Break Space (U+FEFF). See #1359. 2072 dummySpan.setHtml( '&#65279;' ); // Zero Width No-Break Space (U+FEFF). See http://dev.ckeditor.com/ticket/1359.
1838 dummySpan.insertBefore( startNode ); 2073 dummySpan.insertBefore( startNode );
1839 2074
1840 if ( isStartMarkerAlone ) { 2075 if ( isStartMarkerAlone ) {
1841 // To expand empty blocks or line spaces after <br>, we need 2076 // To expand empty blocks or line spaces after <br>, we need
1842 // instead to have any char, which will be later deleted using the 2077 // instead to have any char, which will be later deleted using the
1843 // selection. 2078 // selection.
1844 // \ufeff = Zero Width No-Break Space (U+FEFF). (#1359) 2079 // \ufeff = Zero Width No-Break Space (U+FEFF). (http://dev.ckeditor.com/ticket/1359)
1845 range.document.createText( '\ufeff' ).insertBefore( startNode ); 2080 range.document.createText( '\ufeff' ).insertBefore( startNode );
1846 } 2081 }
1847 } 2082 }
@@ -1873,7 +2108,7 @@
1873 } else { 2108 } else {
1874 var sel = this.getNative(); 2109 var sel = this.getNative();
1875 2110
1876 // getNative() returns null if iframe is "display:none" in FF. (#6577) 2111 // getNative() returns null if iframe is "display:none" in FF. (http://dev.ckeditor.com/ticket/6577)
1877 if ( !sel ) 2112 if ( !sel )
1878 return; 2113 return;
1879 2114
@@ -1889,7 +2124,7 @@
1889 between.setStart( left.endContainer, left.endOffset ); 2124 between.setStart( left.endContainer, left.endOffset );
1890 between.setEnd( right.startContainer, right.startOffset ); 2125 between.setEnd( right.startContainer, right.startOffset );
1891 2126
1892 // Don't confused by Firefox adjancent multi-ranges 2127 // Don't confused by Firefox adjacent multi-ranges
1893 // introduced by table cells selection. 2128 // introduced by table cells selection.
1894 if ( !between.collapsed ) { 2129 if ( !between.collapsed ) {
1895 between.shrink( CKEDITOR.NODE_ELEMENT, true ); 2130 between.shrink( CKEDITOR.NODE_ELEMENT, true );
@@ -1898,7 +2133,7 @@
1898 2133
1899 // The following cases has to be considered: 2134 // The following cases has to be considered:
1900 // 1. <span contenteditable="false">[placeholder]</span> 2135 // 1. <span contenteditable="false">[placeholder]</span>
1901 // 2. <input contenteditable="false" type="radio"/> (#6621) 2136 // 2. <input contenteditable="false" type="radio"/> (http://dev.ckeditor.com/ticket/6621)
1902 if ( ancestor.isReadOnly() || enclosed && enclosed.isReadOnly() ) { 2137 if ( ancestor.isReadOnly() || enclosed && enclosed.isReadOnly() ) {
1903 right.setStart( left.startContainer, left.startOffset ); 2138 right.setStart( left.startContainer, left.startOffset );
1904 ranges.splice( i--, 1 ); 2139 ranges.splice( i--, 1 );
@@ -1913,7 +2148,7 @@
1913 2148
1914 if ( range.collapsed && CKEDITOR.env.webkit && rangeRequiresFix( range ) ) { 2149 if ( range.collapsed && CKEDITOR.env.webkit && rangeRequiresFix( range ) ) {
1915 // Append a zero-width space so WebKit will not try to 2150 // Append a zero-width space so WebKit will not try to
1916 // move the selection by itself (#1272). 2151 // move the selection by itself (http://dev.ckeditor.com/ticket/1272).
1917 var fillingChar = createFillingCharSequenceNode( this.root ); 2152 var fillingChar = createFillingCharSequenceNode( this.root );
1918 range.insertNode( fillingChar ); 2153 range.insertNode( fillingChar );
1919 2154
@@ -1972,7 +2207,7 @@
1972 fake: function( element, ariaLabel ) { 2207 fake: function( element, ariaLabel ) {
1973 var editor = this.root.editor; 2208 var editor = this.root.editor;
1974 2209
1975 // Attempt to retreive aria-label if possible (#14539). 2210 // Attempt to retrieve aria-label if possible (http://dev.ckeditor.com/ticket/14539).
1976 if ( ariaLabel === undefined && element.hasAttribute( 'aria-label' ) ) { 2211 if ( ariaLabel === undefined && element.hasAttribute( 'aria-label' ) ) {
1977 ariaLabel = element.getAttribute( 'aria-label' ); 2212 ariaLabel = element.getAttribute( 'aria-label' );
1978 } 2213 }
@@ -2031,6 +2266,38 @@
2031 }, 2266 },
2032 2267
2033 /** 2268 /**
2269 * Checks if the selection contains an HTML element inside a table.
2270 * Returns `false` for text selection inside a table (e.g. it will return `false`
2271 * for text selected in one cell).
2272 *
2273 * editor.getSelection().isInTable();
2274 *
2275 * @since 4.7.0
2276 * @param {Boolean} [allowPartialSelection=false] Whether a partial cell selection should be included.
2277 * Added in 4.7.2.
2278 * @returns {Boolean}
2279 */
2280 isInTable: function( allowPartialSelection ) {
2281 return isTableSelection( this.getRanges(), allowPartialSelection );
2282 },
2283
2284 /**
2285 * Checks if the selection contains only one range which is collapsed.
2286 *
2287 * if ( editor.getSelection().isCollapsed() ) {
2288 * // Do something when the selection is collapsed.
2289 * }
2290 *
2291 * @since 4.7.3
2292 * @returns {Boolean}
2293 */
2294 isCollapsed: function() {
2295 var ranges = this.getRanges();
2296
2297 return ranges.length === 1 && ranges[ 0 ].collapsed;
2298 },
2299
2300 /**
2034 * Creates a bookmark for each range of this selection (from {@link #getRanges}) 2301 * Creates a bookmark for each range of this selection (from {@link #getRanges})
2035 * by calling the {@link CKEDITOR.dom.range#createBookmark} method, 2302 * by calling the {@link CKEDITOR.dom.range#createBookmark} method,
2036 * with extra care taken to avoid interference among those ranges. The arguments 2303 * with extra care taken to avoid interference among those ranges. The arguments
@@ -2083,17 +2350,19 @@
2083 2350
2084 // It may happen that the content change during loading, before selection is set so bookmark leads to text node. 2351 // It may happen that the content change during loading, before selection is set so bookmark leads to text node.
2085 if ( bookmarks.isFake ) { 2352 if ( bookmarks.isFake ) {
2086 node = ranges[ 0 ].getEnclosedNode(); 2353 node = isTableSelection( ranges ) ? ranges[ 0 ]._getTableElement() : ranges[ 0 ].getEnclosedNode();
2354
2087 if ( !node || node.type != CKEDITOR.NODE_ELEMENT ) { 2355 if ( !node || node.type != CKEDITOR.NODE_ELEMENT ) {
2088 CKEDITOR.warn( 'selection-not-fake' ); 2356 CKEDITOR.warn( 'selection-not-fake' );
2089 bookmarks.isFake = 0; 2357 bookmarks.isFake = 0;
2090 } 2358 }
2091 } 2359 }
2092 2360
2093 if ( bookmarks.isFake ) 2361 if ( bookmarks.isFake && !isTableSelection( ranges ) ) {
2094 this.fake( node ); 2362 this.fake( node );
2095 else 2363 } else {
2096 this.selectRanges( ranges ); 2364 this.selectRanges( ranges );
2365 }
2097 2366
2098 return this; 2367 return this;
2099 }, 2368 },
@@ -2130,7 +2399,7 @@
2130 * Remove all the selection ranges from the document. 2399 * Remove all the selection ranges from the document.
2131 */ 2400 */
2132 removeAllRanges: function() { 2401 removeAllRanges: function() {
2133 // Don't clear selection outside this selection's root (#11500). 2402 // Don't clear selection outside this selection's root (http://dev.ckeditor.com/ticket/11500).
2134 if ( this.getType() == CKEDITOR.SELECTION_NONE ) 2403 if ( this.getType() == CKEDITOR.SELECTION_NONE )
2135 return; 2404 return;
2136 2405
diff --git a/sources/core/skin.js b/sources/core/skin.js
index 4f0ee7c..290157d 100644
--- a/sources/core/skin.js
+++ b/sources/core/skin.js
@@ -125,7 +125,7 @@
125 offset = overrideOffset || ( icon && icon.offset ); 125 offset = overrideOffset || ( icon && icon.offset );
126 bgsize = overrideBgsize || ( icon && icon.bgsize ) || '16px'; 126 bgsize = overrideBgsize || ( icon && icon.bgsize ) || '16px';
127 127
128 // If we use apostrophes in background-image, we must escape apostrophes in path (just to be sure). (#13361) 128 // If we use apostrophes in background-image, we must escape apostrophes in path (just to be sure). (http://dev.ckeditor.com/ticket/13361)
129 if ( path ) 129 if ( path )
130 path = path.replace( /'/g, '\\\'' ); 130 path = path.replace( /'/g, '\\\'' );
131 131
diff --git a/sources/core/style.js b/sources/core/style.js
index efb9d7f..b3cf0bc 100644
--- a/sources/core/style.js
+++ b/sources/core/style.js
@@ -235,7 +235,7 @@ CKEDITOR.STYLE_OBJECT = 3;
235 var initialEnterMode = this._.enterMode; 235 var initialEnterMode = this._.enterMode;
236 236
237 // Before CKEditor 4.4 style knew nothing about editor, so in order to provide enterMode 237 // Before CKEditor 4.4 style knew nothing about editor, so in order to provide enterMode
238 // which should be used developers were forced to hack the style object (see #10190). 238 // which should be used developers were forced to hack the style object (see http://dev.ckeditor.com/ticket/10190).
239 // Since CKEditor 4.4 style knows about editor (at least when it's being applied/removed), but we 239 // Since CKEditor 4.4 style knows about editor (at least when it's being applied/removed), but we
240 // use _.enterMode for backward compatibility with those hacks. 240 // use _.enterMode for backward compatibility with those hacks.
241 // Note: we should not change style's enter mode if it was already set. 241 // Note: we should not change style's enter mode if it was already set.
@@ -569,7 +569,7 @@ CKEDITOR.STYLE_OBJECT = 3;
569 var styleVal = stylesDef[ style ], 569 var styleVal = stylesDef[ style ],
570 text = ( style + ':' + styleVal ).replace( semicolonFixRegex, ';' ); 570 text = ( style + ':' + styleVal ).replace( semicolonFixRegex, ';' );
571 571
572 // Some browsers don't support 'inherit' property value, leave them intact. (#5242) 572 // Some browsers don't support 'inherit' property value, leave them intact. (http://dev.ckeditor.com/ticket/5242)
573 if ( styleVal == 'inherit' ) 573 if ( styleVal == 'inherit' )
574 specialStylesText += text; 574 specialStylesText += text;
575 else 575 else
@@ -1024,7 +1024,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1024 if ( !CKEDITOR.env.ie ) 1024 if ( !CKEDITOR.env.ie )
1025 styleNode.$.normalize(); 1025 styleNode.$.normalize();
1026 } 1026 }
1027 // Style already inherit from parents, left just to clear up any internal overrides. (#5931) 1027 // Style already inherit from parents, left just to clear up any internal overrides. (http://dev.ckeditor.com/ticket/5931)
1028 else { 1028 else {
1029 styleNode = new CKEDITOR.dom.element( 'span' ); 1029 styleNode = new CKEDITOR.dom.element( 'span' );
1030 styleRange.extractContents().appendTo( styleNode ); 1030 styleRange.extractContents().appendTo( styleNode );
@@ -1042,7 +1042,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1042 // Remove the bookmark nodes. 1042 // Remove the bookmark nodes.
1043 range.moveToBookmark( boundaryNodes ); 1043 range.moveToBookmark( boundaryNodes );
1044 1044
1045 // Minimize the result range to exclude empty text nodes. (#5374) 1045 // Minimize the result range to exclude empty text nodes. (http://dev.ckeditor.com/ticket/5374)
1046 range.shrink( CKEDITOR.SHRINK_TEXT ); 1046 range.shrink( CKEDITOR.SHRINK_TEXT );
1047 1047
1048 // Get inside the remaining element if range.shrink( TEXT ) has failed because of non-editable elements inside. 1048 // Get inside the remaining element if range.shrink( TEXT ) has failed because of non-editable elements inside.
@@ -1058,27 +1058,31 @@ CKEDITOR.STYLE_OBJECT = 3;
1058 range.enlarge( CKEDITOR.ENLARGE_INLINE, 1 ); 1058 range.enlarge( CKEDITOR.ENLARGE_INLINE, 1 );
1059 1059
1060 var bookmark = range.createBookmark(), 1060 var bookmark = range.createBookmark(),
1061 startNode = bookmark.startNode; 1061 startNode = bookmark.startNode,
1062 alwaysRemoveElement = this._.definition.alwaysRemoveElement;
1062 1063
1063 if ( range.collapsed ) { 1064 if ( range.collapsed ) {
1064 var startPath = new CKEDITOR.dom.elementPath( startNode.getParent(), range.root ), 1065 var startPath = new CKEDITOR.dom.elementPath( startNode.getParent(), range.root ),
1065 // The topmost element in elementspatch which we should jump out of. 1066 // The topmost element in elements path which we should jump out of.
1066 boundaryElement; 1067 boundaryElement;
1067 1068
1068
1069 for ( var i = 0, element; i < startPath.elements.length && ( element = startPath.elements[ i ] ); i++ ) { 1069 for ( var i = 0, element; i < startPath.elements.length && ( element = startPath.elements[ i ] ); i++ ) {
1070 // 1. If it's collaped inside text nodes, try to remove the style from the whole element. 1070 // 1. If it's collaped inside text nodes, try to remove the style from the whole element.
1071 // 1071 //
1072 // 2. Otherwise if it's collapsed on element boundaries, moving the selection 1072 // 2. Otherwise if it's collapsed on element boundaries, moving the selection
1073 // outside the styles instead of removing the whole tag, 1073 // outside the styles instead of removing the whole tag,
1074 // also make sure other inner styles were well preserverd.(#3309) 1074 // also make sure other inner styles were well preserved.(http://dev.ckeditor.com/ticket/3309)
1075 if ( element == startPath.block || element == startPath.blockLimit ) 1075 //
1076 // 3. Force removing the element even if it's an boundary element when alwaysRemoveElement is true.
1077 // Without it, the links won't be unlinked if the cursor is placed right before/after it. (http://dev.ckeditor.com/ticket/13062)
1078 if ( element == startPath.block || element == startPath.blockLimit ) {
1076 break; 1079 break;
1080 }
1077 1081
1078 if ( this.checkElementRemovable( element ) ) { 1082 if ( this.checkElementRemovable( element ) ) {
1079 var isStart; 1083 var isStart;
1080 1084
1081 if ( range.collapsed && ( range.checkBoundaryOfElement( element, CKEDITOR.END ) || ( isStart = range.checkBoundaryOfElement( element, CKEDITOR.START ) ) ) ) { 1085 if ( !alwaysRemoveElement && range.collapsed && ( range.checkBoundaryOfElement( element, CKEDITOR.END ) || ( isStart = range.checkBoundaryOfElement( element, CKEDITOR.START ) ) ) ) {
1082 boundaryElement = element; 1086 boundaryElement = element;
1083 boundaryElement.match = isStart ? 'start' : 'end'; 1087 boundaryElement.match = isStart ? 'start' : 'end';
1084 } else { 1088 } else {
@@ -1087,10 +1091,11 @@ CKEDITOR.STYLE_OBJECT = 3;
1087 // no difference that they're separate entities in the DOM tree. So, merge 1091 // no difference that they're separate entities in the DOM tree. So, merge
1088 // them before removal. 1092 // them before removal.
1089 element.mergeSiblings(); 1093 element.mergeSiblings();
1090 if ( element.is( this.element ) ) 1094 if ( element.is( this.element ) ) {
1091 removeFromElement.call( this, element ); 1095 removeFromElement.call( this, element );
1092 else 1096 } else {
1093 removeOverrides( element, getOverrides( this )[ element.getName() ] ); 1097 removeOverrides( element, getOverrides( this )[ element.getName() ] );
1098 }
1094 } 1099 }
1095 } 1100 }
1096 } 1101 }
@@ -1235,7 +1240,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1235 } 1240 }
1236 1241
1237 function applyObjectStyle( range ) { 1242 function applyObjectStyle( range ) {
1238 // Selected or parent element. (#9651) 1243 // Selected or parent element. (http://dev.ckeditor.com/ticket/9651)
1239 var start = range.getEnclosedNode() || range.getCommonAncestor( false, true ), 1244 var start = range.getEnclosedNode() || range.getCommonAncestor( false, true ),
1240 element = new CKEDITOR.dom.elementPath( start, range.root ).contains( this.element, 1 ); 1245 element = new CKEDITOR.dom.elementPath( start, range.root ).contains( this.element, 1 );
1241 1246
@@ -1276,7 +1281,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1276 var iterator = range.createIterator(); 1281 var iterator = range.createIterator();
1277 iterator.enforceRealBlocks = true; 1282 iterator.enforceRealBlocks = true;
1278 1283
1279 // make recognize <br /> tag as a separator in ENTER_BR mode (#5121) 1284 // make recognize <br /> tag as a separator in ENTER_BR mode (http://dev.ckeditor.com/ticket/5121)
1280 if ( this._.enterMode ) 1285 if ( this._.enterMode )
1281 iterator.enlargeBr = ( this._.enterMode != CKEDITOR.ENTER_BR ); 1286 iterator.enlargeBr = ( this._.enterMode != CKEDITOR.ENTER_BR );
1282 1287
@@ -1326,7 +1331,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1326 1331
1327 // Replace the original block with new one, with special treatment 1332 // Replace the original block with new one, with special treatment
1328 // for <pre> blocks to make sure content format is well preserved, and merging/splitting adjacent 1333 // for <pre> blocks to make sure content format is well preserved, and merging/splitting adjacent
1329 // when necessary. (#3188) 1334 // when necessary. (http://dev.ckeditor.com/ticket/3188)
1330 function replaceBlock( block, newBlock ) { 1335 function replaceBlock( block, newBlock ) {
1331 // Block is to be removed, create a temp element to 1336 // Block is to be removed, create a temp element to
1332 // save contents. 1337 // save contents.
@@ -1502,11 +1507,11 @@ CKEDITOR.STYLE_OBJECT = 3;
1502 1507
1503 // Remove definition attributes/style from the elemnt. 1508 // Remove definition attributes/style from the elemnt.
1504 for ( var attName in attributes ) { 1509 for ( var attName in attributes ) {
1505 // The 'class' element value must match (#1318). 1510 // The 'class' element value must match (http://dev.ckeditor.com/ticket/1318).
1506 if ( ( attName == 'class' || this._.definition.fullMatch ) && element.getAttribute( attName ) != normalizeProperty( attName, attributes[ attName ] ) ) 1511 if ( ( attName == 'class' || this._.definition.fullMatch ) && element.getAttribute( attName ) != normalizeProperty( attName, attributes[ attName ] ) )
1507 continue; 1512 continue;
1508 1513
1509 // Do not touch data-* attributes (#11011) (#11258). 1514 // Do not touch data-* attributes (http://dev.ckeditor.com/ticket/11011) (http://dev.ckeditor.com/ticket/11258).
1510 if ( keepDataAttrs && attName.slice( 0, 5 ) == 'data-' ) 1515 if ( keepDataAttrs && attName.slice( 0, 5 ) == 'data-' )
1511 continue; 1516 continue;
1512 1517
@@ -1515,7 +1520,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1515 } 1520 }
1516 1521
1517 for ( var styleName in styles ) { 1522 for ( var styleName in styles ) {
1518 // Full match style insist on having fully equivalence. (#5018) 1523 // Full match style insist on having fully equivalence. (http://dev.ckeditor.com/ticket/5018)
1519 if ( this._.definition.fullMatch && element.getStyle( styleName ) != normalizeProperty( styleName, styles[ styleName ], true ) ) 1524 if ( this._.definition.fullMatch && element.getStyle( styleName ) != normalizeProperty( styleName, styles[ styleName ], true ) )
1520 continue; 1525 continue;
1521 1526
@@ -1649,7 +1654,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1649 // Create the element. 1654 // Create the element.
1650 el = new CKEDITOR.dom.element( elementName, targetDocument ); 1655 el = new CKEDITOR.dom.element( elementName, targetDocument );
1651 1656
1652 // #6226: attributes should be copied before the new ones are applied 1657 // http://dev.ckeditor.com/ticket/6226: attributes should be copied before the new ones are applied
1653 if ( element ) 1658 if ( element )
1654 element.copyAttributes( el ); 1659 element.copyAttributes( el );
1655 1660
@@ -1797,7 +1802,7 @@ CKEDITOR.STYLE_OBJECT = 3;
1797 // @returns {Boolean} 1802 // @returns {Boolean}
1798 function compareCssText( source, target ) { 1803 function compareCssText( source, target ) {
1799 function filter( string, propertyName ) { 1804 function filter( string, propertyName ) {
1800 // In case of font-families we'll skip quotes. (#10750) 1805 // In case of font-families we'll skip quotes. (http://dev.ckeditor.com/ticket/10750)
1801 return propertyName.toLowerCase() == 'font-family' ? string.replace( /["']/g, '' ) : string; 1806 return propertyName.toLowerCase() == 'font-family' ? string.replace( /["']/g, '' ) : string;
1802 } 1807 }
1803 1808
@@ -1824,13 +1829,25 @@ CKEDITOR.STYLE_OBJECT = 3;
1824 var doc = selection.document, 1829 var doc = selection.document,
1825 ranges = selection.getRanges(), 1830 ranges = selection.getRanges(),
1826 func = remove ? this.removeFromRange : this.applyToRange, 1831 func = remove ? this.removeFromRange : this.applyToRange,
1827 range; 1832 originalRanges,
1833 range,
1834 i;
1835
1836 // In case of fake table selection, we would like to apply all styles and then select
1837 // the original ranges. Otherwise browsers would complain about discontiguous selection.
1838 if ( selection.isFake && selection.isInTable() ) {
1839 originalRanges = [];
1840
1841 for ( i = 0; i < ranges.length; i++ ) {
1842 originalRanges.push( ranges[ i ].clone() );
1843 }
1844 }
1828 1845
1829 var iterator = ranges.createIterator(); 1846 var iterator = ranges.createIterator();
1830 while ( ( range = iterator.getNextRange() ) ) 1847 while ( ( range = iterator.getNextRange() ) )
1831 func.call( this, range, editor ); 1848 func.call( this, range, editor );
1832 1849
1833 selection.selectRanges( ranges ); 1850 selection.selectRanges( originalRanges || ranges );
1834 doc.removeCustomData( 'doc_processing_style' ); 1851 doc.removeCustomData( 'doc_processing_style' );
1835 } 1852 }
1836} )(); 1853} )();
@@ -1901,7 +1918,7 @@ CKEDITOR.styleCommand.prototype.exec = function( editor ) {
1901 */ 1918 */
1902CKEDITOR.stylesSet = new CKEDITOR.resourceManager( '', 'stylesSet' ); 1919CKEDITOR.stylesSet = new CKEDITOR.resourceManager( '', 'stylesSet' );
1903 1920
1904// Backward compatibility (#5025). 1921// Backward compatibility (http://dev.ckeditor.com/ticket/5025).
1905CKEDITOR.addStylesSet = CKEDITOR.tools.bind( CKEDITOR.stylesSet.add, CKEDITOR.stylesSet ); 1922CKEDITOR.addStylesSet = CKEDITOR.tools.bind( CKEDITOR.stylesSet.add, CKEDITOR.stylesSet );
1906CKEDITOR.loadStylesSet = function( name, url, callback ) { 1923CKEDITOR.loadStylesSet = function( name, url, callback ) {
1907 CKEDITOR.stylesSet.addExternal( name, url, '' ); 1924 CKEDITOR.stylesSet.addExternal( name, url, '' );
@@ -2004,7 +2021,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, {
2004 return; 2021 return;
2005 } 2022 }
2006 2023
2007 // #5352 Allow to define the styles directly in the config object 2024 // http://dev.ckeditor.com/ticket/5352 Allow to define the styles directly in the config object
2008 if ( configStyleSet instanceof Array ) { 2025 if ( configStyleSet instanceof Array ) {
2009 editor._.stylesDefinitions = configStyleSet; 2026 editor._.stylesDefinitions = configStyleSet;
2010 callback( configStyleSet ); 2027 callback( configStyleSet );
diff --git a/sources/core/template.js b/sources/core/template.js
index 2b9e932..a627c34 100644
--- a/sources/core/template.js
+++ b/sources/core/template.js
@@ -9,11 +9,7 @@
9 */ 9 */
10 10
11( function() { 11( function() {
12 var cache = {}, 12 var rePlaceholder = /{([^}]+)}/g;
13 rePlaceholder = /{([^}]+)}/g,
14 reEscapableChars = /([\\'])/g,
15 reNewLine = /\n/g,
16 reCarriageReturn = /\r/g;
17 13
18 /** 14 /**
19 * Lightweight template used to build the output string from variables. 15 * Lightweight template used to build the output string from variables.
@@ -27,42 +23,35 @@
27 * @param {String} source The template source. 23 * @param {String} source The template source.
28 */ 24 */
29 CKEDITOR.template = function( source ) { 25 CKEDITOR.template = function( source ) {
30 // Builds an optimized function body for the output() method, focused on performance. 26 /**
31 // For example, if we have this "source": 27 * The current template source.
32 // '<div style="{style}">{editorName}</div>' 28 *
33 // ... the resulting function body will be (apart from the "buffer" handling): 29 * @readonly
34 // return [ '<div style="', data['style'] == undefined ? '{style}' : data['style'], '">', data['editorName'] == undefined ? '{editorName}' : data['editorName'], '</div>' ].join(''); 30 * @member CKEDITOR.template
31 * @property {String}
32 */
33 this.source = String( source );
34 };
35 35
36 // Try to read from the cache. 36 /**
37 if ( cache[ source ] ) 37 * Processes the template, filling its variables with the provided data.
38 this.output = cache[ source ]; 38 *
39 else { 39 * @method
40 var fn = source 40 * @member CKEDITOR.template
41 // Escape chars like slash "\" or single quote "'". 41 * @param {Object} data An object containing properties whose values will be
42 .replace( reEscapableChars, '\\$1' ) 42 * used to fill the template variables. The property names must match the
43 .replace( reNewLine, '\\n' ) 43 * template variables names. Variables without matching properties will be
44 .replace( reCarriageReturn, '\\r' ) 44 * kept untouched.
45 // Inject the template keys replacement. 45 * @param {Array} [buffer] An array that the output data will be pushed into.
46 .replace( rePlaceholder, function( m, key ) { 46 * The number of entries appended to the array is unknown.
47 return "',data['" + key + "']==undefined?'{" + key + "}':data['" + key + "'],'"; 47 * @returns {String/Number} If `buffer` has not been provided, the processed
48 } ); 48 * template output data; otherwise the new length of `buffer`.
49 */
50 CKEDITOR.template.prototype.output = function( data, buffer ) {
51 var output = this.source.replace( rePlaceholder, function( fullMatch, dataKey ) {
52 return data[ dataKey ] !== undefined ? data[ dataKey ] : fullMatch;
53 } );
49 54
50 fn = "return buffer?buffer.push('" + fn + "'):['" + fn + "'].join('');"; 55 return buffer ? buffer.push( output ) : output;
51 this.output = cache[ source ] = Function( 'data', 'buffer', fn );
52 }
53 }; 56 };
54} )(); 57} )();
55
56/**
57 * Processes the template, filling its variables with the provided data.
58 *
59 * @method output
60 * @param {Object} data An object containing properties which values will be
61 * used to fill the template variables. The property names must match the
62 * template variables names. Variables without matching properties will be
63 * kept untouched.
64 * @param {Array} [buffer] An array into which the output data will be pushed into.
65 * The number of entries appended to the array is unknown.
66 * @returns {String/Number} If `buffer` has not been provided, the processed
67 * template output data, otherwise the new length of `buffer`.
68 */
diff --git a/sources/core/tools.js b/sources/core/tools.js
index 7e0083f..a4b736d 100644
--- a/sources/core/tools.js
+++ b/sources/core/tools.js
@@ -1021,7 +1021,7 @@
1021 styleText = CKEDITOR.tools.normalizeHex( CKEDITOR.tools.convertRgbToHex( styleText ) ); 1021 styleText = CKEDITOR.tools.normalizeHex( CKEDITOR.tools.convertRgbToHex( styleText ) );
1022 } 1022 }
1023 1023
1024 // IE will leave a single semicolon when failed to parse the style text. (#3891) 1024 // IE will leave a single semicolon when failed to parse the style text. (http://dev.ckeditor.com/ticket/3891)
1025 if ( !styleText || styleText == ';' ) 1025 if ( !styleText || styleText == ';' )
1026 return retval; 1026 return retval;
1027 1027
@@ -1463,6 +1463,37 @@
1463 }, 1463 },
1464 1464
1465 /** 1465 /**
1466 * Detects which mouse button generated a given DOM event.
1467 *
1468 * @since 4.7.3
1469 * @param {CKEDITOR.dom.event} evt DOM event.
1470 * @returns {Number|Boolean} Returns a number indicating the mouse button or `false`
1471 * if the mouse button cannot be determined.
1472 */
1473 getMouseButton: function( evt ) {
1474 var evtData = evt.data,
1475 domEvent = evtData && evtData.$;
1476
1477 if ( !( evtData && domEvent ) ) {
1478 // Added in case when there's no data available. That's the case in some unit test in built version which
1479 // mock event but doesn't put data object.
1480 return false;
1481 }
1482
1483 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
1484 if ( domEvent.button === 4 ) {
1485 return CKEDITOR.MOUSE_BUTTON_MIDDLE;
1486 } else if ( domEvent.button === 1 ) {
1487 return CKEDITOR.MOUSE_BUTTON_LEFT;
1488 } else {
1489 return CKEDITOR.MOUSE_BUTTON_RIGHT;
1490 }
1491 }
1492
1493 return domEvent.button;
1494 },
1495
1496 /**
1466 * A set of functions for operations on styles. 1497 * A set of functions for operations on styles.
1467 * 1498 *
1468 * @property {CKEDITOR.tools.style} 1499 * @property {CKEDITOR.tools.style}
@@ -1627,6 +1658,21 @@
1627 yellowgreen: '#9ACD32' 1658 yellowgreen: '#9ACD32'
1628 }, 1659 },
1629 1660
1661 _borderStyle: [
1662 'none',
1663 'hidden',
1664 'dotted',
1665 'dashed',
1666 'solid',
1667 'double',
1668 'groove',
1669 'ridge',
1670 'inset',
1671 'outset'
1672 ],
1673
1674 _widthRegExp: /^(thin|medium|thick|[\+-]?\d+(\.\d+)?[a-z%]+|[\+-]?0+(\.0+)?|\.\d+[a-z%]+)$/,
1675
1630 _rgbaRegExp: /rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(?:,\s*[0-9.]+\s*)?\)/gi, 1676 _rgbaRegExp: /rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(?:,\s*[0-9.]+\s*)?\)/gi,
1631 1677
1632 _hslaRegExp: /hsla?\(\s*[0-9.]+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[0-9.]+\s*)?\)/gi, 1678 _hslaRegExp: /hsla?\(\s*[0-9.]+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[0-9.]+\s*)?\)/gi,
@@ -1647,10 +1693,8 @@
1647 * @member CKEDITOR.tools.style.parse 1693 * @member CKEDITOR.tools.style.parse
1648 */ 1694 */
1649 background: function( value ) { 1695 background: function( value ) {
1650 var ret = [], 1696 var ret = {},
1651 colors = []; 1697 colors = this._findColor( value );
1652
1653 colors = this._findColor( value );
1654 1698
1655 if ( colors.length ) { 1699 if ( colors.length ) {
1656 ret.color = colors[ 0 ]; 1700 ret.color = colors[ 0 ];
@@ -1715,6 +1759,51 @@
1715 }, 1759 },
1716 1760
1717 /** 1761 /**
1762 * Parses the `border` CSS property shorthand format.
1763 * This CSS property does not support inheritance (https://www.w3.org/TR/css3-background/#the-border-shorthands).
1764 *
1765 * console.log( CKEDITOR.tools.style.parse.border( '3px solid #ffeedd' ) );
1766 * // Logs: { width: "3px", style: "solid", color: "#ffeedd" }
1767 *
1768 * @param {String} value The `border` property value.
1769 * @returns {Object}
1770 * @returns {String} return.width The border-width attribute.
1771 * @returns {String} return.style The border-style attribute.
1772 * @returns {String} return.color The border-color attribute.
1773 * @member CKEDITOR.tools.style.parse
1774 */
1775 border: function( value ) {
1776 var ret = {},
1777 input = value.split( /\s+/ );
1778
1779 CKEDITOR.tools.array.forEach( input, function( val ) {
1780 if ( !ret.color ) {
1781 var parseColor = CKEDITOR.tools.style.parse._findColor( val );
1782 if ( parseColor.length ) {
1783 ret.color = parseColor[ 0 ];
1784 return;
1785 }
1786 }
1787
1788 if ( !ret.style ) {
1789 if ( CKEDITOR.tools.indexOf( CKEDITOR.tools.style.parse._borderStyle, val ) !== -1 ) {
1790 ret.style = val;
1791 return;
1792 }
1793 }
1794
1795 if ( !ret.width ) {
1796 if ( CKEDITOR.tools.style.parse._widthRegExp.test( val ) ) {
1797 ret.width = val;
1798 return;
1799 }
1800 }
1801
1802 } );
1803 return ret;
1804 },
1805
1806 /**
1718 * Searches the `value` for any CSS color occurrences and returns it. 1807 * Searches the `value` for any CSS color occurrences and returns it.
1719 * 1808 *
1720 * @private 1809 * @private
@@ -1846,6 +1935,39 @@
1846 } 1935 }
1847 return acc; 1936 return acc;
1848 } 1937 }
1938 },
1939
1940 /**
1941 * A set of object helpers.
1942 *
1943 * @property {CKEDITOR.tools.object}
1944 * @member CKEDITOR.tools
1945 */
1946 object: {
1947 /**
1948 * Returns the first key from `obj` which has a given `value`.
1949 *
1950 * @param {Object} obj An object whose `key` is looked for.
1951 * @param {Mixed} value An object's `value` to be looked for.
1952 * @returns {String/null} Matched `key` or `null` if not found.
1953 * @member CKEDITOR.tools.object
1954 */
1955
1956 findKey: function( obj, value ) {
1957 if ( typeof obj !== 'object' ) {
1958 return null;
1959 }
1960
1961 var key;
1962
1963 for ( key in obj ) {
1964 if ( obj[ key ] === value ) {
1965 return key;
1966 }
1967 }
1968
1969 return null;
1970 }
1849 } 1971 }
1850 }; 1972 };
1851 1973
@@ -1889,7 +2011,35 @@
1889 */ 2011 */
1890 CKEDITOR.tools.array.isArray = CKEDITOR.tools.isArray; 2012 CKEDITOR.tools.array.isArray = CKEDITOR.tools.isArray;
1891 2013
2014 /**
2015 * Left mouse button.
2016 *
2017 * @since 4.7.3
2018 * @readonly
2019 * @property {Number} [=0]
2020 * @member CKEDITOR
2021 */
2022 CKEDITOR.MOUSE_BUTTON_LEFT = 0;
1892 2023
2024 /**
2025 * Middle mouse button.
2026 *
2027 * @since 4.7.3
2028 * @readonly
2029 * @property {Number} [=1]
2030 * @member CKEDITOR
2031 */
2032 CKEDITOR.MOUSE_BUTTON_MIDDLE = 1;
2033
2034 /**
2035 * Right mouse button.
2036 *
2037 * @since 4.7.3
2038 * @readonly
2039 * @property {Number} [=2]
2040 * @member CKEDITOR
2041 */
2042 CKEDITOR.MOUSE_BUTTON_RIGHT = 2;
1893 2043
1894 /** 2044 /**
1895 * The namespace containing functions to work on CSS properties. 2045 * The namespace containing functions to work on CSS properties.
@@ -1911,6 +2061,13 @@
1911 * @since 4.6.1 2061 * @since 4.6.1
1912 * @class CKEDITOR.tools.array 2062 * @class CKEDITOR.tools.array
1913 */ 2063 */
2064
2065 /**
2066 * The namespace with helper functions and polyfills for objects.
2067 *
2068 * @since 4.7.1
2069 * @class CKEDITOR.tools.object
2070 */
1914} )(); 2071} )();
1915 2072
1916// PACKAGER_RENAME( CKEDITOR.tools ) 2073// PACKAGER_RENAME( CKEDITOR.tools )
diff --git a/sources/lang/af.js b/sources/lang/af.js
index 925dc4a..ea941be 100644
--- a/sources/lang/af.js
+++ b/sources/lang/af.js
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'af' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Backspace',
103 13: 'Enter', // MISSING 103 13: 'Enter',
104 16: 'Shift', // MISSING 104 16: 'Skuif',
105 17: 'Ctrl', 105 17: 'Ctrl',
106 18: 'Alt', 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Spasie',
108 35: 'Einde', 108 35: 'Einde',
109 36: 'Tuis', 109 36: 'Tuis',
110 46: 'Verwyder', 110 46: 'Verwyder',
111 224: 'Command' // MISSING 111 224: 'Bevel'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Sleutel kombenasie'
116 } 116 }
117}; 117};
diff --git a/sources/lang/cs.js b/sources/lang/cs.js
index b76bee7..b5cf226 100644
--- a/sources/lang/cs.js
+++ b/sources/lang/cs.js
@@ -104,14 +104,14 @@ CKEDITOR.lang[ 'cs' ] = {
104 16: 'Shift', 104 16: 'Shift',
105 17: 'Ctrl', 105 17: 'Ctrl',
106 18: 'Alt', 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Mezerník',
108 35: 'Konec', 108 35: 'Konec',
109 36: 'Domů', 109 36: 'Domů',
110 46: 'Smazat', 110 46: 'Smazat',
111 224: 'Command' // MISSING 111 224: 'Command'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Klávesová zkratka'
116 } 116 }
117}; 117};
diff --git a/sources/lang/de.js b/sources/lang/de.js
index cf1bc09..441179a 100644
--- a/sources/lang/de.js
+++ b/sources/lang/de.js
@@ -63,7 +63,7 @@ CKEDITOR.lang[ 'de' ] = {
63 generalTab: 'Allgemein', 63 generalTab: 'Allgemein',
64 advancedTab: 'Erweitert', 64 advancedTab: 'Erweitert',
65 validateNumberFailed: 'Dieser Wert ist keine Nummer.', 65 validateNumberFailed: 'Dieser Wert ist keine Nummer.',
66 confirmNewPage: 'Alle nicht gespeicherten Änderungen gehen verlohren. Sind Sie sicher die neue Seite zu laden?', 66 confirmNewPage: 'Alle nicht gespeicherten Änderungen gehen verloren. Sind Sie sicher die neue Seite zu laden?',
67 confirmCancel: 'Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schließen?', 67 confirmCancel: 'Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schließen?',
68 options: 'Optionen', 68 options: 'Optionen',
69 target: 'Zielseite', 69 target: 'Zielseite',
diff --git a/sources/lang/el.js b/sources/lang/el.js
index 445c43d..635ce36 100644
--- a/sources/lang/el.js
+++ b/sources/lang/el.js
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'el' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Backspace',
103 13: 'Enter', // MISSING 103 13: 'Enter',
104 16: 'Shift', // MISSING 104 16: 'Shift',
105 17: 'Ctrl', // MISSING 105 17: 'Ctrl',
106 18: 'Alt', // MISSING 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Space', // MISSING
108 35: 'End', // MISSING 108 35: 'End',
109 36: 'Home', // MISSING 109 36: 'Home',
110 46: 'Delete', // MISSING 110 46: 'Delete',
111 224: 'Command' // MISSING 111 224: 'Command' // MISSING
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Συντόμευση πληκτρολογίου'
116 } 116 }
117}; 117};
diff --git a/sources/lang/eo.js b/sources/lang/eo.js
index f270dfc..4ea1b84 100644
--- a/sources/lang/eo.js
+++ b/sources/lang/eo.js
@@ -104,14 +104,14 @@ CKEDITOR.lang[ 'eo' ] = {
104 16: 'Registrumo', 104 16: 'Registrumo',
105 17: 'Stirklavo', 105 17: 'Stirklavo',
106 18: 'Alt-klavo', 106 18: 'Alt-klavo',
107 32: 'Space', // MISSING 107 32: 'Spaco',
108 35: 'Fino', 108 35: 'Fino',
109 36: 'Hejmo', 109 36: 'Hejmo',
110 46: 'Forigi', 110 46: 'Forigi',
111 224: 'Command' // MISSING 111 224: 'Komando'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Fulmoklavo'
116 } 116 }
117}; 117};
diff --git a/sources/lang/es-mx.js b/sources/lang/es-mx.js
new file mode 100644
index 0000000..3b8c1c3
--- /dev/null
+++ b/sources/lang/es-mx.js
@@ -0,0 +1,116 @@
1/**
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
8*/
9
10/**#@+
11 @type String
12 @example
13*/
14
15/**
16 * Contains the dictionary of language entries.
17 * @namespace
18 */
19CKEDITOR.lang[ 'es-mx' ] = {
20 // ARIA description.
21 editor: 'Editor de texto enriquecido',
22 editorPanel: 'Panel del editor de texto',
23
24 // Common messages and labels.
25 common: {
26 // Screenreader titles. Please note that screenreaders are not always capable
27 // of reading non-English words. So be careful while translating it.
28 editorHelp: 'Presiona ALT + 0 para ayuda',
29
30 browseServer: 'Examinar servidor',
31 url: 'URL',
32 protocol: 'Protocolo',
33 upload: 'Subir',
34 uploadSubmit: 'Enviar al servidor',
35 image: 'Imagen',
36 flash: 'Flash',
37 form: 'Formulario',
38 checkbox: 'Casilla de verificación',
39 radio: 'Botón de opción',
40 textField: 'Campo de texto',
41 textarea: 'Área de texto',
42 hiddenField: 'Campo oculto',
43 button: 'Botón',
44 select: 'Campo de selección',
45 imageButton: 'Botón de imagen',
46 notSet: '<not set>',
47 id: 'Id',
48 name: 'Nombre',
49 langDir: 'Dirección de idiomas',
50 langDirLtr: 'Izquierda a derecha (LTR)',
51 langDirRtl: 'Derecha a izquierda (RTL)',
52 langCode: 'Código de lenguaje',
53 longDescr: 'URL descripción larga',
54 cssClass: 'Clases de hoja de estilo',
55 advisoryTitle: 'Título del anuncio',
56 cssStyle: 'Estilo',
57 ok: 'OK',
58 cancel: 'Cancelar',
59 close: 'Cerrar',
60 preview: 'Vista previa',
61 resize: 'Redimensionar',
62 generalTab: 'General',
63 advancedTab: 'Avanzada',
64 validateNumberFailed: 'Este valor no es un número.',
65 confirmNewPage: 'Se perderán todos los cambios no guardados en este contenido. ¿Seguro que quieres cargar nueva página?',
66 confirmCancel: 'Ha cambiado algunas opciones. ¿Está seguro de que desea cerrar la ventana de diálogo?',
67 options: 'Opciones',
68 target: 'Objetivo',
69 targetNew: 'Nueva ventana (_blank)',
70 targetTop: 'Ventana superior (_top)',
71 targetSelf: 'Misma ventana (_self)',
72 targetParent: 'Ventana principal (_parent)',
73 langDirLTR: 'Izquierda a Derecha (LTR)',
74 langDirRTL: 'Derecha a Izquierda (RTL)',
75 styles: 'Estilo',
76 cssClasses: 'Clases de hojas de estilo',
77 width: 'Ancho',
78 height: 'Alto',
79 align: 'Alineación',
80 alignLeft: 'Izquierda',
81 alignRight: 'Derecha',
82 alignCenter: 'Centrado',
83 alignJustify: 'Justificado',
84 alignTop: 'Arriba',
85 alignMiddle: 'En medio',
86 alignBottom: 'Abajo',
87 alignNone: 'Ninguno',
88 invalidValue: 'Valor inválido',
89 invalidHeight: 'La altura debe ser un número.',
90 invalidWidth: 'La anchura debe ser un número.',
91 invalidCssLength: 'El valor especificado para el campo "% 1" debe ser un número positivo con o sin una unidad de medida CSS válida (px, %, in, cm, mm, em, ex, pt, or pc).',
92 invalidHtmlLength: 'El valor especificado para el campo "% 1" debe ser un número positivo con o sin una unidad de medición HTML válida (px or %).',
93 invalidInlineStyle: 'El valor especificado para el estilo en línea debe constar de una o más tuplas con el formato de "nombre: valor", separados por punto y coma',
94 cssLengthTooltip: 'Introduzca un número para un valor en píxeles o un número con una unidad CSS válida (px, %, in, cm, mm, em, ex, pt, or pc).',
95
96 // Put the voice-only part of the label in the span.
97 unavailable: '%1<span class="cke_accessibility">, no disponible</span>',
98
99 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
100 keyboard: {
101 8: 'Retroceso',
102 13: 'Intro',
103 16: 'Shift',
104 17: 'Ctrl',
105 18: 'Alt',
106 32: 'Espacio',
107 35: 'Fin',
108 36: 'Inicio',
109 46: 'Borrar',
110 224: 'Comando'
111 },
112
113 // Prepended to ARIA labels with shortcuts.
114 keyboardShortcut: 'Atajo de teclado'
115 }
116};
diff --git a/sources/lang/fr.js b/sources/lang/fr.js
index 95b2d41..5cd39b0 100644
--- a/sources/lang/fr.js
+++ b/sources/lang/fr.js
@@ -31,7 +31,7 @@ CKEDITOR.lang[ 'fr' ] = {
31 browseServer: 'Parcourir le serveur', 31 browseServer: 'Parcourir le serveur',
32 url: 'URL', 32 url: 'URL',
33 protocol: 'Protocole', 33 protocol: 'Protocole',
34 upload: 'Téléverser', 34 upload: 'Télécharger',
35 uploadSubmit: 'Envoyer sur le serveur', 35 uploadSubmit: 'Envoyer sur le serveur',
36 image: 'Image', 36 image: 'Image',
37 flash: 'Flash', 37 flash: 'Flash',
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'fr' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Retour arrière',
103 13: 'Entrée', 103 13: 'Entrée',
104 16: 'Majuscule', 104 16: 'Majuscule',
105 17: 'Ctrl', 105 17: 'Ctrl',
106 18: 'Alt', 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Espace',
108 35: 'Fin', 108 35: 'Fin',
109 36: 'Origine', 109 36: 'Origine',
110 46: 'Supprimer', 110 46: 'Supprimer',
111 224: 'Command' // MISSING 111 224: 'Commande'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Raccourci clavier'
116 } 116 }
117}; 117};
diff --git a/sources/lang/gl.js b/sources/lang/gl.js
index 331a21b..092db98 100644
--- a/sources/lang/gl.js
+++ b/sources/lang/gl.js
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'gl' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Ir atrás',
103 13: 'Intro', 103 13: 'Intro',
104 16: 'Maiús', 104 16: 'Maiús',
105 17: 'Ctrl', 105 17: 'Ctrl',
106 18: 'Alt', 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Espazo',
108 35: 'Fin', 108 35: 'Fin',
109 36: 'Inicio', 109 36: 'Inicio',
110 46: 'Supr', 110 46: 'Supr',
111 224: 'Command' // MISSING 111 224: 'Orde'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Atallo de teclado'
116 } 116 }
117}; 117};
diff --git a/sources/lang/hr.js b/sources/lang/hr.js
index d12a338..7bf089e 100644
--- a/sources/lang/hr.js
+++ b/sources/lang/hr.js
@@ -85,7 +85,7 @@ CKEDITOR.lang[ 'hr' ] = {
85 alignTop: 'Vrh', 85 alignTop: 'Vrh',
86 alignMiddle: 'Sredina', 86 alignMiddle: 'Sredina',
87 alignBottom: 'Dolje', 87 alignBottom: 'Dolje',
88 alignNone: 'None', // MISSING 88 alignNone: 'Bez poravnanja',
89 invalidValue: 'Neispravna vrijednost.', 89 invalidValue: 'Neispravna vrijednost.',
90 invalidHeight: 'Visina mora biti broj.', 90 invalidHeight: 'Visina mora biti broj.',
91 invalidWidth: 'Širina mora biti broj.', 91 invalidWidth: 'Širina mora biti broj.',
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'hr' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Backspace',
103 13: 'Enter', // MISSING 103 13: 'Enter',
104 16: 'Shift', // MISSING 104 16: 'Shift',
105 17: 'Ctrl', // MISSING 105 17: 'Ctrl',
106 18: 'Alt', // MISSING 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Space',
108 35: 'End', // MISSING 108 35: 'End',
109 36: 'Home', // MISSING 109 36: 'Home',
110 46: 'Delete', // MISSING 110 46: 'Delete',
111 224: 'Command' // MISSING 111 224: 'Command'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Prečica na tipkovnici'
116 } 116 }
117}; 117};
diff --git a/sources/lang/hu.js b/sources/lang/hu.js
index 0cd0d96..6f6e91e 100644
--- a/sources/lang/hu.js
+++ b/sources/lang/hu.js
@@ -85,7 +85,7 @@ CKEDITOR.lang[ 'hu' ] = {
85 alignTop: 'Tetejére', 85 alignTop: 'Tetejére',
86 alignMiddle: 'Középre', 86 alignMiddle: 'Középre',
87 alignBottom: 'Aljára', 87 alignBottom: 'Aljára',
88 alignNone: 'None', // MISSING 88 alignNone: 'Semmi',
89 invalidValue: 'Érvénytelen érték.', 89 invalidValue: 'Érvénytelen érték.',
90 invalidHeight: 'A magasság mezőbe csak számokat írhat.', 90 invalidHeight: 'A magasság mezőbe csak számokat írhat.',
91 invalidWidth: 'A szélesség mezőbe csak számokat írhat.', 91 invalidWidth: 'A szélesség mezőbe csak számokat írhat.',
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'hu' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Backspace',
103 13: 'Enter', // MISSING 103 13: 'Enter',
104 16: 'Shift', // MISSING 104 16: 'Shift',
105 17: 'Ctrl', // MISSING 105 17: 'Ctrl',
106 18: 'Alt', // MISSING 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Space',
108 35: 'End', // MISSING 108 35: 'End',
109 36: 'Home', // MISSING 109 36: 'Home',
110 46: 'Delete', // MISSING 110 46: 'Delete',
111 224: 'Command' // MISSING 111 224: 'Command'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: 'Gyorsbillent'
116 } 116 }
117}; 117};
diff --git a/sources/lang/ja.js b/sources/lang/ja.js
index 56b69f7..17dcefc 100644
--- a/sources/lang/ja.js
+++ b/sources/lang/ja.js
@@ -62,7 +62,7 @@ CKEDITOR.lang[ 'ja' ] = {
62 resize: 'ドラッグしてリサイズ', 62 resize: 'ドラッグしてリサイズ',
63 generalTab: '全般', 63 generalTab: '全般',
64 advancedTab: '高度な設定', 64 advancedTab: '高度な設定',
65 validateNumberFailed: '値が数ではありません', 65 validateNumberFailed: '値が数ではありません',
66 confirmNewPage: '変更内容を保存せず、 新しいページを開いてもよろしいでしょうか?', 66 confirmNewPage: '変更内容を保存せず、 新しいページを開いてもよろしいでしょうか?',
67 confirmCancel: 'オプション設定を変更しました。ダイアログを閉じてもよろしいでしょうか?', 67 confirmCancel: 'オプション設定を変更しました。ダイアログを閉じてもよろしいでしょうか?',
68 options: 'オプション', 68 options: 'オプション',
diff --git a/sources/lang/ko.js b/sources/lang/ko.js
index d08261d..fe575d9 100644
--- a/sources/lang/ko.js
+++ b/sources/lang/ko.js
@@ -28,7 +28,7 @@ CKEDITOR.lang[ 'ko' ] = {
28 // of reading non-English words. So be careful while translating it. 28 // of reading non-English words. So be careful while translating it.
29 editorHelp: '도움이 필요하면 ALT 0 을 누르세요', 29 editorHelp: '도움이 필요하면 ALT 0 을 누르세요',
30 30
31 browseServer: '서버 보기', 31 browseServer: '서버 탐색',
32 url: 'URL', 32 url: 'URL',
33 protocol: '프로토콜', 33 protocol: '프로토콜',
34 upload: '업로드', 34 upload: '업로드',
@@ -99,19 +99,19 @@ CKEDITOR.lang[ 'ko' ] = {
99 99
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: '백스페이스',
103 13: 'Enter', // MISSING 103 13: '엔터',
104 16: 'Shift', // MISSING 104 16: '시프트',
105 17: 'Ctrl', // MISSING 105 17: '컨트롤',
106 18: 'Alt', // MISSING 106 18: '알트',
107 32: 'Space', // MISSING 107 32: '간격',
108 35: 'End', // MISSING 108 35: '엔드',
109 36: 'Home', // MISSING 109 36: '',
110 46: 'Delete', // MISSING 110 46: '딜리트',
111 224: 'Command' // MISSING 111 224: '커맨드'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
115 keyboardShortcut: 'Keyboard shortcut' // MISSING 115 keyboardShortcut: '키보드 단축키'
116 } 116 }
117}; 117};
diff --git a/sources/lang/ku.js b/sources/lang/ku.js
index ec53e49..171059b 100644
--- a/sources/lang/ku.js
+++ b/sources/lang/ku.js
@@ -98,19 +98,19 @@ CKEDITOR.lang[ 'ku' ] = {
98 98
99 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 99 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
100 keyboard: { 100 keyboard: {
101 8: 'Backspace', // MISSING 101 8: 'Backspace',
102 13: 'Enter', // MISSING 102 13: 'Enter',
103 16: 'Shift', // MISSING 103 16: 'Shift',
104 17: 'Ctrl', // MISSING 104 17: 'Ctrl',
105 18: 'Alt', // MISSING 105 18: 'Alt',
106 32: 'Space', // MISSING 106 32: 'Space',
107 35: 'End', // MISSING 107 35: 'End',
108 36: 'Home', // MISSING 108 36: 'Home',
109 46: 'Delete', // MISSING 109 46: 'Delete',
110 224: 'Command' // MISSING 110 224: 'فەرمان'
111 }, 111 },
112 112
113 // Prepended to ARIA labels with shortcuts. 113 // Prepended to ARIA labels with shortcuts.
114 keyboardShortcut: 'Keyboard shortcut' // MISSING 114 keyboardShortcut: 'کورتبڕی تەختەکلیل'
115 } 115 }
116}; 116};
diff --git a/sources/lang/pt.js b/sources/lang/pt.js
index d5ae35e..cfc1ced 100644
--- a/sources/lang/pt.js
+++ b/sources/lang/pt.js
@@ -100,15 +100,15 @@ CKEDITOR.lang[ 'pt' ] = {
100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels. 100 // Keyboard keys translations used for creating shortcuts descriptions in tooltips, context menus and ARIA labels.
101 keyboard: { 101 keyboard: {
102 8: 'Backspace', // MISSING 102 8: 'Backspace', // MISSING
103 13: 'Enter', // MISSING 103 13: 'Enter',
104 16: 'Shift', 104 16: 'Shift',
105 17: 'Ctrl', 105 17: 'Ctrl',
106 18: 'Alt', 106 18: 'Alt',
107 32: 'Space', // MISSING 107 32: 'Espaço',
108 35: 'Fim', 108 35: 'Fim',
109 36: 'Entrada', 109 36: 'Entrada',
110 46: 'Eliminar', 110 46: 'Eliminar',
111 224: 'Command' // MISSING 111 224: 'Comando'
112 }, 112 },
113 113
114 // Prepended to ARIA labels with shortcuts. 114 // Prepended to ARIA labels with shortcuts.
diff --git a/sources/lang/uk.js b/sources/lang/uk.js
index baa78e6..3fbc52d 100644
--- a/sources/lang/uk.js
+++ b/sources/lang/uk.js
@@ -20,7 +20,7 @@
20CKEDITOR.lang[ 'uk' ] = { 20CKEDITOR.lang[ 'uk' ] = {
21 // ARIA description. 21 // ARIA description.
22 editor: 'Текстовий редактор', 22 editor: 'Текстовий редактор',
23 editorPanel: 'Панель текстового редактора', 23 editorPanel: 'Панель озширеного екстового редактора',
24 24
25 // Common messages and labels. 25 // Common messages and labels.
26 common: { 26 common: {
diff --git a/sources/plugins/a11yhelp/dialogs/a11yhelp.js b/sources/plugins/a11yhelp/dialogs/a11yhelp.js
index 73b930c..eb12d4c 100644
--- a/sources/plugins/a11yhelp/dialogs/a11yhelp.js
+++ b/sources/plugins/a11yhelp/dialogs/a11yhelp.js
@@ -77,7 +77,7 @@ CKEDITOR.dialog.add( 'a11yHelp', function( editor ) {
77 // Modifier keys override. 77 // Modifier keys override.
78 keyMap[ CKEDITOR.ALT ] = coreLang[ 18 ]; 78 keyMap[ CKEDITOR.ALT ] = coreLang[ 18 ];
79 keyMap[ CKEDITOR.SHIFT ] = coreLang[ 16 ]; 79 keyMap[ CKEDITOR.SHIFT ] = coreLang[ 16 ];
80 keyMap[ CKEDITOR.CTRL ] = coreLang[ 17 ]; 80 keyMap[ CKEDITOR.CTRL ] = CKEDITOR.env.mac ? coreLang[ 224 ] : coreLang[ 17 ];
81 81
82 // Sort in desc. 82 // Sort in desc.
83 var modifiers = [ CKEDITOR.ALT, CKEDITOR.SHIFT, CKEDITOR.CTRL ]; 83 var modifiers = [ CKEDITOR.ALT, CKEDITOR.SHIFT, CKEDITOR.CTRL ];
@@ -85,7 +85,6 @@ CKEDITOR.dialog.add( 'a11yHelp', function( editor ) {
85 function representKeyStroke( keystroke ) { 85 function representKeyStroke( keystroke ) {
86 var quotient, modifier, 86 var quotient, modifier,
87 presentation = []; 87 presentation = [];
88
89 for ( var i = 0; i < modifiers.length; i++ ) { 88 for ( var i = 0; i < modifiers.length; i++ ) {
90 modifier = modifiers[ i ]; 89 modifier = modifiers[ i ];
91 quotient = keystroke / modifiers[ i ]; 90 quotient = keystroke / modifiers[ i ];
@@ -100,23 +99,14 @@ CKEDITOR.dialog.add( 'a11yHelp', function( editor ) {
100 return presentation.join( '+' ); 99 return presentation.join( '+' );
101 } 100 }
102 101
103 var variablesPattern = /\$\{(.*?)\}/g; 102 var variablesPattern = /\$\{(.*?)\}/g,
104 103 replaceVariables = function( match, name ) {
105 var replaceVariables = ( function() { 104 var keystrokeCode = editor.getCommandKeystroke( name );
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 105
114 return function( match, name ) {
115 // Return the keystroke representation or leave match untouched 106 // Return the keystroke representation or leave match untouched
116 // if there's no keystroke for such command. 107 // if there's no keystroke for such command.
117 return keystrokesByName[ name ] ? representKeyStroke( keystrokesByName[ name ] ) : match; 108 return keystrokeCode ? representKeyStroke( keystrokeCode ) : match;
118 }; 109 };
119 } )();
120 110
121 // Create the help list directly from lang file entries. 111 // Create the help list directly from lang file entries.
122 function buildHelpContents() { 112 function buildHelpContents() {
@@ -137,13 +127,17 @@ CKEDITOR.dialog.add( 'a11yHelp', function( editor ) {
137 127
138 for ( var j = 0; j < itemsLength; j++ ) { 128 for ( var j = 0; j < itemsLength; j++ ) {
139 var item = items[ j ], 129 var item = items[ j ],
140 itemLegend = item.legend.replace( variablesPattern, replaceVariables ); 130 // (http://dev.ckeditor.com/ticket/16980) There should be a different hotkey shown in Commands on Edge browser.
131 itemLegend = CKEDITOR.env.edge && item.legendEdge ? item.legendEdge : item.legend;
141 132
142 // (#9765) If some commands haven't been replaced in the legend, 133 itemLegend = itemLegend.replace( variablesPattern, replaceVariables );
134
135 // (http://dev.ckeditor.com/ticket/9765) If some commands haven't been replaced in the legend,
143 // most likely their keystrokes are unavailable and we shouldn't include 136 // most likely their keystrokes are unavailable and we shouldn't include
144 // them in our help list. 137 // them in our help list.
145 if ( itemLegend.match( variablesPattern ) ) 138 if ( itemLegend.match( variablesPattern ) ) {
146 continue; 139 continue;
140 }
147 141
148 sectionHtml.push( itemTpl.replace( '%1', item.name ).replace( '%2', itemLegend ) ); 142 sectionHtml.push( itemTpl.replace( '%1', item.name ).replace( '%2', itemLegend ) );
149 } 143 }
@@ -179,7 +173,7 @@ CKEDITOR.dialog.add( 'a11yHelp', function( editor ) {
179 'overflow-y:auto;' + 173 'overflow-y:auto;' +
180 'overflow-x:hidden;' + 174 'overflow-x:hidden;' +
181 '}' + 175 '}' +
182 // Some adjustments are to be done for Quirks to work "properly" (#5757) 176 // Some adjustments are to be done for Quirks to work "properly" (http://dev.ckeditor.com/ticket/5757)
183 '.cke_browser_quirks .cke_accessibility_legend,' + 177 '.cke_browser_quirks .cke_accessibility_legend,' +
184 '{' + 178 '{' +
185 'height:390px' + 179 'height:390px' +
diff --git a/sources/plugins/a11yhelp/dialogs/lang/af.js b/sources/plugins/a11yhelp/dialogs/lang/af.js
index 7469bc1..f1062a9 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/af.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/af.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'af', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ar.js b/sources/plugins/a11yhelp/dialogs/lang/ar.js
index 5c316c7..870d60d 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ar.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ar.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ar', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/az.js b/sources/plugins/a11yhelp/dialogs/lang/az.js
index 9c04b65..bda91a4 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/az.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/az.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'az', {
79 { 79 {
80 name: 'Hərtərəfli Kömək', 80 name: 'Hərtərəfli Kömək',
81 legend: '${a11yHelp} basın' 81 legend: '${a11yHelp} basın'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/bg.js b/sources/plugins/a11yhelp/dialogs/lang/bg.js
index ce9cdd8..9a809ff 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/bg.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/bg.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'bg', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ca.js b/sources/plugins/a11yhelp/dialogs/lang/ca.js
index f415b90..5bbaced 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ca.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ca.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ca', {
79 { 79 {
80 name: 'Ajuda d\'accessibilitat', 80 name: 'Ajuda d\'accessibilitat',
81 legend: 'Premi ${a11yHelp}' 81 legend: 'Premi ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/cs.js b/sources/plugins/a11yhelp/dialogs/lang/cs.js
index 39e4d64..f792c46 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/cs.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/cs.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'cs', {
79 { 79 {
80 name: ' Nápověda přístupnosti', 80 name: ' Nápověda přístupnosti',
81 legend: 'Stiskněte ${a11yHelp}' 81 legend: 'Stiskněte ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/cy.js b/sources/plugins/a11yhelp/dialogs/lang/cy.js
index 3ac77cf..e0cc0ba 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/cy.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/cy.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'cy', {
79 { 79 {
80 name: 'Cymorth Hygyrchedd', 80 name: 'Cymorth Hygyrchedd',
81 legend: 'Pwyswch ${a11yHelp}' 81 legend: 'Pwyswch ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/da.js b/sources/plugins/a11yhelp/dialogs/lang/da.js
index f507bf0..ae21300 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/da.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/da.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'da', {
79 { 79 {
80 name: 'Tilgængelighedshjælp', 80 name: 'Tilgængelighedshjælp',
81 legend: 'Kilk ${a11yHelp}' 81 legend: 'Kilk ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/de-ch.js b/sources/plugins/a11yhelp/dialogs/lang/de-ch.js
index 8d26d73..206bbf6 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/de-ch.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/de-ch.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'de-ch', {
79 { 79 {
80 name: 'Eingabehilfen', 80 name: 'Eingabehilfen',
81 legend: 'Drücken Sie ${a11yHelp}' 81 legend: 'Drücken Sie ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/de.js b/sources/plugins/a11yhelp/dialogs/lang/de.js
index c74be37..5e798cb 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/de.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/de.js
@@ -18,7 +18,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'de', {
18 { 18 {
19 name: 'Editordialog', 19 name: 'Editordialog',
20 legend: 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 21 'Drücke innerhalb eines Dialogs TAB, um zum nächsten Element zu springen. Drücke SHIFT+TAB, um zum vorigen Element zu springen, drücke ENTER um das Formular im Dialog abzusenden, drücke ESC, um den Dialog zu schließen. Hat der Dialog mehrere Tabs, dann kannst du durch ALT+F10 die Tab-Liste aufrufen or mittels TAB als Teil der Dialog-Tab-Reihenfolge. Ist die Tab-Liste fokussiert, dann mithilfe der Pfeiltasten (LINKS und RECHTS) zwischen den Tabs gewechselt werden.'
22 }, 22 },
23 23
24 { 24 {
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'de', {
79 { 79 {
80 name: 'Eingabehilfen', 80 name: 'Eingabehilfen',
81 legend: 'Drücken Sie ${a11yHelp}' 81 legend: 'Drücken Sie ${a11yHelp}'
82 },
83 {
84 name: 'Einfügen als unformatierter Text. ',
85 legend: 'Drücke ${pastetext}',
86 legendEdge: 'Drücke ${pastetext} und anschließend ${paste}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/el.js b/sources/plugins/a11yhelp/dialogs/lang/el.js
index 11febeb..f3e598f 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/el.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/el.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'el', {
79 { 79 {
80 name: 'Βοήθεια Προσβασιμότητας', 80 name: 'Βοήθεια Προσβασιμότητας',
81 legend: 'Πατήστε ${a11yHelp}' 81 legend: 'Πατήστε ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/en-gb.js b/sources/plugins/a11yhelp/dialogs/lang/en-gb.js
index 98bf636..6fa41b3 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/en-gb.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/en-gb.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'en-gb', {
79 { 79 {
80 name: ' Accessibility Help', 80 name: ' Accessibility Help',
81 legend: 'Press ${a11yHelp}' 81 legend: 'Press ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/en.js b/sources/plugins/a11yhelp/dialogs/lang/en.js
index fee0b4e..a9ea5bd 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/en.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/en.js
@@ -98,6 +98,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'en', {
98 { 98 {
99 name: ' Accessibility Help', 99 name: ' Accessibility Help',
100 legend: 'Press ${a11yHelp}' 100 legend: 'Press ${a11yHelp}'
101 },
102 {
103 name: ' Paste as plain text',
104 legend: 'Press ${pastetext}',
105 legendEdge: 'Press ${pastetext}, followed by ${paste}'
101 } 106 }
102 ] 107 ]
103 } 108 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/eo.js b/sources/plugins/a11yhelp/dialogs/lang/eo.js
index c2bc106..061e7b5 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/eo.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/eo.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'eo', {
79 { 79 {
80 name: 'Helpilo pri atingeblo', 80 name: 'Helpilo pri atingeblo',
81 legend: 'Premu ${a11yHelp}' 81 legend: 'Premu ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/es-mx.js b/sources/plugins/a11yhelp/dialogs/lang/es-mx.js
new file mode 100644
index 0000000..7ef6a4c
--- /dev/null
+++ b/sources/plugins/a11yhelp/dialogs/lang/es-mx.js
@@ -0,0 +1,145 @@
1/**
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-mx', {
7 title: 'Instrucciones de accesibilidad',
8 contents: 'Contenidos de ayuda. Para cerrar este cuadro de diálogo presione ESC.',
9 legend: [
10 {
11 name: 'General',
12 items: [
13 {
14 name: 'Barra de herramientas del editor',
15 legend: 'Presione ${toolbarFocus} para navegar a la barra de herramientas. Desplácese al grupo de barras de herramientas siguiente y anterior con SHIFT + TAB. Desplácese al botón siguiente y anterior de la barra de herramientas con FLECHA DERECHA o FLECHA IZQUIERDA. Presione SPACE o ENTER para activar el botón de la barra de herramientas.'
16 },
17
18 {
19 name: 'Editor de diálogo',
20 legend:
21 'Dentro de un cuadro de diálogo, pulse TAB para desplazarse hasta el siguiente elemento de diálogo, pulse MAYÚS + TAB para desplazarse al elemento de diálogo anterior, pulse ENTER para enviar el diálogo, pulse ESC para cancelar el diálogo. Cuando un cuadro de diálogo tiene varias pestañas, se puede acceder a la lista de pestañas con ALT + F10 o con TAB como parte del orden de tabulación del diálogo. Con la lista de tabuladores enfocada, mueva a la pestaña siguiente y anterior con las flechas DERECHA y IZQUIERDA, respectivamente.'
22 },
23
24 {
25 name: 'Menú contextual del editor',
26 legend: 'Presione ${contextMenu} o CLAVE DE APLICACIÓN para abrir el menú contextual. A continuación, vaya a la siguiente opción del menú con TAB o DOWN ARROW. Desplácese a la opción anterior con SHIFT + TAB o FLECHA ARRIBA. Presione SPACE o ENTER para seleccionar la opción del menú. Abra el submenú de la opción actual con ESPACIO o ENTER o FLECHA DERECHA. Vuelva al elemento de menú principal con ESC o FLECHA IZQUIERDA. Cerrar el menú contextual con ESC.'
27 },
28
29 {
30 name: 'Editor de cuadro de lista',
31 legend: 'Dentro de un cuadro de lista, mueva al siguiente elemento de lista con TAB O FLECHA ABAJO. Mueva al elemento anterior de la lista con MAYÚS + TAB o FLECHA ARRIBA. Presione SPACE o ENTER para seleccionar la opción de lista. Presione ESC para cerrar el cuadro de lista.'
32 },
33
34 {
35 name: 'Barra de ruta del elemento del editor',
36 legend: 'Presione ${elementsPathFocus} para navegar a la barra de ruta de elementos. Desplácese al siguiente botón de elemento con TAB o FLECHA DERECHA. Desplácese al botón anterior con SHIFT + TAB o FLECHA IZQUIERDA. Presione SPACE 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 cursiva',
57 legend: 'Presiona {italic}'
58 },
59 {
60 name: 'Comando subrayado',
61 legend: 'Presiona ${underline}'
62 },
63 {
64 name: 'Comando enlace',
65 legend: 'Presiona ${link}'
66 },
67 {
68 name: 'Comando colapsar barra de herramientas',
69 legend: 'Presiona ${toolbarCollapse}'
70 },
71 {
72 name: 'Acceda al comando de espacio de enfoque anterior',
73 legend: 'Presione ${accessPreviousSpace} para acceder al espacio de enfoque inaccesible más cercano antes del cursor, por ejemplo: dos elementos HR adyacentes. Repita la combinación de teclas para alcanzar los espacios de enfoque distantes.'
74 },
75 {
76 name: 'Acceder al siguiente comando de espacio de enfoque',
77 legend: 'Pulse ${accessNextSpace} para acceder al espacio de enfoque más cercano inaccesible después del cursor, por ejemplo: dos elementos HR adyacentes. Repita la combinación de teclas para alcanzar los espacios de enfoque distantes.'
78 },
79 {
80 name: 'Ayuda de accesibilidad',
81 legend: 'Presiona ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
87 }
88 ]
89 }
90 ],
91 tab: 'Tabulador',
92 pause: 'Pausa',
93 capslock: 'Mayúsculas',
94 escape: 'Escape',
95 pageUp: 'Página arriba',
96 pageDown: 'Página abajo',
97 leftArrow: 'Flecha izquierda',
98 upArrow: 'Flecha arriba',
99 rightArrow: 'Flecha derecha',
100 downArrow: 'Flecha abajo',
101 insert: 'Insertar',
102 leftWindowKey: 'Tecla izquierda de Windows',
103 rightWindowKey: 'Tecla derecha de Windows',
104 selectKey: 'Tecla de selección',
105 numpad0: 'Teclado numérico 0',
106 numpad1: 'Teclado numérico 1',
107 numpad2: 'Teclado numérico 2',
108 numpad3: 'Teclado numérico 3',
109 numpad4: 'Teclado numérico 4',
110 numpad5: 'Teclado numérico 5',
111 numpad6: 'Teclado numérico 6',
112 numpad7: 'Teclado numérico 7',
113 numpad8: 'Teclado numérico 8',
114 numpad9: 'Teclado numérico 9',
115 multiply: 'Multiplicar',
116 add: 'Sumar',
117 subtract: 'Restar',
118 decimalPoint: 'Punto decimal',
119 divide: 'Dividir',
120 f1: 'F1',
121 f2: 'F2',
122 f3: 'F3',
123 f4: 'F4',
124 f5: 'F5',
125 f6: 'F6',
126 f7: 'F7',
127 f8: 'F8',
128 f9: 'F9',
129 f10: 'F10',
130 f11: 'F11',
131 f12: 'F12',
132 numLock: 'Números',
133 scrollLock: 'Bloqueo de desplazamiento',
134 semiColon: 'punto y coma',
135 equalSign: 'Signo igual',
136 comma: 'Coma',
137 dash: 'Guión',
138 period: 'Espacio',
139 forwardSlash: 'Diagonal',
140 graveAccent: 'Acento grave',
141 openBracket: 'Abrir paréntesis',
142 backSlash: 'Diagonal invertida',
143 closeBracket: 'Cerrar paréntesis',
144 singleQuote: 'Comillas simple'
145} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/es.js b/sources/plugins/a11yhelp/dialogs/lang/es.js
index b1eaa20..d3b29a2 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/es.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/es.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'es', {
79 { 79 {
80 name: 'Ayuda de Accesibilidad', 80 name: 'Ayuda de Accesibilidad',
81 legend: 'Presiona ${a11yHelp}' 81 legend: 'Presiona ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/et.js b/sources/plugins/a11yhelp/dialogs/lang/et.js
index 0146089..3f6524b 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/et.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/et.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'et', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/eu.js b/sources/plugins/a11yhelp/dialogs/lang/eu.js
index b53748f..80c60db 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/eu.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/eu.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'eu', {
79 { 79 {
80 name: 'Erabilerraztasunaren laguntza', 80 name: 'Erabilerraztasunaren laguntza',
81 legend: 'Sakatu ${a11yHelp}' 81 legend: 'Sakatu ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fa.js b/sources/plugins/a11yhelp/dialogs/lang/fa.js
index 88072f0..dbe99dc 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/fa.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/fa.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'fa', {
79 { 79 {
80 name: 'راهنمای دسترسی', 80 name: 'راهنمای دسترسی',
81 legend: 'فشردن ${a11yHelp}' 81 legend: 'فشردن ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fi.js b/sources/plugins/a11yhelp/dialogs/lang/fi.js
index 093d409..028020c 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/fi.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/fi.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'fi', {
79 { 79 {
80 name: 'Saavutettavuus ohjeet', 80 name: 'Saavutettavuus ohjeet',
81 legend: 'Paina ${a11yHelp}' 81 legend: 'Paina ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fo.js b/sources/plugins/a11yhelp/dialogs/lang/fo.js
index efce724..358ca6e 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/fo.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/fo.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'fo', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js b/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js
index c87c586..88c4a1f 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/fr-ca.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'fr-ca', {
79 { 79 {
80 name: 'Aide d\'accessibilité', 80 name: 'Aide d\'accessibilité',
81 legend: 'Appuyer sur ${a11yHelp}' 81 legend: 'Appuyer sur ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/fr.js b/sources/plugins/a11yhelp/dialogs/lang/fr.js
index 9727639..a2f4649 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/fr.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/fr.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'fr', {
79 { 79 {
80 name: ' Aide sur l\'accessibilité', 80 name: ' Aide sur l\'accessibilité',
81 legend: 'Appuyer sur ${a11yHelp}' 81 legend: 'Appuyer sur ${a11yHelp}'
82 },
83 {
84 name: 'Coller comme texte sans mise en forme',
85 legend: 'Appuyer sur ${pastetext}',
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/gl.js b/sources/plugins/a11yhelp/dialogs/lang/gl.js
index 4978330..1bb9595 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/gl.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/gl.js
@@ -18,7 +18,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'gl', {
18 { 18 {
19 name: 'Editor de diálogo', 19 name: 'Editor de diálogo',
20 legend: 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 21 'Dentro do diálogo, prema TAB para navegar cara os seguintes elementos de diálogo, prema MAIÚS+TAB para moverse cara os anteriores elementos de diálogo, prema INTRO para enviar o diálogo, prema ESC para cancelar o diálogo. Cando o diálogo ten múltiples lapelas, a lista de lapelas pode cinguirse con ALT+F10 ou con TAB como parte da orde de lapelas do diálogo. Coa lapela en foco, pode moverse cara a seguinte ou a anterior lapela coas FRECHAS ESQUERDA e DEREICHA respectivamente.'
22 }, 22 },
23 23
24 { 24 {
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'gl', {
79 { 79 {
80 name: 'Axuda da accesibilidade', 80 name: 'Axuda da accesibilidade',
81 legend: 'Prema ${a11yHelp}' 81 legend: 'Prema ${a11yHelp}'
82 },
83 {
84 name: 'Pegar como texto simple',
85 legend: 'Prema ${pastetext}',
86 legendEdge: 'Prema ${pastetext}, seguido de ${paste}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/gu.js b/sources/plugins/a11yhelp/dialogs/lang/gu.js
index 30eb2cd..6fa2b3d 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/gu.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/gu.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'gu', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/he.js b/sources/plugins/a11yhelp/dialogs/lang/he.js
index 24b8572..ed668c4 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/he.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/he.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'he', {
79 { 79 {
80 name: ' הוראות נגישות', 80 name: ' הוראות נגישות',
81 legend: 'לחץ ${a11yHelp}' 81 legend: 'לחץ ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/hi.js b/sources/plugins/a11yhelp/dialogs/lang/hi.js
index 308c5ef..de1e54b 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/hi.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/hi.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'hi', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/hr.js b/sources/plugins/a11yhelp/dialogs/lang/hr.js
index b05273e..ae28062 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/hr.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/hr.js
@@ -18,7 +18,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'hr', {
18 { 18 {
19 name: 'Dijalog', 19 name: 'Dijalog',
20 legend: 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 21 'Unutar dijaloga, pritisnite TAB kako bi navigirali do sljedećeg elementa dijaloga, pritisnite SHIFT+TAB kako bi se pomaknuli do prethodnog elementa, pritisnite ENTER kako bi poslali dijalog, pritisnite ESC za gašenje dijaloga. Kada dijalog ima više kartica, listi kartica se može pristupiti pomoću ALT+F10 ili sa TAB. Kada je fokusirana lista kartica, pomaknite se naprijed ili nazad pomoću strelica LIJEVO ili DESNO.'
22 }, 22 },
23 23
24 { 24 {
@@ -69,72 +69,77 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'hr', {
69 legend: 'Pritisni ${toolbarCollapse}' 69 legend: 'Pritisni ${toolbarCollapse}'
70 }, 70 },
71 { 71 {
72 name: 'Access previous focus space naredba', 72 name: 'Naredba za pristupi prethodnom prostoru fokusa',
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.' 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 }, 74 },
75 { 75 {
76 name: 'Access next focus space naredba', 76 name: 'Naredba za pristup sljedećem prostoru fokusa',
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.' 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 }, 78 },
79 { 79 {
80 name: 'Pomoć za dostupnost', 80 name: 'Pomoć za dostupnost',
81 legend: 'Pritisni ${a11yHelp}' 81 legend: 'Pritisni ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
85 ], 90 ],
86 tab: 'Tab', // MISSING 91 tab: 'Tab',
87 pause: 'Pause', // MISSING 92 pause: 'Pause',
88 capslock: 'Caps Lock', // MISSING 93 capslock: 'Caps Lock',
89 escape: 'Escape', // MISSING 94 escape: 'Escape',
90 pageUp: 'Page Up', // MISSING 95 pageUp: 'Page Up',
91 pageDown: 'Page Down', // MISSING 96 pageDown: 'Page Down',
92 leftArrow: 'Left Arrow', // MISSING 97 leftArrow: 'Lijev strelica',
93 upArrow: 'Up Arrow', // MISSING 98 upArrow: 'Strelica gore',
94 rightArrow: 'Right Arrow', // MISSING 99 rightArrow: 'Desna strelica',
95 downArrow: 'Down Arrow', // MISSING 100 downArrow: 'Strelica dolje',
96 insert: 'Insert', // MISSING 101 insert: 'Insert',
97 leftWindowKey: 'Left Windows key', // MISSING 102 leftWindowKey: 'Lijeva Windows tipka',
98 rightWindowKey: 'Right Windows key', // MISSING 103 rightWindowKey: 'Desna Windows tipka',
99 selectKey: 'Select key', // MISSING 104 selectKey: 'Tipka Select',
100 numpad0: 'Numpad 0', // MISSING 105 numpad0: 'Numpad 0',
101 numpad1: 'Numpad 1', // MISSING 106 numpad1: 'Numpad 1',
102 numpad2: 'Numpad 2', // MISSING 107 numpad2: 'Numpad 2',
103 numpad3: 'Numpad 3', // MISSING 108 numpad3: 'Numpad 3',
104 numpad4: 'Numpad 4', // MISSING 109 numpad4: 'Numpad 4',
105 numpad5: 'Numpad 5', // MISSING 110 numpad5: 'Numpad 5',
106 numpad6: 'Numpad 6', // MISSING 111 numpad6: 'Numpad 6',
107 numpad7: 'Numpad 7', // MISSING 112 numpad7: 'Numpad 7',
108 numpad8: 'Numpad 8', // MISSING 113 numpad8: 'umpad 8',
109 numpad9: 'Numpad 9', // MISSING 114 numpad9: 'Numpad 9',
110 multiply: 'Multiply', // MISSING 115 multiply: 'Množenje',
111 add: 'Add', // MISSING 116 add: 'Zbrajanje',
112 subtract: 'Subtract', // MISSING 117 subtract: 'Oduzimanje',
113 decimalPoint: 'Decimal Point', // MISSING 118 decimalPoint: 'Decimalna točka',
114 divide: 'Divide', // MISSING 119 divide: 'Dijeljenje',
115 f1: 'F1', // MISSING 120 f1: 'F1',
116 f2: 'F2', // MISSING 121 f2: 'F2',
117 f3: 'F3', // MISSING 122 f3: 'F3',
118 f4: 'F4', // MISSING 123 f4: 'F4',
119 f5: 'F5', // MISSING 124 f5: 'F5',
120 f6: 'F6', // MISSING 125 f6: 'F6',
121 f7: 'F7', // MISSING 126 f7: 'F7',
122 f8: 'F8', // MISSING 127 f8: 'F8',
123 f9: 'F9', // MISSING 128 f9: 'F9',
124 f10: 'F10', // MISSING 129 f10: 'F10',
125 f11: 'F11', // MISSING 130 f11: 'F11',
126 f12: 'F12', // MISSING 131 f12: 'F12',
127 numLock: 'Num Lock', // MISSING 132 numLock: 'Num Lock',
128 scrollLock: 'Scroll Lock', // MISSING 133 scrollLock: 'Scroll Lock',
129 semiColon: 'Semicolon', // MISSING 134 semiColon: 'Točka zarez',
130 equalSign: 'Equal Sign', // MISSING 135 equalSign: 'Jednako',
131 comma: 'Comma', // MISSING 136 comma: 'Zarez',
132 dash: 'Dash', // MISSING 137 dash: 'Crtica',
133 period: 'Period', // MISSING 138 period: 'Točka',
134 forwardSlash: 'Forward Slash', // MISSING 139 forwardSlash: 'Kosa crta',
135 graveAccent: 'Grave Accent', // MISSING 140 graveAccent: 'Akcent',
136 openBracket: 'Open Bracket', // MISSING 141 openBracket: 'Otvorena uglata zagrada',
137 backSlash: 'Backslash', // MISSING 142 backSlash: 'Obrnuta kosa crta',
138 closeBracket: 'Close Bracket', // MISSING 143 closeBracket: 'Zatvorena uglata zagrada',
139 singleQuote: 'Single Quote' // MISSING 144 singleQuote: 'Jednostruki navodnik'
140} ); 145} );
diff --git a/sources/plugins/a11yhelp/dialogs/lang/hu.js b/sources/plugins/a11yhelp/dialogs/lang/hu.js
index f14f17d..1bae59f 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/hu.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/hu.js
@@ -18,7 +18,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'hu', {
18 { 18 {
19 name: 'Szerkesző párbeszéd ablak', 19 name: 'Szerkesző párbeszéd ablak',
20 legend: 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 21 'Párbeszédablakban nyomjon TAB-ot a következő párbeszédmezőhöz ugráshoz, nyomjon SHIFT + TAB-ot az előző mezőhöz ugráshoz, nyomjon ENTER-t a párbeszédablak elfogadásához, nyomjon ESC-et a párbeszédablak elvetéséhez. Azokhoz a párbeszédablakokhoz, amik több fület tartalmaznak, nyomjon ALT + F10-et vagy TAB-ot hogy a fülekre ugorjon. Ezután a TAB-al vagy a JOBB NYÍLLAL a következő fülre ugorhat.'
22 }, 22 },
23 23
24 { 24 {
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'hu', {
79 { 79 {
80 name: 'Kisegítő súgó', 80 name: 'Kisegítő súgó',
81 legend: 'Nyomjon ${a11yHelp}' 81 legend: 'Nyomjon ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/id.js b/sources/plugins/a11yhelp/dialogs/lang/id.js
index 7799b38..89aeee7 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/id.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/id.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'id', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/it.js b/sources/plugins/a11yhelp/dialogs/lang/it.js
index 55ecadc..224bd49 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/it.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/it.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'it', {
79 { 79 {
80 name: ' Aiuto Accessibilità', 80 name: ' Aiuto Accessibilità',
81 legend: 'Premi ${a11yHelp}' 81 legend: 'Premi ${a11yHelp}'
82 },
83 {
84 name: 'Incolla come testo semplice',
85 legend: 'Premi ${pastetext}',
86 legendEdge: 'Premi ${pastetext}, seguito da ${paste}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ja.js b/sources/plugins/a11yhelp/dialogs/lang/ja.js
index 9053e37..b21d740 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ja.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ja.js
@@ -65,7 +65,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ja', {
65 legend: '${link} をクリック' 65 legend: '${link} をクリック'
66 }, 66 },
67 { 67 {
68 name: 'ツールバーを', 68 name: 'ツールバーを',
69 legend: '${toolbarCollapse} をクリック' 69 legend: '${toolbarCollapse} をクリック'
70 }, 70 },
71 { 71 {
@@ -73,12 +73,17 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ja', {
73 legend: '${accessPreviousSpace} を押すとカーソルより前にあるカーソルキーで入り込めないスペースへ移動できます。例えば、HRエレメントが2つ接している場合などです。離れた場所へは、複数回キーを押します。' 73 legend: '${accessPreviousSpace} を押すとカーソルより前にあるカーソルキーで入り込めないスペースへ移動できます。例えば、HRエレメントが2つ接している場合などです。離れた場所へは、複数回キーを押します。'
74 }, 74 },
75 { 75 {
76 name: '次のカーソル移動できないイントへ', 76 name: '次のカーソルポイントへ移動する',
77 legend: '${accessNextSpace} を押すとカーソルより後ろにあるカーソルキーで入り込めないスペースへ移動できます。例えば、HRエレメントが2つ接している場合などです。離れた場所へは、複数回キーを押します。' 77 legend: '${accessNextSpace} を押すとカーソルより後ろにあるカーソルキーで入り込めないスペースへ移動できます。例えば、HRエレメントが2つ接している場合などです。離れた場所へは、複数回キーを押します。'
78 }, 78 },
79 { 79 {
80 name: 'ユーザー補助ヘルプ', 80 name: 'ユーザー補助ヘルプ',
81 legend: '${a11yHelp} をクリック' 81 legend: '${a11yHelp} をクリック'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/km.js b/sources/plugins/a11yhelp/dialogs/lang/km.js
index 4cdd048..91018f5 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/km.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/km.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'km', {
79 { 79 {
80 name: 'ជំនួយ​ពី​ភាព​ងាយស្រួល', 80 name: 'ជំនួយ​ពី​ភាព​ងាយស្រួល',
81 legend: 'ជួយ ${a11yHelp}' 81 legend: 'ជួយ ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ko.js b/sources/plugins/a11yhelp/dialogs/lang/ko.js
index e5ed192..78fc71c 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ko.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ko.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ko', {
79 { 79 {
80 name: ' 접근성 도움말', 80 name: ' 접근성 도움말',
81 legend: '${a11yHelp} 누르시오' 81 legend: '${a11yHelp} 누르시오'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ku.js b/sources/plugins/a11yhelp/dialogs/lang/ku.js
index 3f044a2..d293c65 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ku.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ku.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ku', {
79 { 79 {
80 name: 'دەستپێگەیشتنی یارمەتی', 80 name: 'دەستپێگەیشتنی یارمەتی',
81 legend: 'کلیك ${a11yHelp}' 81 legend: 'کلیك ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/lt.js b/sources/plugins/a11yhelp/dialogs/lang/lt.js
index c27e3ba..b4095c4 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/lt.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/lt.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'lt', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/lv.js b/sources/plugins/a11yhelp/dialogs/lang/lv.js
index aac4129..67d0d6e 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/lv.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/lv.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'lv', {
79 { 79 {
80 name: 'Pieejamības palīdzība', 80 name: 'Pieejamības palīdzība',
81 legend: 'Nospiediet ${a11yHelp}' 81 legend: 'Nospiediet ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/mk.js b/sources/plugins/a11yhelp/dialogs/lang/mk.js
index 8316358..bd24e38 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/mk.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/mk.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'mk', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/mn.js b/sources/plugins/a11yhelp/dialogs/lang/mn.js
index eb11634..3037312 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/mn.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/mn.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'mn', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/nb.js b/sources/plugins/a11yhelp/dialogs/lang/nb.js
index ccfeb66..dc49357 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/nb.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/nb.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'nb', {
79 { 79 {
80 name: 'Hjelp for tilgjengelighet', 80 name: 'Hjelp for tilgjengelighet',
81 legend: 'Trykk ${a11yHelp}' 81 legend: 'Trykk ${a11yHelp}'
82 },
83 {
84 name: 'Lim inn som ren tekst',
85 legend: 'Trykk ${pastetext}',
86 legendEdge: 'Trykk ${pastetext}, etterfulgt av ${past}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/nl.js b/sources/plugins/a11yhelp/dialogs/lang/nl.js
index 00d53ea..4ee8799 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/nl.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/nl.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'nl', {
79 { 79 {
80 name: 'Toegankelijkheidshulp', 80 name: 'Toegankelijkheidshulp',
81 legend: 'Druk op ${a11yHelp}' 81 legend: 'Druk op ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/no.js b/sources/plugins/a11yhelp/dialogs/lang/no.js
index 4402ddf..e015fc3 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/no.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/no.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'no', {
79 { 79 {
80 name: 'Hjelp for tilgjengelighet', 80 name: 'Hjelp for tilgjengelighet',
81 legend: 'Trykk ${a11yHelp}' 81 legend: 'Trykk ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/oc.js b/sources/plugins/a11yhelp/dialogs/lang/oc.js
index 8df209d..fe313f4 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/oc.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/oc.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'oc', {
79 { 79 {
80 name: ' Ajuda sus l\'accessibilitat', 80 name: ' Ajuda sus l\'accessibilitat',
81 legend: 'Quichar sus ${a11yHelp}' 81 legend: 'Quichar sus ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/pl.js b/sources/plugins/a11yhelp/dialogs/lang/pl.js
index 825ea08..23801fa 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/pl.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/pl.js
@@ -69,16 +69,21 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'pl', {
69 legend: 'Naciśnij ${toolbarCollapse}' 69 legend: 'Naciśnij ${toolbarCollapse}'
70 }, 70 },
71 { 71 {
72 name: ' Access previous focus space command', // MISSING 72 name: 'Przejdź do poprzedniego miejsca, w którym można ustawić focus',
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 73 legend: 'Naciśnij ${accessPreviousSpace}, aby przejść do najbliższego niedostępnego miejsca przed kursorem, w którym można ustawić focus. Przykład: dwa przylegające elementy HR. Powtórz ten skrót klawiaturowy, by dotrzeć do kolejnych takich miejsc.'
74 }, 74 },
75 { 75 {
76 name: ' Access next focus space command', // MISSING 76 name: 'Przejdź do naspnego miejsca, w którym mna ustawić focus',
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 77 legend: 'Naciśnij ${accessNextSpace}, aby przejść do najbliższego niedostępnego miejsca po kursorze, w którym można ustawić focus. Przykład: dwa przylegające elementy HR. Powtórz ten skrót klawiaturowy, by dotrzeć do kolejnych takich miejsc.'
78 }, 78 },
79 { 79 {
80 name: 'Pomoc dotycząca dostępności', 80 name: 'Pomoc dotycząca dostępności',
81 legend: 'Naciśnij ${a11yHelp}' 81 legend: 'Naciśnij ${a11yHelp}'
82 },
83 {
84 name: 'Wklej jako tekst',
85 legend: 'Naciśnij ${pastetext}',
86 legendEdge: 'Naciśnij ${pastetext}, a następnie ${paste}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/pt-br.js b/sources/plugins/a11yhelp/dialogs/lang/pt-br.js
index 030df98..b233f2e 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/pt-br.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/pt-br.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'pt-br', {
79 { 79 {
80 name: ' Ajuda de Acessibilidade', 80 name: ' Ajuda de Acessibilidade',
81 legend: 'Pressione ${a11yHelp}' 81 legend: 'Pressione ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/pt.js b/sources/plugins/a11yhelp/dialogs/lang/pt.js
index 986a377..cc02ae2 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/pt.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/pt.js
@@ -23,7 +23,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'pt', {
23 23
24 { 24 {
25 name: 'Menu de contexto do editor', 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.' 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. Vá para o item do menu contentor com ESC ou SETA ESQUERDA. Feche o menu de contexto com ESC.'
27 }, 27 },
28 28
29 { 29 {
@@ -79,24 +79,29 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'pt', {
79 { 79 {
80 name: 'Ajuda a acessibilidade', 80 name: 'Ajuda a acessibilidade',
81 legend: 'Pressione ${a11yHelp}' 81 legend: 'Pressione ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
85 ], 90 ],
86 tab: 'Tab', // MISSING 91 tab: 'Separador',
87 pause: 'Pausa', 92 pause: 'Pausa',
88 capslock: 'Maiúsculas', 93 capslock: 'Maiúsculas',
89 escape: 'Esc', 94 escape: 'Esc',
90 pageUp: 'Page Up', // MISSING 95 pageUp: 'Subir página',
91 pageDown: 'Page Down', // MISSING 96 pageDown: 'Descer página',
92 leftArrow: 'Seta esquerda', 97 leftArrow: 'Seta esquerda',
93 upArrow: 'Seta para cima', 98 upArrow: 'Seta para cima',
94 rightArrow: 'Seta direita', 99 rightArrow: 'Seta direita',
95 downArrow: 'Seta para baixo', 100 downArrow: 'Seta para baixo',
96 insert: 'Inserir', 101 insert: 'Inserir',
97 leftWindowKey: 'Left Windows key', // MISSING 102 leftWindowKey: 'Tecla esquerda Windows',
98 rightWindowKey: 'Right Windows key', // MISSING 103 rightWindowKey: 'Tecla direita Windows',
99 selectKey: 'Select key', // MISSING 104 selectKey: 'Selecionar tecla',
100 numpad0: 'Numpad 0', // MISSING 105 numpad0: 'Numpad 0', // MISSING
101 numpad1: 'Numpad 1', // MISSING 106 numpad1: 'Numpad 1', // MISSING
102 numpad2: 'Numpad 2', // MISSING 107 numpad2: 'Numpad 2', // MISSING
@@ -110,7 +115,7 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'pt', {
110 multiply: 'Multiplicar', 115 multiply: 'Multiplicar',
111 add: 'Adicionar', 116 add: 'Adicionar',
112 subtract: 'Subtrair', 117 subtract: 'Subtrair',
113 decimalPoint: 'Decimal Point', // MISSING 118 decimalPoint: 'Ponto decimal',
114 divide: 'Separar', 119 divide: 'Separar',
115 f1: 'F1', 120 f1: 'F1',
116 f2: 'F2', 121 f2: 'F2',
@@ -126,8 +131,8 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'pt', {
126 f12: 'F12', 131 f12: 'F12',
127 numLock: 'Num Lock', // MISSING 132 numLock: 'Num Lock', // MISSING
128 scrollLock: 'Scroll Lock', // MISSING 133 scrollLock: 'Scroll Lock', // MISSING
129 semiColon: 'Semicolon', // MISSING 134 semiColon: 'Ponto e vírgula',
130 equalSign: 'Equal Sign', // MISSING 135 equalSign: 'Sinald e igual',
131 comma: 'Vírgula', 136 comma: 'Vírgula',
132 dash: 'Cardinal', 137 dash: 'Cardinal',
133 period: 'Ponto', 138 period: 'Ponto',
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ro.js b/sources/plugins/a11yhelp/dialogs/lang/ro.js
index a182bbd..11177ba 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ro.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ro.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ro', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ru.js b/sources/plugins/a11yhelp/dialogs/lang/ru.js
index 19d502a..852a17f 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ru.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ru.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ru', {
79 { 79 {
80 name: 'Справка по горячим клавишам', 80 name: 'Справка по горячим клавишам',
81 legend: 'Нажмите ${a11yHelp}' 81 legend: 'Нажмите ${a11yHelp}'
82 },
83 {
84 name: 'Вставить только текст',
85 legend: 'Нажмите ${pastetext}',
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/si.js b/sources/plugins/a11yhelp/dialogs/lang/si.js
index 14d94ad..ce72579 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/si.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/si.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'si', {
79 { 79 {
80 name: 'ප්‍රවේශ ', 80 name: 'ප්‍රවේශ ',
81 legend: 'ඔබන්න ${a11y }' 81 legend: 'ඔබන්න ${a11y }'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sk.js b/sources/plugins/a11yhelp/dialogs/lang/sk.js
index 2d74c3b..3800f14 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/sk.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/sk.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'sk', {
79 { 79 {
80 name: 'Pomoc prístupnosti', 80 name: 'Pomoc prístupnosti',
81 legend: 'Stlačte ${a11yHelp}' 81 legend: 'Stlačte ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sl.js b/sources/plugins/a11yhelp/dialogs/lang/sl.js
index bb38713..779b410 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/sl.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/sl.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'sl', {
79 { 79 {
80 name: 'Pomoč dostopnosti', 80 name: 'Pomoč dostopnosti',
81 legend: 'Pritisnite ${a11yHelp}' 81 legend: 'Pritisnite ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sq.js b/sources/plugins/a11yhelp/dialogs/lang/sq.js
index c5947cc..6283fee 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/sq.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/sq.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'sq', {
79 { 79 {
80 name: 'Ndihmë Qasjeje', 80 name: 'Ndihmë Qasjeje',
81 legend: 'Shtyp ${a11yHelp}' 81 legend: 'Shtyp ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js b/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js
index 5b743ac..f8caf01 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/sr-latn.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'sr-latn', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sr.js b/sources/plugins/a11yhelp/dialogs/lang/sr.js
index 0e3e979..0ef0222 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/sr.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/sr.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'sr', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/sv.js b/sources/plugins/a11yhelp/dialogs/lang/sv.js
index 4962b95..867beda 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/sv.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/sv.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'sv', {
79 { 79 {
80 name: 'Hjälp om tillgänglighet', 80 name: 'Hjälp om tillgänglighet',
81 legend: 'Tryck ${a11yHelp}' 81 legend: 'Tryck ${a11yHelp}'
82 },
83 {
84 name: 'Klistra in som vanlig text',
85 legend: 'Tryck ${pastetext}',
86 legendEdge: 'Tryck ${pastetext}, följt av ${paste}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/th.js b/sources/plugins/a11yhelp/dialogs/lang/th.js
index 1382894..5da604f 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/th.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/th.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'th', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: 'Press ${a11yHelp}' // MISSING 81 legend: 'Press ${a11yHelp}' // MISSING
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/tr.js b/sources/plugins/a11yhelp/dialogs/lang/tr.js
index 15306a5..86b4c97 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/tr.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/tr.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'tr', {
79 { 79 {
80 name: 'Erişilebilirlik Yardımı', 80 name: 'Erişilebilirlik Yardımı',
81 legend: '${a11yHelp}\'e basın' 81 legend: '${a11yHelp}\'e basın'
82 },
83 {
84 name: 'Düz Metin Olarak Yapıştır',
85 legend: '${pastetext} basın',
86 legendEdge: 'Önce ${pastetext} ardından${paste} basın'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/tt.js b/sources/plugins/a11yhelp/dialogs/lang/tt.js
index bdd9847..e73f5dd 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/tt.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/tt.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'tt', {
79 { 79 {
80 name: ' Accessibility Help', // MISSING 80 name: ' Accessibility Help', // MISSING
81 legend: '${a11yHelp} басыгыз' 81 legend: '${a11yHelp} басыгыз'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/ug.js b/sources/plugins/a11yhelp/dialogs/lang/ug.js
index 1771562..4768c55 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/ug.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/ug.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'ug', {
79 { 79 {
80 name: 'توسالغۇسىز لايىھە چۈشەندۈرۈشى', 80 name: 'توسالغۇسىز لايىھە چۈشەندۈرۈشى',
81 legend: '${a11yHelp} نى بېسىڭ' 81 legend: '${a11yHelp} نى بېسىڭ'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/uk.js b/sources/plugins/a11yhelp/dialogs/lang/uk.js
index d1e8589..99a7002 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/uk.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/uk.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'uk', {
79 { 79 {
80 name: 'Допомога з доступності', 80 name: 'Допомога з доступності',
81 legend: 'Натисніть ${a11yHelp}' 81 legend: 'Натисніть ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/vi.js b/sources/plugins/a11yhelp/dialogs/lang/vi.js
index 497deb2..b8c9fe9 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/vi.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/vi.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'vi', {
79 { 79 {
80 name: 'Trợ giúp liên quan', 80 name: 'Trợ giúp liên quan',
81 legend: 'Nhấn ${a11yHelp}' 81 legend: 'Nhấn ${a11yHelp}'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js b/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js
index d2d0f2b..0ce61d2 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/zh-cn.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'zh-cn', {
79 { 79 {
80 name: '辅助功能帮助', 80 name: '辅助功能帮助',
81 legend: '按 ${a11yHelp}' 81 legend: '按 ${a11yHelp}'
82 },
83 {
84 name: '粘贴为纯文本',
85 legend: '按 ${pastetext}',
86 legendEdge: '按 ${pastetext},然后再按 ${paste}'
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/dialogs/lang/zh.js b/sources/plugins/a11yhelp/dialogs/lang/zh.js
index 0fe1310..2e35e1d 100644
--- a/sources/plugins/a11yhelp/dialogs/lang/zh.js
+++ b/sources/plugins/a11yhelp/dialogs/lang/zh.js
@@ -79,6 +79,11 @@ CKEDITOR.plugins.setLang( 'a11yhelp', 'zh', {
79 { 79 {
80 name: '協助工具說明', 80 name: '協助工具說明',
81 legend: '請按下「${a11yHelp}」' 81 legend: '請按下「${a11yHelp}」'
82 },
83 {
84 name: ' Paste as plain text', // MISSING
85 legend: 'Press ${pastetext}', // MISSING
86 legendEdge: 'Press ${pastetext}, followed by ${paste}' // MISSING
82 } 87 }
83 ] 88 ]
84 } 89 }
diff --git a/sources/plugins/a11yhelp/plugin.js b/sources/plugins/a11yhelp/plugin.js
index 9e2925a..65da25e 100644
--- a/sources/plugins/a11yhelp/plugin.js
+++ b/sources/plugins/a11yhelp/plugin.js
@@ -17,7 +17,7 @@
17 17
18 // List of available localizations. 18 // List of available localizations.
19 // jscs:disable 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 }, 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,'es-mx':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 21 // jscs:enable
22 22
23 init: function( editor ) { 23 init: function( editor ) {
diff --git a/sources/plugins/basicstyles/lang/es-mx.js b/sources/plugins/basicstyles/lang/es-mx.js
new file mode 100644
index 0000000..a57ba4b
--- /dev/null
+++ b/sources/plugins/basicstyles/lang/es-mx.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-mx', {
6 bold: 'Negrita',
7 italic: 'Cursiva',
8 strike: 'Tachado',
9 subscript: 'subíndice',
10 superscript: 'Sobrescrito',
11 underline: 'Subrayada'
12} );
diff --git a/sources/plugins/basicstyles/lang/hr.js b/sources/plugins/basicstyles/lang/hr.js
index 6ddfb31..94bc730 100644
--- a/sources/plugins/basicstyles/lang/hr.js
+++ b/sources/plugins/basicstyles/lang/hr.js
@@ -3,8 +3,8 @@ Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license 3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/ 4*/
5CKEDITOR.plugins.setLang( 'basicstyles', 'hr', { 5CKEDITOR.plugins.setLang( 'basicstyles', 'hr', {
6 bold: 'Podebljaj', 6 bold: 'Podebljano',
7 italic: 'Ukosi', 7 italic: 'Ukošeno',
8 strike: 'Precrtano', 8 strike: 'Precrtano',
9 subscript: 'Subscript', 9 subscript: 'Subscript',
10 superscript: 'Superscript', 10 superscript: 'Superscript',
diff --git a/sources/plugins/basicstyles/plugin.js b/sources/plugins/basicstyles/plugin.js
index 4a6325a..474ea09 100644
--- a/sources/plugins/basicstyles/plugin.js
+++ b/sources/plugins/basicstyles/plugin.js
@@ -5,7 +5,7 @@
5 5
6CKEDITOR.plugins.add( 'basicstyles', { 6CKEDITOR.plugins.add( 'basicstyles', {
7 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
9 // jscs:enable maximumLineLength 9 // jscs:enable maximumLineLength
10 icons: 'bold,italic,underline,strike,subscript,superscript', // %REMOVE_LINE_CORE% 10 icons: 'bold,italic,underline,strike,subscript,superscript', // %REMOVE_LINE_CORE%
11 hidpi: true, // %REMOVE_LINE_CORE% 11 hidpi: true, // %REMOVE_LINE_CORE%
diff --git a/sources/plugins/button/lang/es-mx.js b/sources/plugins/button/lang/es-mx.js
new file mode 100644
index 0000000..3b1b47b
--- /dev/null
+++ b/sources/plugins/button/lang/es-mx.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-mx', {
7 selectedLabel: '%1 (Seleccionado)'
8} );
diff --git a/sources/plugins/button/lang/hr.js b/sources/plugins/button/lang/hr.js
new file mode 100644
index 0000000..031f8f5
--- /dev/null
+++ b/sources/plugins/button/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( 'button', 'hr', {
7 selectedLabel: '%1 (Odabrano)'
8} );
diff --git a/sources/plugins/button/plugin.js b/sources/plugins/button/plugin.js
index 6d2db33..e91fa86 100644
--- a/sources/plugins/button/plugin.js
+++ b/sources/plugins/button/plugin.js
@@ -29,7 +29,7 @@
29 29
30 template += ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event);"' + 30 template += ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event);"' +
31 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' + 31 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' +
32 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188 32 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // http://dev.ckeditor.com/ticket/188
33 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' + 33 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' +
34 '<span class="cke_button_icon cke_button__{iconName}_icon" style="{style}"'; 34 '<span class="cke_button_icon cke_button__{iconName}_icon" style="{style}"';
35 35
@@ -49,7 +49,7 @@
49 btnTpl = CKEDITOR.addTemplate( 'button', template ); 49 btnTpl = CKEDITOR.addTemplate( 'button', template );
50 50
51 CKEDITOR.plugins.add( 'button', { 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% 52 lang: 'af,ar,az,bg,ca,cs,da,de,de-ch,el,en,en-gb,eo,es,es-mx,eu,fa,fi,fr,gl,he,hr,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 ) { 53 beforeInit: function( editor ) {
54 editor.ui.addHandler( CKEDITOR.UI_BUTTON, CKEDITOR.ui.button.handler ); 54 editor.ui.addHandler( CKEDITOR.UI_BUTTON, CKEDITOR.ui.button.handler );
55 } 55 }
@@ -189,7 +189,7 @@
189 } 189 }
190 instance.execute(); 190 instance.execute();
191 191
192 // Fixed iOS focus issue when your press disabled button (#12381). 192 // Fixed iOS focus issue when your press disabled button (http://dev.ckeditor.com/ticket/12381).
193 if ( env.iOS ) { 193 if ( env.iOS ) {
194 editor.focus(); 194 editor.focus();
195 } 195 }
@@ -256,7 +256,7 @@
256 var name = this.name || this.command, 256 var name = this.name || this.command,
257 iconName = name; 257 iconName = name;
258 258
259 // Check if we're pointing to an icon defined by another command. (#9555) 259 // Check if we're pointing to an icon defined by another command. (http://dev.ckeditor.com/ticket/9555)
260 if ( this.icon && !( /\./ ).test( this.icon ) ) { 260 if ( this.icon && !( /\./ ).test( this.icon ) ) {
261 iconName = this.icon; 261 iconName = this.icon;
262 this.icon = null; 262 this.icon = null;
@@ -311,7 +311,7 @@
311 element.removeAttribute( 'aria-disabled' ); 311 element.removeAttribute( 'aria-disabled' );
312 312
313 if ( !this.hasArrow ) { 313 if ( !this.hasArrow ) {
314 // Note: aria-pressed attribute should not be added to menuButton instances. (#11331) 314 // Note: aria-pressed attribute should not be added to menuButton instances. (http://dev.ckeditor.com/ticket/11331)
315 state == CKEDITOR.TRISTATE_ON ? 315 state == CKEDITOR.TRISTATE_ON ?
316 element.setAttribute( 'aria-pressed', true ) : 316 element.setAttribute( 'aria-pressed', true ) :
317 element.removeAttribute( 'aria-pressed' ); 317 element.removeAttribute( 'aria-pressed' );
diff --git a/sources/plugins/clipboard/dev/dnd.html b/sources/plugins/clipboard/dev/dnd.html
index 2dfb2be..c45475b 100644
--- a/sources/plugins/clipboard/dev/dnd.html
+++ b/sources/plugins/clipboard/dev/dnd.html
@@ -6,7 +6,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
6<html> 6<html>
7<head> 7<head>
8 <meta charset="utf-8"> 8 <meta charset="utf-8">
9 <title>Manual test for #11460</title> 9 <title>Manual test for http://dev.ckeditor.com/ticket/11460</title>
10 <script src="../../../ckeditor.js"></script> 10 <script src="../../../ckeditor.js"></script>
11 <script src="../../../dev/console/console.js"></script> 11 <script src="../../../dev/console/console.js"></script>
12 <script src="../../../plugins/clipboard/dev/console.js"></script> 12 <script src="../../../plugins/clipboard/dev/console.js"></script>
diff --git a/sources/plugins/clipboard/dialogs/paste.js b/sources/plugins/clipboard/dialogs/paste.js
deleted file mode 100644
index 80ce29f..0000000
--- a/sources/plugins/clipboard/dialogs/paste.js
+++ /dev/null
@@ -1,254 +0,0 @@
1/**
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/lang/af.js b/sources/plugins/clipboard/lang/af.js
index f87522f..5860867 100644
--- a/sources/plugins/clipboard/lang/af.js
+++ b/sources/plugins/clipboard/lang/af.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'af', {
8 cut: 'Knip', 8 cut: 'Knip',
9 cutError: 'U blaaier se sekuriteitsinstelling belet die outomatiese knip-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).', 9 cutError: 'U blaaier se sekuriteitsinstelling belet die outomatiese knip-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).',
10 paste: 'Plak', 10 paste: 'Plak',
11 pasteArea: 'Plak-area', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ar.js b/sources/plugins/clipboard/lang/ar.js
index aa96596..6d1a0b0 100644
--- a/sources/plugins/clipboard/lang/ar.js
+++ b/sources/plugins/clipboard/lang/ar.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ar', {
8 cut: 'قص', 8 cut: 'قص',
9 cutError: 'الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع القص التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl/Cmd+X).', 9 cutError: 'الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع القص التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl/Cmd+X).',
10 paste: 'لصق', 10 paste: 'لصق',
11 pasteArea: 'منطقة اللصق', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'الصق داخل الصندوق بإستخدام زرائر (<STRONG>Ctrl/Cmd+V</STRONG>) في لوحة المفاتيح، ثم اضغط زر <STRONG>موافق</STRONG>.',
13 securityMsg: 'نظراً لإعدادات الأمان الخاصة بمتصفحك، لن يتمكن هذا المحرر من الوصول لمحتوى حافظتك، لذلك يجب عليك لصق المحتوى مرة أخرى في هذه النافذة.',
14 title: 'لصق'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/az.js b/sources/plugins/clipboard/lang/az.js
index 1fc1a99..8f60f35 100644
--- a/sources/plugins/clipboard/lang/az.js
+++ b/sources/plugins/clipboard/lang/az.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'az', {
8 cut: 'Kəs', 8 cut: 'Kəs',
9 cutError: 'Avtomatik kəsmə mümkün deyil. Ctrl+X basın.', 9 cutError: 'Avtomatik kəsmə mümkün deyil. Ctrl+X basın.',
10 paste: 'Əlavə et', 10 paste: 'Əlavə et',
11 pasteArea: 'Əlavəetmə sahəsi', 11 pasteNotification: 'Sizin İnternet bələdçisi bu cür mətnin köçürməsi dəstəklənmir. Əlavə etmək üçün %1 basın.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/bg.js b/sources/plugins/clipboard/lang/bg.js
index 93a5a9c..2d8eede 100644
--- a/sources/plugins/clipboard/lang/bg.js
+++ b/sources/plugins/clipboard/lang/bg.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bg', {
8 cut: 'Отрежи', 8 cut: 'Отрежи',
9 cutError: 'Настройките за сигурност на Вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. Моля ползвайте клавиатурните команди за целта (ctrl+x).', 9 cutError: 'Настройките за сигурност на Вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. Моля ползвайте клавиатурните команди за целта (ctrl+x).',
10 paste: 'Вмъкни', 10 paste: 'Вмъкни',
11 pasteArea: 'Зона за вмъкване', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'Вмъкнете тук съдъжанието с клавиатуарата (<STRONG>Ctrl/Cmd+V</STRONG>) и натиснете <STRONG>OK</STRONG>.',
13 securityMsg: 'Заради настройките за сигурност на Вашия браузър, редакторът не може да прочете данните от клипборда коректно.',
14 title: 'Вмъкни'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/bn.js b/sources/plugins/clipboard/lang/bn.js
index f821fa0..1d0922a 100644
--- a/sources/plugins/clipboard/lang/bn.js
+++ b/sources/plugins/clipboard/lang/bn.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bn', {
8 cut: 'কাট', 8 cut: 'কাট',
9 cutError: 'আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কাট করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl/Cmd+X)।', 9 cutError: 'আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কাট করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl/Cmd+X)।',
10 paste: 'পেস্ট', 10 paste: 'পেস্ট',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/bs.js b/sources/plugins/clipboard/lang/bs.js
index 1c23a61..62f3f1b 100644
--- a/sources/plugins/clipboard/lang/bs.js
+++ b/sources/plugins/clipboard/lang/bs.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bs', {
8 cut: 'Izreži', 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).', 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', 10 paste: 'Zalijepi',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ca.js b/sources/plugins/clipboard/lang/ca.js
index 52179c1..6cd3b58 100644
--- a/sources/plugins/clipboard/lang/ca.js
+++ b/sources/plugins/clipboard/lang/ca.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ca', {
8 cut: 'Retallar', 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).', 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', 10 paste: 'Enganxar',
11 pasteArea: 'Àrea d\'enganxat', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/cs.js b/sources/plugins/clipboard/lang/cs.js
index 7cf573e..4cbf3b4 100644
--- a/sources/plugins/clipboard/lang/cs.js
+++ b/sources/plugins/clipboard/lang/cs.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'cs', {
8 cut: 'Vyjmout', 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).', 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', 10 paste: 'Vložit',
11 pasteArea: 'Oblast vkládání', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/cy.js b/sources/plugins/clipboard/lang/cy.js
index 00c5eeb..e854e13 100644
--- a/sources/plugins/clipboard/lang/cy.js
+++ b/sources/plugins/clipboard/lang/cy.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'cy', {
8 cut: 'Torri', 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).', 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', 10 paste: 'Gludo',
11 pasteArea: 'Ardal Gludo', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/da.js b/sources/plugins/clipboard/lang/da.js
index c029016..257c9d4 100644
--- a/sources/plugins/clipboard/lang/da.js
+++ b/sources/plugins/clipboard/lang/da.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'da', {
8 cut: 'Klip', 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).', 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', 10 paste: 'Indsæt',
11 pasteArea: 'Indsæt område', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/de-ch.js b/sources/plugins/clipboard/lang/de-ch.js
index 325b100..e3b9ead 100644
--- a/sources/plugins/clipboard/lang/de-ch.js
+++ b/sources/plugins/clipboard/lang/de-ch.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'de-ch', {
8 cut: 'Ausschneiden', 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).', 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', 10 paste: 'Einfügen',
11 pasteArea: 'Einfügebereich', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/de.js b/sources/plugins/clipboard/lang/de.js
index 2d6b30b..5244081 100644
--- a/sources/plugins/clipboard/lang/de.js
+++ b/sources/plugins/clipboard/lang/de.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'de', {
8 cut: 'Ausschneiden', 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).', 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', 10 paste: 'Einfügen',
11 pasteArea: 'Einfügebereich', 11 pasteNotification: 'Ihr Browser verhindert das Einfügen über diesen Weg. Zum einfügen drücken Sie %1.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/el.js b/sources/plugins/clipboard/lang/el.js
index 0528840..4ee396b 100644
--- a/sources/plugins/clipboard/lang/el.js
+++ b/sources/plugins/clipboard/lang/el.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'el', {
8 cut: 'Αποκοπή', 8 cut: 'Αποκοπή',
9 cutError: 'Οι ρυθμίσεις ασφαλείας του περιηγητή σας δεν επιτρέπουν την επιλεγμένη εργασία αποκοπής. Παρακαλώ χρησιμοποιείστε το πληκτρολόγιο (Ctrl/Cmd+X).', 9 cutError: 'Οι ρυθμίσεις ασφαλείας του περιηγητή σας δεν επιτρέπουν την επιλεγμένη εργασία αποκοπής. Παρακαλώ χρησιμοποιείστε το πληκτρολόγιο (Ctrl/Cmd+X).',
10 paste: 'Επικόλληση', 10 paste: 'Επικόλληση',
11 pasteArea: 'Περιοχή Επικόλλησης', 11 pasteNotification: 'Ο περιηγητής σας δεν σας επιτρέπει να επικολλήσετε με αυτόν τον τρόπο. Πατήστε %1 για επικόλληση.'
12 pasteMsg: 'Παρακαλώ επικολλήστε στο ακόλουθο κουτί χρησιμοποιώντας το πληκτρολόγιο (<strong>Ctrl/Cmd+V</strong>) και πατήστε OK.',
13 securityMsg: 'Λόγων των ρυθμίσεων ασφάλειας του περιηγητή σας, ο επεξεργαστής δεν μπορεί να έχει πρόσβαση στην μνήμη επικόλλησης. Χρειάζεται να επικολλήσετε ξανά σε αυτό το παράθυρο.',
14 title: 'Επικόλληση'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/en-au.js b/sources/plugins/clipboard/lang/en-au.js
index 5c497fb..018a754 100644
--- a/sources/plugins/clipboard/lang/en-au.js
+++ b/sources/plugins/clipboard/lang/en-au.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-au', {
8 cut: 'Cut', 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).', 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', 10 paste: 'Paste',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/en-ca.js b/sources/plugins/clipboard/lang/en-ca.js
index 036ebab..fd76ba7 100644
--- a/sources/plugins/clipboard/lang/en-ca.js
+++ b/sources/plugins/clipboard/lang/en-ca.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-ca', {
8 cut: 'Cut', 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).', 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', 10 paste: 'Paste',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/en-gb.js b/sources/plugins/clipboard/lang/en-gb.js
index bb511ce..fb6aa2e 100644
--- a/sources/plugins/clipboard/lang/en-gb.js
+++ b/sources/plugins/clipboard/lang/en-gb.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-gb', {
8 cut: 'Cut', 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).', 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', 10 paste: 'Paste',
11 pasteArea: 'Paste Area', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/en.js b/sources/plugins/clipboard/lang/en.js
index 4db6960..5d81cc0 100644
--- a/sources/plugins/clipboard/lang/en.js
+++ b/sources/plugins/clipboard/lang/en.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en', {
8 cut: 'Cut', 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).', 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', 10 paste: 'Paste',
11 pasteArea: 'Paste Area', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/eo.js b/sources/plugins/clipboard/lang/eo.js
index 2df4150..3a01213 100644
--- a/sources/plugins/clipboard/lang/eo.js
+++ b/sources/plugins/clipboard/lang/eo.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'eo', {
8 cut: 'Eltondi', 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).', 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', 10 paste: 'Interglui',
11 pasteArea: 'Intergluoareo', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/es-mx.js b/sources/plugins/clipboard/lang/es-mx.js
new file mode 100644
index 0000000..f4a1be2
--- /dev/null
+++ b/sources/plugins/clipboard/lang/es-mx.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( 'clipboard', 'es-mx', {
6 copy: 'Copiar',
7 copyError: 'La configuración de seguridad de su navegador no permite al editor ejecutar automáticamente operaciones de copiado. Por favor, utilice el teclado para (Ctrl/Cmd+C).',
8 cut: 'Cortar',
9 cutError: 'La configuración de seguridad de su navegador no permite al editor ejecutar automáticamente operaciones de corte. Por favor, utilice el teclado para (Ctrl/Cmd+X).',
10 paste: 'Pegar',
11 pasteNotification: 'Tu navegador no permite pegar de esta manera. Presiona %1 para pegar.'
12} );
diff --git a/sources/plugins/clipboard/lang/es.js b/sources/plugins/clipboard/lang/es.js
index c455992..741d912 100644
--- a/sources/plugins/clipboard/lang/es.js
+++ b/sources/plugins/clipboard/lang/es.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'es', {
8 cut: 'Cortar', 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).', 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', 10 paste: 'Pegar',
11 pasteArea: 'Zona de pegado', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/et.js b/sources/plugins/clipboard/lang/et.js
index 7d86b30..106ca61 100644
--- a/sources/plugins/clipboard/lang/et.js
+++ b/sources/plugins/clipboard/lang/et.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'et', {
8 cut: 'Lõika', 8 cut: 'Lõika',
9 cutError: 'Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).', 9 cutError: 'Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).',
10 paste: 'Aseta', 10 paste: 'Aseta',
11 pasteArea: 'Asetamise ala', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/eu.js b/sources/plugins/clipboard/lang/eu.js
index 93240b5..140fcb8 100644
--- a/sources/plugins/clipboard/lang/eu.js
+++ b/sources/plugins/clipboard/lang/eu.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'eu', {
8 cut: 'Ebaki', 8 cut: 'Ebaki',
9 cutError: 'Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki moztea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+X).', 9 cutError: 'Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki moztea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+X).',
10 paste: 'Itsatsi', 10 paste: 'Itsatsi',
11 pasteArea: 'Itsasteko area', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/fa.js b/sources/plugins/clipboard/lang/fa.js
index 8abee21..8dca4b3 100644
--- a/sources/plugins/clipboard/lang/fa.js
+++ b/sources/plugins/clipboard/lang/fa.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fa', {
8 cut: 'برش', 8 cut: 'برش',
9 cutError: 'تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).', 9 cutError: 'تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).',
10 paste: 'چسباندن', 10 paste: 'چسباندن',
11 pasteArea: 'محل چسباندن', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'لطفا متن را با کلیدهای (<STRONG>Ctrl/Cmd+V</STRONG>) در این جعبهٴ متنی بچسبانید و <STRONG>پذیرش</STRONG> را بزنید.',
13 securityMsg: 'به خاطر تنظیمات امنیتی مرورگر شما، ویرایشگر نمیتواند دسترسی مستقیم به دادههای clipboard داشته باشد. شما باید دوباره آنرا در این پنجره بچسبانید.',
14 title: 'چسباندن'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/fi.js b/sources/plugins/clipboard/lang/fi.js
index d165fb3..b2db77a 100644
--- a/sources/plugins/clipboard/lang/fi.js
+++ b/sources/plugins/clipboard/lang/fi.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fi', {
8 cut: 'Leikkaa', 8 cut: 'Leikkaa',
9 cutError: 'Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).', 9 cutError: 'Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).',
10 paste: 'Liitä', 10 paste: 'Liitä',
11 pasteArea: 'Leikealue', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/fo.js b/sources/plugins/clipboard/lang/fo.js
index 5c1ec8a..8485ef3 100644
--- a/sources/plugins/clipboard/lang/fo.js
+++ b/sources/plugins/clipboard/lang/fo.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fo', {
8 cut: 'Kvett', 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).', 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', 10 paste: 'Innrita',
11 pasteArea: 'Avritingarumráði', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/fr-ca.js b/sources/plugins/clipboard/lang/fr-ca.js
index 3425f56..1a2dd3d 100644
--- a/sources/plugins/clipboard/lang/fr-ca.js
+++ b/sources/plugins/clipboard/lang/fr-ca.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fr-ca', {
8 cut: 'Couper', 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).', 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', 10 paste: 'Coller',
11 pasteArea: 'Coller la zone', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/fr.js b/sources/plugins/clipboard/lang/fr.js
index bb8349f..054d055 100644
--- a/sources/plugins/clipboard/lang/fr.js
+++ b/sources/plugins/clipboard/lang/fr.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fr', {
8 cut: 'Couper', 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).', 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', 10 paste: 'Coller',
11 pasteArea: 'Coller la zone', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/gl.js b/sources/plugins/clipboard/lang/gl.js
index 3c89dd0..5b4fd1a 100644
--- a/sources/plugins/clipboard/lang/gl.js
+++ b/sources/plugins/clipboard/lang/gl.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'gl', {
8 cut: 'Cortar', 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).', 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', 10 paste: 'Pegar',
11 pasteArea: 'Zona de pegado', 11 pasteNotification: 'O seu navegador non permite pegar deste xeito. Prema %1 para pegar.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/gu.js b/sources/plugins/clipboard/lang/gu.js
index fcf039a..aeac560 100644
--- a/sources/plugins/clipboard/lang/gu.js
+++ b/sources/plugins/clipboard/lang/gu.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'gu', {
8 cut: 'કાપવું', 8 cut: 'કાપવું',
9 cutError: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસ કટ કરવાની પરવાનગી નથી આપતી. (Ctrl/Cmd+X) નો ઉપયોગ કરો.', 9 cutError: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસ કટ કરવાની પરવાનગી નથી આપતી. (Ctrl/Cmd+X) નો ઉપયોગ કરો.',
10 paste: 'પેસ્ટ', 10 paste: 'પેસ્ટ',
11 pasteArea: 'પેસ્ટ કરવાની જગ્યા', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'Ctrl/Cmd+V નો પ્રયોગ કરી પેસ્ટ કરો',
13 securityMsg: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસના કારણે,એડિટર તમારા કિલ્પબોર્ડ ડેટા ને કોપી નથી કરી શકતો. તમારે આ વિન્ડોમાં ફરીથી પેસ્ટ કરવું પડશે.',
14 title: 'પેસ્ટ'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/he.js b/sources/plugins/clipboard/lang/he.js
index a3726c3..460b9c6 100644
--- a/sources/plugins/clipboard/lang/he.js
+++ b/sources/plugins/clipboard/lang/he.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'he', {
8 cut: 'גזירה', 8 cut: 'גזירה',
9 cutError: 'הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות גזירה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+X).', 9 cutError: 'הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות גזירה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+X).',
10 paste: 'הדבקה', 10 paste: 'הדבקה',
11 pasteArea: 'איזור הדבקה', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'נא להדביק בתוך הקופסה באמצעות (<b>Ctrl/Cmd+V</b>) וללחוץ על <b>אישור</b>.',
13 securityMsg: 'עקב הגדרות אבטחה בדפדפן, לא ניתן לגשת אל לוח הגזירים (Clipboard) בצורה ישירה. נא להדביק שוב בחלון זה.',
14 title: 'הדבקה'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/hi.js b/sources/plugins/clipboard/lang/hi.js
index 738b0b9..112853c 100644
--- a/sources/plugins/clipboard/lang/hi.js
+++ b/sources/plugins/clipboard/lang/hi.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hi', {
8 cut: 'कट', 8 cut: 'कट',
9 cutError: 'आपके ब्राउज़र की सुरक्षा सॅटिन्ग्स ने कट करने की अनुमति नहीं प्रदान की है। (Ctrl/Cmd+X) का प्रयोग करें।', 9 cutError: 'आपके ब्राउज़र की सुरक्षा सॅटिन्ग्स ने कट करने की अनुमति नहीं प्रदान की है। (Ctrl/Cmd+X) का प्रयोग करें।',
10 paste: 'पेस्ट', 10 paste: 'पेस्ट',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'Ctrl/Cmd+V का प्रयोग करके पेस्ट करें और ठीक है करें.',
13 securityMsg: 'आपके ब्राउज़र की सुरक्षा आपके ब्राउज़र की सुरKश सैटिंग के कारण, एडिटर आपके क्लिपबोर्ड डेटा को नहीं पा सकता है. आपको उसे इस विन्डो में दोबारा पेस्ट करना होगा.',
14 title: 'पेस्ट'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/hr.js b/sources/plugins/clipboard/lang/hr.js
index 7366069..4eff9ce 100644
--- a/sources/plugins/clipboard/lang/hr.js
+++ b/sources/plugins/clipboard/lang/hr.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hr', {
8 cut: 'Izreži', 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).', 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', 10 paste: 'Zalijepi',
11 pasteArea: 'Prostor za ljepljenje', 11 pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje na ovaj način. Za lijepljenje, pritisnite %1.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/hu.js b/sources/plugins/clipboard/lang/hu.js
index b124e35..646fb15 100644
--- a/sources/plugins/clipboard/lang/hu.js
+++ b/sources/plugins/clipboard/lang/hu.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hu', {
8 cut: 'Kivágás', 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).', 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', 10 paste: 'Beillesztés',
11 pasteArea: 'Beszúrás mező', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/id.js b/sources/plugins/clipboard/lang/id.js
index e7b40ad..b68425f 100644
--- a/sources/plugins/clipboard/lang/id.js
+++ b/sources/plugins/clipboard/lang/id.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'id', {
8 cut: 'Potong', 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 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', 10 paste: 'Tempel',
11 pasteArea: 'Area Tempel', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/is.js b/sources/plugins/clipboard/lang/is.js
index 6b36cef..32a0fce 100644
--- a/sources/plugins/clipboard/lang/is.js
+++ b/sources/plugins/clipboard/lang/is.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'is', {
8 cut: 'Klippa', 8 cut: 'Klippa',
9 cutError: 'Öryggisstillingar vafrans þíns leyfa ekki klippingu texta með músaraðgerð. Notaðu lyklaborðið í klippa (Ctrl/Cmd+X).', 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', 10 paste: 'Líma',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/it.js b/sources/plugins/clipboard/lang/it.js
index 21f8815..46e015c 100644
--- a/sources/plugins/clipboard/lang/it.js
+++ b/sources/plugins/clipboard/lang/it.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'it', {
8 cut: 'Taglia', 8 cut: 'Taglia',
9 cutError: 'Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+X).', 9 cutError: 'Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+X).',
10 paste: 'Incolla', 10 paste: 'Incolla',
11 pasteArea: 'Incolla', 11 pasteNotification: 'Il browser non permette di incollare in questo modo. Premere %1 per incollare.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ja.js b/sources/plugins/clipboard/lang/ja.js
index f099380..f527e7c 100644
--- a/sources/plugins/clipboard/lang/ja.js
+++ b/sources/plugins/clipboard/lang/ja.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ja', {
8 cut: '切り取り', 8 cut: '切り取り',
9 cutError: 'ブラウザーのセキュリティ設定によりエディタの切り取り操作を自動で実行することができません。実行するには手動でキーボードの(Ctrl/Cmd+X)を使用してください。', 9 cutError: 'ブラウザーのセキュリティ設定によりエディタの切り取り操作を自動で実行することができません。実行するには手動でキーボードの(Ctrl/Cmd+X)を使用してください。',
10 paste: '貼り付け', 10 paste: '貼り付け',
11 pasteArea: '貼り付け場所', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'キーボード(<STRONG>Ctrl/Cmd+V</STRONG>)を使用して、次の入力エリア内で貼り付けて、<STRONG>OK</STRONG>を押してください。',
13 securityMsg: 'ブラウザのセキュリティ設定により、エディタはクリップボードデータに直接アクセスすることができません。このウィンドウは貼り付け操作を行う度に表示されます。',
14 title: '貼り付け'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ka.js b/sources/plugins/clipboard/lang/ka.js
index e1af8cb..2fa9e23 100644
--- a/sources/plugins/clipboard/lang/ka.js
+++ b/sources/plugins/clipboard/lang/ka.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ka', {
8 cut: 'ამოჭრა', 8 cut: 'ამოჭრა',
9 cutError: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა ამოჭრის ოპერაციის ავტომატურად განხორციელების საშუალებას. გამოიყენეთ კლავიატურა ამისთვის (Ctrl/Cmd+X).', 9 cutError: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა ამოჭრის ოპერაციის ავტომატურად განხორციელების საშუალებას. გამოიყენეთ კლავიატურა ამისთვის (Ctrl/Cmd+X).',
10 paste: 'ჩასმა', 10 paste: 'ჩასმა',
11 pasteArea: 'ჩასმის არე', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'ჩასვით ამ არის შიგნით კლავიატურის გამოყენებით (<strong>Ctrl/Cmd+V</strong>) და დააჭირეთ OK-ს',
13 securityMsg: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა clipboard-ის მონაცემების წვდომის უფლებას. კიდევ უნდა ჩასვათ ტექსტი ამ ფანჯარაში.',
14 title: 'ჩასმა'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/km.js b/sources/plugins/clipboard/lang/km.js
index 32c30cb..dc66ee8 100644
--- a/sources/plugins/clipboard/lang/km.js
+++ b/sources/plugins/clipboard/lang/km.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'km', {
8 cut: 'កាត់យក', 8 cut: 'កាត់យក',
9 cutError: 'ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ កាត់អត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl/Cmd+X) ។', 9 cutError: 'ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ កាត់អត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl/Cmd+X) ។',
10 paste: 'បិទ​ភ្ជាប់', 10 paste: 'បិទ​ភ្ជាប់',
11 pasteArea: 'តំបន់​បិទ​ភ្ជាប់', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'សូមចំលងអត្ថបទទៅដាក់ក្នុងប្រអប់ដូចខាងក្រោមដោយប្រើប្រាស់ ឃី ​(<STRONG>Ctrl/Cmd+V</STRONG>) ហើយចុច <STRONG>OK</STRONG> ។',
13 securityMsg: 'ព្រោះតែ​ការកំណត់​សុវត្ថិភាព ប្រអប់សរសេរ​មិន​អាចចាប់​យកទិន្នន័យពីក្តារតម្បៀតខ្ទាស់​អ្នក​​ដោយផ្ទាល់​បានទេ។ អ្នក​ត្រូវចំលង​ដាក់វាម្តង​ទៀត ក្នុងផ្ទាំងនេះ។',
14 title: 'បិទ​ភ្ជាប់'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ko.js b/sources/plugins/clipboard/lang/ko.js
index 0a0d1e9..8472358 100644
--- a/sources/plugins/clipboard/lang/ko.js
+++ b/sources/plugins/clipboard/lang/ko.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ko', {
8 cut: '잘라내기', 8 cut: '잘라내기',
9 cutError: '브라우저의 보안설정 때문에 잘라내기 기능을 실행할 수 없습니다. 키보드(Ctrl/Cmd+X)를 이용해서 잘라내기 하십시오', 9 cutError: '브라우저의 보안설정 때문에 잘라내기 기능을 실행할 수 없습니다. 키보드(Ctrl/Cmd+X)를 이용해서 잘라내기 하십시오',
10 paste: '붙여넣기', 10 paste: '붙여넣기',
11 pasteArea: '붙여넣기 범위', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: '키보드(<strong>Ctrl/Cmd+V</strong>)를 이용해서 상자안에 붙여넣고 <strong>확인</strong> 를 누르세요.',
13 securityMsg: '브라우저 보안 설정으로 인해, 클립보드에 직접 접근할 수 없습니다. 이 창에 다시 붙여넣기 하십시오.',
14 title: '붙여넣기'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ku.js b/sources/plugins/clipboard/lang/ku.js
index 86e1778..b87aa8b 100644
--- a/sources/plugins/clipboard/lang/ku.js
+++ b/sources/plugins/clipboard/lang/ku.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ku', {
8 cut: 'بڕین', 8 cut: 'بڕین',
9 cutError: 'پارێزی وێبگەڕەکەت ڕێگەنادات بە سەرنووسەکە لەبڕینی خۆکارانە. تکایە لەبری ئەمە ئەم فەرمانە بەکاربهێنە بەداگرتنی کلیلی (Ctrl/Cmd+X).', 9 cutError: 'پارێزی وێبگەڕەکەت ڕێگەنادات بە سەرنووسەکە لەبڕینی خۆکارانە. تکایە لەبری ئەمە ئەم فەرمانە بەکاربهێنە بەداگرتنی کلیلی (Ctrl/Cmd+X).',
10 paste: 'لکاندن', 10 paste: 'لکاندن',
11 pasteArea: 'ناوچەی لکاندن', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'تکایە بیلکێنە لەناوەوەی ئەم سنوقە لەڕێی تەختەکلیلەکەت بە بەکارهێنانی کلیلی (<STRONG>Ctrl/Cmd+V</STRONG>) دووای کلیکی باشە بکە.',
13 securityMsg: 'بەهۆی شێوەپێدانی پارێزی وێبگەڕەکەت، سەرنووسەکه ناتوانێت دەستبگەیەنێت بەهەڵگیراوەکە ڕاستەوخۆ. بۆیه پێویسته دووباره بیلکێنیت لەم پەنجەرەیه.',
14 title: 'لکاندن'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/lt.js b/sources/plugins/clipboard/lang/lt.js
index 86ecbbb..c8d3611 100644
--- a/sources/plugins/clipboard/lang/lt.js
+++ b/sources/plugins/clipboard/lang/lt.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'lt', {
8 cut: 'Iškirpti', 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).', 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', 10 paste: 'Įdėti',
11 pasteArea: 'Įkelti dalį', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/lv.js b/sources/plugins/clipboard/lang/lv.js
index c762fc6..49775de 100644
--- a/sources/plugins/clipboard/lang/lv.js
+++ b/sources/plugins/clipboard/lang/lv.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'lv', {
8 cut: 'Izgriezt', 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.', 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', 10 paste: 'Ielīmēt',
11 pasteArea: 'Ielīmēšanas zona', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/mk.js b/sources/plugins/clipboard/lang/mk.js
index eb16066..07a3d56 100644
--- a/sources/plugins/clipboard/lang/mk.js
+++ b/sources/plugins/clipboard/lang/mk.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'mk', {
8 cut: 'Исечи (Cut)', 8 cut: 'Исечи (Cut)',
9 cutError: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот автоматски да изврши сечење. Ве молиме употребете ја тастатурата. (Ctrl/Cmd+C)', 9 cutError: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот автоматски да изврши сечење. Ве молиме употребете ја тастатурата. (Ctrl/Cmd+C)',
10 paste: 'Залепи (Paste)', 10 paste: 'Залепи (Paste)',
11 pasteArea: 'Простор за залепување', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'Ве молиме да залепите во следниот квадрат користејќи ја тастатурата (<string>Ctrl/Cmd+V</string>) и да притиснете OK',
13 securityMsg: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот директно да пристапи до копираните податоци. Потребно е повторно да се обидете во овој прозорец.',
14 title: 'Залепи (Paste)'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/mn.js b/sources/plugins/clipboard/lang/mn.js
index 5351941..3ba66f5 100644
--- a/sources/plugins/clipboard/lang/mn.js
+++ b/sources/plugins/clipboard/lang/mn.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'mn', {
8 cut: 'Хайчлах', 8 cut: 'Хайчлах',
9 cutError: 'Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хайчлах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl/Cmd+X) товчны хослолыг ашиглана уу.', 9 cutError: 'Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хайчлах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl/Cmd+X) товчны хослолыг ашиглана уу.',
10 paste: 'Буулгах', 10 paste: 'Буулгах',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: '(<strong>Ctrl/Cmd+V</strong>) товчийг ашиглан paste хийнэ үү. Мөн <strong>OK</strong> дар.',
13 securityMsg: 'Таны үзүүлэгч/browser/-н хамгаалалтын тохиргооноос болоод editor clipboard өгөгдөлрүү шууд хандах боломжгүй. Энэ цонход дахин paste хийхийг оролд.',
14 title: 'Буулгах'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ms.js b/sources/plugins/clipboard/lang/ms.js
index 3a01be4..b9e479a 100644
--- a/sources/plugins/clipboard/lang/ms.js
+++ b/sources/plugins/clipboard/lang/ms.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ms', {
8 cut: 'Potong', 8 cut: 'Potong',
9 cutError: 'Keselamatan perisian browser anda tidak membenarkan operasi suntingan text/imej. Sila gunakan papan kekunci (Ctrl/Cmd+X).', 9 cutError: 'Keselamatan perisian browser anda tidak membenarkan operasi suntingan text/imej. Sila gunakan papan kekunci (Ctrl/Cmd+X).',
10 paste: 'Tampal', 10 paste: 'Tampal',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/nb.js b/sources/plugins/clipboard/lang/nb.js
index 5355b8a..bdf1563 100644
--- a/sources/plugins/clipboard/lang/nb.js
+++ b/sources/plugins/clipboard/lang/nb.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'nb', {
8 cut: 'Klipp ut', 8 cut: 'Klipp ut',
9 cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk tastatursnarveien (Ctrl/Cmd+X).', 9 cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk tastatursnarveien (Ctrl/Cmd+X).',
10 paste: 'Lim inn', 10 paste: 'Lim inn',
11 pasteArea: 'Innlimingsområde', 11 pasteNotification: 'Nettleseren din lar deg ikke lime inn på denne måten. Trykk %1 for å lime inn.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/nl.js b/sources/plugins/clipboard/lang/nl.js
index bae806f..16bafd8 100644
--- a/sources/plugins/clipboard/lang/nl.js
+++ b/sources/plugins/clipboard/lang/nl.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'nl', {
8 cut: 'Knippen', 8 cut: 'Knippen',
9 cutError: 'De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl/Cmd+X van het toetsenbord.', 9 cutError: 'De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl/Cmd+X van het toetsenbord.',
10 paste: 'Plakken', 10 paste: 'Plakken',
11 pasteArea: 'Plakgebied', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/no.js b/sources/plugins/clipboard/lang/no.js
index e8c48da..77ff08a 100644
--- a/sources/plugins/clipboard/lang/no.js
+++ b/sources/plugins/clipboard/lang/no.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'no', {
8 cut: 'Klipp ut', 8 cut: 'Klipp ut',
9 cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk snarveien (Ctrl/Cmd+X).', 9 cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk snarveien (Ctrl/Cmd+X).',
10 paste: 'Lim inn', 10 paste: 'Lim inn',
11 pasteArea: 'Innlimingsområde', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/oc.js b/sources/plugins/clipboard/lang/oc.js
index e9e78cd..40d99fa 100644
--- a/sources/plugins/clipboard/lang/oc.js
+++ b/sources/plugins/clipboard/lang/oc.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'oc', {
8 cut: 'Talhar', 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).', 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', 10 paste: 'Pegar',
11 pasteArea: 'Pegar la zòna', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/pl.js b/sources/plugins/clipboard/lang/pl.js
index e2ccd16..494c9c1 100644
--- a/sources/plugins/clipboard/lang/pl.js
+++ b/sources/plugins/clipboard/lang/pl.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pl', {
8 cut: 'Wytnij', 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.', 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', 10 paste: 'Wklej',
11 pasteArea: 'Obszar wklejania', 11 pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/pt-br.js b/sources/plugins/clipboard/lang/pt-br.js
index 74608ba..e0359d9 100644
--- a/sources/plugins/clipboard/lang/pt-br.js
+++ b/sources/plugins/clipboard/lang/pt-br.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pt-br', {
8 cut: 'Recortar', 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).', 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', 10 paste: 'Colar',
11 pasteArea: 'Área para Colar', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/pt.js b/sources/plugins/clipboard/lang/pt.js
index 623ce06..6a6df67 100644
--- a/sources/plugins/clipboard/lang/pt.js
+++ b/sources/plugins/clipboard/lang/pt.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pt', {
8 cut: 'Cortar', 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).', 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', 10 paste: 'Colar',
11 pasteArea: 'Colar área', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ro.js b/sources/plugins/clipboard/lang/ro.js
index 1e57798..4eb472a 100644
--- a/sources/plugins/clipboard/lang/ro.js
+++ b/sources/plugins/clipboard/lang/ro.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ro', {
8 cut: 'Taie', 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).', 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ă', 10 paste: 'Adaugă',
11 pasteArea: 'Suprafața de adăugare', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ru.js b/sources/plugins/clipboard/lang/ru.js
index d9b4d58..9ef951f 100644
--- a/sources/plugins/clipboard/lang/ru.js
+++ b/sources/plugins/clipboard/lang/ru.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ru', {
8 cut: 'Вырезать', 8 cut: 'Вырезать',
9 cutError: 'Настройки безопасности вашего браузера не разрешают редактору выполнять операции по вырезке текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+X).', 9 cutError: 'Настройки безопасности вашего браузера не разрешают редактору выполнять операции по вырезке текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+X).',
10 paste: 'Вставить', 10 paste: 'Вставить',
11 pasteArea: 'Зона для вставки', 11 pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1'
12 pasteMsg: 'Пожалуйста, вставьте текст в зону ниже, используя клавиатуру (<strong>Ctrl/Cmd+V</strong>) и нажмите кнопку "OK".',
13 securityMsg: 'Настройки безопасности вашего браузера не разрешают редактору напрямую обращаться к буферу обмена. Вы должны вставить текст снова в это окно.',
14 title: 'Вставить'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/si.js b/sources/plugins/clipboard/lang/si.js
index 8430d01..7356cf4 100644
--- a/sources/plugins/clipboard/lang/si.js
+++ b/sources/plugins/clipboard/lang/si.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'si', {
8 cut: 'කපාගන්න', 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 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: 'අලවන්න', 10 paste: 'අලවන්න',
11 pasteArea: 'අලවන ප්‍රදේශ', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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: 'අලවන්න'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/sk.js b/sources/plugins/clipboard/lang/sk.js
index 6b2b4f4..b844e58 100644
--- a/sources/plugins/clipboard/lang/sk.js
+++ b/sources/plugins/clipboard/lang/sk.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sk', {
8 cut: 'Vystrihnúť', 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).', 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ť', 10 paste: 'Vložiť',
11 pasteArea: 'Miesto na vloženie', 11 pasteNotification: 'Váš prehliadač nepovoľuje prilepiť text takýmto spôsobom. Pre prilepenie stlačte %1.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/sl.js b/sources/plugins/clipboard/lang/sl.js
index 3ddc89e..787e6fc 100644
--- a/sources/plugins/clipboard/lang/sl.js
+++ b/sources/plugins/clipboard/lang/sl.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sl', {
8 cut: 'Izreži', 8 cut: 'Izreži',
9 cutError: 'Varnostne nastavitve brskalnika ne dopuščajo samodejnega izrezovanja. Uporabite kombinacijo tipk na tipkovnici (Ctrl/Cmd+X).', 9 cutError: 'Varnostne nastavitve brskalnika ne dopuščajo samodejnega izrezovanja. Uporabite kombinacijo tipk na tipkovnici (Ctrl/Cmd+X).',
10 paste: 'Prilepi', 10 paste: 'Prilepi',
11 pasteArea: 'Prilepi območje', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/sq.js b/sources/plugins/clipboard/lang/sq.js
index eda22e7..d78b2e7 100644
--- a/sources/plugins/clipboard/lang/sq.js
+++ b/sources/plugins/clipboard/lang/sq.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sq', {
8 cut: 'Preje', 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).', 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', 10 paste: 'Hidhe',
11 pasteArea: 'Hapësira Hedhëse', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/sr-latn.js b/sources/plugins/clipboard/lang/sr-latn.js
index 52102f6..797429f 100644
--- a/sources/plugins/clipboard/lang/sr-latn.js
+++ b/sources/plugins/clipboard/lang/sr-latn.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sr-latn', {
8 cut: 'Iseci', 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).', 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', 10 paste: 'Zalepi',
11 pasteArea: 'Prostor za lepljenje', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/sr.js b/sources/plugins/clipboard/lang/sr.js
index c59ff1f..bd4e655 100644
--- a/sources/plugins/clipboard/lang/sr.js
+++ b/sources/plugins/clipboard/lang/sr.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sr', {
8 cut: 'Исеци', 8 cut: 'Исеци',
9 cutError: 'Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског исецања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl/Cmd+X).', 9 cutError: 'Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског исецања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl/Cmd+X).',
10 paste: 'Залепи', 10 paste: 'Залепи',
11 pasteArea: 'Залепи зону', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'Молимо Вас да залепите унутар доње површине користећи тастатурну пречицу (<STRONG>Ctrl/Cmd+V</STRONG>) и да притиснете <STRONG>OK</STRONG>.',
13 securityMsg: 'Због сигурносних подешавања претраживача, едитор не може да приступи оставу. Требате да га поново залепите у овом прозору.',
14 title: 'Залепи'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/sv.js b/sources/plugins/clipboard/lang/sv.js
index 9663daa..d1ab00b 100644
--- a/sources/plugins/clipboard/lang/sv.js
+++ b/sources/plugins/clipboard/lang/sv.js
@@ -4,12 +4,9 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
4*/ 4*/
5CKEDITOR.plugins.setLang( 'clipboard', 'sv', { 5CKEDITOR.plugins.setLang( 'clipboard', 'sv', {
6 copy: 'Kopiera', 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.', 7 copyError: 'Säkerhetsinställningar i din webbläsare tillåter inte åtgärden kopiera. Använd (Ctrl/Cmd+C) istället.',
8 cut: 'Klipp ut', 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.', 9 cutError: 'Säkerhetsinställningar i din webbläsare tillåter inte åtgärden klipp ut. Använd (Ctrl/Cmd+X) istället.',
10 paste: 'Klistra in', 10 paste: 'Klistra in',
11 pasteArea: 'Paste Area', 11 pasteNotification: 'Din webbläsare tillåter dig inte att klistra in på detta vis. Tryck på %1 för att klistra in.'
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/th.js b/sources/plugins/clipboard/lang/th.js
index 29664a6..b645b90 100644
--- a/sources/plugins/clipboard/lang/th.js
+++ b/sources/plugins/clipboard/lang/th.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'th', {
8 cut: 'ตัด', 8 cut: 'ตัด',
9 cutError: 'ไม่สามารถตัดข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl/Cmd และตัว X พร้อมกัน).', 9 cutError: 'ไม่สามารถตัดข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl/Cmd และตัว X พร้อมกัน).',
10 paste: 'วาง', 10 paste: 'วาง',
11 pasteArea: 'Paste Area', // MISSING 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/tr.js b/sources/plugins/clipboard/lang/tr.js
index a60ddc7..4645335 100644
--- a/sources/plugins/clipboard/lang/tr.js
+++ b/sources/plugins/clipboard/lang/tr.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'tr', {
8 cut: 'Kes', 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.', 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', 10 paste: 'Yapıştır',
11 pasteArea: 'Yapıştırma Alanı', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/tt.js b/sources/plugins/clipboard/lang/tt.js
index e4b0537..5e641e3 100644
--- a/sources/plugins/clipboard/lang/tt.js
+++ b/sources/plugins/clipboard/lang/tt.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'tt', {
8 cut: 'Кисеп алу', 8 cut: 'Кисеп алу',
9 cutError: 'Браузерыгызның иминлек үзлекләре автоматик рәвештә күчермәләү үтәүне тыя. Тиз төймәләрне (Ctrl/Cmd+C) кулланыгыз.', 9 cutError: 'Браузерыгызның иминлек үзлекләре автоматик рәвештә күчермәләү үтәүне тыя. Тиз төймәләрне (Ctrl/Cmd+C) кулланыгыз.',
10 paste: 'Өстәү', 10 paste: 'Өстәү',
11 pasteArea: 'Өстәү мәйданы', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // 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: 'Өстәү'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/ug.js b/sources/plugins/clipboard/lang/ug.js
index dcdf29c..deb1d2b 100644
--- a/sources/plugins/clipboard/lang/ug.js
+++ b/sources/plugins/clipboard/lang/ug.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ug', {
8 cut: 'كەس', 8 cut: 'كەس',
9 cutError: 'تور كۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى تەھرىرلىگۈچنىڭ كەس مەشغۇلاتىنى ئۆزلۈكىدىن ئىجرا قىلىشىغا يول قويمايدۇ، ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+X) ئارقىلىق تاماملاڭ', 9 cutError: 'تور كۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى تەھرىرلىگۈچنىڭ كەس مەشغۇلاتىنى ئۆزلۈكىدىن ئىجرا قىلىشىغا يول قويمايدۇ، ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+X) ئارقىلىق تاماملاڭ',
10 paste: 'چاپلا', 10 paste: 'چاپلا',
11 pasteArea: 'چاپلاش دائىرىسى', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'ھەرپتاختا تېز كۇنۇپكا (<STRONG>Ctrl/Cmd+V</STRONG>) نى ئىشلىتىپ مەزمۇننى تۆۋەندىكى رامكىغا كۆچۈرۈڭ، ئاندىن <STRONG>جەزملە</STRONG>نى بېسىڭ',
13 securityMsg: 'توركۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى سەۋەبىدىن بۇ تەھرىرلىگۈچ چاپلاش تاختىسىدىكى مەزمۇننى بىۋاستە زىيارەت قىلالمايدۇ، بۇ كۆزنەكتە قايتا بىر قېتىم چاپلىشىڭىز كېرەك.',
14 title: 'چاپلا'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/uk.js b/sources/plugins/clipboard/lang/uk.js
index 242688f..f3e06a5 100644
--- a/sources/plugins/clipboard/lang/uk.js
+++ b/sources/plugins/clipboard/lang/uk.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'uk', {
8 cut: 'Вирізати', 8 cut: 'Вирізати',
9 cutError: 'Налаштування безпеки Вашого браузера не дозволяють редактору автоматично виконувати операції вирізування. Будь ласка, використовуйте клавіатуру для цього (Ctrl/Cmd+X)', 9 cutError: 'Налаштування безпеки Вашого браузера не дозволяють редактору автоматично виконувати операції вирізування. Будь ласка, використовуйте клавіатуру для цього (Ctrl/Cmd+X)',
10 paste: 'Вставити', 10 paste: 'Вставити',
11 pasteArea: 'Область вставки', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: 'Будь ласка, вставте інформацію з буфера обміну в цю область, користуючись комбінацією клавіш (<STRONG>Ctrl/Cmd+V</STRONG>), та натисніть <STRONG>OK</STRONG>.',
13 securityMsg: 'Редактор не може отримати прямий доступ до буферу обміну у зв\'язку з налаштуваннями Вашого браузера. Вам потрібно вставити інформацію в це вікно.',
14 title: 'Вставити'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/vi.js b/sources/plugins/clipboard/lang/vi.js
index fd36e1f..2928a95 100644
--- a/sources/plugins/clipboard/lang/vi.js
+++ b/sources/plugins/clipboard/lang/vi.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'vi', {
8 cut: 'Cắt', 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).', 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', 10 paste: 'Dán',
11 pasteArea: 'Khu vực dán', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
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} ); 12} );
diff --git a/sources/plugins/clipboard/lang/zh-cn.js b/sources/plugins/clipboard/lang/zh-cn.js
index 930f24e..4b738cb 100644
--- a/sources/plugins/clipboard/lang/zh-cn.js
+++ b/sources/plugins/clipboard/lang/zh-cn.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'zh-cn', {
8 cut: '剪切', 8 cut: '剪切',
9 cutError: '您的浏览器安全设置不允许编辑器自动执行剪切操作,请使用键盘快捷键(Ctrl/Cmd+X)来完成。', 9 cutError: '您的浏览器安全设置不允许编辑器自动执行剪切操作,请使用键盘快捷键(Ctrl/Cmd+X)来完成。',
10 paste: '粘贴', 10 paste: '粘贴',
11 pasteArea: '粘贴区域', 11 pasteNotification: '您的浏览器不允许用此方式粘贴,要粘贴请按 %1。'
12 pasteMsg: '请使用键盘快捷键(<STRONG>Ctrl/Cmd+V</STRONG>)把内容粘贴到下面的方框里,再按 <STRONG>确定</STRONG>',
13 securityMsg: '因为您的浏览器的安全设置原因,本编辑器不能直接访问您的剪贴板内容,你需要在本窗口重新粘贴一次。',
14 title: '粘贴'
15} ); 12} );
diff --git a/sources/plugins/clipboard/lang/zh.js b/sources/plugins/clipboard/lang/zh.js
index 33a4ef0..f91de7e 100644
--- a/sources/plugins/clipboard/lang/zh.js
+++ b/sources/plugins/clipboard/lang/zh.js
@@ -8,8 +8,5 @@ CKEDITOR.plugins.setLang( 'clipboard', 'zh', {
8 cut: '剪下', 8 cut: '剪下',
9 cutError: '瀏覽器的安全性設定不允許編輯器自動執行剪下動作。請使用鏐盤快捷鍵 (Ctrl/Cmd+X) 剪下。', 9 cutError: '瀏覽器的安全性設定不允許編輯器自動執行剪下動作。請使用鏐盤快捷鍵 (Ctrl/Cmd+X) 剪下。',
10 paste: '貼上', 10 paste: '貼上',
11 pasteArea: '貼上區', 11 pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING
12 pasteMsg: '請使用鍵盤快捷鍵 (<strong>Ctrl/Cmd+V</strong>) 貼到下方區域中並按下「確定」。',
13 securityMsg: '因為瀏覽器的安全性設定,本編輯器無法直接存取您的剪貼簿資料,請您自行在本視窗進行貼上動作。',
14 title: '貼上'
15} ); 12} );
diff --git a/sources/plugins/clipboard/plugin.js b/sources/plugins/clipboard/plugin.js
index 5c387b3..433f547 100644
--- a/sources/plugins/clipboard/plugin.js
+++ b/sources/plugins/clipboard/plugin.js
@@ -44,7 +44,6 @@
44// -- Paste command 44// -- Paste command
45// * fire 'paste' on editable ('beforepaste' for IE) 45// * fire 'paste' on editable ('beforepaste' for IE)
46// * !canceled && execCommand 'paste' 46// * !canceled && execCommand 'paste'
47// * !success && fire 'pasteDialog' on editor
48// -- Paste from native context menu & menubar 47// -- Paste from native context menu & menubar
49// (Fx & Webkits are handled in 'paste' default listener. 48// (Fx & Webkits are handled in 'paste' default listener.
50// Opera cannot be handled at all because it doesn't fire any events 49// Opera cannot be handled at all because it doesn't fire any events
@@ -117,9 +116,9 @@
117( function() { 116( function() {
118 // Register the plugin. 117 // Register the plugin.
119 CKEDITOR.plugins.add( 'clipboard', { 118 CKEDITOR.plugins.add( 'clipboard', {
120 requires: 'dialog', 119 requires: 'notification,toolbar',
121 // jscs:disable maximumLineLength 120 // 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% 121 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
123 // jscs:enable maximumLineLength 122 // jscs:enable maximumLineLength
124 icons: 'copy,copy-rtl,cut,cut-rtl,paste,paste-rtl', // %REMOVE_LINE_CORE% 123 icons: 'copy,copy-rtl,cut,cut-rtl,paste,paste-rtl', // %REMOVE_LINE_CORE%
125 hidpi: true, // %REMOVE_LINE_CORE% 124 hidpi: true, // %REMOVE_LINE_CORE%
@@ -143,8 +142,6 @@
143 initPasteClipboard( editor ); 142 initPasteClipboard( editor );
144 initDragDrop( editor ); 143 initDragDrop( editor );
145 144
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 145 // 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. 146 // step as the conversion is asynchronous and should hold all further paste processing.
150 if ( CKEDITOR.env.gecko ) { 147 if ( CKEDITOR.env.gecko ) {
@@ -156,7 +153,7 @@
156 data = dataObj.dataValue, 153 data = dataObj.dataValue,
157 dataTransfer = dataObj.dataTransfer; 154 dataTransfer = dataObj.dataTransfer;
158 155
159 // If data empty check for image content inside data transfer. #16705 156 // If data empty check for image content inside data transfer. http://dev.ckeditor.com/ticket/16705
160 if ( !data && dataObj.method == 'paste' && dataTransfer && dataTransfer.getFilesCount() == 1 && latestId != dataTransfer.id ) { 157 if ( !data && dataObj.method == 'paste' && dataTransfer && dataTransfer.getFilesCount() == 1 && latestId != dataTransfer.id ) {
161 var file = dataTransfer.getFile( 0 ); 158 var file = dataTransfer.getFile( 0 );
162 159
@@ -250,14 +247,14 @@
250 data = data.replace( /(<[^>]+) class="Apple-[^"]*"/gi, '$1' ); 247 data = data.replace( /(<[^>]+) class="Apple-[^"]*"/gi, '$1' );
251 } 248 }
252 249
253 // Strip editable that was copied from inside. (#9534) 250 // Strip editable that was copied from inside. (http://dev.ckeditor.com/ticket/9534)
254 if ( data.match( /^<[^<]+cke_(editable|contents)/i ) ) { 251 if ( data.match( /^<[^<]+cke_(editable|contents)/i ) ) {
255 var tmp, 252 var tmp,
256 editable_wrapper, 253 editable_wrapper,
257 wrapper = new CKEDITOR.dom.element( 'div' ); 254 wrapper = new CKEDITOR.dom.element( 'div' );
258 255
259 wrapper.setHtml( data ); 256 wrapper.setHtml( data );
260 // Verify for sure and check for nested editor UI parts. (#9675) 257 // Verify for sure and check for nested editor UI parts. (http://dev.ckeditor.com/ticket/9675)
261 while ( wrapper.getChildCount() == 1 && 258 while ( wrapper.getChildCount() == 1 &&
262 ( tmp = wrapper.getFirst() ) && 259 ( tmp = wrapper.getFirst() ) &&
263 tmp.type == CKEDITOR.NODE_ELEMENT && // Make sure first-child is element. 260 tmp.type == CKEDITOR.NODE_ELEMENT && // Make sure first-child is element.
@@ -299,7 +296,7 @@
299 296
300 editor.on( 'paste', function( evt ) { 297 editor.on( 'paste', function( evt ) {
301 var dataObj = evt.data, 298 var dataObj = evt.data,
302 type = dataObj.type, 299 type = editor._.nextPasteType || dataObj.type,
303 data = dataObj.dataValue, 300 data = dataObj.dataValue,
304 trueType, 301 trueType,
305 // Default is 'html'. 302 // Default is 'html'.
@@ -313,13 +310,15 @@
313 trueType = recogniseContentType( data ); 310 trueType = recogniseContentType( data );
314 } 311 }
315 312
313 delete editor._.nextPasteType;
314
316 // Unify text markup. 315 // Unify text markup.
317 if ( trueType == 'htmlifiedtext' ) { 316 if ( trueType == 'htmlifiedtext' ) {
318 data = htmlifiedTextHtmlification( editor.config, data ); 317 data = htmlifiedTextHtmlification( editor.config, data );
319 } 318 }
320 319
321 // Strip presentational markup & unify text markup. 320 // Strip presentational markup & unify text markup.
322 // Forced plain text (dialog or forcePAPT). 321 // Forced plain text.
323 // Note: we do not check dontFilter option in this case, because forcePAPT was implemented 322 // 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 323 // 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. 324 // forcePAPT should have priority as it had before 4.5.
@@ -364,17 +363,6 @@
364 }, 0 ); 363 }, 0 );
365 } 364 }
366 }, null, null, 1000 ); 365 }, 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 } 366 }
379 } ); 367 } );
380 368
@@ -402,8 +390,8 @@
402 } 390 }
403 391
404 // Because of FF bug we need to use this hack, otherwise cursor is hidden 392 // Because of FF bug we need to use this hack, otherwise cursor is hidden
405 // or it is not possible to move it (#12420). 393 // or it is not possible to move it (http://dev.ckeditor.com/ticket/12420).
406 // Also, check that editor.toolbox exists, because the toolbar plugin might not be loaded (#13305). 394 // Also, check that editor.toolbox exists, because the toolbar plugin might not be loaded (http://dev.ckeditor.com/ticket/13305).
407 if ( CKEDITOR.env.gecko && data.method == 'drop' && editor.toolbox ) { 395 if ( CKEDITOR.env.gecko && data.method == 'drop' && editor.toolbox ) {
408 editor.once( 'afterPaste', function() { 396 editor.once( 'afterPaste', function() {
409 editor.toolbox.focus(); 397 editor.toolbox.focus();
@@ -423,28 +411,25 @@
423 addButtonsCommands(); 411 addButtonsCommands();
424 412
425 /** 413 /**
426 * Gets clipboard data by directly accessing the clipboard (IE only) or opening the paste dialog window. 414 * Gets clipboard data by directly accessing the clipboard (IE only).
427 * 415 *
428 * editor.getClipboardData( { title: 'Get my data' }, function( data ) { 416 * editor.getClipboardData( function( data ) {
429 * if ( data ) 417 * if ( data )
430 * alert( data.type + ' ' + data.dataValue ); 418 * alert( data.type + ' ' + data.dataValue );
431 * } ); 419 * } );
432 * 420 *
433 * @member CKEDITOR.editor 421 * @member CKEDITOR.editor
434 * @param {Object} options 422 * @param {Function/Object} callbackOrOptions For function, see the `callback` parameter documentation. The object was used before 4.7.0 with the `title` property, to set the paste dialog's title.
435 * @param {String} [options.title] The title of the paste dialog window. 423 * @param {Function} callback A function that will be executed with the `data` property of the
436 * @param {Function} callback A function that will be executed with `data.type` and `data.dataValue` 424 * {@link CKEDITOR.editor#event-paste paste event} or `null` if none of the capturing methods succeeded.
437 * or `null` if none of the capturing methods succeeded. 425 * Since 4.7.0 the `callback` should be provided as a first argument, just like in the example above. This parameter will be removed in
426 * an upcoming major release.
438 */ 427 */
439 editor.getClipboardData = function( options, callback ) { 428 editor.getClipboardData = function( callbackOrOptions, callback ) {
440 var beforePasteNotCanceled = false,
441 dataType = 'auto',
442 dialogCommited = false;
443
444 // Options are optional - args shift. 429 // Options are optional - args shift.
445 if ( !callback ) { 430 if ( !callback ) {
446 callback = options; 431 callback = callbackOrOptions;
447 options = null; 432 callbackOrOptions = null;
448 } 433 }
449 434
450 // Listen with maximum priority to handle content before everyone else. 435 // Listen with maximum priority to handle content before everyone else.
@@ -452,39 +437,13 @@
452 // access to the clipboard succeed in IE. 437 // access to the clipboard succeed in IE.
453 editor.on( 'paste', onPaste, null, null, 0 ); 438 editor.on( 'paste', onPaste, null, null, 0 );
454 439
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 440 // If command didn't succeed (only IE allows to access clipboard and only if
463 // user agrees) open and handle paste dialog. 441 // user agrees) invoke callback with null, meaning that paste is not blocked.
464 if ( getClipboardDataDirectly() === false ) { 442 if ( getClipboardDataDirectly() === false ) {
465 // Direct access to the clipboard wasn't successful so remove listener. 443 // Direct access to the clipboard wasn't successful so remove listener.
466 editor.removeListener( 'paste', onPaste ); 444 editor.removeListener( 'paste', onPaste );
467 445
468 // If beforePaste was canceled do not open dialog. 446 callback( null );
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 } 447 }
489 448
490 function onPaste( evt ) { 449 function onPaste( evt ) {
@@ -492,30 +451,6 @@
492 evt.cancel(); 451 evt.cancel();
493 callback( evt.data ); 452 callback( evt.data );
494 } 453 }
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 }; 454 };
520 455
521 function addButtonsCommands() { 456 function addButtonsCommands() {
@@ -574,7 +509,7 @@
574 509
575 if ( CKEDITOR.plugins.clipboard.isCustomCopyCutSupported ) { 510 if ( CKEDITOR.plugins.clipboard.isCustomCopyCutSupported ) {
576 var initOnCopyCut = function( evt ) { 511 var initOnCopyCut = function( evt ) {
577 // If user tries to cut in read-only editor, we must prevent default action. (#13872) 512 // If user tries to cut in read-only editor, we must prevent default action. (http://dev.ckeditor.com/ticket/13872)
578 if ( !editor.readOnly || evt.name != 'cut' ) { 513 if ( !editor.readOnly || evt.name != 'cut' ) {
579 clipboard.initPasteDataTransfer( evt, editor ); 514 clipboard.initPasteDataTransfer( evt, editor );
580 } 515 }
@@ -586,7 +521,7 @@
586 521
587 // Delete content with the low priority so one can overwrite cut data. 522 // Delete content with the low priority so one can overwrite cut data.
588 editable.on( 'cut', function() { 523 editable.on( 'cut', function() {
589 // If user tries to cut in read-only editor, we must prevent default action. (#13872) 524 // If user tries to cut in read-only editor, we must prevent default action. (http://dev.ckeditor.com/ticket/13872)
590 if ( !editor.readOnly ) { 525 if ( !editor.readOnly ) {
591 editor.extractSelectedHtml(); 526 editor.extractSelectedHtml();
592 } 527 }
@@ -663,17 +598,15 @@
663 pasteDataFromClipboard( evt ); 598 pasteDataFromClipboard( evt );
664 599
665 // Force IE to paste content into pastebin so pasteDataFromClipboard will work. 600 // Force IE to paste content into pastebin so pasteDataFromClipboard will work.
666 if ( !execIECommand( 'paste' ) ) { 601 execIECommand( 'paste' );
667 editor.openDialog( 'paste' );
668 }
669 } ); 602 } );
670 603
671 // If mainPasteEvent is 'beforePaste' (IE before Edge), 604 // If mainPasteEvent is 'beforePaste' (IE before Edge),
672 // dismiss the (wrong) 'beforepaste' event fired on context/toolbar menu open. (#7953) 605 // dismiss the (wrong) 'beforepaste' event fired on context/toolbar menu open. (http://dev.ckeditor.com/ticket/7953)
673 editable.on( 'contextmenu', preventBeforePasteEventNow, null, null, 0 ); 606 editable.on( 'contextmenu', preventBeforePasteEventNow, null, null, 0 );
674 607
675 editable.on( 'beforepaste', function( evt ) { 608 editable.on( 'beforepaste', function( evt ) {
676 // Do not prevent event on CTRL+V and SHIFT+INS because it blocks paste (#11970). 609 // Do not prevent event on CTRL+V and SHIFT+INS because it blocks paste (http://dev.ckeditor.com/ticket/11970).
677 if ( evt.data && !evt.data.$.ctrlKey && !evt.data.$.shiftKey ) 610 if ( evt.data && !evt.data.$.ctrlKey && !evt.data.$.shiftKey )
678 preventBeforePasteEventNow(); 611 preventBeforePasteEventNow();
679 }, null, null, 0 ); 612 }, null, null, 0 );
@@ -687,7 +620,7 @@
687 620
688 // Use editor.document instead of editable in non-IEs for observing mouseup 621 // 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 622 // since editable won't fire the event if selection process started within
690 // iframe and ended out of the editor (#9851). 623 // iframe and ended out of the editor (http://dev.ckeditor.com/ticket/9851).
691 editable.attachListener( CKEDITOR.env.ie ? editable : editor.document.getDocumentElement(), 'mouseup', function() { 624 editable.attachListener( CKEDITOR.env.ie ? editable : editor.document.getDocumentElement(), 'mouseup', function() {
692 mouseupTimeout = setTimeout( function() { 625 mouseupTimeout = setTimeout( function() {
693 setToolbarStates(); 626 setToolbarStates();
@@ -696,7 +629,7 @@
696 629
697 // Make sure that deferred mouseup callback isn't executed after editor instance 630 // 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 631 // 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). 632 // with mouseup event (i.e. a button with onclick callback) (http://dev.ckeditor.com/ticket/10219).
700 editor.on( 'destroy', function() { 633 editor.on( 'destroy', function() {
701 clearTimeout( mouseupTimeout ); 634 clearTimeout( mouseupTimeout );
702 } ); 635 } );
@@ -746,27 +679,73 @@
746 canUndo: false, 679 canUndo: false,
747 async: true, 680 async: true,
748 fakeKeystroke: CKEDITOR.CTRL + 86 /*V*/, 681 fakeKeystroke: CKEDITOR.CTRL + 86 /*V*/,
682
683 /**
684 * The default implementation of the paste command.
685 *
686 * @private
687 * @param {CKEDITOR.editor} editor An instance of the editor where the command is being executed.
688 * @param {Object/String} data If `data` is a string, then it is considered content that is being pasted.
689 * Otherwise it is treated as an object with options.
690 * @param {Boolean/String} [data.notification=true] Content for a notification shown after an unsuccessful
691 * paste attempt. If `false`, the notification will not be displayed. This parameter was added in 4.7.0.
692 * @param {String} [data.type='html'] The type of pasted content. There are two allowed values:
693 * * 'html'
694 * * 'text'
695 * @param {String/Object} data.dataValue Content being pasted. If this parameter is an object, it
696 * is supposed to be a `data` property of the {@link CKEDITOR.editor#paste} event.
697 * @param {CKEDITOR.plugins.clipboard.dataTransfer} data.dataTransfer Data transfer instance connected
698 * with the current paste action.
699 * @member CKEDITOR.editor.commands.paste
700 */
749 exec: function( editor, data ) { 701 exec: function( editor, data ) {
702 data = typeof data !== 'undefined' && data !== null ? data : {};
703
750 var cmd = this, 704 var cmd = this,
751 fire = function( data, withBeforePaste ) { 705 notification = typeof data.notification !== 'undefined' ? data.notification : true,
752 data && firePasteEvents( editor, data, !!withBeforePaste ); 706 forcedType = data.type,
753 707 keystroke = CKEDITOR.tools.keystrokeToString( editor.lang.common.keyboard,
754 editor.fire( 'afterCommandExec', { 708 editor.getCommandKeystroke( this ) ),
755 name: 'paste', 709 msg = typeof notification === 'string' ? notification : editor.lang.clipboard.pasteNotification
756 command: cmd, 710 .replace( /%1/, '<kbd aria-label="' + keystroke.aria + '">' + keystroke.display + '</kbd>' ),
757 returnValue: !!data 711 pastedContent = typeof data === 'string' ? data : data.dataValue;
758 } ); 712
759 }; 713 function callback( data, withBeforePaste ) {
760 714 withBeforePaste = typeof withBeforePaste !== 'undefined' ? withBeforePaste : true;
761 // Check data precisely - don't open dialog on empty string. 715
762 if ( typeof data == 'string' ) 716 if ( data ) {
763 fire( { 717 data.method = 'paste';
764 dataValue: data, 718
765 method: 'paste', 719 if ( !data.dataTransfer ) {
766 dataTransfer: clipboard.initPasteDataTransfer() 720 data.dataTransfer = clipboard.initPasteDataTransfer();
767 }, 1 ); 721 }
768 else 722
769 editor.getClipboardData( fire ); 723 firePasteEvents( editor, data, withBeforePaste );
724 } else if ( notification ) {
725 editor.showNotification( msg, 'info', editor.config.clipboard_notificationDuration );
726 }
727
728 editor.fire( 'afterCommandExec', {
729 name: 'paste',
730 command: cmd,
731 returnValue: !!data
732 } );
733 }
734
735 // Force type for the next paste.
736 if ( forcedType ) {
737 editor._.nextPasteType = forcedType;
738 } else {
739 delete editor._.nextPasteType;
740 }
741
742 if ( typeof pastedContent === 'string' ) {
743 callback( {
744 dataValue: pastedContent
745 } );
746 } else {
747 editor.getClipboardData( callback );
748 }
770 } 749 }
771 }; 750 };
772 } 751 }
@@ -820,7 +799,7 @@
820 return enabled; 799 return enabled;
821 } 800 }
822 801
823 // Cutting off control type element in IE standards breaks the selection entirely. (#4881) 802 // Cutting off control type element in IE standards breaks the selection entirely. (http://dev.ckeditor.com/ticket/4881)
824 function fixCut() { 803 function fixCut() {
825 if ( !CKEDITOR.env.ie || CKEDITOR.env.quirks ) 804 if ( !CKEDITOR.env.ie || CKEDITOR.env.quirks )
826 return; 805 return;
@@ -857,14 +836,14 @@
857 }, 836 },
858 blurListener; 837 blurListener;
859 838
860 // Avoid recursions on 'paste' event or consequent paste too fast. (#5730) 839 // Avoid recursions on 'paste' event or consequent paste too fast. (http://dev.ckeditor.com/ticket/5730)
861 if ( doc.getById( 'cke_pastebin' ) ) 840 if ( doc.getById( 'cke_pastebin' ) )
862 return; 841 return;
863 842
864 var sel = editor.getSelection(); 843 var sel = editor.getSelection();
865 var bms = sel.createBookmarks(); 844 var bms = sel.createBookmarks();
866 845
867 // #11384. On IE9+ we use native selectionchange (i.e. editor#selectionCheck) to cache the most 846 // http://dev.ckeditor.com/ticket/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. 847 // recent selection which we then lock on editable blur. See selection.js for more info.
869 // selectionchange fired before getClipboardDataByPastebin() cached selection 848 // selectionchange fired before getClipboardDataByPastebin() cached selection
870 // before creating bookmark (cached selection will be invalid, because bookmarks modified the DOM), 849 // before creating bookmark (cached selection will be invalid, because bookmarks modified the DOM),
@@ -898,7 +877,7 @@
898 // It's better to paste close to the real paste destination, so inherited styles 877 // 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. 878 // (which Webkits will try to compensate by styling span) differs less from the destination's one.
900 editable.append( pastebin ); 879 editable.append( pastebin );
901 // Style pastebin like .cke_editable, to minimize differences between origin and destination. (#9754) 880 // Style pastebin like .cke_editable, to minimize differences between origin and destination. (http://dev.ckeditor.com/ticket/9754)
902 pastebin.addClass( 'cke_editable' ); 881 pastebin.addClass( 'cke_editable' );
903 882
904 // Compensate position of offsetParent. 883 // Compensate position of offsetParent.
@@ -932,7 +911,7 @@
932 padding: 0 911 padding: 0
933 } ); 912 } );
934 913
935 // Paste fails in Safari when the body tag has 'user-select: none'. (#12506) 914 // Paste fails in Safari when the body tag has 'user-select: none'. (http://dev.ckeditor.com/ticket/12506)
936 if ( CKEDITOR.env.safari ) 915 if ( CKEDITOR.env.safari )
937 pastebin.setStyles( CKEDITOR.tools.cssVendorPrefix( 'user-select', 'text' ) ); 916 pastebin.setStyles( CKEDITOR.tools.cssVendorPrefix( 'user-select', 'text' ) );
938 917
@@ -955,8 +934,8 @@
955 934
956 // Webkit fill fire blur on editable when moving selection to 935 // Webkit fill fire blur on editable when moving selection to
957 // pastebin (if body is used). Cancel it because it causes incorrect 936 // pastebin (if body is used). Cancel it because it causes incorrect
958 // selection lock in case of inline editor (#10644). 937 // selection lock in case of inline editor (http://dev.ckeditor.com/ticket/10644).
959 // The same seems to apply to Firefox (#10787). 938 // The same seems to apply to Firefox (http://dev.ckeditor.com/ticket/10787).
960 if ( CKEDITOR.env.webkit || CKEDITOR.env.gecko ) 939 if ( CKEDITOR.env.webkit || CKEDITOR.env.gecko )
961 blurListener = editable.once( 'blur', cancel, null, null, -100 ); 940 blurListener = editable.once( 'blur', cancel, null, null, -100 );
962 941
@@ -969,7 +948,7 @@
969 // If non-native paste is executed, IE will open security alert and blur editable. 948 // 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 949 // 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 950 // this selection will be restored. We overwrite stored selection, so it's restored
972 // in pastebin. (#9552) 951 // in pastebin. (http://dev.ckeditor.com/ticket/9552)
973 if ( CKEDITOR.env.ie ) { 952 if ( CKEDITOR.env.ie ) {
974 blurListener = editable.once( 'blur', function() { 953 blurListener = editable.once( 'blur', function() {
975 editor.lockSelection( selPastebin ); 954 editor.lockSelection( selPastebin );
@@ -981,18 +960,18 @@
981 // Wait a while and grab the pasted contents. 960 // Wait a while and grab the pasted contents.
982 setTimeout( function() { 961 setTimeout( function() {
983 // Restore main window's scroll position which could have been changed 962 // Restore main window's scroll position which could have been changed
984 // by browser in cases described in #9771. 963 // by browser in cases described in http://dev.ckeditor.com/ticket/9771.
985 if ( CKEDITOR.env.webkit ) 964 if ( CKEDITOR.env.webkit )
986 CKEDITOR.document.getBody().$.scrollTop = scrollTop; 965 CKEDITOR.document.getBody().$.scrollTop = scrollTop;
987 966
988 // Blur will be fired only on non-native paste. In other case manually remove listener. 967 // Blur will be fired only on non-native paste. In other case manually remove listener.
989 blurListener && blurListener.removeListener(); 968 blurListener && blurListener.removeListener();
990 969
991 // Restore properly the document focus. (#8849) 970 // Restore properly the document focus. (http://dev.ckeditor.com/ticket/8849)
992 if ( CKEDITOR.env.ie ) 971 if ( CKEDITOR.env.ie )
993 editable.focus(); 972 editable.focus();
994 973
995 // IE7: selection must go before removing pastebin. (#8691) 974 // IE7: selection must go before removing pastebin. (http://dev.ckeditor.com/ticket/8691)
996 sel.selectBookmarks( bms ); 975 sel.selectBookmarks( bms );
997 pastebin.remove(); 976 pastebin.remove();
998 977
@@ -1018,7 +997,6 @@
1018 // On other browsers we should fire beforePaste event and return false. 997 // On other browsers we should fire beforePaste event and return false.
1019 function getClipboardDataDirectly() { 998 function getClipboardDataDirectly() {
1020 if ( clipboard.mainPasteEvent == 'paste' ) { 999 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' } ); 1000 editor.fire( 'beforePaste', { type: 'auto', method: 'paste' } );
1023 return false; 1001 return false;
1024 } 1002 }
@@ -1031,7 +1009,7 @@
1031 // we're canceling it. 1009 // we're canceling it.
1032 preventPasteEventNow(); 1010 preventPasteEventNow();
1033 1011
1034 // #9247: Lock focus to prevent IE from hiding toolbar for inline editor. 1012 // http://dev.ckeditor.com/ticket/9247: Lock focus to prevent IE from hiding toolbar for inline editor.
1035 var focusManager = editor.focusManager; 1013 var focusManager = editor.focusManager;
1036 focusManager.lock(); 1014 focusManager.lock();
1037 1015
@@ -1074,7 +1052,7 @@
1074 editor.fire( 'saveSnapshot' ); // Save before cut 1052 editor.fire( 'saveSnapshot' ); // Save before cut
1075 setTimeout( function() { 1053 setTimeout( function() {
1076 editor.fire( 'saveSnapshot' ); // Save after cut 1054 editor.fire( 'saveSnapshot' ); // Save after cut
1077 }, 50 ); // OSX is slow (#11416). 1055 }, 50 ); // OSX is slow (http://dev.ckeditor.com/ticket/11416).
1078 } 1056 }
1079 } 1057 }
1080 1058
@@ -1327,7 +1305,7 @@
1327 1305
1328 // -------------- DRAGOVER TOP & BOTTOM -------------- 1306 // -------------- DRAGOVER TOP & BOTTOM --------------
1329 1307
1330 // Not allowing dragging on toolbar and bottom (#12613). 1308 // Not allowing dragging on toolbar and bottom (http://dev.ckeditor.com/ticket/12613).
1331 clipboard.preventDefaultDropOnElement( top ); 1309 clipboard.preventDefaultDropOnElement( top );
1332 clipboard.preventDefaultDropOnElement( bottom ); 1310 clipboard.preventDefaultDropOnElement( bottom );
1333 1311
@@ -1349,7 +1327,7 @@
1349 // Save drag range globally for cross editor D&D. 1327 // Save drag range globally for cross editor D&D.
1350 var dragRange = clipboard.dragRange = editor.getSelection().getRanges()[ 0 ]; 1328 var dragRange = clipboard.dragRange = editor.getSelection().getRanges()[ 0 ];
1351 1329
1352 // Store number of children, so we can later tell if any text node was split on drop. (#13011, #13447) 1330 // Store number of children, so we can later tell if any text node was split on drop. (http://dev.ckeditor.com/ticket/13011, http://dev.ckeditor.com/ticket/13447)
1353 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { 1331 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) {
1354 clipboard.dragStartContainerChildCount = dragRange ? getContainerChildCount( dragRange.startContainer ) : null; 1332 clipboard.dragStartContainerChildCount = dragRange ? getContainerChildCount( dragRange.startContainer ) : null;
1355 clipboard.dragEndContainerChildCount = dragRange ? getContainerChildCount( dragRange.endContainer ) : null; 1333 clipboard.dragEndContainerChildCount = dragRange ? getContainerChildCount( dragRange.endContainer ) : null;
@@ -1373,9 +1351,15 @@
1373 // we drop image it will overwrite document. 1351 // we drop image it will overwrite document.
1374 1352
1375 editable.attachListener( dropTarget, 'dragover', function( evt ) { 1353 editable.attachListener( dropTarget, 'dragover', function( evt ) {
1354 // Edge requires this handler to have `preventDefault()` regardless of the situation.
1355 if ( CKEDITOR.env.edge ) {
1356 evt.data.preventDefault();
1357 return;
1358 }
1359
1376 var target = evt.data.getTarget(); 1360 var target = evt.data.getTarget();
1377 1361
1378 // Prevent reloading page when dragging image on empty document (#12619). 1362 // Prevent reloading page when dragging image on empty document (http://dev.ckeditor.com/ticket/12619).
1379 if ( target && target.is && target.is( 'html' ) ) { 1363 if ( target && target.is && target.is( 'html' ) ) {
1380 evt.data.preventDefault(); 1364 evt.data.preventDefault();
1381 return; 1365 return;
@@ -1396,7 +1380,7 @@
1396 // -------------- DROP -------------- 1380 // -------------- DROP --------------
1397 1381
1398 editable.attachListener( dropTarget, 'drop', function( evt ) { 1382 editable.attachListener( dropTarget, 'drop', function( evt ) {
1399 // Do nothing if event was already prevented. (#13879) 1383 // Do nothing if event was already prevented. (http://dev.ckeditor.com/ticket/13879)
1400 if ( evt.data.$.defaultPrevented ) { 1384 if ( evt.data.$.defaultPrevented ) {
1401 return; 1385 return;
1402 } 1386 }
@@ -1407,7 +1391,7 @@
1407 var target = evt.data.getTarget(), 1391 var target = evt.data.getTarget(),
1408 readOnly = target.isReadOnly(); 1392 readOnly = target.isReadOnly();
1409 1393
1410 // Do nothing if drop on non editable element (#13015). 1394 // Do nothing if drop on non editable element (http://dev.ckeditor.com/ticket/13015).
1411 // The <html> tag isn't editable (body is), but we want to allow drop on it 1395 // 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). 1396 // (so it is possible to drop below editor contents).
1413 if ( readOnly && !( target.type == CKEDITOR.NODE_ELEMENT && target.is( 'html' ) ) ) { 1397 if ( readOnly && !( target.type == CKEDITOR.NODE_ELEMENT && target.is( 'html' ) ) ) {
@@ -1582,18 +1566,24 @@
1582 } 1566 }
1583 1567
1584 // In Chrome we can trust Clipboard API, with the exception of Chrome on Android (in both - mobile and desktop modes), where 1568 // 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). 1569 // clipboard API is not available so we need to check it (http://dev.ckeditor.com/ticket/13187).
1586 if ( CKEDITOR.env.chrome && !dataTransfer.isEmpty() ) { 1570 if ( CKEDITOR.env.chrome && !dataTransfer.isEmpty() ) {
1587 return true; 1571 return true;
1588 } 1572 }
1589 1573
1590 // Because of a Firefox bug HTML data are not available in some cases (e.g. paste from Word), in such cases we 1574 // 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). 1575 // need to use the pastebin (http://dev.ckeditor.com/ticket/13528, https://bugzilla.mozilla.org/show_bug.cgi?id=1183686).
1592 if ( CKEDITOR.env.gecko && ( dataTransfer.getData( 'text/html' ) || dataTransfer.getFilesCount() ) ) { 1576 if ( CKEDITOR.env.gecko && ( dataTransfer.getData( 'text/html' ) || dataTransfer.getFilesCount() ) ) {
1593 return true; 1577 return true;
1594 } 1578 }
1595 1579
1596 // In Safari and IE HTML data is not available though the Clipboard API. 1580 // Safari fixed clipboard in 10.1 (https://bugs.webkit.org/show_bug.cgi?id=19893) (http://dev.ckeditor.com/ticket/16982).
1581 // However iOS version still doesn't work well enough (https://bugs.webkit.org/show_bug.cgi?id=19893#c34).
1582 if ( CKEDITOR.env.safari && CKEDITOR.env.version >= 603 && !CKEDITOR.env.iOS ) {
1583 return true;
1584 }
1585
1586 // In older Safari and IE HTML data is not available though the Clipboard API.
1597 // In Edge things are a bit messy at the moment - 1587 // 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 1588 // 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. 1589 // It is safer to use the paste bin in unknown cases.
@@ -1610,8 +1600,8 @@
1610 getDropTarget: function( editor ) { 1600 getDropTarget: function( editor ) {
1611 var editable = editor.editable(); 1601 var editable = editor.editable();
1612 1602
1613 // #11123 Firefox needs to listen on document, because otherwise event won't be fired. 1603 // http://dev.ckeditor.com/ticket/11123 Firefox needs to listen on document, because otherwise event won't be fired.
1614 // #11086 IE8 cannot listen on document. 1604 // http://dev.ckeditor.com/ticket/11086 IE8 cannot listen on document.
1615 if ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) || editable.isInline() ) { 1605 if ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) || editable.isInline() ) {
1616 return editable; 1606 return editable;
1617 } else { 1607 } else {
@@ -1809,7 +1799,7 @@
1809 // Check if drop range is inside range. 1799 // Check if drop range is inside range.
1810 // This is an edge case when we drop something on editable's margin/padding. 1800 // 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. 1801 // 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) 1802 // When we drop, browser tries to find closest drop position and it finds it inside drag range. (http://dev.ckeditor.com/ticket/13453)
1813 var startNode = dragBookmark.startNode, 1803 var startNode = dragBookmark.startNode,
1814 endNode = dragBookmark.endNode, 1804 endNode = dragBookmark.endNode,
1815 dropNode = dropBookmark.startNode, 1805 dropNode = dropBookmark.startNode,
@@ -1863,7 +1853,7 @@
1863 return dropEvt.data.testRange; 1853 return dropEvt.data.testRange;
1864 1854
1865 // Webkits. 1855 // Webkits.
1866 if ( document.caretRangeFromPoint ) { 1856 if ( document.caretRangeFromPoint && editor.document.$.caretRangeFromPoint( x, y ) ) {
1867 $range = editor.document.$.caretRangeFromPoint( x, y ); 1857 $range = editor.document.$.caretRangeFromPoint( x, y );
1868 range.setStart( CKEDITOR.dom.node( $range.startContainer ), $range.startOffset ); 1858 range.setStart( CKEDITOR.dom.node( $range.startContainer ), $range.startOffset );
1869 range.collapse( true ); 1859 range.collapse( true );
@@ -2089,7 +2079,7 @@
2089 */ 2079 */
2090 initPasteDataTransfer: function( evt, sourceEditor ) { 2080 initPasteDataTransfer: function( evt, sourceEditor ) {
2091 if ( !this.isCustomCopyCutSupported ) { 2081 if ( !this.isCustomCopyCutSupported ) {
2092 // Edge does not support custom copy/cut, but it have some useful data in the clipboardData (#13755). 2082 // Edge does not support custom copy/cut, but it have some useful data in the clipboardData (http://dev.ckeditor.com/ticket/13755).
2093 return new this.dataTransfer( ( CKEDITOR.env.edge && evt && evt.data.$ && evt.data.$.clipboardData ) || null, sourceEditor ); 2083 return new this.dataTransfer( ( CKEDITOR.env.edge && evt && evt.data.$ && evt.data.$.clipboardData ) || null, sourceEditor );
2094 } else if ( evt && evt.data && evt.data.$ ) { 2084 } else if ( evt && evt.data && evt.data.$ ) {
2095 var dataTransfer = new this.dataTransfer( evt.data.$.clipboardData, sourceEditor ); 2085 var dataTransfer = new this.dataTransfer( evt.data.$.clipboardData, sourceEditor );
@@ -2270,13 +2260,31 @@
2270 * Facade for the native `getData` method. 2260 * Facade for the native `getData` method.
2271 * 2261 *
2272 * @param {String} type The type of data to retrieve. 2262 * @param {String} type The type of data to retrieve.
2263 * @param {Boolean} [getNative=false] Indicates if the whole, original content of the dataTransfer should be returned.
2264 * Introduced in CKEditor 4.7.0.
2273 * @returns {String} type Stored data for the given type or an empty string if the data for that type does not exist. 2265 * @returns {String} type Stored data for the given type or an empty string if the data for that type does not exist.
2274 */ 2266 */
2275 getData: function( type ) { 2267 getData: function( type, getNative ) {
2276 function isEmpty( data ) { 2268 function isEmpty( data ) {
2277 return data === undefined || data === null || data === ''; 2269 return data === undefined || data === null || data === '';
2278 } 2270 }
2279 2271
2272 function filterUnwantedCharacters( data ) {
2273 if ( typeof data !== 'string' ) {
2274 return data;
2275 }
2276
2277 var htmlEnd = data.indexOf( '</html>' );
2278
2279 if ( htmlEnd !== -1 ) {
2280 // Just cut everything after `</html>`, so everything after htmlEnd index + length of `</html>`.
2281 // Required to workaround bug: https://bugs.chromium.org/p/chromium/issues/detail?id=696978
2282 return data.substring( 0, htmlEnd + 7 );
2283 }
2284
2285 return data;
2286 }
2287
2280 type = this._.normalizeType( type ); 2288 type = this._.normalizeType( type );
2281 2289
2282 var data = this._.data[ type ], 2290 var data = this._.data[ type ],
@@ -2297,8 +2305,9 @@
2297 // This code removes meta tags and returns only the contents of the <body> element if found. Note that 2305 // 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. 2306 // some significant content may be placed outside Start/EndFragment comments so it's kept.
2299 // 2307 //
2300 // See #13583 for more details. 2308 // See http://dev.ckeditor.com/ticket/13583 for more details.
2301 if ( type == 'text/html' ) { 2309 // Additionally http://dev.ckeditor.com/ticket/16847 adds a flag allowing to get the whole, original content.
2310 if ( type == 'text/html' && !getNative ) {
2302 data = data.replace( this._.metaRegExp, '' ); 2311 data = data.replace( this._.metaRegExp, '' );
2303 2312
2304 // Keep only contents of the <body> element 2313 // Keep only contents of the <body> element
@@ -2318,7 +2327,7 @@
2318 data = ''; 2327 data = '';
2319 } 2328 }
2320 2329
2321 return data; 2330 return filterUnwantedCharacters( data );
2322 }, 2331 },
2323 2332
2324 /** 2333 /**
@@ -2339,7 +2348,7 @@
2339 } 2348 }
2340 2349
2341 // If we use the text type to bind the ID, then if someone tries to set the text, we must also 2350 // 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. 2351 // update ID accordingly. http://dev.ckeditor.com/ticket/13468.
2343 if ( clipboardIdDataType == 'Text' && type == 'Text' ) { 2352 if ( clipboardIdDataType == 'Text' && type == 'Text' ) {
2344 this.id = value; 2353 this.id = value;
2345 } 2354 }
@@ -2384,7 +2393,7 @@
2384 function getAndSetData( type ) { 2393 function getAndSetData( type ) {
2385 type = that._.normalizeType( type ); 2394 type = that._.normalizeType( type );
2386 2395
2387 var data = that.getData( type ); 2396 var data = that.getData( type, true );
2388 if ( data ) { 2397 if ( data ) {
2389 that._.data[ type ] = data; 2398 that._.data[ type ] = data;
2390 } 2399 }
@@ -2407,7 +2416,7 @@
2407 if ( ( this.$ && this.$.files ) || file ) { 2416 if ( ( this.$ && this.$.files ) || file ) {
2408 this._.files = []; 2417 this._.files = [];
2409 2418
2410 // Edge have empty files property with no length (#13755). 2419 // Edge have empty files property with no length (http://dev.ckeditor.com/ticket/13755).
2411 if ( this.$.files && this.$.files.length ) { 2420 if ( this.$.files && this.$.files.length ) {
2412 for ( i = 0; i < this.$.files.length; i++ ) { 2421 for ( i = 0; i < this.$.files.length; i++ ) {
2413 this._.files.push( this.$.files[ i ] ); 2422 this._.files.push( this.$.files[ i ] );
@@ -2507,7 +2516,7 @@
2507 2516
2508 /** 2517 /**
2509 * When the content of the clipboard is pasted in Chrome, the clipboard data object has an empty `files` property, 2518 * 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). 2519 * but it is possible to get the file as `items[0].getAsFile();` (http://dev.ckeditor.com/ticket/12961).
2511 * 2520 *
2512 * @private 2521 * @private
2513 * @returns {File} File instance or `null` if not found. 2522 * @returns {File} File instance or `null` if not found.
@@ -2593,7 +2602,7 @@
2593 * @member CKEDITOR.editor 2602 * @member CKEDITOR.editor
2594 */ 2603 */
2595 2604
2596 /** 2605/**
2597 * Fired after the {@link #paste} event if content was modified. Note that if the paste 2606 * 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. 2607 * event does not insert any data, the `afterPaste` event will not be fired.
2599 * 2608 *
@@ -2602,16 +2611,6 @@
2602 */ 2611 */
2603 2612
2604/** 2613/**
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. 2614 * Facade for the native `drop` event. Fired when the native `drop` event occurs.
2616 * 2615 *
2617 * **Note:** To manipulate dropped data, use the {@link CKEDITOR.editor#paste} event. 2616 * **Note:** To manipulate dropped data, use the {@link CKEDITOR.editor#paste} event.
@@ -2770,3 +2769,12 @@
2770 * @property {CKEDITOR.filter} [pasteFilter] 2769 * @property {CKEDITOR.filter} [pasteFilter]
2771 * @member CKEDITOR.editor 2770 * @member CKEDITOR.editor
2772 */ 2771 */
2772
2773/**
2774 * Duration of the notification displayed after pasting was blocked by the browser.
2775 *
2776 * @since 4.7.0
2777 * @cfg {Number} [clipboard_notificationDuration=10000]
2778 * @member CKEDITOR.config
2779 */
2780CKEDITOR.config.clipboard_notificationDuration = 10000;
diff --git a/sources/plugins/colorbutton/lang/az.js b/sources/plugins/colorbutton/lang/az.js
index 6d989ff..9c118ac 100644
--- a/sources/plugins/colorbutton/lang/az.js
+++ b/sources/plugins/colorbutton/lang/az.js
@@ -24,7 +24,7 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'az', {
24 '808080': 'Boz', 24 '808080': 'Boz',
25 F00: 'Qırmızı', 25 F00: 'Qırmızı',
26 FF8C00: 'Tünd narıncı', 26 FF8C00: 'Tünd narıncı',
27 FFD700: 'Qızıl', 27 FFD700: 'Qızılı',
28 '008000': 'Yaşıl', 28 '008000': 'Yaşıl',
29 '0FF': 'Mavi', 29 '0FF': 'Mavi',
30 '00F': 'Göy', 30 '00F': 'Göy',
@@ -41,33 +41,33 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'az', {
41 FFF0F5: 'Yasəmən', 41 FFF0F5: 'Yasəmən',
42 FAEBD7: 'Kağız', 42 FAEBD7: 'Kağız',
43 FFFFE0: 'Acıq sarı', 43 FFFFE0: 'Acıq sarı',
44 F0FFF0: 'Bal', 44 F0FFF0: 'Yemişi',
45 F0FFFF: 'Gömgöy', 45 F0FFFF: 'Gömgöy',
46 F0F8FF: 'Solğun göy', 46 F0F8FF: 'Solğun göy',
47 E6E6FA: 'Lavanda', 47 E6E6FA: 'Lavanda',
48 FFF: 'Ağ', 48 FFF: 'Ağ',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Güclü mavi',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'mrüd',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Parlaq göy',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametist',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Bozlu göy',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Sapsarı',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Tünd mavi',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Tünd mrüd',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Güclü göy',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Tünd bənövşəyi',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Rəngsiz göy',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Nan',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Yerkökülü',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Solğun qırmızı',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Parlaq gümüşü',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Acıq bozlu mavi',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Acıq boz',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Balqabaqlı',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Güclü qırmızı',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Gümüşü',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Bozlu mavi',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Tünd boz'
71 }, 71 },
72 more: 'Digər rənglər...', 72 more: 'Digər rənglər...',
73 panelTitle: 'Rənglər', 73 panelTitle: 'Rənglər',
diff --git a/sources/plugins/colorbutton/lang/cs.js b/sources/plugins/colorbutton/lang/cs.js
index 2361bd2..0ea045f 100644
--- a/sources/plugins/colorbutton/lang/cs.js
+++ b/sources/plugins/colorbutton/lang/cs.js
@@ -47,9 +47,9 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'cs', {
47 E6E6FA: 'Levandulová', 47 E6E6FA: 'Levandulová',
48 FFF: 'Bílá', 48 FFF: 'Bílá',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Strong Cyan', // MISSING
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Emeraldová',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Jasně modrá',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametystová',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Grayish Blue', // MISSING
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Vivid Yellow', // MISSING
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Dark Cyan', // MISSING
@@ -57,15 +57,15 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'cs', {
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Strong Blue', // MISSING
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Dark Violet', // MISSING
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturated Blue', // MISSING
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Oranžová',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Mrkvo',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Pale Red', // MISSING
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Bright Silver', // MISSING
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Light Grayish Cyan', // MISSING
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Light Gray', // MISSING
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Dýňová',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Strong Red', // MISSING
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Stříbr',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Grayish Cyan', // MISSING
70 '999': 'Dark Gray' // MISSING 70 '999': 'Dark Gray' // MISSING
71 }, 71 },
diff --git a/sources/plugins/colorbutton/lang/de.js b/sources/plugins/colorbutton/lang/de.js
index f6d8b6e..389718f 100644
--- a/sources/plugins/colorbutton/lang/de.js
+++ b/sources/plugins/colorbutton/lang/de.js
@@ -47,27 +47,27 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'de', {
47 E6E6FA: 'Lavendel', 47 E6E6FA: 'Lavendel',
48 FFF: 'Weiß', 48 FFF: 'Weiß',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Strong Cyan', // MISSING
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Smaragdgrün',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Bright Blue', // MISSING
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Amethystblau',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Graublau',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Vivid Yellow', // MISSING
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Dunkelcyan',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Dunkelsmaragdgrün',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Strong Blue', // MISSING
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Dunkelviolett',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Entsättigtes blau',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Orange',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Möhrenfarben',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Blassrot',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Glänzendes Silber',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Helles Graublau',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Hellgrau',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Kürbisfarben',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Strong Red', // MISSING
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Silber',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Graucyan',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Dunkelgrau'
71 }, 71 },
72 more: 'Weitere Farben...', 72 more: 'Weitere Farben...',
73 panelTitle: 'Farben', 73 panelTitle: 'Farben',
diff --git a/sources/plugins/colorbutton/lang/el.js b/sources/plugins/colorbutton/lang/el.js
index cb6ca5b..a61cd4a 100644
--- a/sources/plugins/colorbutton/lang/el.js
+++ b/sources/plugins/colorbutton/lang/el.js
@@ -57,15 +57,15 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'el', {
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Strong Blue', // MISSING
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Dark Violet', // MISSING
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturated Blue', // MISSING
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Πορτοκαλί',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Καροτί',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Pale Red', // MISSING
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Bright Silver', // MISSING
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Light Grayish Cyan', // MISSING
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Light Gray', // MISSING
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Pumpkin', // MISSING
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Strong Red', // MISSING
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Αργυρό',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Grayish Cyan', // MISSING
70 '999': 'Dark Gray' // MISSING 70 '999': 'Dark Gray' // MISSING
71 }, 71 },
diff --git a/sources/plugins/colorbutton/lang/eo.js b/sources/plugins/colorbutton/lang/eo.js
index 65ecc24..6bd50e8 100644
--- a/sources/plugins/colorbutton/lang/eo.js
+++ b/sources/plugins/colorbutton/lang/eo.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'eo', {
46 F0F8FF: 'Aliceblua', 46 F0F8FF: 'Aliceblua',
47 E6E6FA: 'Lavendkolora', 47 E6E6FA: 'Lavendkolora',
48 FFF: 'Blanka', 48 FFF: 'Blanka',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Fortverdblua',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Smeraldkolora',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Brilblua',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametistkolora',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Grizblua',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Brilflava',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Malhelverdblua',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Malhelsmeraldkolora',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Fortblua',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Malhelviola',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Malsaturita Bluo',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Oranĝkolora',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Karotkolora',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Pale Ruĝa',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Brile Arĝenta',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Helgrizverdblua',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Helgriza',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Kukurbokolora',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Forte ruĝa',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Arĝenta',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Grizverdblua',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Malhelgriza'
71 }, 71 },
72 more: 'Pli da Koloroj...', 72 more: 'Pli da Koloroj...',
73 panelTitle: 'Koloroj', 73 panelTitle: 'Koloroj',
diff --git a/sources/plugins/colorbutton/lang/es-mx.js b/sources/plugins/colorbutton/lang/es-mx.js
new file mode 100644
index 0000000..de3998a
--- /dev/null
+++ b/sources/plugins/colorbutton/lang/es-mx.js
@@ -0,0 +1,75 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'colorbutton', 'es-mx', {
6 auto: 'Automático',
7 bgColorTitle: 'Color de fondo',
8 colors: {
9 '000': 'Negro',
10 '800000': 'Marrón',
11 '8B4513': 'Café sucio',
12 '2F4F4F': 'Gris pizarra oscuro',
13 '008080': 'Teal',
14 '000080': 'Armada',
15 '4B0082': 'Indigo',
16 '696969': 'Gris oscuro',
17 B22222: 'Ladrillo de fuego',
18 A52A2A: 'Café',
19 DAA520: 'Barra de oro',
20 '006400': 'Verde oscuro',
21 '40E0D0': 'Turquesa',
22 '0000CD': 'Azul medio',
23 '800080': 'Morado',
24 '808080': 'Gris',
25 F00: 'Rojo',
26 FF8C00: 'Naranja oscuro',
27 FFD700: 'Oro',
28 '008000': 'Verde',
29 '0FF': 'Cian',
30 '00F': 'Azul',
31 EE82EE: 'Violeta',
32 A9A9A9: 'Gris oscuro',
33 FFA07A: 'Salmón claro',
34 FFA500: 'Naranja',
35 FFFF00: 'Amarillo',
36 '00FF00': 'Lima',
37 AFEEEE: 'Turquesa pálido',
38 ADD8E6: 'Azul claro',
39 DDA0DD: 'Ciruela',
40 D3D3D3: 'Gris claro',
41 FFF0F5: 'Rubor de lavanda',
42 FAEBD7: 'Blanco antiguo',
43 FFFFE0: 'Amarillo claro',
44 F0FFF0: 'Gotas de miel',
45 F0FFFF: 'Azul celeste',
46 F0F8FF: 'Azul Alicia',
47 E6E6FA: 'Lavanda',
48 FFF: 'Blanco',
49 '1ABC9C': 'Cian fuerte',
50 '2ECC71': 'Esmeralda',
51 '3498DB': 'Azul brillante',
52 '9B59B6': 'Amatista',
53 '4E5F70': 'Azul grisáceo',
54 'F1C40F': 'Amarillo vívido',
55 '16A085': 'Cian oscuro',
56 '27AE60': 'Esmeralda oscuro',
57 '2980B9': 'Azul fuerte',
58 '8E44AD': 'Violeta oscuro',
59 '2C3E50': 'Azul Desaturado',
60 'F39C12': 'Naranja',
61 'E67E22': 'Zanahoria',
62 'E74C3C': 'Rojo pálido',
63 'ECF0F1': 'Plata brillante',
64 '95A5A6': 'Cian grisáceo claro',
65 'DDD': 'Gris claro',
66 'D35400': 'Calabaza',
67 'C0392B': 'Rojo fuerte',
68 'BDC3C7': 'Plata',
69 '7F8C8D': 'Cian grisáceo',
70 '999': 'Gris oscuro'
71 },
72 more: 'Más colores...',
73 panelTitle: 'Colores',
74 textColorTitle: 'Color de texto'
75} );
diff --git a/sources/plugins/colorbutton/lang/fr.js b/sources/plugins/colorbutton/lang/fr.js
index 0245d8f..aa67109 100644
--- a/sources/plugins/colorbutton/lang/fr.js
+++ b/sources/plugins/colorbutton/lang/fr.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'fr', {
46 F0F8FF: 'Bleu Alice', 46 F0F8FF: 'Bleu Alice',
47 E6E6FA: 'Lavande', 47 E6E6FA: 'Lavande',
48 FFF: 'Blanc', 48 FFF: 'Blanc',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Cyan dur',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Émeraude',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Bleu brillant',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Améthyste',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Bleu-gris',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Jaune vif',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Cyan foncé',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Émeraude foncée',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Bleu dur',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Violet foncé',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Bleu désaturé',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Orange',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Carotte',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Rouge pâle',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Argent brillant',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Cyan-gris clair',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Gris clair',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Citrouille',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Rouge dur',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Argent',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Cyan-gris',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Gris foncé'
71 }, 71 },
72 more: 'Plus de couleurs...', 72 more: 'Plus de couleurs...',
73 panelTitle: 'Couleurs', 73 panelTitle: 'Couleurs',
diff --git a/sources/plugins/colorbutton/lang/gl.js b/sources/plugins/colorbutton/lang/gl.js
index b27b0bd..b72f01c 100644
--- a/sources/plugins/colorbutton/lang/gl.js
+++ b/sources/plugins/colorbutton/lang/gl.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'gl', {
46 F0F8FF: 'Azul pálido', 46 F0F8FF: 'Azul pálido',
47 E6E6FA: 'Lavanda', 47 E6E6FA: 'Lavanda',
48 FFF: 'Branco', 48 FFF: 'Branco',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Cian forte',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Esmeralda',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Azul brillante',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Amatista',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Azul agrisado',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Amarelo vívido',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Cian escuro',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Esmeralda escuro',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Azul forte',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Violeta escuro',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Azul desaturado',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Laranxa',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Cenoria',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Vermello pálido',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Plata brillante',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Cian agrisado claro',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Gris claro',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Cabaza',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Vermello forte',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Plata',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Cian agrisado',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Gris escuro'
71 }, 71 },
72 more: 'Máis cores...', 72 more: 'Máis cores...',
73 panelTitle: 'Cores', 73 panelTitle: 'Cores',
diff --git a/sources/plugins/colorbutton/lang/hr.js b/sources/plugins/colorbutton/lang/hr.js
index 397dbb8..27901a9 100644
--- a/sources/plugins/colorbutton/lang/hr.js
+++ b/sources/plugins/colorbutton/lang/hr.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'hr', {
46 F0F8FF: 'Alice plava', 46 F0F8FF: 'Alice plava',
47 E6E6FA: 'Lavanda', 47 E6E6FA: 'Lavanda',
48 FFF: 'Bijela', 48 FFF: 'Bijela',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Jaka cijan',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Emerald',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Svijetlo plava',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametist',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Sivkasto plava',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Žarka žuta',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Tamna cijan',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Tamna emerald',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Jaka plava',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Tamno ljubičasta',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desatuirarana plava',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Narančasta',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Mrkva',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Blijedo crvena',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Sjana srebrna',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Svijetlo sivkasta cijan',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Svijetlo siva',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Tikva',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Jaka crvena',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Srebrna',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Sivkasto cijan',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Tamno siva'
71 }, 71 },
72 more: 'Više boja...', 72 more: 'Više boja...',
73 panelTitle: 'Boje', 73 panelTitle: 'Boje',
diff --git a/sources/plugins/colorbutton/lang/hu.js b/sources/plugins/colorbutton/lang/hu.js
index 3f89b9e..ce23c0e 100644
--- a/sources/plugins/colorbutton/lang/hu.js
+++ b/sources/plugins/colorbutton/lang/hu.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'hu', {
46 F0F8FF: 'Halvány kék', 46 F0F8FF: 'Halvány kék',
47 E6E6FA: 'Lavender', 47 E6E6FA: 'Lavender',
48 FFF: 'Fehér', 48 FFF: 'Fehér',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Erős cián',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Smaragd',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Fényes kék',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametiszt',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Szürskék',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Világossárga',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Sötét cián',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Sötét smaragd',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Erős kék',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Sötétlila',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Világoskék',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Narancs',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Répa',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Sápadt vörös',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Fényes ezüst',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Vigos szürs cián',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Vigosszürke',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'k',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Erős vörös',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Ezüst',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Szürs cián',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Sötétszürke'
71 }, 71 },
72 more: 'További színek...', 72 more: 'További színek...',
73 panelTitle: 'Színek', 73 panelTitle: 'Színek',
diff --git a/sources/plugins/colorbutton/lang/ja.js b/sources/plugins/colorbutton/lang/ja.js
index 25d2698..5b110d7 100644
--- a/sources/plugins/colorbutton/lang/ja.js
+++ b/sources/plugins/colorbutton/lang/ja.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'ja', {
46 F0F8FF: 'Alice Blue', 46 F0F8FF: 'Alice Blue',
47 E6E6FA: 'Lavender', 47 E6E6FA: 'Lavender',
48 FFF: 'White', 48 FFF: 'White',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Strong Cyan',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Emerald',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Bright Blue',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Amethyst',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Grayish Blue',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Vivid Yellow',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Dark Cyan',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Dark Emerald',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Strong Blue',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Dark Violet',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturated Blue',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Orange',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Carrot',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Pale Red',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Bright Silver',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Light Grayish Cyan',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Light Gray',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Pumpkin',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Strong Red',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Silver',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Grayish Cyan',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Dark Gray'
71 }, 71 },
72 more: 'その他の色...', 72 more: 'その他の色...',
73 panelTitle: '色', 73 panelTitle: '色',
diff --git a/sources/plugins/colorbutton/lang/ko.js b/sources/plugins/colorbutton/lang/ko.js
index 69ab16a..33b4347 100644
--- a/sources/plugins/colorbutton/lang/ko.js
+++ b/sources/plugins/colorbutton/lang/ko.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'ko', {
46 F0F8FF: '앨리스 블루', 46 F0F8FF: '앨리스 블루',
47 E6E6FA: '라벤더', 47 E6E6FA: '라벤더',
48 FFF: '흰색', 48 FFF: '흰색',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': '진한 청록색',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': '에메랄드',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': '밝은 파랑',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': '자수정',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': '회청색',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': '선명한 노랑',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': '다크 시안',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': '다크 에메랄드',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': '진한 파랑',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': '다크 바이올렛',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': '탁한 파랑',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': '주황',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': '당근',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': '창백한 빨강',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': '밝은 은색',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': '밝은 회청록',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': '밝은 회색',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': '호박',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': '진한 빨강',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': '은색',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': '회청록',
70 '999': 'Dark Gray' // MISSING 70 '999': '암회색'
71 }, 71 },
72 more: '색상 선택...', 72 more: '색상 선택...',
73 panelTitle: '색상', 73 panelTitle: '색상',
diff --git a/sources/plugins/colorbutton/lang/ku.js b/sources/plugins/colorbutton/lang/ku.js
index ffbe225..c5c6e91 100644
--- a/sources/plugins/colorbutton/lang/ku.js
+++ b/sources/plugins/colorbutton/lang/ku.js
@@ -48,26 +48,26 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'ku', {
48 FFF: 'سپی', 48 FFF: 'سپی',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Strong Cyan', // MISSING
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Emerald', // MISSING
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'شینی ناتۆخ',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Amethyst', // MISSING
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Grayish Blue', // MISSING
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Vivid Yellow', // MISSING
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Dark Cyan', // MISSING
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Dark Emerald', // MISSING
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'شینی تۆخ',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'پەمەیی تاریک',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturated Blue', // MISSING
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'نارنجی',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'گێزەر',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Pale Red', // MISSING
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'زیوی ڕووناک',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Light Grayish Cyan', // MISSING
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'ڕەساسی بریسکەدار',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'کولەکەی شیرین',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'سوری بەهێز',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'زیوی',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Grayish Cyan', // MISSING
70 '999': 'Dark Gray' // MISSING 70 '999': 'ڕەساسی تۆخ'
71 }, 71 },
72 more: 'ڕەنگی زیاتر...', 72 more: 'ڕەنگی زیاتر...',
73 panelTitle: 'ڕەنگەکان', 73 panelTitle: 'ڕەنگەکان',
diff --git a/sources/plugins/colorbutton/lang/nb.js b/sources/plugins/colorbutton/lang/nb.js
index b1e9f92..d576ec7 100644
--- a/sources/plugins/colorbutton/lang/nb.js
+++ b/sources/plugins/colorbutton/lang/nb.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'nb', {
46 F0F8FF: 'Svak cyan', 46 F0F8FF: 'Svak cyan',
47 E6E6FA: 'Lavendel', 47 E6E6FA: 'Lavendel',
48 FFF: 'Hvit', 48 FFF: 'Hvit',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Sterk cyan',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Smaragd',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Lys blå',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametyst',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Gråaktig blå',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Livaktig gul',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'rk cyan',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'rk smaragd',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Sterk blå',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'rk fiolett',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturert blå',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Oransje',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Gulrot',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Blek d',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Klar lv',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Lys gråaktig cyan',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Lys grå',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Gresskar',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Sterk d',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Sølv',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Gråaktig cyan',
70 '999': 'Dark Gray' // MISSING 70 '999': 'rk grå'
71 }, 71 },
72 more: 'Flere farger...', 72 more: 'Flere farger...',
73 panelTitle: 'Farger', 73 panelTitle: 'Farger',
diff --git a/sources/plugins/colorbutton/lang/pt-br.js b/sources/plugins/colorbutton/lang/pt-br.js
index b33da35..2deba28 100644
--- a/sources/plugins/colorbutton/lang/pt-br.js
+++ b/sources/plugins/colorbutton/lang/pt-br.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'pt-br', {
46 F0F8FF: 'Azul Alice', 46 F0F8FF: 'Azul Alice',
47 E6E6FA: 'Lavanda 2', 47 E6E6FA: 'Lavanda 2',
48 FFF: 'Branco', 48 FFF: 'Branco',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Ciano Forte',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Esmeralda',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Azul Brilhante',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametista',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Azul acinzentado',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Amarelo Vívido',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Ciano Escuro',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Esmeralda Escura',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Azul Forte',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Violeta Escura',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Azul Dessaturado',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Laranja',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Laranja Cenoura',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Vermelho Pálido',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Prata Brilhante',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Ciano Acinzentado Claro ',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Cinza Claro',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Abóbora',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Vermelho Forte',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Prata',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Ciano Acinzentado',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Cinza Escuro'
71 }, 71 },
72 more: 'Mais Cores...', 72 more: 'Mais Cores...',
73 panelTitle: 'Cores', 73 panelTitle: 'Cores',
diff --git a/sources/plugins/colorbutton/lang/pt.js b/sources/plugins/colorbutton/lang/pt.js
index 78481a9..afadf7f 100644
--- a/sources/plugins/colorbutton/lang/pt.js
+++ b/sources/plugins/colorbutton/lang/pt.js
@@ -9,7 +9,7 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'pt', {
9 '000': 'Black', 9 '000': 'Black',
10 '800000': 'Castanho', 10 '800000': 'Castanho',
11 '8B4513': 'Saddle Brown', 11 '8B4513': 'Saddle Brown',
12 '2F4F4F': 'Dark Slate Gray', 12 '2F4F4F': 'Cinza lousa escuro',
13 '008080': 'Teal', 13 '008080': 'Teal',
14 '000080': 'Azul naval', 14 '000080': 'Azul naval',
15 '4B0082': 'Indigo', 15 '4B0082': 'Indigo',
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'pt', {
46 F0F8FF: 'Azul Alice (f0f8ff)', 46 F0F8FF: 'Azul Alice (f0f8ff)',
47 E6E6FA: 'Lavanda', 47 E6E6FA: 'Lavanda',
48 FFF: 'Branco', 48 FFF: 'Branco',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Ciano forte',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Esmeralda',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Azul brilhante',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Amethyst', // MISSING
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Azul acinzentado',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Amarelo vívido',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Ciano escuro',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Esmeralda escuro',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Azul forte',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Violeta escuro',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturated Blue', // MISSING
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Laranja',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Cenoura',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Vermelho claro',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Prateado brilhante',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Ciano acinzentado claro',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Cinza claro',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Abóbora',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Strong Red', // MISSING
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Prateado',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Ciano acinzentado',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Cinza escuro'
71 }, 71 },
72 more: 'Mais cores...', 72 more: 'Mais cores...',
73 panelTitle: 'Cores', 73 panelTitle: 'Cores',
diff --git a/sources/plugins/colorbutton/lang/ru.js b/sources/plugins/colorbutton/lang/ru.js
index 3a01781..3d5cc99 100644
--- a/sources/plugins/colorbutton/lang/ru.js
+++ b/sources/plugins/colorbutton/lang/ru.js
@@ -47,27 +47,27 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'ru', {
47 E6E6FA: 'Лавандовый', 47 E6E6FA: 'Лавандовый',
48 FFF: 'Белый', 48 FFF: 'Белый',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Strong Cyan', // MISSING
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Изумрудный',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Bright Blue', // MISSING
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Amethyst', // MISSING
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Grayish Blue', // MISSING
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Ярко-желтый',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Dark Cyan', // MISSING
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Тёмно-изумрудный',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Strong Blue', // MISSING
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Тёмно-фиолетовый',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Desaturated Blue', // MISSING
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Оранжевый',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Морковный',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Pale Red', // MISSING
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Bright Silver', // MISSING
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Light Grayish Cyan', // MISSING
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Светло-серый',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Pumpkin', // MISSING
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Strong Red', // MISSING
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Silver', // MISSING
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Grayish Cyan', // MISSING
70 '999': 'Dark Gray' // MISSING 70 '999': 'Тёмно-серый'
71 }, 71 },
72 more: 'Ещё цвета...', 72 more: 'Ещё цвета...',
73 panelTitle: 'Цвета', 73 panelTitle: 'Цвета',
diff --git a/sources/plugins/colorbutton/lang/sk.js b/sources/plugins/colorbutton/lang/sk.js
index 158ff9e..83c4946 100644
--- a/sources/plugins/colorbutton/lang/sk.js
+++ b/sources/plugins/colorbutton/lang/sk.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'sk', {
46 F0F8FF: 'Alicovo modrá', 46 F0F8FF: 'Alicovo modrá',
47 E6E6FA: 'Levanduľová', 47 E6E6FA: 'Levanduľová',
48 FFF: 'Biela', 48 FFF: 'Biela',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Silno tyrkysová',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Smaragdová',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Svetlo modrá',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametystová',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Sivo modrá',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Sýto žl',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Tmavo tyrkysová',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Tmavo smaragdová',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Silno modrá',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Tmavo fialová',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Nesýto modrá',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Oranžová',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Mrkvo',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Bledo červená',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Svetlá bronzová',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Svet sivo-tyrkysová',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Svetlo sivá',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Tekvicová',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Silno červená',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Striebor',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Sivo tyrkysová',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Tmavo sivá'
71 }, 71 },
72 more: 'Viac farieb...', 72 more: 'Viac farieb...',
73 panelTitle: 'Farby', 73 panelTitle: 'Farby',
diff --git a/sources/plugins/colorbutton/lang/sv.js b/sources/plugins/colorbutton/lang/sv.js
index 72be373..4131fbd 100644
--- a/sources/plugins/colorbutton/lang/sv.js
+++ b/sources/plugins/colorbutton/lang/sv.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'sv', {
46 F0F8FF: 'Aliceblå', 46 F0F8FF: 'Aliceblå',
47 E6E6FA: 'Lavendel', 47 E6E6FA: 'Lavendel',
48 FFF: 'Vit', 48 FFF: 'Vit',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Stark turkos',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'Smaragd',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Klarblå',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametist',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Gråblå',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Klargul',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'rk turkos',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'rk smaragd',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Stark blå',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'rk violett',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Blek blå',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Orange',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Morot',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Blekröd',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Stark silver',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Ljus gråaktig turkos',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Ljusgrå',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Pumpa',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Stark d',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Silver',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Gråaktig turkos',
70 '999': 'Dark Gray' // MISSING 70 '999': 'rkgrå'
71 }, 71 },
72 more: 'Fler färger...', 72 more: 'Fler färger...',
73 panelTitle: 'Färger', 73 panelTitle: 'Färger',
diff --git a/sources/plugins/colorbutton/lang/tr.js b/sources/plugins/colorbutton/lang/tr.js
index 9a3e6f8..1e0e6e1 100644
--- a/sources/plugins/colorbutton/lang/tr.js
+++ b/sources/plugins/colorbutton/lang/tr.js
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'tr', {
46 F0F8FF: 'Reha Mavi', 46 F0F8FF: 'Reha Mavi',
47 E6E6FA: 'Eflatun', 47 E6E6FA: 'Eflatun',
48 FFF: 'Beyaz', 48 FFF: 'Beyaz',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': 'Koyu Camgöbeği',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': 'mrüt Yeşili',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': 'Parlak Mavi',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': 'Ametist Moru',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': 'Kirli Gri Mavi',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': 'Canlı Sarı',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': 'Koyu Camgöbeği',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': 'Koyu mrüt Yeşili',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': 'Koyu Mavi',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': 'Koyu Menekşe',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': 'Koyu Lacivert',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': 'Turuncu',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': 'Havuç Turuncusu',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': 'Soluk Kırmızı',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': 'Parlak Gümüş',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': 'Açık Kirli Gri Camgöbeği',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': 'Açık Gri',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': 'Balkabağı Turuncusu',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': 'Kan Kırmızı',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': 'Gümüş',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': 'Kirli Gri Camgöbeği',
70 '999': 'Dark Gray' // MISSING 70 '999': 'Koyu Gri'
71 }, 71 },
72 more: 'Diğer renkler...', 72 more: 'Diğer renkler...',
73 panelTitle: 'Renkler', 73 panelTitle: 'Renkler',
diff --git a/sources/plugins/colorbutton/lang/zh-cn.js b/sources/plugins/colorbutton/lang/zh-cn.js
index 6d7cb7a..d440572 100644
--- a/sources/plugins/colorbutton/lang/zh-cn.js
+++ b/sources/plugins/colorbutton/lang/zh-cn.js
@@ -6,68 +6,68 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'zh-cn', {
6 auto: '自动', 6 auto: '自动',
7 bgColorTitle: '背景颜色', 7 bgColorTitle: '背景颜色',
8 colors: { 8 colors: {
9 '000': '黑', 9 '000': '黑',
10 '800000': '', 10 '800000': '',
11 '8B4513': '褐', 11 '8B4513': '',
12 '2F4F4F': '', 12 '2F4F4F': '',
13 '008080': '绿松石', 13 '008080': '绿',
14 '000080': '海军蓝', 14 '000080': '海军蓝',
15 '4B0082': '靛', 15 '4B0082': '靛',
16 '696969': '灰', 16 '696969': '',
17 B22222: '砖红', 17 B22222: '',
18 A52A2A: '褐', 18 A52A2A: '褐',
19 DAA520: '金', 19 DAA520: '金菊色',
20 '006400': '深绿', 20 '006400': '深绿',
21 '40E0D0': '绿', 21 '40E0D0': '绿松石色',
22 '0000CD': '中蓝', 22 '0000CD': '中蓝',
23 '800080': '紫', 23 '800080': '紫',
24 '808080': '灰', 24 '808080': '灰',
25 F00: '红', 25 F00: '红',
26 FF8C00: '深橙', 26 FF8C00: '深橙',
27 FFD700: '金', 27 FFD700: '金',
28 '008000': '绿', 28 '008000': '绿',
29 '0FF': '青', 29 '0FF': '青',
30 '00F': '蓝', 30 '00F': '蓝',
31 EE82EE: '紫罗兰', 31 EE82EE: '紫罗兰',
32 A9A9A9: '灰', 32 A9A9A9: '',
33 FFA07A: '', 33 FFA07A: '鲑红色',
34 FFA500: '橙', 34 FFA500: '橙',
35 FFFF00: '黄', 35 FFFF00: '黄',
36 '00FF00': '绿', 36 '00FF00': '绿',
37 AFEEEE: '', 37 AFEEEE: '绿石色',
38 ADD8E6: '蓝', 38 ADD8E6: '',
39 DDA0DD: '梅红', 39 DDA0DD: '梅红',
40 D3D3D3: '灰', 40 D3D3D3: '',
41 FFF0F5: '紫红', 41 FFF0F5: '紫红',
42 FAEBD7: '古董白', 42 FAEBD7: '古董白',
43 FFFFE0: '黄', 43 FFFFE0: '',
44 F0FFF0: '蜜', 44 F0FFF0: '蜜绿色',
45 F0FFFF: '蓝', 45 F0FFFF: '',
46 F0F8FF: '蓝', 46 F0F8FF: '爱丽丝',
47 E6E6FA: '紫', 47 E6E6FA: '',
48 FFF: '白', 48 FFF: '白',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': '浓青色',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': '碧绿色',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': '亮蓝色',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': '紫水晶色',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': '灰蓝色',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': '鲜黄色',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': '深青色',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': '深碧绿色',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': '浓蓝色',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': '深紫罗兰色',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': '不饱和蓝色',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': '橙色',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': '红萝卜红色',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': '灰红色',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': '亮银色',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': '浅灰青色',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': '浅灰色',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': '南瓜黄色',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': '浓红色',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': '银色',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': '灰青色',
70 '999': 'Dark Gray' // MISSING 70 '999': '深灰色'
71 }, 71 },
72 more: '其它颜色...', 72 more: '其它颜色...',
73 panelTitle: '颜色', 73 panelTitle: '颜色',
diff --git a/sources/plugins/colorbutton/lang/zh.js b/sources/plugins/colorbutton/lang/zh.js
index 85a7293..888d3b1 100644
--- a/sources/plugins/colorbutton/lang/zh.js
+++ b/sources/plugins/colorbutton/lang/zh.js
@@ -26,7 +26,7 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'zh', {
26 FF8C00: '深橘色', 26 FF8C00: '深橘色',
27 FFD700: '金色', 27 FFD700: '金色',
28 '008000': '綠色', 28 '008000': '綠色',
29 '0FF': '', 29 '0FF': '色',
30 '00F': '藍色', 30 '00F': '藍色',
31 EE82EE: '紫色', 31 EE82EE: '紫色',
32 A9A9A9: '暗灰色', 32 A9A9A9: '暗灰色',
@@ -46,28 +46,28 @@ CKEDITOR.plugins.setLang( 'colorbutton', 'zh', {
46 F0F8FF: '愛麗斯蘭', 46 F0F8FF: '愛麗斯蘭',
47 E6E6FA: '淺紫色', 47 E6E6FA: '淺紫色',
48 FFF: '白色', 48 FFF: '白色',
49 '1ABC9C': 'Strong Cyan', // MISSING 49 '1ABC9C': '深青色',
50 '2ECC71': 'Emerald', // MISSING 50 '2ECC71': '翠綠色',
51 '3498DB': 'Bright Blue', // MISSING 51 '3498DB': '亮藍色',
52 '9B59B6': 'Amethyst', // MISSING 52 '9B59B6': '紫色',
53 '4E5F70': 'Grayish Blue', // MISSING 53 '4E5F70': '藍灰色',
54 'F1C40F': 'Vivid Yellow', // MISSING 54 'F1C40F': '鮮黃色',
55 '16A085': 'Dark Cyan', // MISSING 55 '16A085': '暗青色',
56 '27AE60': 'Dark Emerald', // MISSING 56 '27AE60': '暗綠色',
57 '2980B9': 'Strong Blue', // MISSING 57 '2980B9': '深藍色',
58 '8E44AD': 'Dark Violet', // MISSING 58 '8E44AD': '暗紫色',
59 '2C3E50': 'Desaturated Blue', // MISSING 59 '2C3E50': '不飽和藍色',
60 'F39C12': 'Orange', // MISSING 60 'F39C12': '橘色',
61 'E67E22': 'Carrot', // MISSING 61 'E67E22': '胡蘿蔔色',
62 'E74C3C': 'Pale Red', // MISSING 62 'E74C3C': '淡紅色',
63 'ECF0F1': 'Bright Silver', // MISSING 63 'ECF0F1': '亮銀色',
64 '95A5A6': 'Light Grayish Cyan', // MISSING 64 '95A5A6': '淺灰青色',
65 'DDD': 'Light Gray', // MISSING 65 'DDD': '淺灰色',
66 'D35400': 'Pumpkin', // MISSING 66 'D35400': '南瓜色',
67 'C0392B': 'Strong Red', // MISSING 67 'C0392B': '深紅色',
68 'BDC3C7': 'Silver', // MISSING 68 'BDC3C7': '銀色',
69 '7F8C8D': 'Grayish Cyan', // MISSING 69 '7F8C8D': '灰青色',
70 '999': 'Dark Gray' // MISSING 70 '999': '深灰色'
71 }, 71 },
72 more: '更多顏色', 72 more: '更多顏色',
73 panelTitle: '顏色', 73 panelTitle: '顏色',
diff --git a/sources/plugins/colorbutton/plugin.js b/sources/plugins/colorbutton/plugin.js
index 5382333..a293ba6 100644
--- a/sources/plugins/colorbutton/plugin.js
+++ b/sources/plugins/colorbutton/plugin.js
@@ -11,7 +11,7 @@
11CKEDITOR.plugins.add( 'colorbutton', { 11CKEDITOR.plugins.add( 'colorbutton', {
12 requires: 'panelbutton,floatpanel', 12 requires: 'panelbutton,floatpanel',
13 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
15 // jscs:enable maximumLineLength 15 // jscs:enable maximumLineLength
16 icons: 'bgcolor,textcolor', // %REMOVE_LINE_CORE% 16 icons: 'bgcolor,textcolor', // %REMOVE_LINE_CORE%
17 hidpi: true, // %REMOVE_LINE_CORE% 17 hidpi: true, // %REMOVE_LINE_CORE%
@@ -85,7 +85,8 @@ CKEDITOR.plugins.add( 'colorbutton', {
85 85
86 function addButton( name, type, title, order, options ) { 86 function addButton( name, type, title, order, options ) {
87 var style = new CKEDITOR.style( config[ 'colorButton_' + type + 'Style' ] ), 87 var style = new CKEDITOR.style( config[ 'colorButton_' + type + 'Style' ] ),
88 colorBoxId = CKEDITOR.tools.getNextId() + '_colorBox'; 88 colorBoxId = CKEDITOR.tools.getNextId() + '_colorBox',
89 panelBlock;
89 90
90 options = options || {}; 91 options = options || {};
91 92
@@ -105,10 +106,12 @@ CKEDITOR.plugins.add( 'colorbutton', {
105 }, 106 },
106 107
107 onBlock: function( panel, block ) { 108 onBlock: function( panel, block ) {
109 panelBlock = block;
110
108 block.autoSize = true; 111 block.autoSize = true;
109 block.element.addClass( 'cke_colorblock' ); 112 block.element.addClass( 'cke_colorblock' );
110 block.element.setHtml( renderColors( panel, type, colorBoxId ) ); 113 block.element.setHtml( renderColors( panel, type, colorBoxId ) );
111 // The block should not have scrollbars (#5933, #6056) 114 // The block should not have scrollbars (http://dev.ckeditor.com/ticket/5933, http://dev.ckeditor.com/ticket/6056)
112 block.element.getDocument().getBody().setStyle( 'overflow', 'hidden' ); 115 block.element.getDocument().getBody().setStyle( 'overflow', 'hidden' );
113 116
114 CKEDITOR.ui.fire( 'ready', this ); 117 CKEDITOR.ui.fire( 'ready', this );
@@ -129,13 +132,13 @@ CKEDITOR.plugins.add( 'colorbutton', {
129 this.setState( CKEDITOR.TRISTATE_DISABLED ); 132 this.setState( CKEDITOR.TRISTATE_DISABLED );
130 }, 133 },
131 134
132 // The automatic colorbox should represent the real color (#6010) 135 // The automatic colorbox should represent the real color (http://dev.ckeditor.com/ticket/6010)
133 onOpen: function() { 136 onOpen: function() {
134 137
135 var selection = editor.getSelection(), 138 var selection = editor.getSelection(),
136 block = selection && selection.getStartElement(), 139 block = selection && selection.getStartElement(),
137 path = editor.elementPath( block ), 140 path = editor.elementPath( block ),
138 color; 141 automaticColor;
139 142
140 if ( !path ) 143 if ( !path )
141 return; 144 return;
@@ -145,19 +148,46 @@ CKEDITOR.plugins.add( 'colorbutton', {
145 148
146 // The background color might be transparent. In that case, look up the color in the DOM tree. 149 // The background color might be transparent. In that case, look up the color in the DOM tree.
147 do { 150 do {
148 color = block && block.getComputedStyle( type == 'back' ? 'background-color' : 'color' ) || 'transparent'; 151 automaticColor = block && block.getComputedStyle( type == 'back' ? 'background-color' : 'color' ) || 'transparent';
149 } 152 }
150 while ( type == 'back' && color == 'transparent' && block && ( block = block.getParent() ) ); 153 while ( type == 'back' && automaticColor == 'transparent' && block && ( block = block.getParent() ) );
151 154
152 // The box should never be transparent. 155 // The box should never be transparent.
153 if ( !color || color == 'transparent' ) 156 if ( !automaticColor || automaticColor == 'transparent' )
154 color = '#ffffff'; 157 automaticColor = '#ffffff';
155 158
156 if ( config.colorButton_enableAutomatic !== false ) { 159 if ( config.colorButton_enableAutomatic !== false ) {
157 this._.panel._.iframe.getFrameDocument().getById( colorBoxId ).setStyle( 'background-color', color ); 160 this._.panel._.iframe.getFrameDocument().getById( colorBoxId ).setStyle( 'background-color', automaticColor );
158 } 161 }
159 162
160 return color; 163 var range = selection && selection.getRanges()[ 0 ];
164
165 if ( range ) {
166 var walker = new CKEDITOR.dom.walker( range ),
167 element = range.collapsed ? range.startContainer : walker.next(),
168 finalColor = '',
169 currentColor;
170
171 while ( element ) {
172 if ( element.type === CKEDITOR.NODE_TEXT ) {
173 element = element.getParent();
174 }
175
176 currentColor = normalizeColor( element.getComputedStyle( type == 'back' ? 'background-color' : 'color' ) );
177 finalColor = finalColor || currentColor;
178
179 if ( finalColor !== currentColor ) {
180 finalColor = '';
181 break;
182 }
183
184 element = walker.next();
185 }
186
187 selectColor( panelBlock, finalColor );
188 }
189
190 return automaticColor;
161 } 191 }
162 } ); 192 } );
163 } 193 }
@@ -169,53 +199,44 @@ CKEDITOR.plugins.add( 'colorbutton', {
169 // Tells if we should include "More Colors..." button. 199 // Tells if we should include "More Colors..." button.
170 moreColorsEnabled = editor.plugins.colordialog && config.colorButton_enableMore !== false, 200 moreColorsEnabled = editor.plugins.colordialog && config.colorButton_enableMore !== false,
171 // aria-setsize and aria-posinset attributes are used to indicate size of options, because 201 // aria-setsize and aria-posinset attributes are used to indicate size of options, because
172 // screen readers doesn't play nice with table, based layouts (#12097). 202 // screen readers doesn't play nice with table, based layouts (http://dev.ckeditor.com/ticket/12097).
173 total = colors.length + ( moreColorsEnabled ? 2 : 1 ); 203 total = colors.length + ( moreColorsEnabled ? 2 : 1 );
174 204
175 var clickFn = CKEDITOR.tools.addFunction( function( color, type ) { 205 var clickFn = CKEDITOR.tools.addFunction( function applyColorStyle( color, type ) {
176 var applyColorStyle = arguments.callee;
177 function onColorDialogClose( evt ) {
178 this.removeListener( 'ok', onColorDialogClose );
179 this.removeListener( 'cancel', onColorDialogClose );
180 206
181 evt.name == 'ok' && applyColorStyle( this.getContentElement( 'picker', 'selectedColor' ).getValue(), type ); 207 editor.focus();
182 } 208 editor.fire( 'saveSnapshot' );
183 209
184 if ( color == '?' ) { 210 if ( color == '?' ) {
185 editor.openDialog( 'colordialog', function() { 211 editor.getColorFromDialog( function( color ) {
186 this.on( 'ok', onColorDialogClose ); 212 if ( color ) {
187 this.on( 'cancel', onColorDialogClose ); 213 return applyColor( color );
214 }
188 } ); 215 } );
189 216 } else {
190 return; 217 return applyColor( color );
191 } 218 }
192 219
193 editor.focus(); 220 function applyColor( color ) {
194 221 // Clean up any conflicting style within the range.
195 panel.hide(); 222 editor.removeStyle( new CKEDITOR.style( config[ 'colorButton_' + type + 'Style' ], { color: 'inherit' } ) );
196
197 editor.fire( 'saveSnapshot' );
198
199 // Clean up any conflicting style within the range.
200 editor.removeStyle( new CKEDITOR.style( config[ 'colorButton_' + type + 'Style' ], { color: 'inherit' } ) );
201
202 if ( color ) {
203 var colorStyle = config[ 'colorButton_' + type + 'Style' ]; 223 var colorStyle = config[ 'colorButton_' + type + 'Style' ];
204 224
205 colorStyle.childRule = type == 'back' ? 225 colorStyle.childRule = type == 'back' ?
206 function( element ) { 226 function( element ) {
207 // It's better to apply background color as the innermost style. (#3599) 227 // It's better to apply background color as the innermost style. (http://dev.ckeditor.com/ticket/3599)
208 // Except for "unstylable elements". (#6103) 228 // Except for "unstylable elements". (http://dev.ckeditor.com/ticket/6103)
209 return isUnstylable( element ); 229 return isUnstylable( element );
210 } : function( element ) { 230 } : function( element ) {
211 // Fore color style must be applied inside links instead of around it. (#4772,#6908) 231 // Fore color style must be applied inside links instead of around it. (http://dev.ckeditor.com/ticket/4772,http://dev.ckeditor.com/ticket/6908)
212 return !( element.is( 'a' ) || element.getElementsByTag( 'a' ).count() ) || isUnstylable( element ); 232 return !( element.is( 'a' ) || element.getElementsByTag( 'a' ).count() ) || isUnstylable( element );
213 }; 233 };
214 234
235 editor.focus();
215 editor.applyStyle( new CKEDITOR.style( colorStyle, { color: color } ) ); 236 editor.applyStyle( new CKEDITOR.style( colorStyle, { color: color } ) );
237 editor.fire( 'saveSnapshot' );
216 } 238 }
217 239
218 editor.fire( 'saveSnapshot' );
219 } ); 240 } );
220 241
221 if ( config.colorButton_enableAutomatic !== false ) { 242 if ( config.colorButton_enableAutomatic !== false ) {
@@ -245,7 +266,7 @@ CKEDITOR.plugins.add( 'colorbutton', {
245 266
246 // The data can be only a color code (without #) or colorName + color code 267 // The data can be only a color code (without #) or colorName + color code
247 // If only a color code is provided, then the colorName is the color with the hash 268 // If only a color code is provided, then the colorName is the color with the hash
248 // Convert the color from RGB to RRGGBB for better compatibility with IE and <font>. See #5676 269 // Convert the color from RGB to RRGGBB for better compatibility with IE and <font>. See http://dev.ckeditor.com/ticket/5676
249 if ( !parts[ 1 ] ) 270 if ( !parts[ 1 ] )
250 colorName = '#' + colorName.replace( /^(.)(.)(.)$/, '$1$1$2$2$3$3' ); 271 colorName = '#' + colorName.replace( /^(.)(.)(.)$/, '$1$1$2$2$3$3' );
251 272
@@ -255,6 +276,7 @@ CKEDITOR.plugins.add( 'colorbutton', {
255 ' title="', colorLabel, '"' + 276 ' title="', colorLabel, '"' +
256 ' onclick="CKEDITOR.tools.callFunction(', clickFn, ',\'', colorName, '\',\'', type, '\'); return false;"' + 277 ' onclick="CKEDITOR.tools.callFunction(', clickFn, ',\'', colorName, '\',\'', type, '\'); return false;"' +
257 ' href="javascript:void(\'', colorLabel, '\')"' + 278 ' href="javascript:void(\'', colorLabel, '\')"' +
279 ' data-value="' + colorCode + '"' +
258 ' role="option" aria-posinset="', ( i + 2 ), '" aria-setsize="', total, '">' + 280 ' role="option" aria-posinset="', ( i + 2 ), '" aria-setsize="', total, '">' +
259 '<span class="cke_colorbox" style="background-color:#', colorCode, '"></span>' + 281 '<span class="cke_colorbox" style="background-color:#', colorCode, '"></span>' +
260 '</a>' + 282 '</a>' +
@@ -281,6 +303,40 @@ CKEDITOR.plugins.add( 'colorbutton', {
281 function isUnstylable( ele ) { 303 function isUnstylable( ele ) {
282 return ( ele.getAttribute( 'contentEditable' ) == 'false' ) || ele.getAttribute( 'data-nostyle' ); 304 return ( ele.getAttribute( 'contentEditable' ) == 'false' ) || ele.getAttribute( 'data-nostyle' );
283 } 305 }
306
307 /*
308 * Selects the specified color in the specified panel block.
309 *
310 * @private
311 * @member CKEDITOR.plugins.colorbutton
312 * @param {CKEDITOR.ui.panel.block} block
313 * @param {String} color
314 */
315 function selectColor( block, color ) {
316 var items = block._.getItems();
317
318 for ( var i = 0; i < items.count(); i++ ) {
319 var item = items.getItem( i );
320
321 item.removeAttribute( 'aria-selected' );
322
323 if ( color && color == normalizeColor( item.getAttribute( 'data-value' ) ) ) {
324 item.setAttribute( 'aria-selected', true );
325 }
326 }
327 }
328
329 /*
330 * Converts a CSS color value to an easily comparable form.
331 *
332 * @private
333 * @member CKEDITOR.plugins.colorbutton
334 * @param {String} color
335 * @returns {String}
336 */
337 function normalizeColor( color ) {
338 return CKEDITOR.tools.convertRgbToHex( color || '' ).replace( /#/, '' ).toLowerCase();
339 }
284 } 340 }
285} ); 341} );
286 342
diff --git a/sources/plugins/colordialog/lang/es-mx.js b/sources/plugins/colordialog/lang/es-mx.js
new file mode 100644
index 0000000..160dd35
--- /dev/null
+++ b/sources/plugins/colordialog/lang/es-mx.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( 'colordialog', 'es-mx', {
6 clear: 'Borrar',
7 highlight: 'Realce',
8 options: 'Opciones de color',
9 selected: 'Color seleccionado',
10 title: 'Selecciona un color'
11} );
diff --git a/sources/plugins/colordialog/lang/nb.js b/sources/plugins/colordialog/lang/nb.js
index f113e21..4c3dc48 100644
--- a/sources/plugins/colordialog/lang/nb.js
+++ b/sources/plugins/colordialog/lang/nb.js
@@ -3,8 +3,8 @@ Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license 3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/ 4*/
5CKEDITOR.plugins.setLang( 'colordialog', 'nb', { 5CKEDITOR.plugins.setLang( 'colordialog', 'nb', {
6 clear: 'Tøm', 6 clear: 'Nullstill',
7 highlight: 'Merk', 7 highlight: 'Fremhevet',
8 options: 'Alternativer for farge', 8 options: 'Alternativer for farge',
9 selected: 'Valgt farge', 9 selected: 'Valgt farge',
10 title: 'Velg farge' 10 title: 'Velg farge'
diff --git a/sources/plugins/colordialog/plugin.js b/sources/plugins/colordialog/plugin.js
index 1ad7e2d..344fa8e 100644
--- a/sources/plugins/colordialog/plugin.js
+++ b/sources/plugins/colordialog/plugin.js
@@ -6,7 +6,7 @@
6CKEDITOR.plugins.colordialog = { 6CKEDITOR.plugins.colordialog = {
7 requires: 'dialog', 7 requires: 'dialog',
8 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
10 // jscs:enable maximumLineLength 10 // jscs:enable maximumLineLength
11 init: function( editor ) { 11 init: function( editor ) {
12 var cmd = new CKEDITOR.dialogCommand( 'colordialog' ); 12 var cmd = new CKEDITOR.dialogCommand( 'colordialog' );
diff --git a/sources/plugins/contextmenu/lang/es-mx.js b/sources/plugins/contextmenu/lang/es-mx.js
new file mode 100644
index 0000000..72bb1fa
--- /dev/null
+++ b/sources/plugins/contextmenu/lang/es-mx.js
@@ -0,0 +1,7 @@
1/*
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-mx', {
6 options: 'Opciones del menú contextual'
7} );
diff --git a/sources/plugins/contextmenu/plugin.js b/sources/plugins/contextmenu/plugin.js
index 6cd3935..4a3bd5f 100644
--- a/sources/plugins/contextmenu/plugin.js
+++ b/sources/plugins/contextmenu/plugin.js
@@ -7,10 +7,10 @@ CKEDITOR.plugins.add( 'contextmenu', {
7 requires: 'menu', 7 requires: 'menu',
8 8
9 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
11 // jscs:enable maximumLineLength 11 // jscs:enable maximumLineLength
12 12
13 // Make sure the base class (CKEDITOR.menu) is loaded before it (#3318). 13 // Make sure the base class (CKEDITOR.menu) is loaded before it (http://dev.ckeditor.com/ticket/3318).
14 onLoad: function() { 14 onLoad: function() {
15 /** 15 /**
16 * Class replacing the non-configurable native context menu with a configurable CKEditor's equivalent. 16 * Class replacing the non-configurable native context menu with a configurable CKEditor's equivalent.
@@ -51,7 +51,7 @@ CKEDITOR.plugins.add( 'contextmenu', {
51 var domEvent = event.data, 51 var domEvent = event.data,
52 isCtrlKeyDown = 52 isCtrlKeyDown =
53 // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event, 53 // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event,
54 // which make this property unreliable. (#4826) 54 // which make this property unreliable. (http://dev.ckeditor.com/ticket/4826)
55 ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) ); 55 ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) );
56 56
57 if ( nativeContextMenuOnCtrl && isCtrlKeyDown ) 57 if ( nativeContextMenuOnCtrl && isCtrlKeyDown )
@@ -60,7 +60,7 @@ CKEDITOR.plugins.add( 'contextmenu', {
60 // Cancel the browser context menu. 60 // Cancel the browser context menu.
61 domEvent.preventDefault(); 61 domEvent.preventDefault();
62 62
63 // Fix selection when non-editable element in Webkit/Blink (Mac) (#11306). 63 // Fix selection when non-editable element in Webkit/Blink (Mac) (http://dev.ckeditor.com/ticket/11306).
64 if ( CKEDITOR.env.mac && CKEDITOR.env.webkit ) { 64 if ( CKEDITOR.env.mac && CKEDITOR.env.webkit ) {
65 var editor = this.editor, 65 var editor = this.editor,
66 contentEditableParent = new CKEDITOR.dom.elementPath( domEvent.getTarget(), editor.editable() ).contains( function( el ) { 66 contentEditableParent = new CKEDITOR.dom.elementPath( domEvent.getTarget(), editor.editable() ).contains( function( el ) {
@@ -83,7 +83,7 @@ CKEDITOR.plugins.add( 'contextmenu', {
83 CKEDITOR.tools.setTimeout( function() { 83 CKEDITOR.tools.setTimeout( function() {
84 this.open( offsetParent, null, offsetX, offsetY ); 84 this.open( offsetParent, null, offsetX, offsetY );
85 85
86 // IE needs a short while to allow selection change before opening menu. (#7908) 86 // IE needs a short while to allow selection change before opening menu. (http://dev.ckeditor.com/ticket/7908)
87 }, CKEDITOR.env.ie ? 200 : 0, this ); 87 }, CKEDITOR.env.ie ? 200 : 0, this );
88 }, this ); 88 }, this );
89 89
@@ -111,10 +111,14 @@ CKEDITOR.plugins.add( 'contextmenu', {
111 * @param {Number} [offsetY] 111 * @param {Number} [offsetY]
112 */ 112 */
113 open: function( offsetParent, corner, offsetX, offsetY ) { 113 open: function( offsetParent, corner, offsetX, offsetY ) {
114 if ( this.editor.config.enableContextMenu === false ) {
115 return;
116 }
117
114 this.editor.focus(); 118 this.editor.focus();
115 offsetParent = offsetParent || CKEDITOR.document.getDocumentElement(); 119 offsetParent = offsetParent || CKEDITOR.document.getDocumentElement();
116 120
117 // #9362: Force selection check to update commands' states in the new context. 121 // http://dev.ckeditor.com/ticket/9362: Force selection check to update commands' states in the new context.
118 this.editor.selectionChange( 1 ); 122 this.editor.selectionChange( 1 );
119 123
120 this.show( offsetParent, corner, offsetX, offsetY ); 124 this.show( offsetParent, corner, offsetX, offsetY );
@@ -157,3 +161,14 @@ CKEDITOR.plugins.add( 'contextmenu', {
157 * @cfg {Boolean} [browserContextMenuOnCtrl=true] 161 * @cfg {Boolean} [browserContextMenuOnCtrl=true]
158 * @member CKEDITOR.config 162 * @member CKEDITOR.config
159 */ 163 */
164
165/**
166 * Whether to enable the context menu. Regardless of the setting the [Context Menu](http://ckeditor.com/addon/contextmenu)
167 * plugin is still loaded.
168 *
169 * config.enableContextMenu = false;
170 *
171 * @since 4.7.0
172 * @cfg {Boolean} [enableContextMenu=true]
173 * @member CKEDITOR.config
174 */
diff --git a/sources/plugins/dialog/plugin.js b/sources/plugins/dialog/plugin.js
index d6af6a2..f26f9c9 100644
--- a/sources/plugins/dialog/plugin.js
+++ b/sources/plugins/dialog/plugin.js
@@ -177,10 +177,10 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
177 title = body.getChild( 0 ), 177 title = body.getChild( 0 ),
178 close = body.getChild( 1 ); 178 close = body.getChild( 1 );
179 179
180 // Don't allow dragging on dialog (#13184). 180 // Don't allow dragging on dialog (http://dev.ckeditor.com/ticket/13184).
181 editor.plugins.clipboard && CKEDITOR.plugins.clipboard.preventDefaultDropOnElement( body ); 181 editor.plugins.clipboard && CKEDITOR.plugins.clipboard.preventDefaultDropOnElement( body );
182 182
183 // IFrame shim for dialog that masks activeX in IE. (#7619) 183 // IFrame shim for dialog that masks activeX in IE. (http://dev.ckeditor.com/ticket/7619)
184 if ( CKEDITOR.env.ie && !CKEDITOR.env.quirks && !CKEDITOR.env.edge ) { 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 185 var src = 'javascript:void(function(){' + encodeURIComponent( 'document.open();(' + CKEDITOR.tools.fixDomain + ')();document.close();' ) + '}())', // jshint ignore:line
186 iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + 186 iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' +
@@ -229,7 +229,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
229 tabsToRemove = {}, 229 tabsToRemove = {},
230 i, processed, stopPropagation; 230 i, processed, stopPropagation;
231 231
232 if ( ( buttonsOrder == 'OS' && CKEDITOR.env.mac ) || // The buttons in MacOS Apps are in reverse order (#4750) 232 if ( ( buttonsOrder == 'OS' && CKEDITOR.env.mac ) || // The buttons in MacOS Apps are in reverse order (http://dev.ckeditor.com/ticket/4750)
233 ( buttonsOrder == 'rtl' && dir == 'ltr' ) || ( buttonsOrder == 'ltr' && dir == 'rtl' ) ) 233 ( buttonsOrder == 'rtl' && dir == 'ltr' ) || ( buttonsOrder == 'ltr' && dir == 'rtl' ) )
234 defaultDefinition.buttons.reverse(); 234 defaultDefinition.buttons.reverse();
235 235
@@ -334,7 +334,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
334 334
335 if ( definition.onOk ) { 335 if ( definition.onOk ) {
336 this.on( 'ok', function( evt ) { 336 this.on( 'ok', function( evt ) {
337 // Dialog confirm might probably introduce content changes (#5415). 337 // Dialog confirm might probably introduce content changes (http://dev.ckeditor.com/ticket/5415).
338 editor.fire( 'saveSnapshot' ); 338 editor.fire( 'saveSnapshot' );
339 setTimeout( function() { 339 setTimeout( function() {
340 editor.fire( 'saveSnapshot' ); 340 editor.fire( 'saveSnapshot' );
@@ -451,7 +451,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
451 currentIndex = currentIndex + offset; 451 currentIndex = currentIndex + offset;
452 452
453 if ( hasTabs && !me._.tabBarMode && ( currentIndex == focusList.length || currentIndex == -1 ) ) { 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). 454 // If the dialog was not in tab mode, then focus the first tab (http://dev.ckeditor.com/ticket/13027).
455 me._.tabBarMode = true; 455 me._.tabBarMode = true;
456 me._.tabs[ me._.currentTabId ][ 0 ].focus(); 456 me._.tabs[ me._.currentTabId ][ 0 ].focus();
457 me._.currentFocusIndex = -1; 457 me._.currentFocusIndex = -1;
@@ -528,7 +528,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
528 button && CKEDITOR.tools.setTimeout( button.click, 0, button ); 528 button && CKEDITOR.tools.setTimeout( button.click, 0, button );
529 processed = 1; 529 processed = 1;
530 } 530 }
531 stopPropagation = 1; // Always block the propagation (#4269) 531 stopPropagation = 1; // Always block the propagation (http://dev.ckeditor.com/ticket/4269)
532 } else if ( keystroke == 27 /*ESC*/ ) { 532 } else if ( keystroke == 27 /*ESC*/ ) {
533 button = this.getButton( 'cancel' ); 533 button = this.getButton( 'cancel' );
534 534
@@ -539,7 +539,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
539 if ( this.fire( 'cancel', { hide: true } ).hide !== false ) 539 if ( this.fire( 'cancel', { hide: true } ).hide !== false )
540 this.hide(); 540 this.hide();
541 } 541 }
542 stopPropagation = 1; // Always block the propagation (#4269) 542 stopPropagation = 1; // Always block the propagation (http://dev.ckeditor.com/ticket/4269)
543 } else { 543 } else {
544 return; 544 return;
545 } 545 }
@@ -563,7 +563,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
563 dialogElement.on( 'keydown', keydownHandler, this ); 563 dialogElement.on( 'keydown', keydownHandler, this );
564 564
565 // Some browsers instead, don't cancel key events in the keydown, but in the 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) 566 // keypress. So we must do a longer trip in those cases. (http://dev.ckeditor.com/ticket/4531,http://dev.ckeditor.com/ticket/8985)
567 if ( CKEDITOR.env.gecko ) 567 if ( CKEDITOR.env.gecko )
568 dialogElement.on( 'keypress', keypressHandler, this ); 568 dialogElement.on( 'keypress', keypressHandler, this );
569 569
@@ -612,7 +612,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
612 } 612 }
613 }, this, null, 0xffffffff ); 613 }, this, null, 0xffffffff );
614 614
615 // IE6 BUG: Text fields and text areas are only half-rendered the first time the dialog appears in IE6 (#2661). 615 // IE6 BUG: Text fields and text areas are only half-rendered the first time the dialog appears in IE6 (http://dev.ckeditor.com/ticket/2661).
616 // This is still needed after [2708] and [2709] because text fields in hidden TR tags are still broken. 616 // This is still needed after [2708] and [2709] because text fields in hidden TR tags are still broken.
617 if ( CKEDITOR.env.ie6Compat ) { 617 if ( CKEDITOR.env.ie6Compat ) {
618 this.on( 'load', function() { 618 this.on( 'load', function() {
@@ -788,7 +788,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
788 var element = this._.element.getFirst(), rtl = this._.editor.lang.dir == 'rtl'; 788 var element = this._.element.getFirst(), rtl = this._.editor.lang.dir == 'rtl';
789 var isFixed = element.getComputedStyle( 'position' ) == 'fixed'; 789 var isFixed = element.getComputedStyle( 'position' ) == 'fixed';
790 790
791 // (#8888) In some cases of a very small viewport, dialog is incorrectly 791 // (http://dev.ckeditor.com/ticket/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 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 793 // scroll down/up to reveal dialog's content below/above the viewport; this is
794 // cumbersome. 794 // cumbersome.
@@ -862,8 +862,10 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
862 // Reset all inputs back to their default value. 862 // Reset all inputs back to their default value.
863 this.reset(); 863 this.reset();
864 864
865 // Select the first tab by default. 865 // Selects the first tab if no tab is already selected.
866 this.selectPage( this.definition.contents[ 0 ].id ); 866 if ( this._.currentTabId === null ) {
867 this.selectPage( this.definition.contents[ 0 ].id );
868 }
867 869
868 // Set z-index. 870 // Set z-index.
869 if ( CKEDITOR.dialog._.currentZIndex === null ) 871 if ( CKEDITOR.dialog._.currentZIndex === null )
@@ -1038,7 +1040,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
1038 commitContent: function() { 1040 commitContent: function() {
1039 var args = arguments; 1041 var args = arguments;
1040 this.foreach( function( widget ) { 1042 this.foreach( function( widget ) {
1041 // Make sure IE triggers "change" event on last focused input before closing the dialog. (#7915) 1043 // Make sure IE triggers "change" event on last focused input before closing the dialog. (http://dev.ckeditor.com/ticket/7915)
1042 if ( CKEDITOR.env.ie && this._.currentFocusIndex == widget.focusIndex ) 1044 if ( CKEDITOR.env.ie && this._.currentFocusIndex == widget.focusIndex )
1043 widget.getInputElement().$.blur(); 1045 widget.getInputElement().$.blur();
1044 1046
@@ -1090,11 +1092,11 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
1090 var editor = this._.editor; 1092 var editor = this._.editor;
1091 editor.focus(); 1093 editor.focus();
1092 1094
1093 // Give a while before unlock, waiting for focus to return to the editable. (#172) 1095 // Give a while before unlock, waiting for focus to return to the editable. (http://dev.ckeditor.com/ticket/172)
1094 setTimeout( function() { 1096 setTimeout( function() {
1095 editor.focusManager.unlock(); 1097 editor.focusManager.unlock();
1096 1098
1097 // Fixed iOS focus issue (#12381). 1099 // Fixed iOS focus issue (http://dev.ckeditor.com/ticket/12381).
1098 // Keep in mind that editor.focus() does not work in this case. 1100 // Keep in mind that editor.focus() does not work in this case.
1099 if ( CKEDITOR.env.iOS ) { 1101 if ( CKEDITOR.env.iOS ) {
1100 editor.window.focus(); 1102 editor.window.focus();
@@ -1111,7 +1113,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
1111 contentObj.resetInitValue && contentObj.resetInitValue(); 1113 contentObj.resetInitValue && contentObj.resetInitValue();
1112 } ); 1114 } );
1113 1115
1114 // Reset dialog state back to IDLE, if busy (#13213). 1116 // Reset dialog state back to IDLE, if busy (http://dev.ckeditor.com/ticket/13213).
1115 this.setState( CKEDITOR.DIALOG_STATE_IDLE ); 1117 this.setState( CKEDITOR.DIALOG_STATE_IDLE );
1116 }, 1118 },
1117 1119
@@ -1232,7 +1234,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
1232 1234
1233 // [IE] an invisible input[type='text'] will enlarge it's width 1235 // [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 1236 // if it's value is long when it shows, so we clear it's value
1235 // before it shows and then recover it (#5649) 1237 // before it shows and then recover it (http://dev.ckeditor.com/ticket/5649)
1236 if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat ) { 1238 if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat ) {
1237 clearOrRecoverTextInputValue( selected[ 1 ] ); 1239 clearOrRecoverTextInputValue( selected[ 1 ] );
1238 selected[ 1 ].show(); 1240 selected[ 1 ].show();
@@ -2199,7 +2201,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
2199 resizeCover = resizeFunc; 2201 resizeCover = resizeFunc;
2200 win.on( 'resize', resizeFunc ); 2202 win.on( 'resize', resizeFunc );
2201 resizeFunc(); 2203 resizeFunc();
2202 // Using Safari/Mac, focus must be kept where it is (#7027) 2204 // Using Safari/Mac, focus must be kept where it is (http://dev.ckeditor.com/ticket/7027)
2203 if ( !( CKEDITOR.env.mac && CKEDITOR.env.webkit ) ) 2205 if ( !( CKEDITOR.env.mac && CKEDITOR.env.webkit ) )
2204 coverElement.focus(); 2206 coverElement.focus();
2205 2207
@@ -2560,7 +2562,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
2560 if ( elementDefinition && elementDefinition.padding !== undefined ) { 2562 if ( elementDefinition && elementDefinition.padding !== undefined ) {
2561 styles.push( 'padding:' + cssLength( elementDefinition.padding ) ); 2563 styles.push( 'padding:' + cssLength( elementDefinition.padding ) );
2562 } 2564 }
2563 // In IE Quirks alignment has to be done on table cells. (#7324) 2565 // In IE Quirks alignment has to be done on table cells. (http://dev.ckeditor.com/ticket/7324)
2564 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align ) { 2566 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align ) {
2565 styles.push( 'text-align:' + children[ i ].align ); 2567 styles.push( 'text-align:' + children[ i ].align );
2566 } 2568 }
@@ -2619,7 +2621,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
2619 html.push( 'height:100%;' ); 2621 html.push( 'height:100%;' );
2620 html.push( 'width:' + cssLength( width || '100%' ), ';' ); 2622 html.push( 'width:' + cssLength( width || '100%' ), ';' );
2621 2623
2622 // (#10123) Temp fix for dialog broken layout in latest webkit. 2624 // (http://dev.ckeditor.com/ticket/10123) Temp fix for dialog broken layout in latest webkit.
2623 if ( CKEDITOR.env.webkit ) 2625 if ( CKEDITOR.env.webkit )
2624 html.push( 'float:none;' ); 2626 html.push( 'float:none;' );
2625 2627
@@ -2639,7 +2641,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
2639 styles.push( 'height:' + Math.floor( 100 / childHtmlList.length ) + '%' ); 2641 styles.push( 'height:' + Math.floor( 100 / childHtmlList.length ) + '%' );
2640 if ( elementDefinition && elementDefinition.padding !== undefined ) 2642 if ( elementDefinition && elementDefinition.padding !== undefined )
2641 styles.push( 'padding:' + cssLength( elementDefinition.padding ) ); 2643 styles.push( 'padding:' + cssLength( elementDefinition.padding ) );
2642 // In IE Quirks alignment has to be done on table cells. (#7324) 2644 // In IE Quirks alignment has to be done on table cells. (http://dev.ckeditor.com/ticket/7324)
2643 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align ) 2645 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align )
2644 styles.push( 'text-align:' + children[ i ].align ); 2646 styles.push( 'text-align:' + children[ i ].align );
2645 if ( styles.length > 0 ) 2647 if ( styles.length > 0 )
@@ -2984,7 +2986,7 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
2984 /** 2986 /**
2985 * Generic dialog command. It opens a specific dialog when executed. 2987 * Generic dialog command. It opens a specific dialog when executed.
2986 * 2988 *
2987 * // Register the "link" command, which opens the "link" dialog. 2989 * // Register the "link" command which opens the "link" dialog.
2988 * editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) ); 2990 * editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) );
2989 * 2991 *
2990 * @class 2992 * @class
@@ -2993,6 +2995,10 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
2993 * @param {String} dialogName The name of the dialog to open when executing 2995 * @param {String} dialogName The name of the dialog to open when executing
2994 * this command. 2996 * this command.
2995 * @param {Object} [ext] Additional command definition's properties. 2997 * @param {Object} [ext] Additional command definition's properties.
2998 * @param {String} [ext.tabId] You can provide additional property (`tabId`) if you wish to open the dialog on a specific tabId.
2999 *
3000 * // Open the dialog on the 'keystroke' tabId.
3001 * editor.addCommand( 'keystroke', new CKEDITOR.dialogCommand( 'a11yHelp', { tabId: 'keystroke' } ) );
2996 */ 3002 */
2997 CKEDITOR.dialogCommand = function( dialogName, ext ) { 3003 CKEDITOR.dialogCommand = function( dialogName, ext ) {
2998 this.dialogName = dialogName; 3004 this.dialogName = dialogName;
@@ -3001,7 +3007,13 @@ CKEDITOR.DIALOG_STATE_BUSY = 2;
3001 3007
3002 CKEDITOR.dialogCommand.prototype = { 3008 CKEDITOR.dialogCommand.prototype = {
3003 exec: function( editor ) { 3009 exec: function( editor ) {
3004 editor.openDialog( this.dialogName ); 3010 var tabId = this.tabId;
3011 editor.openDialog( this.dialogName, function( dialog ) {
3012 // Select different tab if it's provided (#830).
3013 if ( tabId ) {
3014 dialog.selectPage( tabId );
3015 }
3016 } );
3005 }, 3017 },
3006 3018
3007 // Dialog commands just open a dialog ui, thus require no undo logic, 3019 // Dialog commands just open a dialog ui, thus require no undo logic,
diff --git a/sources/plugins/dialogui/plugin.js b/sources/plugins/dialogui/plugin.js
index cf91407..ab36791 100644
--- a/sources/plugins/dialogui/plugin.js
+++ b/sources/plugins/dialogui/plugin.js
@@ -72,7 +72,7 @@ CKEDITOR.plugins.add( 'dialogui', {
72 if ( !this._.domOnChangeRegistered ) { 72 if ( !this._.domOnChangeRegistered ) {
73 dialog.on( 'load', function() { 73 dialog.on( 'load', function() {
74 this.getInputElement().on( 'change', function() { 74 this.getInputElement().on( 'change', function() {
75 // Make sure 'onchange' doesn't get fired after dialog closed. (#5719) 75 // Make sure 'onchange' doesn't get fired after dialog closed. (http://dev.ckeditor.com/ticket/5719)
76 if ( !dialog.parts.dialog.isVisible() ) 76 if ( !dialog.parts.dialog.isVisible() )
77 return; 77 return;
78 78
@@ -240,7 +240,7 @@ CKEDITOR.plugins.add( 'dialogui', {
240 keyPressedOnMe = true; 240 keyPressedOnMe = true;
241 } ); 241 } );
242 242
243 // Lower the priority this 'keyup' since 'ok' will close the dialog.(#3749) 243 // Lower the priority this 'keyup' since 'ok' will close the dialog.(http://dev.ckeditor.com/ticket/3749)
244 me.getInputElement().on( 'keyup', function( evt ) { 244 me.getInputElement().on( 'keyup', function( evt ) {
245 if ( evt.data.getKeystroke() == 13 && keyPressedOnMe ) { 245 if ( evt.data.getKeystroke() == 13 && keyPressedOnMe ) {
246 dialog.getButton( 'ok' ) && setTimeout( function() { 246 dialog.getButton( 'ok' ) && setTimeout( function() {
@@ -472,7 +472,7 @@ CKEDITOR.plugins.add( 'dialogui', {
472 if ( typeof inputDefinition.inputStyle != 'undefined' ) 472 if ( typeof inputDefinition.inputStyle != 'undefined' )
473 inputDefinition.style = inputDefinition.inputStyle; 473 inputDefinition.style = inputDefinition.inputStyle;
474 474
475 // Make inputs of radio type focusable (#10866). 475 // Make inputs of radio type focusable (http://dev.ckeditor.com/ticket/10866).
476 inputDefinition.keyboardFocusable = true; 476 inputDefinition.keyboardFocusable = true;
477 477
478 children.push( new CKEDITOR.ui.dialog.uiElement( dialog, inputDefinition, inputHtml, 'input', null, inputAttributes ) ); 478 children.push( new CKEDITOR.ui.dialog.uiElement( dialog, inputDefinition, inputHtml, 'input', null, inputAttributes ) );
@@ -537,7 +537,7 @@ CKEDITOR.plugins.add( 'dialogui', {
537 ( function() { 537 ( function() {
538 element.on( 'click', function( evt ) { 538 element.on( 'click', function( evt ) {
539 me.click(); 539 me.click();
540 // #9958 540 // http://dev.ckeditor.com/ticket/9958
541 evt.data.preventDefault(); 541 evt.data.preventDefault();
542 } ); 542 } );
543 543
@@ -686,7 +686,7 @@ CKEDITOR.plugins.add( 'dialogui', {
686 ' src="javascript:void(' 686 ' src="javascript:void('
687 ]; 687 ];
688 688
689 // Support for custom document.domain on IE. (#10165) 689 // Support for custom document.domain on IE. (http://dev.ckeditor.com/ticket/10165)
690 html.push( CKEDITOR.env.ie ? 690 html.push( CKEDITOR.env.ie ?
691 '(function(){' + encodeURIComponent( 691 '(function(){' + encodeURIComponent(
692 'document.open();' + 692 'document.open();' +
@@ -1423,7 +1423,7 @@ CKEDITOR.plugins.add( 'dialogui', {
1423 '<label id="', _.labelId, '" for="', inputId, '" style="display:none">', 1423 '<label id="', _.labelId, '" for="', inputId, '" style="display:none">',
1424 CKEDITOR.tools.htmlEncode( elementDefinition.label ), 1424 CKEDITOR.tools.htmlEncode( elementDefinition.label ),
1425 '</label>', 1425 '</label>',
1426 // Set width to make sure that input is not clipped by the iframe (#11253). 1426 // Set width to make sure that input is not clipped by the iframe (http://dev.ckeditor.com/ticket/11253).
1427 '<input style="width:100%" id="', inputId, '" aria-labelledby="', _.labelId, '" type="file" name="', 1427 '<input style="width:100%" id="', inputId, '" aria-labelledby="', _.labelId, '" type="file" name="',
1428 CKEDITOR.tools.htmlEncode( elementDefinition.id || 'cke_upload' ), 1428 CKEDITOR.tools.htmlEncode( elementDefinition.id || 'cke_upload' ),
1429 '" size="', 1429 '" size="',
@@ -1446,7 +1446,7 @@ CKEDITOR.plugins.add( 'dialogui', {
1446 buttons[ i ].enable(); 1446 buttons[ i ].enable();
1447 } 1447 }
1448 1448
1449 // #3465: Wait for the browser to finish rendering the dialog first. 1449 // http://dev.ckeditor.com/ticket/3465: Wait for the browser to finish rendering the dialog first.
1450 if ( CKEDITOR.env.gecko ) 1450 if ( CKEDITOR.env.gecko )
1451 setTimeout( generateFormField, 500 ); 1451 setTimeout( generateFormField, 500 );
1452 else 1452 else
diff --git a/sources/plugins/div/dialogs/div.js b/sources/plugins/div/dialogs/div.js
index 140424f..73dde56 100644
--- a/sources/plugins/div/dialogs/div.js
+++ b/sources/plugins/div/dialogs/div.js
@@ -44,7 +44,7 @@
44 var container = editor.elementPath( element ).blockLimit; 44 var container = editor.elementPath( element ).blockLimit;
45 45
46 // Never consider read-only (i.e. contenteditable=false) element as 46 // Never consider read-only (i.e. contenteditable=false) element as
47 // a first div limit (#11083). 47 // a first div limit (http://dev.ckeditor.com/ticket/11083).
48 if ( container.isReadOnly() ) 48 if ( container.isReadOnly() )
49 container = container.getParent(); 49 container = container.getParent();
50 50
@@ -131,12 +131,24 @@
131 var ancestor, divElement; 131 var ancestor, divElement;
132 132
133 for ( i = 0; i < blockGroups.length; i++ ) { 133 for ( i = 0; i < blockGroups.length; i++ ) {
134 // Sometimes we could get empty block group if all elements inside it
135 // don't have parent's nodes (http://dev.ckeditor.com/ticket/13585).
136 if ( !blockGroups[ i ].length ) {
137 continue;
138 }
139
134 var currentNode = blockGroups[ i ][ 0 ]; 140 var currentNode = blockGroups[ i ][ 0 ];
135 141
136 // Calculate the common parent node of all contained elements. 142 // Calculate the common parent node of all contained elements.
137 ancestor = currentNode.getParent(); 143 ancestor = currentNode.getParent();
138 for ( j = 1; j < blockGroups[ i ].length; j++ ) 144 for ( j = 1; j < blockGroups[ i ].length; j++ ) {
139 ancestor = ancestor.getCommonAncestor( blockGroups[ i ][ j ] ); 145 ancestor = ancestor.getCommonAncestor( blockGroups[ i ][ j ] );
146 }
147
148 // If there is no ancestor, mark editable as one (http://dev.ckeditor.com/ticket/13585).
149 if ( !ancestor ) {
150 ancestor = editor.editable();
151 }
140 152
141 divElement = new CKEDITOR.dom.element( 'div', editor.document ); 153 divElement = new CKEDITOR.dom.element( 'div', editor.document );
142 154
@@ -144,8 +156,10 @@
144 for ( j = 0; j < blockGroups[ i ].length; j++ ) { 156 for ( j = 0; j < blockGroups[ i ].length; j++ ) {
145 currentNode = blockGroups[ i ][ j ]; 157 currentNode = blockGroups[ i ][ j ];
146 158
147 while ( !currentNode.getParent().equals( ancestor ) ) 159 // Check if the currentNode has a parent before attempting to operate on it (http://dev.ckeditor.com/ticket/13585).
160 while ( currentNode.getParent() && !currentNode.getParent().equals( ancestor ) ) {
148 currentNode = currentNode.getParent(); 161 currentNode = currentNode.getParent();
162 }
149 163
150 // This could introduce some duplicated elements in array. 164 // This could introduce some duplicated elements in array.
151 blockGroups[ i ][ j ] = currentNode; 165 blockGroups[ i ][ j ] = currentNode;
@@ -160,8 +174,9 @@
160 currentNode.is && CKEDITOR.dom.element.setMarker( database, currentNode, 'block_processed', true ); 174 currentNode.is && CKEDITOR.dom.element.setMarker( database, currentNode, 'block_processed', true );
161 175
162 // Establish new container, wrapping all elements in this group. 176 // Establish new container, wrapping all elements in this group.
163 if ( !j ) 177 if ( !j ) {
164 divElement.insertBefore( currentNode ); 178 divElement.insertBefore( currentNode );
179 }
165 180
166 divElement.append( currentNode ); 181 divElement.append( currentNode );
167 } 182 }
@@ -192,8 +207,13 @@
192 lastDivLimit = limit; 207 lastDivLimit = limit;
193 groups.push( [] ); 208 groups.push( [] );
194 } 209 }
195 groups[ groups.length - 1 ].push( block ); 210
211 // Sometimes we got nodes that are not inside the DOM, which causes error (http://dev.ckeditor.com/ticket/13585).
212 if ( block.getParent() ) {
213 groups[ groups.length - 1 ].push( block );
214 }
196 } 215 }
216
197 return groups; 217 return groups;
198 } 218 }
199 219
@@ -368,7 +388,7 @@
368 // it if no options are available at all. 388 // it if no options are available at all.
369 stylesField[ stylesField.items.length > 1 ? 'enable' : 'disable' ](); 389 stylesField[ stylesField.items.length > 1 ? 'enable' : 'disable' ]();
370 390
371 // Now setup the field value manually if dialog was opened on element. (#9689) 391 // Now setup the field value manually if dialog was opened on element. (http://dev.ckeditor.com/ticket/9689)
372 setTimeout( function() { 392 setTimeout( function() {
373 dialog._element && stylesField.setup( dialog._element ); 393 dialog._element && stylesField.setup( dialog._element );
374 }, 0 ); 394 }, 0 );
@@ -402,7 +422,7 @@
402 this.hide(); 422 this.hide();
403 }, 423 },
404 onHide: function() { 424 onHide: function() {
405 // Remove style only when editing existing DIV. (#6315) 425 // Remove style only when editing existing DIV. (http://dev.ckeditor.com/ticket/6315)
406 if ( command == 'editdiv' ) 426 if ( command == 'editdiv' )
407 this._element.removeCustomData( 'elementStyle' ); 427 this._element.removeCustomData( 'elementStyle' );
408 delete this._element; 428 delete this._element;
diff --git a/sources/plugins/div/lang/es-mx.js b/sources/plugins/div/lang/es-mx.js
new file mode 100644
index 0000000..f3ef630
--- /dev/null
+++ b/sources/plugins/div/lang/es-mx.js
@@ -0,0 +1,19 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'div', 'es-mx', {
6 IdInputLabel: 'Id',
7 advisoryTitleInputLabel: 'Título del anuncio',
8 cssClassInputLabel: 'Clases de la hoja de estilos',
9 edit: 'Editar Div',
10 inlineStyleInputLabel: 'Estilo de línea',
11 langDirLTRLabel: 'Izquierda a Derecha (LTR)',
12 langDirLabel: 'Dirección de idiomas',
13 langDirRTLLabel: 'Derecha a Izquierda (RTL)',
14 languageCodeInputLabel: 'Código del idioma',
15 remove: 'Remover Div',
16 styleSelectLabel: 'Estilo',
17 title: 'Crear contenedor Div',
18 toolbar: 'Crear contenedor Div'
19} );
diff --git a/sources/plugins/div/lang/ja.js b/sources/plugins/div/lang/ja.js
index 50abe05..263326e 100644
--- a/sources/plugins/div/lang/ja.js
+++ b/sources/plugins/div/lang/ja.js
@@ -14,6 +14,6 @@ CKEDITOR.plugins.setLang( 'div', 'ja', {
14 languageCodeInputLabel: ' 言語コード', 14 languageCodeInputLabel: ' 言語コード',
15 remove: 'Divコンテナを削除', 15 remove: 'Divコンテナを削除',
16 styleSelectLabel: 'スタイル', 16 styleSelectLabel: 'スタイル',
17 title: 'Divコンテナ', 17 title: 'Divコンテナを作成',
18 toolbar: 'Divコンテナ' 18 toolbar: 'Divコンテナを作成'
19} ); 19} );
diff --git a/sources/plugins/div/lang/pt.js b/sources/plugins/div/lang/pt.js
index 5df020c..554e2c4 100644
--- a/sources/plugins/div/lang/pt.js
+++ b/sources/plugins/div/lang/pt.js
@@ -7,11 +7,11 @@ CKEDITOR.plugins.setLang( 'div', 'pt', {
7 advisoryTitleInputLabel: 'Título', 7 advisoryTitleInputLabel: 'Título',
8 cssClassInputLabel: 'Classes de folhas de estilo', 8 cssClassInputLabel: 'Classes de folhas de estilo',
9 edit: 'Editar Div', 9 edit: 'Editar Div',
10 inlineStyleInputLabel: 'Estilho em Linha', 10 inlineStyleInputLabel: 'Estilo na etiqueta',
11 langDirLTRLabel: 'Esquerda para a direita (EPD)', 11 langDirLTRLabel: 'Esquerda para a direita (EPD)',
12 langDirLabel: 'Orientação de idioma', 12 langDirLabel: 'Orientação de idioma',
13 langDirRTLLabel: 'Direita para a Esquerda (DPE)', 13 langDirRTLLabel: 'Direita para a Esquerda (DPE)',
14 languageCodeInputLabel: 'Codigo do Idioma', 14 languageCodeInputLabel: 'Código do idioma',
15 remove: 'Remover Div', 15 remove: 'Remover Div',
16 styleSelectLabel: 'Estilo', 16 styleSelectLabel: 'Estilo',
17 title: 'Criar Div', 17 title: 'Criar Div',
diff --git a/sources/plugins/div/plugin.js b/sources/plugins/div/plugin.js
index dbced72..a64d9e9 100644
--- a/sources/plugins/div/plugin.js
+++ b/sources/plugins/div/plugin.js
@@ -12,7 +12,7 @@
12 CKEDITOR.plugins.add( 'div', { 12 CKEDITOR.plugins.add( 'div', {
13 requires: 'dialog', 13 requires: 'dialog',
14 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
16 // jscs:enable maximumLineLength 16 // jscs:enable maximumLineLength
17 icons: 'creatediv', // %REMOVE_LINE_CORE% 17 icons: 'creatediv', // %REMOVE_LINE_CORE%
18 hidpi: true, // %REMOVE_LINE_CORE% 18 hidpi: true, // %REMOVE_LINE_CORE%
@@ -126,7 +126,7 @@
126 getSurroundDiv: function( editor, start ) { 126 getSurroundDiv: function( editor, start ) {
127 var path = editor.elementPath( start ); 127 var path = editor.elementPath( start );
128 return editor.elementPath( path.blockLimit ).contains( function( node ) { 128 return editor.elementPath( path.blockLimit ).contains( function( node ) {
129 // Avoid read-only (i.e. contenteditable="false") divs (#11083). 129 // Avoid read-only (i.e. contenteditable="false") divs (http://dev.ckeditor.com/ticket/11083).
130 return node.is( 'div' ) && !node.isReadOnly(); 130 return node.is( 'div' ) && !node.isReadOnly();
131 }, 1 ); 131 }, 1 );
132 } 132 }
diff --git a/sources/plugins/elementspath/lang/es-mx.js b/sources/plugins/elementspath/lang/es-mx.js
new file mode 100644
index 0000000..625d951
--- /dev/null
+++ b/sources/plugins/elementspath/lang/es-mx.js
@@ -0,0 +1,8 @@
1/*
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-mx', {
6 eleLabel: 'Ruta de los elementos',
7 eleTitle: '%1 elemento'
8} );
diff --git a/sources/plugins/elementspath/lang/hr.js b/sources/plugins/elementspath/lang/hr.js
index 90a7fd0..004182b 100644
--- a/sources/plugins/elementspath/lang/hr.js
+++ b/sources/plugins/elementspath/lang/hr.js
@@ -3,6 +3,6 @@ Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license 3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/ 4*/
5CKEDITOR.plugins.setLang( 'elementspath', 'hr', { 5CKEDITOR.plugins.setLang( 'elementspath', 'hr', {
6 eleLabel: 'Putanja elemenata', 6 eleLabel: 'Putanje elemenata',
7 eleTitle: '%1 element' 7 eleTitle: '%1 element'
8} ); 8} );
diff --git a/sources/plugins/elementspath/plugin.js b/sources/plugins/elementspath/plugin.js
index 07ba5c2..f66d7ad 100644
--- a/sources/plugins/elementspath/plugin.js
+++ b/sources/plugins/elementspath/plugin.js
@@ -17,7 +17,7 @@
17 var idBase = editor._.elementsPath.idBase; 17 var idBase = editor._.elementsPath.idBase;
18 var element = CKEDITOR.document.getById( idBase + '0' ); 18 var element = CKEDITOR.document.getById( idBase + '0' );
19 19
20 // Make the first button focus accessible for IE. (#3417) 20 // Make the first button focus accessible for IE. (http://dev.ckeditor.com/ticket/3417)
21 // Adobe AIR instead need while of delay. 21 // Adobe AIR instead need while of delay.
22 element && element.focus( CKEDITOR.env.ie || CKEDITOR.env.air ); 22 element && element.focus( CKEDITOR.env.ie || CKEDITOR.env.air );
23 } 23 }
@@ -55,7 +55,7 @@
55 55
56 CKEDITOR.plugins.add( 'elementspath', { 56 CKEDITOR.plugins.add( 'elementspath', {
57 // jscs:disable maximumLineLength 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% 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,es-mx,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 59 // jscs:enable maximumLineLength
60 init: function( editor ) { 60 init: function( editor ) {
61 editor._.elementsPath = { 61 editor._.elementsPath = {
@@ -104,13 +104,13 @@
104 selection.selectElement( element ); 104 selection.selectElement( element );
105 } 105 }
106 106
107 // Explicitly fire selectionChange when clicking on an element path button. (#13548) 107 // Explicitly fire selectionChange when clicking on an element path button. (http://dev.ckeditor.com/ticket/13548)
108 if ( CKEDITOR.env.ie ) { 108 if ( CKEDITOR.env.ie ) {
109 editor.fire( 'selectionChange', { selection: selection, path: new CKEDITOR.dom.elementPath( element ) } ); 109 editor.fire( 'selectionChange', { selection: selection, path: new CKEDITOR.dom.elementPath( element ) } );
110 } 110 }
111 111
112 // It is important to focus() *after* the above selection 112 // It is important to focus() *after* the above selection
113 // manipulation, otherwise Firefox will have troubles. #10119 113 // manipulation, otherwise Firefox will have troubles. http://dev.ckeditor.com/ticket/10119
114 editor.focus(); 114 editor.focus();
115 } 115 }
116 116
@@ -160,7 +160,7 @@
160 filters = elementsPath.filters, 160 filters = elementsPath.filters,
161 isContentEditable = true, 161 isContentEditable = true,
162 162
163 // Use elementPath to consider children of editable only (#11124). 163 // Use elementPath to consider children of editable only (http://dev.ckeditor.com/ticket/11124).
164 elementsChain = editor.elementPath().elements, 164 elementsChain = editor.elementPath().elements,
165 name; 165 name;
166 166
diff --git a/sources/plugins/enterkey/plugin.js b/sources/plugins/enterkey/plugin.js
index 9410bbd..e65555f 100644
--- a/sources/plugins/enterkey/plugin.js
+++ b/sources/plugins/enterkey/plugin.js
@@ -43,7 +43,7 @@
43 return; 43 return;
44 44
45 // When range is in nested editable, we have to replace range with this one, 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) 46 // which have root property set to closest editable, to make auto paragraphing work. (http://dev.ckeditor.com/ticket/12162)
47 range = replaceRangeWithClosestEditableRoot( range ); 47 range = replaceRangeWithClosestEditableRoot( range );
48 48
49 var doc = range.document; 49 var doc = range.document;
@@ -58,9 +58,9 @@
58 58
59 newBlock; 59 newBlock;
60 60
61 // Exit the list when we're inside an empty list item block. (#5376) 61 // Exit the list when we're inside an empty list item block. (http://dev.ckeditor.com/ticket/5376)
62 if ( atBlockStart && atBlockEnd ) { 62 if ( atBlockStart && atBlockEnd ) {
63 // Exit the list when we're inside an empty list item block. (#5376) 63 // Exit the list when we're inside an empty list item block. (http://dev.ckeditor.com/ticket/5376)
64 if ( block && ( block.is( 'li' ) || block.getParent().is( 'li' ) ) ) { 64 if ( block && ( block.is( 'li' ) || block.getParent().is( 'li' ) ) ) {
65 // Make sure to point to the li when dealing with empty list item. 65 // Make sure to point to the li when dealing with empty list item.
66 if ( !block.is( 'li' ) ) 66 if ( !block.is( 'li' ) )
@@ -293,7 +293,7 @@
293 293
294 var node; 294 var node;
295 295
296 // If this is a block under a list item, split it as well. (#1647) 296 // If this is a block under a list item, split it as well. (http://dev.ckeditor.com/ticket/1647)
297 if ( nextBlock ) { 297 if ( nextBlock ) {
298 node = nextBlock.getParent(); 298 node = nextBlock.getParent();
299 if ( node.is( 'li' ) ) { 299 if ( node.is( 'li' ) ) {
@@ -313,7 +313,7 @@
313 if ( !isStartOfBlock && !isEndOfBlock ) { 313 if ( !isStartOfBlock && !isEndOfBlock ) {
314 // If the next block is an <li> with another list tree as the first 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 315 // child, we'll need to append a filler (<br>/NBSP) or the list item
316 // wouldn't be editable. (#1420) 316 // wouldn't be editable. (http://dev.ckeditor.com/ticket/1420)
317 if ( nextBlock.is( 'li' ) ) { 317 if ( nextBlock.is( 'li' ) ) {
318 var walkerRange = range.clone(); 318 var walkerRange = range.clone();
319 walkerRange.selectNodeContents( nextBlock ); 319 walkerRange.selectNodeContents( nextBlock );
@@ -335,7 +335,7 @@
335 335
336 if ( previousBlock ) { 336 if ( previousBlock ) {
337 // Do not enter this block if it's a header tag, or we are in 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 338 // a Shift+Enter (http://dev.ckeditor.com/ticket/77). Create a new block element instead
339 // (later in the code). 339 // (later in the code).
340 if ( previousBlock.is( 'li' ) || !( headerTagRegex.test( previousBlock.getName() ) || previousBlock.is( 'pre' ) ) ) { 340 if ( previousBlock.is( 'li' ) || !( headerTagRegex.test( previousBlock.getName() ) || previousBlock.is( 'pre' ) ) ) {
341 // Otherwise, duplicate the previous block. 341 // Otherwise, duplicate the previous block.
@@ -346,7 +346,7 @@
346 } 346 }
347 347
348 if ( !newBlock ) { 348 if ( !newBlock ) {
349 // We have already created a new list item. (#6849) 349 // We have already created a new list item. (http://dev.ckeditor.com/ticket/6849)
350 if ( node && node.is( 'li' ) ) 350 if ( node && node.is( 'li' ) )
351 newBlock = node; 351 newBlock = node;
352 else { 352 else {
@@ -384,8 +384,8 @@
384 if ( !newBlock.getParent() ) 384 if ( !newBlock.getParent() )
385 range.insertNode( newBlock ); 385 range.insertNode( newBlock );
386 386
387 // list item start number should not be duplicated (#7330), but we need 387 // list item start number should not be duplicated (http://dev.ckeditor.com/ticket/7330), but we need
388 // to remove the attribute after it's onto the DOM tree because of old IEs (#7581). 388 // to remove the attribute after it's onto the DOM tree because of old IEs (http://dev.ckeditor.com/ticket/7581).
389 newBlock.is( 'li' ) && newBlock.removeAttribute( 'value' ); 389 newBlock.is( 'li' ) && newBlock.removeAttribute( 'value' );
390 390
391 // This is tricky, but to make the new block visible correctly 391 // This is tricky, but to make the new block visible correctly
@@ -453,7 +453,7 @@
453 } else { 453 } else {
454 var lineBreak; 454 var lineBreak;
455 455
456 // IE<8 prefers text node as line-break inside of <pre> (#4711). 456 // IE<8 prefers text node as line-break inside of <pre> (http://dev.ckeditor.com/ticket/4711).
457 if ( startBlockTag == 'pre' && CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) 457 if ( startBlockTag == 'pre' && CKEDITOR.env.ie && CKEDITOR.env.version < 8 )
458 lineBreak = doc.createText( '\r' ); 458 lineBreak = doc.createText( '\r' );
459 else 459 else
@@ -503,7 +503,7 @@
503 function shiftEnter( editor ) { 503 function shiftEnter( editor ) {
504 // On SHIFT+ENTER: 504 // On SHIFT+ENTER:
505 // 1. We want to enforce the mode to be respected, instead 505 // 1. We want to enforce the mode to be respected, instead
506 // of cloning the current block. (#77) 506 // of cloning the current block. (http://dev.ckeditor.com/ticket/77)
507 return enter( editor, editor.activeShiftEnterMode, 1 ); 507 return enter( editor, editor.activeShiftEnterMode, 1 );
508 } 508 }
509 509
@@ -521,7 +521,8 @@
521 // Check path block specialities: 521 // Check path block specialities:
522 // 1. Cannot be a un-splittable element, e.g. table caption; 522 // 1. Cannot be a un-splittable element, e.g. table caption;
523 var path = editor.elementPath(); 523 var path = editor.elementPath();
524 if ( !path.isContextFor( 'p' ) ) { 524
525 if ( path && !path.isContextFor( 'p' ) ) {
525 mode = CKEDITOR.ENTER_BR; 526 mode = CKEDITOR.ENTER_BR;
526 forceMode = 1; 527 forceMode = 1;
527 } 528 }
diff --git a/sources/plugins/fakeobjects/lang/es-mx.js b/sources/plugins/fakeobjects/lang/es-mx.js
new file mode 100644
index 0000000..f9e87e7
--- /dev/null
+++ b/sources/plugins/fakeobjects/lang/es-mx.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-mx', {
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/plugin.js b/sources/plugins/fakeobjects/plugin.js
index d35698b..b1a8e0c 100644
--- a/sources/plugins/fakeobjects/plugin.js
+++ b/sources/plugins/fakeobjects/plugin.js
@@ -53,7 +53,7 @@
53 53
54 CKEDITOR.plugins.add( 'fakeobjects', { 54 CKEDITOR.plugins.add( 'fakeobjects', {
55 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
57 // jscs:enable maximumLineLength 57 // jscs:enable maximumLineLength
58 58
59 init: function( editor ) { 59 init: function( editor ) {
@@ -75,8 +75,15 @@
75 } ); 75 } );
76 76
77 /** 77 /**
78 * Creates fake {@link CKEDITOR.dom.element} based on real element.
79 * Fake element is an img with special attributes, which keep real element properties.
80 *
78 * @member CKEDITOR.editor 81 * @member CKEDITOR.editor
79 * @todo 82 * @param {CKEDITOR.dom.element} realElement Real element to transform.
83 * @param {String} className Class name which will be used as class of fake element.
84 * @param {String} realElementType Stores type of fake element.
85 * @param {Boolean} isResizable Keeps information if element is resizable.
86 * @returns {CKEDITOR.dom.element} Fake element.
80 */ 87 */
81 CKEDITOR.editor.prototype.createFakeElement = function( realElement, className, realElementType, isResizable ) { 88 CKEDITOR.editor.prototype.createFakeElement = function( realElement, className, realElementType, isResizable ) {
82 var lang = this.lang.fakeobjects, 89 var lang = this.lang.fakeobjects,
@@ -91,7 +98,7 @@
91 align: realElement.getAttribute( 'align' ) || '' 98 align: realElement.getAttribute( 'align' ) || ''
92 }; 99 };
93 100
94 // Do not set "src" on high-contrast so the alt text is displayed. (#8945) 101 // Do not set "src" on high-contrast so the alt text is displayed. (http://dev.ckeditor.com/ticket/8945)
95 if ( !CKEDITOR.env.hc ) 102 if ( !CKEDITOR.env.hc )
96 attributes.src = CKEDITOR.tools.transparentImageData; 103 attributes.src = CKEDITOR.tools.transparentImageData;
97 104
@@ -115,8 +122,14 @@
115 }; 122 };
116 123
117 /** 124 /**
125 * Creates fake {@link CKEDITOR.htmlParser.element} based on real element.
126 *
118 * @member CKEDITOR.editor 127 * @member CKEDITOR.editor
119 * @todo 128 * @param {CKEDITOR.dom.element} realElement Real element to transform.
129 * @param {String} className Class name which will be used as class of fake element.
130 * @param {String} realElementType Store type of fake element.
131 * @param {Boolean} isResizable Keep information if element is resizable.
132 * @returns {CKEDITOR.htmlParser.element} Fake htmlParser element.
120 */ 133 */
121 CKEDITOR.editor.prototype.createFakeParserElement = function( realElement, className, realElementType, isResizable ) { 134 CKEDITOR.editor.prototype.createFakeParserElement = function( realElement, className, realElementType, isResizable ) {
122 var lang = this.lang.fakeobjects, 135 var lang = this.lang.fakeobjects,
@@ -136,7 +149,7 @@
136 align: realElement.attributes.align || '' 149 align: realElement.attributes.align || ''
137 }; 150 };
138 151
139 // Do not set "src" on high-contrast so the alt text is displayed. (#8945) 152 // Do not set "src" on high-contrast so the alt text is displayed. (http://dev.ckeditor.com/ticket/8945)
140 if ( !CKEDITOR.env.hc ) 153 if ( !CKEDITOR.env.hc )
141 attributes.src = CKEDITOR.tools.transparentImageData; 154 attributes.src = CKEDITOR.tools.transparentImageData;
142 155
@@ -160,8 +173,11 @@
160 }; 173 };
161 174
162 /** 175 /**
176 * Creates {@link CKEDITOR.dom.element} from fake element.
177 *
163 * @member CKEDITOR.editor 178 * @member CKEDITOR.editor
164 * @todo 179 * @param {CKEDITOR.dom.element} fakeElement Fake element to transform.
180 * @returns {CKEDITOR.dom.element/null} Returns real element or `null` if transformed element wasn't fake.
165 */ 181 */
166 CKEDITOR.editor.prototype.restoreRealElement = function( fakeElement ) { 182 CKEDITOR.editor.prototype.restoreRealElement = function( fakeElement ) {
167 if ( fakeElement.data( 'cke-real-node-type' ) != CKEDITOR.NODE_ELEMENT ) 183 if ( fakeElement.data( 'cke-real-node-type' ) != CKEDITOR.NODE_ELEMENT )
diff --git a/sources/plugins/filebrowser/plugin.js b/sources/plugins/filebrowser/plugin.js
index a622a37..51744f5 100644
--- a/sources/plugins/filebrowser/plugin.js
+++ b/sources/plugins/filebrowser/plugin.js
@@ -167,7 +167,7 @@
167 params.langCode = editor.langCode; 167 params.langCode = editor.langCode;
168 168
169 var url = addQueryString( this.filebrowser.url, params ); 169 var url = addQueryString( this.filebrowser.url, params );
170 // TODO: V4: Remove backward compatibility (#8163). 170 // TODO: V4: Remove backward compatibility (http://dev.ckeditor.com/ticket/8163).
171 editor.popup( url, width, height, editor.config.filebrowserWindowFeatures || editor.config.fileBrowserWindowFeatures ); 171 editor.popup( url, width, height, editor.config.filebrowserWindowFeatures || editor.config.fileBrowserWindowFeatures );
172 } 172 }
173 173
diff --git a/sources/plugins/floatingspace/plugin.js b/sources/plugins/floatingspace/plugin.js
index 878d952..bea3306 100644
--- a/sources/plugins/floatingspace/plugin.js
+++ b/sources/plugins/floatingspace/plugin.js
@@ -68,7 +68,7 @@
68 } 68 }
69 69
70 return function( evt ) { 70 return function( evt ) {
71 // #10112 Do not fail on editable-less editor. 71 // http://dev.ckeditor.com/ticket/10112 Do not fail on editable-less editor.
72 if ( !( editable = editor.editable() ) ) 72 if ( !( editable = editor.editable() ) )
73 return; 73 return;
74 74
@@ -159,7 +159,7 @@
159 alignSide = mid - editorRect.left > editorRect.right - mid ? 'left' : 'right'; 159 alignSide = mid - editorRect.left > editorRect.right - mid ? 'left' : 'right';
160 } 160 }
161 161
162 // (#9769) If viewport width is less than space width, 162 // (http://dev.ckeditor.com/ticket/9769) If viewport width is less than space width,
163 // make sure space never cross the left boundary of the viewport. 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. 164 // In other words: top-left corner of the space is always visible.
165 if ( spaceRect.width > viewRect.width ) { 165 if ( spaceRect.width > viewRect.width ) {
@@ -226,7 +226,7 @@
226 offset = 0; 226 offset = 0;
227 } 227 }
228 228
229 // (#9769) Finally, stick the space to the opposite side of 229 // (http://dev.ckeditor.com/ticket/9769) Finally, stick the space to the opposite side of
230 // the viewport when it's cut off horizontally on the left/right 230 // the viewport when it's cut off horizontally on the left/right
231 // side like below. 231 // side like below.
232 // 232 //
@@ -258,7 +258,7 @@
258 } 258 }
259 259
260 // Pin mode is fixed, so don't include scroll-x. 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. 261 // (http://dev.ckeditor.com/ticket/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; 262 var scroll = mode == 'pin' ? 0 : alignSide == 'left' ? pageScrollX : -pageScrollX;
263 263
264 floatSpace.setStyle( alignSide, pixelate( ( mode == 'pin' ? pinnedOffsetX : dockedOffsetX ) + offset + scroll ) ); 264 floatSpace.setStyle( alignSide, pixelate( ( mode == 'pin' ? pinnedOffsetX : dockedOffsetX ) + offset + scroll ) );
diff --git a/sources/plugins/floatpanel/plugin.js b/sources/plugins/floatpanel/plugin.js
index 1a851f9..c480696 100644
--- a/sources/plugins/floatpanel/plugin.js
+++ b/sources/plugins/floatpanel/plugin.js
@@ -61,7 +61,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
61 iframe = element.getFirst(), 61 iframe = element.getFirst(),
62 that = this; 62 that = this;
63 63
64 // Disable native browser menu. (#4825) 64 // Disable native browser menu. (http://dev.ckeditor.com/ticket/4825)
65 element.disableContextMenu(); 65 element.disableContextMenu();
66 66
67 this.element = element; 67 this.element = element;
@@ -83,7 +83,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
83 editor.on( 'resize', hide ); 83 editor.on( 'resize', hide );
84 84
85 // When resize of the window is triggered floatpanel should be repositioned according to new dimensions. 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. 86 // http://dev.ckeditor.com/ticket/11724. Fixes issue with undesired panel hiding on Android and iOS.
87 doc.getWindow().on( 'resize', function() { 87 doc.getWindow().on( 'resize', function() {
88 this.reposition(); 88 this.reposition();
89 }, this ); 89 }, this );
@@ -155,7 +155,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
155 155
156 var element = this.element, 156 var element = this.element,
157 iframe = this._.iframe, 157 iframe = this._.iframe,
158 // Edge prefers iframe's window to the iframe, just like the rest of the browsers (#13143). 158 // Edge prefers iframe's window to the iframe, just like the rest of the browsers (http://dev.ckeditor.com/ticket/13143).
159 focused = CKEDITOR.env.ie && !CKEDITOR.env.edge ? iframe : new CKEDITOR.dom.window( iframe.$.contentWindow ), 159 focused = CKEDITOR.env.ie && !CKEDITOR.env.edge ? iframe : new CKEDITOR.dom.window( iframe.$.contentWindow ),
160 doc = element.getDocument(), 160 doc = element.getDocument(),
161 positionedAncestor = this._.parentElement.getPositionedAncestor(), 161 positionedAncestor = this._.parentElement.getPositionedAncestor(),
@@ -165,7 +165,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
165 left = position.x + ( offsetX || 0 ) - positionedAncestorPosition.x, 165 left = position.x + ( offsetX || 0 ) - positionedAncestorPosition.x,
166 top = position.y + ( offsetY || 0 ) - positionedAncestorPosition.y; 166 top = position.y + ( offsetY || 0 ) - positionedAncestorPosition.y;
167 167
168 // Floating panels are off by (-1px, 0px) in RTL mode. (#3438) 168 // Floating panels are off by (-1px, 0px) in RTL mode. (http://dev.ckeditor.com/ticket/3438)
169 if ( rtl && ( corner == 1 || corner == 4 ) ) 169 if ( rtl && ( corner == 1 || corner == 4 ) )
170 left += offsetParent.$.offsetWidth; 170 left += offsetParent.$.offsetWidth;
171 else if ( !rtl && ( corner == 2 || corner == 3 ) ) 171 else if ( !rtl && ( corner == 2 || corner == 3 ) )
@@ -198,7 +198,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
198 198
199 // With addEventListener compatible browsers, we must 199 // With addEventListener compatible browsers, we must
200 // useCapture when registering the focus/blur events to 200 // useCapture when registering the focus/blur events to
201 // guarantee they will be firing in all situations. (#3068, #3222 ) 201 // guarantee they will be firing in all situations. (http://dev.ckeditor.com/ticket/3068, http://dev.ckeditor.com/ticket/3222 )
202 CKEDITOR.event.useCapture = true; 202 CKEDITOR.event.useCapture = true;
203 203
204 focused.on( 'blur', function( ev ) { 204 focused.on( 'blur', function( ev ) {
@@ -211,7 +211,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
211 211
212 if ( this.visible && !this._.activeChild ) { 212 if ( this.visible && !this._.activeChild ) {
213 // [iOS] Allow hide to be prevented if touch is bound 213 // [iOS] Allow hide to be prevented if touch is bound
214 // to any parent of the iframe blur happens before touch (#10714). 214 // to any parent of the iframe blur happens before touch (http://dev.ckeditor.com/ticket/10714).
215 if ( CKEDITOR.env.iOS ) { 215 if ( CKEDITOR.env.iOS ) {
216 if ( !this._.hideTimeout ) 216 if ( !this._.hideTimeout )
217 this._.hideTimeout = CKEDITOR.tools.setTimeout( doHide, 0, this ); 217 this._.hideTimeout = CKEDITOR.tools.setTimeout( doHide, 0, this );
@@ -235,7 +235,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
235 }, this ); 235 }, this );
236 236
237 // [iOS] if touch is bound to any parent of the iframe blur 237 // [iOS] if touch is bound to any parent of the iframe blur
238 // happens twice before touchstart and before touchend (#10714). 238 // happens twice before touchstart and before touchend (http://dev.ckeditor.com/ticket/10714).
239 if ( CKEDITOR.env.iOS ) { 239 if ( CKEDITOR.env.iOS ) {
240 // Prevent false hiding on blur. 240 // Prevent false hiding on blur.
241 // We don't need to return focus here because touchend will fire anyway. 241 // We don't need to return focus here because touchend will fire anyway.
@@ -266,7 +266,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
266 var target = element; 266 var target = element;
267 267
268 // Reset panel width as the new content can be narrower 268 // Reset panel width as the new content can be narrower
269 // than the old one. (#9355) 269 // than the old one. (http://dev.ckeditor.com/ticket/9355)
270 target.removeStyle( 'width' ); 270 target.removeStyle( 'width' );
271 271
272 if ( block.autoSize ) { 272 if ( block.autoSize ) {
@@ -275,7 +275,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
275 275
276 // Account for extra height needed due to IE quirks box model bug: 276 // Account for extra height needed due to IE quirks box model bug:
277 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug 277 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
278 // (#3426) 278 // (http://dev.ckeditor.com/ticket/3426)
279 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && width > 0 ) 279 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && width > 0 )
280 width += ( target.$.offsetWidth || 0 ) - ( target.$.clientWidth || 0 ) + 3; 280 width += ( target.$.offsetWidth || 0 ) - ( target.$.clientWidth || 0 ) + 3;
281 281
@@ -288,7 +288,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
288 288
289 // Account for extra height needed due to IE quirks box model bug: 289 // Account for extra height needed due to IE quirks box model bug:
290 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug 290 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
291 // (#3426) 291 // (http://dev.ckeditor.com/ticket/3426)
292 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && height > 0 ) 292 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && height > 0 )
293 height += ( target.$.offsetHeight || 0 ) - ( target.$.clientHeight || 0 ) + 3; 293 height += ( target.$.offsetHeight || 0 ) - ( target.$.clientHeight || 0 ) + 3;
294 294
@@ -364,7 +364,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
364 364
365 // If IE is in RTL, we have troubles with absolute 365 // If IE is in RTL, we have troubles with absolute
366 // position and horizontal scrolls. Here we have a 366 // position and horizontal scrolls. Here we have a
367 // series of hacks to workaround it. (#6146) 367 // series of hacks to workaround it. (http://dev.ckeditor.com/ticket/6146)
368 if ( CKEDITOR.env.ie ) { 368 if ( CKEDITOR.env.ie ) {
369 var offsetParent = new CKEDITOR.dom.element( element.$.offsetParent ), 369 var offsetParent = new CKEDITOR.dom.element( element.$.offsetParent ),
370 scrollParent = offsetParent; 370 scrollParent = offsetParent;
@@ -383,7 +383,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
383 } 383 }
384 384
385 // Trigger the onHide event of the previously active panel to prevent 385 // Trigger the onHide event of the previously active panel to prevent
386 // incorrect styles from being applied (#6170) 386 // incorrect styles from being applied (http://dev.ckeditor.com/ticket/6170)
387 var innerElement = element.getFirst(), 387 var innerElement = element.getFirst(),
388 activePanel; 388 activePanel;
389 if ( ( activePanel = innerElement.getCustomData( 'activePanel' ) ) ) 389 if ( ( activePanel = innerElement.getCustomData( 'activePanel' ) ) )
@@ -410,12 +410,22 @@ CKEDITOR.plugins.add( 'floatpanel', {
410 // Focus the block now. 410 // Focus the block now.
411 block.element.focus(); 411 block.element.focus();
412 412
413 // #10623, #10951 - restore the viewport's scroll position after focusing list element. 413 // http://dev.ckeditor.com/ticket/10623, http://dev.ckeditor.com/ticket/10951 - restore the viewport's scroll position after focusing list element.
414 if ( CKEDITOR.env.webkit ) 414 if ( CKEDITOR.env.webkit )
415 CKEDITOR.document.getBody().$.scrollTop = scrollTop; 415 CKEDITOR.document.getBody().$.scrollTop = scrollTop;
416 416
417 // We need this get fired manually because of unfired focus() function. 417 // We need this get fired manually because of unfired focus() function.
418 this.allowBlur( true ); 418 this.allowBlur( true );
419
420 // Ensure that the first item is focused (http://dev.ckeditor.com/ticket/16804).
421 if ( CKEDITOR.env.ie ) {
422 CKEDITOR.tools.setTimeout( function() {
423 block.markFirstDisplayed ? block.markFirstDisplayed() : block._.markFirstDisplayed();
424 }, 0 );
425 } else {
426 block.markFirstDisplayed ? block.markFirstDisplayed() : block._.markFirstDisplayed();
427 }
428
419 this._.editor.fire( 'panelShow', this ); 429 this._.editor.fire( 'panelShow', this );
420 }, 0, this ); 430 }, 0, this );
421 }, CKEDITOR.env.air ? 200 : 0, this ); 431 }, CKEDITOR.env.air ? 200 : 0, this );
@@ -473,13 +483,13 @@ CKEDITOR.plugins.add( 'floatpanel', {
473 hide: function( returnFocus ) { 483 hide: function( returnFocus ) {
474 if ( this.visible && ( !this.onHide || this.onHide.call( this ) !== true ) ) { 484 if ( this.visible && ( !this.onHide || this.onHide.call( this ) !== true ) ) {
475 this.hideChild(); 485 this.hideChild();
476 // Blur previously focused element. (#6671) 486 // Blur previously focused element. (http://dev.ckeditor.com/ticket/6671)
477 CKEDITOR.env.gecko && this._.iframe.getFrameDocument().$.activeElement.blur(); 487 CKEDITOR.env.gecko && this._.iframe.getFrameDocument().$.activeElement.blur();
478 this.element.setStyle( 'display', 'none' ); 488 this.element.setStyle( 'display', 'none' );
479 this.visible = 0; 489 this.visible = 0;
480 this.element.getFirst().removeCustomData( 'activePanel' ); 490 this.element.getFirst().removeCustomData( 'activePanel' );
481 491
482 // Return focus properly. (#6247) 492 // Return focus properly. (http://dev.ckeditor.com/ticket/6247)
483 var focusReturn = returnFocus && this._.returnFocus; 493 var focusReturn = returnFocus && this._.returnFocus;
484 if ( focusReturn ) { 494 if ( focusReturn ) {
485 // Webkit requires focus moved out panel iframe first. 495 // Webkit requires focus moved out panel iframe first.
@@ -500,7 +510,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
500 * @todo 510 * @todo
501 */ 511 */
502 allowBlur: function( allow ) { 512 allowBlur: function( allow ) {
503 // Prevent editor from hiding the panel. (#3222) 513 // Prevent editor from hiding the panel. (http://dev.ckeditor.com/ticket/3222)
504 var panel = this._.panel; 514 var panel = this._.panel;
505 if ( allow !== undefined ) 515 if ( allow !== undefined )
506 panel.allowBlur = allow; 516 panel.allowBlur = allow;
@@ -553,7 +563,7 @@ CKEDITOR.plugins.add( 'floatpanel', {
553 panel.showBlock( blockName, offsetParent, corner, offsetX, offsetY ); 563 panel.showBlock( blockName, offsetParent, corner, offsetX, offsetY );
554 this.blur(); 564 this.blur();
555 565
556 /* #3767 IE: Second level menu may not have borders */ 566 /* http://dev.ckeditor.com/ticket/3767 IE: Second level menu may not have borders */
557 if ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) { 567 if ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) {
558 setTimeout( function() { 568 setTimeout( function() {
559 panel.element.getChild( 0 ).$.style.cssText += ''; 569 panel.element.getChild( 0 ).$.style.cssText += '';
@@ -584,10 +594,10 @@ CKEDITOR.plugins.add( 'floatpanel', {
584 594
585 for ( var i in panels ) { 595 for ( var i in panels ) {
586 var panel = panels[ i ]; 596 var panel = panels[ i ];
587 // Safe to destroy it since there're no more instances.(#4241) 597 // Safe to destroy it since there're no more instances.(http://dev.ckeditor.com/ticket/4241)
588 if ( isLastInstance ) 598 if ( isLastInstance )
589 panel.destroy(); 599 panel.destroy();
590 // Panel might be used by other instances, just hide them.(#4552) 600 // Panel might be used by other instances, just hide them.(http://dev.ckeditor.com/ticket/4552)
591 else 601 else
592 panel.element.hide(); 602 panel.element.hide();
593 } 603 }
diff --git a/sources/plugins/font/lang/es-mx.js b/sources/plugins/font/lang/es-mx.js
new file mode 100644
index 0000000..5d4cdcf
--- /dev/null
+++ b/sources/plugins/font/lang/es-mx.js
@@ -0,0 +1,14 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'font', 'es-mx', {
6 fontSize: {
7 label: 'Tamaño',
8 voiceLabel: 'Tamaño de letra',
9 panelTitle: 'Tamaño de letra'
10 },
11 label: 'Letra',
12 panelTitle: 'Nombre de letra',
13 voiceLabel: 'Letra'
14} );
diff --git a/sources/plugins/font/lang/hr.js b/sources/plugins/font/lang/hr.js
index 0313aa3..669169c 100644
--- a/sources/plugins/font/lang/hr.js
+++ b/sources/plugins/font/lang/hr.js
@@ -9,6 +9,6 @@ CKEDITOR.plugins.setLang( 'font', 'hr', {
9 panelTitle: 'Veličina' 9 panelTitle: 'Veličina'
10 }, 10 },
11 label: 'Font', 11 label: 'Font',
12 panelTitle: 'Font', 12 panelTitle: 'Naziv fonta',
13 voiceLabel: 'Font' 13 voiceLabel: 'Font'
14} ); 14} );
diff --git a/sources/plugins/font/plugin.js b/sources/plugins/font/plugin.js
index 8794d89..fe5f47e 100644
--- a/sources/plugins/font/plugin.js
+++ b/sources/plugins/font/plugin.js
@@ -104,8 +104,8 @@
104 var previousValue = this.getValue(), 104 var previousValue = this.getValue(),
105 style = styles[ value ]; 105 style = styles[ value ];
106 106
107 // When applying one style over another, first remove the previous one (#12403). 107 // When applying one style over another, first remove the previous one (http://dev.ckeditor.com/ticket/12403).
108 // NOTE: This is only a temporary fix. It will be moved to the styles system (#12687). 108 // NOTE: This is only a temporary fix. It will be moved to the styles system (http://dev.ckeditor.com/ticket/12687).
109 if ( previousValue && value != previousValue ) { 109 if ( previousValue && value != previousValue ) {
110 var previousStyle = styles[ previousValue ], 110 var previousStyle = styles[ previousValue ],
111 range = editor.getSelection().getRanges()[ 0 ]; 111 range = editor.getSelection().getRanges()[ 0 ];
@@ -223,7 +223,7 @@
223 CKEDITOR.plugins.add( 'font', { 223 CKEDITOR.plugins.add( 'font', {
224 requires: 'richcombo', 224 requires: 'richcombo',
225 // jscs:disable maximumLineLength 225 // jscs:disable maximumLineLength
226 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% 226 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
227 // jscs:enable maximumLineLength 227 // jscs:enable maximumLineLength
228 init: function( editor ) { 228 init: function( editor ) {
229 var config = editor.config; 229 var config = editor.config;
diff --git a/sources/plugins/format/lang/es-mx.js b/sources/plugins/format/lang/es-mx.js
new file mode 100644
index 0000000..d311012
--- /dev/null
+++ b/sources/plugins/format/lang/es-mx.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-mx', {
6 label: 'Formato',
7 panelTitle: 'Formato de párrafo',
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: 'Formateado'
18} );
diff --git a/sources/plugins/format/lang/hr.js b/sources/plugins/format/lang/hr.js
index 2d6ec21..fbafb0e 100644
--- a/sources/plugins/format/lang/hr.js
+++ b/sources/plugins/format/lang/hr.js
@@ -4,15 +4,15 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
4*/ 4*/
5CKEDITOR.plugins.setLang( 'format', 'hr', { 5CKEDITOR.plugins.setLang( 'format', 'hr', {
6 label: 'Format', 6 label: 'Format',
7 panelTitle: 'Format', 7 panelTitle: 'Format paragrafa',
8 tag_address: 'Address', 8 tag_address: 'Adresa',
9 tag_div: 'Normal (DIV)', 9 tag_div: 'Normalno (DIV)',
10 tag_h1: 'Heading 1', 10 tag_h1: 'Naslov 1',
11 tag_h2: 'Heading 2', 11 tag_h2: 'Naslov 2',
12 tag_h3: 'Heading 3', 12 tag_h3: 'Naslov 3',
13 tag_h4: 'Heading 4', 13 tag_h4: 'Naslov 4',
14 tag_h5: 'Heading 5', 14 tag_h5: 'Naslov 5',
15 tag_h6: 'Heading 6', 15 tag_h6: 'Naslov 6',
16 tag_p: 'Normal', 16 tag_p: 'Normalno',
17 tag_pre: 'Formatirano' 17 tag_pre: 'Formatirano'
18} ); 18} );
diff --git a/sources/plugins/format/plugin.js b/sources/plugins/format/plugin.js
index 826cbcf..54d43ca 100644
--- a/sources/plugins/format/plugin.js
+++ b/sources/plugins/format/plugin.js
@@ -6,7 +6,7 @@
6CKEDITOR.plugins.add( 'format', { 6CKEDITOR.plugins.add( 'format', {
7 requires: 'richcombo', 7 requires: 'richcombo',
8 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
10 // jscs:enable maximumLineLength 10 // jscs:enable maximumLineLength
11 init: function( editor ) { 11 init: function( editor ) {
12 if ( editor.blockless ) 12 if ( editor.blockless )
@@ -69,7 +69,7 @@ CKEDITOR.plugins.add( 'format', {
69 69
70 editor[ style.checkActive( elementPath, editor ) ? 'removeStyle' : 'applyStyle' ]( style ); 70 editor[ style.checkActive( elementPath, editor ) ? 'removeStyle' : 'applyStyle' ]( style );
71 71
72 // Save the undo snapshot after all changes are affected. (#4899) 72 // Save the undo snapshot after all changes are affected. (http://dev.ckeditor.com/ticket/4899)
73 setTimeout( function() { 73 setTimeout( function() {
74 editor.fire( 'saveSnapshot' ); 74 editor.fire( 'saveSnapshot' );
75 }, 0 ); 75 }, 0 );
diff --git a/sources/plugins/horizontalrule/lang/es-mx.js b/sources/plugins/horizontalrule/lang/es-mx.js
new file mode 100644
index 0000000..9c389cc
--- /dev/null
+++ b/sources/plugins/horizontalrule/lang/es-mx.js
@@ -0,0 +1,7 @@
1/*
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-mx', {
6 toolbar: 'Insertar una línea horizontal'
7} );
diff --git a/sources/plugins/horizontalrule/plugin.js b/sources/plugins/horizontalrule/plugin.js
index 6e52c31..6f2186c 100644
--- a/sources/plugins/horizontalrule/plugin.js
+++ b/sources/plugins/horizontalrule/plugin.js
@@ -24,7 +24,7 @@
24 // Register a plugin named "horizontalrule". 24 // Register a plugin named "horizontalrule".
25 CKEDITOR.plugins.add( pluginName, { 25 CKEDITOR.plugins.add( pluginName, {
26 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
28 // jscs:enable maximumLineLength 28 // jscs:enable maximumLineLength
29 icons: 'horizontalrule', // %REMOVE_LINE_CORE% 29 icons: 'horizontalrule', // %REMOVE_LINE_CORE%
30 hidpi: true, // %REMOVE_LINE_CORE% 30 hidpi: true, // %REMOVE_LINE_CORE%
diff --git a/sources/plugins/html5audio/dialogs/html5audio.js b/sources/plugins/html5audio/dialogs/html5audio.js
index 0ab0d7d..47de947 100644
--- a/sources/plugins/html5audio/dialogs/html5audio.js
+++ b/sources/plugins/html5audio/dialogs/html5audio.js
@@ -109,6 +109,24 @@
109 commit: function( widget ) { 109 commit: function( widget ) {
110 widget.setData( 'autoplay', this.getValue() ); 110 widget.setData( 'autoplay', this.getValue() );
111 } 111 }
112 },
113 {
114 type: 'radio',
115 id: 'allowdownload',
116 label: editor.lang.html5audio.allowdownload,
117 items: [
118 [editor.lang.html5audio.yes, 'yes'],
119 [editor.lang.html5audio.no, 'no']
120 ],
121 'default': 'no',
122 setup: function( widget ) {
123 if ( widget.data.allowdownload ) {
124 this.setValue(widget.data.allowdownload);
125 }
126 },
127 commit: function( widget ) {
128 widget.setData( 'allowdownload', this.getValue() );
129 }
112 } ] 130 } ]
113 } ] 131 } ]
114 } ] 132 } ]
diff --git a/sources/plugins/html5audio/lang/de.js b/sources/plugins/html5audio/lang/de.js
index e084a60..e779745 100644
--- a/sources/plugins/html5audio/lang/de.js
+++ b/sources/plugins/html5audio/lang/de.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Zum Server senden', 8 btnUpload: 'Zum Server senden',
9 advanced: 'Erweitert', 9 advanced: 'Erweitert',
10 autoplay: 'Autoplay?', 10 autoplay: 'Autoplay?',
11 allowdownload: 'Download zulassen?',
11 yes: 'Ja', 12 yes: 'Ja',
12 no: 'Nein' 13 no: 'Nein'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/el.js b/sources/plugins/html5audio/lang/el.js
new file mode 100644
index 0000000..a7d2f84
--- /dev/null
+++ b/sources/plugins/html5audio/lang/el.js
@@ -0,0 +1,14 @@
1CKEDITOR.plugins.setLang( 'html5audio', 'el', {
2 button: 'Προσθέστε HTML5 ήχο',
3 title: 'HTML5 ήχος',
4 infoLabel: 'Πληροφορίες ήχου',
5 urlMissing: 'Η πηγή URL ήχου απουσιάζει.',
6 audioProperties: 'Ιδιότητες ήχου',
7 upload: 'Upload',
8 btnUpload: 'Αποστολή στον διακομιστή',
9 advanced: 'Προχωρημένα',
10 autoplay: 'Αυτόματη αναπαραγωγή;',
11 allowdownload: 'Επιτρέψτε τη λήψη;',
12 yes: 'Ναι',
13 no: 'Όχι'
14} );
diff --git a/sources/plugins/html5audio/lang/en.js b/sources/plugins/html5audio/lang/en.js
index fffce1e..63e8c40 100644
--- a/sources/plugins/html5audio/lang/en.js
+++ b/sources/plugins/html5audio/lang/en.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Send it to the server', 8 btnUpload: 'Send it to the server',
9 advanced: 'Advanced', 9 advanced: 'Advanced',
10 autoplay: 'Autoplay?', 10 autoplay: 'Autoplay?',
11 allowdownload: 'Allow download?',
11 yes: 'Yes', 12 yes: 'Yes',
12 no: 'No' 13 no: 'No'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/es.js b/sources/plugins/html5audio/lang/es.js
index f1aec8e..a9dd960 100644
--- a/sources/plugins/html5audio/lang/es.js
+++ b/sources/plugins/html5audio/lang/es.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Enviar al servidor', 8 btnUpload: 'Enviar al servidor',
9 advanced: 'Avanzado', 9 advanced: 'Avanzado',
10 autoplay: '¿Reproducir automáticamente?', 10 autoplay: '¿Reproducir automáticamente?',
11 allowdownload: '¿Permitir la descarga?',
11 yes: 'Si', 12 yes: 'Si',
12 no: 'No' 13 no: 'No'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/eu.js b/sources/plugins/html5audio/lang/eu.js
index 9275d88..5a7d103 100644
--- a/sources/plugins/html5audio/lang/eu.js
+++ b/sources/plugins/html5audio/lang/eu.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Bidali zerbitzarira', 8 btnUpload: 'Bidali zerbitzarira',
9 advanced: 'Aurreratua', 9 advanced: 'Aurreratua',
10 autoplay: 'Automatikoki erreproduzitu?', 10 autoplay: 'Automatikoki erreproduzitu?',
11 allowdownload: 'Baimendu deskargatzea?',
11 yes: 'Bai', 12 yes: 'Bai',
12 no: 'Ez' 13 no: 'Ez'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/fr.js b/sources/plugins/html5audio/lang/fr.js
index b9fa4af..51103f2 100644
--- a/sources/plugins/html5audio/lang/fr.js
+++ b/sources/plugins/html5audio/lang/fr.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Envoyer vers le serveur', 8 btnUpload: 'Envoyer vers le serveur',
9 advanced: 'Avancé', 9 advanced: 'Avancé',
10 autoplay: 'Jouer automatiquement ?', 10 autoplay: 'Jouer automatiquement ?',
11 allowdownload: 'Autoriser le téléchargement?',
11 yes: 'Oui', 12 yes: 'Oui',
12 no: 'Non' 13 no: 'Non'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/ru.js b/sources/plugins/html5audio/lang/ru.js
index 94be193..7060753 100644
--- a/sources/plugins/html5audio/lang/ru.js
+++ b/sources/plugins/html5audio/lang/ru.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Загрузить на сервер', 8 btnUpload: 'Загрузить на сервер',
9 advanced: 'Дополнительно', 9 advanced: 'Дополнительно',
10 autoplay: 'Автовоспроизведение', 10 autoplay: 'Автовоспроизведение',
11 allowdownload: 'Разрешить загрузку',
11 yes: 'Да', 12 yes: 'Да',
12 no: 'Нет' 13 no: 'Нет'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/uk.js b/sources/plugins/html5audio/lang/uk.js
index 6e050f1..3d10fd0 100644
--- a/sources/plugins/html5audio/lang/uk.js
+++ b/sources/plugins/html5audio/lang/uk.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Відвантажити на сервер', 8 btnUpload: 'Відвантажити на сервер',
9 advanced: 'Додатково', 9 advanced: 'Додатково',
10 autoplay: 'Автовідтворення?', 10 autoplay: 'Автовідтворення?',
11 allowdownload: 'Дозволити завантажити?',
11 yes: 'Так', 12 yes: 'Так',
12 no: 'Ні' 13 no: 'Ні'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/uz.js b/sources/plugins/html5audio/lang/uz.js
index 8827b53..c21b2c6 100644
--- a/sources/plugins/html5audio/lang/uz.js
+++ b/sources/plugins/html5audio/lang/uz.js
@@ -8,6 +8,7 @@
8 btnUpload: 'Serverga jo‘natish', 8 btnUpload: 'Serverga jo‘natish',
9 advanced: 'Kengaytrilgan', 9 advanced: 'Kengaytrilgan',
10 autoplay: 'Avtoijro?', 10 autoplay: 'Avtoijro?',
11 allowdownload: 'Yuklab olish uchun ruxsat berilsinmi?',
11 yes: 'Ha', 12 yes: 'Ha',
12 no: 'Yo‘q' 13 no: 'Yo‘q'
13} ); 14} );
diff --git a/sources/plugins/html5audio/lang/zh-cn.js b/sources/plugins/html5audio/lang/zh-cn.js
new file mode 100644
index 0000000..018ffb0
--- /dev/null
+++ b/sources/plugins/html5audio/lang/zh-cn.js
@@ -0,0 +1,14 @@
1CKEDITOR.plugins.setLang( 'html5audio', 'zh-cn', {
2 button: '插入HTML5音频',
3 title: 'HTML5 音频',
4 infoLabel: '音频信息',
5 urlMissing: '音频URL',
6 audioProperties: '音频属性',
7 upload: '上传',
8 btnUpload: '上传到服务器',
9 advanced: '高级',
10 autoplay: '自动播放?',
11 allowdownload: '允许下载?',
12 yes: '是',
13 no: '否'
14} );
diff --git a/sources/plugins/html5audio/plugin.js b/sources/plugins/html5audio/plugin.js
index 86bcfbd..7d0d886 100644
--- a/sources/plugins/html5audio/plugin.js
+++ b/sources/plugins/html5audio/plugin.js
@@ -1,6 +1,6 @@
1CKEDITOR.plugins.add( 'html5audio', { 1CKEDITOR.plugins.add( 'html5audio', {
2 requires: 'widget', 2 requires: 'widget',
3 lang: 'de,en,eu,es,fr,ru,uk,uz', 3 lang: 'de,el,en,eu,es,fr,ru,uk,uz,zh-cn',
4 icons: 'html5audio', 4 icons: 'html5audio',
5 init: function( editor ) { 5 init: function( editor ) {
6 editor.widgets.add( 'html5audio', { 6 editor.widgets.add( 'html5audio', {
@@ -13,7 +13,7 @@
13 * - div-s with text-align,float,margin-left,margin-right inline style rules and required ckeditor-html5-audio class. 13 * - div-s with text-align,float,margin-left,margin-right inline style rules and required ckeditor-html5-audio class.
14 * - audio tags with src and controls attributes. 14 * - audio tags with src and controls attributes.
15 */ 15 */
16 allowedContent: 'div(!ckeditor-html5-audio){text-align,float,margin-left,margin-right}; audio[src,controls,autoplay];', 16 allowedContent: 'div(!ckeditor-html5-audio){text-align,float,margin-left,margin-right}; audio[src,controls,controlslist,autoplay];',
17 requiredContent: 'div(ckeditor-html5-audio); audio[src,controls];', 17 requiredContent: 'div(ckeditor-html5-audio); audio[src,controls];',
18 upcast: function( element ) { 18 upcast: function( element ) {
19 return element.name === 'div' && element.hasClass( 'ckeditor-html5-audio' ); 19 return element.name === 'div' && element.hasClass( 'ckeditor-html5-audio' );
@@ -29,6 +29,7 @@
29 // get it's attributes. 29 // get it's attributes.
30 src = this.element.getChild( 0 ).getAttribute( 'src' ); 30 src = this.element.getChild( 0 ).getAttribute( 'src' );
31 autoplay = this.element.getChild( 0 ).getAttribute( 'autoplay' ); 31 autoplay = this.element.getChild( 0 ).getAttribute( 'autoplay' );
32 allowdownload = !this.element.getChild( 0 ).getAttribute( 'controlslist' );
32 } 33 }
33 34
34 if ( src ) { 35 if ( src ) {
@@ -43,6 +44,10 @@
43 if ( autoplay ) { 44 if ( autoplay ) {
44 this.setData( 'autoplay', 'yes' ); 45 this.setData( 'autoplay', 'yes' );
45 } 46 }
47
48 if ( allowdownload ) {
49 this.setData( 'allowdownload', 'yes' );
50 }
46 } 51 }
47 }, 52 },
48 data: function() { 53 data: function() {
@@ -84,6 +89,11 @@
84 } else { 89 } else {
85 this.element.getChild( 0 ).removeAttribute( 'autoplay' ); 90 this.element.getChild( 0 ).removeAttribute( 'autoplay' );
86 } 91 }
92 if ( this.data.allowdownload === 'yes' ) {
93 this.element.getChild( 0 ).removeAttribute( 'controlslist' );
94 } else {
95 this.element.getChild( 0 ).setAttribute( 'controlslist', 'nodownload' );
96 }
87 } 97 }
88 } 98 }
89 } ); 99 } );
diff --git a/sources/plugins/html5video/dialogs/html5video.js b/sources/plugins/html5video/dialogs/html5video.js
index 99f89c3..76799e7 100644
--- a/sources/plugins/html5video/dialogs/html5video.js
+++ b/sources/plugins/html5video/dialogs/html5video.js
@@ -41,13 +41,23 @@
41 } ] 41 } ]
42 }, 42 },
43 { 43 {
44 type: 'checkbox',
45 id: 'responsive',
46 label: editor.lang.html5video.responsive,
47 setup: function( widget ) {
48 this.setValue( widget.data.responsive );
49 },
50 commit: function( widget ) {
51 widget.setData( 'responsive', this.getValue()?'true':'' );
52 }
53 },
54 {
44 type: 'hbox', 55 type: 'hbox',
45 id: 'size', 56 id: 'size',
46 children: [ { 57 children: [ {
47 type: 'text', 58 type: 'text',
48 id: 'width', 59 id: 'width',
49 label: editor.lang.common.width, 60 label: editor.lang.common.width,
50 'default': 400,
51 setup: function( widget ) { 61 setup: function( widget ) {
52 if ( widget.data.width ) { 62 if ( widget.data.width ) {
53 this.setValue( widget.data.width ); 63 this.setValue( widget.data.width );
@@ -61,7 +71,6 @@
61 type: 'text', 71 type: 'text',
62 id: 'height', 72 id: 'height',
63 label: editor.lang.common.height, 73 label: editor.lang.common.height,
64 'default': 300,
65 setup: function( widget ) { 74 setup: function( widget ) {
66 if ( widget.data.height ) { 75 if ( widget.data.height ) {
67 this.setValue( widget.data.height ); 76 this.setValue( widget.data.height );
diff --git a/sources/plugins/html5video/lang/en.js b/sources/plugins/html5video/lang/en.js
index ebac6e5..40eae12 100644
--- a/sources/plugins/html5video/lang/en.js
+++ b/sources/plugins/html5video/lang/en.js
@@ -10,5 +10,6 @@
10 advanced: 'Advanced', 10 advanced: 'Advanced',
11 autoplay: 'Autoplay?', 11 autoplay: 'Autoplay?',
12 yes: 'Yes', 12 yes: 'Yes',
13 no: 'No' 13 no: 'No',
14 responsive: 'Responsive width'
14} ); 15} );
diff --git a/sources/plugins/html5video/lang/ru.js b/sources/plugins/html5video/lang/ru.js
index 5eeeba6..cd5a195 100644
--- a/sources/plugins/html5video/lang/ru.js
+++ b/sources/plugins/html5video/lang/ru.js
@@ -10,5 +10,6 @@
10 advanced: 'Дополнительно', 10 advanced: 'Дополнительно',
11 autoplay: 'Автовоспроизведение', 11 autoplay: 'Автовоспроизведение',
12 yes: 'Да', 12 yes: 'Да',
13 no: 'Нет' 13 no: 'Нет',
14 responsive: 'Адаптивная ширина'
14} ); 15} );
diff --git a/sources/plugins/html5video/plugin.js b/sources/plugins/html5video/plugin.js
index 1bfff7f..bf51285 100644
--- a/sources/plugins/html5video/plugin.js
+++ b/sources/plugins/html5video/plugin.js
@@ -9,9 +9,9 @@
9 /* 9 /*
10 * Allowed content rules (http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules): 10 * Allowed content rules (http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules):
11 * - div-s with text-align,float,margin-left,margin-right inline style rules and required ckeditor-html5-video class. 11 * - div-s with text-align,float,margin-left,margin-right inline style rules and required ckeditor-html5-video class.
12 * - video tags with src and controls attributes. 12 * - video tags with src, controls, width and height attributes.
13 */ 13 */
14 allowedContent: 'div(!ckeditor-html5-video){text-align,float,margin-left,margin-right}; video[src,controls,autoplay];', 14 allowedContent: 'div[data-responsive](!ckeditor-html5-video){text-align,float,margin-left,margin-right}; video[src,controls,autoplay,width, height]{max-width,height};',
15 requiredContent: 'div(ckeditor-html5-video); video[src,controls];', 15 requiredContent: 'div(ckeditor-html5-video); video[src,controls];',
16 upcast: function( element ) { 16 upcast: function( element ) {
17 return element.name === 'div' && element.hasClass( 'ckeditor-html5-video' ); 17 return element.name === 'div' && element.hasClass( 'ckeditor-html5-video' );
@@ -32,6 +32,7 @@
32 width = this.element.getChild( 0 ).getAttribute( 'width' ); 32 width = this.element.getChild( 0 ).getAttribute( 'width' );
33 height = this.element.getChild( 0 ).getAttribute( 'height' ); 33 height = this.element.getChild( 0 ).getAttribute( 'height' );
34 autoplay = this.element.getChild( 0 ).getAttribute( 'autoplay' ); 34 autoplay = this.element.getChild( 0 ).getAttribute( 'autoplay' );
35 responsive = this.element.getAttribute( 'data-responsive' );
35 } 36 }
36 37
37 if ( src ) { 38 if ( src ) {
@@ -45,19 +46,19 @@
45 46
46 if ( width ) { 47 if ( width ) {
47 this.setData( 'width', width ); 48 this.setData( 'width', width );
48 } else {
49 this.setData( 'width', '400' );
50 } 49 }
51 50
52 if ( height ) { 51 if ( height ) {
53 this.setData( 'height', height ); 52 this.setData( 'height', height );
54 } else {
55 this.setData( 'height', '300' );
56 } 53 }
57 54
58 if ( autoplay ) { 55 if ( autoplay ) {
59 this.setData( 'autoplay', 'yes' ); 56 this.setData( 'autoplay', 'yes' );
60 } 57 }
58
59 if ( responsive ) {
60 this.setData( 'responsive', responsive );
61 }
61 } 62 }
62 }, 63 },
63 data: function() { 64 data: function() {
@@ -72,9 +73,18 @@
72 // Append it to the container of the plugin. 73 // Append it to the container of the plugin.
73 this.element.append( videoElement ); 74 this.element.append( videoElement );
74 } 75 }
75 this.element.getChild( 0 ).setAttribute( 'src', this.data.src ) 76 this.element.getChild( 0 ).setAttribute( 'src', this.data.src );
76 .setAttribute( 'width', this.data.width ) 77 if (this.data.width) this.element.getChild( 0 ).setAttribute( 'width', this.data.width );
77 .setAttribute( 'height', this.data.height ); 78 if (this.data.height) this.element.getChild( 0 ).setAttribute( 'height', this.data.height );
79
80 if ( this.data.responsive ) {
81 this.element.setAttribute("data-responsive", this.data.responsive);
82 this.element.getChild( 0 ).setStyle( 'max-width', '100%' );
83 this.element.getChild( 0 ).setStyle( 'height', 'auto' );
84 } else {
85 this.element.getChild( 0 ).removeStyle( 'max-width' );
86 this.element.getChild( 0 ).removeStyle( 'height' );
87 }
78 } 88 }
79 89
80 this.element.removeStyle( 'float' ); 90 this.element.removeStyle( 'float' );
diff --git a/sources/plugins/htmlwriter/plugin.js b/sources/plugins/htmlwriter/plugin.js
index b6d2716..61d6ac6 100644
--- a/sources/plugins/htmlwriter/plugin.js
+++ b/sources/plugins/htmlwriter/plugin.js
@@ -69,7 +69,7 @@ CKEDITOR.htmlWriter = CKEDITOR.tools.createClass( {
69 69
70 this._.indent = 0; 70 this._.indent = 0;
71 this._.indentation = ''; 71 this._.indentation = '';
72 // Indicate preformatted block context status. (#5789) 72 // Indicate preformatted block context status. (http://dev.ckeditor.com/ticket/5789)
73 this._.inPre = 0; 73 this._.inPre = 0;
74 this._.rules = {}; 74 this._.rules = {};
75 75
@@ -180,7 +180,7 @@ CKEDITOR.htmlWriter = CKEDITOR.tools.createClass( {
180 180
181 if ( typeof attValue == 'string' ) { 181 if ( typeof attValue == 'string' ) {
182 this.forceSimpleAmpersand && ( attValue = attValue.replace( /&amp;/g, '&' ) ); 182 this.forceSimpleAmpersand && ( attValue = attValue.replace( /&amp;/g, '&' ) );
183 // Browsers don't always escape special character in attribute values. (#4683, #4719). 183 // Browsers don't always escape special character in attribute values. (http://dev.ckeditor.com/ticket/4683, http://dev.ckeditor.com/ticket/4719).
184 attValue = CKEDITOR.tools.htmlEncodeAttr( attValue ); 184 attValue = CKEDITOR.tools.htmlEncodeAttr( attValue );
185 } 185 }
186 186
diff --git a/sources/plugins/iframe/dialogs/iframe.js b/sources/plugins/iframe/dialogs/iframe.js
index bb39bdf..22c24f7 100644
--- a/sources/plugins/iframe/dialogs/iframe.js
+++ b/sources/plugins/iframe/dialogs/iframe.js
@@ -65,7 +65,7 @@
65 65
66 // A subset of the specified attributes/styles 66 // A subset of the specified attributes/styles
67 // should also be applied on the fake element to 67 // should also be applied on the fake element to
68 // have better visual effect. (#5240) 68 // have better visual effect. (http://dev.ckeditor.com/ticket/5240)
69 var extraStyles = {}, 69 var extraStyles = {},
70 extraAttributes = {}; 70 extraAttributes = {};
71 this.commitContent( iframeNode, extraStyles, extraAttributes ); 71 this.commitContent( iframeNode, extraStyles, extraAttributes );
diff --git a/sources/plugins/iframe/lang/es-mx.js b/sources/plugins/iframe/lang/es-mx.js
new file mode 100644
index 0000000..767147e
--- /dev/null
+++ b/sources/plugins/iframe/lang/es-mx.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-mx', {
6 border: 'Mostrar el borde del marco',
7 noUrl: 'Ingresa la URL del iframe',
8 scrolling: 'Habilitar la barra de desplazamiento',
9 title: 'Propiedades del IFrame',
10 toolbar: 'Iframe'
11} );
diff --git a/sources/plugins/iframe/lang/hr.js b/sources/plugins/iframe/lang/hr.js
index 986e000..9f289a7 100644
--- a/sources/plugins/iframe/lang/hr.js
+++ b/sources/plugins/iframe/lang/hr.js
@@ -4,7 +4,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
4*/ 4*/
5CKEDITOR.plugins.setLang( 'iframe', 'hr', { 5CKEDITOR.plugins.setLang( 'iframe', 'hr', {
6 border: 'Prikaži okvir IFrame-a', 6 border: 'Prikaži okvir IFrame-a',
7 noUrl: 'Unesite URL iframe-a', 7 noUrl: 'Unesite URL IFrame-a',
8 scrolling: 'Omogući trake za skrolanje', 8 scrolling: 'Omogući trake za skrolanje',
9 title: 'IFrame svojstva', 9 title: 'IFrame svojstva',
10 toolbar: 'IFrame' 10 toolbar: 'IFrame'
diff --git a/sources/plugins/iframe/plugin.js b/sources/plugins/iframe/plugin.js
index 52c816a..7c479c0 100644
--- a/sources/plugins/iframe/plugin.js
+++ b/sources/plugins/iframe/plugin.js
@@ -7,7 +7,7 @@
7 CKEDITOR.plugins.add( 'iframe', { 7 CKEDITOR.plugins.add( 'iframe', {
8 requires: 'dialog,fakeobjects', 8 requires: 'dialog,fakeobjects',
9 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
11 // jscs:enable maximumLineLength 11 // jscs:enable maximumLineLength
12 icons: 'iframe', // %REMOVE_LINE_CORE% 12 icons: 'iframe', // %REMOVE_LINE_CORE%
13 hidpi: true, // %REMOVE_LINE_CORE% 13 hidpi: true, // %REMOVE_LINE_CORE%
diff --git a/sources/plugins/image/dialogs/image.js b/sources/plugins/image/dialogs/image.js
index 7d7537a..5302a7c 100644
--- a/sources/plugins/image/dialogs/image.js
+++ b/sources/plugins/image/dialogs/image.js
@@ -107,7 +107,7 @@
107 107
108 var oImageOriginal = dialog.originalElement; 108 var oImageOriginal = dialog.originalElement;
109 109
110 // Dialog may already closed. (#5505) 110 // Dialog may already closed. (http://dev.ckeditor.com/ticket/5505)
111 if ( !oImageOriginal ) 111 if ( !oImageOriginal )
112 return null; 112 return null;
113 113
@@ -233,7 +233,7 @@
233 this.firstLoad = false; 233 this.firstLoad = false;
234 this.dontResetSize = false; 234 this.dontResetSize = false;
235 235
236 // Possible fix for #12818. 236 // Possible fix for http://dev.ckeditor.com/ticket/12818.
237 updatePreview( this ); 237 updatePreview( this );
238 }; 238 };
239 239
@@ -310,7 +310,7 @@
310 this.linkEditMode = true; 310 this.linkEditMode = true;
311 311
312 // If there is an existing link, by default keep it (true). 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) 313 // It will be removed if certain conditions are met and Link tab is enabled. (http://dev.ckeditor.com/ticket/13351)
314 this.addLink = true; 314 this.addLink = true;
315 315
316 // Look for Image element. 316 // Look for Image element.
@@ -542,7 +542,7 @@
542 this.getDialog().dontResetSize = true; 542 this.getDialog().dontResetSize = true;
543 543
544 field.setValue( url ); // And call this.onChange() 544 field.setValue( url ); // And call this.onChange()
545 // Manually set the initial value.(#4191) 545 // Manually set the initial value.(http://dev.ckeditor.com/ticket/4191)
546 field.setInitValue(); 546 field.setInitValue();
547 } 547 }
548 }, 548 },
diff --git a/sources/plugins/image/lang/es-mx.js b/sources/plugins/image/lang/es-mx.js
new file mode 100644
index 0000000..dc9b24c
--- /dev/null
+++ b/sources/plugins/image/lang/es-mx.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-mx', {
6 alt: 'Texto alternativo',
7 border: 'Borde',
8 btnUpload: 'Enviar al servidor',
9 button2Img: '¿Desea transformar el botón de imagen seleccionado en una imagen simple?',
10 hSpace: 'Espacio horizontal',
11 img2Button: '¿Desea transformar la imagen seleccionada en un botón de imagen?',
12 infoTab: 'Información de imagen',
13 linkTab: 'Enlace',
14 lockRatio: 'Bloquear aspecto',
15 menu: 'Propiedades de la imagen',
16 resetSize: 'Reiniciar tamaño',
17 title: 'Propiedades de la imagen',
18 titleButton: 'Propiedades del botón de imagen',
19 upload: 'Cargar',
20 urlMissing: 'Falta la URL de origen de la imagen.',
21 vSpace: 'Espacio vertical',
22 validateBorder: 'El borde debe ser un número entero.',
23 validateHSpace: 'El espacio horizontal debe ser un número entero.',
24 validateVSpace: 'El espacio vertical debe ser un número entero.'
25} );
diff --git a/sources/plugins/image/lang/hr.js b/sources/plugins/image/lang/hr.js
index 8c272eb..962533a 100644
--- a/sources/plugins/image/lang/hr.js
+++ b/sources/plugins/image/lang/hr.js
@@ -10,7 +10,7 @@ CKEDITOR.plugins.setLang( 'image', 'hr', {
10 hSpace: 'HSpace', 10 hSpace: 'HSpace',
11 img2Button: 'Želite li promijeniti odabranu sliku u gumb?', 11 img2Button: 'Želite li promijeniti odabranu sliku u gumb?',
12 infoTab: 'Info slike', 12 infoTab: 'Info slike',
13 linkTab: 'Link', 13 linkTab: 'Veza',
14 lockRatio: 'Zaključaj odnos', 14 lockRatio: 'Zaključaj odnos',
15 menu: 'Svojstva slika', 15 menu: 'Svojstva slika',
16 resetSize: 'Obriši veličinu', 16 resetSize: 'Obriši veličinu',
diff --git a/sources/plugins/image/lang/pt.js b/sources/plugins/image/lang/pt.js
index 2b8f50c..729c48e 100644
--- a/sources/plugins/image/lang/pt.js
+++ b/sources/plugins/image/lang/pt.js
@@ -6,9 +6,9 @@ CKEDITOR.plugins.setLang( 'image', 'pt', {
6 alt: 'Texto alternativo', 6 alt: 'Texto alternativo',
7 border: 'Limite', 7 border: 'Limite',
8 btnUpload: 'Enviar para o servidor', 8 btnUpload: 'Enviar para o servidor',
9 button2Img: 'Deseja transformar o botão com imagem selecionado em uma imagem?', 9 button2Img: 'Deseja transformar o botão com imagem selecionado numa imagem simples?',
10 hSpace: 'Esp. Horiz', 10 hSpace: 'Esp. Horiz',
11 img2Button: 'Deseja transformar a imagem selecionada em um botão com imagem?', 11 img2Button: 'Deseja transformar a imagem selecionada num botão com imagem?',
12 infoTab: 'Informação da imagem', 12 infoTab: 'Informação da imagem',
13 linkTab: 'Hiperligação', 13 linkTab: 'Hiperligação',
14 lockRatio: 'Proporcional', 14 lockRatio: 'Proporcional',
@@ -17,9 +17,9 @@ CKEDITOR.plugins.setLang( 'image', 'pt', {
17 title: 'Propriedades da imagem', 17 title: 'Propriedades da imagem',
18 titleButton: 'Propriedades do botão de imagem', 18 titleButton: 'Propriedades do botão de imagem',
19 upload: 'Carregar', 19 upload: 'Carregar',
20 urlMissing: 'O URL da fonte da imagem está em falta.', 20 urlMissing: 'O URL de origem da imagem está em falta.',
21 vSpace: 'Esp. Vert', 21 vSpace: 'Esp. Vert',
22 validateBorder: 'A borda tem de ser um numero.', 22 validateBorder: 'A borda tem de ser um número inteiro.',
23 validateHSpace: 'HSpace tem de ser um numero.', 23 validateHSpace: 'HSpace tem de ser um numero.',
24 validateVSpace: 'VSpace tem de ser um numero.' 24 validateVSpace: 'VSpace tem de ser um numero.'
25} ); 25} );
diff --git a/sources/plugins/image/plugin.js b/sources/plugins/image/plugin.js
index 1394510..507ce0a 100644
--- a/sources/plugins/image/plugin.js
+++ b/sources/plugins/image/plugin.js
@@ -12,13 +12,13 @@
12 CKEDITOR.plugins.add( 'image', { 12 CKEDITOR.plugins.add( 'image', {
13 requires: 'dialog', 13 requires: 'dialog',
14 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
16 // jscs:enable maximumLineLength 16 // jscs:enable maximumLineLength
17 icons: 'image', // %REMOVE_LINE_CORE% 17 icons: 'image', // %REMOVE_LINE_CORE%
18 hidpi: true, // %REMOVE_LINE_CORE% 18 hidpi: true, // %REMOVE_LINE_CORE%
19 init: function( editor ) { 19 init: function( editor ) {
20 // Abort when Image2 is to be loaded since both plugins 20 // Abort when Image2 is to be loaded since both plugins
21 // share the same button, command, etc. names (#11222). 21 // share the same button, command, etc. names (http://dev.ckeditor.com/ticket/11222).
22 if ( editor.plugins.image2 ) 22 if ( editor.plugins.image2 )
23 return; 23 return;
24 24
@@ -78,11 +78,11 @@
78 }, 78 },
79 afterInit: function( editor ) { 79 afterInit: function( editor ) {
80 // Abort when Image2 is to be loaded since both plugins 80 // Abort when Image2 is to be loaded since both plugins
81 // share the same button, command, etc. names (#11222). 81 // share the same button, command, etc. names (http://dev.ckeditor.com/ticket/11222).
82 if ( editor.plugins.image2 ) 82 if ( editor.plugins.image2 )
83 return; 83 return;
84 84
85 // Customize the behavior of the alignment commands. (#7430) 85 // Customize the behavior of the alignment commands. (http://dev.ckeditor.com/ticket/7430)
86 setupAlignCommand( 'left' ); 86 setupAlignCommand( 'left' );
87 setupAlignCommand( 'right' ); 87 setupAlignCommand( 'right' );
88 setupAlignCommand( 'center' ); 88 setupAlignCommand( 'center' );
diff --git a/sources/plugins/indent/lang/es-mx.js b/sources/plugins/indent/lang/es-mx.js
new file mode 100644
index 0000000..8a6e549
--- /dev/null
+++ b/sources/plugins/indent/lang/es-mx.js
@@ -0,0 +1,8 @@
1/*
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-mx', {
6 indent: 'Incrementar sangría',
7 outdent: 'Decrementar sangría'
8} );
diff --git a/sources/plugins/indent/plugin.js b/sources/plugins/indent/plugin.js
index 0e887cf..900e343 100644
--- a/sources/plugins/indent/plugin.js
+++ b/sources/plugins/indent/plugin.js
@@ -15,7 +15,7 @@
15 15
16 CKEDITOR.plugins.add( 'indent', { 16 CKEDITOR.plugins.add( 'indent', {
17 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
19 // jscs:enable maximumLineLength 19 // jscs:enable maximumLineLength
20 icons: 'indent,indent-rtl,outdent,outdent-rtl', // %REMOVE_LINE_CORE% 20 icons: 'indent,indent-rtl,outdent,outdent-rtl', // %REMOVE_LINE_CORE%
21 hidpi: true, // %REMOVE_LINE_CORE% 21 hidpi: true, // %REMOVE_LINE_CORE%
diff --git a/sources/plugins/indentlist/plugin.js b/sources/plugins/indentlist/plugin.js
index 15c661f..0ee30c0 100644
--- a/sources/plugins/indentlist/plugin.js
+++ b/sources/plugins/indentlist/plugin.js
@@ -35,17 +35,24 @@
35 // Indent and outdent lists with TAB/SHIFT+TAB key. Indenting can 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. 36 // be done for any list item that isn't the first child of the parent.
37 editor.on( 'key', function( evt ) { 37 editor.on( 'key', function( evt ) {
38 var path = editor.elementPath();
39
38 if ( editor.mode != 'wysiwyg' ) 40 if ( editor.mode != 'wysiwyg' )
39 return; 41 return;
40 42
41 if ( evt.data.keyCode == this.indentKey ) { 43 if ( evt.data.keyCode == this.indentKey ) {
42 var list = this.getContext( editor.elementPath() ); 44 // Prevent of getting context of empty path (#424)(https://dev.ckeditor.com/ticket/17028).
45 if ( !path ) {
46 return;
47 }
48
49 var list = this.getContext( path );
43 50
44 if ( list ) { 51 if ( list ) {
45 // Don't indent if in first list item of the parent. 52 // Don't indent if in first list item of the parent.
46 // Outdent, however, can always be done to collapse 53 // Outdent, however, can always be done to collapse
47 // the list into a paragraph (div). 54 // the list into a paragraph (div).
48 if ( this.isIndent && CKEDITOR.plugins.indentList.firstItemInPath( this.context, editor.elementPath(), list ) ) 55 if ( this.isIndent && CKEDITOR.plugins.indentList.firstItemInPath( this.context, path, list ) )
49 return; 56 return;
50 57
51 // Exec related global indentation command. Global 58 // Exec related global indentation command. Global
@@ -109,7 +116,8 @@
109 function indentList( editor ) { 116 function indentList( editor ) {
110 var that = this, 117 var that = this,
111 database = this.database, 118 database = this.database,
112 context = this.context; 119 context = this.context,
120 range;
113 121
114 function indent( listNode ) { 122 function indent( listNode ) {
115 // Our starting and ending points of the range might be inside some blocks under a list item... 123 // Our starting and ending points of the range might be inside some blocks under a list item...
@@ -164,7 +172,7 @@
164 172
165 for ( i = startItem.getCustomData( 'listarray_index' ); i <= lastItem.getCustomData( 'listarray_index' ); i++ ) { 173 for ( i = startItem.getCustomData( 'listarray_index' ); i <= lastItem.getCustomData( 'listarray_index' ); i++ ) {
166 listArray[ i ].indent += indentOffset; 174 listArray[ i ].indent += indentOffset;
167 // Make sure the newly created sublist get a brand-new element of the same type. (#5372) 175 // Make sure the newly created sublist get a brand-new element of the same type. (http://dev.ckeditor.com/ticket/5372)
168 if ( indentOffset > 0 ) { 176 if ( indentOffset > 0 ) {
169 var listRoot = listArray[ i ].parent; 177 var listRoot = listArray[ i ].parent;
170 listArray[ i ].parent = new CKEDITOR.dom.element( listRoot.getName(), listRoot.getDocument() ); 178 listArray[ i ].parent = new CKEDITOR.dom.element( listRoot.getName(), listRoot.getDocument() );
@@ -179,7 +187,7 @@
179 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, listNode.getDirection() ); 187 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, listNode.getDirection() );
180 188
181 // Avoid nested <li> after outdent even they're visually same, 189 // Avoid nested <li> after outdent even they're visually same,
182 // recording them for later refactoring.(#3982) 190 // recording them for later refactoring.(http://dev.ckeditor.com/ticket/3982)
183 if ( !that.isIndent ) { 191 if ( !that.isIndent ) {
184 var parentLiElement; 192 var parentLiElement;
185 if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) ) { 193 if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) ) {
@@ -207,7 +215,7 @@
207 // Nest preceding <ul>/<ol> inside current <li> if any. 215 // Nest preceding <ul>/<ol> inside current <li> if any.
208 while ( ( followingList = followingList.getNext() ) && followingList.is && followingList.getName() in context ) { 216 while ( ( followingList = followingList.getNext() ) && followingList.is && followingList.getName() in context ) {
209 // IE requires a filler NBSP for nested list inside empty list item, 217 // IE requires a filler NBSP for nested list inside empty list item,
210 // otherwise the list item will be inaccessiable. (#4476) 218 // otherwise the list item will be inaccessiable. (http://dev.ckeditor.com/ticket/4476)
211 if ( CKEDITOR.env.needsNbspFiller && !li.getFirst( neitherWhitespacesNorBookmark ) ) 219 if ( CKEDITOR.env.needsNbspFiller && !li.getFirst( neitherWhitespacesNorBookmark ) )
212 li.append( range.document.createText( '\u00a0' ) ); 220 li.append( range.document.createText( '\u00a0' ) );
213 221
@@ -226,14 +234,13 @@
226 234
227 var selection = editor.getSelection(), 235 var selection = editor.getSelection(),
228 ranges = selection && selection.getRanges(), 236 ranges = selection && selection.getRanges(),
229 iterator = ranges.createIterator(), 237 iterator = ranges.createIterator();
230 range;
231 238
232 while ( ( range = iterator.getNextRange() ) ) { 239 while ( ( range = iterator.getNextRange() ) ) {
233 var nearestListBlock = range.getCommonAncestor(); 240 var nearestListBlock = range.getCommonAncestor();
234 241
235 while ( nearestListBlock && !( nearestListBlock.type == CKEDITOR.NODE_ELEMENT && context[ nearestListBlock.getName() ] ) ) { 242 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) 243 // Avoid having plugin propagate to parent of editor in inline mode by canceling the indentation. (http://dev.ckeditor.com/ticket/12796)
237 if ( editor.editable().equals( nearestListBlock ) ) { 244 if ( editor.editable().equals( nearestListBlock ) ) {
238 nearestListBlock = false; 245 nearestListBlock = false;
239 break; 246 break;
@@ -248,7 +255,7 @@
248 range.setEndAt( nearestListBlock, CKEDITOR.POSITION_BEFORE_END ); 255 range.setEndAt( nearestListBlock, CKEDITOR.POSITION_BEFORE_END );
249 } 256 }
250 257
251 // Avoid having selection enclose the entire list. (#6138) 258 // Avoid having selection enclose the entire list. (http://dev.ckeditor.com/ticket/6138)
252 // [<ul><li>...</li></ul>] =><ul><li>[...]</li></ul> 259 // [<ul><li>...</li></ul>] =><ul><li>[...]</li></ul>
253 if ( !nearestListBlock ) { 260 if ( !nearestListBlock ) {
254 var selectedNode = range.getEnclosedNode(); 261 var selectedNode = range.getEnclosedNode();
diff --git a/sources/plugins/justify/lang/es-mx.js b/sources/plugins/justify/lang/es-mx.js
new file mode 100644
index 0000000..96443e0
--- /dev/null
+++ b/sources/plugins/justify/lang/es-mx.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-mx', {
6 block: 'Justificar',
7 center: 'Centrar',
8 left: 'Alinear a la izquierda',
9 right: 'Alinear a la derecha'
10} );
diff --git a/sources/plugins/justify/plugin.js b/sources/plugins/justify/plugin.js
index ce5cab3..21b9221 100644
--- a/sources/plugins/justify/plugin.js
+++ b/sources/plugins/justify/plugin.js
@@ -37,7 +37,6 @@
37 this.name = name; 37 this.name = name;
38 this.value = value; 38 this.value = value;
39 this.context = 'p'; 39 this.context = 'p';
40
41 var classes = editor.config.justifyClasses, 40 var classes = editor.config.justifyClasses,
42 blockTag = editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div'; 41 blockTag = editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div';
43 42
@@ -150,6 +149,17 @@
150 if ( block.isReadOnly() ) 149 if ( block.isReadOnly() )
151 continue; 150 continue;
152 151
152 // Check if style or class might be applied to currently processed element (#455).
153 var tag = block.getName(),
154 isAllowedTextAlign, isAllowedCssClass;
155
156 isAllowedTextAlign = editor.activeFilter.check( tag + '{text-align}' );
157 isAllowedCssClass = editor.activeFilter.check( tag + '(' + cssClassName + ')' );
158
159 if ( !isAllowedCssClass && !isAllowedTextAlign ) {
160 continue;
161 }
162
153 block.removeAttribute( 'align' ); 163 block.removeAttribute( 'align' );
154 block.removeStyle( 'text-align' ); 164 block.removeStyle( 'text-align' );
155 165
@@ -158,13 +168,13 @@
158 168
159 var apply = ( this.state == CKEDITOR.TRISTATE_OFF ) && ( !useComputedState || ( getAlignment( block, true ) != this.value ) ); 169 var apply = ( this.state == CKEDITOR.TRISTATE_OFF ) && ( !useComputedState || ( getAlignment( block, true ) != this.value ) );
160 170
161 if ( cssClassName ) { 171 if ( cssClassName && isAllowedCssClass ) {
162 // Append the desired class name. 172 // Append the desired class name.
163 if ( apply ) 173 if ( apply )
164 block.addClass( cssClassName ); 174 block.addClass( cssClassName );
165 else if ( !className ) 175 else if ( !className )
166 block.removeAttribute( 'class' ); 176 block.removeAttribute( 'class' );
167 } else if ( apply ) { 177 } else if ( apply && isAllowedTextAlign ) {
168 block.setStyle( 'text-align', this.value ); 178 block.setStyle( 'text-align', this.value );
169 } 179 }
170 } 180 }
@@ -177,15 +187,31 @@
177 }, 187 },
178 188
179 refresh: function( editor, path ) { 189 refresh: function( editor, path ) {
180 var firstBlock = path.block || path.blockLimit; 190 var firstBlock = path.block || path.blockLimit,
181 191 name = firstBlock.getName(),
182 this.setState( firstBlock.getName() != 'body' && getAlignment( firstBlock, this.editor.config.useComputedState ) == this.value ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF ); 192 isEditable = firstBlock.equals( editor.editable() ),
193 isStylable = this.cssClassName ? editor.activeFilter.check( name + '(' + this.cssClassName + ')' ) :
194 editor.activeFilter.check( name + '{text-align}' );
195
196 // #455
197 // 1. Check if we are directly in editbale. Justification should be always allowed, and not highlighted.
198 // Checking path.elements.length is required to filter out situation `body > ul` where ul is selected and path.blockLimit returns editable.
199 // 2. Check if current element can have applied specific class.
200 // 3. Check if current element can have applied text-align style.
201 if ( isEditable && path.elements.length === 1 ) {
202 this.setState( CKEDITOR.TRISTATE_OFF );
203 } else if ( !isEditable && isStylable ) {
204 // 2 & 3 in one condition.
205 this.setState( getAlignment( firstBlock, this.editor.config.useComputedState ) == this.value ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
206 } else {
207 this.setState( CKEDITOR.TRISTATE_DISABLED );
208 }
183 } 209 }
184 }; 210 };
185 211
186 CKEDITOR.plugins.add( 'justify', { 212 CKEDITOR.plugins.add( 'justify', {
187 // jscs:disable maximumLineLength 213 // 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% 214 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
189 // jscs:enable maximumLineLength 215 // jscs:enable maximumLineLength
190 icons: 'justifyblock,justifycenter,justifyleft,justifyright', // %REMOVE_LINE_CORE% 216 icons: 'justifyblock,justifycenter,justifyleft,justifyright', // %REMOVE_LINE_CORE%
191 hidpi: true, // %REMOVE_LINE_CORE% 217 hidpi: true, // %REMOVE_LINE_CORE%
@@ -225,7 +251,6 @@
225 toolbar: 'align,40' 251 toolbar: 'align,40'
226 } ); 252 } );
227 } 253 }
228
229 editor.on( 'dirChanged', onDirChanged ); 254 editor.on( 'dirChanged', onDirChanged );
230 } 255 }
231 } ); 256 } );
diff --git a/sources/plugins/lineutils/plugin.js b/sources/plugins/lineutils/plugin.js
index e0473ee..d84c5f3 100644
--- a/sources/plugins/lineutils/plugin.js
+++ b/sources/plugins/lineutils/plugin.js
@@ -379,7 +379,7 @@
379 continue; 379 continue;
380 } 380 }
381 381
382 // On IE8 element.getElementsByTagName returns comments... sic! (#13176) 382 // On IE8 element.getElementsByTagName returns comments... sic! (http://dev.ckeditor.com/ticket/13176)
383 if ( el.type != CKEDITOR.NODE_ELEMENT ) { 383 if ( el.type != CKEDITOR.NODE_ELEMENT ) {
384 continue; 384 continue;
385 } 385 }
@@ -840,7 +840,7 @@
840 840
841 // Let's calculate the vertical position of the line. 841 // Let's calculate the vertical position of the line.
842 if ( this.inline ) { 842 if ( this.inline ) {
843 // (#13155) 843 // (http://dev.ckeditor.com/ticket/13155)
844 styles.top = loc + this.winTopScroll.y - this.rect.relativeY; 844 styles.top = loc + this.winTopScroll.y - this.rect.relativeY;
845 } else { 845 } else {
846 styles.top = this.rect.top + this.winTopScroll.y + loc; 846 styles.top = this.rect.top + this.winTopScroll.y + loc;
@@ -853,7 +853,7 @@
853 853
854 // Now let's calculate the horizontal alignment (left and width). 854 // Now let's calculate the horizontal alignment (left and width).
855 if ( this.inline ) { 855 if ( this.inline ) {
856 // (#13155) 856 // (http://dev.ckeditor.com/ticket/13155)
857 styles.left = rel.elementRect.left - this.rect.relativeX; 857 styles.left = rel.elementRect.left - this.rect.relativeX;
858 } else { 858 } else {
859 if ( rel.elementRect.left > 0 ) 859 if ( rel.elementRect.left > 0 )
@@ -939,13 +939,13 @@
939 this.winTopScroll = this.winTop.getScrollPosition(); 939 this.winTopScroll = this.winTop.getScrollPosition();
940 this.winTopPane = this.winTop.getViewPaneSize(); 940 this.winTopPane = this.winTop.getViewPaneSize();
941 941
942 // (#13155) 942 // (http://dev.ckeditor.com/ticket/13155)
943 this.rect = this.getClientRect( this.inline ? this.editable : this.frame ); 943 this.rect = this.getClientRect( this.inline ? this.editable : this.frame );
944 }, 944 },
945 945
946 /** 946 /**
947 * Returns `boundingClientRect` of an element, shifted by the position 947 * Returns `boundingClientRect` of an element, shifted by the position
948 * of `container` when the container is not `static` (#13155). 948 * of `container` when the container is not `static` (http://dev.ckeditor.com/ticket/13155).
949 * 949 *
950 * See also: {@link CKEDITOR.dom.element#getClientRect}. 950 * See also: {@link CKEDITOR.dom.element#getClientRect}.
951 * 951 *
diff --git a/sources/plugins/link/dialogs/anchor.js b/sources/plugins/link/dialogs/anchor.js
index 2b32b71..04a4abe 100644
--- a/sources/plugins/link/dialogs/anchor.js
+++ b/sources/plugins/link/dialogs/anchor.js
@@ -18,6 +18,21 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
18 } ), 'cke_anchor', 'anchor' ); 18 } ), 'cke_anchor', 'anchor' );
19 } 19 }
20 20
21
22 function getSelectedAnchor( selection ) {
23 var range = selection.getRanges()[ 0 ],
24 element = selection.getSelectedElement();
25
26 // In case of table cell selection, we want to shrink selection from td to a element.
27 range.shrink( CKEDITOR.SHRINK_ELEMENT );
28 element = range.getEnclosedNode();
29
30 if ( element && element.type === CKEDITOR.NODE_ELEMENT &&
31 ( element.data( 'cke-real-element-type' ) === 'anchor' || element.is( 'a' ) ) ) {
32 return element;
33 }
34 }
35
21 return { 36 return {
22 title: editor.lang.link.anchor.title, 37 title: editor.lang.link.anchor.title,
23 minWidth: 300, 38 minWidth: 300,
@@ -35,9 +50,10 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
35 var newFake = createFakeAnchor( editor, attributes ); 50 var newFake = createFakeAnchor( editor, attributes );
36 newFake.replace( this._.selectedElement ); 51 newFake.replace( this._.selectedElement );
37 52
38 // Selecting fake element for IE. (#11377) 53 // Selecting fake element for IE. (http://dev.ckeditor.com/ticket/11377)
39 if ( CKEDITOR.env.ie ) 54 if ( CKEDITOR.env.ie ) {
40 editor.getSelection().selectElement( newFake ); 55 editor.getSelection().selectElement( newFake );
56 }
41 } else { 57 } else {
42 this._.selectedElement.setAttributes( attributes ); 58 this._.selectedElement.setAttributes( attributes );
43 } 59 }
@@ -56,7 +72,7 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
56 // Apply style. 72 // Apply style.
57 var style = new CKEDITOR.style( { element: 'a', attributes: attributes } ); 73 var style = new CKEDITOR.style( { element: 'a', attributes: attributes } );
58 style.type = CKEDITOR.STYLE_INLINE; 74 style.type = CKEDITOR.STYLE_INLINE;
59 editor.applyStyle( style ); 75 style.applyToRange( range );
60 } 76 }
61 } 77 }
62 }, 78 },
@@ -67,7 +83,7 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
67 83
68 onShow: function() { 84 onShow: function() {
69 var sel = editor.getSelection(), 85 var sel = editor.getSelection(),
70 fullySelected = sel.getSelectedElement(), 86 fullySelected = getSelectedAnchor( sel ),
71 fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ), 87 fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ),
72 linkElement = fakeSelected ? 88 linkElement = fakeSelected ?
73 CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) : 89 CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) :
@@ -77,8 +93,9 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
77 loadElements.call( this, linkElement ); 93 loadElements.call( this, linkElement );
78 !fakeSelected && sel.selectElement( linkElement ); 94 !fakeSelected && sel.selectElement( linkElement );
79 95
80 if ( fullySelected ) 96 if ( fullySelected ) {
81 this._.selectedElement = fullySelected; 97 this._.selectedElement = fullySelected;
98 }
82 } 99 }
83 100
84 this.getContentElement( 'info', 'txtName' ).focus(); 101 this.getContentElement( 'info', 'txtName' ).focus();
diff --git a/sources/plugins/link/dialogs/link.js b/sources/plugins/link/dialogs/link.js
index 914471f..4c60928 100644
--- a/sources/plugins/link/dialogs/link.js
+++ b/sources/plugins/link/dialogs/link.js
@@ -10,6 +10,110 @@
10 var plugin = CKEDITOR.plugins.link, 10 var plugin = CKEDITOR.plugins.link,
11 initialLinkText; 11 initialLinkText;
12 12
13 function createRangeForLink( editor, link ) {
14 var range = editor.createRange();
15
16 range.setStartBefore( link );
17 range.setEndAfter( link );
18
19 return range;
20 }
21
22 function insertLinksIntoSelection( editor, data ) {
23 var attributes = plugin.getLinkAttributes( editor, data ),
24 ranges = editor.getSelection().getRanges(),
25 style = new CKEDITOR.style( {
26 element: 'a',
27 attributes: attributes.set
28 } ),
29 rangesToSelect = [],
30 range,
31 text,
32 nestedLinks,
33 i,
34 j;
35
36 style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
37
38 for ( i = 0; i < ranges.length; i++ ) {
39 range = ranges[ i ];
40
41 // Use link URL as text with a collapsed cursor.
42 if ( range.collapsed ) {
43 // Short mailto link text view (http://dev.ckeditor.com/ticket/5736).
44 text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ?
45 data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document );
46 range.insertNode( text );
47 range.selectNodeContents( text );
48 } else if ( initialLinkText !== data.linkText ) {
49 text = new CKEDITOR.dom.text( data.linkText, editor.document );
50
51 // Shrink range to preserve block element.
52 range.shrink( CKEDITOR.SHRINK_TEXT );
53
54 // Use extractHtmlFromRange to remove markup within the selection. Also this method is a little
55 // smarter than range#deleteContents as it plays better e.g. with table cells.
56 editor.editable().extractHtmlFromRange( range );
57
58 range.insertNode( text );
59 }
60
61 // Editable links nested within current range should be removed, so that the link is applied to whole selection.
62 nestedLinks = range._find( 'a' );
63
64 for ( j = 0; j < nestedLinks.length; j++ ) {
65 nestedLinks[ j ].remove( true );
66 }
67
68
69 // Apply style.
70 style.applyToRange( range, editor );
71
72 rangesToSelect.push( range );
73 }
74
75 editor.getSelection().selectRanges( rangesToSelect );
76 }
77
78 function editLinksInSelection( editor, selectedElements, data ) {
79 var attributes = plugin.getLinkAttributes( editor, data ),
80 ranges = [],
81 element,
82 href,
83 textView,
84 newText,
85 i;
86
87 for ( i = 0; i < selectedElements.length; i++ ) {
88 // We're only editing an existing link, so just overwrite the attributes.
89 element = selectedElements[ i ];
90 href = element.data( 'cke-saved-href' );
91 textView = element.getHtml();
92
93 element.setAttributes( attributes.set );
94 element.removeAttributes( attributes.removed );
95
96
97 if ( data.linkText && initialLinkText != data.linkText ) {
98 // Display text has been changed.
99 newText = data.linkText;
100 } else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {
101 // Update text view when user changes protocol (http://dev.ckeditor.com/ticket/4612).
102 // Short mailto link text view (http://dev.ckeditor.com/ticket/5736).
103 newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ];
104 }
105
106 if ( newText ) {
107 element.setText( newText );
108 }
109
110 ranges.push( createRangeForLink( editor, element ) );
111 }
112
113 // We changed the content, so need to select it again.
114 editor.getSelection().selectRanges( ranges );
115 }
116
13 // Handles the event when the "Target" selection box is changed. 117 // Handles the event when the "Target" selection box is changed.
14 var targetChanged = function() { 118 var targetChanged = function() {
15 var dialog = this.getDialog(), 119 var dialog = this.getDialog(),
@@ -163,7 +267,7 @@
163 label: commonLang.protocol, 267 label: commonLang.protocol,
164 'default': 'http://', 268 'default': 'http://',
165 items: [ 269 items: [
166 // Force 'ltr' for protocol names in BIDI. (#5433) 270 // Force 'ltr' for protocol names in BIDI. (http://dev.ckeditor.com/ticket/5433)
167 [ 'http://\u200E', 'http://' ], 271 [ 'http://\u200E', 'http://' ],
168 [ 'https://\u200E', 'https://' ], 272 [ 'https://\u200E', 'https://' ],
169 [ 'ftp://\u200E', 'ftp://' ], 273 [ 'ftp://\u200E', 'ftp://' ],
@@ -236,7 +340,7 @@
236 }, 340 },
237 commit: function( data ) { 341 commit: function( data ) {
238 // IE will not trigger the onChange event if the mouse has been used 342 // IE will not trigger the onChange event if the mouse has been used
239 // to carry all the operations #4724 343 // to carry all the operations http://dev.ckeditor.com/ticket/4724
240 this.onChange(); 344 this.onChange();
241 345
242 if ( !data.url ) 346 if ( !data.url )
@@ -819,33 +923,30 @@
819 onShow: function() { 923 onShow: function() {
820 var editor = this.getParentEditor(), 924 var editor = this.getParentEditor(),
821 selection = editor.getSelection(), 925 selection = editor.getSelection(),
822 selectedElement = selection.getSelectedElement(),
823 displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(), 926 displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(),
824 element = null; 927 elements = plugin.getSelectedLink( editor, true ),
928 firstLink = elements[ 0 ] || null;
825 929
826 // Fill in all the relevant fields if there's already one link selected. 930 // Fill in all the relevant fields if there's already one link selected.
827 if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) ) { 931 if ( firstLink && firstLink.hasAttribute( 'href' ) ) {
828 // Don't change selection if some element is already selected. 932 // Don't change selection if some element is already selected.
829 // For example - don't destroy fake selection. 933 // For example - don't destroy fake selection.
830 if ( !selectedElement ) { 934 if ( !selection.getSelectedElement() && !selection.isInTable() ) {
831 selection.selectElement( element ); 935 selection.selectElement( firstLink );
832 selectedElement = element;
833 } 936 }
834 } else {
835 element = null;
836 } 937 }
837 938
939 var data = plugin.parseLinkAttributes( editor, firstLink );
940
838 // Here we'll decide whether or not we want to show Display Text field. 941 // Here we'll decide whether or not we want to show Display Text field.
839 if ( plugin.showDisplayTextForElement( selectedElement, editor ) ) { 942 if ( elements.length <= 1 && plugin.showDisplayTextForElement( firstLink, editor ) ) {
840 displayTextField.show(); 943 displayTextField.show();
841 } else { 944 } else {
842 displayTextField.hide(); 945 displayTextField.hide();
843 } 946 }
844 947
845 var data = plugin.parseLinkAttributes( editor, element );
846
847 // Record down the selected element in the dialog. 948 // Record down the selected element in the dialog.
848 this._.selectedElement = element; 949 this._.selectedElements = elements;
849 950
850 this.setupContent( data ); 951 this.setupContent( data );
851 }, 952 },
@@ -855,77 +956,12 @@
855 // Collect data from fields. 956 // Collect data from fields.
856 this.commitContent( data ); 957 this.commitContent( data );
857 958
858 var selection = editor.getSelection(), 959 if ( !this._.selectedElements.length ) {
859 attributes = plugin.getLinkAttributes( editor, data ), 960 insertLinksIntoSelection( 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 { 961 } else {
904 // We're only editing an existing link, so just overwrite the attributes. 962 editLinksInSelection( editor, this._.selectedElements, data );
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 963
928 delete this._.selectedElement; 964 delete this._.selectedElements;
929 } 965 }
930 }, 966 },
931 onLoad: function() { 967 onLoad: function() {
diff --git a/sources/plugins/link/lang/eo.js b/sources/plugins/link/lang/eo.js
index 7991231..d2b6faf 100644
--- a/sources/plugins/link/lang/eo.js
+++ b/sources/plugins/link/lang/eo.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'eo', {
19 anchorName: 'Per Ankronomo', 19 anchorName: 'Per Ankronomo',
20 charset: 'Signaro de la Ligita Rimedo', 20 charset: 'Signaro de la Ligita Rimedo',
21 cssClasses: 'Klasoj de Stilfolioj', 21 cssClasses: 'Klasoj de Stilfolioj',
22 download: 'Force Download', // MISSING 22 download: 'Altrudi Elŝuton',
23 displayText: 'Display Text', // MISSING 23 displayText: 'Vidigi Tekston',
24 emailAddress: 'Retpoŝto', 24 emailAddress: 'Retpoŝto',
25 emailBody: 'Mesaĝa korpo', 25 emailBody: 'Mesaĝa korpo',
26 emailSubject: 'Mesaĝa Temo', 26 emailSubject: 'Mesaĝa Temo',
diff --git a/sources/plugins/link/lang/es-mx.js b/sources/plugins/link/lang/es-mx.js
new file mode 100644
index 0000000..1c27060
--- /dev/null
+++ b/sources/plugins/link/lang/es-mx.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-mx', {
6 acccessKey: 'Llave de acceso',
7 advanced: 'Avanzada',
8 advisoryContentType: 'Tipo de contenido consultivo',
9 advisoryTitle: 'Título asesor',
10 anchor: {
11 toolbar: 'Ancla',
12 menu: 'Editar ancla',
13 title: 'Propiedades del ancla',
14 name: 'Nombre del ancla',
15 errorName: 'Escriba el nombre del ancla',
16 remove: 'Remover ancla'
17 },
18 anchorId: 'Por Id del elemento',
19 anchorName: 'Por nombre del ancla',
20 charset: 'Recurso relacionado Charset',
21 cssClasses: 'Clases de estilo de hoja',
22 download: 'Forzar la descarga',
23 displayText: 'Mostrar texto',
24 emailAddress: 'Dirección de correo electrónico',
25 emailBody: 'Cuerpo del mensaje',
26 emailSubject: 'Asunto del mensaje',
27 id: 'Id',
28 info: 'Información del enlace',
29 langCode: 'Código del idioma',
30 langDir: 'Dirección del idioma',
31 langDirLTR: 'Izquierda a Derecha (LTR)',
32 langDirRTL: 'Derecha a Izquierda (RTL)',
33 menu: 'Editar enlace',
34 name: 'Nombre',
35 noAnchors: '(No hay anclas disponibles en el documento)',
36 noEmail: 'Escriba la dirección de correo electrónico',
37 noUrl: 'Escriba la URL del enlace',
38 other: '<other>',
39 popupDependent: 'Dependiente (Netscape)',
40 popupFeatures: 'Ventana emergente',
41 popupFullScreen: 'Pantalla completa (IE)',
42 popupLeft: 'Posición Izquierda',
43 popupLocationBar: 'Ubicación de la barra',
44 popupMenuBar: 'Barra de menú',
45 popupResizable: 'Redimensionable',
46 popupScrollBars: 'Barras de desplazamiento',
47 popupStatusBar: 'Barra de estado',
48 popupToolbar: 'Barra de herramienta',
49 popupTop: 'Posición superior',
50 rel: 'Relación',
51 selectAnchor: 'Selecciona un ancla',
52 styles: 'Estilo',
53 tabIndex: 'Indice de tabulación',
54 target: 'Objetivo',
55 targetFrame: '<frame>',
56 targetFrameName: 'Nombre del marco de destino',
57 targetPopup: '<popup window>',
58 targetPopupName: 'Nombre de ventana emergente',
59 title: 'Enlace',
60 toAnchor: 'Enlace al ancla en el texto',
61 toEmail: 'Correo electrónico',
62 toUrl: 'URL',
63 toolbar: 'Enlace',
64 type: 'Tipo de enlace',
65 unlink: 'Desconectar',
66 upload: 'Subir'
67} );
diff --git a/sources/plugins/link/lang/fr.js b/sources/plugins/link/lang/fr.js
index a4561cb..d40d8d9 100644
--- a/sources/plugins/link/lang/fr.js
+++ b/sources/plugins/link/lang/fr.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'fr', {
19 anchorName: 'Par nom d\'ancre', 19 anchorName: 'Par nom d\'ancre',
20 charset: 'Encodage de la ressource liée', 20 charset: 'Encodage de la ressource liée',
21 cssClasses: 'Classes de style', 21 cssClasses: 'Classes de style',
22 download: 'Force Download', // MISSING 22 download: 'Forcer le téléchargement',
23 displayText: 'Display Text', // MISSING 23 displayText: 'Afficher le texte',
24 emailAddress: 'Adresse électronique', 24 emailAddress: 'Adresse électronique',
25 emailBody: 'Corps du message', 25 emailBody: 'Corps du message',
26 emailSubject: 'Sujet du message', 26 emailSubject: 'Sujet du message',
diff --git a/sources/plugins/link/lang/gl.js b/sources/plugins/link/lang/gl.js
index 45ced42..a7d7b0b 100644
--- a/sources/plugins/link/lang/gl.js
+++ b/sources/plugins/link/lang/gl.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'gl', {
19 anchorName: 'Polo nome da ancoraxe', 19 anchorName: 'Polo nome da ancoraxe',
20 charset: 'Codificación do recurso ligado', 20 charset: 'Codificación do recurso ligado',
21 cssClasses: 'Clases da folla de estilos', 21 cssClasses: 'Clases da folla de estilos',
22 download: 'Force Download', // MISSING 22 download: 'Forzar a descarga',
23 displayText: 'Display Text', // MISSING 23 displayText: 'Amosar o texto',
24 emailAddress: 'Enderezo de correo', 24 emailAddress: 'Enderezo de correo',
25 emailBody: 'Corpo da mensaxe', 25 emailBody: 'Corpo da mensaxe',
26 emailSubject: 'Asunto da mensaxe', 26 emailSubject: 'Asunto da mensaxe',
diff --git a/sources/plugins/link/lang/hr.js b/sources/plugins/link/lang/hr.js
index 898b18b..5bb1b88 100644
--- a/sources/plugins/link/lang/hr.js
+++ b/sources/plugins/link/lang/hr.js
@@ -5,8 +5,8 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
5CKEDITOR.plugins.setLang( 'link', 'hr', { 5CKEDITOR.plugins.setLang( 'link', 'hr', {
6 acccessKey: 'Pristupna tipka', 6 acccessKey: 'Pristupna tipka',
7 advanced: 'Napredno', 7 advanced: 'Napredno',
8 advisoryContentType: 'Advisory vrsta sadržaja', 8 advisoryContentType: 'Savjetodavna vrsta sadržaja',
9 advisoryTitle: 'Advisory naslov', 9 advisoryTitle: 'Savjetodavni naslov',
10 anchor: { 10 anchor: {
11 toolbar: 'Ubaci/promijeni sidro', 11 toolbar: 'Ubaci/promijeni sidro',
12 menu: 'Svojstva sidra', 12 menu: 'Svojstva sidra',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'hr', {
19 anchorName: 'Po nazivu sidra', 19 anchorName: 'Po nazivu sidra',
20 charset: 'Kodna stranica povezanih resursa', 20 charset: 'Kodna stranica povezanih resursa',
21 cssClasses: 'Stylesheet klase', 21 cssClasses: 'Stylesheet klase',
22 download: 'Force Download', // MISSING 22 download: 'Preuzmi na silu',
23 displayText: 'Display Text', // MISSING 23 displayText: 'Prikaži tekst',
24 emailAddress: 'E-Mail adresa', 24 emailAddress: 'E-Mail adresa',
25 emailBody: 'Sadržaj poruke', 25 emailBody: 'Sadržaj poruke',
26 emailSubject: 'Naslov', 26 emailSubject: 'Naslov',
@@ -56,12 +56,12 @@ CKEDITOR.plugins.setLang( 'link', 'hr', {
56 targetFrameName: 'Ime ciljnog okvira', 56 targetFrameName: 'Ime ciljnog okvira',
57 targetPopup: '<popup prozor>', 57 targetPopup: '<popup prozor>',
58 targetPopupName: 'Naziv popup prozora', 58 targetPopupName: 'Naziv popup prozora',
59 title: 'Link', 59 title: 'Veza',
60 toAnchor: 'Sidro na ovoj stranici', 60 toAnchor: 'Sidro na ovoj stranici',
61 toEmail: 'E-Mail', 61 toEmail: 'E-Mail',
62 toUrl: 'URL', 62 toUrl: 'URL',
63 toolbar: 'Ubaci/promijeni link', 63 toolbar: 'Ubaci/promijeni vezu',
64 type: 'Link vrsta', 64 type: 'Vrsta veze',
65 unlink: 'Ukloni link', 65 unlink: 'Ukloni vezu',
66 upload: 'Pošalji' 66 upload: 'Pošalji'
67} ); 67} );
diff --git a/sources/plugins/link/lang/hu.js b/sources/plugins/link/lang/hu.js
index 52c09a8..102ca56 100644
--- a/sources/plugins/link/lang/hu.js
+++ b/sources/plugins/link/lang/hu.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'hu', {
19 anchorName: 'Horgony név szerint', 19 anchorName: 'Horgony név szerint',
20 charset: 'Hivatkozott tartalom kódlapja', 20 charset: 'Hivatkozott tartalom kódlapja',
21 cssClasses: 'Stíluskészlet', 21 cssClasses: 'Stíluskészlet',
22 download: 'Force Download', // MISSING 22 download: 'Kötelező letöltés',
23 displayText: 'Display Text', // MISSING 23 displayText: 'Megjeletett szöveg',
24 emailAddress: 'E-Mail cím', 24 emailAddress: 'E-Mail cím',
25 emailBody: 'Üzenet', 25 emailBody: 'Üzenet',
26 emailSubject: 'Üzenet tárgya', 26 emailSubject: 'Üzenet tárgya',
diff --git a/sources/plugins/link/lang/ja.js b/sources/plugins/link/lang/ja.js
index 94108b5..342025f 100644
--- a/sources/plugins/link/lang/ja.js
+++ b/sources/plugins/link/lang/ja.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'ja', {
19 anchorName: 'アンカー名', 19 anchorName: 'アンカー名',
20 charset: 'リンク先のcharset', 20 charset: 'リンク先のcharset',
21 cssClasses: 'スタイルシートクラス', 21 cssClasses: 'スタイルシートクラス',
22 download: 'Force Download', // MISSING 22 download: '強制的にダウンロード',
23 displayText: 'Display Text', // MISSING 23 displayText: '表示文字',
24 emailAddress: 'E-Mail アドレス', 24 emailAddress: 'E-Mail アドレス',
25 emailBody: '本文', 25 emailBody: '本文',
26 emailSubject: '件名', 26 emailSubject: '件名',
diff --git a/sources/plugins/link/lang/ko.js b/sources/plugins/link/lang/ko.js
index 86a797d..894ac62 100644
--- a/sources/plugins/link/lang/ko.js
+++ b/sources/plugins/link/lang/ko.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'ko', {
19 anchorName: '책갈피 이름', 19 anchorName: '책갈피 이름',
20 charset: '링크된 자료 문자열 인코딩', 20 charset: '링크된 자료 문자열 인코딩',
21 cssClasses: '스타일시트 클래스', 21 cssClasses: '스타일시트 클래스',
22 download: 'Force Download', // MISSING 22 download: '강제 다운로드',
23 displayText: 'Display Text', // MISSING 23 displayText: '보이는 글자',
24 emailAddress: '이메일 주소', 24 emailAddress: '이메일 주소',
25 emailBody: '메시지 내용', 25 emailBody: '메시지 내용',
26 emailSubject: '메시지 제목', 26 emailSubject: '메시지 제목',
diff --git a/sources/plugins/link/lang/ku.js b/sources/plugins/link/lang/ku.js
index 16faf24..ad06cd9 100644
--- a/sources/plugins/link/lang/ku.js
+++ b/sources/plugins/link/lang/ku.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'ku', {
19 anchorName: 'بەپێی ناوی لەنگەر', 19 anchorName: 'بەپێی ناوی لەنگەر',
20 charset: 'بەستەری سەرچاوەی نووسە', 20 charset: 'بەستەری سەرچاوەی نووسە',
21 cssClasses: 'شێوازی چینی پەڕه', 21 cssClasses: 'شێوازی چینی پەڕه',
22 download: 'Force Download', // MISSING 22 download: 'داگرتنی بەهێز',
23 displayText: 'Display Text', // MISSING 23 displayText: 'پیشاندانی دەق',
24 emailAddress: 'ناونیشانی ئیمەیل', 24 emailAddress: 'ناونیشانی ئیمەیل',
25 emailBody: 'ناوەڕۆکی نامە', 25 emailBody: 'ناوەڕۆکی نامە',
26 emailSubject: 'بابەتی نامە', 26 emailSubject: 'بابەتی نامە',
diff --git a/sources/plugins/link/lang/ru.js b/sources/plugins/link/lang/ru.js
index 7f4b775..7bc00d5 100644
--- a/sources/plugins/link/lang/ru.js
+++ b/sources/plugins/link/lang/ru.js
@@ -19,7 +19,7 @@ CKEDITOR.plugins.setLang( 'link', 'ru', {
19 anchorName: 'По имени', 19 anchorName: 'По имени',
20 charset: 'Кодировка ресурса', 20 charset: 'Кодировка ресурса',
21 cssClasses: 'Классы CSS', 21 cssClasses: 'Классы CSS',
22 download: 'Force Download', // MISSING 22 download: 'Скачать как файл',
23 displayText: 'Отображаемый текст', 23 displayText: 'Отображаемый текст',
24 emailAddress: 'Email адрес', 24 emailAddress: 'Email адрес',
25 emailBody: 'Текст сообщения', 25 emailBody: 'Текст сообщения',
diff --git a/sources/plugins/link/lang/sk.js b/sources/plugins/link/lang/sk.js
index 87b60bd..6383fc9 100644
--- a/sources/plugins/link/lang/sk.js
+++ b/sources/plugins/link/lang/sk.js
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'sk', {
19 anchorName: 'Podľa mena kotvy', 19 anchorName: 'Podľa mena kotvy',
20 charset: 'Priradená znaková sada', 20 charset: 'Priradená znaková sada',
21 cssClasses: 'Triedy štýlu', 21 cssClasses: 'Triedy štýlu',
22 download: 'Force Download', // MISSING 22 download: 'Vynútené sťahovanie.',
23 displayText: 'Display Text', // MISSING 23 displayText: 'Zobraziť text',
24 emailAddress: 'E-Mailová adresa', 24 emailAddress: 'E-Mailová adresa',
25 emailBody: 'Telo správy', 25 emailBody: 'Telo správy',
26 emailSubject: 'Predmet správy', 26 emailSubject: 'Predmet správy',
diff --git a/sources/plugins/link/lang/zh.js b/sources/plugins/link/lang/zh.js
index 5ba3d1c..a2cee62 100644
--- a/sources/plugins/link/lang/zh.js
+++ b/sources/plugins/link/lang/zh.js
@@ -19,7 +19,7 @@ CKEDITOR.plugins.setLang( 'link', 'zh', {
19 anchorName: '依錨點名稱', 19 anchorName: '依錨點名稱',
20 charset: '連結資源的字元集', 20 charset: '連結資源的字元集',
21 cssClasses: '樣式表類別', 21 cssClasses: '樣式表類別',
22 download: 'Force Download', // MISSING 22 download: '強制下載',
23 displayText: '顯示文字', 23 displayText: '顯示文字',
24 emailAddress: '電子郵件地址', 24 emailAddress: '電子郵件地址',
25 emailBody: '郵件本文', 25 emailBody: '郵件本文',
diff --git a/sources/plugins/link/plugin.js b/sources/plugins/link/plugin.js
index 94d582b..120097f 100644
--- a/sources/plugins/link/plugin.js
+++ b/sources/plugins/link/plugin.js
@@ -9,7 +9,7 @@
9 CKEDITOR.plugins.add( 'link', { 9 CKEDITOR.plugins.add( 'link', {
10 requires: 'dialog,fakeobjects', 10 requires: 'dialog,fakeobjects',
11 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
13 // jscs:enable maximumLineLength 13 // jscs:enable maximumLineLength
14 icons: 'anchor,anchor-rtl,link,unlink', // %REMOVE_LINE_CORE% 14 icons: 'anchor,anchor-rtl,link,unlink', // %REMOVE_LINE_CORE%
15 hidpi: true, // %REMOVE_LINE_CORE% 15 hidpi: true, // %REMOVE_LINE_CORE%
@@ -92,9 +92,12 @@
92 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' ); 92 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' );
93 93
94 editor.on( 'doubleclick', function( evt ) { 94 editor.on( 'doubleclick', function( evt ) {
95 var element = CKEDITOR.plugins.link.getSelectedLink( editor ) || evt.data.element; 95 // If the link has descendants and the last part of it is also a part of a word partially
96 // unlinked, clicked element may be a descendant of the link, not the link itself (http://dev.ckeditor.com/ticket/11956).
97 // The evt.data.element.getAscendant( 'img', 1 ) condition allows opening anchor dialog if the anchor is empty (#501).
98 var element = evt.data.element.getAscendant( { a: 1, img: 1 }, true );
96 99
97 if ( !element.isReadOnly() ) { 100 if ( element && !element.isReadOnly() ) {
98 if ( element.is( 'a' ) ) { 101 if ( element.is( 'a' ) ) {
99 evt.data.dialog = ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) ? 'anchor' : 'link'; 102 evt.data.dialog = ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) ? 'anchor' : 'link';
100 103
@@ -108,7 +111,7 @@
108 111
109 // If event was cancelled, link passed in event data will not be selected. 112 // If event was cancelled, link passed in event data will not be selected.
110 editor.on( 'doubleclick', function( evt ) { 113 editor.on( 'doubleclick', function( evt ) {
111 // Make sure both links and anchors are selected (#11822). 114 // Make sure both links and anchors are selected (http://dev.ckeditor.com/ticket/11822).
112 if ( evt.data.dialog in { link: 1, anchor: 1 } && evt.data.link ) 115 if ( evt.data.dialog in { link: 1, anchor: 1 } && evt.data.link )
113 editor.getSelection().selectElement( evt.data.link ); 116 editor.getSelection().selectElement( evt.data.link );
114 }, null, null, 20 ); 117 }, null, null, 20 );
@@ -311,20 +314,38 @@
311 * 314 *
312 * @since 3.2.1 315 * @since 3.2.1
313 * @param {CKEDITOR.editor} editor 316 * @param {CKEDITOR.editor} editor
317 * @param {Boolean} [returnMultiple=false] Indicates whether the function should return only the first selected link or all of them.
318 * @returns {CKEDITOR.dom.element/CKEDITOR.dom.element[]/null} A single link element or an array of link
319 * elements relevant to the current selection.
314 */ 320 */
315 getSelectedLink: function( editor ) { 321 getSelectedLink: function( editor, returnMultiple ) {
316 var selection = editor.getSelection(); 322 var selection = editor.getSelection(),
317 var selectedElement = selection.getSelectedElement(); 323 selectedElement = selection.getSelectedElement(),
318 if ( selectedElement && selectedElement.is( 'a' ) ) 324 ranges = selection.getRanges(),
325 links = [],
326 link,
327 range,
328 i;
329
330 if ( !returnMultiple && selectedElement && selectedElement.is( 'a' ) ) {
319 return selectedElement; 331 return selectedElement;
332 }
333
334 for ( i = 0; i < ranges.length; i++ ) {
335 range = selection.getRanges()[ i ];
320 336
321 var range = selection.getRanges()[ 0 ]; 337 // Skip bogus to cover cases of multiple selection inside tables (#tp2245).
338 range.shrink( CKEDITOR.SHRINK_TEXT, false, { skipBogus: true } );
339 link = editor.elementPath( range.getCommonAncestor() ).contains( 'a', 1 );
322 340
323 if ( range ) { 341 if ( link && returnMultiple ) {
324 range.shrink( CKEDITOR.SHRINK_TEXT ); 342 links.push( link );
325 return editor.elementPath( range.getCommonAncestor() ).contains( 'a', 1 ); 343 } else if ( link ) {
344 return link;
345 }
326 } 346 }
327 return null; 347
348 return returnMultiple ? links : null;
328 }, 349 },
329 350
330 /** 351 /**
@@ -340,7 +361,7 @@
340 var editable = editor.editable(), 361 var editable = editor.editable(),
341 362
342 // The scope of search for anchors is the entire document for inline editors 363 // The scope of search for anchors is the entire document for inline editors
343 // and editor's editable for classic editor/divarea (#11359). 364 // and editor's editable for classic editor/divarea (http://dev.ckeditor.com/ticket/11359).
344 scope = ( editable.isInline() && !editor.plugins.divarea ) ? editor.document : editable, 365 scope = ( editable.isInline() && !editor.plugins.divarea ) ? editor.document : editable,
345 366
346 links = scope.getElementsByTag( 'a' ), 367 links = scope.getElementsByTag( 'a' ),
@@ -384,7 +405,7 @@
384 fakeAnchor: true, 405 fakeAnchor: true,
385 406
386 /** 407 /**
387 * For browsers that do not support CSS3 `a[name]:empty()`. Note that IE9 is included because of #7783. 408 * For browsers that do not support CSS3 `a[name]:empty()`. Note that IE9 is included because of http://dev.ckeditor.com/ticket/7783.
388 * 409 *
389 * @readonly 410 * @readonly
390 * @deprecated 4.3.3 It is set to `false` in every browser. 411 * @deprecated 4.3.3 It is set to `false` in every browser.
@@ -438,7 +459,7 @@
438 if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) ) { 459 if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) ) {
439 if ( emailProtection == 'encode' ) { 460 if ( emailProtection == 'encode' ) {
440 href = href.replace( encodedEmailLinkRegex, function( match, protectedAddress, rest ) { 461 href = href.replace( encodedEmailLinkRegex, function( match, protectedAddress, rest ) {
441 // Without it 'undefined' is appended to e-mails without subject and body (#9192). 462 // Without it 'undefined' is appended to e-mails without subject and body (http://dev.ckeditor.com/ticket/9192).
442 rest = rest || ''; 463 rest = rest || '';
443 464
444 return 'mailto:' + 465 return 'mailto:' +
@@ -513,7 +534,7 @@
513 534
514 var featureMatch; 535 var featureMatch;
515 while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[ 2 ] ) ) ) { 536 while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[ 2 ] ) ) ) {
516 // Some values should remain numbers (#7300) 537 // Some values should remain numbers (http://dev.ckeditor.com/ticket/7300)
517 if ( ( featureMatch[ 2 ] == 'yes' || featureMatch[ 2 ] == '1' ) && !( featureMatch[ 1 ] in { height: 1, width: 1, top: 1, left: 1 } ) ) 538 if ( ( featureMatch[ 2 ] == 'yes' || featureMatch[ 2 ] == '1' ) && !( featureMatch[ 1 ] in { height: 1, width: 1, top: 1, left: 1 } ) )
518 retval.target[ featureMatch[ 1 ] ] = true; 539 retval.target[ featureMatch[ 1 ] ] = true;
519 else if ( isFinite( featureMatch[ 2 ] ) ) 540 else if ( isFinite( featureMatch[ 2 ] ) )
@@ -689,7 +710,7 @@
689 set[ 'data-cke-saved-name' ] = set.name; 710 set[ 'data-cke-saved-name' ] = set.name;
690 } 711 }
691 712
692 // Browser need the "href" fro copy/paste link to work. (#6641) 713 // Browser need the "href" fro copy/paste link to work. (http://dev.ckeditor.com/ticket/6641)
693 if ( set[ 'data-cke-saved-href' ] ) 714 if ( set[ 'data-cke-saved-href' ] )
694 set.href = set[ 'data-cke-saved-href' ]; 715 set.href = set[ 'data-cke-saved-href' ];
695 716
@@ -726,21 +747,26 @@
726 */ 747 */
727 showDisplayTextForElement: function( element, editor ) { 748 showDisplayTextForElement: function( element, editor ) {
728 var undesiredElements = { 749 var undesiredElements = {
729 img: 1, 750 img: 1,
730 table: 1, 751 table: 1,
731 tbody: 1, 752 tbody: 1,
732 thead: 1, 753 thead: 1,
733 tfoot: 1, 754 tfoot: 1,
734 input: 1, 755 input: 1,
735 select: 1, 756 select: 1,
736 textarea: 1 757 textarea: 1
737 }; 758 },
759 selection = editor.getSelection();
738 760
739 // Widget duck typing, we don't want to show display text for widgets. 761 // Widget duck typing, we don't want to show display text for widgets.
740 if ( editor.widgets && editor.widgets.focused ) { 762 if ( editor.widgets && editor.widgets.focused ) {
741 return false; 763 return false;
742 } 764 }
743 765
766 if ( selection && selection.getRanges().length > 1 ) {
767 return false;
768 }
769
744 return !element || !element.getName || !element.is( undesiredElements ); 770 return !element || !element.getName || !element.is( undesiredElements );
745 } 771 }
746 }; 772 };
@@ -750,8 +776,29 @@
750 CKEDITOR.unlinkCommand = function() {}; 776 CKEDITOR.unlinkCommand = function() {};
751 CKEDITOR.unlinkCommand.prototype = { 777 CKEDITOR.unlinkCommand.prototype = {
752 exec: function( editor ) { 778 exec: function( editor ) {
779 // IE/Edge removes link from selection while executing "unlink" command when cursor
780 // is right before/after link's text. Therefore whole link must be selected and the
781 // position of cursor must be restored to its initial state after unlinking. (http://dev.ckeditor.com/ticket/13062)
782 if ( CKEDITOR.env.ie ) {
783 var range = editor.getSelection().getRanges()[ 0 ],
784 link = ( range.getPreviousEditableNode() && range.getPreviousEditableNode().getAscendant( 'a', true ) ) ||
785 ( range.getNextEditableNode() && range.getNextEditableNode().getAscendant( 'a', true ) ),
786 bookmark;
787
788 if ( range.collapsed && link ) {
789 bookmark = range.createBookmark();
790 range.selectNodeContents( link );
791 range.select();
792 }
793 }
794
753 var style = new CKEDITOR.style( { element: 'a', type: CKEDITOR.STYLE_INLINE, alwaysRemoveElement: 1 } ); 795 var style = new CKEDITOR.style( { element: 'a', type: CKEDITOR.STYLE_INLINE, alwaysRemoveElement: 1 } );
754 editor.removeStyle( style ); 796 editor.removeStyle( style );
797
798 if ( bookmark ) {
799 range.moveToBookmark( bookmark );
800 range.select();
801 }
755 }, 802 },
756 803
757 refresh: function( editor, path ) { 804 refresh: function( editor, path ) {
@@ -768,7 +815,8 @@
768 815
769 contextSensitive: 1, 816 contextSensitive: 1,
770 startDisabled: 1, 817 startDisabled: 1,
771 requiredContent: 'a[href]' 818 requiredContent: 'a[href]',
819 editorFocus: 1
772 }; 820 };
773 821
774 CKEDITOR.removeAnchorCommand = function() {}; 822 CKEDITOR.removeAnchorCommand = function() {};
diff --git a/sources/plugins/list/lang/es-mx.js b/sources/plugins/list/lang/es-mx.js
new file mode 100644
index 0000000..5e50fcb
--- /dev/null
+++ b/sources/plugins/list/lang/es-mx.js
@@ -0,0 +1,8 @@
1/*
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-mx', {
6 bulletedlist: 'Insertar/Remover Lista con viñetas',
7 numberedlist: 'Insertar/Remover Lista numerada'
8} );
diff --git a/sources/plugins/list/plugin.js b/sources/plugins/list/plugin.js
index 7280cc2..73f5d0b 100644
--- a/sources/plugins/list/plugin.js
+++ b/sources/plugins/list/plugin.js
@@ -60,7 +60,7 @@
60 for ( var i = 0, count = listNode.getChildCount(); i < count; i++ ) { 60 for ( var i = 0, count = listNode.getChildCount(); i < count; i++ ) {
61 var listItem = listNode.getChild( i ); 61 var listItem = listNode.getChild( i );
62 62
63 // Fixing malformed nested lists by moving it into a previous list item. (#6236) 63 // Fixing malformed nested lists by moving it into a previous list item. (http://dev.ckeditor.com/ticket/6236)
64 if ( listItem.type == CKEDITOR.NODE_ELEMENT && listItem.getName() in CKEDITOR.dtd.$list ) 64 if ( listItem.type == CKEDITOR.NODE_ELEMENT && listItem.getName() in CKEDITOR.dtd.$list )
65 CKEDITOR.plugins.list.listToArray( listItem, database, baseArray, baseIndentLevel + 1 ); 65 CKEDITOR.plugins.list.listToArray( listItem, database, baseArray, baseIndentLevel + 1 );
66 66
@@ -137,13 +137,13 @@
137 currentListItem.append( item.contents[ i ].clone( 1, 1 ) ); 137 currentListItem.append( item.contents[ i ].clone( 1, 1 ) );
138 currentIndex++; 138 currentIndex++;
139 } else if ( item.indent == Math.max( indentLevel, 0 ) + 1 ) { 139 } else if ( item.indent == Math.max( indentLevel, 0 ) + 1 ) {
140 // Maintain original direction (#6861). 140 // Maintain original direction (http://dev.ckeditor.com/ticket/6861).
141 var currDir = listArray[ currentIndex - 1 ].element.getDirection( 1 ), 141 var currDir = listArray[ currentIndex - 1 ].element.getDirection( 1 ),
142 listData = CKEDITOR.plugins.list.arrayToList( listArray, null, currentIndex, paragraphMode, currDir != orgDir ? orgDir : null ); 142 listData = CKEDITOR.plugins.list.arrayToList( listArray, null, currentIndex, paragraphMode, currDir != orgDir ? orgDir : null );
143 143
144 // If the next block is an <li> with another list tree as the first 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 145 // child, we'll need to append a filler (<br>/NBSP) or the list item
146 // wouldn't be editable. (#6724) 146 // wouldn't be editable. (http://dev.ckeditor.com/ticket/6724)
147 if ( !currentListItem.getChildCount() && CKEDITOR.env.needsNbspFiller && doc.$.documentMode <= 7 ) 147 if ( !currentListItem.getChildCount() && CKEDITOR.env.needsNbspFiller && doc.$.documentMode <= 7 )
148 currentListItem.append( doc.createText( '\xa0' ) ); 148 currentListItem.append( doc.createText( '\xa0' ) );
149 currentListItem.append( listData.listNode ); 149 currentListItem.append( listData.listNode );
@@ -416,7 +416,7 @@
416 contentBlock.appendTo( listItem ); 416 contentBlock.appendTo( listItem );
417 else { 417 else {
418 contentBlock.copyAttributes( listItem ); 418 contentBlock.copyAttributes( listItem );
419 // Remove direction attribute after it was merged into list root. (#7657) 419 // Remove direction attribute after it was merged into list root. (http://dev.ckeditor.com/ticket/7657)
420 if ( listDir && contentBlock.getDirection() ) { 420 if ( listDir && contentBlock.getDirection() ) {
421 listItem.removeStyle( 'direction' ); 421 listItem.removeStyle( 'direction' );
422 listItem.removeAttribute( 'dir' ); 422 listItem.removeAttribute( 'dir' );
@@ -477,7 +477,7 @@
477 477
478 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, groupObj.root.getAttribute( 'dir' ) ); 478 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, groupObj.root.getAttribute( 'dir' ) );
479 479
480 // Compensate <br> before/after the list node if the surrounds are non-blocks.(#3836) 480 // Compensate <br> before/after the list node if the surrounds are non-blocks.(http://dev.ckeditor.com/ticket/3836)
481 var docFragment = newList.listNode, 481 var docFragment = newList.listNode,
482 boundaryNode, siblingNode; 482 boundaryNode, siblingNode;
483 483
@@ -504,9 +504,9 @@
504 // Checks wheather this block should be element preserved (not transformed to <li>) when creating list. 504 // Checks wheather this block should be element preserved (not transformed to <li>) when creating list.
505 function shouldPreserveBlock( block ) { 505 function shouldPreserveBlock( block ) {
506 return ( 506 return (
507 // #5335 507 // http://dev.ckeditor.com/ticket/5335
508 block.is( 'pre' ) || 508 block.is( 'pre' ) ||
509 // #5271 - this is a header. 509 // http://dev.ckeditor.com/ticket/5271 - this is a header.
510 headerTagRegex.test( block.getName() ) || 510 headerTagRegex.test( block.getName() ) ||
511 // 11083 - this is a non-editable element. 511 // 11083 - this is a non-editable element.
512 block.getAttribute( 'contenteditable' ) == 'false' 512 block.getAttribute( 'contenteditable' ) == 'false'
@@ -523,7 +523,7 @@
523 523
524 var elementType = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT ); 524 var elementType = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT );
525 525
526 // Merge child nodes with direction preserved. (#7448) 526 // Merge child nodes with direction preserved. (http://dev.ckeditor.com/ticket/7448)
527 function mergeChildren( from, into, refNode, forward ) { 527 function mergeChildren( from, into, refNode, forward ) {
528 var child, itemDir; 528 var child, itemDir;
529 while ( ( child = from[ forward ? 'getLast' : 'getFirst' ]( elementType ) ) ) { 529 while ( ( child = from[ forward ? 'getLast' : 'getFirst' ]( elementType ) ) ) {
@@ -556,7 +556,7 @@
556 selection.selectRanges( ranges ); 556 selection.selectRanges( ranges );
557 } 557 }
558 // Maybe a single range there enclosing the whole list, 558 // Maybe a single range there enclosing the whole list,
559 // turn on the list state manually(#4129). 559 // turn on the list state manually(http://dev.ckeditor.com/ticket/4129).
560 else { 560 else {
561 var range = ranges.length == 1 && ranges[ 0 ], 561 var range = ranges.length == 1 && ranges[ 0 ],
562 enclosedNode = range && range.getEnclosedNode(); 562 enclosedNode = range && range.getEnclosedNode();
@@ -606,13 +606,13 @@
606 606
607 // First, try to group by a list ancestor. 607 // First, try to group by a list ancestor.
608 for ( var i = pathElementsCount - 1; i >= 0 && ( element = pathElements[ i ] ); i-- ) { 608 for ( var i = pathElementsCount - 1; i >= 0 && ( element = pathElements[ i ] ); i-- ) {
609 // Don't leak outside block limit (#3940). 609 // Don't leak outside block limit (http://dev.ckeditor.com/ticket/3940).
610 if ( listNodeNames[ element.getName() ] && blockLimit.contains( element ) ) { 610 if ( listNodeNames[ element.getName() ] && blockLimit.contains( element ) ) {
611 // If we've encountered a list inside a block limit 611 // If we've encountered a list inside a block limit
612 // The last group object of the block limit element should 612 // The last group object of the block limit element should
613 // no longer be valid. Since paragraphs after the list 613 // no longer be valid. Since paragraphs after the list
614 // should belong to a different group of paragraphs before 614 // should belong to a different group of paragraphs before
615 // the list. (Bug #1309) 615 // the list. (Bug http://dev.ckeditor.com/ticket/1309)
616 blockLimit.removeCustomData( 'list_group_object_' + index ); 616 blockLimit.removeCustomData( 'list_group_object_' + index );
617 617
618 var groupObj = element.getCustomData( 'list_group_object' ); 618 var groupObj = element.getCustomData( 'list_group_object' );
@@ -688,7 +688,7 @@
688 function mergeSibling( rtl ) { 688 function mergeSibling( rtl ) {
689 var sibling = listNode[ rtl ? 'getPrevious' : 'getNext' ]( nonEmpty ); 689 var sibling = listNode[ rtl ? 'getPrevious' : 'getNext' ]( nonEmpty );
690 if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT && sibling.is( listNode.getName() ) ) { 690 if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT && sibling.is( listNode.getName() ) ) {
691 // Move children order by merge direction.(#3820) 691 // Move children order by merge direction.(http://dev.ckeditor.com/ticket/3820)
692 mergeChildren( listNode, sibling, null, !rtl ); 692 mergeChildren( listNode, sibling, null, !rtl );
693 693
694 listNode.remove(); 694 listNode.remove();
@@ -770,7 +770,7 @@
770 nextPath = nextCursor.startPath(); 770 nextPath = nextCursor.startPath();
771 nextBlock = nextPath.block; 771 nextBlock = nextPath.block;
772 772
773 // Abort when nothing to be removed (#10890). 773 // Abort when nothing to be removed (http://dev.ckeditor.com/ticket/10890).
774 if ( !nextBlock ) 774 if ( !nextBlock )
775 break; 775 break;
776 776
@@ -785,7 +785,7 @@
785 nextBlock.remove(); 785 nextBlock.remove();
786 } 786 }
787 787
788 // Check if need to further merge with the list resides after the merged block. (#9080) 788 // Check if need to further merge with the list resides after the merged block. (http://dev.ckeditor.com/ticket/9080)
789 var walkerRng = nextCursor.clone(), editable = editor.editable(); 789 var walkerRng = nextCursor.clone(), editable = editor.editable();
790 walkerRng.setEndAt( editable, CKEDITOR.POSITION_BEFORE_END ); 790 walkerRng.setEndAt( editable, CKEDITOR.POSITION_BEFORE_END );
791 var walker = new CKEDITOR.dom.walker( walkerRng ); 791 var walker = new CKEDITOR.dom.walker( walkerRng );
@@ -811,7 +811,7 @@
811 811
812 CKEDITOR.plugins.add( 'list', { 812 CKEDITOR.plugins.add( 'list', {
813 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
815 // jscs:enable maximumLineLength 815 // jscs:enable maximumLineLength
816 icons: 'bulletedlist,bulletedlist-rtl,numberedlist,numberedlist-rtl', // %REMOVE_LINE_CORE% 816 icons: 'bulletedlist,bulletedlist-rtl,numberedlist,numberedlist-rtl', // %REMOVE_LINE_CORE%
817 hidpi: true, // %REMOVE_LINE_CORE% 817 hidpi: true, // %REMOVE_LINE_CORE%
@@ -840,7 +840,7 @@
840 } ); 840 } );
841 } 841 }
842 842
843 // Handled backspace/del key to join list items. (#8248,#9080) 843 // Handled backspace/del key to join list items. (http://dev.ckeditor.com/ticket/8248,http://dev.ckeditor.com/ticket/9080)
844 editor.on( 'key', function( evt ) { 844 editor.on( 'key', function( evt ) {
845 // Use getKey directly in order to ignore modifiers. 845 // Use getKey directly in order to ignore modifiers.
846 // Justification: http://dev.ckeditor.com/ticket/11861#comment:13 846 // Justification: http://dev.ckeditor.com/ticket/11861#comment:13
@@ -908,7 +908,7 @@
908 // Place cursor at the end of previous block. 908 // Place cursor at the end of previous block.
909 cursor.moveToElementEditEnd( joinWith ); 909 cursor.moveToElementEditEnd( joinWith );
910 910
911 // And then just before end of closest block element (#12729). 911 // And then just before end of closest block element (http://dev.ckeditor.com/ticket/12729).
912 cursor.moveToPosition( cursor.endPath().block, CKEDITOR.POSITION_BEFORE_END ); 912 cursor.moveToPosition( cursor.endPath().block, CKEDITOR.POSITION_BEFORE_END );
913 } 913 }
914 } 914 }
@@ -919,7 +919,7 @@
919 } 919 }
920 else { 920 else {
921 var list = path.contains( listNodeNames ); 921 var list = path.contains( listNodeNames );
922 // Backspace pressed at the start of list outdents the first list item. (#9129) 922 // Backspace pressed at the start of list outdents the first list item. (http://dev.ckeditor.com/ticket/9129)
923 if ( list && range.checkBoundaryOfElement( list, CKEDITOR.START ) ) { 923 if ( list && range.checkBoundaryOfElement( list, CKEDITOR.START ) ) {
924 li = list.getFirst( nonEmpty ); 924 li = list.getFirst( nonEmpty );
925 925
@@ -981,7 +981,7 @@
981 nextLine = range.clone(); 981 nextLine = range.clone();
982 nextLine.moveToElementEditStart( next ); 982 nextLine.moveToElementEditStart( next );
983 983
984 // #13409 984 // http://dev.ckeditor.com/ticket/13409
985 // For the following case and similar 985 // For the following case and similar
986 // 986 //
987 // <ul> 987 // <ul>
@@ -1049,7 +1049,7 @@
1049 } 1049 }
1050 } 1050 }
1051 1051
1052 // Moving `cursor` and `next line` only when at the end literally (#12729). 1052 // Moving `cursor` and `next line` only when at the end literally (http://dev.ckeditor.com/ticket/12729).
1053 if ( isAtEnd == 2 ) { 1053 if ( isAtEnd == 2 ) {
1054 cursor.moveToPosition( cursor.endPath().block, CKEDITOR.POSITION_BEFORE_END ); 1054 cursor.moveToPosition( cursor.endPath().block, CKEDITOR.POSITION_BEFORE_END );
1055 1055
diff --git a/sources/plugins/listblock/plugin.js b/sources/plugins/listblock/plugin.js
index 21e6b08..100159a 100644
--- a/sources/plugins/listblock/plugin.js
+++ b/sources/plugins/listblock/plugin.js
@@ -12,7 +12,7 @@ CKEDITOR.plugins.add( 'listblock', {
12 '<a id="{id}_option" _cke_focus=1 hidefocus=true' + 12 '<a id="{id}_option" _cke_focus=1 hidefocus=true' +
13 ' title="{title}"' + 13 ' title="{title}"' +
14 ' href="javascript:void(\'{val}\')" ' + 14 ' href="javascript:void(\'{val}\')" ' +
15 ' {onclick}="CKEDITOR.tools.callFunction({clickFn},\'{val}\'); return false;"' + // #188 15 ' {onclick}="CKEDITOR.tools.callFunction({clickFn},\'{val}\'); return false;"' + // http://dev.ckeditor.com/ticket/188
16 ' role="option">' + 16 ' role="option">' +
17 '{text}' + 17 '{text}' +
18 '</a>' + 18 '</a>' +
@@ -50,7 +50,7 @@ CKEDITOR.plugins.add( 'listblock', {
50 keys[ 38 ] = 'prev'; // ARROW-UP 50 keys[ 38 ] = 'prev'; // ARROW-UP
51 keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB 51 keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB
52 keys[ 32 ] = CKEDITOR.env.ie ? 'mouseup' : 'click'; // SPACE 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). 53 CKEDITOR.env.ie && ( keys[ 13 ] = 'mouseup' ); // Manage ENTER, since onclick is blocked in IE (http://dev.ckeditor.com/ticket/8041).
54 54
55 this._.pendingHtml = []; 55 this._.pendingHtml = [];
56 this._.pendingList = []; 56 this._.pendingList = [];
@@ -180,6 +180,14 @@ CKEDITOR.plugins.add( 'listblock', {
180 this.onMark && this.onMark( item ); 180 this.onMark && this.onMark( item );
181 }, 181 },
182 182
183 markFirstDisplayed: function() {
184 var context = this;
185 this._.markFirstDisplayed( function() {
186 if ( !context.multiSelect )
187 context.unmarkAll();
188 } );
189 },
190
183 unmark: function( value ) { 191 unmark: function( value ) {
184 var doc = this.element.getDocument(), 192 var doc = this.element.getDocument(),
185 itemId = this._.items[ value ], 193 itemId = this._.items[ value ],
diff --git a/sources/plugins/liststyle/lang/es-mx.js b/sources/plugins/liststyle/lang/es-mx.js
new file mode 100644
index 0000000..56e6fa7
--- /dev/null
+++ b/sources/plugins/liststyle/lang/es-mx.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-mx', {
6 armenian: 'Numeración armenia',
7 bulletedTitle: 'Propiedades de la lista con viñetas',
8 circle: 'Círculo',
9 decimal: 'Decimal (1, 2, 3, etc.)',
10 decimalLeadingZero: 'Decimal con cero (01, 02, 03, etc.)',
11 disc: 'Desc',
12 georgian: 'Numeración gregoriana (an, ban, gan, etc.)',
13 lowerAlpha: 'Alfabeto minúscula (a, b, c, d, e, etc.)',
14 lowerGreek: 'Griego minúscula (alpha, beta, gamma, etc.)',
15 lowerRoman: 'Romano minúscula (i, ii, iii, iv, v, etc.)',
16 none: 'Ninguno',
17 notset: '<not set>',
18 numberedTitle: 'Propiedades de la lista numerada',
19 square: 'Cuadrado',
20 start: 'Inicio',
21 type: 'Tipo',
22 upperAlpha: 'Abecedario mayúscula (A, B, C, D, E, etc.)',
23 upperRoman: 'Romanos mayúscula (I, II, III, IV, V, etc.)',
24 validateStartNumber: 'El número de inicio de la lista debe ser un número entero.'
25} );
diff --git a/sources/plugins/liststyle/plugin.js b/sources/plugins/liststyle/plugin.js
index 2d94142..f281edc 100644
--- a/sources/plugins/liststyle/plugin.js
+++ b/sources/plugins/liststyle/plugin.js
@@ -7,7 +7,7 @@
7 CKEDITOR.plugins.liststyle = { 7 CKEDITOR.plugins.liststyle = {
8 requires: 'dialog,contextmenu', 8 requires: 'dialog,contextmenu',
9 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
11 // jscs:enable maximumLineLength 11 // jscs:enable maximumLineLength
12 init: function( editor ) { 12 init: function( editor ) {
13 if ( editor.blockless ) 13 if ( editor.blockless )
diff --git a/sources/plugins/magicline/lang/es-mx.js b/sources/plugins/magicline/lang/es-mx.js
new file mode 100644
index 0000000..faf006a
--- /dev/null
+++ b/sources/plugins/magicline/lang/es-mx.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-mx', {
7 title: 'Insertar un párrafo aquí'
8} );
diff --git a/sources/plugins/magicline/lang/pt.js b/sources/plugins/magicline/lang/pt.js
index c03c48a..97884c0 100644
--- a/sources/plugins/magicline/lang/pt.js
+++ b/sources/plugins/magicline/lang/pt.js
@@ -4,5 +4,5 @@
4 */ 4 */
5 5
6CKEDITOR.plugins.setLang( 'magicline', 'pt', { 6CKEDITOR.plugins.setLang( 'magicline', 'pt', {
7 title: 'Insira aqui o parágrafo' 7 title: 'Inserir parágrafo aqui'
8} ); 8} );
diff --git a/sources/plugins/magicline/plugin.js b/sources/plugins/magicline/plugin.js
index ac4bb78..45b6fea 100644
--- a/sources/plugins/magicline/plugin.js
+++ b/sources/plugins/magicline/plugin.js
@@ -12,7 +12,7 @@
12 12
13( function() { 13( function() {
14 CKEDITOR.plugins.add( 'magicline', { 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% 15 lang: 'af,ar,az,bg,ca,cs,cy,da,de,de-ch,el,en,en-gb,eo,es,es-mx,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 16 init: initPlugin
17 } ); 17 } );
18 18
@@ -38,7 +38,7 @@
38 // %REMOVE_START% 38 // %REMOVE_START%
39 // Internal DEBUG uses tools located in the topmost window. 39 // Internal DEBUG uses tools located in the topmost window.
40 40
41 // (#9701) Due to security limitations some browsers may throw 41 // (http://dev.ckeditor.com/ticket/9701) Due to security limitations some browsers may throw
42 // errors when accessing window.top object. Do it safely first then. 42 // errors when accessing window.top object. Do it safely first then.
43 try { 43 try {
44 that.debug = window.top.DEBUG; 44 that.debug = window.top.DEBUG;
@@ -278,7 +278,7 @@
278 var elements, element, i; 278 var elements, element, i;
279 279
280 for ( var t in { p: 1, br: 1, div: 1 } ) { 280 for ( var t in { p: 1, br: 1, div: 1 } ) {
281 // document.find is not available in QM (#11149). 281 // document.find is not available in QM (http://dev.ckeditor.com/ticket/11149).
282 elements = editor.document.getElementsByTag( t ); 282 elements = editor.document.getElementsByTag( t );
283 283
284 for ( i = elements.count(); i--; ) { 284 for ( i = elements.count(); i--; ) {
@@ -428,7 +428,7 @@
428 function elementFromPoint( doc, mouse ) { 428 function elementFromPoint( doc, mouse ) {
429 var pointedElement = doc.$.elementFromPoint( mouse.x, mouse.y ); 429 var pointedElement = doc.$.elementFromPoint( mouse.x, mouse.y );
430 430
431 // IE9QM: from times to times it will return an empty object on scroll bar hover. (#12185) 431 // IE9QM: from times to times it will return an empty object on scroll bar hover. (http://dev.ckeditor.com/ticket/12185)
432 return pointedElement && pointedElement.nodeType ? 432 return pointedElement && pointedElement.nodeType ?
433 new CKEDITOR.dom.element( pointedElement ) : 433 new CKEDITOR.dom.element( pointedElement ) :
434 null; 434 null;
@@ -483,7 +483,7 @@
483 // If trigger is an element, neither editable nor editable's ascendant. 483 // If trigger is an element, neither editable nor editable's ascendant.
484 if ( trigger && that.editable.contains( trigger ) ) { 484 if ( trigger && that.editable.contains( trigger ) ) {
485 // Check for closest editable limit. 485 // Check for closest editable limit.
486 // Don't consider trigger as a limit as it may be nested editable (includeSelf=false) (#12009). 486 // Don't consider trigger as a limit as it may be nested editable (includeSelf=false) (http://dev.ckeditor.com/ticket/12009).
487 var limit = getClosestEditableLimit( trigger ); 487 var limit = getClosestEditableLimit( trigger );
488 488
489 // Trigger in nested editable area. 489 // Trigger in nested editable area.
@@ -730,7 +730,7 @@
730 730
731 // Consider the editable to be an element with overflow:scroll 731 // Consider the editable to be an element with overflow:scroll
732 // and non-zero scrollTop/scrollLeft value. 732 // and non-zero scrollTop/scrollLeft value.
733 // For example: divarea editable. (#9383) 733 // For example: divarea editable. (http://dev.ckeditor.com/ticket/9383)
734 styleSet.top += view.editable.scroll.top; 734 styleSet.top += view.editable.scroll.top;
735 styleSet.left += view.editable.scroll.left; 735 styleSet.left += view.editable.scroll.left;
736 } 736 }
@@ -931,7 +931,7 @@
931 var selected = editor.getSelection().getStartElement(), 931 var selected = editor.getSelection().getStartElement(),
932 limit; 932 limit;
933 933
934 // (#9833) Go down to the closest non-inline element in DOM structure 934 // (http://dev.ckeditor.com/ticket/9833) Go down to the closest non-inline element in DOM structure
935 // since inline elements don't participate in in magicline. 935 // since inline elements don't participate in in magicline.
936 selected = selected.getAscendant( DTD_BLOCK, 1 ); 936 selected = selected.getAscendant( DTD_BLOCK, 1 );
937 937
diff --git a/sources/plugins/maximize/lang/es-mx.js b/sources/plugins/maximize/lang/es-mx.js
new file mode 100644
index 0000000..f47486c
--- /dev/null
+++ b/sources/plugins/maximize/lang/es-mx.js
@@ -0,0 +1,8 @@
1/*
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-mx', {
6 maximize: 'Maximizar',
7 minimize: 'Minimizar'
8} );
diff --git a/sources/plugins/maximize/plugin.js b/sources/plugins/maximize/plugin.js
index 16967a0..fbce920 100644
--- a/sources/plugins/maximize/plugin.js
+++ b/sources/plugins/maximize/plugin.js
@@ -51,7 +51,7 @@
51 } 51 }
52 52
53 retval.inline = $element.style.cssText || ''; 53 retval.inline = $element.style.cssText || '';
54 if ( !isInsideEditor ) // Reset any external styles that might interfere. (#2474) 54 if ( !isInsideEditor ) // Reset any external styles that might interfere. (http://dev.ckeditor.com/ticket/2474)
55 $element.style.cssText = 'position: static; overflow: visible'; 55 $element.style.cssText = 'position: static; overflow: visible';
56 56
57 restoreFormStyles( data ); 57 restoreFormStyles( data );
@@ -72,14 +72,14 @@
72 if ( editor.editable().isInline() ) 72 if ( editor.editable().isInline() )
73 return; 73 return;
74 74
75 // Refresh all editor instances on the page (#5724). 75 // Refresh all editor instances on the page (http://dev.ckeditor.com/ticket/5724).
76 var all = CKEDITOR.instances; 76 var all = CKEDITOR.instances;
77 for ( var i in all ) { 77 for ( var i in all ) {
78 var one = all[ i ]; 78 var one = all[ i ];
79 if ( one.mode == 'wysiwyg' && !one.readOnly ) { 79 if ( one.mode == 'wysiwyg' && !one.readOnly ) {
80 var body = one.document.getBody(); 80 var body = one.document.getBody();
81 // Refresh 'contentEditable' otherwise 81 // Refresh 'contentEditable' otherwise
82 // DOM lifting breaks design mode. (#5560) 82 // DOM lifting breaks design mode. (http://dev.ckeditor.com/ticket/5560)
83 body.setAttribute( 'contentEditable', false ); 83 body.setAttribute( 'contentEditable', false );
84 body.setAttribute( 'contentEditable', true ); 84 body.setAttribute( 'contentEditable', true );
85 } 85 }
@@ -93,7 +93,7 @@
93 93
94 CKEDITOR.plugins.add( 'maximize', { 94 CKEDITOR.plugins.add( 'maximize', {
95 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
97 // jscs:enable maximumLineLength 97 // jscs:enable maximumLineLength
98 icons: 'maximize', // %REMOVE_LINE_CORE% 98 icons: 'maximize', // %REMOVE_LINE_CORE%
99 hidpi: true, // %REMOVE_LINE_CORE% 99 hidpi: true, // %REMOVE_LINE_CORE%
@@ -122,7 +122,7 @@
122 var savedState = CKEDITOR.TRISTATE_OFF; 122 var savedState = CKEDITOR.TRISTATE_OFF;
123 123
124 editor.addCommand( 'maximize', { 124 editor.addCommand( 'maximize', {
125 // Disabled on iOS (#8307). 125 // Disabled on iOS (http://dev.ckeditor.com/ticket/8307).
126 modes: { wysiwyg: !CKEDITOR.env.iOS, source: !CKEDITOR.env.iOS }, 126 modes: { wysiwyg: !CKEDITOR.env.iOS, source: !CKEDITOR.env.iOS },
127 readOnly: 1, 127 readOnly: 1,
128 editorFocus: false, 128 editorFocus: false,
@@ -163,7 +163,7 @@
163 163
164 // Hide scroll bars. 164 // Hide scroll bars.
165 var styles = { 165 var styles = {
166 overflow: CKEDITOR.env.webkit ? '' : 'hidden', // #6896 166 overflow: CKEDITOR.env.webkit ? '' : 'hidden', // http://dev.ckeditor.com/ticket/6896
167 width: 0, 167 width: 0,
168 height: 0 168 height: 0
169 }; 169 };
@@ -172,15 +172,15 @@
172 !CKEDITOR.env.gecko && mainDocument.getDocumentElement().setStyle( 'position', 'fixed' ); 172 !CKEDITOR.env.gecko && mainDocument.getDocumentElement().setStyle( 'position', 'fixed' );
173 !( CKEDITOR.env.gecko && CKEDITOR.env.quirks ) && mainDocument.getBody().setStyles( styles ); 173 !( CKEDITOR.env.gecko && CKEDITOR.env.quirks ) && mainDocument.getBody().setStyles( styles );
174 174
175 // Scroll to the top left (IE needs some time for it - #4923). 175 // Scroll to the top left (IE needs some time for it - http://dev.ckeditor.com/ticket/4923).
176 CKEDITOR.env.ie ? setTimeout( function() { 176 CKEDITOR.env.ie ? setTimeout( function() {
177 mainWindow.$.scrollTo( 0, 0 ); 177 mainWindow.$.scrollTo( 0, 0 );
178 }, 0 ) : mainWindow.$.scrollTo( 0, 0 ); 178 }, 0 ) : mainWindow.$.scrollTo( 0, 0 );
179 179
180 // Resize and move to top left. 180 // Resize and move to top left.
181 // Special treatment for FF Quirks (#7284) 181 // Special treatment for FF Quirks (http://dev.ckeditor.com/ticket/7284)
182 container.setStyle( 'position', CKEDITOR.env.gecko && CKEDITOR.env.quirks ? 'fixed' : 'absolute' ); 182 container.setStyle( 'position', CKEDITOR.env.gecko && CKEDITOR.env.quirks ? 'fixed' : 'absolute' );
183 container.$.offsetLeft; // SAFARI BUG: See #2066. 183 container.$.offsetLeft; // SAFARI BUG: See http://dev.ckeditor.com/ticket/2066.
184 container.setStyles( { 184 container.setStyles( {
185 // Show under floatpanels (-1) and context menu (-2). 185 // Show under floatpanels (-1) and context menu (-2).
186 'z-index': editor.config.baseFloatZIndex - 5, 186 'z-index': editor.config.baseFloatZIndex - 5,
@@ -188,19 +188,19 @@
188 top: '0px' 188 top: '0px'
189 } ); 189 } );
190 190
191 // Add cke_maximized class before resize handle since that will change things sizes (#5580) 191 // Add cke_maximized class before resize handle since that will change things sizes (http://dev.ckeditor.com/ticket/5580)
192 container.addClass( 'cke_maximized' ); 192 container.addClass( 'cke_maximized' );
193 193
194 resizeHandler(); 194 resizeHandler();
195 195
196 // Still not top left? Fix it. (Bug #174) 196 // Still not top left? Fix it. (Bug http://dev.ckeditor.com/ticket/174)
197 var offset = container.getDocumentPosition(); 197 var offset = container.getDocumentPosition();
198 container.setStyles( { 198 container.setStyles( {
199 left: ( -1 * offset.x ) + 'px', 199 left: ( -1 * offset.x ) + 'px',
200 top: ( -1 * offset.y ) + 'px' 200 top: ( -1 * offset.y ) + 'px'
201 } ); 201 } );
202 202
203 // Fixing positioning editor chrome in Firefox break design mode. (#5149) 203 // Fixing positioning editor chrome in Firefox break design mode. (http://dev.ckeditor.com/ticket/5149)
204 CKEDITOR.env.gecko && refreshCursor( editor ); 204 CKEDITOR.env.gecko && refreshCursor( editor );
205 } 205 }
206 // Restore from fullscreen if the state is on. 206 // Restore from fullscreen if the state is on.
@@ -229,7 +229,7 @@
229 // Remove cke_maximized class. 229 // Remove cke_maximized class.
230 container.removeClass( 'cke_maximized' ); 230 container.removeClass( 'cke_maximized' );
231 231
232 // Webkit requires a re-layout on editor chrome. (#6695) 232 // Webkit requires a re-layout on editor chrome. (http://dev.ckeditor.com/ticket/6695)
233 if ( CKEDITOR.env.webkit ) { 233 if ( CKEDITOR.env.webkit ) {
234 container.setStyle( 'display', 'inline' ); 234 container.setStyle( 'display', 'inline' );
235 setTimeout( function() { 235 setTimeout( function() {
@@ -250,7 +250,7 @@
250 250
251 // Toggle button label. 251 // Toggle button label.
252 var button = this.uiItems[ 0 ]; 252 var button = this.uiItems[ 0 ];
253 // Only try to change the button if it exists (#6166) 253 // Only try to change the button if it exists (http://dev.ckeditor.com/ticket/6166)
254 if ( button ) { 254 if ( button ) {
255 var label = ( this.state == CKEDITOR.TRISTATE_OFF ) ? lang.maximize.maximize : lang.maximize.minimize; 255 var label = ( this.state == CKEDITOR.TRISTATE_OFF ) ? lang.maximize.maximize : lang.maximize.minimize;
256 var buttonNode = CKEDITOR.document.getById( button._.id ); 256 var buttonNode = CKEDITOR.document.getById( button._.id );
@@ -262,7 +262,7 @@
262 // Restore selection and scroll position in editing area. 262 // Restore selection and scroll position in editing area.
263 if ( editor.mode == 'wysiwyg' ) { 263 if ( editor.mode == 'wysiwyg' ) {
264 if ( savedSelection ) { 264 if ( savedSelection ) {
265 // Fixing positioning editor chrome in Firefox break design mode. (#5149) 265 // Fixing positioning editor chrome in Firefox break design mode. (http://dev.ckeditor.com/ticket/5149)
266 CKEDITOR.env.gecko && refreshCursor( editor ); 266 CKEDITOR.env.gecko && refreshCursor( editor );
267 267
268 editor.getSelection().selectRanges( savedSelection ); 268 editor.getSelection().selectRanges( savedSelection );
@@ -294,7 +294,7 @@
294 toolbar: 'tools,10' 294 toolbar: 'tools,10'
295 } ); 295 } );
296 296
297 // Restore the command state after mode change, unless it has been changed to disabled (#6467) 297 // Restore the command state after mode change, unless it has been changed to disabled (http://dev.ckeditor.com/ticket/6467)
298 editor.on( 'mode', function() { 298 editor.on( 'mode', function() {
299 var command = editor.getCommand( 'maximize' ); 299 var command = editor.getCommand( 'maximize' );
300 command.setState( command.state == CKEDITOR.TRISTATE_DISABLED ? CKEDITOR.TRISTATE_DISABLED : savedState ); 300 command.setState( command.state == CKEDITOR.TRISTATE_DISABLED ? CKEDITOR.TRISTATE_DISABLED : savedState );
diff --git a/sources/plugins/menu/plugin.js b/sources/plugins/menu/plugin.js
index 1312a62..3596e52 100644
--- a/sources/plugins/menu/plugin.js
+++ b/sources/plugins/menu/plugin.js
@@ -102,13 +102,13 @@ CKEDITOR.plugins.add( 'menu', {
102 menuItemSource += ' onkeypress="return false;"'; 102 menuItemSource += ' onkeypress="return false;"';
103 103
104 // With Firefox, we need to force the button to redraw, otherwise it 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). 105 // will remain in the focus state. Also we some extra help to prevent dragging (http://dev.ckeditor.com/ticket/10373).
106 if ( CKEDITOR.env.gecko ) { 106 if ( CKEDITOR.env.gecko ) {
107 menuItemSource += ( ' onblur="this.style.cssText = this.style.cssText;"' + 107 menuItemSource += ( ' onblur="this.style.cssText = this.style.cssText;"' +
108 ' ondragstart="return false;"' ); 108 ' ondragstart="return false;"' );
109 } 109 }
110 110
111 // #188 111 // http://dev.ckeditor.com/ticket/188
112 menuItemSource += ' onmouseover="CKEDITOR.tools.callFunction({hoverFn},{index});"' + 112 menuItemSource += ' onmouseover="CKEDITOR.tools.callFunction({hoverFn},{index});"' +
113 ' onmouseout="CKEDITOR.tools.callFunction({moveOutFn},{index});" ' + 113 ' onmouseout="CKEDITOR.tools.callFunction({moveOutFn},{index});" ' +
114 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + 114 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) +
@@ -258,7 +258,7 @@ CKEDITOR.plugins.add( 'menu', {
258 258
259 // Show the submenu. 259 // Show the submenu.
260 // This timeout is needed to give time for the sub-menu get 260 // This timeout is needed to give time for the sub-menu get
261 // focus when JAWS is running. (#9844) 261 // focus when JAWS is running. (http://dev.ckeditor.com/ticket/9844)
262 setTimeout( function() { 262 setTimeout( function() {
263 menu.show( element, 2 ); 263 menu.show( element, 2 );
264 }, 0 ); 264 }, 0 );
@@ -274,7 +274,7 @@ CKEDITOR.plugins.add( 'menu', {
274 add: function( item ) { 274 add: function( item ) {
275 // Later we may sort the items, but Array#sort is not stable in 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 276 // some browsers, here we're forcing the original sequence with
277 // 'order' attribute if it hasn't been assigned. (#3868) 277 // 'order' attribute if it hasn't been assigned. (http://dev.ckeditor.com/ticket/3868)
278 if ( !item.order ) 278 if ( !item.order )
279 item.order = this.items.length; 279 item.order = this.items.length;
280 280
@@ -342,7 +342,7 @@ CKEDITOR.plugins.add( 'menu', {
342 keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB 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) 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 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). 345 CKEDITOR.env.ie && ( keys[ 13 ] = 'mouseup' ); // Manage ENTER, since onclick is blocked in IE (http://dev.ckeditor.com/ticket/8041).
346 346
347 element = this._.element = block.element; 347 element = this._.element = block.element;
348 348
diff --git a/sources/plugins/notification/lang/az.js b/sources/plugins/notification/lang/az.js
new file mode 100644
index 0000000..7b04ae2
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'az', {
6 closed: 'Xəbərdarlıq pəncərəsi bağlanıb'
7} );
diff --git a/sources/plugins/notification/lang/ca.js b/sources/plugins/notification/lang/ca.js
new file mode 100644
index 0000000..bcff547
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'ca', {
6 closed: 'Notificació tancada.'
7} );
diff --git a/sources/plugins/notification/lang/cs.js b/sources/plugins/notification/lang/cs.js
new file mode 100644
index 0000000..1bf1c04
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'cs', {
6 closed: 'Oznámení zavřeno.'
7} );
diff --git a/sources/plugins/notification/lang/da.js b/sources/plugins/notification/lang/da.js
new file mode 100644
index 0000000..bd3f508
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'da', {
6 closed: 'Notefikation lukket.'
7} );
diff --git a/sources/plugins/notification/lang/de-ch.js b/sources/plugins/notification/lang/de-ch.js
new file mode 100644
index 0000000..6b97661
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'de-ch', {
6 closed: 'Benachrichtigung geschlossen.'
7} );
diff --git a/sources/plugins/notification/lang/de.js b/sources/plugins/notification/lang/de.js
new file mode 100644
index 0000000..2dc45a3
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'de', {
6 closed: 'Benachrichtigung geschlossen.'
7} );
diff --git a/sources/plugins/notification/lang/en.js b/sources/plugins/notification/lang/en.js
new file mode 100644
index 0000000..4731650
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'en', {
6 closed: 'Notification closed.'
7} );
diff --git a/sources/plugins/notification/lang/eo.js b/sources/plugins/notification/lang/eo.js
new file mode 100644
index 0000000..743b8de
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'eo', {
6 closed: 'Sciigo fermita'
7} );
diff --git a/sources/plugins/notification/lang/es-mx.js b/sources/plugins/notification/lang/es-mx.js
new file mode 100644
index 0000000..e759a4b
--- /dev/null
+++ b/sources/plugins/notification/lang/es-mx.js
@@ -0,0 +1,7 @@
1/*
2Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'notification', 'es-mx', {
6 closed: 'Notificación cerrada.'
7} );
diff --git a/sources/plugins/notification/lang/es.js b/sources/plugins/notification/lang/es.js
new file mode 100644
index 0000000..a0bc477
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'es', {
6 closed: 'Notificación cerrada.'
7} );
diff --git a/sources/plugins/notification/lang/eu.js b/sources/plugins/notification/lang/eu.js
new file mode 100644
index 0000000..a2a01ee
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'eu', {
6 closed: 'Jakinarazpena itxita.'
7} );
diff --git a/sources/plugins/notification/lang/fr.js b/sources/plugins/notification/lang/fr.js
new file mode 100644
index 0000000..4ddacc4
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'fr', {
6 closed: 'Notification fermée.'
7} );
diff --git a/sources/plugins/notification/lang/gl.js b/sources/plugins/notification/lang/gl.js
new file mode 100644
index 0000000..38f90c4
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'gl', {
6 closed: 'Notificación pechada.'
7} );
diff --git a/sources/plugins/notification/lang/hr.js b/sources/plugins/notification/lang/hr.js
new file mode 100644
index 0000000..e453afc
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'hr', {
6 closed: 'Obavijest zatvorena.'
7} );
diff --git a/sources/plugins/notification/lang/hu.js b/sources/plugins/notification/lang/hu.js
new file mode 100644
index 0000000..48a846e
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'hu', {
6 closed: 'Értesítés bezárva.'
7} );
diff --git a/sources/plugins/notification/lang/id.js b/sources/plugins/notification/lang/id.js
new file mode 100644
index 0000000..d8917af
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'id', {
6 closed: 'Pemberitahuan ditutup'
7} );
diff --git a/sources/plugins/notification/lang/it.js b/sources/plugins/notification/lang/it.js
new file mode 100644
index 0000000..aa48a61
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'it', {
6 closed: 'Notifica chiusa.'
7} );
diff --git a/sources/plugins/notification/lang/ja.js b/sources/plugins/notification/lang/ja.js
new file mode 100644
index 0000000..38469b9
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'ja', {
6 closed: '通知を閉じました。'
7} );
diff --git a/sources/plugins/notification/lang/km.js b/sources/plugins/notification/lang/km.js
new file mode 100644
index 0000000..458db41
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'km', {
6 closed: 'បាន​បិទ​ការ​ផ្ដល់​ដំណឹង។'
7} );
diff --git a/sources/plugins/notification/lang/ko.js b/sources/plugins/notification/lang/ko.js
new file mode 100644
index 0000000..001f391
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'ko', {
6 closed: '알림이 닫힘.'
7} );
diff --git a/sources/plugins/notification/lang/ku.js b/sources/plugins/notification/lang/ku.js
new file mode 100644
index 0000000..e2bac2a
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'ku', {
6 closed: 'ئاگادارکەرەوەکە داخرا.'
7} );
diff --git a/sources/plugins/notification/lang/nb.js b/sources/plugins/notification/lang/nb.js
new file mode 100644
index 0000000..7a299dc
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'nb', {
6 closed: 'Varsling lukket.'
7} );
diff --git a/sources/plugins/notification/lang/nl.js b/sources/plugins/notification/lang/nl.js
new file mode 100644
index 0000000..9e6c9b1
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'nl', {
6 closed: 'Melding gesloten.'
7} );
diff --git a/sources/plugins/notification/lang/oc.js b/sources/plugins/notification/lang/oc.js
new file mode 100644
index 0000000..7d2445a
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'oc', {
6 closed: 'Notificacion tampada.'
7} );
diff --git a/sources/plugins/notification/lang/pl.js b/sources/plugins/notification/lang/pl.js
new file mode 100644
index 0000000..51a787f
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'pl', {
6 closed: 'Powiadomienie zostało zamknięte.'
7} );
diff --git a/sources/plugins/notification/lang/pt-br.js b/sources/plugins/notification/lang/pt-br.js
new file mode 100644
index 0000000..f8cd30a
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'pt-br', {
6 closed: 'Notificação fechada.'
7} );
diff --git a/sources/plugins/notification/lang/pt.js b/sources/plugins/notification/lang/pt.js
new file mode 100644
index 0000000..3a74685
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'pt', {
6 closed: 'Notificação encerrada.'
7} );
diff --git a/sources/plugins/notification/lang/ru.js b/sources/plugins/notification/lang/ru.js
new file mode 100644
index 0000000..1fa54f2
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'ru', {
6 closed: 'Уведомление закрыто'
7} );
diff --git a/sources/plugins/notification/lang/sk.js b/sources/plugins/notification/lang/sk.js
new file mode 100644
index 0000000..ec6c9c0
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'sk', {
6 closed: 'Notifikácia zatvorená.'
7} );
diff --git a/sources/plugins/notification/lang/sv.js b/sources/plugins/notification/lang/sv.js
new file mode 100644
index 0000000..f7ae2ad
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'sv', {
6 closed: 'Notifiering stängd.'
7} );
diff --git a/sources/plugins/notification/lang/tr.js b/sources/plugins/notification/lang/tr.js
new file mode 100644
index 0000000..5d6565a
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'tr', {
6 closed: 'Uyarılar kapatıldı.'
7} );
diff --git a/sources/plugins/notification/lang/ug.js b/sources/plugins/notification/lang/ug.js
new file mode 100644
index 0000000..f0d9c78
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'ug', {
6 closed: 'ئوقتۇرۇش تاقالدى.'
7} );
diff --git a/sources/plugins/notification/lang/uk.js b/sources/plugins/notification/lang/uk.js
new file mode 100644
index 0000000..aa683ae
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'uk', {
6 closed: 'Сповіщення закрито.'
7} );
diff --git a/sources/plugins/notification/lang/zh-cn.js b/sources/plugins/notification/lang/zh-cn.js
new file mode 100644
index 0000000..5eaf02e
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'zh-cn', {
6 closed: '通知已关闭'
7} );
diff --git a/sources/plugins/notification/lang/zh.js b/sources/plugins/notification/lang/zh.js
new file mode 100644
index 0000000..518b36c
--- /dev/null
+++ b/sources/plugins/notification/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( 'notification', 'zh', {
6 closed: '通知已關閉。'
7} );
diff --git a/sources/plugins/notification/plugin.js b/sources/plugins/notification/plugin.js
new file mode 100644
index 0000000..305db28
--- /dev/null
+++ b/sources/plugins/notification/plugin.js
@@ -0,0 +1,929 @@
1/**
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 "Notification" plugin.
8 *
9 */
10
11'use strict';
12
13CKEDITOR.plugins.add( 'notification', {
14 lang: 'az,ca,cs,da,de,de-ch,en,eo,es,es-mx,eu,fr,gl,hr,hu,id,it,ja,km,ko,ku,nb,nl,oc,pl,pt,pt-br,ru,sk,sv,tr,ug,uk,zh,zh-cn', // %REMOVE_LINE_CORE%
15
16 init: function( editor ) {
17 editor._.notificationArea = new Area( editor );
18
19 // Overwrites default `editor.showNotification`.
20 editor.showNotification = function( message, type, progressOrDuration ) {
21 var progress, duration;
22
23 if ( type == 'progress' ) {
24 progress = progressOrDuration;
25 } else {
26 duration = progressOrDuration;
27 }
28
29 var notification = new CKEDITOR.plugins.notification( editor, {
30 message: message,
31 type: type,
32 progress: progress,
33 duration: duration
34 } );
35
36 notification.show();
37
38 return notification;
39 };
40
41 // Close the last notification on ESC.
42 editor.on( 'key', function( evt ) {
43 if ( evt.data.keyCode == 27 ) { /* ESC */
44 var notifications = editor._.notificationArea.notifications;
45
46 if ( !notifications.length ) {
47 return;
48 }
49
50 // As long as this is not a common practice to inform screen-reader users about actions, in this case
51 // this is the best solution (unfortunately there is no standard for accessibility for notifications).
52 // Notification has an `alert` aria role what means that it does not get a focus nor is needed to be
53 // closed (unlike `alertdialog`). However notification will capture ESC key so we need to inform user
54 // why it does not do other actions.
55 say( editor.lang.notification.closed );
56
57 // Hide last.
58 notifications[ notifications.length - 1 ].hide();
59
60 evt.cancel();
61 }
62 } );
63
64 // Send the message to the screen readers.
65 function say( text ) {
66 var message = new CKEDITOR.dom.element( 'div' );
67 message.setStyles( {
68 position: 'fixed',
69 'margin-left': '-9999px'
70 } );
71 message.setAttributes( {
72 'aria-live': 'assertive',
73 'aria-atomic': 'true'
74 } );
75 message.setText( text );
76
77 CKEDITOR.document.getBody().append( message );
78
79 setTimeout( function() {
80 message.remove();
81 }, 100 );
82 }
83 }
84} );
85
86/**
87 * Notification class. Notifications are used to display short messages to the user. They might be used to show the result of
88 * asynchronous actions or information about changes in the editor content. It is recommended to use them instead of
89 * alert dialogs. They should **not** be used if a user response is required nor with dialog windows (e.g. in dialog validation).
90 *
91 * There are four types of notifications available, see the {@link #type} property.
92 *
93 * Note that the notification constructor only creates a notification instance. To show it, use the {@link #show} method:
94 *
95 * var notification = new CKEDITOR.plugins.notification( editor, { message: 'Foo' } );
96 * notification.show();
97 *
98 * You can also use the {@link CKEDITOR.editor#showNotification} method:
99 *
100 * editor.showNotification( 'Foo' );
101 *
102 * All of the notification actions: ({@link #show}, {@link #update} and {@link #hide}) fire cancelable events
103 * on the related {@link CKEDITOR.editor} instance so you can integrate editor notifications with your website notifications.
104 *
105 * Refer to the [Notifications](http://docs.ckeditor.com/#!/guide/dev_notifications) article for more information about this feature.
106 *
107 * @since 4.5
108 * @class CKEDITOR.plugins.notification
109 * @constructor Create a notification object. Call {@link #show} to show the created notification.
110 * @param {CKEDITOR.editor} editor The editor instance.
111 * @param {Object} options
112 * @param {String} options.message The message displayed in the notification.
113 * @param {String} [options.type='info'] Notification type, see {@link #type}.
114 * @param {Number} [options.progress=0] If the type is `progress` this may be a progress from 0 to 1.
115 * @param {Number} [options.duration] How long the notification will be visible, see {@link #duration}.
116 */
117function Notification( editor, options ) {
118 CKEDITOR.tools.extend( this, options, {
119 editor: editor,
120 id: 'cke-' + CKEDITOR.tools.getUniqueId(),
121 area: editor._.notificationArea
122 } );
123
124 if ( !options.type ) {
125 this.type = 'info';
126 }
127
128 this.element = this._createElement();
129
130 // Don't allow dragging on notification (http://dev.ckeditor.com/ticket/13184).
131 editor.plugins.clipboard && CKEDITOR.plugins.clipboard.preventDefaultDropOnElement( this.element );
132}
133
134/**
135 * The editor instance.
136 *
137 * @readonly
138 * @property {CKEDITOR.editor} editor
139 */
140
141/**
142 * Message displayed in the notification.
143 *
144 * @readonly
145 * @property {String} message
146 */
147
148/**
149 * Notification type. There are four types available:
150 *
151 * * `info` (default) &ndash; Information for the user (e.g. "File is uploading.", "ACF modified content."),
152 * * `warning` &ndash; Warning or error message (e.g. "This type of file is not supported.",
153 * "You cannot paste the script."),
154 * * `success` &ndash; Information that an operation finished successfully (e.g. "File uploaded.", "Data imported.").
155 * * `progress` &ndash; Information about the progress of an operation. When the operation is done, the notification
156 * type should be changed to `success`.
157 *
158 * @readonly
159 * @property {String} type
160 */
161
162/**
163 * If the notification {@link #type} is `'progress'`, this is the progress from `0` to `1`.
164 *
165 * @readonly
166 * @property {Number} progress
167 */
168
169/**
170 * Notification duration. Determines after how many milliseconds the notification should close automatically.
171 * `0` means that the notification will not close automatically and that the user needs to close it manually.
172 * The default value for `warning` and `progress` notifications is `0`. For `info` and `success` the value can
173 * either be set through the {@link CKEDITOR.config#notification_duration} configuration option or equals `5000`
174 * if the configuration option is not set.
175 *
176 * @readonly
177 * @property {Number} duration
178 */
179
180/**
181 * Unique notification ID.
182 *
183 * @readonly
184 * @property {Number} id
185 */
186
187/**
188 * Notification DOM element. There is one element per notification. It is created when the notification is created,
189 * even if it is not shown. If the notification is hidden, the element is detached from the document but not deleted.
190 * It will be reused if the notification is shown again.
191 *
192 * @readonly
193 * @property {CKEDITOR.dom.element} element
194 */
195
196/**
197 * {@link CKEDITOR.plugins.notification.area Notification area} reference.
198 *
199 * @readonly
200 * @property {CKEDITOR.plugins.notification.area} area
201 */
202
203Notification.prototype = {
204 /**
205 * Adds the notification element to the notification area. The notification will be hidden automatically if
206 * {@link #duration} is set.
207 *
208 * Fires the {@link CKEDITOR.editor#notificationShow} event.
209 */
210 show: function() {
211 if ( this.editor.fire( 'notificationShow', { notification: this } ) === false ) {
212 return;
213 }
214
215 this.area.add( this );
216
217 this._hideAfterTimeout();
218 },
219
220 /**
221 * Updates the notification object and element.
222 *
223 * Fires the {@link CKEDITOR.editor#notificationUpdate} event.
224 *
225 * @param {Object} options
226 * @param {String} [options.message] {@link #message}
227 * @param {String} [options.type] {@link #type}
228 * @param {Number} [options.progress] {@link #progress}
229 * @param {Number} [options.duration] {@link #duration}
230 * @param {Boolean} [options.important=false] If the update is important, the notification will be shown
231 * if it was hidden and read by screen readers.
232 */
233 update: function( options ) {
234 var show = true;
235
236 if ( this.editor.fire( 'notificationUpdate', { notification: this, options: options } ) === false ) {
237 // The idea of cancelable event is to let user create his own way of displaying notification, so if
238 // `notificationUpdate` event will be canceled there will be no interaction with notification area, but on
239 // the other hand the logic should work anyway so object will be updated (including `element` property).
240 // Note: we can safely update the element's attributes below, because this element is created inside
241 // the constructor. If the notificatinShow event was canceled as well, the element is detached from DOM.
242 show = false;
243 }
244
245 var element = this.element,
246 messageElement = element.findOne( '.cke_notification_message' ),
247 progressElement = element.findOne( '.cke_notification_progress' ),
248 type = options.type;
249
250 element.removeAttribute( 'role' );
251
252 // Change type to progress if `options.progress` is set.
253 if ( options.progress && this.type != 'progress' ) {
254 type = 'progress';
255 }
256
257 if ( type ) {
258 element.removeClass( this._getClass() );
259 element.removeAttribute( 'aria-label' );
260
261 this.type = type;
262
263 element.addClass( this._getClass() );
264 element.setAttribute( 'aria-label', this.type );
265
266 if ( this.type == 'progress' && !progressElement ) {
267 progressElement = this._createProgressElement();
268 progressElement.insertBefore( messageElement );
269 } else if ( this.type != 'progress' && progressElement ) {
270 progressElement.remove();
271 }
272 }
273
274 if ( options.message !== undefined ) {
275 this.message = options.message;
276 messageElement.setHtml( this.message );
277 }
278
279 if ( options.progress !== undefined ) {
280 this.progress = options.progress;
281
282 if ( progressElement ) {
283 progressElement.setStyle( 'width', this._getPercentageProgress() );
284 }
285 }
286
287 if ( show && options.important ) {
288 element.setAttribute( 'role', 'alert' );
289
290 if ( !this.isVisible() ) {
291 this.area.add( this );
292 }
293 }
294
295 // Overwrite even if it is undefined.
296 this.duration = options.duration;
297
298 this._hideAfterTimeout();
299 },
300
301 /**
302 * Removes the notification element from the notification area.
303 *
304 * Fires the {@link CKEDITOR.editor#notificationHide} event.
305 */
306 hide: function() {
307 if ( this.editor.fire( 'notificationHide', { notification: this } ) === false ) {
308 return;
309 }
310
311 this.area.remove( this );
312 },
313
314 /**
315 * Returns `true` if the notification is in the notification area.
316 *
317 * @returns {Boolean} `true` if the notification is in the notification area.
318 */
319 isVisible: function() {
320 return CKEDITOR.tools.indexOf( this.area.notifications, this ) >= 0;
321 },
322
323 /**
324 * Creates the notification DOM element.
325 *
326 * @private
327 * @returns {CKEDITOR.dom.element} Notification DOM element.
328 */
329 _createElement: function() {
330 var notification = this,
331 notificationElement, notificationMessageElement, notificationCloseElement,
332 close = this.editor.lang.common.close;
333
334 notificationElement = new CKEDITOR.dom.element( 'div' );
335 notificationElement.addClass( 'cke_notification' );
336 notificationElement.addClass( this._getClass() );
337 notificationElement.setAttributes( {
338 id: this.id,
339 role: 'alert',
340 'aria-label': this.type
341 } );
342
343 if ( this.type == 'progress' )
344 notificationElement.append( this._createProgressElement() );
345
346 notificationMessageElement = new CKEDITOR.dom.element( 'p' );
347 notificationMessageElement.addClass( 'cke_notification_message' );
348 notificationMessageElement.setHtml( this.message );
349 notificationElement.append( notificationMessageElement );
350
351 notificationCloseElement = CKEDITOR.dom.element.createFromHtml(
352 '<a class="cke_notification_close" href="javascript:void(0)" title="' + close + '" role="button" tabindex="-1">' +
353 '<span class="cke_label">X</span>' +
354 '</a>' );
355 notificationElement.append( notificationCloseElement );
356
357 notificationCloseElement.on( 'click', function() {
358 // Focus editor on close (http://dev.ckeditor.com/ticket/12865)
359 notification.editor.focus();
360
361 notification.hide();
362 } );
363
364 return notificationElement;
365 },
366
367 /**
368 * Gets the notification CSS class.
369 *
370 * @private
371 * @returns {String} Notification CSS class.
372 */
373 _getClass: function() {
374 return ( this.type == 'progress' ) ?
375 'cke_notification_info' :
376 ( 'cke_notification_' + this.type );
377 },
378
379 /**
380 * Creates a progress element for the notification element.
381 *
382 * @private
383 * @returns {CKEDITOR.dom.element} Progress element for the notification element.
384 */
385 _createProgressElement: function() {
386 var element = new CKEDITOR.dom.element( 'span' );
387 element.addClass( 'cke_notification_progress' );
388 element.setStyle( 'width', this._getPercentageProgress() );
389 return element;
390 },
391
392 /**
393 * Gets the progress as a percentage (ex. `0.3` -> `30%`).
394 *
395 * @private
396 * @returns {String} Progress as a percentage.
397 */
398 _getPercentageProgress: function() {
399 return Math.round( ( this.progress || 0 ) * 100 ) + '%';
400 },
401
402 /**
403 * Hides the notification after a timeout.
404 *
405 * @private
406 */
407 _hideAfterTimeout: function() {
408 var notification = this,
409 duration;
410
411 if ( this._hideTimeoutId ) {
412 clearTimeout( this._hideTimeoutId );
413 }
414
415 if ( typeof this.duration == 'number' ) {
416 duration = this.duration;
417 } else if ( this.type == 'info' || this.type == 'success' ) {
418 duration = ( typeof this.editor.config.notification_duration == 'number' ) ?
419 this.editor.config.notification_duration :
420 5000;
421 }
422
423 if ( duration ) {
424 notification._hideTimeoutId = setTimeout( function() {
425 notification.hide();
426 }, duration );
427 }
428 }
429};
430
431/**
432 * Notification area is an area where all notifications are put. The area is laid out dynamically.
433 * When the first notification is added, the area is shown and all listeners are added.
434 * When the last notification is removed, the area is hidden and all listeners are removed.
435 *
436 * @since 4.5
437 * @private
438 * @class CKEDITOR.plugins.notification.area
439 * @constructor
440 * @param {CKEDITOR.editor} editor The editor instance.
441 */
442function Area( editor ) {
443 var that = this;
444
445 this.editor = editor;
446 this.notifications = [];
447 this.element = this._createElement();
448 this._uiBuffer = CKEDITOR.tools.eventsBuffer( 10, this._layout, this );
449 this._changeBuffer = CKEDITOR.tools.eventsBuffer( 500, this._layout, this );
450
451 editor.on( 'destroy', function() {
452 that._removeListeners();
453 that.element.remove();
454 } );
455}
456
457/**
458 * The editor instance.
459 *
460 * @readonly
461 * @property {CKEDITOR.editor} editor
462 */
463
464/**
465 * The array of added notifications.
466 *
467 * @readonly
468 * @property {Array} notifications
469 */
470
471/**
472 * Notification area DOM element. This element is created when the area object is created. It will be attached to the document
473 * when the first notification is added and removed when the last notification is removed.
474 *
475 * @readonly
476 * @property {CKEDITOR.dom.element} element
477 */
478
479/**
480 * Notification width. Cached for performance reasons.
481 *
482 * @private
483 * @property {CKEDITOR.dom.element} _notificationWidth
484 */
485
486/**
487 * Notification margin. Cached for performance reasons.
488 *
489 * @private
490 * @property {CKEDITOR.dom.element} _notificationMargin
491 */
492
493/**
494 * Event buffer object for UI events to optimize performance.
495 *
496 * @private
497 * @property {Object} _uiBuffer
498 */
499
500/**
501 * Event buffer object for editor change events to optimize performance.
502 *
503 * @private
504 * @property {Object} _changeBuffer
505 */
506
507Area.prototype = {
508 /**
509 * Adds the notification to the notification area. If it is the first notification, the area will also be attached to
510 * the document and listeners will be attached.
511 *
512 * Note that the proper way to show a notification is to call the {@link CKEDITOR.plugins.notification#show} method.
513 *
514 * @param {CKEDITOR.plugins.notification} notification Notification to add.
515 */
516 add: function( notification ) {
517 this.notifications.push( notification );
518
519 this.element.append( notification.element );
520
521 if ( this.element.getChildCount() == 1 ) {
522 CKEDITOR.document.getBody().append( this.element );
523 this._attachListeners();
524 }
525
526 this._layout();
527 },
528
529 /**
530 * Removes the notification from the notification area. If it is the last notification, the area will also be
531 * detached from the document and listeners will be detached.
532 *
533 * Note that the proper way to hide a notification is to call the {@link CKEDITOR.plugins.notification#hide} method.
534 *
535 * @param {CKEDITOR.plugins.notification} notification Notification to remove.
536 */
537 remove: function( notification ) {
538 var i = CKEDITOR.tools.indexOf( this.notifications, notification );
539
540 if ( i < 0 ) {
541 return;
542 }
543
544 this.notifications.splice( i, 1 );
545
546 notification.element.remove();
547
548 if ( !this.element.getChildCount() ) {
549 this._removeListeners();
550 this.element.remove();
551 }
552 },
553
554 /**
555 * Creates the notification area element.
556 *
557 * @private
558 * @returns {CKEDITOR.dom.element} Notification area element.
559 */
560 _createElement: function() {
561 var editor = this.editor,
562 config = editor.config,
563 notificationArea = new CKEDITOR.dom.element( 'div' );
564
565 notificationArea.addClass( 'cke_notifications_area' );
566 notificationArea.setAttribute( 'id', 'cke_notifications_area_' + editor.name );
567 notificationArea.setStyle( 'z-index', config.baseFloatZIndex - 2 );
568
569 return notificationArea;
570 },
571
572 /**
573 * Attaches listeners to the notification area.
574 *
575 * @private
576 */
577 _attachListeners: function() {
578 var win = CKEDITOR.document.getWindow(),
579 editor = this.editor;
580
581 win.on( 'scroll', this._uiBuffer.input );
582 win.on( 'resize', this._uiBuffer.input );
583 editor.on( 'change', this._changeBuffer.input );
584 editor.on( 'floatingSpaceLayout', this._layout, this, null, 20 );
585 editor.on( 'blur', this._layout, this, null, 20 );
586 },
587
588 /**
589 * Detaches listeners from the notification area.
590 *
591 * @private
592 */
593 _removeListeners: function() {
594 var win = CKEDITOR.document.getWindow(),
595 editor = this.editor;
596
597 win.removeListener( 'scroll', this._uiBuffer.input );
598 win.removeListener( 'resize', this._uiBuffer.input );
599 editor.removeListener( 'change', this._changeBuffer.input );
600 editor.removeListener( 'floatingSpaceLayout', this._layout );
601 editor.removeListener( 'blur', this._layout );
602 },
603
604 /**
605 * Sets the position of the notification area based on the editor content, toolbar as well as
606 * viewport position and dimensions.
607 *
608 * @private
609 */
610 _layout: function() {
611 var area = this.element,
612 editor = this.editor,
613 contentsRect = editor.ui.contentsElement.getClientRect(),
614 contentsPos = editor.ui.contentsElement.getDocumentPosition(),
615 top,
616 topRect,
617 areaRect = area.getClientRect(),
618 notification,
619 notificationWidth = this._notificationWidth,
620 notificationMargin = this._notificationMargin,
621 win = CKEDITOR.document.getWindow(),
622 scrollPos = win.getScrollPosition(),
623 viewRect = win.getViewPaneSize(),
624 body = CKEDITOR.document.getBody(),
625 bodyPos = body.getDocumentPosition(),
626 cssLength = CKEDITOR.tools.cssLength;
627
628 // Cache for optimization
629 if ( !notificationWidth || !notificationMargin ) {
630 notification = this.element.getChild( 0 );
631 notificationWidth = this._notificationWidth = notification.getClientRect().width;
632 notificationMargin = this._notificationMargin =
633 parseInt( notification.getComputedStyle( 'margin-left' ), 10 ) +
634 parseInt( notification.getComputedStyle( 'margin-right' ), 10 );
635 }
636
637 // Check if toolbar exist and if so, then assign values to it (#491).
638 if ( editor.toolbar ) {
639 top = editor.ui.space( 'top' );
640 topRect = top.getClientRect();
641 }
642
643
644 // --------------------------------------- Horizontal layout ----------------------------------------
645
646 // +---Viewport-------------------------------+ +---Viewport-------------------------------+
647 // | | | |
648 // | +---Toolbar----------------------------+ | | +---Content----------------------------+ |
649 // | | | | | | | |
650 // | +---Content----------------------------+ | | | | |
651 // | | | | | +---Toolbar----------------------+ | |
652 // | | +------Notification------+ | | | | | | |
653 // | | | | OR | +--------------------------------+ | |
654 // | | | | | | | |
655 // | | | | | | +------Notification------+ | |
656 // | | | | | | | |
657 // | | | | | | | |
658 // | +--------------------------------------+ | | +--------------------------------------+ |
659 // +------------------------------------------+ +------------------------------------------+
660 if ( top && top.isVisible() &&
661 topRect.bottom > contentsRect.top &&
662 topRect.bottom < contentsRect.bottom - areaRect.height ) {
663 setBelowToolbar();
664
665 // +---Viewport-------------------------------+
666 // | |
667 // | +---Content----------------------------+ |
668 // | | | |
669 // | | +------Notification------+ | |
670 // | | | |
671 // | | | |
672 // | | | |
673 // | +--------------------------------------+ |
674 // | |
675 // +------------------------------------------+
676 } else if ( contentsRect.top > 0 ) {
677 setTopStandard();
678
679 // +---Content----------------------------+
680 // | |
681 // +---Viewport-------------------------------+
682 // | | | |
683 // | | +------Notification------+ | |
684 // | | | |
685 // | | | |
686 // | | | |
687 // | +--------------------------------------+ |
688 // | |
689 // +------------------------------------------+
690 } else if ( contentsPos.y + contentsRect.height - areaRect.height > scrollPos.y ) {
691 setTopFixed();
692
693 // +---Content----------------------------+ +---Content----------------------------+
694 // | | | |
695 // | | | |
696 // | | | +------Notification------+ |
697 // | | | |
698 // | | OR +--------------------------------------+
699 // +---Viewport-------------------------------+
700 // | | +------Notification------+ | | +---Viewport-------------------------------+
701 // | | | | | |
702 // | +--------------------------------------+ | | |
703 // | | | |
704 // +------------------------------------------+ +------------------------------------------+
705 } else {
706 setBottom();
707 }
708
709 function setTopStandard() {
710 area.setStyles( {
711 position: 'absolute',
712 top: cssLength( contentsPos.y )
713 } );
714 }
715
716 function setBelowToolbar() {
717 area.setStyles( {
718 position: 'fixed',
719 top: cssLength( topRect.bottom )
720 } );
721 }
722
723 function setTopFixed() {
724 area.setStyles( {
725 position: 'fixed',
726 top: 0
727 } );
728 }
729
730 function setBottom() {
731 area.setStyles( {
732 position: 'absolute',
733 top: cssLength( contentsPos.y + contentsRect.height - areaRect.height )
734 } );
735 }
736
737 // ---------------------------------------- Vertical layout -----------------------------------------
738
739 var leftBase = area.getStyle( 'position' ) == 'fixed' ?
740 contentsRect.left :
741 body.getComputedStyle( 'position' ) != 'static' ? contentsPos.x - bodyPos.x : contentsPos.x;
742
743 // Content is narrower than notification
744 if ( contentsRect.width < notificationWidth + notificationMargin ) {
745
746 // +---Viewport-------------------------------+
747 // | |
748 // | +---Content------------+ |
749 // | | | |
750 // | +------Notification------+ | |
751 // | | | |
752 // | +----------------------+ |
753 // | |
754 // +------------------------------------------+
755 if ( contentsPos.x + notificationWidth + notificationMargin > scrollPos.x + viewRect.width ) {
756 setRight();
757
758 // +---Viewport-------------------------------+ +---Viewport--------------------------+
759 // | | | |
760 // | +---Content------------+ | +---Content------------+ |
761 // | | | | | | | |
762 // | | +------Notification------+ | OR | +------Notification------+ |
763 // | | | | | | | |
764 // | +----------------------+ | +----------------------+ |
765 // | | | |
766 // +------------------------------------------+ +-------------------------------------+
767 } else {
768 setLeft();
769 }
770
771 // Content is wider than notification.
772 } else {
773
774 // +--+Viewport+------------------------+
775 // | |
776 // | +---Content-----------------------------------------+
777 // | | | |
778 // | | +-----+Notification+-----+ |
779 // | | | |
780 // | | | |
781 // | | | |
782 // | +---------------------------------------------------+
783 // | |
784 // +------------------------------------+
785 if ( contentsPos.x + notificationWidth + notificationMargin > scrollPos.x + viewRect.width ) {
786 setLeft();
787
788 // +---Viewport-------------------------+
789 // | |
790 // | +---Content----------------------------------------------+
791 // | | | |
792 // | | +------Notification------+ | |
793 // | | | |
794 // | | | |
795 // | +--------------------------------------------------------+
796 // | |
797 // +------------------------------------+
798 } else if ( contentsPos.x + contentsRect.width / 2 +
799 notificationWidth / 2 + notificationMargin > scrollPos.x + viewRect.width ) {
800 setRightFixed();
801
802 // +---Viewport-------------------------+
803 // | |
804 // +---Content----------------------------+ |
805 // | | | |
806 // | +------Notification------+ | |
807 // | | | |
808 // | | | |
809 // +--------------------------------------+ |
810 // | |
811 // +------------------------------------+
812 } else if ( contentsRect.left + contentsRect.width - notificationWidth - notificationMargin < 0 ) {
813 setRight();
814
815 // +---Viewport-------------------------+
816 // | |
817 // +---Content---------------------------------------------+ |
818 // | | | |
819 // | | +------Notification------+ | |
820 // | | | |
821 // | | | |
822 // +-------------------------------------------------------+ |
823 // | |
824 // +------------------------------------+
825 } else if ( contentsRect.left + contentsRect.width / 2 - notificationWidth / 2 < 0 ) {
826 setLeftFixed();
827
828 // +---Viewport-------------------------+
829 // | |
830 // | +---Content----------------------+ |
831 // | | | |
832 // | | +-----Notification-----+ | |
833 // | | | |
834 // | | | |
835 // | +--------------------------------+ |
836 // | |
837 // +------------------------------------+
838 } else {
839 setCenter();
840 }
841 }
842
843 function setLeft() {
844 area.setStyle( 'left', cssLength( leftBase ) );
845 }
846
847 function setLeftFixed() {
848 area.setStyle( 'left', cssLength( leftBase - contentsPos.x + scrollPos.x ) );
849 }
850
851 function setCenter() {
852 area.setStyle( 'left', cssLength( leftBase + contentsRect.width / 2 - notificationWidth / 2 - notificationMargin / 2 ) );
853 }
854
855 function setRight() {
856 area.setStyle( 'left', cssLength( leftBase + contentsRect.width - notificationWidth - notificationMargin ) );
857 }
858
859 function setRightFixed() {
860 area.setStyle( 'left', cssLength( leftBase - contentsPos.x + scrollPos.x + viewRect.width -
861 notificationWidth - notificationMargin ) );
862 }
863 }
864};
865
866CKEDITOR.plugins.notification = Notification;
867
868/**
869 * After how many milliseconds the notification of the `info` and `success`
870 * {@link CKEDITOR.plugins.notification#type type} should close automatically.
871 * `0` means that notifications will not close automatically.
872 * Note that `warning` and `progress` notifications will never close automatically.
873 *
874 * Refer to the [Notifications](http://docs.ckeditor.com/#!/guide/dev_notifications) article
875 * for more information about this feature.
876 *
877 * @since 4.5
878 * @cfg {Number} [notification_duration=5000]
879 * @member CKEDITOR.config
880 */
881
882/**
883 * Event fired when the {@link CKEDITOR.plugins.notification#show} method is called, before the
884 * notification is shown. If this event is canceled, the notification will not be shown.
885 *
886 * Using this event allows you to fully customize how a notification will be shown. It may be used to integrate
887 * the CKEditor notification system with your web page notifications.
888 *
889 * @since 4.5
890 * @event notificationShow
891 * @member CKEDITOR.editor
892 * @param data
893 * @param {CKEDITOR.plugins.notification} data.notification Notification which will be shown.
894 * @param {CKEDITOR.editor} editor The editor instance.
895 */
896
897/**
898 * Event fired when the {@link CKEDITOR.plugins.notification#update} method is called, before the
899 * notification is updated. If this event is canceled, the notification will not be shown even if the update was important,
900 * but the object will be updated anyway. Note that canceling this event does not prevent updating {@link #element}
901 * attributes, but if {@link #notificationShow} was canceled as well, this element is detached from the DOM.
902 *
903 * Using this event allows you to fully customize how a notification will be updated. It may be used to integrate
904 * the CKEditor notification system with your web page notifications.
905 *
906 * @since 4.5
907 * @event notificationUpdate
908 * @member CKEDITOR.editor
909 * @param data
910 * @param {CKEDITOR.plugins.notification} data.notification Notification which will be updated.
911 * Note that it contains the data that has not been updated yet.
912 * @param {Object} data.options Update options, see {@link CKEDITOR.plugins.notification#update}.
913 * @param {CKEDITOR.editor} editor The editor instance.
914 */
915
916/**
917 * Event fired when the {@link CKEDITOR.plugins.notification#hide} method is called, before the
918 * notification is hidden. If this event is canceled, the notification will not be hidden.
919 *
920 * Using this event allows you to fully customize how a notification will be hidden. It may be used to integrate
921 * the CKEditor notification system with your web page notifications.
922 *
923 * @since 4.5
924 * @event notificationHide
925 * @member CKEDITOR.editor
926 * @param data
927 * @param {CKEDITOR.plugins.notification} data.notification Notification which will be hidden.
928 * @param {CKEDITOR.editor} editor The editor instance.
929 */
diff --git a/sources/plugins/panel/plugin.js b/sources/plugins/panel/plugin.js
index b64c540..816ccc4 100644
--- a/sources/plugins/panel/plugin.js
+++ b/sources/plugins/panel/plugin.js
@@ -99,7 +99,7 @@
99 parentDiv = iframe.getParent(), 99 parentDiv = iframe.getParent(),
100 doc = iframe.getFrameDocument(); 100 doc = iframe.getFrameDocument();
101 101
102 // Make it scrollable on iOS. (#8308) 102 // Make it scrollable on iOS. (http://dev.ckeditor.com/ticket/8308)
103 CKEDITOR.env.iOS && parentDiv.setStyles( { 103 CKEDITOR.env.iOS && parentDiv.setStyles( {
104 'overflow': 'scroll', 104 'overflow': 'scroll',
105 '-webkit-overflow-scrolling': 'touch' 105 '-webkit-overflow-scrolling': 'touch'
@@ -121,7 +121,7 @@
121 // Register the CKEDITOR global. 121 // Register the CKEDITOR global.
122 win.$.CKEDITOR = CKEDITOR; 122 win.$.CKEDITOR = CKEDITOR;
123 123
124 // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (#4534). 124 // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (http://dev.ckeditor.com/ticket/4534).
125 doc.on( 'keydown', function( evt ) { 125 doc.on( 'keydown', function( evt ) {
126 var keystroke = evt.data.getKeystroke(), 126 var keystroke = evt.data.getKeystroke(),
127 dir = this.document.getById( this.id ).getAttribute( 'dir' ); 127 dir = this.document.getById( this.id ).getAttribute( 'dir' );
@@ -219,7 +219,7 @@
219 current = this._.currentBlock; 219 current = this._.currentBlock;
220 220
221 // ARIA role works better in IE on the body element, while on the iframe 221 // ARIA role works better in IE on the body element, while on the iframe
222 // for FF. (#8864) 222 // for FF. (http://dev.ckeditor.com/ticket/8864)
223 var holder = !this.forceIFrame || CKEDITOR.env.ie ? this._.holder : this.document.getById( this.id + '_frame' ); 223 var holder = !this.forceIFrame || CKEDITOR.env.ie ? this._.holder : this.document.getById( this.id + '_frame' );
224 224
225 if ( current ) 225 if ( current )
@@ -300,13 +300,68 @@
300 var links = this.element.getElementsByTag( 'a' ); 300 var links = this.element.getElementsByTag( 'a' );
301 var item = links.getItem( this._.focusIndex = index ); 301 var item = links.getItem( this._.focusIndex = index );
302 302
303 // Safari need focus on the iframe window first(#3389), but we need 303 // Safari need focus on the iframe window first(http://dev.ckeditor.com/ticket/3389), but we need
304 // lock the blur to avoid hiding the panel. 304 // lock the blur to avoid hiding the panel.
305 if ( CKEDITOR.env.webkit ) 305 if ( CKEDITOR.env.webkit )
306 item.getDocument().getWindow().focus(); 306 item.getDocument().getWindow().focus();
307 item.focus(); 307 item.focus();
308 308
309 this.onMark && this.onMark( item ); 309 this.onMark && this.onMark( item );
310 },
311
312 /**
313 * Marks the first visible item or the one whose `aria-selected` attribute is set to `true`.
314 * The latter has priority over the former.
315 *
316 * @private
317 * @param beforeMark function to be executed just before marking.
318 * Used in cases when any preparatory cleanup (like unmarking all items) would simultaneously
319 * destroy the information that is needed to determine the focused item.
320 */
321 markFirstDisplayed: function( beforeMark ) {
322 var notDisplayed = function( element ) {
323 return element.type == CKEDITOR.NODE_ELEMENT && element.getStyle( 'display' ) == 'none';
324 },
325 links = this._.getItems(),
326 item, focused;
327
328 for ( var i = links.count() - 1; i >= 0; i-- ) {
329 item = links.getItem( i );
330
331 if ( !item.getAscendant( notDisplayed ) ) {
332 focused = item;
333 this._.focusIndex = i;
334 }
335
336 if ( item.getAttribute( 'aria-selected' ) == 'true' ) {
337 focused = item;
338 this._.focusIndex = i;
339 break;
340 }
341 }
342
343 if ( !focused ) {
344 return;
345 }
346
347 if ( beforeMark ) {
348 beforeMark();
349 }
350
351 if ( CKEDITOR.env.webkit )
352 focused.getDocument().getWindow().focus();
353 focused.focus();
354
355 this.onMark && this.onMark( focused );
356 },
357
358 /**
359 * Returns a `CKEDITOR.dom.nodeList` of block items.
360 *
361 * @returns {*|CKEDITOR.dom.nodeList}
362 */
363 getItems: function() {
364 return this.element.getElementsByTag( 'a' );
310 } 365 }
311 }, 366 },
312 367
@@ -340,7 +395,7 @@
340 } 395 }
341 } 396 }
342 397
343 // If no link was found, cycle and restart from the top. (#11125) 398 // If no link was found, cycle and restart from the top. (http://dev.ckeditor.com/ticket/11125)
344 if ( !link && !noCycle ) { 399 if ( !link && !noCycle ) {
345 this._.focusIndex = -1; 400 this._.focusIndex = -1;
346 return this.onKeyDown( keystroke, 1 ); 401 return this.onKeyDown( keystroke, 1 );
@@ -364,11 +419,11 @@
364 } 419 }
365 420
366 // Make sure link is null when the loop ends and nothing was 421 // Make sure link is null when the loop ends and nothing was
367 // found (#11125). 422 // found (http://dev.ckeditor.com/ticket/11125).
368 link = null; 423 link = null;
369 } 424 }
370 425
371 // If no link was found, cycle and restart from the bottom. (#11125) 426 // If no link was found, cycle and restart from the bottom. (http://dev.ckeditor.com/ticket/11125)
372 if ( !link && !noCycle ) { 427 if ( !link && !noCycle ) {
373 this._.focusIndex = links.count(); 428 this._.focusIndex = links.count();
374 return this.onKeyDown( keystroke, 1 ); 429 return this.onKeyDown( keystroke, 1 );
diff --git a/sources/plugins/popup/plugin.js b/sources/plugins/popup/plugin.js
index 352d239..89b6201 100644
--- a/sources/plugins/popup/plugin.js
+++ b/sources/plugins/popup/plugin.js
@@ -48,7 +48,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, {
48 return false; 48 return false;
49 49
50 try { 50 try {
51 // Chrome is problematic with moveTo/resizeTo, but it's not really needed here (#8855). 51 // Chrome is problematic with moveTo/resizeTo, but it's not really needed here (http://dev.ckeditor.com/ticket/8855).
52 var ua = navigator.userAgent.toLowerCase(); 52 var ua = navigator.userAgent.toLowerCase();
53 if ( ua.indexOf( ' chrome/' ) == -1 ) { 53 if ( ua.indexOf( ' chrome/' ) == -1 ) {
54 popupWindow.moveTo( left, top ); 54 popupWindow.moveTo( left, top );
diff --git a/sources/plugins/removeformat/lang/es-mx.js b/sources/plugins/removeformat/lang/es-mx.js
new file mode 100644
index 0000000..dda30c5
--- /dev/null
+++ b/sources/plugins/removeformat/lang/es-mx.js
@@ -0,0 +1,7 @@
1/*
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-mx', {
6 toolbar: 'Remover formato'
7} );
diff --git a/sources/plugins/removeformat/plugin.js b/sources/plugins/removeformat/plugin.js
index 20f7ecb..94360ee 100644
--- a/sources/plugins/removeformat/plugin.js
+++ b/sources/plugins/removeformat/plugin.js
@@ -5,7 +5,7 @@
5 5
6CKEDITOR.plugins.add( 'removeformat', { 6CKEDITOR.plugins.add( 'removeformat', {
7 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
9 // jscs:enable maximumLineLength 9 // jscs:enable maximumLineLength
10 icons: 'removeformat', // %REMOVE_LINE_CORE% 10 icons: 'removeformat', // %REMOVE_LINE_CORE%
11 hidpi: true, // %REMOVE_LINE_CORE% 11 hidpi: true, // %REMOVE_LINE_CORE%
@@ -120,7 +120,7 @@ CKEDITOR.plugins.removeformat = {
120 } 120 }
121 121
122 // The selection path may not changed, but we should force a selection 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) 123 // change event to refresh command states, due to the above attribution change. (http://dev.ckeditor.com/ticket/9238)
124 editor.forceNextSelectionCheck(); 124 editor.forceNextSelectionCheck();
125 editor.getSelection().selectRanges( ranges ); 125 editor.getSelection().selectRanges( ranges );
126 } 126 }
diff --git a/sources/plugins/resize/plugin.js b/sources/plugins/resize/plugin.js
index 095ee12..123dd2d 100644
--- a/sources/plugins/resize/plugin.js
+++ b/sources/plugins/resize/plugin.js
@@ -19,7 +19,7 @@ CKEDITOR.plugins.add( 'resize', {
19 if ( resizeVertical ) 19 if ( resizeVertical )
20 height = Math.max( config.resize_minHeight, Math.min( internalHeight, config.resize_maxHeight ) ); 20 height = Math.max( config.resize_minHeight, Math.min( internalHeight, config.resize_maxHeight ) );
21 21
22 // DO NOT impose fixed size with single direction resize. (#6308) 22 // DO NOT impose fixed size with single direction resize. (http://dev.ckeditor.com/ticket/6308)
23 editor.resize( resizeHorizontal ? width : null, height ); 23 editor.resize( resizeHorizontal ? width : null, height );
24 } 24 }
25 25
@@ -37,7 +37,7 @@ CKEDITOR.plugins.add( 'resize', {
37 var spaceId = editor.ui.spaceId( 'resizer' ); 37 var spaceId = editor.ui.spaceId( 'resizer' );
38 38
39 // Resize in the same direction of chrome, 39 // Resize in the same direction of chrome,
40 // which is identical to dir of editor element. (#6614) 40 // which is identical to dir of editor element. (http://dev.ckeditor.com/ticket/6614)
41 var resizeDir = editor.element ? editor.element.getDirection( 1 ) : 'ltr'; 41 var resizeDir = editor.element ? editor.element.getDirection( 1 ) : 'ltr';
42 42
43 !config.resize_dir && ( config.resize_dir = 'vertical' ); 43 !config.resize_dir && ( config.resize_dir = 'vertical' );
diff --git a/sources/plugins/richcombo/plugin.js b/sources/plugins/richcombo/plugin.js
index 231a7c7..15b04b1 100644
--- a/sources/plugins/richcombo/plugin.js
+++ b/sources/plugins/richcombo/plugin.js
@@ -37,7 +37,7 @@ CKEDITOR.plugins.add( 'richcombo', {
37 template += 37 template +=
38 ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event,this);"' + 38 ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event,this);"' +
39 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' + 39 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' +
40 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188 40 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // http://dev.ckeditor.com/ticket/188
41 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' + 41 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' +
42 '<span id="{id}_text" class="cke_combo_text cke_combo_inlinelabel">{label}</span>' + 42 '<span id="{id}_text" class="cke_combo_text cke_combo_inlinelabel">{label}</span>' +
43 '<span class="cke_combo_open">' + 43 '<span class="cke_combo_open">' +
@@ -160,7 +160,7 @@ CKEDITOR.plugins.add( 'richcombo', {
160 }; 160 };
161 161
162 function updateState() { 162 function updateState() {
163 // Don't change state while richcombo is active (#11793). 163 // Don't change state while richcombo is active (http://dev.ckeditor.com/ticket/11793).
164 if ( this.getState() == CKEDITOR.TRISTATE_ON ) 164 if ( this.getState() == CKEDITOR.TRISTATE_ON )
165 return; 165 return;
166 166
@@ -189,15 +189,6 @@ CKEDITOR.plugins.add( 'richcombo', {
189 189
190 var keystroke = ev.getKeystroke(); 190 var keystroke = ev.getKeystroke();
191 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 ) { 192 switch ( keystroke ) {
202 case 13: // ENTER 193 case 13: // ENTER
203 case 32: // SPACE 194 case 32: // SPACE
@@ -266,12 +257,6 @@ CKEDITOR.plugins.add( 'richcombo', {
266 257
267 if ( me.onOpen ) 258 if ( me.onOpen )
268 me.onOpen(); 259 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 }; 260 };
276 261
277 panel.onHide = function( preventOnClose ) { 262 panel.onHide = function( preventOnClose ) {
diff --git a/sources/plugins/sourcearea/lang/es-mx.js b/sources/plugins/sourcearea/lang/es-mx.js
new file mode 100644
index 0000000..6dc6469
--- /dev/null
+++ b/sources/plugins/sourcearea/lang/es-mx.js
@@ -0,0 +1,7 @@
1/*
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-mx', {
6 toolbar: 'Fuente'
7} );
diff --git a/sources/plugins/sourcearea/plugin.js b/sources/plugins/sourcearea/plugin.js
index 837bc30..09745be 100644
--- a/sources/plugins/sourcearea/plugin.js
+++ b/sources/plugins/sourcearea/plugin.js
@@ -11,7 +11,7 @@
11( function() { 11( function() {
12 CKEDITOR.plugins.add( 'sourcearea', { 12 CKEDITOR.plugins.add( 'sourcearea', {
13 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
15 // jscs:enable maximumLineLength 15 // jscs:enable maximumLineLength
16 icons: 'source,source-rtl', // %REMOVE_LINE_CORE% 16 icons: 'source,source-rtl', // %REMOVE_LINE_CORE%
17 hidpi: true, // %REMOVE_LINE_CORE% 17 hidpi: true, // %REMOVE_LINE_CORE%
@@ -38,7 +38,7 @@
38 CKEDITOR.tools.cssVendorPrefix( 'tab-size', editor.config.sourceAreaTabSize || 4 ) ) ); 38 CKEDITOR.tools.cssVendorPrefix( 'tab-size', editor.config.sourceAreaTabSize || 4 ) ) );
39 39
40 // Make sure that source code is always displayed LTR, 40 // Make sure that source code is always displayed LTR,
41 // regardless of editor language (#10105). 41 // regardless of editor language (http://dev.ckeditor.com/ticket/10105).
42 textarea.setAttribute( 'dir', 'ltr' ); 42 textarea.setAttribute( 'dir', 'ltr' );
43 43
44 textarea.addClass( 'cke_source' ).addClass( 'cke_reset' ).addClass( 'cke_enable_context_menu' ); 44 textarea.addClass( 'cke_source' ).addClass( 'cke_reset' ).addClass( 'cke_enable_context_menu' );
@@ -53,7 +53,7 @@
53 // Having to make <textarea> fixed sized to conquer the following bugs: 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. 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 55 // 2. Unexpected vertical-scrolling behavior happens whenever focus is moving out of editor
56 // if text content within it has overflowed. (#4762) 56 // if text content within it has overflowed. (http://dev.ckeditor.com/ticket/4762)
57 if ( CKEDITOR.env.ie ) { 57 if ( CKEDITOR.env.ie ) {
58 editable.attachListener( editor, 'resize', onResize, editable ); 58 editable.attachListener( editor, 'resize', onResize, editable );
59 editable.attachListener( CKEDITOR.document.getWindow(), 'resize', onResize, editable ); 59 editable.attachListener( CKEDITOR.document.getWindow(), 'resize', onResize, editable );
@@ -83,7 +83,7 @@
83 83
84 function onResize() { 84 function onResize() {
85 // We have to do something with focus on IE9, because if sourcearea had focus 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). 86 // before being resized, the caret ends somewhere in the editor UI (http://dev.ckeditor.com/ticket/11839).
87 var wasActive = needsFocusHack && this.equals( CKEDITOR.document.getActive() ); 87 var wasActive = needsFocusHack && this.equals( CKEDITOR.document.getActive() );
88 88
89 // Holder rectange size is stretched by textarea, 89 // Holder rectange size is stretched by textarea,
diff --git a/sources/plugins/toolbar/lang/es-mx.js b/sources/plugins/toolbar/lang/es-mx.js
new file mode 100644
index 0000000..4af52fe
--- /dev/null
+++ b/sources/plugins/toolbar/lang/es-mx.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-mx', {
6 toolbarCollapse: 'Colapsar barra de herramientas',
7 toolbarExpand: 'Expandir barra de herramientas',
8 toolbarGroups: {
9 document: 'Documento',
10 clipboard: 'Portapapeles/deshacer',
11 editing: 'Editando',
12 forms: 'Formularios',
13 basicstyles: 'Estilo básico',
14 paragraph: 'Párrafo',
15 links: 'Enlaces',
16 insert: 'Insertar',
17 styles: 'Estilos',
18 colors: 'Colores',
19 tools: 'Herramientas'
20 },
21 toolbars: 'Editor de barra de herramientas'
22} );
diff --git a/sources/plugins/toolbar/plugin.js b/sources/plugins/toolbar/plugin.js
index b267b51..fc19359 100644
--- a/sources/plugins/toolbar/plugin.js
+++ b/sources/plugins/toolbar/plugin.js
@@ -34,7 +34,7 @@
34 if ( editor.toolbox ) { 34 if ( editor.toolbox ) {
35 editor.toolbox.focusCommandExecuted = true; 35 editor.toolbox.focusCommandExecuted = true;
36 36
37 // Make the first button focus accessible for IE. (#3417) 37 // Make the first button focus accessible for IE. (http://dev.ckeditor.com/ticket/3417)
38 // Adobe AIR instead need while of delay. 38 // Adobe AIR instead need while of delay.
39 if ( CKEDITOR.env.ie || CKEDITOR.env.air ) { 39 if ( CKEDITOR.env.ie || CKEDITOR.env.air ) {
40 setTimeout( function() { 40 setTimeout( function() {
@@ -51,7 +51,7 @@
51 CKEDITOR.plugins.add( 'toolbar', { 51 CKEDITOR.plugins.add( 'toolbar', {
52 requires: 'button', 52 requires: 'button',
53 // jscs:disable maximumLineLength 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% 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,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
55 // jscs:enable maximumLineLength 55 // jscs:enable maximumLineLength
56 56
57 init: function( editor ) { 57 init: function( editor ) {
@@ -118,10 +118,6 @@
118 return false; 118 return false;
119 case 40: // DOWN-ARROW 119 case 40: // DOWN-ARROW
120 if ( item.button && item.button.hasArrow ) { 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(); 121 item.execute();
126 } else { 122 } else {
127 // Send left arrow key. 123 // Send left arrow key.
@@ -205,7 +201,7 @@
205 // available because it's a common mistake to leave 201 // available because it's a common mistake to leave
206 // an extra comma in the toolbar definition 202 // an extra comma in the toolbar definition
207 // settings, which leads on the editor not loading 203 // settings, which leads on the editor not loading
208 // at all in IE. (#3983) 204 // at all in IE. (http://dev.ckeditor.com/ticket/3983)
209 if ( !row ) 205 if ( !row )
210 continue; 206 continue;
211 207
@@ -287,7 +283,7 @@
287 itemObj.toolbar = toolbarObj; 283 itemObj.toolbar = toolbarObj;
288 itemObj.onkey = itemKeystroke; 284 itemObj.onkey = itemKeystroke;
289 285
290 // Fix for #3052: 286 // Fix for http://dev.ckeditor.com/ticket/3052:
291 // Prevent JAWS from focusing the toolbar after document load. 287 // Prevent JAWS from focusing the toolbar after document load.
292 itemObj.onfocus = function() { 288 itemObj.onfocus = function() {
293 if ( !editor.toolbox.focusCommandExecuted ) 289 if ( !editor.toolbox.focusCommandExecuted )
diff --git a/sources/plugins/widget/dev/assets/simplebox/plugin.js b/sources/plugins/widget/dev/assets/simplebox/plugin.js
index 43dbad5..4c22d0d 100644
--- a/sources/plugins/widget/dev/assets/simplebox/plugin.js
+++ b/sources/plugins/widget/dev/assets/simplebox/plugin.js
@@ -3,7 +3,7 @@
3// Register the plugin within the editor. 3// Register the plugin within the editor.
4CKEDITOR.plugins.add( 'simplebox', { 4CKEDITOR.plugins.add( 'simplebox', {
5 // This plugin requires the Widgets System defined in the 'widget' plugin. 5 // This plugin requires the Widgets System defined in the 'widget' plugin.
6 requires: 'widget', 6 requires: 'widget,dialog',
7 7
8 // Register the icon used for the toolbar button. It must be the same 8 // Register the icon used for the toolbar button. It must be the same
9 // as the name of the widget. 9 // as the name of the widget.
diff --git a/sources/plugins/widget/lang/eo.js b/sources/plugins/widget/lang/eo.js
index f4979ac..381511a 100644
--- a/sources/plugins/widget/lang/eo.js
+++ b/sources/plugins/widget/lang/eo.js
@@ -4,5 +4,5 @@
4 */ 4 */
5CKEDITOR.plugins.setLang( 'widget', 'eo', { 5CKEDITOR.plugins.setLang( 'widget', 'eo', {
6 'move': 'klaki kaj treni por movi', 6 'move': 'klaki kaj treni por movi',
7 'label': '%1 widget' // MISSING 7 'label': '%1 fenestraĵo'
8} ); 8} );
diff --git a/sources/plugins/widget/lang/es-mx.js b/sources/plugins/widget/lang/es-mx.js
new file mode 100644
index 0000000..279ea3e
--- /dev/null
+++ b/sources/plugins/widget/lang/es-mx.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-mx', {
6 'move': 'Presiona y arrastra para mover',
7 'label': '%1 widget'
8} );
diff --git a/sources/plugins/widget/lang/gl.js b/sources/plugins/widget/lang/gl.js
index ef070b6..32f65d1 100644
--- a/sources/plugins/widget/lang/gl.js
+++ b/sources/plugins/widget/lang/gl.js
@@ -4,5 +4,5 @@
4 */ 4 */
5CKEDITOR.plugins.setLang( 'widget', 'gl', { 5CKEDITOR.plugins.setLang( 'widget', 'gl', {
6 'move': 'Prema e arrastre para mover', 6 'move': 'Prema e arrastre para mover',
7 'label': '%1 widget' // MISSING 7 'label': 'Trebello %1'
8} ); 8} );
diff --git a/sources/plugins/widget/lang/hr.js b/sources/plugins/widget/lang/hr.js
index 952d800..6b47d95 100644
--- a/sources/plugins/widget/lang/hr.js
+++ b/sources/plugins/widget/lang/hr.js
@@ -3,6 +3,6 @@
3 * For licensing, see LICENSE.md or http://ckeditor.com/license 3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */ 4 */
5CKEDITOR.plugins.setLang( 'widget', 'hr', { 5CKEDITOR.plugins.setLang( 'widget', 'hr', {
6 'move': 'Klikni i povuci da pomakneš', 6 'move': 'Klikni i povuci za pomicanje',
7 'label': '%1 widget' // MISSING 7 'label': '%1 widget'
8} ); 8} );
diff --git a/sources/plugins/widget/lang/hu.js b/sources/plugins/widget/lang/hu.js
index 4721305..a06047f 100644
--- a/sources/plugins/widget/lang/hu.js
+++ b/sources/plugins/widget/lang/hu.js
@@ -4,5 +4,5 @@
4 */ 4 */
5CKEDITOR.plugins.setLang( 'widget', 'hu', { 5CKEDITOR.plugins.setLang( 'widget', 'hu', {
6 'move': 'Kattints és húzd a mozgatáshoz', 6 'move': 'Kattints és húzd a mozgatáshoz',
7 'label': '%1 widget' // MISSING 7 'label': '%1 modul'
8} ); 8} );
diff --git a/sources/plugins/widget/lang/ko.js b/sources/plugins/widget/lang/ko.js
index 0107a13..03afb95 100644
--- a/sources/plugins/widget/lang/ko.js
+++ b/sources/plugins/widget/lang/ko.js
@@ -4,5 +4,5 @@
4 */ 4 */
5CKEDITOR.plugins.setLang( 'widget', 'ko', { 5CKEDITOR.plugins.setLang( 'widget', 'ko', {
6 'move': '움직이려면 클릭 후 드래그 하세요', 6 'move': '움직이려면 클릭 후 드래그 하세요',
7 'label': '%1 widget' // MISSING 7 'label': '%1 위젯'
8} ); 8} );
diff --git a/sources/plugins/widget/lang/sk.js b/sources/plugins/widget/lang/sk.js
index 05acac4..5bf4cc0 100644
--- a/sources/plugins/widget/lang/sk.js
+++ b/sources/plugins/widget/lang/sk.js
@@ -4,5 +4,5 @@
4 */ 4 */
5CKEDITOR.plugins.setLang( 'widget', 'sk', { 5CKEDITOR.plugins.setLang( 'widget', 'sk', {
6 'move': 'Kliknite a potiahnite pre presunutie', 6 'move': 'Kliknite a potiahnite pre presunutie',
7 'label': '%1 widget' // MISSING 7 'label': '%1 widget'
8} ); 8} );
diff --git a/sources/plugins/widget/plugin.js b/sources/plugins/widget/plugin.js
index 37374ab..2708e09 100644
--- a/sources/plugins/widget/plugin.js
+++ b/sources/plugins/widget/plugin.js
@@ -14,7 +14,7 @@
14 14
15 CKEDITOR.plugins.add( 'widget', { 15 CKEDITOR.plugins.add( 'widget', {
16 // jscs:disable maximumLineLength 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% 17 lang: 'af,ar,az,bg,ca,cs,cy,da,de,de-ch,el,en,en-gb,eo,es,es-mx,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 18 // jscs:enable maximumLineLength
19 requires: 'lineutils,clipboard,widgetselection', 19 requires: 'lineutils,clipboard,widgetselection',
20 onLoad: function() { 20 onLoad: function() {
@@ -46,13 +46,13 @@
46 'width:' + DRAG_HANDLER_SIZE + 'px;' + 46 'width:' + DRAG_HANDLER_SIZE + 'px;' +
47 'height:0;' + 47 'height:0;' +
48 // Initially drag handler should not be visible, until its position will be 48 // Initially drag handler should not be visible, until its position will be
49 // calculated (#11177). 49 // calculated (http://dev.ckeditor.com/ticket/11177).
50 // We need to hide unpositined handlers, so they don't extend 50 // We need to hide unpositined handlers, so they don't extend
51 // widget's outline far to the left (#12024). 51 // widget's outline far to the left (http://dev.ckeditor.com/ticket/12024).
52 'display:none;' + 52 'display:none;' +
53 'opacity:0.75;' + 53 'opacity:0.75;' +
54 'transition:height 0s 0.2s;' + // Delay hiding drag handler. 54 'transition:height 0s 0.2s;' + // Delay hiding drag handler.
55 // Prevent drag handler from being misplaced (#11198). 55 // Prevent drag handler from being misplaced (http://dev.ckeditor.com/ticket/11198).
56 'line-height:0' + 56 'line-height:0' +
57 '}' + 57 '}' +
58 '.cke_widget_wrapper:hover>.cke_widget_drag_handler_container{' + 58 '.cke_widget_wrapper:hover>.cke_widget_drag_handler_container{' +
@@ -1211,7 +1211,7 @@
1211 * @returns {Boolean} Whether an editable was successfully initialized. 1211 * @returns {Boolean} Whether an editable was successfully initialized.
1212 */ 1212 */
1213 initEditable: function( editableName, definition ) { 1213 initEditable: function( editableName, definition ) {
1214 // Don't fetch just first element which matched selector but look for a correct one. (#13334) 1214 // Don't fetch just first element which matched selector but look for a correct one. (http://dev.ckeditor.com/ticket/13334)
1215 var editable = this._findOneNotNested( definition.selector ); 1215 var editable = this._findOneNotNested( definition.selector );
1216 1216
1217 if ( editable && editable.is( CKEDITOR.dtd.$editable ) ) { 1217 if ( editable && editable.is( CKEDITOR.dtd.$editable ) ) {
@@ -1255,7 +1255,7 @@
1255 1255
1256 /** 1256 /**
1257 * Looks inside wrapper element to find a node that 1257 * Looks inside wrapper element to find a node that
1258 * matches given selector and is not nested in other widget. (#13334) 1258 * matches given selector and is not nested in other widget. (http://dev.ckeditor.com/ticket/13334)
1259 * 1259 *
1260 * @since 4.5 1260 * @since 4.5
1261 * @private 1261 * @private
@@ -1320,7 +1320,7 @@
1320 !isDirty && this.editor.resetDirty(); 1320 !isDirty && this.editor.resetDirty();
1321 } 1321 }
1322 1322
1323 // Always focus editor (not only when focusManger.hasFocus is false) (because of #10483). 1323 // Always focus editor (not only when focusManger.hasFocus is false) (because of http://dev.ckeditor.com/ticket/10483).
1324 this.editor.focus(); 1324 this.editor.focus();
1325 }, 1325 },
1326 1326
@@ -1473,7 +1473,7 @@
1473 if ( oldPos && newPos.x == oldPos.x && newPos.y == oldPos.y ) 1473 if ( oldPos && newPos.x == oldPos.x && newPos.y == oldPos.y )
1474 return; 1474 return;
1475 1475
1476 // We need to make sure that dirty state is not changed (#11487). 1476 // We need to make sure that dirty state is not changed (http://dev.ckeditor.com/ticket/11487).
1477 var initialDirty = editor.checkDirty(); 1477 var initialDirty = editor.checkDirty();
1478 1478
1479 editor.fire( 'lockSnapshot' ); 1479 editor.fire( 'lockSnapshot' );
@@ -2008,7 +2008,7 @@
2008 2008
2009 // Remove widgets which have no corresponding elements in DOM. 2009 // Remove widgets which have no corresponding elements in DOM.
2010 for ( i in instances ) { 2010 for ( i in instances ) {
2011 // #13410 Remove widgets that are ready. This prevents from destroying widgets that are during loading process. 2011 // http://dev.ckeditor.com/ticket/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 ) ) 2012 if ( instances[ i ].isReady() && !editable.contains( instances[ i ].wrapper ) )
2013 this.destroy( instances[ i ], true ); 2013 this.destroy( instances[ i ], true );
2014 } 2014 }
@@ -2027,7 +2027,7 @@
2027 2027
2028 // Check if: 2028 // Check if:
2029 // * there's no instance for this widget 2029 // * there's no instance for this widget
2030 // * wrapper is not inside some temporary element like copybin (#11088) 2030 // * wrapper is not inside some temporary element like copybin (http://dev.ckeditor.com/ticket/11088)
2031 // * it was a nested widget's wrapper which has been detached from DOM, 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 2032 // when nested editable has been initialized (it overwrites its innerHTML
2033 // and initializes nested widgets). 2033 // and initializes nested widgets).
@@ -2095,7 +2095,7 @@
2095 // @returns {CKEDITOR.filter} Filter instance or `null` if rules are not defined. 2095 // @returns {CKEDITOR.filter} Filter instance or `null` if rules are not defined.
2096 // @context CKEDITOR.plugins.widget.repository 2096 // @context CKEDITOR.plugins.widget.repository
2097 function createEditableFilter( widgetName, editableName, editableDefinition ) { 2097 function createEditableFilter( widgetName, editableName, editableDefinition ) {
2098 if ( !editableDefinition.allowedContent ) 2098 if ( !editableDefinition.allowedContent && !editableDefinition.disallowedContent )
2099 return null; 2099 return null;
2100 2100
2101 var editables = this._.filters[ widgetName ]; 2101 var editables = this._.filters[ widgetName ];
@@ -2105,8 +2105,15 @@
2105 2105
2106 var filter = editables[ editableName ]; 2106 var filter = editables[ editableName ];
2107 2107
2108 if ( !filter ) 2108 if ( !filter ) {
2109 editables[ editableName ] = filter = new CKEDITOR.filter( editableDefinition.allowedContent ); 2109 filter = editableDefinition.allowedContent ? new CKEDITOR.filter( editableDefinition.allowedContent ) : this.editor.filter.clone();
2110
2111 editables[ editableName ] = filter;
2112
2113 if ( editableDefinition.disallowedContent ) {
2114 filter.disallow( editableDefinition.disallowedContent );
2115 }
2116 }
2110 2117
2111 return filter; 2118 return filter;
2112 } 2119 }
@@ -2149,7 +2156,7 @@
2149 return false; 2156 return false;
2150 } 2157 }
2151 else if ( ( upcastsLength = upcasts.length ) ) { 2158 else if ( ( upcastsLength = upcasts.length ) ) {
2152 // Ignore elements with data-cke-widget-upcasted to avoid multiple upcasts (#11533). 2159 // Ignore elements with data-cke-widget-upcasted to avoid multiple upcasts (http://dev.ckeditor.com/ticket/11533).
2153 // Do not iterate over descendants. 2160 // Do not iterate over descendants.
2154 if ( element.attributes[ 'data-cke-widget-upcasted' ] ) 2161 if ( element.attributes[ 'data-cke-widget-upcasted' ] )
2155 return false; 2162 return false;
@@ -2356,7 +2363,7 @@
2356 '(?:</(?:div|span)>)?' + 2363 '(?:</(?:div|span)>)?' +
2357 '(?:</(?:div|span)>)?' + 2364 '(?:</(?:div|span)>)?' +
2358 '$', 2365 '$',
2359 // IE8 prefers uppercase when browsers stick to lowercase HTML (#13460). 2366 // IE8 prefers uppercase when browsers stick to lowercase HTML (http://dev.ckeditor.com/ticket/13460).
2360 'i' 2367 'i'
2361 ); 2368 );
2362 2369
@@ -2384,7 +2391,7 @@
2384 // IE needs focus. 2391 // IE needs focus.
2385 editor.focus(); 2392 editor.focus();
2386 2393
2387 // and widget need to be focused on drag start (#12172#comment:10). 2394 // and widget need to be focused on drag start (http://dev.ckeditor.com/ticket/12172#comment:10).
2388 widget.focus(); 2395 widget.focus();
2389 } 2396 }
2390 } ); 2397 } );
@@ -2396,7 +2403,7 @@
2396 dragRange = editor.createRange(), 2403 dragRange = editor.createRange(),
2397 sourceWidget; 2404 sourceWidget;
2398 2405
2399 // Disable cross-editor drag & drop for widgets - #13599. 2406 // Disable cross-editor drag & drop for widgets - http://dev.ckeditor.com/ticket/13599.
2400 if ( id !== '' && transferType === CKEDITOR.DATA_TRANSFER_CROSS_EDITORS ) { 2407 if ( id !== '' && transferType === CKEDITOR.DATA_TRANSFER_CROSS_EDITORS ) {
2401 evt.cancel(); 2408 evt.cancel();
2402 return; 2409 return;
@@ -2440,16 +2447,16 @@
2440 if ( !el.is( CKEDITOR.dtd.$block ) ) 2447 if ( !el.is( CKEDITOR.dtd.$block ) )
2441 return; 2448 return;
2442 2449
2443 // Allow drop line inside, but never before or after nested editable (#12006). 2450 // Allow drop line inside, but never before or after nested editable (http://dev.ckeditor.com/ticket/12006).
2444 if ( Widget.isDomNestedEditable( el ) ) 2451 if ( Widget.isDomNestedEditable( el ) )
2445 return; 2452 return;
2446 2453
2447 // Do not allow droping inside the widget being dragged (#13397). 2454 // Do not allow droping inside the widget being dragged (http://dev.ckeditor.com/ticket/13397).
2448 if ( widgetsRepo._.draggedWidget.wrapper.contains( el ) ) { 2455 if ( widgetsRepo._.draggedWidget.wrapper.contains( el ) ) {
2449 return; 2456 return;
2450 } 2457 }
2451 2458
2452 // If element is nested editable, make sure widget can be dropped there (#12006). 2459 // If element is nested editable, make sure widget can be dropped there (http://dev.ckeditor.com/ticket/12006).
2453 var nestedEditable = Widget.getNestedEditable( editable, el ); 2460 var nestedEditable = Widget.getNestedEditable( editable, el );
2454 if ( nestedEditable ) { 2461 if ( nestedEditable ) {
2455 var draggedWidget = widgetsRepo._.draggedWidget; 2462 var draggedWidget = widgetsRepo._.draggedWidget;
@@ -2503,11 +2510,11 @@
2503 editable.attachListener( evtRoot, 'mousedown', function( evt ) { 2510 editable.attachListener( evtRoot, 'mousedown', function( evt ) {
2504 var target = evt.data.getTarget(); 2511 var target = evt.data.getTarget();
2505 2512
2506 // #10887 Clicking scrollbar in IE8 will invoke event with empty target object. 2513 // Clicking scrollbar in Chrome will invoke event with target object of document type (#663).
2507 if ( !target.type ) 2514 // In IE8 the target object will be empty (http://dev.ckeditor.com/ticket/10887).
2508 return false; 2515 // We need to check if target is a proper element.
2516 widget = ( target instanceof CKEDITOR.dom.element ) ? widgetsRepo.getByElement( target ) : null;
2509 2517
2510 widget = widgetsRepo.getByElement( target );
2511 mouseDownOnDragHandler = 0; // Reset. 2518 mouseDownOnDragHandler = 0; // Reset.
2512 2519
2513 // Widget was clicked, but not editable nested in it. 2520 // Widget was clicked, but not editable nested in it.
@@ -2518,7 +2525,7 @@
2518 mouseDownOnDragHandler = 1; 2525 mouseDownOnDragHandler = 1;
2519 2526
2520 // When drag handler is pressed we have to clear current selection if it wasn't already on this widget. 2527 // 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.) 2528 // Otherwise, the selection may be in a fillingChar, which prevents dragging a widget. (http://dev.ckeditor.com/ticket/13284, see comment 8 and 9.)
2522 if ( widgetsRepo.focused != widget ) 2529 if ( widgetsRepo.focused != widget )
2523 editor.getSelection().removeAllRanges(); 2530 editor.getSelection().removeAllRanges();
2524 2531
@@ -2725,7 +2732,7 @@
2725 // Save the reference to this nested editable in the closest widget to be downcasted. 2732 // 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 2733 // 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 2734 // for dataFilter's "excludeNestedEditable" option to do its job (that option relies on
2728 // contenteditable="true" attribute) (#11372). 2735 // contenteditable="true" attribute) (http://dev.ckeditor.com/ticket/11372).
2729 toBeDowncasted[ toBeDowncasted.length - 1 ].editables[ attrs[ 'data-cke-widget-editable' ] ] = element; 2736 toBeDowncasted[ toBeDowncasted.length - 1 ].editables[ attrs[ 'data-cke-widget-editable' ] ] = element;
2730 2737
2731 // Don't check children - there won't be next wrapper or nested editable which we 2738 // Don't check children - there won't be next wrapper or nested editable which we
@@ -2836,7 +2843,7 @@
2836 // If drag'n'drop kind of paste into nested editable (data.range), selection is set AFTER 2843 // 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. 2844 // 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 2845 // 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). 2846 // funny things get inserted. Changing the filter by analysis of the paste range below (http://dev.ckeditor.com/ticket/13186).
2840 if ( data.range ) { 2847 if ( data.range ) {
2841 // Check if pasting into nested editable. 2848 // Check if pasting into nested editable.
2842 var nestedEditable = Widget.getNestedEditable( editor.editable(), data.range.startContainer ); 2849 var nestedEditable = Widget.getNestedEditable( editor.editable(), data.range.startContainer );
@@ -3132,7 +3139,7 @@
3132 } ); 3139 } );
3133 } 3140 }
3134 3141
3135 // Add a listener to data event that will set/change widget's label (#14539). 3142 // Add a listener to data event that will set/change widget's label (http://dev.ckeditor.com/ticket/14539).
3136 function setupA11yListener( widget ) { 3143 function setupA11yListener( widget ) {
3137 // Note, the function gets executed in a context of widget instance. 3144 // Note, the function gets executed in a context of widget instance.
3138 function getLabelDefault() { 3145 function getLabelDefault() {
@@ -3160,11 +3167,11 @@
3160 return; 3167 return;
3161 3168
3162 var editor = widget.editor, 3169 var editor = widget.editor,
3163 // Use getLast to find wrapper's direct descendant (#12022). 3170 // Use getLast to find wrapper's direct descendant (http://dev.ckeditor.com/ticket/12022).
3164 container = widget.wrapper.getLast( Widget.isDomDragHandlerContainer ), 3171 container = widget.wrapper.getLast( Widget.isDomDragHandlerContainer ),
3165 img; 3172 img;
3166 3173
3167 // Reuse drag handler if already exists (#11281). 3174 // Reuse drag handler if already exists (http://dev.ckeditor.com/ticket/11281).
3168 if ( container ) 3175 if ( container )
3169 img = container.findOne( 'img' ); 3176 img = container.findOne( 'img' );
3170 else { 3177 else {
@@ -3191,7 +3198,7 @@
3191 widget.wrapper.append( container ); 3198 widget.wrapper.append( container );
3192 } 3199 }
3193 3200
3194 // Preventing page reload when dropped content on widget wrapper (#13015). 3201 // Preventing page reload when dropped content on widget wrapper (http://dev.ckeditor.com/ticket/13015).
3195 // Widget is not editable so by default drop on it isn't allowed what means that 3202 // 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 3203 // 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. 3204 // the drop, so page is reloaded. This listener enables drop on widget wrappers.
@@ -3336,7 +3343,7 @@
3336 if ( !widget.mask ) 3343 if ( !widget.mask )
3337 return; 3344 return;
3338 3345
3339 // Reuse mask if already exists (#11281). 3346 // Reuse mask if already exists (http://dev.ckeditor.com/ticket/11281).
3340 var img = widget.wrapper.findOne( '.cke_widget_mask' ); 3347 var img = widget.wrapper.findOne( '.cke_widget_mask' );
3341 3348
3342 if ( !img ) { 3349 if ( !img ) {
@@ -3377,7 +3384,7 @@
3377 setupDataClassesListener( widget ); 3384 setupDataClassesListener( widget );
3378 setupA11yListener( widget ); 3385 setupA11yListener( widget );
3379 3386
3380 // #11145: [IE8] Non-editable content of widget is draggable. 3387 // http://dev.ckeditor.com/ticket/11145: [IE8] Non-editable content of widget is draggable.
3381 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { 3388 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
3382 widget.wrapper.on( 'dragstart', function( evt ) { 3389 widget.wrapper.on( 'dragstart', function( evt ) {
3383 var target = evt.data.getTarget(); 3390 var target = evt.data.getTarget();
@@ -3415,7 +3422,7 @@
3415 widget.on( 'doubleclick', function( evt ) { 3422 widget.on( 'doubleclick', function( evt ) {
3416 if ( widget.edit() ) { 3423 if ( widget.edit() ) {
3417 // We have to cancel event if edit method opens a dialog, otherwise 3424 // We have to cancel event if edit method opens a dialog, otherwise
3418 // link plugin may open extra dialog (#12140). 3425 // link plugin may open extra dialog (http://dev.ckeditor.com/ticket/12140).
3419 evt.cancel(); 3426 evt.cancel();
3420 } 3427 }
3421 } ); 3428 } );
@@ -4116,11 +4123,25 @@
4116 * This option is similar to {@link CKEDITOR.config#allowedContent} and one can 4123 * 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. 4124 * use it to limit the editor features available in the nested editable.
4118 * 4125 *
4126 * If no `allowedContent` is specified, the editable will use the editor default
4127 * {@link CKEDITOR.editor#filter}.
4128 *
4119 * @property {CKEDITOR.filter.allowedContentRules} allowedContent 4129 * @property {CKEDITOR.filter.allowedContentRules} allowedContent
4120 */ 4130 */
4121 4131
4122/** 4132/**
4123 * Nested editable name displayed in elements path. 4133 * The [Advanced Content Filter](#!/guide/dev_advanced_content_filter) rules
4134 * which will be used to blacklist elements within this nested editable.
4135 * This option is similar to {@link CKEDITOR.config#disallowedContent}.
4136 *
4137 * Note that `disallowedContent` work on top of the definition's {@link #allowedContent}.
4138 *
4139 * @since 4.7.3
4140 * @property {CKEDITOR.filter.disallowedContentRules} disallowedContent
4141 */
4142
4143/**
4144 * Nested editable name displayed in the elements path.
4124 * 4145 *
4125 * @property {String} pathName 4146 * @property {String} pathName
4126 */ 4147 */
diff --git a/sources/plugins/widgetselection/plugin.js b/sources/plugins/widgetselection/plugin.js
index b7aa6a0..6c788cb 100644
--- a/sources/plugins/widgetselection/plugin.js
+++ b/sources/plugins/widgetselection/plugin.js
@@ -4,7 +4,7 @@
4 */ 4 */
5 5
6/** 6/**
7 * @fileOverview A plugin created to handle ticket #11064. While the issue is caused by native WebKit/Blink behaviour, 7 * @fileOverview A plugin created to handle ticket http://dev.ckeditor.com/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. 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 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. 10 * Webkit/Blink if a non-editable element is at the beginning or the end of the content.
diff --git a/sources/plugins/wysiwygarea/plugin.js b/sources/plugins/wysiwygarea/plugin.js
index 962f31e..1358129 100644
--- a/sources/plugins/wysiwygarea/plugin.js
+++ b/sources/plugins/wysiwygarea/plugin.js
@@ -29,7 +29,7 @@
29 // With IE, the custom domain has to be taken care at first, 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 30 // for other browers, the 'src' attribute should be left empty to
31 // trigger iframe's 'load' event. 31 // trigger iframe's 'load' event.
32 // Microsoft Edge throws "Permission Denied" if treated like an IE (#13441). 32 // Microsoft Edge throws "Permission Denied" if treated like an IE (http://dev.ckeditor.com/ticket/13441).
33 if ( CKEDITOR.env.air ) { 33 if ( CKEDITOR.env.air ) {
34 src = 'javascript:void(0)'; // jshint ignore:line 34 src = 'javascript:void(0)'; // jshint ignore:line
35 } else if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { 35 } else if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) {
@@ -139,7 +139,7 @@
139 body.hideFocus = true; 139 body.hideFocus = true;
140 140
141 // Disable and re-enable the body to avoid IE from 141 // Disable and re-enable the body to avoid IE from
142 // taking the editing focus at startup. (#141 / #523) 142 // taking the editing focus at startup. (http://dev.ckeditor.com/ticket/141 / http://dev.ckeditor.com/ticket/523)
143 body.disabled = true; 143 body.disabled = true;
144 body.removeAttribute( 'disabled' ); 144 body.removeAttribute( 'disabled' );
145 } 145 }
@@ -156,19 +156,19 @@
156 156
157 var editable = this; 157 var editable = this;
158 158
159 // Without it IE8 has problem with removing selection in nested editable. (#13785) 159 // Without it IE8 has problem with removing selection in nested editable. (http://dev.ckeditor.com/ticket/13785)
160 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { 160 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) {
161 doc.getDocumentElement().addClass( doc.$.compatMode ); 161 doc.getDocumentElement().addClass( doc.$.compatMode );
162 } 162 }
163 163
164 // Prevent IE/Edge from leaving a new paragraph/div after deleting all contents in body. (#6966, #13142) 164 // Prevent IE/Edge from leaving a new paragraph/div after deleting all contents in body. (http://dev.ckeditor.com/ticket/6966, http://dev.ckeditor.com/ticket/13142)
165 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_P ) { 165 if ( CKEDITOR.env.ie && !CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_P ) {
166 removeSuperfluousElement( 'p' ); 166 removeSuperfluousElement( 'p' );
167 } else if ( CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_DIV ) { 167 } else if ( CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_DIV ) {
168 removeSuperfluousElement( 'div' ); 168 removeSuperfluousElement( 'div' );
169 } 169 }
170 170
171 // Fix problem with cursor not appearing in Webkit and IE11+ when clicking below the body (#10945, #10906). 171 // Fix problem with cursor not appearing in Webkit and IE11+ when clicking below the body (http://dev.ckeditor.com/ticket/10945, http://dev.ckeditor.com/ticket/10906).
172 // Fix for older IEs (8-10 and QM) is placed inside selection.js. 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 ) ) { 173 if ( CKEDITOR.env.webkit || ( CKEDITOR.env.ie && CKEDITOR.env.version > 10 ) ) {
174 doc.getDocumentElement().on( 'mousedown', function( evt ) { 174 doc.getDocumentElement().on( 'mousedown', function( evt ) {
@@ -196,7 +196,7 @@
196 // PageUp OR PageDown 196 // PageUp OR PageDown
197 if ( keyCode == 33 || keyCode == 34 ) { 197 if ( keyCode == 33 || keyCode == 34 ) {
198 // PageUp/PageDown scrolling is broken in document 198 // PageUp/PageDown scrolling is broken in document
199 // with standard doctype, manually fix it. (#4736) 199 // with standard doctype, manually fix it. (http://dev.ckeditor.com/ticket/4736)
200 if ( CKEDITOR.env.ie ) { 200 if ( CKEDITOR.env.ie ) {
201 setTimeout( function() { 201 setTimeout( function() {
202 editor.getSelection().scrollIntoView(); 202 editor.getSelection().scrollIntoView();
@@ -205,7 +205,7 @@
205 // Page up/down cause editor selection to leak 205 // Page up/down cause editor selection to leak
206 // outside of editable thus we try to intercept 206 // outside of editable thus we try to intercept
207 // the behavior, while it affects only happen 207 // the behavior, while it affects only happen
208 // when editor contents are not overflowed. (#7955) 208 // when editor contents are not overflowed. (http://dev.ckeditor.com/ticket/7955)
209 else if ( editor.window.$.innerHeight > this.$.offsetHeight ) { 209 else if ( editor.window.$.innerHeight > this.$.offsetHeight ) {
210 var range = editor.createRange(); 210 var range = editor.createRange();
211 range[ keyCode == 33 ? 'moveToElementEditStart' : 'moveToElementEditEnd' ]( this ); 211 range[ keyCode == 33 ? 'moveToElementEditStart' : 'moveToElementEditEnd' ]( this );
@@ -221,14 +221,14 @@
221 // focus is moved onto a non-editing host, e.g. link or button, but 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 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 223 // handler attached on it will mark other part of the UI, especially
224 // for the dialog. (#8157) 224 // for the dialog. (http://dev.ckeditor.com/ticket/8157)
225 // [IE<8 & Opera] Even worse For old IEs, the cursor will not vanish even if 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) 226 // the selection has been moved to another text input in some cases. (http://dev.ckeditor.com/ticket/4716)
227 // 227 //
228 // Now the range restore is disabled, so we simply force IE to clean 228 // Now the range restore is disabled, so we simply force IE to clean
229 // up the selection before blur. 229 // up the selection before blur.
230 this.attachListener( doc, 'blur', function() { 230 this.attachListener( doc, 'blur', function() {
231 // Error proof when the editor is not visible. (#6375) 231 // Error proof when the editor is not visible. (http://dev.ckeditor.com/ticket/6375)
232 try { 232 try {
233 doc.$.selection.empty(); 233 doc.$.selection.empty();
234 } catch ( er ) {} 234 } catch ( er ) {}
@@ -237,14 +237,14 @@
237 237
238 if ( CKEDITOR.env.iOS ) { 238 if ( CKEDITOR.env.iOS ) {
239 // [iOS] If touch is bound to any parent of the iframe blur happens on any touch 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). 240 // event and body becomes the focused element (http://dev.ckeditor.com/ticket/10714).
241 this.attachListener( doc, 'touchend', function() { 241 this.attachListener( doc, 'touchend', function() {
242 win.focus(); 242 win.focus();
243 } ); 243 } );
244 } 244 }
245 245
246 var title = editor.document.getElementsByTag( 'title' ).getItem( 0 ); 246 var title = editor.document.getElementsByTag( 'title' ).getItem( 0 );
247 // document.title is malfunctioning on Chrome, so get value from the element (#12402). 247 // document.title is malfunctioning on Chrome, so get value from the element (http://dev.ckeditor.com/ticket/12402).
248 title.data( 'cke-title', title.getText() ); 248 title.data( 'cke-title', title.getText() );
249 249
250 // [IE] JAWS will not recognize the aria label we used on the iframe 250 // [IE] JAWS will not recognize the aria label we used on the iframe
@@ -292,7 +292,7 @@
292 // 2. On keyup remove all elements that were not marked 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). 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 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). 295 // leak fake selection's content into editable due to removing hidden selection container (http://dev.ckeditor.com/ticket/14831).
296 editable.attachListener( editable, 'keyup', function() { 296 editable.attachListener( editable, 'keyup', function() {
297 var elements = doc.getElementsByTag( tagName ); 297 var elements = doc.getElementsByTag( tagName );
298 if ( lockRetain ) { 298 if ( lockRetain ) {
@@ -312,7 +312,7 @@
312 312
313 this._.frameLoadedHandler = CKEDITOR.tools.addFunction( function( win ) { 313 this._.frameLoadedHandler = CKEDITOR.tools.addFunction( function( win ) {
314 // Avoid opening design mode in a frame window thread, 314 // Avoid opening design mode in a frame window thread,
315 // which will cause host page scrolling.(#4397) 315 // which will cause host page scrolling.(http://dev.ckeditor.com/ticket/4397)
316 CKEDITOR.tools.setTimeout( onDomReady, 0, this, win ); 316 CKEDITOR.tools.setTimeout( onDomReady, 0, this, win );
317 }, this ); 317 }, this );
318 318
@@ -330,7 +330,7 @@
330 this.fixInitialSelection(); 330 this.fixInitialSelection();
331 331
332 // Fire dataReady for the consistency with inline editors 332 // Fire dataReady for the consistency with inline editors
333 // and because it makes sense. (#10370) 333 // and because it makes sense. (http://dev.ckeditor.com/ticket/10370)
334 editor.fire( 'dataReady' ); 334 editor.fire( 'dataReady' );
335 } 335 }
336 else { 336 else {
@@ -420,7 +420,7 @@
420 } 420 }
421 421
422 // The script that launches the bootstrap logic on 'domReady', so the document 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). 423 // is fully editable even before the editing iframe is fully loaded (http://dev.ckeditor.com/ticket/4455).
424 var bootstrapCode = 424 var bootstrapCode =
425 '<script id="cke_actscrpt" type="text/javascript"' + ( CKEDITOR.env.ie ? ' defer="defer" ' : '' ) + '>' + 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. 426 'var wasLoaded=0;' + // It must be always set to 0 as it remains as a window property.
@@ -442,7 +442,7 @@
442 } 442 }
443 443
444 // IE<10 needs this hack to properly enable <base href="...">. 444 // IE<10 needs this hack to properly enable <base href="...">.
445 // See: http://stackoverflow.com/a/13373180/1485219 (#11910). 445 // See: http://stackoverflow.com/a/13373180/1485219 (http://dev.ckeditor.com/ticket/11910).
446 if ( baseTag && CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { 446 if ( baseTag && CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) {
447 bootstrapCode += 447 bootstrapCode +=
448 '<script id="cke_basetagscrpt">' + 448 '<script id="cke_basetagscrpt">' +
@@ -461,7 +461,7 @@
461 461
462 var doc = this.getDocument(); 462 var doc = this.getDocument();
463 463
464 // Work around Firefox bug - error prune when called from XUL (#320), 464 // Work around Firefox bug - error prune when called from XUL (http://dev.ckeditor.com/ticket/320),
465 // defer it thanks to the async nature of this method. 465 // defer it thanks to the async nature of this method.
466 try { 466 try {
467 doc.write( data ); 467 doc.write( data );
@@ -486,9 +486,9 @@
486 486
487 var data = fullPage ? doc.getDocumentElement().getOuterHtml() : doc.getBody().getHtml(); 487 var data = fullPage ? doc.getDocumentElement().getOuterHtml() : doc.getBody().getHtml();
488 488
489 // BR at the end of document is bogus node for Mozilla. (#5293). 489 // BR at the end of document is bogus node for Mozilla. (http://dev.ckeditor.com/ticket/5293).
490 // Prevent BRs from disappearing from the end of the content 490 // Prevent BRs from disappearing from the end of the content
491 // while enterMode is ENTER_BR (#10146). 491 // while enterMode is ENTER_BR (http://dev.ckeditor.com/ticket/10146).
492 if ( CKEDITOR.env.gecko && config.enterMode != CKEDITOR.ENTER_BR ) 492 if ( CKEDITOR.env.gecko && config.enterMode != CKEDITOR.ENTER_BR )
493 data = data.replace( /<br>(?=\s*(:?$|<\/body>))/, '' ); 493 data = data.replace( /<br>(?=\s*(:?$|<\/body>))/, '' );
494 494
@@ -517,7 +517,7 @@
517 onResize; 517 onResize;
518 518
519 // Trying to access window's frameElement property on Edge throws an exception 519 // Trying to access window's frameElement property on Edge throws an exception
520 // when frame was already removed from DOM. (#13850, #13790) 520 // when frame was already removed from DOM. (http://dev.ckeditor.com/ticket/13850, http://dev.ckeditor.com/ticket/13790)
521 try { 521 try {
522 iframe = editor.window.getFrame(); 522 iframe = editor.window.getFrame();
523 } catch ( e ) {} 523 } catch ( e ) {}
@@ -530,7 +530,7 @@
530 CKEDITOR.tools.removeFunction( this._.frameLoadedHandler ); 530 CKEDITOR.tools.removeFunction( this._.frameLoadedHandler );
531 531
532 // On IE, iframe is returned even after remove() method is called on it. 532 // On IE, iframe is returned even after remove() method is called on it.
533 // Checking if parent is present fixes this issue. (#13850) 533 // Checking if parent is present fixes this issue. (http://dev.ckeditor.com/ticket/13850)
534 if ( iframe && iframe.getParent() ) { 534 if ( iframe && iframe.getParent() ) {
535 iframe.clearCustomData(); 535 iframe.clearCustomData();
536 onResize = iframe.removeCustomData( 'onResize' ); 536 onResize = iframe.removeCustomData( 'onResize' );
@@ -538,7 +538,7 @@
538 538
539 // IE BUG: When destroying editor DOM with the selection remains inside 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 540 // editing area would break IE7/8's selection system, we have to put the editing
541 // iframe offline first. (#3812 and #5441) 541 // iframe offline first. (http://dev.ckeditor.com/ticket/3812 and http://dev.ckeditor.com/ticket/5441)
542 iframe.remove(); 542 iframe.remove();
543 } else { 543 } else {
544 CKEDITOR.warn( 'editor-destroy-iframe' ); 544 CKEDITOR.warn( 'editor-destroy-iframe' );
@@ -593,7 +593,7 @@
593 var css = []; 593 var css = [];
594 594
595 // IE>=8 stricts mode doesn't have 'contentEditable' in effect 595 // IE>=8 stricts mode doesn't have 'contentEditable' in effect
596 // on element unless it has layout. (#5562) 596 // on element unless it has layout. (http://dev.ckeditor.com/ticket/5562)
597 if ( CKEDITOR.document.$.documentMode >= 8 ) { 597 if ( CKEDITOR.document.$.documentMode >= 8 ) {
598 css.push( 'html.CSS1Compat [contenteditable=false]{min-height:0 !important}' ); 598 css.push( 'html.CSS1Compat [contenteditable=false]{min-height:0 !important}' );
599 599
@@ -604,14 +604,14 @@
604 604
605 css.push( selectors.join( ',' ) + '{display:inline-block}' ); 605 css.push( selectors.join( ',' ) + '{display:inline-block}' );
606 } 606 }
607 // Set the HTML style to 100% to have the text cursor in affect (#6341) 607 // Set the HTML style to 100% to have the text cursor in affect (http://dev.ckeditor.com/ticket/6341)
608 else if ( CKEDITOR.env.gecko ) { 608 else if ( CKEDITOR.env.gecko ) {
609 css.push( 'html{height:100% !important}' ); 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}' ); 610 css.push( 'img:-moz-broken{-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}' );
611 } 611 }
612 612
613 // #6341: The text cursor must be set on the editor area. 613 // http://dev.ckeditor.com/ticket/6341: The text cursor must be set on the editor area.
614 // #6632: Avoid having "text" shape of cursor in IE7 scrollbars. 614 // http://dev.ckeditor.com/ticket/6632: Avoid having "text" shape of cursor in IE7 scrollbars.
615 css.push( 'html{cursor:text;*cursor:auto}' ); 615 css.push( 'html{cursor:text;*cursor:auto}' );
616 616
617 // Use correct cursor for these elements 617 // Use correct cursor for these elements
diff --git a/sources/samples/index.html b/sources/samples/index.html
index 3d274cf..5f47351 100644
--- a/sources/samples/index.html
+++ b/sources/samples/index.html
@@ -18,7 +18,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
18 <div class="grid-container"> 18 <div class="grid-container">
19 <ul class="navigation-a-left grid-width-70"> 19 <ul class="navigation-a-left grid-width-70">
20 <li><a href="http://ckeditor.com">Project Homepage</a></li> 20 <li><a href="http://ckeditor.com">Project Homepage</a></li>
21 <li><a href="http://dev.ckeditor.com/">I found a bug</a></li> 21 <li><a href="https://github.com/ckeditor/ckeditor-dev/issues">I found a bug</a></li>
22 <li><a href="http://github.com/ckeditor/ckeditor-dev" class="icon-pos-right icon-navigation-a-github">Fork CKEditor on GitHub</a></li> 22 <li><a href="http://github.com/ckeditor/ckeditor-dev" class="icon-pos-right icon-navigation-a-github">Fork CKEditor on GitHub</a></li>
23 </ul> 23 </ul>
24 <ul class="navigation-a-right grid-width-30"> 24 <ul class="navigation-a-right grid-width-30">
diff --git a/sources/samples/old/assets/uilanguages/languages.js b/sources/samples/old/assets/uilanguages/languages.js
index df6b2dc..a3cf84f 100644
--- a/sources/samples/old/assets/uilanguages/languages.js
+++ b/sources/samples/old/assets/uilanguages/languages.js
@@ -26,6 +26,7 @@ var CKEDITOR_LANGS = ( function() {
26 'en-gb': 'English (United Kingdom)', 26 'en-gb': 'English (United Kingdom)',
27 eo: 'Esperanto', 27 eo: 'Esperanto',
28 es: 'Spanish', 28 es: 'Spanish',
29 'es-mx': 'Spanish (Mexico)',
29 et: 'Estonian', 30 et: 'Estonian',
30 eu: 'Basque', 31 eu: 'Basque',
31 fa: 'Persian', 32 fa: 'Persian',
diff --git a/sources/samples/toolbarconfigurator/index.html b/sources/samples/toolbarconfigurator/index.html
index 4d31289..ea216d2 100644
--- a/sources/samples/toolbarconfigurator/index.html
+++ b/sources/samples/toolbarconfigurator/index.html
@@ -26,7 +26,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license
26 <div class="grid-container"> 26 <div class="grid-container">
27 <ul class="navigation-a-left grid-width-70"> 27 <ul class="navigation-a-left grid-width-70">
28 <li><a href="http://ckeditor.com">Project Homepage</a></li> 28 <li><a href="http://ckeditor.com">Project Homepage</a></li>
29 <li><a href="http://dev.ckeditor.com/">I found a bug</a></li> 29 <li><a href="https://github.com/ckeditor/ckeditor-dev/issues">I found a bug</a></li>
30 <li><a href="http://github.com/ckeditor/ckeditor-dev" class="icon-pos-right icon-navigation-a-github">Fork CKEditor on GitHub</a></li> 30 <li><a href="http://github.com/ckeditor/ckeditor-dev" class="icon-pos-right icon-navigation-a-github">Fork CKEditor on GitHub</a></li>
31 </ul> 31 </ul>
32 <ul class="navigation-a-right grid-width-30"> 32 <ul class="navigation-a-right grid-width-30">
diff --git a/sources/samples/toolbarconfigurator/lib/codemirror/codemirror.js b/sources/samples/toolbarconfigurator/lib/codemirror/codemirror.js
index 37e2685..e5c3155 100644
--- a/sources/samples/toolbarconfigurator/lib/codemirror/codemirror.js
+++ b/sources/samples/toolbarconfigurator/lib/codemirror/codemirror.js
@@ -1181,7 +1181,7 @@
1181 // very slow. So make the area wide instead. 1181 // very slow. So make the area wide instead.
1182 if (webkit) te.style.width = "1000px"; 1182 if (webkit) te.style.width = "1000px";
1183 else te.setAttribute("wrap", "off"); 1183 else te.setAttribute("wrap", "off");
1184 // If border: 0; -- iOS fails to open keyboard (issue #1287) 1184 // If border: 0; -- iOS fails to open keyboard (issue http://dev.ckeditor.com/ticket/1287)
1185 if (ios) te.style.border = "1px solid black"; 1185 if (ios) te.style.border = "1px solid black";
1186 disableBrowserMagic(te); 1186 disableBrowserMagic(te);
1187 return div; 1187 return div;
@@ -1397,7 +1397,7 @@
1397 if (text == prevInput && !cm.somethingSelected()) return false; 1397 if (text == prevInput && !cm.somethingSelected()) return false;
1398 // Work around nonsensical selection resetting in IE9/10, and 1398 // Work around nonsensical selection resetting in IE9/10, and
1399 // inexplicable appearance of private area unicode characters on 1399 // inexplicable appearance of private area unicode characters on
1400 // some key combos in Mac (#2689). 1400 // some key combos in Mac (http://dev.ckeditor.com/ticket/2689).
1401 if (ie && ie_version >= 9 && this.hasSelection === text || 1401 if (ie && ie_version >= 9 && this.hasSelection === text ||
1402 mac && /[\uf700-\uf7ff]/.test(text)) { 1402 mac && /[\uf700-\uf7ff]/.test(text)) {
1403 cm.display.input.reset(); 1403 cm.display.input.reset();
@@ -1457,7 +1457,7 @@
1457 "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " + 1457 "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
1458 (ie ? "rgba(255, 255, 255, .05)" : "transparent") + 1458 (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
1459 "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; 1459 "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
1460 if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) 1460 if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (http://dev.ckeditor.com/ticket/2712)
1461 display.input.focus(); 1461 display.input.focus();
1462 if (webkit) window.scrollTo(null, oldScrollY); 1462 if (webkit) window.scrollTo(null, oldScrollY);
1463 display.input.reset(); 1463 display.input.reset();
@@ -3581,7 +3581,7 @@
3581 e_preventDefault(e2); 3581 e_preventDefault(e2);
3582 if (!modifier && +new Date - 200 < startTime) 3582 if (!modifier && +new Date - 200 < startTime)
3583 extendSelection(cm.doc, start); 3583 extendSelection(cm.doc, start);
3584 // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) 3584 // Work around unexplainable focus problem in IE9 (http://dev.ckeditor.com/ticket/2127) and Chrome (http://dev.ckeditor.com/ticket/3081)
3585 if (webkit || ie && ie_version == 9) 3585 if (webkit || ie && ie_version == 9)
3586 setTimeout(function() {document.body.focus(); display.input.focus();}, 20); 3586 setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
3587 else 3587 else
@@ -3769,7 +3769,7 @@
3769 } 3769 }
3770 3770
3771 // Kludge to work around strange IE behavior where it'll sometimes 3771 // Kludge to work around strange IE behavior where it'll sometimes
3772 // re-fire a series of drag-related events right after the drop (#1551) 3772 // re-fire a series of drag-related events right after the drop (http://dev.ckeditor.com/ticket/1551)
3773 var lastDrop = 0; 3773 var lastDrop = 0;
3774 3774
3775 function onDrop(e) { 3775 function onDrop(e) {
@@ -4139,7 +4139,7 @@
4139 // select-all detection hack) 4139 // select-all detection hack)
4140 if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { 4140 if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
4141 cm.display.input.reset(); 4141 cm.display.input.reset();
4142 if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730 4142 if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue http://dev.ckeditor.com/ticket/1730
4143 } 4143 }
4144 cm.display.input.receivedFocus(); 4144 cm.display.input.receivedFocus();
4145 } 4145 }
@@ -6832,7 +6832,7 @@
6832 } 6832 }
6833 } 6833 }
6834 6834
6835 // See issue #2901 6835 // See issue http://dev.ckeditor.com/ticket/2901
6836 if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className)) 6836 if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
6837 builder.content.className = "cm-tab-wrap-hack"; 6837 builder.content.className = "cm-tab-wrap-hack";
6838 6838
@@ -8367,7 +8367,7 @@
8367 if (badBidiRects != null) return badBidiRects; 8367 if (badBidiRects != null) return badBidiRects;
8368 var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); 8368 var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
8369 var r0 = range(txt, 0, 1).getBoundingClientRect(); 8369 var r0 = range(txt, 0, 1).getBoundingClientRect();
8370 if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780) 8370 if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (http://dev.ckeditor.com/ticket/2780)
8371 var r1 = range(txt, 1, 2).getBoundingClientRect(); 8371 var r1 = range(txt, 1, 2).getBoundingClientRect();
8372 return badBidiRects = (r1.right - r0.right < 3); 8372 return badBidiRects = (r1.right - r0.right < 3);
8373 } 8373 }
diff --git a/sources/styles.js b/sources/styles.js
index 733bb4b..dd9680e 100644
--- a/sources/styles.js
+++ b/sources/styles.js
@@ -126,7 +126,7 @@ CKEDITOR.stylesSet.add( 'default', [
126 { name: '1080p', type: 'widget', widget: 'embedSemantic', attributes: { 'class': 'embed-1080p' }, group: 'size' }, 126 { name: '1080p', type: 'widget', widget: 'embedSemantic', attributes: { 'class': 'embed-1080p' }, group: 'size' },
127 127
128 // Adding space after the style name is an intended workaround. For now, there 128 // Adding space after the style name is an intended workaround. For now, there
129 // is no option to create two styles with the same name for different widget types. See #16664. 129 // is no option to create two styles with the same name for different widget types. See http://dev.ckeditor.com/ticket/16664.
130 { name: '240p ', type: 'widget', widget: 'embed', attributes: { 'class': 'embed-240p' }, group: 'size' }, 130 { name: '240p ', type: 'widget', widget: 'embed', attributes: { 'class': 'embed-240p' }, group: 'size' },
131 { name: '360p ', type: 'widget', widget: 'embed', attributes: { 'class': 'embed-360p' }, group: 'size' }, 131 { name: '360p ', type: 'widget', widget: 'embed', attributes: { 'class': 'embed-360p' }, group: 'size' },
132 { name: '480p ', type: 'widget', widget: 'embed', attributes: { 'class': 'embed-480p' }, group: 'size' }, 132 { name: '480p ', type: 'widget', widget: 'embed', attributes: { 'class': 'embed-480p' }, group: 'size' },